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

  • 相关阅读:
    vim使用技巧
    排序
    2020-3-27 学习面向对象的笔记
    小圆圈第三章答案
    内置函数部分用法
    Pycharm快捷键
    小猿圈第二章答案
    Typora学习笔记
    AI的真实感
    Unity 横版2D移动跳跃问题——关于一段跳与二段跳
  • 原文地址:https://www.cnblogs.com/xuehen/p/4305930.html
Copyright © 2011-2022 走看看