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









發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章