根据web.xml中的url规则拦截配置
如果匹配则被org.apache.struts2.dispatcher.FilterDispatcher拦截,执行方法doFilter(ServletRequest req, ServletResponse res, FilterChain chain)。
request = prepareDispatcherAndWrapRequest(request, response);在这里面会设置request 的defaultEncoding,response的defaultLocale。
1. mapping=actionMapper.getMapping(request,dispatcher.getConfigurationManager());
从url得到 namespace,name,action,,method构建ActionMapping对象,以在struts.xml中寻找相应的package中的action来执行。
1.1. 类:org.apache.struts2.dispatcher.mapper. DefaultActionMapper
方法:parseNameAndNamespace(String uri, ActionMapping mapping,
ConfigurationManager configManager)
执行后得到namespace和name.
1.2. 类:org.apache.struts2.dispatcher.mapper. DefaultActionMapper
方法:parseActionName(mapping);
从形如action!method分解出method
2. staticResourceLoader.findStaticResource(resourcePath, request, response);
如果根据ActionMapping找不到action配置适配请求,那么就认为此url请求的是静态文件,去相应的静态文件夹下尝试找静态文件,找到即返回
类:org.apache.struts2.dispatcher.DefaultStaticContentLoader
方法:public void findStaticResource(String path, HttpServletRequest request, HttpServletResponse response)
String name = cleanupPath(path);
清除url中表示静态文件的部分
URL resourceUrl = findResource(buildPath(name, pathPrefix));
然后在前面加上可自定义的pathPrefixes在classpath中寻找,找到则返回,找不到则转交FilterChain处理,这里给外挂servlet提供了出口。
3. dispatcher.serviceAction(request, response, servletContext, mapping);
类:org.apache.struts2.dispatcher.FilterDispatcher
方法:void serviceAction(HttpServletRequest request, HttpServletResponse response, ServletContext context,
ActionMapping mapping)
执行interceptor,Action,最后进行 Result的渲染
3.1. Map<String,Object> extraContext = createContextMap(requestMap, params, session, application, request, response, context);
类:org.apache.struts2.dispatcher.FilterDispatcher
方法:Map<String,Object> createContextMap(HttpServletRequest request, HttpServletResponse response,
ActionMapping mapping, ServletContext context)
创建extraContext,并在其_values属性里面存放了request,session,application, parameters,attr等常用servlet对象。最后把actionMapping, valuestack也放入。
3.2. ActionProxy proxy = config.getContainer().getInstance(ActionProxyFactory.class).createActionProxy(namespace, name, method, extraContext, true, false);
类:com.opensymphony.xwork2.DefaultActionProxyFactory
方法:ActionProxy createActionProxy(String namespace, String actionName, String methodName, Map<String, Object> extraContext, boolean executeResult, boolean cleanupContext)
根据namespace,name,method创建相应的ActionProxy
2.2.1. 在类DefaultActionProxyFactory中创建ActionInvocation,
ActionInvocation inv = new DefaultActionInvocation(extraContext, true);
2.2.2 invocation.init(this);
类:com.opensymphony.xwork2.DefaultActionInvocation
方法:void init(ActionProxy proxy)
a. createAction(contextMap);
类:com.opensymphony.xwork2.DefaultActionInvocation
方法:createAction(Map<String, Object> contextMap)
Object buildAction(String actionName, String namespace, ActionConfig config, Map<String, Object> extraContext)
类:com.opensymphony.xwork2.ObjectFactory
方法:public Object buildAction(String actionName, String namespace, ActionConfig config, Map<String, Object> extraContext)
针对每次请求新建一个Action, 当使用spring作为bean的容器时,SpringObjectFactory先去spring的ApplicationContext中找,找不到则直接创建一个Action,并将spring 容器中构建好的属性的值填充入Action.
b. List<InterceptorMapping> interceptorList = new ArrayList<InterceptorMapping>(proxy.getConfig().getInterceptors());
interceptors = interceptorList.iterator();
得到所有拦截器,以作拦截
2.3.proxy.execute();执行调用
2.3.1 invocation.invoke();
类: com.opensymphony.xwork2.DefaultActionInvocation
方法:public String invoke()
resultCode =interceptor.getInterceptor().intercept(DefaultActionInvocation.this);
在interceptor里面也调用invocation.invoke方法。通过对全局变量interceptors的next()调用不停地执行interceptor.intercept()。最后调用resultCode = invokeActionOnly();
String invokeAction(Object action, ActionConfig actionConfig) throws Exception
调用Action的相应Method,默认调用execute():
method = getAction().getClass().getMethod(methodName, EMPTY_CLASS_ARRAY);
methodResult = method.invoke(action, new Object[0]);
2.4. executeResult();
3.dispatcher.cleanUpRequest(request);