struts的运行图如下:
先看我自己画的时序图:
<filter> <filter-name>struts2</filter-name> <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class> </filter> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>很显然,我们得去StrutsPrepareAndExecuteFilter里看看,这是一个filter。
//StrutsPrepareAndExecuteFilter.java public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) res; try { if (excludedPatterns != null && prepare.isUrlExcluded(request, excludedPatterns)) { chain.doFilter(request, response); } else { prepare.setEncodingAndLocale(request, response); prepare.createActionContext(request, response); prepare.assignDispatcherToThread(); request = prepare.wrapRequest(request); //之前的代码 我们先不管 //第三步 找到action的信息 ActionMapping mapping = prepare.findActionMapping(request, response, true); if (mapping == null) { boolean handled = execute.executeStaticResourceRequest(request, response); if (!handled) { chain.doFilter(request, response); } } else { execute.executeAction(request, response, mapping); } } } finally { prepare.cleanupRequest(request); } }上面的ActionMapping mapping = prepare.findActionMapping(request, response, true);就是找到对应的action,怎么找的?看代码:
//PrepareOperations.java public ActionMapping findActionMapping(HttpServletRequest request, HttpServletResponse response, boolean forceLookup) { ActionMapping mapping = (ActionMapping) request.getAttribute(STRUTS_ACTION_MAPPING_KEY); if (mapping == null || forceLookup) { try { mapping = dispatcher.getContainer().getInstance(ActionMapper.class).getMapping(request, dispatcher.getConfigurationManager()); if (mapping != null) { request.setAttribute(STRUTS_ACTION_MAPPING_KEY, mapping); } } catch (Exception ex) { dispatcher.sendError(request, response, servletContext, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, ex); } } return mapping; }这里有一个actionmapping,它是干什么的?
public class ActionMapping { private String name; private String namespace; private String method; private String extension; private Map<String, Object> params; private Result result; //..... }懂了么?,就是对应一个action
//DefaultActionMapper.java 下面的就是时序图中的第四步 public ActionMapping getMapping(HttpServletRequest request, ConfigurationManager configManager) { ActionMapping mapping = new ActionMapping(); //去除工程名等等 获得uri String uri = RequestUtils.getUri(request); //url的带; jsessionid 问题 int indexOfSemicolon = uri.indexOf(";"); uri = (indexOfSemicolon > -1) ? uri.substring(0, indexOfSemicolon) : uri; //删除扩展名,如.action或者.do uri = dropExtension(uri, mapping); if (uri == null) { return null; } //把uri中的信息分析到mapping中 parseNameAndNamespace(uri, mapping, configManager); //处理特殊参数 handleSpecialParameters(request, mapping); //主要是用来处理形如/userAction!getAll.action的请求,分离action名和方法名: return parseActionName(mapping); }对DefaultActionMapper的getMapping方法,我们得边调试边看。
//Dispatcher.java 时序图中的第六步 public void serviceAction(HttpServletRequest request, HttpServletResponse response, ServletContext context, ActionMapping mapping) throws ServletException { //处理栈的问题 String namespace = mapping.getNamespace(); String name = mapping.getName(); String method = mapping.getMethod(); Configuration config = configurationManager.getConfiguration(); //时序图中的第7,8步 ActionProxy proxy = config.getContainer().getInstance(ActionProxyFactory.class).createActionProxy( namespace, name, method, extraContext, true, false); //时序图中的第9步 //4、如果ActionMapper决定需要调用某个Action, //FilterDispatcher把请求的处理交给ActionProxy; proxy.execute(); }
//StrutsActionProxy.java 时序图中的第10步 public String execute() throws Exception { ActionContext previous = ActionContext.getContext(); ActionContext.setContext(invocation.getInvocationContext()); try { return invocation.invoke(); } finally { if (cleanupContext) ActionContext.setContext(previous); } }
//DefaultActionInvocation.java public String invoke() throws Exception { if (interceptors.hasNext()) { final InterceptorMapping interceptor = interceptors.next(); resultCode = interceptor.getInterceptor().intercept(DefaultActionInvocation.this); } else { resultCode = invokeActionOnly(); } return resultCode; } }关于interceptor.getInterceptor().intercept(DefaultActionInvocation.this),这是一个典型的责任链模式,如果对它不清楚,大家可以参考
//DefaultActionInvocation.java 代码有省略 protected String invokeAction(Object action, ActionConfig actionConfig) throws Exception { String methodName = proxy.getMethod(); String timerKey = "invokeAction: " + proxy.getActionName(); boolean methodCalled = false; Object methodResult = null; Method method = null; try { method = getAction().getClass().getMethod(methodName, EMPTY_CLASS_ARRAY); } if (!methodCalled) { //OK,我们已经进入 自己写的action了 methodResult = method.invoke(action, EMPTY_OBJECT_ARRAY); } return saveResult(actionConfig, methodResult); }