欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Struts2 在Action中操作数据

程序员文章站 2022-07-02 13:02:38
Servlet存储数据的方式 在Servlet中,使用ServletContext对象来存储整个WebApp的数据,ServletContext中直接存储整个WebApp的公共数据,可使用set|get|removeAttribute()来操作数据。 此外ServletContext中还有3类众多的 ......

 

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、params对象

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();

 

 

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");

 

 

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方法,很繁杂。

 

 

 

 

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用的,使用struts2就尽量使用action的方式操作数据。但操作cookie还是原生的servlet对象方便一些。

action中的域(map)与servlet的域对应,在jsp中同样可以使用el表达式取出域中的值。