• Java框架之Struts2(二)


    一、Action 配置说明

    //请求的直接转发
    <package name="packageUser" namespace="" extends="struts-default">
        <action name="addUser">
        <result>success.jsp</result>
        </action>    
    </package>

    访问的时候 : http://localhost:8080/Struts2-02/addUser

    注意

    1) action 没有写 class 属性

    2) action 没有写 method 属性

    3) result 没写 name 属性

    那它们的值是怎么得到的呢? 实际上,它们都是有默认值的,在每个action被执行的时候,它都会被反射成一个java对象,// struts2中的action是多实例的

    action 配置中,各项的默认值

    1) 如果不写class 它的默认值是  ActionSupport

    2) 如果不指定 method 它的默认值是 execute   

    3) 如果不指定result 的name  默认是 success

    上面的写法,相当于

    <action name="addUser" class="com.opensymphony.xwork2.ActionSupport" method="execute" >
    <result name="success" >success.jsp</result>
    </action>    

    二、result 的配置说明

    在 struts2-core-2.3.16.3.jar  -> 下的 struts-default.xml 文件中有如下声明:

    <package name="struts-default" abstract="true">
        <result-types>
            <result-type name="chain" class="com.opensymphony.xwork2.ActionChainResult"/>
            <result-type name="dispatcher" class="org.apache.struts2.dispatcher.ServletDispatcherResult" default="true"/>
            <result-type name="freemarker" class="org.apache.struts2.views.freemarker.FreemarkerResult"/>
            <result-type name="httpheader" class="org.apache.struts2.dispatcher.HttpHeaderResult"/>
            <result-type name="redirect" class="org.apache.struts2.dispatcher.ServletRedirectResult"/>
            <result-type name="redirectAction" class="org.apache.struts2.dispatcher.ServletActionRedirectResult"/>
            <result-type name="stream" class="org.apache.struts2.dispatcher.StreamResult"/>
            <result-type name="velocity" class="org.apache.struts2.dispatcher.VelocityResult"/>
            <result-type name="xslt" class="org.apache.struts2.views.xslt.XSLTResult"/>
            <result-type name="plainText" class="org.apache.struts2.dispatcher.PlainTextResult" />
            <result-type name="postback" class="org.apache.struts2.dispatcher.PostbackResult" />
        </result-types>
            .... 
    </package>

    1) dispatcher(默认值)  //内部请求转发,和过去servlet 中 forwart 一样

    2) redirect  //重定向 注意,重定向,是不可能定向到 WEB-INF 下的

    3) redirectAction //重定向到某个Action上 ,最典型的应用,比如添加用户以后,重定向到一个用户查询的action上

    4) plainText //以文本的形显示jsp或html

    5) chain //用来处理Action链,一个action处理完后,转发到下一个action

    6) stream //向浏览器发送InputStream 对象,通常用来下载,还可以返回ajax数据

    7) freemarker //处理 freemarker 模板

    8) httpheader //控制特殊HTTP行为的结果类型 根据值栈返回自定义的HttpHeader,status指定响应状态

    9) velocity //处理Velocity模板  //Velocity是一个基于java的模板引擎

    10) xslt // 处理XML/XLST模板

    11)postback

    //例子 使用 redirect方式在 url 后面传值的例子
    <package name="packageThree" namespace=""  extends="struts-default">
       <action name="usrEdit" class="cat.action.UserEditAction" method="execute" >
       <result name="success" type="redirect" >/test_redirect.jsp?userName=${userName}</result> 注意,这里的 type 为redirect
       </action>
    </package>
                        
    //并且,在 UserEditAction 中:
    public class UserEditAction {
       private String userName; //要生成get set 方法
       public String execute(){
              try {  
                   userName=URLEncoder.encode("这是很久很久没来的高睿","UTF-8");  //为了处理乱码,这里要URLEncoder
                  } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                                        }
                   return "success";
    }
    //在test_redirect.jsp中,可以用 ${userName} 取出来值,但如果有中文将出现乱码,可以如下处理
    <% 
        String userName= request.getParameter("userName");
        userName=new String(userName.getBytes("iso8859-1"),"UTF-8");
        // userName=URLDecoder.decode(userName,"UTF-8");  实测不加也可以
            out.println(userName);
    %
    //例子 重定向到别的action 
    <action name="redirectOtherActionTest">
    <result type="redirectAction">otherActionName</result>    
    </action>
                        
    <action name="otherActionName">
    <result>success.jsp</result>
    </action>
    //例子 重定向到别的包中的 action 
    <action name="redirectOtherPackageActionTest">
    <result type="redirectAction">
    <param name="actionName">xxx</param>
    <param name="namespace">/two</param>
    </result>    
    </action>

    三、配置全局视图

    <global-results>
      <result name="g_error">/error.jsp</result> //这是包范围内的全局视图
    </global-results>
             
    <action name="userAdd" class="cat.action.UserAction" method="add" >
    //这里没有配置 result 
    </action>
             
    public class UserAction extends ActionSupport {
           public String add(){
           return "g_error";  //全局视图
           }
    }

    如果视图要做成全局的怎么办 (跨包)

    1) 声明一个包 并继承 struts-default ,把它交给别人继承。在这个包里,声明全局视图

    2) 用别的包来继承它

    //这个包是专门用来给别的包继承的
         <package name="base" extends="struts-default" >
               <global-results>
                   <result name="g_success">/success.jsp</result>
                   <result name="g_eror">/error.jsp</result>
               </global-results>
        </package>
       
       <package name="packageUser" namespace="" extends="base">
              <action name="userAdd" class="cat.action.UserAction" method="add" > 
                 //如果这里也有一个 <result name="g_eror">/error.jsp</result> ,则会覆盖全局视图
              </action>
       </package>
            
            public class UserAction extends ActionSupport {
                public String add(){
                    return "g_success";  //全局视图
                    }
          }

    result 用来配置逻辑视图与物理视图之间的映射关系,视图资源不一定是JSP页面,目前的视图资源有:

    Velocity

    FreeMarker

    JFreeChart

    报表 JasperReports

    XSLT

    四、为 Action 的属性注入值

    public class NumZhuRuAction {
                private String compName;  //公司名称
                private String money;  //公司现金
                
                  ...  get set 方法
                
                    public String execute(){
                        return "success";
                    }
            }
    
         <package name="packageUser" namespace="" extends="base">
            <action name="numZhuRuAction" class="cat.action.NumZhuRuAction" method="execute">
                <param name="compName">海康公司</param>
                <param name="money">100元</param>
                <result name="success">/zhuru_ok.jsp</result>
            </action>
       </package>

    五、struts2 中的常用常量

    指定 struts2 请求的后缀,在前面,访问请求地址都可以加上.action 后缀。写在web.xml中的过滤器 org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter 是Struts 2框架的核心控制器,它负责拦截由  <url-pattern>杠*</url-pattern>指定的所有用户请求,当用户请求到达时,该Filter会过滤用户请求。默认情况下,如果用户请求的路径以.action结尾,该请求将被转入Struts2框架处理,否则该请求将略过Struts2 框架的处理。

    可以通过配置常量,来指定这个请求的后缀  struts.action.extension

    <constant name="struts.action.extension" value="do,action,cat"></constant>  可以指定多个

    常量可以在struts.xml或struts.properties中配置,建议在struts.xml中配置,两种配置方式如下:

    --struts.xml

    <struts>
       <constant name="struts.action.extension" value="do"/>
    </struts>

     --struts.properties 文件中

    struts.action.extension=do

    通常,struts2按如下搜索顺序加载struts2常量:

    struts-default.xml //struts-core-2.3.25.2.jar 中

    struts-plugin.xml //struts2-convention-plugin-2.1.6.jar ?

    struts.xml

    struts.properties //它在哪儿? 在src下手工建一个就行了 里面放上 struts.action.extension=cat,dog 则会覆盖 struts.xml 中的配置

    web.xml

    如果在多个文件中配置了同一个常量,则后一个文件中配置的常量值会覆盖前面文件中配置的常量值

    Struts2常用的常量  svn  极限开发,可以在帮助文档中的 home.html 中的指南下找到。struts2 的常量,也叫 struts2 的属性,主要用来控制整个struts2 的运行特性。

    --<constant name="struts.i18n.encoding" value="UTF-8" />//指定默认编码集 作用于HttpServletRequest的SetCharaterEncoding方法和 freemarker,velocity(模板技术) 输出

    --<constant name="struts.action.extension" value="do" /> //指定请求后缀 ,多个用逗号分开

    --<constant name="struts.serve.static.browserCache" value="false" /> //指定浏览器是否缓存静态内容,默认值为true(生产环境下使用),开发阶段最好关闭

    jsp——servlet——class 好:提高执行效率0.05s 0.7s  不好:不能及时的反应程序上的变化

    --<constant name="struts.Configuration.xml.reload" value="true" /> //指定struts配置文件修改后,系统是否自动重新加载该文件,默认为false(生产环境下用),开发除阶段最好打开

    --<constant name="struts.devMode" value="true" /> //开发模式下使用,这样可以打印出更详细的错误信息

    --<constant name="struts.ui.theme" value="simple" /> //指定默认的视图主题(Struts2  中有一些标签使用了视图主题 后面会有介绍)

    --<constant name="struts.objectFacvtory" value="spring" /> //指定创建Action 对象明的工厂类(本例:与 spring集成时,指定由sping负责Action的创建)

    --<constant name="struts.enable.DynamicMethodInvocation" value="false" /> //指定Struts2 是否支持动态方法调用,默认值是 false

    --<constant name="struts.mutipart.maxSzie" value="10701096" /> //设定上传文件的大小(不是指一个,是指一组)

    --<constant name="struts.multipart.saveDir" value="" />  设置上传言语件的临时目录

    六、Struts2的处理流程

    用户请求  ---->

    --->StrutsPreparedAndExecuteFilter   //配置在web.xml中的过滤器

    --->Interceptor  //struts2内置的一些拦截器或用户自定义的拦截器

    --->Action //用户定义的业务处理类,

    --->Result //视图

    --->jsp / html /其他

    StrutsPrepareAndExceuteFilter 是Struts 框架的核心控制器, 它负责拦截由<url-pattern>杠*</url-pattern> 指定的用户请求   

    当用户请求到达时,该filter 会过滤用户请求,默认情况下,如果用户请求的路径不带后缀, 或以.action结尾,则这时请求被转入到Struts2 框架进行处理,否则Sttuts2将略过该请求。

    当请求进入Struts2框架处理时会先经过一系列的拦截器, 然后再到Action与Struts1不同,Struts 2 对用户的每一次请示都会创建一个Action,所以Struts2中的Action是线程安全的管理方式,是一个常见的面试题(线程安全)Struts1 创建Action 中,会放到缓存里去(单例)。

    附:可以在action的构造函数中,输出内容,观察到每次访问,都会引起构造函数的调用。

    //为应用指定多个struts 配置文件
                    
    //在主文件中  <include file="good_conf.xml" />
                     
    //新建一个 配置文件,名称为 good_conf.xml
    <?xml version="1.0" encoding="UTF-8" ?>
        <!DOCTYPE struts PUBLIC
        "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
        "http://struts.apache.org/dtds/struts-2.3.dtd">
    <struts>
     <package name="package_xxx" extends="base">
      <action name="hellowGoods" >
       <result name="success">/goods_add.jsp</result>
      </action>
     </package>
    </struts>

    七、动态方法调用和使用通配符定义Action

    //动态方法调
    <constant name="struts.enable.DynamicMethodInvocation" value="true" />
       <action name="userAction" class="cat.action.UserAction" >  
           <result name="add_success">/add_success.jsp</result>
           <result name="del_success">/del_success.jsp</result>
           <result name="update_success">/update_success.jsp</result>
       </action>

    访问的时候: 在! 后面传要被调用的方法名

    http://localhost:8080/Struts2-02/userAction!delUser(不推荐 使用)

    //使用通配符的方式
    <action name="userActionNew_*" class="cat.action.UserAction" method="{1}">
       <result name="xxx_success">/{1}_success.jsp</result>  // 这里可以写成 {1}.jsp
    </action>

    http://localhost:8080/Struts2-02/userActionNew_updateUser
    http://localhost:8080/Struts2-02/userActionNew_addUser
    http://localhost:8080/Struts2-02/userActionNew_delUser

    附: 可以在视图中使用 ognl 表达式,以达到动态视图的效果,如下

    <result name="success">/WEB-INF/page/${某属性}.jsp</result>

    八、请求参数接收

    1.采用基本类型接收请求参数(get/post)

    在Action类中定义与请求参数同名的属性,struts2便能自动接收请求参数并赋予给同名属性。

    请求路径: http://localhost:8080/view.action?id=78

    Public class HellowAction{
       private integer id; 生成get 和set 方法
    //struts用反射技术处理,调用与请求参数同名的属性的seeter方法来获取请求参数值
    }

    2.采用复合类型接收请求参数

    请求路径 同上 http://localhost:8080/view.action?id=78

    Public class ProductAction{
        private Product prod;
        public void setProd(Product prod){this.prod=prod}
        public Product getProd(){ return this.prod}
    } 

    struts2首先通过反射技术调用Product 的默认构造方法,创建出product对象,然后再通过反射技术调用product中与请示参数同名的属性的setter方法来获取请求参数值。

    代码实例:

    1 建立Action类

    public class ParamTestAction {
           private String userName; //为之生成get 和set方法
           private String password;
                    
           public String execute() {    
           //if (this.userName.equals("admin") && this.password.equals("123")) { 
           if ("admin".equals(this.userName) && "123".equals(this.password)) {        //注意,这样的技可以避免空指针异常
              return "success";
              } else {
                return "err";
              }
            }
    }

    2 在structs.xml中配置

    <package name="packageSix" namespace="" extends="struts-default"> //注意,放在了默认的命名空间下,访问就不用写上/test了
      <action name="ParamTestAction" class="cat.action.ParamTestAction"    method="execute">
              <result name="success">/ParamSucc.jsp</result>
              <result name="err">/ParamErr.jsp</result>
      </action>
    </package>

    =====简单类型

    3 在ParamSucc.jsp中

    <body>
      登录成功
      ${userName }
      ${password }  
    </body>

    4 访问,以get方式传参

    http://localhost:8080/Struts/ParamTestAction?userName=admin&password=1234

    5 访问,以 form表单的post方式传参  在 Login.Jsp 中以form表单形式提交,结果同上

    <form action="ParamTestAction" method="post">
          <input type="text" name="userName" /> 
          <input type="password"    name="password" />
          <input type="submit" value="提交" >
    </form>

    ===采用复合类型

    1 建立Action类 先创建包bean ,再里面然添 UserInfo类,然后再创建Action

    public class BeanParamAction {
          private UserInfo userInfo; //生成get和set方法
          public String execute() {
             if ("admin".equals(userInfo.getUserName())    && ("123".equals(userInfo.getPassword()))) {    
             return "success";
             } else {
             return "err";
             }
          }
    }

    2 在structs.xml中配置 可以发现,这里的配置基本与上例相同

    <action name="BeanParamAction" class="cat.action.BeanParamAction"    method="execute">
       <result name="success">/BeanParamSucc.jsp</result>
       <result name="err">/BeanParamErr.jsp</result>
    </action>

    3 在BeanParamSucc.jsp 中

    <body>
      登录成功  采用复合类型接收参数
      ${userInfo.userName}
      ${userInfo.password}
    </body>

    4 访问,创建 BeanLogin.Jsp

    <form action="BeanParamAction" method="post">
       <input type="text" name="userInfo.userName" />  //注意参数的传法
       <input type="password"    name="userInfo.password" /> //注意参数的传法
       <input type="submit" value="提交" >
    </form>

    5 访问 http://localhost:8080/Struts/BeanLogin.jsp ,添加入数据进行验证

    需要注意的是:

    1)struts2 是通过反射,给userInfo注入的,所以 UserInfo 类必须提供默认的构造函数

    2)UserInfo中可以有多余字段   

    九、访问或添加request/session/application属性

    在struts2中 ,没有继承自HttpServlet , 方法,也没有传过来 request ,response 等参数。但假如我们想在作用域中传值,怎么处理?

    struts2 有两种处理方式

    1.伪访问  ActionContext

    public String execute(){    
           ActionContext ctx=ActionContext.getContext();  //是struts2 提供的
           ctx.getApplication().put("app_key", "全局范围内的值"); //相当于往 ServletContext 中放入
           ctx.getSession().put("session_key", "这是session内的值") ; //相当于往 session中放入
           ctx.put("request_key", "这是request中的值");
                    
           //ctx.getSession() 等操作,得到的是 map集合
           return "success";
    }
    //success.jsp
    <body>
      application : ${applicationScope.app_key}
      session:  ${sessionScope.session_key }
       request:  ${requestScope.request_key }
    </body>

    2.真访问  ServletActionContext 方式一

    public String testScope(){
           HttpServletRequest request =  ServletActionContext.getRequest();
           ServletContext application=ServletActionContext.getServletContext();
           HttpSession session=request.getSession();
                            
           request.setAttribute("requestKey", "用request对象设置的request的值");
           session.setAttribute("sessionKey", "用session对象设置的session的值");
           application.setAttribute("appKey", "用application 对象设置的 application的值");
    
           return "success";
           }
                    
          application : ${applicationScope.appKey}  <br>
          session:  ${sessionScope.sessionKey } <br>
          request:  ${requestScope.requestKey } <br>

    取得 作用域对象方式 二

    (实现接口,由struts2 运行的时候注入)

    public class BaseAction  extends ActionSupport implements ServletRequestAware,ServletContextAware,ServletResponseAware {
                            public HttpServletRequest request;
                            public ServletContext  servletContext;
                            public HttpServletResponse response;
                            public HttpSession session;
                            
                            public String execute(){
                                request.setAttribute("hahaha", "哈哈哈,这都是啥子");
                                return "success";     
                            }
                        
                            @Override
                            public void setServletResponse(HttpServletResponse response) {
                                this.response=response; 
                                
                            }
                        
                            @Override
                            public void setServletContext(ServletContext context) {
                                this.servletContext=context;
                            }
                        
                            @Override
                            public void setServletRequest(HttpServletRequest request) {
                                this.request=request;
                                this.session=request.getSession();
                            }    
                        }

    说明:一般情况下,这个BaseAction是用来给别的Action进行继承的。

  • 相关阅读:
    查询mysql哪些表正在被锁状态
    查询mysql哪些表正在被锁状态
    查询mysql哪些表正在被锁状态
    JS模块化工具requirejs教程(二):基本知识
    JS模块化工具requirejs教程(二):基本知识
    JS模块化工具requirejs教程(一):初识requirejs
    sublime的安装与使用
    清除浏览器默认样式——css reset & normalize.css
    webstorm常见快捷方法与遇到的一些问题
    【Git】commit成功后,GitHub贡献图方格没变绿
  • 原文地址:https://www.cnblogs.com/1693977889zz/p/8076434.html
Copyright © 2020-2023  润新知