這一篇我會介紹一些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