Struts2中Result类型介绍
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类型介绍相关推荐
- Struts2中 Result类型配置详解
一个result代表了一个可能的输出.当Action类的方法执行完成时,它返回一个字符串类型的结果码,框架根据这个结果码选择对应的result,向用户输出. 在com.opensymphony.xwo ...
- 关于struts2 中result type=stream
struts2中 result="stream",可以实现文件的下载功能. 这里有两篇比较清楚和基础的文章:http://kin111.blog.51cto.com/738881/ ...
- struts2中result的type跳转类型总结
1,局部result和全局result 局部result:包含在Action定义中, result属性是一个Action的子元素.其作用范围只能在本Action中. 全局result:使用<gl ...
- Struts2中自定义类型转换器
Struts2虽然提供了强大的类型转换机制,但是有的情况还是需要程序员手动去转换. 同样拿经典的用户登录功能: <h2>局部类型转换器</h2><s:form actio ...
- 运维:Windows 系统安全日志中登录类型介绍
IT运维者必备技能包括能看懂操作系统的日志,才能快速定位问题处理问题,Windows系统的安全日志中可以获得更多有价值的信息,比如它细分了很多种登录类型,可以方便让你区分登录者到底是从本地登录.网络登 ...
- ABAP中P类型介绍
ABAP中比较难以理解的是P类型的使用,P类型是一种压缩类型,主要用于存储小数,定义时要指定字节数和小数点位数,定义语法如下: DATA: name(n) TYPE P decimals m,n代表字 ...
- redis中hash类型介绍
在redis中,hash数据类型存储的数据与mysql数据库中存储一条记录极为相似,是一个string类型的field和value的映射表,它特别适合用于存储对象,但字段值只能是字符串,不支持其他类型 ...
- struts2中result的type属性详解
(1)type="dispatcher" 为默认,用于jsp页面跳转 <result name="success">/index.jsp</ ...
- struts2中常用Result类型的用法
一.dispatcher (1)为缺省的result类型,一般情况下我们在struts.xml会这么写: <result name="success">/main.js ...
最新文章
- python端午dragboat消消乐 美轮美奂的界面效果
- 奥数国家队最强6人集结,深圳中学独占2席,人大附中连续三年入围
- 小型数据中心规划和设计原则
- springboot读取json文件_SpringBoot:配置文件属性读取
- 我的域控是不是被攻击了?吓!
- 2017-2018-1 20155301 20155307 20155339 《信息安全系统设计基础》 实验一 开发环境的熟悉...
- 一筐鸡蛋筐拿鸡蛋的问题
- 十次方项目 请仔细查看
- 姓名常用汉字代码查询器
- 单片机学习方法总结资料分享
- HTML5期末大作业:网站——餐饮网页设计(HTML+CSS+JS)
- Python实现图片灰度化
- 银河麒麟鸿蒙计划,银河麒麟Kydroid2.0发布,支持海量安卓APP,要抢鸿蒙的风头吗?...
- 解决Python无法找到入口——无法定位到程序输入点
- 魂斗罗java代码素材和代码_魂斗罗素材
- Recoil - Facebook 官方 React 状态管理器
- 厌倦只是一瞬间的事 2012-03-29 09:54:01 明明该有许多话要交代下去有许多事要汇报上去,明明有很多事情要去做,可是偏偏都不想去。可是突然还是打算留在电脑前漫无目的地把时间都耗费在了
- PX4多冗余传感器代码解读
- Ballerina语言有望改善应用程序集成
- 英语口语练习三十之听歌学口语:Boom Clap,你在我的世界里闪闪发光用法
热门文章
- 归纳(四):树链剖分
- Linux查找大文件 (find的用法)
- nQueen问题java实现
- TensorFlow2.0(七)--基础API使用
- 7-7 旅游规划 (8 分)
- 掉入陷阱的数字 (15 分)
- android sdk版本升级,个推 Android SDK 老版本升级2.9.+
- php 响应时间,PHP下解决ajax请求服务器响应时间过长问题
- android 进度条图标方形_Android - 条纹进度条实现,调整view宽度仿进度条
- php登陆+链接+验证,php+ajax验证登录跳转登录的实现方法