这一篇我会介绍一些dreamvc的核心类Dispatcher都做了些什么,首先我们先来看一看init方法,这是在DispatcherServlet和DispatcherFilter里面都会调用到的一个方法
void init(FixableConfig config)throws ServletException{
this.servletContext=config.getServletContext();
try {
initProxy(config);
log.info("init controllers and control");
} catch (ServletException e) {
throw e;
} catch (Exception e) {
throw new ServletException("Dispatcher init failed.", e);
}
}
/**
* controller/Interceptor/
* @param config context
* @throws Exception
*/
private void initProxy(FixableConfig config)throws Exception {
String IocName=config.getInitParameter("container");
if(IocName==null||"".equals(IocName)){
throw new NoParamterException("Missing init parameter <container>.");
}
/*
CodeEnhancement=config.getInitParameter("CodeEnhancement");
if(CodeEnhancement==null||CodeEnhancement.equals("")){
throw new NoParamterException("Missing init parameter <CodeEnhancement>.");
}
if(!CodeEnhancement.equals("SpringAsm")&!CodeEnhancement.equals("javassist")){
throw new NoParamterException("You must get a right codeEnhancement handler like SpringAsm if your IOC is Spring");
}*/
IocFactory factory=FactoryHelper.getInstance().createIocFactory(IocName);
factory.init(servletContext);
List<Object> controllerBean=factory.getControllers();
List<Object> InterceptorBeans=factory.getInterceptors();
//controller/interceptor
initControllerHander(controllerBean);
initInterceptorHander(InterceptorBeans);
initTemplates(config);
}
在initProxy这个方法中,首先我们先得到ioc模块,初始化后,一次得到controller和interceptor集合,接着进行操作和模板的初始化,先来看initControllerHander
private void initControllerHander(List<Object> controllerBean) {
log.info("handler controller init");
int size=controllerBean.size();
for (int i = 0; i < size; i++) {
Object obj=controllerBean.get(i);
addUrlMather(obj);
}
}
private void addUrlMather(Object obj) {
Class clazz=obj.getClass();
Method[] method=clazz.getMethods();
for (int i = 0; i < method.length; i++) {
if(isLegalMethod(method[i])){
String annotation=method[i].getAnnotation(RequestURI.class).value();
Action action=new Action(obj, method[i]);
URI uri=new URI(annotation);
uri_action.put(uri, action);
}
}
}
/**
*
* @param method
* @return
*/
private boolean isLegalMethod(Method method) {
RequestURI requestURI=method.getAnnotation(RequestURI.class);
if(requestURI==null||requestURI.value().length()==0){
return false;
}
if(Modifier.isStatic(method.getModifiers())){
return false;
}
Class<?>[] putParameters=method.getParameterTypes();
for (Class<?> class1 : putParameters) {
if(!switcherFactory.isLegalMethod(class1)){
return false;
}
}
Class<?> retType = method.getReturnType();
if (retType.equals(void.class)
|| retType.equals(String.class)
|| Renderer.class.isAssignableFrom(retType)
){
return true;
}else{
log.warn("Your method named "+method.getName()+"'s result type must be String/void/Templement");
}
return false;
}
我们首先要得到这个controller里面的对应方法,然后对该方法进行检查,关键字,返回值,参数等等,Switcher包里面里面定义了一些对参数的处理,主要是对参数的检查等,读者可以自行查看,然后我们会得到annotation注解,也就是该方法的请求路径,关联到URI这个类里面,
package org.majorxie.dreamvc.tag;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.majorxie.dreamvc.interceptor.Interceptor;
/**
* uri 类
* @author xiezhaodong
*
*/
public class URI {
private String uri;
public String getUri() {
return uri;
}
public void setUri(String uri) {
this.uri = uri;
}
public URI(String uri) {
super();
this.uri = uri;
}
/**
* 匹配相应的interceptor
* @param interceptor_map 装有interceptor的map
* @return 该请求路径的拦截器链
*/
public List<Interceptor> getMatchedInterceptor(Map<String,Interceptor> interceptor_map){
List<Interceptor> list=new ArrayList<Interceptor>();
for (String interceptorUri:interceptor_map.keySet()) {
String returnInterceptor=matcher(this.uri, interceptorUri);
if(returnInterceptor!=null){
list.add(interceptor_map.get(returnInterceptor));
}
}
return list;
}
/**
* 判断url和拦截器路径是否相对等价比如 /user/login和/user/*是相对等价的,就能够匹配
* @param url 请求url
* @param interceptors 拦截器url
* @return 匹配成功返回,否则返回null
*/
public String matcher(String url,String interceptors){
if(url.equals(interceptors))return interceptors;//完全相同
if(interceptors.endsWith("/"))return null;//不能这样结尾
String[] urlsArray=url.split("/");
String[] interceptorsArray=interceptors.split("/");
if(interceptorsArray.length<urlsArray.length){
boolean isMatched=true;
if(interceptorsArray[interceptorsArray.length-1].equals("*")){
//如果比他url短最后必须要以*结尾
for(int i = 0; i < interceptorsArray.length; i++) {
if(!isMatched(urlsArray[i], interceptorsArray[i])){//以短的一个为遍历
isMatched=false;
break;
}
}
if(isMatched)return interceptors;
}else{
return null;
}
}
if(interceptorsArray.length==urlsArray.length){
//等于
boolean isMatched=true;
for (int i = 0; i < interceptorsArray.length; i++) {//长度都一样
if(!isMatched(urlsArray[i], interceptorsArray[i])){
isMatched=false;
break;
}
}
if(isMatched){//如果最后匹配完还是相同的话
return interceptors;
}
}
return null;
}
/**
* 匹配每一个节点
* @param urlPart 原始路径节点
* @param intersPart 拦截路径节点
* @return
*/
private boolean isMatched(String urlPart,String interceptorPart){
return urlPart.equals(interceptorPart)||interceptorPart.equals("*");
}
//重写hashcode()和equals方法,要作为map的key
@Override
public int hashCode() {
// TODO Auto-generated method stub
return uri.hashCode();
}
@Override
public boolean equals(Object obj) {
if(this==obj){
return true;
}else if(obj instanceof URI){
return ((URI) obj).uri.equals(this.uri);
}
return false;
}
}
这个类里面,主要是封装了URI请求的一些操作,和拦截器匹配等等,覆盖了hashCode()和equals()函数,作为hashmap的key。接下来就是Action类了,这个类里面有3个参数
private Object instance;
private Method method;
private Class<?>[] arguments;
封装了该方法,该类,和该参数
最后我们将URI和Action分别作为MAP的key,value放入到map中!接下来加载interceptor类
private void initInterceptorHander(List<Object> interceptorBeans) {
int size=interceptorBeans.size();
for (int i = 0; i <size; i++) {
Interceptor interceptor=(Interceptor) interceptorBeans.get(i);
InterceptorURI interceptorURI=interceptor.getClass().getAnnotation(InterceptorURI.class);
String annotationUri=interceptorURI.url();
interceptor_uri.put(annotationUri, interceptor);
}
}
最总将uri和interceptor关联起来
最后加载我们需要使用的模板
private void initTemplates(FixableConfig config) throws Exception{
String template=config.getInitParameter("template");
if("".equals(template)||template==null){
log.info("You don't have template Parameters ,we will user default JSP template");
template=JSPTEMPLATE;
}
TemplateFactory templateFactory=FactoryHelper.getInstance().createTemplateFactory(template);
templateFactory.init(config);
templateFactory.setInstance(templateFactory);
}
这样,Dispatcher类的初始化工作就做完了。下一张,我们将会介绍一个请求如何到相关方法,参数的注入,拦截器的工作方式,和拦截器ur的匹配方式
转载请注明出处http://blog.csdn.net/a837199685