从今天开始进行struts2的源码阅读计划,希望一周内能搞定它!
首先从网络上下载struts2和xwork的源代码(如果不知道怎么下载....百度一下你就知道了),然后在MyEclipse中建立一个简单的javaweb项目,引入struts2-core-xxx.jar和xwork-core-xxx.jar。然后右键点击这两个jar文件,选择Properties->Java Source Attachment,在右边的界面中关联到相应的源代码文件就可以开始阅读源代码了!
先贴一个从网上找的struts2比较经典的一个运行原理图
按照上图的示意,决定先看ActionContextCleanUp类,(注意:具体有几个filter需要看web.xml文件中的配置,如果需要debugeActionContextCleanUp类,需要先在web.xml中配置使用此filter)(建议看struts2源码以前先了解一下servlet的一些基本知识,在此推荐孙卫琴老师写的《Tomcat与Java Web开发技术详解》),此类在org.apache.struts2.dispatcher包中,源代码如下(看源码的时候建议连同与该类相关的类也看看)
package org.apache.struts2.dispatcher;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.util.logging.Logger;
import com.opensymphony.xwork2.util.logging.LoggerFactory;
import com.opensymphony.xwork2.util.profiling.UtilTimerStack;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
//可以看出这个类是一个Servlet的过滤器,实现了Servlet的Filter接口
public class ActionContextCleanUp implements Filter {
private static final Logger LOG = LoggerFactory.getLogger(ActionContextCleanUp.class);
private static final String COUNTER = "__cleanup_recursion_counter";
/**
* @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain)
*/
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
showDeprecatedWarning();//输出警告信息
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
String timerKey = "ActionContextCleanUp_doFilter: ";
try {
UtilTimerStack.push(timerKey);
try {
Integer count = (Integer)request.getAttribute(COUNTER);
if (count == null) {
count = Integer.valueOf(1);
}
else {
count = Integer.valueOf(count.intValue()+1);
}
request.setAttribute(COUNTER, count);
//LOG.debug("filtering counter="+count);
chain.doFilter(request, response);
} finally {
int counterVal = ((Integer)request.getAttribute(COUNTER)).intValue();
counterVal -= 1;
request.setAttribute(COUNTER, Integer.valueOf(counterVal));
cleanUp(request);
}
}
finally {
UtilTimerStack.pop(timerKey);
}
}
/**
* Clean up the request of threadlocals if this is the last execution
*
* @param req The servlet request
*/
protected static void cleanUp(ServletRequest req) {
// should we clean up yet?
Integer count = (Integer) req.getAttribute(COUNTER);
if (count != null && count > 0 ) {
if (LOG.isDebugEnabled()) {
LOG.debug("skipping cleanup counter="+count);
}
return;
}
// always dontClean up the thread request, even if an action hasn't been executed
ActionContext.setContext(null);
Dispatcher.setInstance(null);
}
public void destroy() {
}
public void init(FilterConfig arg0) throws ServletException {
}
private void showDeprecatedWarning() {
String msg =
"\n\n" +
"***************************************************************************\n" +
"* WARNING!!! *\n" +
"* *\n" +
"* >>> ActionContextCleanUp <<< is deprecated! Please use the new filters! *\n" +
"* *\n" +
"* This can be a source of unpredictable problems! *\n" +
"* *\n" +
"* Please refer to the docs for more details! *\n" +
"* http://struts.apache.org/2.x/docs/webxml.html *\n" +
"* *\n" +
"***************************************************************************\n\n";
System.out.println(msg);
}
}
此类会根据给定的参数判断是否清除ActionContext和Dispatcher。