1.org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.doFilter()方法中

public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {

        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;

        try {
            prepare.setEncodingAndLocale(request, response);    //设置编码和本地化信息
            prepare.createActionContext(request, response);        //创建ActionContext对象
            prepare.assignDispatcherToThread();                    //分配当前线程的分发器
            if (excludedPatterns != null && prepare.isUrlExcluded(request, excludedPatterns)) {
                chain.doFilter(request, response);
            } else {
                request = prepare.wrapRequest(request);            //对request对象进行封装          //获取ActionMapping对象, ActionMapping对象对应一个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); //执行Action请求, 进入下面方法 重要
                }
            }
        } finally {
            prepare.cleanupRequest(request);
        }
    }
StrutsPrepareAndExecuteFilter。doFilter()
  • 设置编码和本地化信息
  • 创建ActionContext对象
  • 分配当前线程的分发器
  • 将request对象进行封装
  • 获取ActionMapping对象, ActionMapping对象对应一个action详细配置信息啊阿斯顿
  • 执行Action请求, 进入下面方法

  2.org.apache.struts2.dispatcher.Dispatcher.serviceAction()方法:

 1     public void serviceAction(HttpServletRequest request, HttpServletResponse response, ServletContext context,             ActionMapping mapping) throws ServletException {
 2 
 3         Map<String, Object> extraContext = createContextMap(request, response, mapping, context);
 4 
 5         //首先获取当前请求是否已经有valueStack对象, 这样做的目的是在接受到chain跳转方式的请求时, 可以直接接管上次请求的action
 6         ValueStack stack = (ValueStack) request.getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY);
 7         boolean nullStack = stack == null;
 8         if (nullStack) {
 9             ActionContext ctx = ActionContext.getContext();  //如果请求中没有ValueStack对象, 获取当前线程的ActionContext对象
10             if (ctx != null) {
11                 stack = ctx.getValueStack();   //从ActionContext中获取ValueStack
12             }
13         }
14         if (stack != null) {
15             extraContext.put(ActionContext.VALUE_STACK, valueStackFactory.createValueStack(stack)); //将事先处理好的请求中的参数put到ValueStack中
16         }
17 
18         String timerKey = "Handling request from Dispatcher";
19         try {
20             UtilTimerStack.push(timerKey);
21             String namespace = mapping.getNamespace();
22             String name = mapping.getName();
23             String method = mapping.getMethod();   //获取ActionMapping中配置的namespace, name, method值
24 
25             Configuration config = configurationManager.getConfiguration();       //根据配置获取当前Action的代理对象ActionProxy(这个过程中会创建Action对象, 同时返回的代理对象是StrutsActionProxy的实例)
26             ActionProxy proxy = config.getContainer().getInstance(ActionProxyFactory.class).createActionProxy(
27                     namespace, name, method, extraContext, true, false);
28   
29             request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, proxy.getInvocation().getStack()); //向request中设置ValueStack对象
30 
31             // if the ActionMapping says to go straight to a result, do it!
32             if (mapping.getResult() != null) {
33                 Result result = mapping.getResult();
34                 result.execute(proxy.getInvocation());
35             } else {
36                 proxy.execute();  //进入ActionProxy的处理 重要
37             }
Dispatcher.serviceAction()
  • 首先获取当前请求是否已经有valueStack对象, 这样做的目的是在接受到chain跳转方式的请求时, 可以直接接管上次请求的action
  • 如果请求中没有ValueStack对象, 获取当前线程的ActionContext对象
  • 从ActionContext中获取ValueStack
  • 将事先处理好的请求中的参数put到ValueStack中
  • 获取ActionMapping中配置的namespace, name, method值
  • 根据配置获取当前Action的代理对象ActionProxy(这个过程中会创建Action对象, 同时返回的代理对象是StrutsActionProxy的实例)
  • 向request中设置ValueStack对象
  • 进入ActionProxy的处理

  3.org.apache.struts2.impl.StrutsActionProxy.execute()方法:

 1     public String execute() throws Exception {
 2         ActionContext previous = ActionContext.getContext();        //准备上下文环境       //StrutsActionProxy是继承自com.opensymphony.xwork2.DefaultActionProxy的, 在这个代理对象内部实际上就持有了     //com.opensymphony.xwork2.DefaultActionInvocation的一个实例的
 3         ActionContext.setContext(invocation.getInvocationContext());    
 4         try {
 5             return invocation.invoke();   //此时, 调用它的invoke方法
 6         } finally {
 7             if (cleanupContext)
 8                 ActionContext.setContext(previous);
 9         }
10     }
StrutsActionProxy.execute()
  • 准备上下文环境
  •  StrutsActionProxy是继承自com.opensymphony.xwork2.DefaultActionProxy的, 在这个代理对象内部实际上就持有了DefaultActionInvocation的一个实例.
  •  DefaultActionInvocation对象中保存了Action调用过程中需要的一切信息
  • 此时, 调用它的invoke方法

  4.com.opensymphony.xwork2.DefaultActionInvocation.invoke()方法:

 1  public String invoke() throws Exception {
 2         String profileKey = "invoke: ";
 3         try {
 4             UtilTimerStack.push(profileKey);
 5 
 6             if (executed) {
 7                 throw new IllegalStateException("Action has already executed");
 8             }
 9 
10             if (interceptors.hasNext()) {
11                 final InterceptorMapping interceptor = interceptors.next();
12                 String interceptorMsg = "interceptor: " + interceptor.getName();
13                 UtilTimerStack.push(interceptorMsg);
14                 try {            //首先会顺序的递归执行当前Action中所配置的所有的拦截器, 直到拦截器遍历完毕调用真正的Action
15                      resultCode = interceptor.getInterceptor().intercept(DefaultActionInvocation.this);
16                             }
17                 finally {
18                     UtilTimerStack.pop(interceptorMsg);
19                 }
20             } else {         //通过调用DefaultActionInvocation的invokeActionOnly()方法去反射调用Action, 调用过程中, 会从当前的invocation对象中得到Action的实例,          // 并通过代理对象获得配置信息.
21                 resultCode = invokeActionOnly();
22             }
DefaultActionInvocation.invoke()
  • 首先会顺序的递归执行当前Action中所配置的所有的拦截器, 直到拦截器遍历完毕调用真正的Action
  •  通过调用DefaultActionInvocation的invokeActionOnly()方法去反射调用Action, 过程中, 会从当前的invocation对象中得到Action的实例, 并通过代理对象获得配置信息.

  5.com.opensymphony.xwork2.DefaultActionInvocation.invokeAction()方法:

  • 反射获得当前请求分发的Action中的方法对象
  • 以传入的Action实例反射调用该处理方法
  • 如果返回的结果不是com.opensymphony.xwork2.Result的实例, 返回强转为字符串的结果.

  6.回到1.4所在方法继续:

  • 将invokeAction返回的resultCode存储到当前的invokeAction实例中
  • 进入result处理

  7.com.opensymphony.xwork2.DefaultActionInvocation.executeResult()方法:

  •  创建result对象(com.opensymphony.xwork2.DefaultActionInvocation.createResult()方法)
    • 如果当时调用Action返回了Result对象, 则直接返回
    • 否则, 通过proxy对象获取配置信息, 根据resultCode获取到Result对象
  • 使用ognl翻译result中的用${}和%{}标识引用ValueStack中的值的参数.
  • 调用执行result

   8.org.apache.struts2.dispatcher.ServletDispatcherResult.doExecute()方法

  • 准备执行环境: request, pageContext等等
  • 判断有没有合适的分发器, 如果没有, 发404消息
  • 在request对象中设定两个属性:
    •  struts.view_uri: 分发之后的url地址
    •  struts.request_uri: 真正请求的url地址
  • 发送真正的响应信息

   9.至此, Action的处理完毕, 回归到1.4.1中指明的递归调用那里, 逐步的返回并执行每个拦截器的invokeAction.invoke()后面的代码, 从这里也就可以看出拦截器的机制.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

c

posted on 2015-05-02 20:00  半死的大头菜  阅读(226)  评论(0编辑  收藏  举报