private FilterConfig filterConfig; protected Dispatcher dispatcher;
filterConfig用来向filter传递信息,提供了四个方法:
public abstract java.lang.String getFilterName(); public abstract javax.servlet.ServletContext getServletContext(); public abstract java.lang.String getInitParameter(java.lang.String arg0); public abstract java.util.Enumeration getInitParameterNames();
dispatcher做了FilterDispatcher大部分的工作。
首先来看init方法:
public void init(FilterConfig filterConfig) throws ServletException { this.filterConfig = filterConfig; //把filterConfig中的parameters和servletContext传递给new Dispatcher(filterConfig.getServletContext(), params) dispatcher = createDispatcher(filterConfig); //加载各种配置 dispatcher.init(); String param = filterConfig.getInitParameter("packages"); String packages = DEFAULT_STATIC_PACKAGES; if (param != null) { packages = param + " " + packages; } this.pathPrefixes = parse(packages); }
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) res; ServletContext servletContext = getServletContext(); String timerKey = "FilterDispatcher_doFilter: "; try { UtilTimerStack.push(timerKey); request = prepareDispatcherAndWrapRequest(request, response); ActionMapping mapping;//ActionMapping有四个字段 method, name, namespace,params, result对应着XML配置文件 try { //装配mappings mapping = actionMapper.getMapping(request, dispatcher.getConfigurationManager()); } catch (Exception ex) { LOG.error("error getting ActionMapping", ex); dispatcher.sendError(request, response, servletContext, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, ex); return; } // 如果mapping是空的,则去找static的内容 if (mapping == null) { String resourcePath = RequestUtils.getServletPath(request); if ("".equals(resourcePath) && null != request.getPathInfo()) { resourcePath = request.getPathInfo(); } if (serveStatic && resourcePath.startsWith("/struts")) { findStaticResource(resourcePath, findAndCheckResources(resourcePath), request, response); } else { // this is a normal request, let it pass through chain.doFilter(request, response); } // The framework did its job here return; } //这个方法是关键 dispatcher.serviceAction(request, response, servletContext, mapping); } finally { try { ActionContextCleanUp.cleanUp(req); } finally { UtilTimerStack.pop(timerKey); } } }
我们再来查看Dispatcher中的serviceAction。
public void serviceAction(HttpServletRequest request, HttpServletResponse response, ServletContext context, ActionMapping mapping) throws ServletException { //创建上下文,extraContext中包括parameterMap, sessionMap, applicationMap, locale, request, response, servletContext等等 Map<String, Object> extraContext = createContextMap(request, response, mapping, context); //如果request之前有value stack,则复制一个并把它放到上下文中。 ValueStack stack = (ValueStack) request.getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY); if (stack != null) { extraContext.put(ActionContext.VALUE_STACK, ValueStackFactory.getFactory().createValueStack(stack)); } String timerKey = "Handling request from Dispatcher"; try { UtilTimerStack.push(timerKey); String namespace = mapping.getNamespace(); String name = mapping.getName(); String method = mapping.getMethod(); Configuration config = configurationManager.getConfiguration(); //利用工厂方法新建一个ActionProxy,它提供诸多代理方法。 ActionProxy proxy = config.getContainer().getInstance(ActionProxyFactory.class).createActionProxy( namespace, name, extraContext, true, false); proxy.setMethod(method); request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, proxy.getInvocation().getStack()); // 如果mapping中定义了Result,则运行这个Result。Result还是非常值得一讲的 if (mapping.getResult() != null) { Result result = mapping.getResult(); result.execute(proxy.getInvocation()); } else { //没有则运行execute,即调用Invocation.invoke() proxy.execute(); } // If there was a previous value stack then set it back onto the request if (stack != null) { request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, stack); } } catch (ConfigurationException e) { LOG.error("Could not find action or result", e); sendError(request, response, context, HttpServletResponse.SC_NOT_FOUND, e); } catch (Exception e) { throw new ServletException(e); } finally { UtilTimerStack.pop(timerKey); } }
public interface ActionProxy { /** 在所有的依赖都配置好调用,在DefaultActionProxyFactory.createActionProxy中使用 */ void prepare() throws Exception; /** @return 返回所代理的对象 */ Object getAction(); /** @return 返回所代理的对象的名字 */ String getActionName(); /** @return ActionProxy产生所借助的ActionConfig */ ActionConfig getConfig(); /** 设置是否在运行完Action之后运行Action所返回的Result */ void setExecuteResult(boolean executeResult); /** @return the status of whether the ActionProxy is set to execute the Result after the Action is executed */ boolean getExecuteResult(); /** @return the ActionInvocation:表示Action的运行状态,包括Interceptors和Action的实例 */ ActionInvocation getInvocation(); /** * @return the namespace the ActionConfig for this ActionProxy is mapped to */ String getNamespace(); /** * 运行ActionProxy. 把ActionContext 设置为 ActionInvocation中的 ActionContext * 关键还是调用ActionInvocation.invoke()。 * DefaultActionProxy中的实现 *public String execute() throws Exception { * ActionContext nestedContext = ActionContext.getContext(); * ActionContext.setContext(invocation.getInvocationContext()); * String retCode = null; * String profileKey = "execute: "; * try { * UtilTimerStack.push(profileKey); * retCode = invocation.invoke(); * } finally { * if (cleanupContext) { * ActionContext.setContext(nestedContext); * } * UtilTimerStack.pop(profileKey); * } * return retCode; *} */ String execute() throws Exception; /** 设置Invocation中的Method的,如果空的话就用execute。 */ void setMethod(String method); /** * Returns the method to execute, or null if no method has been specified (meaning "execute" will be invoked) */ String getMethod(); }
再来看一下ActionInvocation.invoke()的实现:
public String invoke() throws Exception { String profileKey = "invoke: "; try { UtilTimerStack.push(profileKey); //如果运行过了,就抛出异常 if (executed) { throw new IllegalStateException("Action has already executed"); } //运行Interceptor if (interceptors.hasNext()) { final InterceptorMapping interceptor = (InterceptorMapping) interceptors.next(); //UtilTimerStack.profile()即 /*public static <T> T profile(String name, ProfilingBlock<T> block) throws Exception { UtilTimerStack.push(name); try { return block.doProfiling(); } finally { UtilTimerStack.pop(name); } }*/ UtilTimerStack.profile("interceptor: "+interceptor.getName(), new UtilTimerStack.ProfilingBlock<String>() { public String doProfiling() throws Exception { resultCode = interceptor.getInterceptor().intercept(DefaultActionInvocation.this); return null; } }); } else { resultCode = invokeActionOnly(); } // this is needed because the result will be executed, then control will return to the Interceptor, which will // return above and flow through again [color=red]没看懂,好像是由于在下面还要调用result.execute(ActionInvocation),那么还是有可能再次调用这个地方?[/color] if (!executed) { if (preResultListeners != null) { for (Iterator iterator = preResultListeners.iterator(); iterator.hasNext();) { PreResultListener listener = (PreResultListener) iterator.next(); String _profileKey="preResultListener: "; try { UtilTimerStack.push(_profileKey); listener.beforeResult(this, resultCode); } finally { UtilTimerStack.pop(_profileKey); } } } // now execute the result, if we're supposed to if (proxy.getExecuteResult()) { //调用result.execute(ActionInvocation); executeResult(); } executed = true; } return resultCode; } finally { UtilTimerStack.pop(profileKey); } }