二.二.三.三 注意事项
1.实现ModelDriven 接口时,T为具体要封装的类型, 封装到user中,为User. 封装到class中为Class.
2.user对象需要实例化,必须自己手动实例化. private User user=new User(); 如果不实例,会空指向异常的.
3.不需要实现对象的setter和getter方法,只需要重写ModelDriven中的getModel()方法即可,返回相应的对象。
4.在前端时,去除封装对象前缀., 因为ModelDriven中只有一个类型,所以知道封装到哪个对象. 在前端jquery动态操作时,也方便使用。
5.表单中的属性值必须与类中的属性值完全保持一致。 开发时,为了简便开发,可以将表单数据与实体类属性完全一致,实体类属性与数据库数据基本一致, 数据库字段值最好为类名第一个字母小写+类中的属性。 表名为t+实体类名。
6.如果前端既传入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 对象中
4.模型驱动并不能像表达式封装那样,明确指明哪一个属性属于哪一个对象。 如果有一个name属性,User 对象有,Teacher 对象也有, ModelDriven对象时,那么这个name即使想表示的是Teacher对象的,也会被封装成user对象的。
5.
ModelDriven对象时,那么这个name即使想表示的是User对象的,也会被封装成 teacher 对象的。
5.模型驱动封装与属性驱动的顺序
当属性驱动与模型驱动同时存在时,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
谢谢您的观看!!!