Result配置详解 
说明:在前面的许多案例中我们所用到的Action基本都继承自ActionSupport这个类,而在这个类中我们定义了五个字段:SUCCESS,NONE,ERROR,INPUT,LOGING。我们可以直接返回这些字段值,这些字段值实质是被定义成:String SUCCESS=”success”这样的形式,所以我们只要在Result元素中用它们的小写即可。 
<result>标准完整形式如下: 
<result name="success" type="dispatcher">  
 
<param name="location">/default.jsp</param> 
</result> 
如果我们都采用默认的形式,最终可以简写成:<result>/default.jsp</result>

探讨type类型:

Type类型值               作用说明                                              对应类 
chain                用来处理Action链                              com.opensymphony.xwork2.ActionChainResult

dispatcher        用来转向页面,通常处理JSP                 org.apache.struts2.dispatcher.ServletDispatcherResult

redirect            重定向到一个URL                              org.apache.struts2.dispatcher.ServletRedirectResult

redirectAction    重定向到一个Action                           org.apache.struts2.dispatcher.ServletActionRedirectResult

plainText       显示源文件内容,如文件源码                    org.apache.struts2.dispatcher.PlainTextResult

freemarker    处理FreeMarker模板                             org.apache.struts2.views.freemarker.FreemarkerResult

httpheader 控制特殊http行为的结果类型                    org.apache.struts2.dispatcher.HttpHeaderResult

stream     向浏览器发送InputSream对象,通              org.apache.struts2.dispatcher.StreamResult

常用来处理文件下载,还可用于返回AJAX数据。
 velocity   处理Velocity模板                                     org.apache.struts2.dispatcher.VelocityResult

xslt         处理XML/XLST模板                                  org.apache.struts2.views.xslt.XSLTResult  
以上对type类型作简要的说明,下面来看实例:当一个Action处理后要返回的Result是另一个Action时,作如何配置,关键就是配置type类型。下面建立struts2result项目说明 步骤一:建立两个Action:TestAction、Test2Action 
步骤二:web.xml配置省略。struts.xml主要配置内容如下: 
<struts>  <package name="resultTest" extends="struts-default">   <action name="test" class="com.asm.TestAction">    <result name="success" type="chain">     
<param name="actionName">test2</param>    
</result> 
  
</action> 
   <action name="test2" class="com.asm.Test2Action">    
<result name="success">/test2Suc.jsp</result>   
</action>  
 
</package> 
</struts> 
说明:在名为“test”的action中,我们配置result元素的type类型值为chain,意为将继续把Action传递到下一个名为test2的Action中去,在test2.action中会把页面转向到test2Suc.jsp中去。在type类型为chain时,它的param有4个值可配,除了这里用到的name=”actionName”外(必须配置,否则报错),还有name=namespace|method|skipActions。其中namespace指定要转向到action的名字空间,由于此处是转到Action位于同一个namespace下,而namesapace的默认值the current namespace,所以可以省略不写(需要说明的是如果要跳到别的名称空间的action中去,除了使用namespace指定外,还可以用:/要跳去action所在名称空间的值/要跳去的action的name值)。Method用于指定转向到一个目标action所调用的方法,默认是调用下一个action的execute方法,所以此处仍可以省略。SkipActions是一个可选的属性,一般不用。具体可以参看chain所对应类的api帮助。 
在本实例中,我们还在TestAction中设定一个username字段,并在execute方法执行为它赋了值,并在test2Suc.jsp中引用了此值。其实这种做法在web开发中还是很有用处,比如可以代替隐藏域。需要注意的是之所以在action的传递中能把设定的这个值保存下去,主要是因为转向都是服务器跳转。如果我们跳转时采取了客户端跳转,比如在test2 action的result中指定type类型为redirect,要想传递参数可以在result指向的jsp页面中附加参数即可,我们可以在test2 action的result中写成: 
<result name="success" type="redirect">

/test2Suc.jsp?username=${username} 
</result>   随后在test2Suc.jsp页面中引用时会出现三个问题:1.EL表达式引用失效,(EL表达式
应该使用${param.username}形式)。我们也可以使用<%=request.getParameter("username")%>获取参数值。  2.由于在前面的TestAction中设定的值为中文,而附加到这里的uri请求的参数后面时会出现乱码问题。(可以使用URI编码再解码解决此问题)3.值栈取值失效:因为每一次request共享同一个值栈,所以服务器端的forward跳转也是能共享同一值栈得。但是着当test action执行后把请求交由test2 action时,test2 action采取的是redirect重定向到test2Suc.jsp页面,这时其实就是重发的一次request,所以在test action保存的值栈内容全部失效。这也就是为什么我们要附加参数的原因。而参数是保存在actionContext中,所以采用了#的方式来取出值。图示说明: 
  
步骤三,编写链接页面index.jsp。发布测试: 
全局result: 
如果我们所有的action均有可能跳到相同的页面,则不防使用全局result。为了方便引用我们专门建立一个package来存放公共的result。在会用到个全局的跳转时,只需要把继承自这个公共的package即可。 建立公共包,代码如下: 
<package name="pubResult" extends="struts-default" abstract="true">   <global-results>    
<result name="error">/error.jsp</result>  
 
</global-results> 
</package>  
由于它下面没的action配置,所以我们可以像默认的struts-default包一样,声明abstract=true,这样声明表示此packgage下不会有action,它一般是用来让别的package继承。随后再在要用到全局result中引用这个公共的package。代码如下: 
<package name="testGlobal" extends="pubResult" >  <action name="error" class="com.asm.ErrorAction"></action>  
<action name="error2" class="com.asm.Error2Action"></action> 
</package>这样操作相当于把全局的result加到了此package下的所有action中去。

异常处理 
步骤一、建立struts2exception项目下,在该项目下建立登录页面login.jsp。主要代码如下: 
<form action="<%=request.getContextPath() %>/login.action">   username:<input type="username" name="username"><br>  
 
<input type="submit" value="login"> 
</form>

步骤二、建立LoginAction,代码如下: 
package com.asm; 
public class LoginAction extends ActionSupport {  private String username; 
 public String execute() throws Exception {   if (username.equals("exception")) { 
   throw new ClassNotFoundException("类未被找到");   } else if (username.equals("global")) {    throw new Exception("全局异常");   } else {    return SUCCESS; 
  } 
 

 ...省力get/set方法 } 
步骤三、struts.xml配置文件如下: 
<struts>  <package name="ex" extends="def">   <action name="login" class="com.asm.LoginAction">    <exception-mapping result="myException"     
exception="java.lang.ClassNotFoundException">    </exception-mapping> 
   <result name="myException">/exception.jsp</result>    
<result name="success">/main.jsp</result> 
  
</action> 
 </package> 
  <package name="def" extends="struts-default" abstract="true">   <global-results>    
<result name="myGlobal">/globalException.jsp</result>   
</global-results> 
   <global-exception-mappings>    <exception-mapping result="myGlobal"     
exception="java.lang.Exception">    
</exception-mapping> 
  
</global-exception-mappings> 
 
</package> 
</struts> 
分析:异常处理机制较为简单,所以在此只略作说明。当登录时输入“exception”时,在LoginAction中会抛出会一个ClassNotFoundException异常,此异常我们采取的局部异常处理的方式,如果登录时输入“globla”,则会抛出Exception异常,此异常我们采取的是全局异常的处理方式,在ex包中我们继承了全局异常所在的包。提示:<exception-mapping>中的result属性的值来源于<result>元素中的name属性的值。从实例可以看出,我们一般把这种全局性的异常放在一个抽象包中供其实包继承。

在Action获取Scope对象 
引言:在前面的Action操作中,关键就是Action中的exectue方法,但是此方法并没有request、session、application等对象作为参数,自然就不能利用这些对象来操作。下面我们建立struts2scope项目,并用四种方式来获取这些对象:

方式一、与Servlet解耦合的非IOC方式 
获取的scope对象与容器无关,通过ActionContext获取。 LoginAction代码如下: 
package com.asm; 
public class LoginAction extends ActionSupport {  private String username;  ActionContext context;  Map request;  Map session;  Map application; 
 public String execute() throws Exception {   context=ActionContext.getContext();   request=(Map) context.get("request");   session=context.getSession(); 
  application=context.getApplication();    
  request.put("req", "requst属性");   session.put("ses", "sesion属性"); 
  application.put("app", "application属性");   return SUCCESS; 
 

 ...省略username的get/set方法 } 
struts.xml配置如下: 
<struts>  <package name="scope" extends="struts-default">   <action name="login" class="com.asm.LoginAction">  
 
 
<result>/loginSuc.jsp</result> 
</action> </package>   
</struts> 
login.jsp内容如下: 
<form action="<%=request.getContextPath() %>/login.action">   用户名:<input type="text" name="username"><br>  
 
<input type="submit" value="login">  
</form> 
loginSuc.jsp的主要内容如下: 
${requestScope.req} ${sessionScope.ses} ${applicationScope.app} 
<h4>以下使用scope.getAttribute的形式来接受</h4>   request: <%=request.getAttribute("req") %><br>  
 session: <%=session.getAttribute("ses") %><br> 
 
 
application:<%=application.getAttribute("app") %><br> 
分析:通过ActionContext的getContext静态方法得到ActionContext对象,然后ActionContext对象调用get方法来获取一个存储在request范围中的对象。我们使用el或通过request.getAttribute这样的方式  

均可以获取对象值,这说明了这些Map request对象实际是存储在request范围内的对象。 方式二、与Servlet解耦合的IOC方式 我们建立Login2Action,主要代码如下: 
package com.asm; 
public class Login2Action extends ActionSupport implements RequestAware,SessionAware,ApplicationAware {  private String username;  Map request;  Map session;  Map application; 
 public String execute() throws Exception {   request.put("req", "requst属性");   session.put("ses", "sesion属性"); 
  application.put("app", "application属性");   return SUCCESS; 
 } 
 public void setRequest(Map<String, Object> request) {   this.request=request; 
 } 
 public void setSession(Map<String, Object> session) {   this.session=session;  } 
 public void setApplication(Map<String, Object> application) {   this.application=application;  

 ...省略username的get/set方法  } 
注册此Action的name为login2,随后修改登录提交为.../login2.action。便可以发布测试。说明:此方法其实和方式一很相似,只是在方式一中我们需要手动的为Map request赋值,但是在方式二中它是通过实现接口,在重写接口中的方法中完成对Map requset的赋值,所以称之IOC方式。借助此例,略谈下依赖注入与控制反转:所谓依赖注入就是一个对象自己本身的初始化是依赖其它对象。比如这里Map request这些对象会依赖struts2来给其初始化,称为依赖注入,而依赖注入的就表示,这些对象的控制权不再由此类本身掌握,而是交给了别的对象,即是控制权反转了。 强调:方式二是开发中主要用的方式,应重点掌握 
方式三、与Servlet耦合的非IOC方式 建立Login3Action,代码如下: 
package com.asm; 
public class Login3Action extends ActionSupport {  private String username;  HttpServletRequest request;  HttpSession session; 
 ServletContext application; 
 public String execute() throws Exception {   request = ServletActionContext.getRequest();   session = request.getSession(); 
  
application = ServletActionContext.getServletContext();

request.setAttribute("req", "requst属性");   session.setAttribute("ses", "sesion属性"); 
  application.setAttribute("app", "application属性");   return SUCCESS; 
 

 ...省略username的get/set方法。 } 
此方法获取的纯粹的Scope对象,它与容器相关,这些Scope对象操作更强。同样只需要注册此Action并修改登录页面便可进行测试。 方式四、与Servlet耦合的IOC方式 建立Login4Action,代码如下: 
package com.asm; 
public class Login4Action extends ActionSupport implements ServletRequestAware,ServletContextAware{  private String username;  ActionContext context;  HttpServletRequest request;  HttpSession session; 
 ServletContext application; 
 public String execute() throws Exception {   context=ActionContext.getContext();   session=request.getSession();  
  request.setAttribute("req", "requst属性");   session.setAttribute("ses", "sesion属性"); 
  application.setAttribute("app", "application属性");   return SUCCESS; 
 }   
 public void setServletRequest(HttpServletRequest request) {   System.out.println("测试:"+request);   this.request=request; 
 } 
 public void setServletContext(ServletContext application) {   System.out.println("测试:"+application);   this.application=application; 
 

 ...省略username的get/set方法 } 
同样只需要注册此Action并修改登录页面便可发布测试

OGNL与ValueStack(VS) 
1.值栈入门 
下面我们建立struts2ognl项目来练习ognl的使用。 步骤一、搭建strust2的开发环境 
步骤二、建立LoginAction,主要代码如下: 
package com.asm; 
public class LoginAction extends ActionSupport{  
private User user;

public String execute() throws Exception {  
   
return SUCCESS; 
 

 ...省略user的get/set方法  } 
步骤三、配置此Action,struts.xml的主要内容如下: 
<struts>  <constant name="struts.devMode" value="true"></constant>   <package name="ognl" extends="struts-default">   <action name="login" class="com.asm.LoginAction">    
<result>/loginSuc.jsp</result>   
</action> 
 
</package> 
</struts> 
步骤四、编写login.jsp页面,主要代码如下: 
<body>  <form action="<%=request.getContextPath()%>/login.action"  method="get">   用户名:<input type="text" name="user.username"><br>   密  码:<input type="password" name="user.password"><br>   
<input type="submit" value="login"> 
 
</form> 
</body> 
步骤五、编写loginSuc.jsp页面,主要代码如下: 
<body>   
 
调试:<s:debug></s:debug> 
  获取值栈中的username属性:<s:property value="user.username"/> <br> </body> 
步骤六、发布测试及说明 
当我们输入用户名并成功跳到logSuc.jsp页面后,会得到登录时输入的用户名信息。下面简要说明这一过程: 
(1).login.jsp登录提交登录信息给login.action 
(2).struts2监听到客户端的login.action请求,按配置文件要求,把此请求交给LoginAction处理。这表示会去new LoginAction(), 当struts2  new出此Action对象后会把这个对象放在context map中,只是这个Action非常特殊,所以放在值栈中,而放在值栈中的对象是可以直接引用的,放在其它context map中的对象引用时会要求加#。 
(3).当new LoginAction时,表示它也会初始化此类中的对象,比如这里会去初始化User对象,但是要注意的是如果我们在用户名和密码什么都不输,再来用debug来看值栈中的user是,发现它仍会new此对象,因为尽管我们没用输入值,但是后台的set方法还是要被调用,所以会new出此对象,但是如果我们直接输入.../struts2ognl/login.action时我们会发现跳转到loginSuc.jsp页面时,用debug来看值栈中此User user,发现它的值为null。第二点要注意的是我们必须为User类提供默认的构造方法,否则将会出现如下错误: java.lang.InstantiationException: com.asm.vo.User 总结:1.Action会在请求时被创建,且会把创建的对象放到值栈中。 
2.Action中的对象字段只有在需要时才会以new 的形式初始化,而且这些对象字段必须提供默认的构造方法。 
3.ValueStack对象贯穿整个Action的生命周期(每个Action类的对象实例会拥有一个ValueStack对象)。当Struts 2接收到一个.action的请求后,会先建立Action类的对象实例,但并不会调用Action方法,而是先将Action类的相应属性放到ValueStack对象的顶层节点(vs对象相当于一个栈)。

补充:值栈(根)对象也可以直接使用EL表达式访问,比如这里可以直接通过${user.username}来获取username的值,我们知道el表达式只能访问四种scope范围内的对象,那为什么这里能访问到值栈对象呢?原因是struts2对HttpServletRequet进行了一次封装,封装的代码主要是重写了getAttribute方法,简述重写此方法的核心代码:首先在原始的HttpServletRequest对象中查找el表达式中的属性,如果找不到再通过ActionContext获取值栈对象,进而再从值栈对象中查找el表达式中要访问的属性。 2.OGNL入门 
下面我们在com.asm.vo.User类中增加一个字段private Address addres;,并提供此字段的get/set方法,随后再在login.jsp中增加如下代码: 
城  市:<input type="text" name="user.addres.city"><br> 然后再在loginSuc.jsp中增加如下代码: 
获取城市属性:<s:property value="user.addres.city"/><br> 
然后测试,会得到登录时输入的城市信息(中文会有乱码)。下面借助此例谈ognl的定义:在这个例子中,我们的LoginAction中有一个User对象,而在User对象中又有一个Address对象,这些对象之间依靠这种类的字段进行关联,或者说是依靠字段属性进行导航,这也就是OGNL的定义:Object Graph Navigation Language:对象图导航图语言,它是建立在值栈技术之上的一种全新语言。 
补充:用%{}可以取出存在值堆栈中的Action对象,直接调用它的方法.我们在loginSuc.jsp中增加如下内容调用LoginAction中的get方法: 
调用值栈对象中的方法:<s:property value="%{get()}"/>  
LoginACtion中增加的get方法如下: 
public String get(){   return "这是User中的get方法"; 

3.普通方法访问 
首先在User中增加一个成员方法,代码如下: 
public String get(){   return "这是User中的get方法"; 

在LoginAction中也有类似的get方法,随后再在loginSuc.jsp中增加如下代码: 
调用值栈对象中的普通方法(2):<s:property value="user.username.length()"/><br> 调用值栈对象中的普通方法(1):<s:property value="user.get()"/><br> 调用LoginAction中的普通方法:<s:property value="get()"/><br> 
最后测试,发现这些方法都可以访问到。 4.静态方法访问 
在LoginAction中增加如下方法: 
public static String getSta() {   return "这是LoginAction中的静态方法"; 

然后在loginSuc.jsp中增加如下代码: 
调用Action中的静态方法:<s:property value="@com.asm.LoginAction@getSta()"/><br> 调用LoginAction中的静态方_方式(2):<s:property value="@vs@getSta()"/><br> 
说明:我们在方式二中用到@vs,只有那些值栈中的对象才可以这样写。 然后访问,发现访问不到,因为在struts2.1.6的版本中,struts.ognl.allowStaticMethodAccess的默认值为false,我们只需在struts.xml中增加如下内容: 
<constant name="struts.ognl.allowStaticMethodAccess" value="true"/> 再来访问时便可以访问到。

struts基础2的更多相关文章

  1. java学习-struts基础(一)

    struts发展 struts是Apache软件基金会赞助的一个开源项目,是一个基于Java EE的MVC开源实现. 它为Servlet/JSP技术的应用提供技术框架2001.7--Struts1正式 ...

  2. Struts基础详解

    1.web.xml配置: <filter> <filter-name>Struts2</filter-name> <filter-class> org. ...

  3. struts基础3-把数据写入页面

    一.OGNL(Object-Groph Navigation Language) 是一种强大的表达式语言,可以存取对象的任意属性,调用对象的方法,遍历整个对象的结构图,实现字段类型转化等功能. 1)与 ...

  4. struts基础

    六个基本包 struts2-core-2.1.6.jar :开发的核心类库 freemarker-2.3.13.jar :struts2的UI标签的模板使用freemarker编写 commons-l ...

  5. 【Struts 基础案例】

    LoginAction package k.action; import k.form.UserForm; import org.apache.struts.action.*; import java ...

  6. 【Web】Eclipse + Maven + Struts搭建服务器

    一.环境 系统:Windows7 IDE:Eclipse-Kepler Service Release 2 使用插件:Maven(请预先在电脑上安装Maven) 二.搭建 在Eclipse中新建一个M ...

  7. 在Apache Struts中利用OGNL注入

    前言 本文简要介绍了Apache Struts的OGNL注入缺陷,文章中介绍使用简单的应用程序复现OGNL注入.深入研究针对公共漏洞,并理解这类漏洞. 内容 安装Apache Tomcat服务器(入门 ...

  8. SSH框架的简单示例(执行流程)

    本文转自一篇博文,感觉通俗易懂,适用于初学j2ee者,与大家一起分享 (一)struts框架部分 1.打开Myeclipse,创建一个web project,项目名称为TestSSH. 2.在web的 ...

  9. SSH入门简单搭建例子

    因为公司涉及项目使用SSH,为了解SSH搭建方式和运作原理,就自己搭建了一个. 采用尽量以最少的JAR包,搭建一个简单的struts2+spring+hibernate环境,希望像我这样的入门者都能理 ...

随机推荐

  1. java中子类继承父类程序执行顺序

    java中子类继承父类程序执行顺序 FatherTest.java public class FatherTest { private String name; public FatherTest() ...

  2. MySQL高级学习笔记(七):MySql主从复制

    文章目录 复制的基本原理 slave会从master读取binlog来进行数据同步 三步骤+原理图 复制的基本原则 复制的最大问题 一主一从常见配置 mysql版本一致且后台以服务运行(双方能够pin ...

  3. yum安装apache

    一.查询是否已经安装apache rpm  -qa  httpd 注:Apache在linux系统里的名字是httpd 如果有返回的信息,则会显示已经安装的软件.如果没有则不会显示其它的信息.如下图是 ...

  4. java.lang

    package cn.sxt;   import java.lang.*;   public class BooleanDemo {      public static void main(Stri ...

  5. Android/IOS APP界面设计之尺寸规范

    1.尺寸以及分辨率 iPhone的界面尺寸不用多说,640*960是基本OK的,也可以是适应5S的640*1136,马上iPhone 6也快来了(随便吐槽一下网上曝的真机谍照,真是丑到离谱...),只 ...

  6. 厉害了,Spring团队又开源 nohttp 项目!

    作者:h4cd 来源:https://www.oschina.net/news/107377/spring-opensource-nohttp Spring 团队开源 nohttp 项目,用以查找.替 ...

  7. USACO 2014 US Open Dueling GPS's /// SPFA

    题目大意: 给定n个点m条边的有向图 有两个GPS 分别认为 A[i]到B[i] 的一条边的花费是P[i].Q[i] 当当前走的边不是GPS认为的最短路上的边就会被警告 即两个GPS都不认为是最短路上 ...

  8. Java的枚举类型使用方法详解

    1.背景在java语言中还没有引入枚举类型之前,表示枚举类型的常用模式是声明一组具有int常量.之前我们通常利用public final static 方法定义的代码如下,分别用1 表示春天,2表示夏 ...

  9. RK3288 控制usb摄像头补光GPIO

    正常可以通过添加dts配置,再从设备树中读取gpio号,在这里为了简单,直接使用GPIO号,先通过终端测试gpio, 系统自带GPIO控制驱动: 内核已经自带了通用GPIO驱动,可以直接在用户空间操作 ...

  10. SVN版本管理与大型代码上线方案(一)

    SVN版本管理与大型代码上线方案(一) 链接:https://pan.baidu.com/s/1A3Iq3gGkGS27L_Gt37_I0g 提取码:ncy2 复制这段内容后打开百度网盘手机App,操 ...