zoukankan      html  css  js  c++  java
  • struts基础2

    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"/> 再来访问时便可以访问到。

  • 相关阅读:
    zoj 3279 线段树 OR 树状数组
    fzu 1962 树状数组 OR 线段树
    hdu 5057 块状链表
    hdu3487 Play with Chain
    bzoj 1588营业额统计(HNOI 2002)
    poj2823 Sliding Window
    poj2828 Buy Tickets
    poj2395 Out of Hay
    poj3667 Hotel
    poj1703 Lost Cows
  • 原文地址:https://www.cnblogs.com/xuehen/p/4305930.html
Copyright © 2011-2022 走看看