Struts2数据封装
Struts2提供了一些基于拦截器的数据封装方式,一共有四种,分为静态参数封装和动态属性封装,动态属性封装又可分为属性驱动和模型驱动,属性驱动又可分为基本属性驱动和对象图导航语言(OGNL,Object Graph Navigation Language)驱动。
思维导图
在Action文件中
静态参数封装
在struts.xml文件中配置
<action name="testAction" class="com.pc.demo.web.action.TestAction" method="testAction">
<result name="success">/success.jsp</result>
<param name="username">Switch</param>
<param name="password">123456</param>
</action>
在Action文件中
package com.pc.demo.web.action;
import com.opensymphony.xwork2.ActionSupport;
/**
* 静态参数封装
* @author Switch
*
* 是由一个名称为staticParams的拦截器为我们封装的
*/
public class Demo1Action extends ActionSupport {
private String name;
private Integer age;
public String testAction(){
System.out.println("name is "+name+" and age is "+age);
return SUCCESS;
}
public String getUserName() {
return name;
}
public void setUserName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
PS:注意封装参数都是按照get/set方法的名字,按名匹配的,不是按字段的名字进行匹配。
其底层是通过一个名叫staticParams的拦截器进行拦截的。
默认拦截器有如下这么多个,可以在Struts2核心包下的struts-default.xml文件中找到
动态参数封装
属性驱动封装
基本属性驱动
基本属性封装是通过请求参数的名称,按照get/set方法的方式进行封装的。
JSP页面
<%--动态属性封装:属性驱动之基本属性 --%>
<form action="${pageContext.request.contextPath}/testAction2.action" method="post">
用户名:<input type="text" name="name"/><br/>
年龄:<input type="text" name="age"/><br/>
<input type="submit" value="提交"/>
</form>
在struts.xml文件中配置
<action name="testAction2" class="com.pc.demo.web.action.TestAction2" method="testAction">
<result name="success">/success.jsp</result>
</action>
在Action文件中
package com.pc.demo.web.action;
import com.opensymphony.xwork2.ActionSupport;
/**
* 动态属性封装:属性驱动
* 基本属性封装
* 要想封装成功的要求:
* 表单元素的name属性取值必须和动作类中私有属性的get/set该方法后面的部分保持一致。
* @author Switch
* 所有的封装动态参数操作:都是一个叫params的拦截器封装的。
*/
public class TestAction2 extends ActionSupport {
private String name;
private Integer age;
public String testAction(){
System.out.println("name is "+name+" and age is "+age);
return SUCCESS;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
PS:这种方式正如你所见,每个参数都要有get/set方法,如果请求参数过多的话,那么将使Action类变得非常臃肿,所以一般不建议使用。
对象导航图语言(OGNL)简单使用
对象导航图语言和hibernate的对象导航查询很相似,都是基于对象加点号操作符的形式,来访问对象字段和其他关联对象。如果不熟悉hibernate,那么想想对象中的方法是怎样调用的,就能明白。
封装对象
JSP页面
<%--动态参数封装:对象导航映射
此时表单元素的name属性取值已经不是一个普通的字符串了。
而是一个OGNL表达式。
OGNL:Object Graphic Navigationg Language
对象 图 导航 语言
--%>
<form action="${pageContext.request.contextPath}/testAction3.action" method="post">
用户名:<input type="text" name="user.name"/><br/>
年龄:<input type="text" name="user.age"/><br/>
<input type="submit" value="提交"/>
</form>
在struts.xml文件中配置
<action name="testAction3" class="com.pc.demo.web.action.TestAction3" method="testAction">
<result name="success">/success.jsp</result>
</action>
在Action文件中
package com.pc.demo.web.action;
import com.pc.demo.domain.User;
import com.opensymphony.xwork2.ActionSupport;
/**
* 动态参数封装:属性驱动
* OGNL
* @author Switch
* 所有的封装动态参数操作:都是一个叫params的拦截器封装的。
*/
public class TestAction3 extends ActionSupport {
private User user = new User();
public String testAction(){
System.out.println("name is "+user.getName()+" and age is "+user.getAge());
return SUCCESS;
}
public User getUser() {
System.out.println("getUser");
return user;
}
public void setUser(User user) {
System.out.println("setUser");
this.user = user;
}
}
PS:对象字段可以不需要new,创建出来,在拦截器中会判断一次,然后会进行处理,具体如下:
用户实体类
package com.pc.demo.domain;
import java.io.Serializable;
/**
* 一个用户的实体(数据模型)
* @author Switch
*
*/
public class User implements Serializable {
private String name;
private Integer age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "User [name=" + name + ", age=" + age + "]";
}
}
封装List集合
JSP页面
<%--动态参数封装:对象导航映射
此时表单元素的name属性取值已经不是一个普通的字符串了。
而是一个OGNL表达式。
OGNL:Object Graphic Navigationg Language
对象 图 导航 语言
--%>
<form action="${pageContext.request.contextPath}/testAction4.action" method="post">
用户名:<input type="text" name="users[0].name"/><br/>
年龄:<input type="text" name="users[0].age"/><br/>
用户名:<input type="text" name="users[1].name"/><br/>
年龄:<input type="text" name="users[1].age"/><br/>
用户名:<input type="text" name="users[2].name"/><br/>
年龄:<input type="text" name="users[2].age"/><br/>
<input type="submit" value="提交"/>
</form>
在struts.xml文件中配置
<action name="testAction4" class="com.pc.demo.web.action.TestAction4" method="testAction">
<result name="success">/success.jsp</result>
</action>
在Action文件中
package com.pc.demo.web.action;
import com.pc.demo.domain.User;
import com.opensymphony.xwork2.ActionSupport;
import java.util.List;
/**
* 动态参数封装:属性驱动
* OGNL
* @author Switch
* 所有的封装动态参数操作:都是一个叫params的拦截器封装的。
*/
public class TestAction4 extends ActionSupport {
private List<User> users;
public String testAction(){
System.out.println(users);
return SUCCESS;
}
public List<User> getUsers() {
return users;
}
public void setUsers(List<User> users) {
this.users = users;
}
}
封装Map集合
JSP页面
<%--动态参数封装:对象导航映射
此时表单元素的name属性取值已经不是一个普通的字符串了。
而是一个OGNL表达式。
OGNL:Object Graphic Navigationg Language
对象 图 导航 语言
--%>
<form action="${pageContext.request.contextPath}/testAction5.action" method="post">
用户名:<input type="text" name="map['switch'].name"/><br/>
年龄:<input type="text" name="map['switch'].age"/><br/>
用户名:<input type="text" name="map['kity'].name"/><br/>
年龄:<input type="text" name="map['kity'].age"/><br/>
用户名:<input type="text" name="map['tomcat'].name"/><br/>
年龄:<input type="text" name="map['tomcat'].age"/><br/>
<input type="submit" value="提交"/>
</form>
在struts.xml文件中配置
<action name="testAction5" class="com.pc.demo.web.action.TestAction5" method="testAction">
<result name="success">/success.jsp</result>
</action>
在Action文件中
package com.pc.demo.web.action;
import com.pc.demo.domain.User;
import com.opensymphony.xwork2.ActionSupport;
import java.util.Map;
/**
* 动态参数封装:属性驱动
* OGNL
* @author Switch
* 所有的封装动态参数操作:都是一个叫params的拦截器封装的。
*/
public class TestAction5 extends ActionSupport {
private Map<String,User> map;
public String testAction(){
System.out.println(map);
return SUCCESS;
}
public Map<String,User> getMap() {
return map;
}
public void setMap(Map<String,User> map) {
this.map = map;
}
}
模型驱动封装
模型驱动(ModelDriven),是通过ModelDriven接口来接收请求参数,Action类必须要实现ModelDriven接口(可以使用泛型),并且要重写getModel()方法,这个方法返回的就是Action所使用的数据模型对象。
模型驱动方式通过JavaBean模型进行数据传递。只要是普通的JavaBean,就可以充当模型部分。采用这种方式,JavaBean所封装的属性与表单的属性一一对应,JavaBean将成为数据传递的载体。
其是通过ModelDrivenInterceptor拦截器,进行封装的
JSP页面
<%--动态参数封装:对象导航映射
此时表单元素的name属性取值已经不是一个普通的字符串了。
而是一个OGNL表达式。
OGNL:Object Graphic Navigationg Language
对象 图 导航 语言
--%>
<form action="${pageContext.request.contextPath}/testAction6.action" method="post">
用户名:<input type="text" name="name"/><br/>
年龄:<input type="text" name="age"/><br/>
<input type="submit" value="提交"/>
</form>
在struts.xml文件中配置
<action name="testAction6" class="com.pc.demo.web.action.TestAction6" method="testAction">
<result name="success">/success.jsp</result>
</action>
在Action文件中
package com.pc.demo.web.action;
import com.pc.demo.domain.User;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
/**
* 动态参数封装:模型驱动
* 要想实现模型驱动,必须满足以下要求:
* 1、动作类必须实现ModelDriven接口
* 2、动作类中必须定义一个模型对象,而且必须由我们自己实例化
* 3、提供抽象方法的实现,并且返回模型
*
* @author Switch
* 所有的封装动态参数操作:都是一个叫params的拦截器封装的。
* 在模型驱动下,它需要modelDriven拦截器的支持。
*/
public class TestAction6 extends ActionSupport implements ModelDriven<User> {
private User user = new User();
@Override
public User getModel() {
return user;
}
public String demo4(){
System.out.println(user);
return SUCCESS;
}
}
PS:在实际开发中,大部分情况下会使用模型驱动的方式进行封装,但是如果我们需要将请求参数封装成多个对象,那么就需要使用OGNL的方式了。
封装参数失败后的处理方式
struts2框架默认转换的数据类型
基本数据类型自动转换。
日期类型按照本地格式转换。本地格式:yyyy-MM-dd 西方国家:MM/dd/yyyy
字符串数组会按照(字符+逗号+空格的方式)拼接成字符串。
关于没有input结果视图的解决
在对应的动作类配置中配置一个<result name="input">的结果视图
input结果视图的含义:在struts2中就是用于数据回显的。
input结果视图配置的地址:从哪来回哪去
错误信息提示
需要借助struts2的标签库。
<s:fielderror fieldName=""/>指定哪个字段有错误提示
<s:actionerror/>指定动作方法执行的错误提示
struts2中的国际化
国际化:I18N internationalization
关于错误信息中文提示的解决
a、在实体类所在的包下创建一个名称为实体类名称.properties的文件
例如:User.java User.properties
b、提示内容是根据页面上的错误信息改造的key
英文错误提示:Invalid field value for field "birthday
key:invalid.fieldvalue.birthday
invalid.fieldvalue.birthday=\u8BF7\u8F93\u5165\u6B63\u786E\u7684\u65E5\u671F\u683C\u5F0F\uFF0C\u65E5\u671F\u683C\u5F0F\u662F\uFF1Ayyyy-MM-dd