勿以恶小而为之,勿以善小而不为--------------------------刘备
劝诸君,多行善事积福报,莫作恶
上一章简单介绍了Action的实现方式和struts.xml配置的详细解释,Struts2的简单执行过程(二),如果没有看过,请观看上一章
Struts2是web层框架,主要有两个方面的作用:
1 . 获取前端的客户端输入
2 . 响应后端输出
常常使用到 Servlet API 中相应的方法。
通常有以下三种方式获取 request,response,session,application 对象信息。
1 . Action 通过 ActionContext() 类访问Servlet API
2 . Action 通过实现 XxxAware 接口直接访问 Servlet API
3 . 使用 ServletActionContext 直接访问 Servlet API
所有的Struts2 文章,都已经在web.xml 中添加了StrutsPrepareAndExecuteFilter 过滤器
<!-- 配置struts2的过滤器 -->
<filter>
<filter-name>struts</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
一. 获取Servlet API 对象
一.一 通过 ActionContext() 类访问 Servlet API
一.一.一 ActionContext 类的主要方法
方法 | 作用 |
static ActionContext getContext() | 静态方法, 获取ActionContext 对象实例 |
void put(String key,Object value) | 设置request范围的属性值,类似于request.setAttribute(String key,Object value) |
Object get(Object key) | 获取 request 范围的属性值,类似于 request.getAttribute(String name) |
Map getSession() | 返回Map 对象,模拟了 session对象 |
Map getApplication() | 返回map对象,模拟了application 对象 |
Map getParameters() | 获取所有的请求参数,类似调用 request.getParameterMap() 方法 |
一.一.二 写Demo验证一下
一.一.二.一 编写Action 类 ActionContextDemo
public class ActionContextDemo extends ActionSupport{
private static final long serialVersionUID = 1L;
// 前端传入一个参数 为 name
private String name;
/*
* 通过此方法,展示一下,将数据放置到 request域,session域,application域的用法。
* */
public String showData(){
ActionContext actionContext=ActionContext.getContext();
//获取 application 作用域
Map<String, Object> applicationData=actionContext.getApplication();
//获取application的值
Integer count=(Integer)applicationData.get("count");
if(count==null){
count=1;
}else{
count=count+1;
}
//设置application的值
applicationData.put("count", count);
//获取session 作用域
Map<String,Object> sessionData=actionContext.getSession();
//放置到session域
sessionData.put("loginName",name);
if("两个蝴蝶飞".equals(sessionData.get("loginName"))){
//放置到request域
actionContext.put("msg","第一种方式 :欢迎您,"+sessionData.get("loginName"));
//返回success
return SUCCESS;
}
//放置到request域
actionContext.put("msg","服务器提示:登录失败");
return ERROR;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
一.一.二.二 配置 struts.xml 文件
<package name="hello" extends="struts-default" namespace="/">
<!-- 配置第一种方式 -->
<action name="actionContextDemo" class="com.yjl.web.action.ActionContextDemo"
method="showData">
<result name="success">/WEB-INF/content/success1.jsp</result>
<result name="error">/WEB-INF/content/error.jsp</result>
</action>
</package>
一.一.二.三 编写前端文件
success1.jsp 里面的内容为:
<body>
本站访问次数:${applicationScope.count} <br/>
${sessionScope.loginName},您已经成功登录<br/>
${requestScope.msg}<br/>
</body>
error.jsp 里面的内容为:
<body>
${requestScope.msg}<br/>
</body>
一.一.二.四 重启服务器,进行验证
当输入网址为: http://localhost:8080/Struts_API/actionContextDemo 时,没有name值,提示登录失败
当输入网址为: http://localhost:8080/Struts_API/actionContextDemo?name=两个蝴蝶飞,name正确,提示登录成功
当输入网址为: http://localhost:8080/Struts_API/actionContextDemo?name=老蝴蝶,name值错误,提示登录失败
可以正常的传输数据。
这种方式,只能往request,session和applicaiton中进行存数据,取数据,只能对数据进行维护,不能像真正的request,response对象提供的那些方法一样强大。 如获取客户端ip,添加cookie 等, 用这种方法就无法实现了。
一.二 通过实现XxxAware 接口实现Servlet API 对象
Struts2针对Servlet 的API 对象,提供了三种接口, HttpServletRequestAware 接口,HttpServletResponseAware接口, ServletContextAware 接口。 其中,session对象可以通过request对象进行获取,所以就没有提供关于session的接口。
一.二.一 XxxAware 接口提供的方法
ServletRequestAware 接口提供了一个 setServletRequest() 方法,用于获取request对象
public abstract interface ServletRequestAware
{
public abstract void setServletRequest(HttpServletRequest paramHttpServletRequest);
}
ServletResponseAware 接口提供了一个 setServletResponse() 方法,用于获取response对象
public abstract interface ServletResponseAware
{
public abstract void setServletResponse(HttpServletResponse paramHttpServletResponse);
}
ServletContextAware 接口提供了一个 setServletContext()方法,用于获取application对象
public abstract interface ServletContextAware
{
public abstract void setServletContext(ServletContext paramServletContext);
}
一.二.二 写Demo验证一下
一.二.二.一 编写Action 类 AwareDemo
public class AwareDemo extends ActionSupport
implements ServletRequestAware,ServletResponseAware,ServletContextAware{
private static final long serialVersionUID = 1L;
private String name;
//接收 application
private ServletContext application;
//接收request
private HttpServletRequest request;
//接收response
private HttpServletResponse response;
//session可以通过 request 进行获取
private HttpSession session;
@Override
public void setServletContext(ServletContext application) {
this.application=application;
}
@Override
public void setServletResponse(HttpServletResponse response) {
this.response=response;
}
@Override
public void setServletRequest(HttpServletRequest request) {
this.request=request;
this.session=request.getSession();
}
public String showData(){
//获取application的值
Integer count=(Integer)application.getAttribute("count");
if(count==null){
count=1;
}else{
count=count+1;
}
//设置application的值
application.setAttribute("count",count);
//放置到session域
session.setAttribute("loginName",name);
if("两个蝴蝶飞".equals(session.getAttribute("loginName"))){
//放置到request域
request.setAttribute("msg","第二种方式:欢迎您,"+session.getAttribute("loginName"));
//展示ip 地址
request.setAttribute("ip",request.getLocalAddr());
//通过response 对象,设置cookie
Cookie cookie=null;
try {
cookie = new Cookie("userName",
URLEncoder.encode(session.getAttribute("loginName").toString(),"UTF-8"));
} catch (UnsupportedEncodingException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
cookie.setMaxAge(60*60);
cookie.setPath("/");
response.addCookie(cookie);
//返回success
return SUCCESS;
}
//放置到request域
request.setAttribute("msg","服务器提示:登录失败");
return ERROR;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
里面多提供了 request获取客户端ip和 response添加 cookie的操作
一.二.二.二 配置struts.xml 文件
<!-- 配置第二种方式 -->
<action name="awareDemo" class="com.yjl.web.action.AwareDemo"
method="showData">
<result name="success">/WEB-INF/content/success2.jsp</result>
<result name="error">/WEB-INF/content/error.jsp</result>
</action>
一.二.二.三 编写前端界面
success2.jsp, 内容主要是:
<!--引入jquery文件,网络版的 -->
<script src="http://code.jquery.com/jquery-latest.js"></script>
<body>
本站访问次数:${applicationScope.count} <br/>
${sessionScope.loginName},您已经成功登录<br/>
${requestScope.msg}<br/>
ip:${requestScope.ip}<br/>
cookie值:<span id="cookieValue"></span>
<script>
$(function(){
var username = decodeURIComponent("${cookie.userName.value}");//如果为空,使用解码后为空字符串
if(!username.length==0){
$("#cookieValue").text(username);
}
})
</script>
</body>
一.二.二.四 重启服务器,进行验证
输入网址: http://localhost:8080/Struts_API/awareDemo?name=两个蝴蝶飞
ip地址和cookie 均可以正常获取。
用js 脚本,解决了 cookie 中文乱码的问题。
这种方式,还需要实现接口,重写里面的方法,如果需要同时获取request,response,application对象,那么需要实现三个接口,太复杂。
一.三 使用 ServletActionContext 工具类获取ServletAPI
一.三.一 ServletActionContext 提供方法
方法名 | 作用 |
static HttpServletRequest getRequest() | 取得request对象 |
static HttpServletResponse getResponse() | 取得response 对象 |
static ServletContext getServletContext() | 取得application 对象 |
session依旧是通过 request 进行获取的。
一.三.二 编写Demo 验证一下
一.三.二.一 编写Action 类 ServletActionContextDemo
public class ServletActionContextDemo extends ActionSupport{
private static final long serialVersionUID = 1L;
private String name;
public String showData(){
//获取application对象
ServletContext application=ServletActionContext.getServletContext();
//获取request对象
HttpServletRequest request=ServletActionContext.getRequest();
//获取response对象
HttpServletResponse response=ServletActionContext.getResponse();
//获取session对象
HttpSession session=request.getSession();
//获取application的值
Integer count=(Integer)application.getAttribute("count");
if(count==null){
count=1;
}else{
count=count+1;
}
//设置application的值
application.setAttribute("count",count);
//放置到session域
session.setAttribute("loginName",name);
if("两个蝴蝶飞".equals(session.getAttribute("loginName"))){
//放置到request域
request.setAttribute("msg","第三种方式:欢迎您,"+session.getAttribute("loginName"));
//展示ip 地址
request.setAttribute("ip",request.getLocalAddr());
//通过response 对象,设置cookie
Cookie cookie=null;
try {
cookie = new Cookie("userName",
URLEncoder.encode(session.getAttribute("loginName").toString(),"UTF-8"));
} catch (UnsupportedEncodingException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
cookie.setMaxAge(60*60);
cookie.setPath("/");
response.addCookie(cookie);
//返回success
return SUCCESS;
}
//放置到request域
request.setAttribute("msg","服务器提示:登录失败");
return ERROR;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
一.三.二.二 配置struts.xml 文件
<!-- 配置第三种方式 -->
<action name="servletDemo" class="com.yjl.web.action.ServletActionContextDemo"
method="showData">
<result name="success">/WEB-INF/content/success2.jsp</result>
<result name="error">/WEB-INF/content/error.jsp</result>
</action>
一.三.二.三 编写 jsp文件
用的是上面的 success2.jsp 文件,不需要重复编写。
一.三.二.四 重启服务器,进行验证
输入网址: http://localhost:8080/Struts_API/servletDemo?name=两个蝴蝶飞
通过 ServletActionContext 工具类,获取request,response,session,application 对象,比较好,一般采用这种方式。
但是不通过这种方式来获取前端传递过来的数据,获取数据,struts2框架提供了更简单的方式。
二. 获取前端数据
二.一. 通过原始的 request 对象进行获取数据
二.一.一 编写Action
public class RequestData extends ActionSupport{
private static final long serialVersionUID = -477463776005071632L;
Logger logger=Logger.getLogger(RequestData.class);
public String getData() {
//有一个ServletActionContext对象来获取底层的HttpServletRequest
HttpServletRequest request=ServletActionContext.getRequest();
//如果获取的是单个数据,如text框,password,hidden,radio性别框,select单选框等。
String userName=request.getParameter("userName");
//如果获取的是checkbox,select多选框.
String []hobbys=request.getParameterValues("hobbys");
logger.info("姓名是:"+userName);
if(hobbys!=null) {
for (String hobby : hobbys) {
logger.info("爱好有:"+hobby);
}
}
return NONE;
}
}
二.一.二 配置struts.xml
<!-- 通过获取request来获取前端数据 -->
<action name="requestData" class="com.yjl.web.action.RequestData"
method="getData">
</action>
<!-- 配置跳转页面,要把它放置到最后 -->
<action name="*">
<result>/WEB-INF/content/{1}.jsp</result>
</action>
二.一.三 编写前端界面
要配置跳转页面的 action
在 /content 文件夹下,创建一个 request.jsp 页面
<body>
<form action="requestData" method="post">
用户名:<input type="text" name="userName"><br/>
爱好: <input type="checkbox" name="hobbys" value="读书"> 读书
<input type="checkbox" name="hobbys" value="编程"> 编程
<input type="checkbox" name="hobbys" value="写小说">写小说<br/>
<input type="submit" value="提交">
</form>
</body>
二.一.四 重启服务器,进行验证
输入网址: http://localhost:8080/Struts_API/request , 会跳转到 /WEB-INF/content/request.jsp 页面,
名称填写 两个蝴蝶飞,爱好是编程和写小说
前端正常跳转,后端控制台打印输出:
ServletActionContext类可以直接获取request对象,response对象,application 对象,可以通过request.getSession()来获取session对象,
但是这种方式获取数据与Servlet产生了高度耦合,若非一些特殊数据需求,如客户端的ip地址,端口号等,不建议使用这种方式。而是采用 struts2框架提供的方式,来获取数据。
下面的例子,都可以正常访问,就不一 一 贴运行效果图了。struts.xml 的配置也很简单,也不一个一 个贴配置文件了。
二.二 通过 Struts2 框架提供的方式进行获取数据
二.二.一 Struts2获取单个普通的单值,如字符串和Integer 值
二.二.一.一 Demo展示
public class SimpleData extends ActionSupport{
private static final long serialVersionUID = -477463776005071632L;
Logger logger=Logger.getLogger(SimpleData.class);
//name为单个值
private String name;
public void setName(String name) {
this.name=name;
}
//多个值,用数组或者是List集合
private String []hobbys;
public void setHobbys(String[] hobbys) {
this.hobbys = hobbys;
}
public String single() {
logger.info("获取的姓名为:"+name);
if(hobbys!=null) {
for (String hobby : hobbys) {
logger.info("爱好有:"+hobby);
}
}
return NONE;
}
}
前端页面为:
<form action="simpleData" method="post">
用户名:<input type="text" name="name"><br/>
爱好: <input type="checkbox" name="hobbys" value="读书"> 读书
<input type="checkbox" name="hobbys" value="编程"> 编程
<input type="checkbox" name="hobbys" value="写小说">写小说<br/>
<input type="submit" value="提交">
</form>
二.二.一.二 注意事项
其中前端的表单的name值要与Action中属性的值相同,并且还需要在Action中实现相应的setter方法,只有这样,才可以进行封装数据。
如果是单个值,用普通的基本类型进行封装(Struts2自动处理了包装类,所以建议用包装类进行接收。String–>String,int—>Integer. 这样当输入年龄的数字时,可以直接将age转换成数字了。不用Integer.parseInt(age)进行转换了)
如果是多个值,如多选框和多选的select框,那么需要用数组 String []hobbys或者 集合 List []hobbys进行相应的接收。
通过这种setter() 方法的封装,叫做属性驱动。
当前端属性数目小时,可以通过这种方式进行封装, 当属性数目过多时,如员工档案数据,有name,age,email,phone 等大量数据时,就不建议用这种方式了。
二.二.二 表达式封装Bean实体类对象
在一个表单里面,如果表单的元素值过多,如一个注册页面,要传递很多的属性数据,如果都写成setter方法,对每一个属性,单独进行封装,那么在Action中会有很多setter() 方法,导致Action 类 会很麻烦。我们希望Struts2可以直接将表单数据封装成Java Bean对象。
二.二.二.一 Demo 展示
先新建一个User.java对象,里面封装一些基本的属性
/**
* @param id 主键编号
* @param name 姓名
* @param sex 性别
* @param age 年龄
* @param relation 关系
*/
private Integer id;
private String name;
private String sex;
private Integer age;
private String relation;
//重写toString()方法,方便查看
@Override
public String toString() {
return "User [id=" + id + ", name=" + name + ", sex=" + sex + ", age=" + age + ", relation=" + relation + "]";
}
...
封装相应的setter 和 getter 方法。
...
在User.java 里面,提供封装setter和getter方法,重写toString()方法
新建UserAction类, 在里面封装User user 的属性,实现setter方法
/**
* @description 处理多个数据提交封装Java Bean的类
*/
public class UserAction extends ActionSupport{
private static final long serialVersionUID = 5018178953781239408L;
private Logger logger=Logger.getLogger(UserAction.class);
private User user;
public void setUser(User user) {
this.user = user;
}
public User getUser() {
return user;
}
public String setData() {
logger.info("获取信息:"+user.toString());
return NONE;
}
}
前端form表单 /content/user.jsp
<body>
<form action="Request_setData" method="post">
姓名:<input type="text" name="user.name"><br/>
性别:<input type="radio" name="user.sex" value="男">男
<input type="radio" name="user.sex" value="女">女<br/>
年龄:<input type="text" name="user.age"><br/>
关系: <select name="user.relation">
<option>父子</option>
<option>母子</option>
<option>姐弟</option>
<option>妻弟</option>
</select>
<br/>
<input type="submit" value="提交">
</form>
</body>
运行Tomcat服务器,填写基本的数据后,控制台可以正常的打印前端输入的数据。
二.二.二.二 注意事项
- 实体类中属性值要与前端表单中的值相同(去除user.后),
- UserAction中user 只是private User user,并没有将其实例化成private User user=new User(), Struts2会自动将其实例化。
- input框中name=“对象.属性”, 这个对象指的是要将数据封装到哪个实体类对象。如果是private User a; 那么这个时候就是name=“a.name”
- 在Action中,必须要实现user的setter和getter()方法,只单独实现setter方法是不行的。
- 如果在Action中有 user 类和 teacher类,其中 user中有name属性,teacher 类也有name属性,那么 用 user.name 表达员工的姓名,teacher.name 表示教师的名称, 可以很方便的进行区分。
二.二.三 模型驱动封装 Java Bean对象。
需要Action 实现ModelDriven接口
二.二.三.一 ModelDriven 接口定义
public interface ModelDriven<T> {
T getModel();
}
需要重写里面的 getModel() 方法。
二.二.三.二 Action实现
/
* @description 处理多个数据提交封装Java Bean的类
*/
public class UserAction2 extends ActionSupport
implements ModelDriven<User>{
private static final long serialVersionUID = 5018178953781239408L;
private Logger logger=Logger.getLogger(UserAction.class);
// 需要直接实例化,不然会返回NPE 异常
private User user=new User();
@Override
public User getModel() {
return user;
}
public String setData() {
logger.info("获取信息:"+user.toString());
return NONE;
}
}
前端时,/conent/user2.jsp
<form action="User2_setData" method="post">
姓名:<input type="text" name="name"><br/>
性别:<input type="radio" name="sex" value="男">男
<input type="radio" name="sex" value="女">女<br/>
年龄:<input type="text" name="age"><br/>
关系: <select name="relation">
<option>父子</option>
<option>母子</option>
<option>姐弟</option>
<option>妻弟</option>
</select>
<br/>
<input type="submit" value="提交">
</form>
重启服务器,输入数据,可以正常的接收到数据。
二.二.三.三 注意事项
- 实现ModelDriven 接口时,T为具体要封装的类型, 封装到user中,为User. 封装到class中为Class.
- user对象需要实例化,必须自己手动实例化. private User user=new User(); 如果不实例,会空指向异常的.
- 不需要实现对象的setter和getter方法,只需要重写ModelDriven中的getModel()方法即可,返回相应的对象。
- 在前端时,去除封装对象前缀., 因为ModelDriven中只有一个类型,所以知道封装到哪个对象. 在前端jquery动态操作时,也方便使用。
- 表单中的属性值必须与类中的属性值完全保持一致。 开发时,为了简便开发,可以将表单数据与实体类属性完全一致,实体类属性与数据库数据基本一致, 数据库字段值最好为类名第一个字母小写+类中的属性。 表名为t+实体类名。
- 如果前端既传入user的name,也传入teacher的name, 那么将无法区分name的值。 故同一个表单中元素的name值必须保证唯一。
二.二.四 三种数据封装方式的比较
上面就是Struts2提供的三种数据封装的方式,
- setter和getter方法封装属性的属性驱动
- 对象.属性名的表达式封装方式
- 实现ModelDriven接口的模型驱动方式。
二.二.四.一 三种方式的区别与联系
- 表达式封装和模型驱动封装,都可以直接封装成Java Bean实体类对象,表达式封装时前端需要对象.属性,要有对象的前缀.,模型驱动不需要。
- 表达式封装,不需要将对象实例化,而模型驱动却必须将封装的对象显式实例化,否则会出现空指向异常。
- 表达式可以封装多个对象中相同的属性值
private User user;
private Teacher teacher;
//user和teacher的setter和getter方法
在前端时, user.name, user.age 表示封装到 user对象中
teacher.name, teacher.age ,表示封装到teacher 对象中
- 模型驱动并不能像表达式封装那样,明确指明哪一个属性属于哪一个对象。 如果有一个name属性,User 对象有,Teacher 对象也有, ModelDriven对象时,那么这个name即使想表示的是Teacher对象的,也会被封装成user对象的。
ModelDriven对象时,那么这个name即使想表示的是User对象的,也会被封装成 teacher 对象的。
- 模型驱动封装与属性驱动的顺序
当属性驱动与模型驱动同时存在时,name在User对象中, 进行了模型驱动封装,并且还实现了name的setter和getter方法,那么这个时候:
private User user=new User();
@Override
public User getModel() {
return user;
}
private String name;
public void setName(String name) {
this.name = name;
}
public String setData() {
//为null
logger.info("属性驱动:"+name);
//获取前端传入的值
logger.info("模型驱动:"+user.getName());
return NONE;
}
模型驱动能够取到值。
二.二.五 提供Action公共代码,创建 BaseAction
在开发中,最常用的是模型驱动,因为这样方便一些。 但每一个类都是继承ActionSupport,实现ModelDriven 接口,太麻烦,一般会用一个BaseAction类来实现。
放置在 com.yjl.utils 包下。
BaseAction.java
package com.yjl.utils;
import java.lang.reflect.ParameterizedType;
import org.apache.log4j.Logger;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
/**
* @author 两个蝴蝶飞
* @version 创建时间:2018年8月23日 下午4:40:13
* @description BaseAction的工具类
*/
@SuppressWarnings(value= {"rawtypes","unchecked"})
public class BaseAction<T> extends ActionSupport implements ModelDriven<T>{
private static final long serialVersionUID = -7180401147510521582L;
private Logger logger=Logger.getLogger(BaseAction.class);
private T t;
private Class clazz;
public BaseAction() {
//得到当前的类
Class class1=this.getClass();
//得到运行中的父类
ParameterizedType parameterizedType=(ParameterizedType) class1.getGenericSuperclass();
clazz=(Class) parameterizedType.getActualTypeArguments()[0];
try {
t=(T) clazz.newInstance();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
logger.info("当前类的类:"+clazz.getName()+"完成初始化");
}
@Override
public T getModel() {
return t;
}
}
然后UserAction类只需要继承BaseAction类即可
public class UserAction extends BaseAction<User>{
//取user对象时,用 super.getModel()
}
TeacherAction 类只需要继承BaseAction 类即可
public class TeacherAction extends BaseAction<Teacher>{
//取teacher对象时,用 super.getModel()
}
这样就可以了。
二.二.六 属性驱动封装List 集合
封装list集合,可以批量添加对象时使用,批量修改对象时使用。
/
* @description 处理多个对象数据提交封装List集合
*/
public class UserAction6 extends ActionSupport{
private static final long serialVersionUID = 5018178953781239408L;
private Logger logger=Logger.getLogger(UserAction.class);
private List<User> userList;
public List<User> getUserList() {
return userList;
}
public void setUserList(List<User> userList) {
this.userList = userList;
}
public String setData() {
if(userList!=null) {
for (User user : userList) {
logger.info(user.toString());
}
}
return NONE;
}
}
其中前端表示为: /content/user6.jsp
<form action="User6_setData" method="post">
姓名:<input type="text" name="userList[0].name"><br/>
性别:<input type="radio" name="userList[0].sex" value="男">男
<input type="radio" name="userList[0].sex" value="女">女<br/>
年龄:<input type="text" name="userList[0].age"><br/>
关系: <select name="userList[0].relation">
<option>父子</option>
<option>母子</option>
<option>姐弟</option>
<option>妻弟</option>
</select>
<br/>
<hr/>
姓名:<input type="text" name="userList[1].name"><br/>
性别:<input type="radio" name="userList[1].sex" value="男">男
<input type="radio" name="userList[1].sex" value="女">女<br/>
年龄:<input type="text" name="userList[1].age"><br/>
关系: <select name="userList[1].relation">
<option>父子</option>
<option>母子</option>
<option>姐弟</option>
<option>妻弟</option>
</select>
<br/>
<input type="submit" value="提交">
</form>
list数据提交时, name=list属性名[下标].属性值。
二.二.七 属性驱动封装Map 集合
UserAction7.java 封装
/**
* @description 处理多个对象数据提交封装Map
*/
public class UserAction7 extends ActionSupport{
private static final long serialVersionUID = 5018178953781239408L;
private Logger logger=Logger.getLogger(UserAction.class);
private Map<String,User> maps;
public Map<String, User> getMaps() {
return maps;
}
public void setMaps(Map<String, User> maps) {
this.maps = maps;
}
public String setData() {
if(maps!=null) {
/*
* 第一种遍历Map的方式 用keySet遍历
* Set<String> sets=maps.keySet();
Iterator <String> iterator=sets.iterator();
while(iterator.hasNext()) {
String key=iterator.next();
User value=maps.get(key);
logger.info(key+"------>"+value.toString());
}*/
//用第二种方式 entrySet
Set<Entry<String,User>> sets=maps.entrySet();
for (Entry<String, User> entry : sets) {
String key=entry.getKey();
User value=entry.getValue();
logger.info(key+"------>"+value.toString());
}
}
return NONE;
}
}
前端时: /content/user7.jsp
<form action="User7_setData" method="post">
姓名:<input type="text" name="maps['one'].name"><br/>
性别:<input type="radio" name="maps['one'].sex" value="男">男
<input type="radio" name="maps['one'].sex" value="女">女<br/>
年龄:<input type="text" name="maps['one'].age"><br/>
关系: <select name="maps['one'].relation">
<option>父子</option>
<option>母子</option>
<option>姐弟</option>
<option>妻弟</option>
</select>
<br/>
<hr/>
姓名:<input type="text" name="maps['two'].name"><br/>
性别:<input type="radio" name="maps['two'].sex" value="男">男
<input type="radio" name="maps['two'].sex" value="女">女<br/>
年龄:<input type="text" name="maps['two'].age"><br/>
关系: <select name="maps['two'].relation">
<option>父子</option>
<option>母子</option>
<option>姐弟</option>
<option>妻弟</option>
</select>
<br/>
<input type="submit" value="提交">
</form>
运行输入数据:
二.二.八 属性封装到Set中
基本没有使用,简单写一下
UserAction8.java
@KeyProperty("id")
private Set<User> userSet=new HashSet<User>();
public Set<User> getUserSet() {
return userSet;
}
public void setUserSet(Set<User> userSet) {
this.userSet = userSet;
}
public String setData() {
if(userSet!=null) {
System.out.println("不为空"+userSet.size());
for (User user : userSet) {
System.out.println(user.toString());
}
}else {
System.out.println("为空");
}
return NONE;
}
jsp页面: /content/user8.jsp
<form action="Request_setData" method="post">
姓名:<input name="userSet.makeNew[0].name" type="text"/><br/>
姓名:<input name="userSet.makeNew[1].name" type="text"/><br/>
<input type="submit" value="提交"/>
</form>
set集合比较特殊,没有顺序,所以不能用[0][1] 下标的方式进行,需要用 set名称.makeNew[下标].属性
并且Action中set需要添加一个注解 @keyProperty(“id”) 其中id为User类的唯一标识。(建议重写User 类的hashCode和equals()方法)
数据封装所配置的struts.xml 文件为:
<!-- 通过获取request来获取前端数据 -->
<action name="requestData" class="com.yjl.web.action.RequestData"
method="getData">
</action>
<!-- 通过setter 方法封装单值 -->
<action name="simpleData" class="com.yjl.web.action.SimpleData"
method="single">
</action>
<!-- 通过表达式封装java bean 对象 -->
<action name="User_setData" class="com.yjl.web.action.UserAction"
method="setData">
</action>
<!-- 通过模型驱动封装java bean 对象 -->
<action name="User2_setData" class="com.yjl.web.action.UserAction2"
method="setData">
</action>
<!-- 属性驱动封装List 集合 -->
<action name="User6_setData" class="com.yjl.web.action.UserAction6"
method="setData">
</action>
<!-- 属性驱动封装Map 集合 -->
<action name="User7_setData" class="com.yjl.web.action.UserAction7"
method="setData">
</action>
<!-- 属性驱动封装Set 集合 -->
<action name="User8_setData" class="com.yjl.web.action.UserAction8"
method="setData">
</action>
本章节代码链接为:
链接:https://pan.baidu.com/s/1RK1RlGqoKKm51kruKJ5cqg
提取码:l5d5
下一章简单介绍了两个小例子登录和显示全部用户信息的模块(四)
谢谢您的观看!!!