📄 dispatcherservlet.java
字号:
package com.javaeedev.lightweight.mvc;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.google.inject.Binding;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.Module;
import com.google.inject.Stage;
import com.google.inject.name.Named;
import com.javaeedev.lightweight.common.Disposable;
/**
* Core dispatcher servlet.
*
* @author Xuefeng
*/
public class DispatcherServlet extends HttpServlet {
private Log log = LogFactory.getLog(getClass());
private Map<String, ActionAndMethod> actionMap;
private Interceptor[] interceptors = null;
private ExceptionResolver exceptionResolver = null;
private ViewResolver viewResolver = null;
private Injector injector = null;
/**
* Don't forget to call super.init(config) if subclass override this method.
*/
@Override
public void init(ServletConfig config) throws ServletException {
long startTime = System.currentTimeMillis();
String moduleClass = config.getInitParameter("module");
if(moduleClass==null || moduleClass.trim().equals(""))
throw new ServletException("Cannot find init parameter in web.xml: <servlet>"
+ "<servlet-name>?</servlet-name><servlet-class>"
+ getClass().getName()
+ "</servlet-class><init-param><param-name>module</param-name><param-value>"
+ "put-your-config-module-full-class-name-here</param-value></init-param></servlet>");
ServletContext context = config.getServletContext();
// init guice:
injector = Guice.createInjector(Stage.PRODUCTION, getConfigModule(moduleClass.trim(), context));
// find out all actions:
log.info("Register all Action classes...");
actionMap = getUrlMapping(findKeysByType(injector, Action.class));
log.info("Register all Interceptor classes...");
interceptors = findInterceptors(findKeysByType(injector, Interceptor.class));
log.info("Register ViewResolver...");
viewResolver = findViewResolver(findKeysByType(injector, ViewResolver.class));
if(viewResolver!=null)
viewResolver.init(context);
// init exception resolver:
exceptionResolver = findExceptionResolver(findKeysByType(injector, ExceptionResolver.class));
if(exceptionResolver!=null)
exceptionResolver.init(context);
long time = System.currentTimeMillis() - startTime;
log.info("DispatcherServlet init completed in " + time + " ms.");
}
private ExceptionResolver findExceptionResolver(List<Key<?>> exceptionResolverKeys) {
if(exceptionResolverKeys.size()==0) {
log.info("No ExceptionResolver found.");
return null;
}
if(exceptionResolverKeys.size()>0) {
log.warn("Found " + exceptionResolverKeys.size() + " ExceptionResolvers, only the first valid ExceptionResolver is available.");
}
for(Key<?> key : exceptionResolverKeys) {
ExceptionResolver resolver = (ExceptionResolver) safeInstantiate(key);
if(resolver!=null)
return resolver;
}
log.warn("Cannot instantiate any ExceptionResolver. ExceptionResolver will be unavailable.");
return null;
}
/**
* Don't forget to call super.destroy if subclass override this method.
*/
@Override
public void destroy() {
// destroy guice: Run all singleton instances' destroy() method:
List<Key<?>> keys = findKeysByType(injector, null);
for(Key<?> key : keys) {
Object obj = injector.getInstance(key);
if(obj instanceof Disposable) {
try {
((Disposable)obj).dispose();
}
catch(Throwable t) {
log.error("Call dispose() failed.", t);
}
}
}
log.info("Servlet destroyed: " + getClass().getName());
}
private ViewResolver findViewResolver(List<Key<?>> viewResolverKeys) {
if(viewResolverKeys.size()==0) {
log.info("No ViewResolver found.");
return null;
}
if(viewResolverKeys.size()>1) {
log.warn("Found " + viewResolverKeys.size() + " ViewResolvers, only the first valid ViewResolver is available.");
}
for(Key<?> key : viewResolverKeys) {
ViewResolver resolver = (ViewResolver) safeInstantiate(key);
if(resolver!=null) {
log.info("Found ViewResolver: " + resolver);
return resolver;
}
}
log.warn("Cannot instantiate any ViewResolver. ViewResolver will be unavailable.");
return null;
}
private <T> T safeInstantiate(Key<T> key) {
try {
return injector.getProvider(key).get();
}
catch(Exception e) {
log.warn("Cannot instantiate by key: " + key, e);
return null;
}
}
private List<Key<?>> findKeysByType(Injector inj, Class<?> type) {
Map<Key<?>, Binding<?>> map = inj.getBindings();
List<Key<?>> keyList = new ArrayList<Key<?>>();
for(Key<?> key : map.keySet()) {
Type t = key.getTypeLiteral().getType();
if(t instanceof Class<?>) {
Class<?> clazz = (Class<?>) t;
if(type==null || type.isAssignableFrom(clazz)) {
keyList.add(key);
}
}
}
return keyList;
}
@SuppressWarnings("unchecked")
private Interceptor[] findInterceptors(List<Key<?>> interceptorKeys) {
List<InterceptorOrder> list = new ArrayList<InterceptorOrder>();
for(Key<?> key : interceptorKeys) {
Object obj = safeInstantiate(key);
if(obj==null)
continue;
Class<Interceptor> intClass = (Class<Interceptor>) obj.getClass();
Order orderAnn = intClass.getAnnotation(Order.class);
int order = 0;
if(orderAnn!=null) {
order = orderAnn.value();
log.info("Found interceptor [" + intClass.getName() + "] with specified order: " + order);
}
else {
log.warn("Found interceptor [" + intClass.getName() + "] but no order specified, set order to default: 0");
}
list.add(new InterceptorOrder((Interceptor)injector.getInstance(key), order));
}
if(list.size()==0)
return new Interceptor[0];
InterceptorOrder[] orderArray = list.toArray(new InterceptorOrder[0]);
Arrays.sort(orderArray);
Interceptor[] intArray = new Interceptor[orderArray.length];
for(int i=0; i<intArray.length; i++) {
intArray[i] = orderArray[i].interceptor;
}
return intArray;
}
@SuppressWarnings("unchecked")
private Map<String, ActionAndMethod> getUrlMapping(List<Key<?>> actionKeys) {
Map<String, ActionAndMethod> urlMapping = new HashMap<String, ActionAndMethod>();
for(Key<?> key : actionKeys) {
Object obj = safeInstantiate(key);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -