http://blog.csdn.net/yerenyuan_pku/article/details/67315598

Struts2访问Servlet的API

前面已经对Struts2的流程已经执行完成了,但是如果表单中有参数,那如何进行接收又或者我们需要向页面保存一些数据,又要如何完成呢?我们可以通过学习Struts2访问Servlet的API来实现这样的功能。 
在Struts2中,Action并没有直接和Servlet API进行耦合,也就是说在Struts2的Action中不能直接访问Servlet API。虽然Struts2中的Action访问Servlet API麻烦一些,但是这却是Struts2中Action的重要改良之一,方便Action进行单元测试。 
尽管Action和Servlet API解耦会带来很多好处,然而在Action中完全不访问Servlet API几乎是不可能的,在实现业务逻辑时,经常要访问Servlet中的对象,如session、request和application等。在Struts2中,访问Servlet API有3种方法,具体如下:

通过ActionContext类访问

Struts2框架提供了ActionContext类来访问Servlet API,ActionContext是Action执行的上下文对象,在ActionContext中保存了Action执行所需要的所有对象,包括parameters,request,session,application等。下面列举ActionContext类访问Servlet API的几个常用方法,具体如表所示: 


列举的是ActionContext类访问Servlet API的常用方法,要访问Servlet API,可以通过如下方式进行,具体示例代码如下:

ActionContext context = ActionContext.getContext();
context.put("name", "liayun");
context.getApplication().put("name", "liayun");
context.getSession().put("name", "liayun");

在上述示例代码中,通过ActionContext类中的方法调用,分别在request、application和session中放入了(“name”, “liayun”)对。可以看到,通过ActionContext类可以非常简单地访问JSP内置对象的属性。 
为了让大家更好地掌握如何通过ActionContext类来访问Servlet API,接下来通过一个具体的案例来演示ActionContext的使用。

  1. 在Eclipse中创建一个名称为struts2_day02的Web项目,将Struts2所需的Jar包复制到项目的lin目录中,并发布到类路径下。在WebContent目录下编写一个简单的登录页面form.jsp,如下所示:

    <%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Insert title here</title>
    </head>
    <body>
    <form action="${pageContext.request.contextPath }/userForm.action" method="post">
    username:<input type="text" name="username" /><br/>
    password:<input type="password" name="password" /><br/>
    <input type="submit" value="提交" />
    </form>
    </body>
    </html>
    • 1

    在该页面中,编写了用户名和密码输入框和一个登录提交按钮。

  2. 在WEB-INF目录下创建一个名称为web.xml的文件,在该文件中配置Struts2的核心控制器,如下所示:

    <!-- 配置Struts2的过滤器 -->
    <filter>
    <filter-name>struts2</filter-name>
    <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
    </filter> <filter-mapping>
    <filter-name>struts2</filter-name>
    <url-pattern>/*</url-pattern>
    </filter-mapping>
    • 1
  3. 在src目录下创建struts.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="demo" extends="struts-default" namespace="/">
    <!-- action获取表单提交数据 -->
    <action name="userForm" class="cn.itcast.action.form.UserFormAction"></action>
    </package>
    </struts>
    • 1
  4. 在src目录下创建一个cn.itcast.action.form包,再在cn.itcast.action.form包中创建UserFormAction类,进行业务逻辑处理,如下所示:

    public class UserFormAction extends ActionSupport {
    
        @Override
    public String execute() throws Exception { // 获取表单提交的数据 ActionContext类
    // 1.先得到ActionContext对象
    ActionContext context = ActionContext.getContext();
    // 2.再调用方法得到表单提交的数据
    Map<String, Object> map = context.getParameters();
    // 遍历
    Set<String> keys = map.keySet();
    for (String key : keys) {
    // 根据key得到value
    // 在map里面的value的类型是数组形式
    String[] value = (String[]) map.get(key);
    System.out.println(key + "::" + Arrays.toString(value)); // 数组作为字符串输出
    }
    return NONE;
    } }
    • 1

通过特定接口访问

Struts2框架提供了ActionContext类来访问Servlet API,虽然这种方法可以访问Servlet API,但是无法直接获得Servlet API实例。为了在Action中直接访问Servlet API,Struts2还提供了一系列接口,具体如下:

  • ServletRequestAware:实现该接口的Action可以直接访问Web应用的HttpServletRequest实例。
  • ServletResponseAware:实现该接口的Action可以直接访问Web应用的HttpServletResponse实例。
  • SessionAware:实现该接口的Action可以直接访问Web应用的HttpSession实例。
  • ServletContextAware:实现该接口的Action可以直接访问Web应用的ServletContext实例。

下面以ServletRequestAware为例,讲解如何在Action中访问HttpServletRequest实例。

  1. 将UserFormAction类的代码修改为:

    public class UserFormAction extends ActionSupport implements ServletRequestAware {
    
        HttpServletRequest request;
    
        public void setServletRequest(HttpServletRequest request) {
    this.request = request;
    } @Override
    public String execute() throws Exception { // 定义成员变量,把setServletRequest方法里面的request对象赋值到成员变量的request里面
    String username = request.getParameter("username");
    String password = request.getParameter("password");
    System.out.println(username + "::" + password); return NONE;
    } }
    • 1

    在上述文件中,自定义的UserFormAction类实现了Action的ServletRequestAware接口。需要注意的是,UserFormAction类中必须实现setServletRequest()方法和execute()方法,通过setServletRequest()方法,可以得到HttpServletRequest的实例,这是在调用execute()方法或者其他自定义的方法之前就调用的,然后在execute()方法中,就可以访问HttpServletRequest的属性内容了。

  2. 重新发布struts2_day02项目,在浏览器地址栏中输入http://localhost:8080/struts2_day02/form.jsp,成功访问后可以看出,使用ServletRequestAware接口顺利访问了Servlet API。

通过ServletActionContext类访问

为了直接访问Servlet API,Struts2框架还提供了ServletActionContext类,该类包含了几个常用的静态方法,具体如下:

  • static HttpServletRequest getRequest():获取Web应用的HttpServletRequest对象
  • static HttpServletResponse getResponse():获取Web应用的HttpServletResponse对象
  • static ServletContext getServletContext():获取Web应用的ServletContext对象
  • static PageContext getPageContext():获取Web应用的PageContext对象

接下来,讲解如何通过ServletActionContext访问Servlet API。

  1. 将UserFormAction类的代码修改为:

    public class UserFormAction extends ActionSupport {
    
        @Override
    public String execute() throws Exception { // 获取表单提交的数据,使用ServletActionContext类
    // 1.直接使用ServletActionContext类得到request对象
    HttpServletRequest request = ServletActionContext.getRequest();
    // 2.可直接调用request的方法得到表单提交的数据
    String username = request.getParameter("username");
    String password = request.getParameter("password");
    System.out.println(username + "::" + password); // 在Action类中如何操作域对象
    // 1.操作request域
    HttpServletRequest request = ServletActionContext.getRequest();
    request.setAttribute("request", "requsetValue"); // 2.操作session域
    request.getSession().setAttribute("session", "sessionValue"); // 3.操作servletContext域
    ServletContext servletContext = ServletActionContext.getServletContext();
    servletContext.setAttribute("servletContext", "servletContextValue"); return NONE;
    } }
  2. 可发现使用表单post方式提交,在Struts2框架的Action中获取数据时不会有乱码问题,这时因为Struts2框架有一个常量设置,如下:

    struts.i18n.encoding=UTF-8
  3. 至于若采用表单的get方式提交,你也只能手动解决了。

  4. 重新运行struts2_day02项目,在浏览器的地址栏中输入http://localhost:8080/struts2_day02/form.jsp。

从以上内容可以看出,借助于ServletActionContext类的帮助,开发者也可以在Action中直接访问Servlet API,避免了Action类实现ServletRequestAware、ServletResponseAware、SessionAware和ServletContextAware等XxxAware接口。虽然如此,该Action依然与Servlet API直接耦合,一样不利于程序解耦。综上三种访问Servlet API的方式,建议在开发中优先使用ActionContext,以避免和Servlet API耦合。 
Servlet的API已经可以访问了,那么在页面跳转的时候我们会发现其实Struts2默认使用的都是转发,那如果我们要使用重定向,应该怎么办呢?接下来我们来看下结果页面的配置。

结果页面的配置

在struts.xml文件中,result的配置非常简单,使用<result>元素来配置result逻辑视图与物理视图之间的映射,<result>元素可以有name和type属性,但这两种属性都不是必选的。

  • name属性:指定逻辑视图的名称,默认值为success。
  • type属性:指定返回的视图资源的类型,不同的类型代表不同的结果输出,默认值是dispatcher。

struts.xml文件中的<result>元素配置代码如下所示:

<action name="person" class="cn.itcast.action.result.PersonAction">
<result name="success" type="dispatcher">/a.jsp</result>
</action>

在上述配置中,使用了<result>元素的name、type属性。其中,为Action配置了name为success的result映射,该映射的值可以是JSP页面,也可以是一个Action的name值。用type属性指定了该result的结果类型为dispatcher,它也是默认的结果类型。 
在结果页面的配置中,Struts2有两种配置的方式,一种称之为全局结果页面,一种称之为局部结果页面。全局结果是指在这个包下的所有返回相同字符串的值,都可以向这个页面来进行跳转。局部结果是指在某个Action中返回的字符串的值,会向这个页面跳转。

全局结果页面

全局结果页面是指在同一个包下面配置的Action中返回相同的字符串的值,都可以跳转到该页面。需要通过<global-results>进行配置。 
在src目录下创建一个cn.itcast.action.result包,再在cn.itcast.action.result包中创建两个Action类——PersonAction类和OrdersAction类,执行默认的execute()方法,默认方法都返回success,如下所示:

  • PersonAction.java

    public class PersonAction extends ActionSupport {
    
        @Override
    public String execute() throws Exception {
    return "success";
    } }
  • OrdersAction.java

    public class OrdersAction extends ActionSupport {
    
        @Override
    public String execute() throws Exception {
    return "success";
    } }

然后再在struts.xml文件对以上两个Action类进行配置,如下:

<action name="person" class="cn.itcast.action.result.PersonAction">
<result name="success">/form.jsp</result>
</action>
<action name="orders" class="cn.itcast.action.result.OrdersAction">
<result name="success">/form.jsp</result>
</action>

上面配置好了两个action,两个action都是执行execute()方法,两个action的execute()方法都返回success,返回之后都到form.jsp这个页面中,这样写功能没有问题,但造成有很多重复的配置。所以可使用全局结果页面进行配置,在action标签所在的package标签里面使用global-results进行配置。如下:

<!-- 配置全局结果页面 -->
<global-results>
<result name="success">/form.jsp</result>
</global-results>
<action name="person" class="cn.itcast.action.result.PersonAction">
<!-- <result name="success">/form.jsp</result> -->
</action>
<action name="orders" class="cn.itcast.action.result.OrdersAction">
<!-- <result name="success">/form.jsp</result> -->
</action>
  • 1

局部结果页面

局部结果页面是指在某个Action中根据该字符串的值进行页面的跳转。只对这个Action有效。

<action name="person" class="cn.itcast.action.result.PersonAction">
<result name="success" type="dispatcher">/a.jsp</result>
</action>

在Struts2中,当框架调用Action对请求进行处理后,就要向用户呈现一个结果视图。现在我来举例说明,在WebContent目录下新建一个JSP页面——a.jsp,它主要作为测试用,所以内容很简单:

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>aaaaaaaaaaaaaaaaaaaaaaaa</h1>
</body>
</html>

然后修改struts.xml文件的内容为:

<!-- 配置全局结果页面 -->
<global-results>
<result name="success">/form.jsp</result>
</global-results> <action name="person" class="cn.itcast.action.result.PersonAction">
<result name="success">/a.jsp</result>
</action>
<action name="orders" class="cn.itcast.action.result.OrdersAction">
<!-- <result name="success">/form.jsp</result> -->
</action>

可得出结论:如果配置了全局结果页面,也配置了局部结果页面,那么最终以局部结果页面为准。

result标签的type属性

result标签里面有一个type属性,type属性的作用——因为result标签是配置到不同的路径上去,所以type属性表示配置如何到路径上去(例如重定向或者转发等)。 
在Struts2中,预定义了多种ResultType,其实就是定义了多种展示结果的技术。一个结果类型就是实现了com.opensymphony.xwork2.Result接口的类,Struts2把内置的<result-type>都放在struts-default包中,struts-default包就是配置包的父包,这个包定义在struts2-core-2.3.24.jar包中的根目录下的struts-default.xml文件中,可以找到相关的<result-type>的定义。 
每个<result-type>元素都是一种视图技术或者跳转方式的封装,其中的name属性指出在<result>元素中如何引用这种视图技术或者跳转方式,对应着<result>元素的type属性。Struts2中预定义的ResultType如表所示: 

注意:上面的两个值dispatcher、redirect这两个值表示配置到不同的页面中。其中红色的几个值比较常用,需要重点记忆。其他的了解即可。 
接下来我就来演示type属性的这两个值——dispatcher、redirect。先举例演示type属性的值——dispatcher,表示的是转发操作,type属性默认就是这个值。 
将PersonAction类的代码修改为:

public class PersonAction extends ActionSupport {

    @Override
public String execute() throws Exception {
// 向request域中放入一个值
HttpServletRequest request = ServletActionContext.getRequest();
request.setAttribute("req", "requestValue");
return "success";
} }

然后修改struts.xml文件的内容为:

<global-results>
<result name="success">/form.jsp</result>
</global-results> <action name="person" class="cn.itcast.action.result.PersonAction">
<result name="success" type="dispatcher">/a.jsp</result>
</action>
<action name="orders" class="cn.itcast.action.result.OrdersAction">
<!-- <result name="success">/form.jsp</result> -->
</action>

紧接着将a.jsp页面的内容修改为:

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>request域中的值:${requestScope.req }</h1>
</body>
</html>

这时在浏览器的地址栏中输入http://localhost:8080/struts2_day02/person.action,回车,则会显示如下效果: 

再来举例演示type属性的值——redirect,表示的重定向操作。 
PersonAction类的代码并不需要修改,我们只须修改struts.xml文件的内容为:

<global-results>
<result name="success">/form.jsp</result>
</global-results> <action name="person" class="cn.itcast.action.result.PersonAction">
<result name="success" type="redirect">/a.jsp</result>
</action>
<action name="orders" class="cn.itcast.action.result.OrdersAction">
<!-- <result name="success">/form.jsp</result> -->
</action>

这时在浏览器的地址栏中输入http://localhost:8080/struts2_day02/person.action,回车,则会显示如下效果: 

到这我们已经了解了Struts2的结果页面的配置了,也知道如何接收数据了,但是接收过来的数据,往往需要进行封装才会向业务层进行传递,那么作为一个框架,如果连这点功能都没有,那就太不像是一个“框架”了,那么在Struts2中提供了对于数据封装的几种方式。接下来我们就来学习一下。

Struts2的数据封装

在很多的实际开发中的场景中,页面提交请求参数到Action,在Action中接收参数并且对请求参数需要进行数据的封装。封装到一个JavaBean中,然后将JavaBean传递给业务层。那么这些操作Struts2已经替我们都想好了。Struts2将数据的封装分成两大类,一类被称为是属性驱动,一类被称为是模型驱动。在讲这两种方式之前,我们来使用传统方式封装数据到JavaBean对象中。

使用传统方式封装数据到JavaBean对象

首先在WebContent目录下新建一个JSP页面——formdata.jsp,内容如下:

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="${pageContext.request.contextPath }/data1.action" method="post">
username:<input type="text" name="username" /><br/>
password:<input type="password" name="password" /><br/>
<input type="submit" value="提交" />
</form>
</body>
</html>

然后新建一个cn.itcast.action.data包,在该包中创建一个封装数据的JavaBean——User.java。

public class User {

    private String username;
private String password;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "User [username=" + username + ", password=" + password + "]";
} }

接着再在该包下创建一个Action类——Data1Action.java:

public class Data1Action extends ActionSupport {

    @Override
public String execute() throws Exception {
// 1.获取表单提交的数据
HttpServletRequest request = ServletActionContext.getRequest();
String username = request.getParameter("username");
String password = request.getParameter("password"); // 2.把表单提交的数据封装到实体类里面去
User user = new User();
user.setUsername(username);
user.setPassword(password); System.out.println(user);
return NONE;
} }

最后在struts.xml核心配置文件中配置好该Action,如下:

<action name="data1" class="cn.itcast.action.data.Data1Action"></action>

了解了如何使用传统方式封装数据到JavaBean对象之后,我们来看第一种:属性驱动。

属性驱动

属性驱动可以细分为两种,一种只需要提供属性的set方法即可。另一种可以通过表达式方式直接封装到对象中。 
在Struts2中,可以直接在Action中定义各种Java基本数据类型的字段,使这些字段与表单数据相对应,并利用这些字段进行数据传递。

属性驱动方式一:提供属性的set方法的方式

首先修改formdata.jsp页面的内容为:

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="${pageContext.request.contextPath }/data2.action" method="post">
username:<input type="text" name="username" /><br/>
password:<input type="password" name="password" /><br/>
<input type="submit" value="提交" />
</form>
</body>
</html>

然后再在cn.itcast.action.data包中创建一个Action类——Data2Action.java:

public class Data2Action extends ActionSupport {

    // 1.定义成员变量
private String username;
private String password; // 2.生成set和get方法
public String getUsername() {
return username;
} public void setUsername(String username) {
this.username = username;
} public String getPassword() {
return password;
} public void setPassword(String password) {
this.password = password;
} @Override
public String execute() throws Exception {
System.out.println(username + "..." + password);
return NONE;
} }

注意:在Action类里面定义成员变量时,成员变量的名称要和表单输入项的name属性值一样。 
最后在struts.xml核心配置文件中配置好该Action,如下:

<action name="data2" class="cn.itcast.action.data.Data2Action"></action>

以上这种方式需要通过在Action中定义属性,并且提供属性的set方法来完成。这种方式只需要提供set方法即可。但若需要传入的数据很多的话,那么Action的属性也会变得很多。再加上属性有对应的getter/setter方法,Action类的代码会很庞大,在Action里编写业务的代码时,会使Action非常臃肿,不够简洁。那么要怎样解决这个问题呢? 
把属性和相应的getter/setter方法从Action里提取出来,单独作为一个值对象,这个对象就是用来封装这些数据的,在相应的Action里直接使用这个对象,而且可以在对个Action里使用。采用这种方式,一般以JavaBean来实现,所封装的属性和表单的属性一一对应,JavaBean将成为数据传递的载体。

属性驱动方式二:页面提供表达式方式

首先修改formdata.jsp页面的内容为:

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="${pageContext.request.contextPath }/fieldDemo.action" method="post">
username:<input type="text" name="user.username" />
password:<input type="password" name="user.password" /><br/>
<input type="submit" value="提交" />
</form>
</body>
</html>

然后再在cn.itcast.action.data包中创建一个Action类——FieldDemoAction.java:

public class FieldDemoAction extends ActionSupport {

    // 1.声明实体类的变量
private User user; // 生成user变量的set和get方法
public User getUser() {
return user;
} public void setUser(User user) {
this.user = user;
} @Override
public String execute() throws Exception {
System.out.println(user);
return NONE;
}
}

以上这种方式需要提供对user变量的get方法,如果没有提供get方法,在Struts2的底层就没有办法获得到该对象,那么在user中只会有一个属性被封装进去,而其他的属性都是null。 
值得幸运的是该方式在实际开发中使用的并不是很多!!!

模型驱动

在Struts2中,Action处理请求参数还有另外一种方式,叫做模型驱动(ModelDriven)。通过实现ModelDriven接口来接收请求参数,Action类必须实现ModelDriven接口,并且要重写getModel()方法,这个方法返回的就是Action所使用的数据模型对象。 
模型驱动方式通过JavaBean模型进行数据传递,只要是普通的JavaBean,就可以充当模型部分。采用这种方式,JavaBean所封装的属性与表单的属性一一对应,JavaBean将成为数据传递的载体。 
首先修改formdata.jsp页面的内容为:

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="${pageContext.request.contextPath }/data3.action" method="post">
username:<input type="text" name="username" /><br/>
password:<input type="password" name="password" /><br/>
<input type="submit" value="提交" />
</form>
</body>
</html>

然后再在cn.itcast.action.data包中创建一个Action类——Data3Action.java:

public class Data3Action extends ActionSupport implements ModelDriven<User> {

    // 创建实体类的对象
// 前提条件:表单输入项的name属性值要和实体类里面的属性名称一致
private User user = new User(); // 实现接口的方法
public User getModel() {
// return创建的实体类的对象
return user;
} @Override
public String execute() throws Exception {
System.out.println(user);
return NONE;
} }

注意:使用模型驱动这种方式处理请求参数的前提条件是:表单输入项的name属性值要和实体类里面的属性名称一致。 
最后在struts.xml核心配置文件中配置好该Action,如下:

<action name="data3" class="cn.itcast.action.data.Data3Action"></action>

这里我还要说明一点就是使用属性封装和使用模型驱动封装有什么区别:

  • 使用属性封装,只能把数据封装到action里面的属性中,不能直接把数据封装到对象里面。
  • 使用模型驱动封装,可以直接把表单提交数据封装到实体类对象里面。

注意的一个问题

在一个action中想要获取同一个表单提交的数据,可以使用属性封装,也可以使用模型驱动封装,但是这两种方式不能同时使用。如果同时使用,只会使用到其中的一种,即只会使用模型驱动。示例代码如下:

public class Data3Action extends ActionSupport implements ModelDriven<User> {

    // 创建实体类的对象
// 前提条件:表单输入项的name属性值要和实体类里面的属性名称一致
private User user = new User(); // 实现接口的方法
public User getModel() {
// return创建的实体类的对象
return user;
} // 属性封装
private String username;
private String password; public String getUsername() {
return username;
} public void setUsername(String username) {
this.username = username;
} public String getPassword() {
return password;
} public void setPassword(String password) {
this.password = password;
} @Override
public String execute() throws Exception {
System.out.println(username + "......" + password);
System.out.println(user);
return NONE;
} }

到这里我们已经能够将数据封装到一个Java对象中了,大部分我们会优先使用模型驱动的方式,因为Struts2内部有很多结果是围绕模型驱动设计的。但如果页面向多个对象中封装,那么就需要使用属性驱动的方式二了。这些都是向某个对象中封装数据,那么如果Action中需要一个对象的集合呢?又应该如何进行数据的封装呢?那么接下来我们来了解一下Struts2中复杂类型数据的封装。

Struts2中封装集合类型的数据

在实际的开发中,有些时候我们需要批量插入用户或者批量插入其他对象,在Action中需要接收到这多个Action中封装的对象,然后传递给业务层。那么这个时候就需要将表单的数据封装到集合中。一般我们通常使用的集合无非是List或者Map集合。下面就以这两种集合进行数据的封装的示例演示。

封装到List集合中

在WebContent目录下编写一个JSP页面——list.jsp。

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="${pageContext.request.contextPath }/list.action" method="post">
<!--
List集合的遍历有4种方式,一种最原始的方式就是普通的for循环。
list[0]:List集合中的第一个元素,而List集合中的第一个元素是User对象的形式。
list[0].username:List集合中的第一个User对象里面的username属性。
-->
username:<input type="text" name="list[0].username" />
password:<input type="password" name="list[0].password" /><br/>
username:<input type="text" name="list[1].username" />
password:<input type="password" name="list[1].password" /><br/>
<input type="submit" value="提交" />
</form>
</body>
</html>

然后在cn.itcast.action.data包中创建一个Action类——ListAction.java。

public class ListAction extends ActionSupport {

    // List集合变量
// 在List集合中有多个User对象
private List<User> list = new ArrayList<User>(); // 生成list的set和get方法
public List<User> getList() {
return list;
} public void setList(List<User> list) {
this.list = list;
} @Override
public String execute() throws Exception {
System.out.println(list);
for (int i = 0; i < list.size(); i++) {
// List集合中的第一个元素下标是0
User user = list.get(i);
}
return NONE;
} }

List集合有下标,所以可以通过list[0],list[1]。那么如果是Map集合又应该如何进行封装呢?那么接下来我们就来看如何将数据封装到Map集合中。

封装数据到Map集合中

在WebContent目录下编写一个JSP页面——list.jsp。

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="${pageContext.request.contextPath }/map.action" method="post">
<!--
map['one']:设置map集合的key的值为one,得到value值是User对象
1.设置map集合的key的值为one
2.根据key得到value,value是User对象,然后向User对象里面设置值
-->
username:<input type="text" name="map['one'].username" />
password:<input type="password" name="map['one'].password" /><br/>
username:<input type="text" name="map['abcd'].username" />
password:<input type="password" name="map['abcd'].password" /><br/>
<input type="submit" value="提交" />
</form>
</body>
</html>

然后在cn.itcast.action.data包中创建一个Action类——ListAction.java。

public class MapAction extends ActionSupport {

    // 1.声明一个map变量
/**
* 遍历Map集合的两种方式:
* 1. 得到所有的key,根据key得到value
* 2. 得到key-value之间的关系,使用并不多
*/
private Map<String, User> map = new HashMap<String, User>(); public Map<String, User> getMap() {
return map;
} public void setMap(Map<String, User> map) {
this.map = map;
} @Override
public String execute() throws Exception {
System.out.println(map);
return NONE;
}
}

到这儿,数据已经可以进行封装了。

(转)Struts2访问Servlet的API及......的更多相关文章

  1. 八 Struts2访问Servlet的API方式三:接口注入

    Struts2访问Servlet的API方式三:接口注入 通过实现ServletRequestAware, ServletContextAware 接口,拿到Request.ServletContex ...

  2. 七 Struts2访问Servlet的API方式二:原生方式

    Struts2访问Servlet的API方式二:原生方式 和解耦合的方式不同,原生方式既可以拿到域对象,也可以调用域对象中的方法 前端jsp: <%@ page language="j ...

  3. Struts2(七) Struts2访问Servlet的API

    当接受表单参数,向页面保持数据时.要用到Struts访问Servlet 的API .下面只做参考,有错误或不同意见可以发送邮箱2440867831@qq.com  .建议大家看struts文档,源代码 ...

  4. 六 Struts2访问Servlet的API方式一:完全解耦合的方式

    注意: 完全解耦合的方式,这种方式只能获得代表request.session.application的数据的Map集合. 不能操作这些对象的本身的方法. 1 jsp: <%@ page lang ...

  5. Struts2学习第2天--Struts2的Servlet的API的访问 Struts2的结果页面的配置 Struts2的数据的封装(包括复杂类型)

    启动后访问jsp 输入姓名密码: 提交后跳转打action 打印: 修改类: 配置同上 结果同上. 实现这俩接口 就得到了 以上代码附上: struts.xml: <?xml version=& ...

  6. struts2学习笔记(四)——访问Servlet的API&结果跳转&数据封装

    一.Struts2访问Servlet的API 前面已经对Struts2的流程执行完成了,但是如果表单中有参数如何进行接收?又或者我们需要向页面保存一些数据,又要如何完成呢?我们可以通过学习Struts ...

  7. Struts2访问Servlet

    知识点: servlet是单例的,Action是多例的,一次请求,创建一个Action的实例 结果页面分为全局和局部两类(局部优先级更高) result标签:name : 默认succestype : ...

  8. 配置Struts2及Struts2访问servlet api的方式

    Struts2的起源与背景 在很长的一段时间内,在所有的MVC框架中,Struts1处于绝对的统治地位,无论是从市场的普及范围,还是具体的使用者数量. 其他MVC框架都无 法与其相比,作为一一款优秀的 ...

  9. Struts2访问Servlet API的三种方式

    有时我们需要用到Request, Response, Session,Page, ServletContext这些我们以前常用的对象,那么在Struts2中怎么样使用到这些对象呢,通常有三种方式. * ...

随机推荐

  1. docker run和nsenter

    docker run和nsenter 1,本机运行java -version没有内容, 使用 docker run java java -version就有内容了: 2, docker run -d ...

  2. 3.3-ISDN

    3.3-ISDN     综合业务数字网ISDN(Integrated Services Digital Network):     ISDN主要有两种接口类型:分为BRI(2B+D=2×64+16K ...

  3. [React Native] Prevent the On-screen Keyboard from Covering up Text Inputs

    When you bring up the on screen keyboard in a mobile app, it will cover any text input or buttons on ...

  4. OCX 打包 CAB 与 JS 调用具体教程

        近期在做一个 WEB 项目.须要调用 OCX 进行连接读卡器读卡.本来并不想用 OCX 技术.由于 ActiveX 技术是微软出品.这样就导致整个系统仅仅能使用 IE 浏览器(其它浏览器能够通 ...

  5. js 实现对ajax请求面向对象的封装

             AJAX 是一种用于创建高速动态网页的技术.通过在后台与server进行少量数据交换.AJAX 能够使网页实现异步更新.这意味着能够在不又一次载入整个网页的情况下,对网页的某部分进行 ...

  6. 虚拟机ODPS初体验

    大数据竞赛的第二阶段须要通过远程桌面的方式连接阿里提供的虚拟机, 全部操作都是在远程主机上进行. 在搞清楚文件回传方式之前真是各种麻烦(写博客都没有办法贴代码). 用了两个上午初步上手, 希望接下来进 ...

  7. MICRO SIM卡(SIM小卡)尺寸图及剪卡图解

    如今使用MICRO SIM卡的手机越来越多.近期刚刚买了一个手机到手才发现尼马使用的是MICRO SIM卡.再去买剪卡器吧,十几二十块用一次就废了,去营业厅吧.又比較远,懒的出门.怎么办呢,自己剪!这 ...

  8. 【bzoj1821】[JSOI2010]Group 部落划分 Group

    题目大意:要求把n个点分成m块,使得每一块之间的距离的最小值最大 n^2枚举所有点之间距离 然后sort一下 并查集维护连通关系 一开始e[]开MAXN然后WA了测了4ms,然后开MAXN<&l ...

  9. 又发现2个高人写的Delphi图文并茂的消息研究

    http://ymg97526.blog.163.com/blog/static/173658160201139101120862/http://ymg97526.blog.163.com/blog/ ...

  10. java问题解读,String类为什么是final的

    一.理解final 望文生义,final意为“最终的,最后的”,我理解为“不能被改变的”,它可以修饰类.变量和方法. 所以我是否可以理解为被它所修饰的类.变量和方法都不能被改变呢?答案是”是“,因为有 ...