JFinal顶层是一个Handler链是责任链模式的一个变种,会拦截到所有请求,包括静态资源请求。
首先、我们来看看Handler的配置,我们在JFinal的Config中可用来配置自定义的Handler。
@Override
public void configHandler(Handlers me) {
me.add(new FakeStaticHandler());
}
在这个添加JFinal内置或者我们自己的Handler,在Handlers中有一个ArrayList来存储她们。
final public class Handlers {
private final List handlerList = new ArrayList();
public Handlers add(Handler handler) {
if (handler != null)
handlerList.add(handler);
return this;
}
public List getHandlerList() {
return handlerList;
}
}
下面、是Handler的初始化,在项目启动JFinalFilter.init初始化时执行了jfinal.init完成了对整个框架的初始化!我们的Handler也是在这里完成初始化的。
boolean init(JFinalConfig jfinalConfig, ServletContext servletContext) {
this.servletContext = servletContext;
this.contextPath = servletContext.getContextPath();
initPathUtil();
Config.configJFinal(jfinalConfig); // start plugin and init logger factory in this method
constants = Config.getConstants();
initActionMapping();
initHandler();
initRender();
initOreillyCos();
initTokenManager();
return true;
}
// 初始化Handler
private void initHandler() {
Handler actionHandler = new ActionHandler(actionMapping, constants);
handler = HandlerFactory.getHandler(Config.getHandlers().getHandlerList(), actionHandler);
}
大家再来看看HandlerFactory,在这里从ArrayList的尾部向头部循环,完成对每个Handler中的nextHandler参数赋值。下面是Handler的结构,她是一个单向的链表。
/**
* Handler.
* * You can config Handler in JFinalConfig.configHandler() method,
* Handler can do anything under the jfinal action.
*/
public abstract class Handler {
protected Handler nextHandler;
/**
* Handle target
* @param target url target of this web http request
* @param request HttpServletRequest of this http request
* @param response HttpServletRequest of this http request
* @param isHandled JFinalFilter will invoke doFilter() method if isHandled[0] == false,
* it is usually to tell Filter should handle the static resource.
*/
public abstract void handle(String target, HttpServletRequest request, HttpServletResponse response, boolean[] isHandled);
}
再来、看看HandlerFactory中的getHandler方法。Handler链条的末端是ActionHandler,是专门处理action动态请求的地方。
/**
* Build handler chain
*/
public static Handler getHandler(List handlerList, Handler actionHandler) {
Handler result = actionHandler;
for (int i=handlerList.size()-1; i>=0; i--) {
Handler temp = handlerList.get(i);
temp.nextHandler = result;
result = temp;
}
return result;
}
最后、我们来看看Handler是怎么工作的
上图描述了JFinal中的一个请求的完整过程JFinalFilter->Handler->Action,请求到达Handler中之后有三种结局。
① 直接跳出链条,执行下一个Filter(如果web.xml中有配置)tomcat、jetty容器对静态资源请求处理。
如果都不满足,将返回容器级别的404,可在web.xml中配置404页。*此处的404不受JFinal配置的404页控制。
静态资源进入到ActionHandler时会被直接跳出,执行同上。请求不会到达Action。(示例代码:JFinal/ActionHandler.java)
if (target.indexOf('.') != -1) {
return ;
}
静态资源进入到ActionHandler时会被直接跳出,执行同上。请求不会到达Action。(示例代码:JFinal/ActionHandler.java)
if (target.indexOf('.') != -1) {
return ;
}
② 请求已经在Handler完成了该有的使命。在Handler执行了render或者在response中返回了我们想要的数据。
该请求也不会到达Action,这里设置isHandled[0] = true;请求到此为止,也不会去执行后面的Filter。(示例代码:jnode/XmlHandler.java)
if (target.endsWith(".xml")) {
String view = target.replace(".xml", ".vm");
RenderFactory.me().getRender("/xml".concat(view)).setContext(request, response).render();
// 跳出
isHandled[0] = true;
return;
}
③ 酒肉穿肠过,佛祖心中留。请求会依次经过各个Handler,抵达Action。
nextHandler.handle(target, request, response, isHandled);