什么叫框架的数据封装?
就是将原本需要使用Servlet的Api手动去解析请求参数,然后封装成model的操作交给了Struts2框架来完成。Struts2的框架采用了拦截器来完成数据的封装。
两类数据封装的方式
1.属性驱动方式
提供对应属性的set方法进行数据的封装。
表单的哪些属性需要封装数据,那么在对应的Action类中提供该属性的set方法即可。
表单中的数据提交,最终找到Action类中的setXxx的方法,最后赋值给全局变量。
例如:
package blog.csdn.net.mchenys;
import com.opensymphony.xwork2.ActionSupport;
/**
* 属性驱动
*
* @author mChenys
*/
public class Regist1Action extends ActionSupport {
private static final long serialVersionUID = -966487869258031548L;
//定义属性,名称需要保持和jsp页面的表单name属性名一直
private String username;
private String password;
private Integer age;
//提供set方法
public void setUsername(String username) {
this.username = username;
}
public void setPassword(String password) {
this.password = password;
}
public void setAge(Integer age) {
this.age = age;
}
public String execute() throws Exception {
//直接使用预定义的属性
System.out.println(username + " " + password + " " + age);
return NONE;
}
}
jsp页面
<form action="${ pageContext.request.contextPath }/regist1.action"
method="post">
姓名:<input type="text" name="username" /><br />
密码:<input type="password" name="password" /><br />
年龄:<input type="text" name="age" /><br />
<input type="submit" value="注册" />
</form>
action的配置
<action name="regist1" class="blog.youkuaiyun.com.mchenys.Regist1Action"/>
注意:
属性驱动这种方式不是特别好,因为属性特别多,就要提供特别多的set方法,而且还需要手动将数据存入到对象中。
这种情况下,Action类就相当于一个JavaBean,就没有体现出MVC的思想,Action类又封装数据,又接收请求处理,耦合性较高。
属性驱动还有另一种方式:
在页面中使用OGNL表达式进行数据的封装,就可以直接把属性封装到某一个JavaBean的对象中。
另外需要在Action类中定义一个JavaBean,并且提供get/set方法;
然后页面中的表单name属性值需要使用OGNL的方式,表单中的写法:<input type="text" name="user.username">
其中点(.)前面的user对应的是Action类中声明的javabean的名称,而username则对应该javabean中的属性名
例如:
package blog.csdn.net.mchenys;
import com.opensymphony.xwork2.ActionSupport;
import blog.csdn.net.mchenys.domain.User;
/**
* 属性驱动方式,把数据封装到JavaBean的对象中
*
* @author mChenys
*/
public class Regist2Action extends ActionSupport {
private static final long serialVersionUID = 6556880331550390473L;
// 声明javabean对象,也可以同时初始化好
private User user;
// 注意:通过javabean的这种方式,需要提供get和set方法
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public String execute() throws Exception {
System.out.println(user);
return NONE;
}
}
javabean编写
public class User {
private String username;
private String password;
private Integer age;
//get/set方法...
}
然后修改表单的name属性如下:
<form action="${ pageContext.request.contextPath }/regist2.action"
method="post">
姓名:<input type="text" name="user.username" /><br />
密码:<input type="password" name="user.password" /><br />
年龄:<input type="text" name="user.age" /><br />
<input type="submit" value="注册" />
</form>
注意:
Action类中什么的javabean对象必须要提供get和set方法,如果已经手动实例化了该javabean对象,那么set方法可以不用写.
2.模型驱动方式
使用模型驱动的方式,也可以把表单中的数据直接封装到一个JavaBean的对象中,并且表单的写法和之前的写法没有区别!
编写的页面不需要任何变化,正常编写name属性的值, 模型驱动的编写步骤:
- Action类需手动实例化JavaBean,即:private User user = new User();
- Action类必须实现
ModelDriven<T>
接口,并实现getModel()的方法,然后在getModel()方法中返回user即可.
例如:
package blog.csdn.net.mchenys;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
import blog.csdn.net.mchenys.domain.User;
/**
* 模型驱动的方式
*
* @author mChenys
*
*/
public class Regist3Action extends ActionSupport implements ModelDriven<User> {
private static final long serialVersionUID = 6556880331550390473L;
// 必须声明和实例化javabean对象
private User user = new User();
// 必须实现该方法
public User getModel() {
return user;
}
public String execute() throws Exception {
System.out.println(user);
return NONE;
}
}
ok,jsp页面不需要额外处理,只需要保持name属性=javabean的属性名即可,然后配置下action就可以了.
如何把数据封装到集合中
Struts2还可以实现将数据封装到集合中(集合类型 Collection 、Map接口等),这个就需要修改jsp页面的name属性了,
1.对于list集合的处理:
在Action中的写法,需要提供products的集合,并且提供get和set方法。例如:
package blog.csdn.net.mchenys;
import java.util.List;
import com.opensymphony.xwork2.ActionSupport;
import blog.csdn.net.mchenys.domain.User;
/**
* 把数据封装到List集合中
*
* @author mChenys
*
*/
public class Regist4Action extends ActionSupport {
private static final long serialVersionUID = 6556880331550390473L;
//声明javabean集合
private List<User> list;
//提供get/set方法
public List<User> getList() {
return list;
}
public void setList(List<User> list) {
this.list = list;
}
public String execute() throws Exception {
for (User user : list) {
System.out.println(user);
}
return NONE;
}
}
因为Collection接口都会有下标值,页面的写法例如<input type="text" name="list[0].username" />
,其中list代表的是Action类中声明的list集合,[0]表示list集合的第一个位置,而username表示的是javabean中的属性名。jsp页面如下:
<form action="${ pageContext.request.contextPath }/regist4.action" method="post">
姓名:<input type="text" name="list[0].username" /><br/>
密码:<input type="password" name="list[0].password" /><br/>
年龄:<input type="password" name="list[0].age" /><br/>
姓名:<input type="text" name="list[1].username" /><br/>
密码:<input type="password" name="list[1].password" /><br/>
年龄:<input type="password" name="list[1].age" /><br/>
<input type="submit" value="注册" />
</form>
2.对于Map的处理:
Action中提供map集合,并且提供get和set方法,例如:
package blog.csdn.net.mchenys;
import java.util.Map;
import com.opensymphony.xwork2.ActionSupport;
import blog.csdn.net.mchenys.domain.User;
/**
* 把数据封装到Map集合中
*
* @author mChenys
*
*/
public class Regist5Action extends ActionSupport {
private static final long serialVersionUID = 6556880331550390473L;
// 声明map集合
private Map<String, User> map;
// 提供get/set方法
public Map<String, User> getMap() {
return map;
}
public void setMap(Map<String, User> map) {
this.map = map;
}
public String execute() throws Exception {
System.out.println(map);
return NONE;
}
}
Map集合是键值对的形式,页面的写法例如<input type="text" name="map['one'].username" />
,其中map表示Action类中声明的map集合,one代表map集合的key而username代表javabean的属性名称。jsp页面如下:
<form action="${ pageContext.request.contextPath }/regist5.action" method="post">
姓名:<input type="text" name="map['one'].username" /><br/>
密码:<input type="password" name="map['one'].password" /><br/>
年龄:<input type="password" name="map['one'].age" /><br/>
姓名:<input type="text" name="map['two'].username" /><br/>
密码:<input type="password" name="map['two'].password" /><br/>
年龄:<input type="password" name="map['two'].age" /><br/>
<input type="submit" value="注册" />
</form>