首页 > 代码库 > dreamvc框架(三),dispartcher做了些什么

dreamvc框架(三),dispartcher做了些什么

这一篇我会介绍一些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);
		
		
	}


和加载ioc容器差不多,如果没有指定模板,dreamvc会自动选择jsp模板



这样,Dispatcher类的初始化工作就做完了。下一张,我们将会介绍一个请求如何到相关方法,参数的注入,拦截器的工作方式,和拦截器ur的匹配方式

转载请注明出处http://blog.csdn.net/a837199685









dreamvc框架(三),dispartcher做了些什么