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的使用。
-
在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
在该页面中,编写了用户名和密码输入框和一个登录提交按钮。
-
在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
-
在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
-
在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实例。
-
将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的属性内容了。
- 重新发布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。
-
将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; } }
-
可发现使用表单post方式提交,在Struts2框架的Action中获取数据时不会有乱码问题,这时因为Struts2框架有一个常量设置,如下:
struts.i18n.encoding=UTF-8
-
至于若采用表单的get方式提交,你也只能手动解决了。
- 重新运行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;
}
}
到这儿,数据已经可以进行封装了。