1.在Struts2中,Result类型有12种,分别为dispatcher,redirect,chain,redirectAction,freemarker,httpheader,stream,velocity,xslt,plainText,titles,postback。下面对这12种Result类型分别进行介绍,其中最常用的有dispatcher,redirect,chain,redirectAction,如果不指定result的type属性,默认为dispatcher分发跳转方式。

2.其中在struts.xml配置文件中,里面的包继承的包为struts_default,而包所继承的这个struts_default为一个xml文件,放在struts2的核心代码库里面,即下图的红色箭头指向处:

打开下图的红色箭头的struts-default.xml文件:

打开后我们可以看到如下图所示:

其中我们可以看到result的type类型有11种,相应的名字和对应的类,所以我们在学习的时候可以看相应的class类,即看源代码学习,下面将对这11种result类型进行介绍。

3.上面的要我们看我们查看源代码学习,所以我们应该学习如何才能看到我们的源代码,没导入jar包和路径的话,都是字节码,不能看到我们熟悉的Java代码,其中我们导入的路径位于我们下载的struts2所需的文档,jar包等等,所以下面介绍如何导入相应的路径来看我们的源代码:

(1).首先,我们选择struts2-core-2.3.20.jar包,然后鼠标右键选择Properties,即属性这个选项,出现下图,点击下图的红色箭头指向处的按钮:

(2).其中我在网上下载的struts-2.3.20-all.zip的压缩包,我们要导入源代码的话,我的是这个路径:E:\struts-2.3.20\struts-2.3.20\src\core\src\main\java,大家看后面几个文件夹便可以找到了,如下图所示:

这样我们就可以查看相应的类文件代码了。

对于result的type属性中有一个是放在xwork-core-2.3.20.jar包下的,所以也需要导入源代码,我的路径为:E:\struts-2.3.20\struts-2.3.20\src\xwork-core\src\main\java,然后像上面一步一样打开属性,然后就可以了,如下图所示:

这样便可以查看底层的代码了。

3.前面说了那么多,还没说到重点,即result的type类型,上面也是为了学习result的type而做的部分工作,接下来便开始介绍result的type了:

(1).dispatcher:运用服务器跳转到jsp页面(视图),不可以跳转到Action,只可以跳转到视图,在struts.xml配置文件中,如果没有为result设置type属性的话,默认就是通过这种方式跳转的。

(2).redirect:客户端跳转(重定向),其中url(地址栏的地址)会发生变化,不可以跳转到Action,只可以跳转到视图。

(3).chain:用来处理Action链,跳转到Action,可以动用到Action,在访问Action时,Action前面不要加 "/" 。

(4).redirectAction:客户端跳转到Action,其中url(地址栏的地址)会发生变化。

(5).freemarker:处理FreeMarker模板。

(6).httpheader:用来控制特殊的Http行为,发送一个Http头。

(7).stream:意思是流,向浏览器发送InputSream对象,通常用来处理文件下载。

(8).velocity:处理Velocity模板。

(9).xslt:处理XML/XLST模板。

(10).plainText:返回页面的源码。

(11).titles:把页面分成几块,每个页面可以动态的指定。

(12).postback:回传,即页面在首次加载后向服务器提交数据,然后服务器把处理好的数据传递到客户端并显示出来。

4.下面新建一个struts2项目,项目名为ResultType,这个项目只对常用的几个result类型进行介绍:

(1).首先,打开index.jsp页面,修改编码方式为utf-8,具体代码如下:

<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><base href="<%=basePath%>"><title>My JSP 'index.jsp' starting page</title><meta http-equiv="pragma" content="no-cache"><meta http-equiv="cache-control" content="no-cache"><meta http-equiv="expires" content="0">    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"><meta http-equiv="description" content="This is my page"><!--<link rel="stylesheet" type="text/css" href="styles.css">--></head><body><ol><li><a href="r/r1">dispatcher</a></li><li><a href="r/r2">redirect</a></li><li><a href="r/r3">chain</a></li><li><a href="r/r4">redirectAction</a></li><li><a href="r/r5">plainText</a></li></ol></body>
</html>

(2).接着新建两个jsp页面,分别为r1.jsp和r2.jsp,其中内容自定:

r1.jsp页面代码如下:

<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><base href="<%=basePath%>"><title>My JSP 'index.jsp' starting page</title><meta http-equiv="pragma" content="no-cache"><meta http-equiv="cache-control" content="no-cache"><meta http-equiv="expires" content="0">    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"><meta http-equiv="description" content="This is my page"><!--<link rel="stylesheet" type="text/css" href="styles.css">--></head><body>dispacther成功</body>
</html>

r2.jsp页面代码如下:

<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><base href="<%=basePath%>"><title>My JSP 'index.jsp' starting page</title><meta http-equiv="pragma" content="no-cache"><meta http-equiv="cache-control" content="no-cache"><meta http-equiv="expires" content="0">    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"><meta http-equiv="description" content="This is my page"><!--<link rel="stylesheet" type="text/css" href="styles.css">--></head><body>redirect成功</body>
</html>

(3).下面对常用的几个result类型进行配置:

dispatcher,相应的struts.xml配置如下:

<action name="r1"><result type="dispatcher">/r1.jsp</result>
</action>

跳转到r1.jsp页面。

redirect,相应的struts.xml配置如下:

<action name="r2"><result type="redirect">/r2.jsp</result>
</action>

重定向到r2.jsp页面,其中地址栏的地址发生变化。

chain,相应的struts.xml配置如下:

<action name="r3"><result type="chain">r1</result>
</action>

r1这个action,跳转到r1.jsp页面

redirectAction,相应的struts.xml配置如下:

<action name="r4"><result type="redirectAction">r2</result>
</action>

访问r2这个action,其中url发生改变,重定向到r2.jsp页面。

注:当访问不同的namespace下的Action时,则使用如下方式:

<action name="r5"><result type="chain"><param name="actionName">r1</param><!-- action名称 --><param name="namespace">/r</param><!-- namespace值 --></result>
</action>

其中为什么要定义actionname,namespace这两个参数呢,因为在底层代码中所有,所以必须把这两个参数传进去,才可以跳转页面,其中chain这个类型放在 哪里呢,我们可以打开前面我们所说的struts-default.xml文件,打开之后,如下图:

我们可以打开这个com.opensymphony.xwork2包下的ActionChainResult类,代码如下:

/** Copyright 2002-2006,2009 The Apache Software Foundation.* * Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at* *      http://www.apache.org/licenses/LICENSE-2.0* * Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/
package com.opensymphony.xwork2;import com.opensymphony.xwork2.inject.Inject;
import com.opensymphony.xwork2.util.TextParseUtil;
import com.opensymphony.xwork2.util.ValueStack;
import com.opensymphony.xwork2.util.logging.Logger;
import com.opensymphony.xwork2.util.logging.LoggerFactory;import java.util.*;/**
* <!-- START SNIPPET: description -->
*
* This result invokes an entire other action, complete with it's own interceptor stack and result.
*
* <!-- END SNIPPET: description -->
*
* <b>This result type takes the following parameters:</b>
*
* <!-- START SNIPPET: params -->
*
* <ul>
*
* <li><b>actionName (default)</b> - the name of the action that will be chained to</li>
*
* <li><b>namespace</b> - used to determine which namespace the Action is in that we're chaining. If namespace is null,
* this defaults to the current namespace</li>
*
* <li><b>method</b> - used to specify another method on target action to be invoked.
* If null, this defaults to execute method</li>
*
* <li><b>skipActions</b> - (optional) the list of comma separated action names for the
* actions that could be chained to</li>
*
* </ul>
*
* <!-- END SNIPPET: params -->
*
* <b>Example:</b>
*
* <pre><!-- START SNIPPET: example -->
* <package name="public" extends="struts-default">
*     <!-- Chain creatAccount to login, using the default parameter -->
*     <action name="createAccount" class="...">
*         <result type="chain">login</result>
*     </action>
*
*     <action name="login" class="...">
*         <!-- Chain to another namespace -->
*         <result type="chain">
*             <param name="actionName">dashboard</param>
*             <param name="namespace">/secure</param>
*         </result>
*     </action>
* </package>
*
* <package name="secure" extends="struts-default" namespace="/secure">
*     <action name="dashboard" class="...">
*         <result>dashboard.jsp</result>
*     </action>
* </package>
* <!-- END SNIPPET: example --></pre>
*
* @author <a href='mailto:the_mindstorm[at]evolva[dot]ro'>Alexandru Popescu</a>
*/
public class ActionChainResult implements Result {private static final Logger LOG = LoggerFactory.getLogger(ActionChainResult.class);/*** The result parameter name to set the name of the action to chain to.*/public static final String DEFAULT_PARAM = "actionName";/*** The action context key to save the chain history.*/private static final String CHAIN_HISTORY = "CHAIN_HISTORY";/*** The result parameter name to set the name of the action to chain to.*/public static final String SKIP_ACTIONS_PARAM = "skipActions";private ActionProxy proxy;private String actionName;private String namespace;private String methodName;/*** The list of actions to skip.*/private String skipActions;private ActionProxyFactory actionProxyFactory;public ActionChainResult() {super();}public ActionChainResult(String namespace, String actionName, String methodName) {this.namespace = namespace;this.actionName = actionName;this.methodName = methodName;}public ActionChainResult(String namespace, String actionName, String methodName, String skipActions) {this.namespace = namespace;this.actionName = actionName;this.methodName = methodName;this.skipActions = skipActions;}/*** @param actionProxyFactory the actionProxyFactory to set*/@Injectpublic void setActionProxyFactory(ActionProxyFactory actionProxyFactory) {this.actionProxyFactory = actionProxyFactory;}/*** Set the action name.** @param actionName The action name.*/public void setActionName(String actionName) {this.actionName = actionName;}/*** sets the namespace of the Action that we're chaining to.  if namespace* is null, this defaults to the current namespace.** @param namespace the name of the namespace we're chaining to*/public void setNamespace(String namespace) {this.namespace = namespace;}/*** Set the list of actions to skip.* To test if an action should not throe an infinite recursion,* only the action name is used, not the namespace.** @param actions The list of action name separated by a white space.*/public void setSkipActions(String actions) {this.skipActions = actions;}public void setMethod(String method) {this.methodName = method;}public ActionProxy getProxy() {return proxy;}/*** Get the XWork chain history.* The stack is a list of <code>namespace/action!method</code> keys.*/public static LinkedList<String> getChainHistory() {LinkedList<String> chainHistory = (LinkedList<String>) ActionContext.getContext().get(CHAIN_HISTORY);//  Add if not existsif (chainHistory == null) {chainHistory = new LinkedList<String>();ActionContext.getContext().put(CHAIN_HISTORY, chainHistory);}return chainHistory;}/*** @param invocation the DefaultActionInvocation calling the action call stack*/public void execute(ActionInvocation invocation) throws Exception {// if the finalNamespace wasn't explicitly defined, assume the current oneif (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);}proxy = actionProxyFactory.createActionProxy(finalNamespace, finalActionName, finalMethodName, extraContext);proxy.execute();}@Override public boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;final ActionChainResult that = (ActionChainResult) o;if (actionName != null ? !actionName.equals(that.actionName) : that.actionName != null) return false;if (methodName != null ? !methodName.equals(that.methodName) : that.methodName != null) return false;if (namespace != null ? !namespace.equals(that.namespace) : that.namespace != null) return false;return true;}@Override public int hashCode() {int result;result = (actionName != null ? actionName.hashCode() : 0);result = 31 * result + (namespace != null ? namespace.hashCode() : 0);result = 31 * result + (methodName != null ? methodName.hashCode() : 0);return result;}private boolean isInChainHistory(String namespace, String actionName, String methodName) {LinkedList<? extends String> chainHistory = ActionChainResult.getChainHistory();if (chainHistory == null) {return false;} else {//  Actions to skipSet<String> skipActionsList = new HashSet<String>();if (skipActions != null && skipActions.length() > 0) {ValueStack stack = ActionContext.getContext().getValueStack();String finalSkipActions = TextParseUtil.translateVariables(this.skipActions, stack);skipActionsList.addAll(TextParseUtil.commaDelimitedStringToSet(finalSkipActions));}if (!skipActionsList.contains(actionName)) {//  Get if key is in the chain historyreturn chainHistory.contains(makeKey(namespace, actionName, methodName));}return false;}}private void addToHistory(String namespace, String actionName, String methodName) {List<String> chainHistory = ActionChainResult.getChainHistory();chainHistory.add(makeKey(namespace, actionName, methodName));}private String makeKey(String namespace, String actionName, String methodName) {if (null == methodName) {return namespace + "/" + actionName;}return namespace + "/" + actionName + "!" + methodName;}
}

该类里面有actionName,namespace属性,还有一些属性,如methodName等。

plainText,相应的struts.xml配置如下:

<action name="r5"><result type="plainText"><param name="location">/index.jsp</param><!-- 跳转的页面位置 --><param name="charSet">utf-8</param><!-- 指定文件的编码 --></result>
</action>

这个会 返回index.jsp页面的源码,其中两个参数,可以看struts-default.xml文件,看plainText放在哪个类中,看源码可看出也是需要两个参数的,这里就不多说了,大家可以自己琢磨!

(4).完整的struts.xml配置文件代码如下:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN""http://struts.apache.org/dtds/struts-2.0.dtd"><struts><constant name="struts.enable.DynamicMethodInvocation" value="true"></constant><package name="rt" namespace="/r" extends="struts-default"><action name="r1"><result type="dispatcher">/r1.jsp</result></action><action name="r2"><result type="redirect">/r2.jsp</result></action><action name="r3"><result type="chain">r1</result></action><action name="r4"><result type="redirectAction">r2</result></action><action name="r5"><result type="plainText"><param name="location">/index.jsp</param><param name="charSet">utf-8</param><!-- 指定文件的编码 --></result></action></package><package name="user" namespace="/g" extends="struts-default"><action name="r5"><result type="chain"><param name="actionName">r1</param><!-- action名称 --><param name="namespace">/r</param><!-- namespace值 --></result></action></package>
</struts>

接着部署该项目到Tomcat服务器上,开启Tomcat服务器,访问index.jsp页面,如下:

依次点击超链接,如下所示:

然后我们访问不同包下的action,如下所示:

5.以上内容仅供大家学习参考,写得不好,请见谅,如有错误,请指出,谢谢!



Struts2中Result类型介绍相关推荐

  1. Struts2中 Result类型配置详解

    一个result代表了一个可能的输出.当Action类的方法执行完成时,它返回一个字符串类型的结果码,框架根据这个结果码选择对应的result,向用户输出. 在com.opensymphony.xwo ...

  2. 关于struts2 中result type=stream

    struts2中 result="stream",可以实现文件的下载功能. 这里有两篇比较清楚和基础的文章:http://kin111.blog.51cto.com/738881/ ...

  3. struts2中result的type跳转类型总结

    1,局部result和全局result 局部result:包含在Action定义中, result属性是一个Action的子元素.其作用范围只能在本Action中. 全局result:使用<gl ...

  4. Struts2中自定义类型转换器

    Struts2虽然提供了强大的类型转换机制,但是有的情况还是需要程序员手动去转换. 同样拿经典的用户登录功能: <h2>局部类型转换器</h2><s:form actio ...

  5. 运维:Windows 系统安全日志中登录类型介绍

    IT运维者必备技能包括能看懂操作系统的日志,才能快速定位问题处理问题,Windows系统的安全日志中可以获得更多有价值的信息,比如它细分了很多种登录类型,可以方便让你区分登录者到底是从本地登录.网络登 ...

  6. ABAP中P类型介绍

    ABAP中比较难以理解的是P类型的使用,P类型是一种压缩类型,主要用于存储小数,定义时要指定字节数和小数点位数,定义语法如下: DATA: name(n) TYPE P decimals m,n代表字 ...

  7. redis中hash类型介绍

    在redis中,hash数据类型存储的数据与mysql数据库中存储一条记录极为相似,是一个string类型的field和value的映射表,它特别适合用于存储对象,但字段值只能是字符串,不支持其他类型 ...

  8. struts2中result的type属性详解

    (1)type="dispatcher" 为默认,用于jsp页面跳转  <result name="success">/index.jsp</ ...

  9. struts2中常用Result类型的用法

    一.dispatcher (1)为缺省的result类型,一般情况下我们在struts.xml会这么写: <result name="success">/main.js ...

最新文章

  1. python端午dragboat消消乐 美轮美奂的界面效果
  2. 奥数国家队最强6人集结,深圳中学独占2席,人大附中连续三年入围
  3. 小型数据中心规划和设计原则
  4. springboot读取json文件_SpringBoot:配置文件属性读取
  5. 我的域控是不是被攻击了?吓!
  6. 2017-2018-1 20155301 20155307 20155339 《信息安全系统设计基础》 实验一 开发环境的熟悉...
  7. 一筐鸡蛋筐拿鸡蛋的问题
  8. 十次方项目 请仔细查看
  9. 姓名常用汉字代码查询器
  10. 单片机学习方法总结资料分享
  11. HTML5期末大作业:网站——餐饮网页设计(HTML+CSS+JS)
  12. Python实现图片灰度化
  13. 银河麒麟鸿蒙计划,银河麒麟Kydroid2.0发布,支持海量安卓APP,要抢鸿蒙的风头吗?...
  14. 解决Python无法找到入口——无法定位到程序输入点
  15. 魂斗罗java代码素材和代码_魂斗罗素材
  16. Recoil - Facebook 官方 React 状态管理器
  17. 厌倦只是一瞬间的事 2012-03-29 09:54:01 明明该有许多话要交代下去有许多事要汇报上去,明明有很多事情要去做,可是偏偏都不想去。可是突然还是打算留在电脑前漫无目的地把时间都耗费在了
  18. PX4多冗余传感器代码解读
  19. Ballerina语言有望改善应用程序集成
  20. 英语口语练习三十之听歌学口语:Boom Clap,你在我的世界里闪闪发光用法

热门文章

  1. 归纳(四):树链剖分
  2. Linux查找大文件 (find的用法)
  3. nQueen问题java实现
  4. TensorFlow2.0(七)--基础API使用
  5. 7-7 旅游规划 (8 分)
  6. 掉入陷阱的数字 (15 分)
  7. android sdk版本升级,个推 Android SDK 老版本升级2.9.+
  8. php 响应时间,PHP下解决ajax请求服务器响应时间过长问题
  9. android 进度条图标方形_Android - 条纹进度条实现,调整view宽度仿进度条
  10. php登陆+链接+验证,php+ajax验证登录跳转登录的实现方法