• Struts2 在Action中操作数据


    Servlet存储数据的方式

    在Servlet中,使用ServletContext对象来存储整个WebApp的数据,ServletContext中直接存储整个WebApp的公共数据,可使用set|get|removeAttribute()来操作数据。

    此外ServletContext中还有3类众多的小对象:

    • ServletConfig     一个ServletConfig存储一个Servlet的初始化配置参数
    • request   一个request存储一个用户的请求参数
    • session   一个session存储一个用户的会话信息

    这3类对象也用于存储数据,也有对应的set|get|removeAttribute()方法。

    一共是4类对象,这4类对象均使用Map来存储数据,这个Map叫做域。


    Action操作数据的方式

    Action是用来代替Servlet的,Servlet用ServletContext来存储数据,Action用ActionContext来存储数据。

     ActionContext context = ActionContext.getContext();
    
            //设置、修改、获取参数
            context.put("age",18);
            int age =(int) context.get("age");   //返回值是Object,需要强转

    ActionContext本身可以存储数据,ActionContext中也有其他的域对象。

     ActionContext context = ActionContext.getContext();
            
            Map<String, Object> application = context.getApplication();  //获取ServletContext的Map对象,即application域
            Map<String, Object> session = context.getSession();  //获取session对象的Map对象,即session域
            HttpParameters parameters = context.getParameters();   //获取所有的请求参数,此对象相当于EL内置的param、paramValues对象

    Map对象、HttpParameters对象均有put()、get()、remove()方法,可通过这些方法来操作数据。


    获取原生的Servlet对象,通过原生的Servlet对象来操作数据

    Struts2提供了三种方式,来获取原生的Servlet对象。

    1、ActionContext本身可以存储数据,也可以获取ServletContext、request、response三个原生的Servlet对象:

     ActionContext context = ActionContext.getContext();
    
            //获取原生的Servlet对象。因为get()返回值是Object,所以均需强转
            ServletContext servletContext = (ServletContext) context.get("com.opensymphony.xwork2.dispatcher.ServletContext");
            HttpServletRequest request = (HttpServletRequest) context.get("com.opensymphony.xwork2.dispatcher.HttpServletRequest");
            HttpServletResponse response = (HttpServletResponse) context.get("com.opensymphony.xwork2.dispatcher.HttpServletResponse");

    2、key太复杂,记不住,所以Struts2提供了工具类ServletActionContext:

    //均为ServletActionContext类的静态方法
            ServletContext servletContext = ServletActionContext.getServletContext();
            HttpServletRequest request = ServletActionContext.getRequest();
            HttpServletResponse response = ServletActionContext.getResponse();

         HttpSession session = ServletActionContext.getRequest().getSession();

    3、通过实现接口来获取

    public class LoginAction extends ActionSupport implements ServletContextAware {
    
        @Override
        public String execute() throws Exception {
            return super.execute();
        }
    
        @Override
        public void setServletContext(ServletContext servletContext) {
    
        }
    }

    实现ServletContextAware接口,只需实现一个方法。Tomcat会获取并传入一个ServletContext对象,我们要做的就是写一个ServletContext类型的成员变量,把传入的值赋给它,这样这个Action中就可以直接使用ServletContext对象了(成员变量)。

    public class LoginAction extends ActionSupport implements ServletContextAware {
        private ServletContext servletContext;
    
        @Override
        public String execute() throws Exception {
            return super.execute();
        }
    
        @Override
        public void setServletContext(ServletContext servletContext) {
            this.servletContext=servletContext;
        }
    }

    要使用ServletContext对象,就实现ServletContextAware接口;

    要使用HttpServletRequest对象,就实现ServletRequestAware接口;

    要使用HttpServletResponset对象,就实现ServletResponseAware接口;

    可同时实现这些接口。

    其实第2、3种方式底层都是:调用第一种方式获取原生的Servlet对象,返回。


     

    ActionContext对象的生命周期

    •  Servlet是线程不安全的。在WebApp运行期间,一个Servlet只有一个实例,所有请求(用户)共享这个实例的成员变量,容易引发问题,通常的做法是把可能会被多个用户修改的变量写在方法体中(局部变量)。基于Servlet的Struts1也是不安全的。

    • Struts2是线程安全的。在WebApp运行期间,Struts2会为每一个请求创建一个新的Action实例,处理完这个请求,对应的Action实例就销毁。

    • ActionContext对象随Action对象的创建而创建,随Action对象的销毁而销毁。即ActionContext与Servlet中原生的request对象的生命周期一致,所以存储数据可以用ActionContext代替Servlet的request。可以用ActionContext来传递数据,但请求参数并不会放在ActionContext的数据区域,不能  ActionContext.getContext().get("xxx")这样来获取请求参数。


    Action中获取请求参数的方式

     1、获取原生的request对象,通过request对象来获取请求参数

    HttpServletRequest request = ServletActionContext.getRequest();
    String name = request.getParameter("name");

    请求参数封装在request对象的parameters对象中,不是直接封装在request对象中,request中直接封装的是setAttribute()的数据。

    把request作为一个大Map,里面还有一个小Map,小Map用于封装请求参数。  Map<String, String[]> parameterMap = request.getParameterMap();  。

     Object obj=request对象.getAttribute("user"); 获取的是setAttribute()存入的数据。

     String user = request对象.getParameter("user"); 获取的才是请求参数(从小Map中查找数据)。

    2、通过ActionContext获取HttpParameters对象,再通过HttpParameters对象来获取请求参数

    ActionContext context = ActionContext.getContext();
            HttpParameters parameters = context.getParameters();
            Parameter name = parameters.get("name");

    获取的参数是Parameter类型。HttpParameters相当于一个Map。

    3、属性驱动

    public class LoginAction extends ActionSupport {
        private String name;
        private Integer age;  //尽管有自动拆箱、装箱,还是尽量用包装类型
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public Integer getAge() {
            return age;
        }
    
        public void setAge(Integer age) {
            this.age = age;
        }
    
        @Override
        public String execute() throws Exception {
            return null;
        }
    
    }

    将要使用的请求参数写成Action的成员变量,并提供setter、getter方法,以及为Action提供空参的构造器。

    请求参数都是String类型,会先将请求参数转换为对应的成员变量的类型,再调用setter方法赋给对应的成员变量。

    只适用于8种基础类型、Date类型,Date类型对字符串格式有要求,比如2019-09-01。

    要求请求参数的name(表单字段的name)与成员变量的变量名相同。

        name:<input type="text" name="name"><br />
        age:<input type="text" name="age"><br />

    属性驱动的缺点:要使用的请求参数很多时,Action中会有大量的成员变量、getter、setter方法,很繁杂。

    静态参数注入:

    <action name="LoginAction" class="action.LoginAction">
                <param name="user">张三</param>
                <param name="age">18</param>
    
                <result name="success">index.jsp</result>
                <result name="fail>login.jsp</result>
    </action>

    在<param>中指定Action成员变量的值,不常用。

    4、对象驱动

    将要使用的请求参数封装到一个JavaBean(实体类)中,作为Action的成员变量,Action要提供对应的getter、setter方法以及空参构造器:

    public class LoginAction extends ActionSupport {
        private User user;
    
        public User getUser() {
            return user;
        }
    
        public void setUser(User user) {
            this.user = user;
        }
    
        @Override
        public String execute() throws Exception {
            System.out.println(user.getName());
            return null;
        }
    
    }

    需要提供JavaBean(实体类),这个实体类要具有getter、setter方法、空参构造器:

    public class User {
        private String name;
        private String age;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getAge() {
            return age;
        }
    
        public void setAge(String age) {
            this.age = age;
        }
    }

    表单字段的name属性要加上对象名:

     name:<input type="text" name="user.name"><br />
     age:<input type="text" name="user.age"><br />

    name属性的写法与之前不同,可能不习惯。

    5、模型驱动

    public class LoginAction extends ActionSupport implements ModelDriven<User> {
        //需要显式创建(new出来),否则为null。
        private User user=new User();
    
        @Override
        public User getModel() {
            //返回接受请求参数的对象
            return user;
        }
    
        @Override
        public String execute() throws Exception {
            return null;
        }
    
    }

    需要实现ModelDriver<T>接口,只需实现getModel()方法,返回接受请求参数的对象。

    需要显式创建接受请求参数的对象,否则这个对象为null,使用这个对象时会引发空指针异常。但不用给这个对象提供setter、getter方法。

    依然需要提供JavaBean(实体类)。

    表单字段的name属性使用原来的写法:

        name:<input type="text" name="name"><br />
        age:<input type="text" name="age"><br />

    模型驱动的缺点:只能有一个Model,只能将请求参数封装到一个实体类中。对象驱动则可以有多个对象,可以将参数封装到多个对象中。

    6、使用集合封装请求参数

    原生的Servlet是将请求参数封装到request中,HttpParameters是将请求参数封装到HttpParameters中,属性驱动是将请求参数封装到Action的多个成员变量中,对象驱动、模型驱动都是将请求参数封装到JavaBean中。

    此外还可以使用集合(List或Map)来封装请求参数。

    • 使用List封装请求参数

    public class LoginAction extends ActionSupport{
        private List<String> list;
    
        public List<String> getList() {
            return list;
        }
    
        public void setList(List<String> list) {
            this.list = list;
        }
    
        @Override
        public String execute() throws Exception {
            return null;
        }
    
    }

    需要提供getter、setter方法。

    表单字段的name属性指定List对象:

        name:<input type="text" name="list"><br />
        age:<input type="text" name="list"><br />

    会把请求字段存储到一个List中,第一个字段存储为List的第一个元素,第二个字段存储为第二个元素......以此类推。

    可以指定存储位置:

        name:<input type="text" name="list"><br />
        age:<input type="text" name="list[3]"><br />
        tel:<input type="tel" name="list"><br />
        

    [name字段的值,tel字段的值,null,age字段的值]

    指定了下标的,存储在指定的位置上;没有指定下标的,从前往后,存储在闲置的位置(null)上。

    • 使用Map封装请求参数

    public class LoginAction extends ActionSupport{
        private Map<String,String> map;
    
        public Map<String, String> getMap() {
            return map;
        }
    
        public void setMap(Map<String, String> map) {
            this.map = map;
        }
    
        @Override
        public String execute() throws Exception {
            return null;
        }
    
    }

    需要提供getter、setter方法。

    表单字段:

        name:<input type="text" name="map['name']"><br />
        age:<input type="text" name="map['age']"><br />

    Map是以键值对来存储字段的,所以还需指定key。Map对象['key']。

      


    原生的Servlet对象是给Servlet用的,在Action中使用原生的Servlet对象,会使Action耦合Serlvet。

    使用Struts2就尽量使用Action的方式操作数据,除非使用原生的Servlet对象会更加方便,比如操作Cookie。

    Action中的域(Map)与Servlet的域对应,在JSP中同样可以使用EL表达式取出域中的值。

  • 相关阅读:
    Vue基础简介
    Vue基础简介
    django生命周期请求l流程图
    CSRF与auth模块
    cookie与session django中间件
    Django forms组件与钩子函数
    ajax结合sweetalert实现删除按钮动态效果
    ajax数据交互
    如何绕过CDN找源站ip
    IP地址的另一种形式---一种隐藏IP的方法
  • 原文地址:https://www.cnblogs.com/chy18883701161/p/11461506.html
Copyright © 2020-2023  润新知