前面把JFianl框架的初始化过程大概理了一遍,接下来,看一下JFinal接受到一个Http请求之后是如何相应的。
回到web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="WebApp_ID" version="3.0">
<filter>
<filter-name>jfinal</filter-name>
<filter-class>com.jfinal.core.JFinalFilter</filter-class>
<init-param>
<param-name>configClass</param-name>
<param-value>com.css.mission.MainConfig</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>jfinal</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
这里配置的jfina Filter是“/*”,也就是说这个Filter或拦截所有的请求。当请求过来之后,都会进入JFinalFilter的doFilter方法
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest)req;
HttpServletResponse response = (HttpServletResponse)res;
request.setCharacterEncoding(encoding);
String target = request.getRequestURI();
if (contextPathLength != 0)
target = target.substring(contextPathLength);
boolean[] isHandled = {false};
try {
handler.handle(target, request, response, isHandled);
}
catch (Exception e) {
if (log.isErrorEnabled()) {
String qs = request.getQueryString();
log.error(qs == null ? target : target + "?" + qs, e);
}
}
if (isHandled[0] == false)
chain.doFilter(request, response);
}
前几行代码没什么说的,获取request,response,设置编码,截取除主机名之后的action请求。
boolean[] isHandled = {false};这行代码就比较有意思了,这里作者用了一个boolean类型的数组来做标记位,标记是否需要doFilter这个请求,有人就会有疑问,为什么不直接用一个boolean类型的变量来做标记,而要用一个数组。《Java虚拟机规范》有一段对boolean类型的描述:“虽然定义了boolean这种数据类型,但是只对它提供了非常有限的支持。在Java虚拟机中没有任何供boolean值专用的字节码指令,Java语言表达式所操作的boolean值,在编译之后都使用Java虚拟机中的int数据类型来代替,而boolean数组将会被编码成Java虚拟机的byte数组,每个元素boolean元素占8位“,《Java虚拟机规范》给出了boolean类型4个字节,和boolean数组1个字节的定义。这里可以看作是作者对内存的一个小的优化,至于Java虚拟机为什么要用4个字节代表boolean类型的值,而不用byte或者short,这里就不再深究,有兴趣的可以自己去查下相关资料。继续往下看
try {
handler.handle(target, request, response, isHandled);
}
catch (Exception e) {
if (log.isErrorEnabled()) {
String qs = request.getQueryString();
log.error(qs == null ? target : target + "?" + qs, e);
}
}
这里调用了handler.handle(target, request, response, isHandled);我们知道handler在初始化的时候被赋值的,对应的是ActionHandler这个类的实例。接着看ActionHandler.handle(target, request, response, isHandled);
public final void handle(String target, HttpServletRequest request, HttpServletResponse response, boolean[] isHandled) {
if (target.indexOf('.') != -1) {
return ;
}
isHandled[0] = true;
String[] urlPara = {null};
Action action = actionMapping.getAction(target, urlPara);
if (action == null) {
if (log.isWarnEnabled()) {
String qs = request.getQueryString();
log.warn("404 Action Not Found: " + (qs == null ? target : target + "?" + qs));
}
renderFactory.getErrorRender(404).setContext(request, response).render();
return ;
}
try {
Controller controller = action.getControllerClass().newInstance();
controller.init(request, response, urlPara[0]);
if (devMode) {
if (ActionReporter.isReportAfterInvocation(request)) {
new Invocation(action, controller).invoke();
ActionReporter.report(controller, action);
} else {
ActionReporter.report(controller, action);
new Invocation(action, controller).invoke();
}
}
else {
new Invocation(action, controller).invoke();
}
Render render = controller.getRender();
if (render instanceof ActionRender) {
String actionUrl = ((ActionRender)render).getActionUrl();
if (target.equals(actionUrl))
throw new RuntimeException("The forward action url is the same as before.");
else
handle(actionUrl, request, response, isHandled);
return ;
}
if (render == null)
render = renderFactory.getDefaultRender(action.getViewPath() + action.getMethodName());
render.setContext(request, response, action.getViewPath()).render();
}
catch (RenderException e) {
...异常处理
}
}
首先方法进来
if (target.indexOf('.') != -1) {
return ;
}
这里的作用是过滤掉资源请求,比如http://localhost:8080/test.html、http://localhost:8080/imge/2.png 等
isHandled[0] = true;
String[] urlPara = {null};
Action action = actionMapping.getAction(target, urlPara);
这里先把标记的标记改为true,说明当前要消耗掉这个请求。actionMapping.getAction(target, urlPara);根据用户的请求地址从actionMapping中获取相应的Action
Action getAction(String url, String[] urlPara) {
Action action = mapping.get(url);
if (action != null) {
return action;
}
// --------
int i = url.lastIndexOf(SLASH);
if (i != -1) {
action = mapping.get(url.substring(0, i));
urlPara[0] = url.substring(i + 1);
}
return action;
}
先是更具用户的请求直接从map集合中获取Action,如果没有获取到,则截取到最后一个”/“之前的请求,作为请求url从,重新从map集合中获取Action,使得/user/login/sdfsfsdfsdfs之类的错误请求能定位到/user/login/,只是现在还不理解作者这里处理的用意是什么。个人觉得这样的设计会反而会增大项目的风险,也可能是我对框架的理解不够透彻。如果你对这里的代码有更好的理解欢迎在下方留言或给我私信
2025 - 快车库 - 我的知识库 重庆启连科技有限公司 渝ICP备16002641号-10
企客连连 表单助手 企服开发 榜单123