Struts2中几种Result源码分析

看了看Struts2中chain dispatcher redirect redirectAction的源码实现方式,记录一下自己的学习历程

1 chain 和  dispatcher是服务器端跳转,一个http请求到服务器,struts进行内部资源的跳转,dispatcher一般向页面进行跳转,chain即可以向页面跳转,也可以向action进行跳转

chain

struts中所有的result类型都实现result接口(典型的策略模式),我们先来看ActionChainResult

public void execute(ActionInvocation invocation) throws Exception {
       //1.保留现场,记录一些数据
        if (this.namespace == null) {
            this.namespace = invocation.getProxy().getNamespace();
        }
        /
        ValueStack stack = ActionContext.getContext().getValueStack();
        String finalNamespace = TextParseUtil.translateVariables(namespace, stack);
        String finalActionName = TextParseUtil.translateVariables(actionName, stack);
        String finalMethodName = this.methodName != null
                ? TextParseUtil.translateVariables(this.methodName, stack)
                : null;

        if (isInChainHistory(finalNamespace, finalActionName, finalMethodName)) {
            addToHistory(finalNamespace, finalActionName, finalMethodName);
            throw new XWorkException("Infinite recursion detected: "
                    + ActionChainResult.getChainHistory().toString());
        }

        if (ActionChainResult.getChainHistory().isEmpty() && invocation != null && invocation.getProxy() != null) {
            addToHistory(finalNamespace, invocation.getProxy().getActionName(), invocation.getProxy().getMethod());
        }
        addToHistory(finalNamespace, finalActionName, finalMethodName);

        HashMap<String, Object> extraContext = new HashMap<String, Object>();
        extraContext.put(ActionContext.VALUE_STACK, ActionContext.getContext().getValueStack());
        extraContext.put(ActionContext.PARAMETERS, ActionContext.getContext().getParameters());
        extraContext.put(CHAIN_HISTORY, ActionChainResult.getChainHistory());

        if (LOG.isDebugEnabled()) {
            LOG.debug("Chaining to action " + finalActionName);
        }

        //2.上面的代码将第一个action的ActionContext全部都保留了下来,然后当作extraContext创建了一个新的ActionProxy,并且调用了execute方法,执行了chain后的action。
        
        proxy = actionProxyFactory.createActionProxy(finalNamespace, finalActionName, finalMethodName, extraContext);
        proxy.execute();
    }

上面的代码将第一个action的actionContext等信息全部保留了下来,当作extraContext放入了一个新建的ActionProxy中,然后调用proxy中的execute方法,将新的acion执行了一遍(PS:新action的一系列interceptor也会执行,其实就是调用了invocation.invoke方法,而不是invocation.invokeActionOnly方法)

dispatcher

也是execute方法,选取其中的关键代码

 public void doExecute(String finalLocation, ActionInvocation invocation) throws Exception {
        .........省略一些代码...........
            HttpServletRequest request = ServletActionContext.getRequest();
            HttpServletResponse response = ServletActionContext.getResponse();
            RequestDispatcher dispatcher = request.getRequestDispatcher(finalLocation);
                //finalLocation就是拼装出来的最终跳转的url地址        
            request.setAttribute("struts.view_uri", finalLocation);
            request.setAttribute("struts.request_uri", request.getRequestURI());
                   //本质是调用org.apache.catalina.core.applicationDispatcher的forward方法  
                dispatcher.forward(request, response);
    }


2.redirect 和 Redirectaction都是客户端的重定向,浏览器会再发出一个http请求,浏览器的url地址会变化

redirect和redirectAction的实现原理基本一样,只是在parse最终生成的url方法上略有差异

protected void sendRedirect(HttpServletResponse response, String finalLocation) throws IOException {
        if (SC_FOUND == statusCode) {
            response.sendRedirect(finalLocation);
        } else {
            response.setStatus(statusCode);
            response.setHeader("Location", finalLocation);
            response.getWriter().write(finalLocation);
            response.getWriter().close();
        }

    }

       execute方法中redirect和redirect拼装好finallocation,最终调用sendRedirect方法,来了个http 302.

PS:注意的是

当使用type=“redirectAction” 或type=“redirect”提交到一个action并且需要传递一个参数时。这里是有区别的:

使用type=“redirectAction”时,结果就只能写Action的配置名,不能带有后缀:“.action”  

使用type=“redirect”时,action要加后缀:“.action”  

转载于:https://my.oschina.net/u/1165712/blog/317323

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值