struts2各个功能详解(1)----参数自动封装和类型自动转换

时间:2023-03-08 15:39:11
struts2各个功能详解(1)----参数自动封装和类型自动转换

struts2里面的各个功能,现在确实都不清楚,完全属于新学!

通过前面的例子,有时就会疑问,这些jsp中的数据信息是怎么传送给action的?例如:

 <form action = "LoginAction.action" method="post">
<p>用户名 <input type = "text" name="user.name"/></p>
<p>密码 <input type = "text" name="user.password"/></p>
<input type = "submit" value = "登录"/>
</form>

user.name是怎么传给action的?  action是怎么获取的??这个就是下面讲解的struts2参数自动封装!

一:struts2参数自动封装

前篇文章对struts2的一个入门,重点是对struts2的架构图有一个大概的了解即可,之后的几篇文章,就是细化struts2,将struts2中的各种功能进行梳理,其实学完之后,对struts2的使用不外乎这几点,参数自动封装,拦截器的使用,数据校验,ognl表达(值栈和actionContext的讲解),struts2的标签,struts2的国际化,struts2的文件上传下载。 把这几个功能都学会了使用之后,struts2基本上就学完了。所以接下来的文章就是对这几个功能进行讲解。如何使用。而进行就对数据自动封装和数据类型自动转型进行讲解。

什么叫封装呢?其实就是把用户输入的数据获取到,然后输出或者封装到类里面去。

struts2各个功能详解(1)----参数自动封装和类型自动转换

1.1 静态参数封装

action获取struts.xml中的参数--------是从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> <constant name="struts.enable.DynamicMethodInvocation" value="false" />
<constant name="struts.devMode" value="true" /> <package name="zxl" namespace="/" extends="struts-default"> <action name="MyParaAction" class="action.MyParaAction" method="test01">
<result name="success">/index.jsp</result>
<param name="username">zhangsan</param>
<param name="password">12345</param>
</action> <action name="MyParaAction2" class="action.MyParaAction2" method="test01">
<result name="success">/index.jsp</result>
<param name="user.username">zhaosi</param>
<param name="user.password">12345</param>
</action> </package>
</struts>

我们来看第一个action:MyParaAction.java

 package action;

 import com.opensymphony.xwork2.ActionSupport;

 public class MyParaAction extends ActionSupport {

     private String username;
private String password;
/**
* @return the username
*/
public String getUsername() {
return username;
}
/**
* @param username the username to set
*/
public void setUsername(String username) {
this.username = username;
}
/**
* @return the password
*/
public String getPassword() {
return password;
}
/**
* @param password the password to set
*/
public void setPassword(String password) {
this.password = password;
} public String test01(){ System.out.println("username : " + username + ", password : " + password); return "success";
} }

加入本测试不关注的index.jsp

 <%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!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=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
Hi, Struts2!!! </body>
</html>

我们在浏览器输入:http://localhost:8080/Struts2Demo/MyParaAction

可以看到浏览器输出:Hi, Struts2!!!

而我们看控制台:username : zhangsan, password : 12345

可以看到在struts.xml中配置的参数传递到了action。

上面这种静态参数是直接定义在action里面,没有对应的实体内。下面我们看有实体内的静态参数怎么传给action:

MyParaAction2的action已经在前面struts.xml已经配置了。看具体action和JavaBean实体类:

 package login;

 public class User {

     private String username;
private String password; /**
* @return the username
*/
public String getUsername() {
return username;
} /**
* @param username the username to set
*/
public void setUsername(String username) {
this.username = username;
}
/**
* @return the password
*/
public String getPassword() {
return password;
}
/**
* @param password the password to set
*/
public void setPassword(String password) {
this.password = password;
} }
 package action;

 import com.opensymphony.xwork2.ActionSupport;

 import login.User;

 public class MyParaAction2 extends ActionSupport {

     private User user;

     /**
* @return the user
*/
public User getUser() {
return user;
} /**
* @param user the user to set
*/
public void setUser(User user) {
this.user = user;
} public String test01(){ System.out.println("user info:"+ user.getUsername() +" " + user.getPassword());
return "success";
} }

在浏览器输入:http://localhost:8080/Struts2Demo/MyParaAction2

同样浏览器输出:Hi, Struts2!!!

控制台输出:user info:zhaosi 12345

从上面可以看出,主要是根据action中定义的情况来配置struts.xml。至于传进去的参数怎么返回给jsp等,不是这个讨论的,后面继续。

——因为在我们执行test01()方法的前后,有很多拦截器interceptor做一些工作,其中有一个叫做staticParams的拦截器,它就是专门负责看看你struts.xml里的action里是否有定义param参数,如果有的话,拿到这个参数的name名字,然后去这个action的对应的类class里面的方法method去找setXXX方法,和setXXX中set后面的XXX比较(这里它会自动转换大小写),如果发现有匹配的,就把值复制给类class里面的变量。然后我们在执行这个方法method的时候,这个变量其实就已经有值了,我们输出到控制台的时候就能看到值了。

记住:静态参数封装就是从struts.xml中获取数据传给action.

1.2 动态参数封装

动态参数封装。核心的例子就是表单数据的提交。所以这个地方开始肯定有表单jsp

struts2各个功能详解(1)----参数自动封装和类型自动转换

1.2.1 属性驱动

1.2.1.1 基本属性驱动基本属性驱动就是数据模型和动作类写在一起(即动作类中有数据模型)

我们看下面这个例子,同样以上面action为例:

 package action;

 import com.opensymphony.xwork2.ActionSupport;

 public class MyParaAction extends ActionSupport {

     private String username;
private String password;
/**
* @return the username
*/
public String getUsername() {
return username;
}
/**
* @param username the username to set
*/
public void setUsername(String username) {
this.username = username;
}
/**
* @return the password
*/
public String getPassword() {
return password;
}
/**
* @param password the password to set
*/
public void setPassword(String password) {
this.password = password;
} public String test01(){ System.out.println("username : " + username + ", password : " + password); return "success";
} }

添加表单页面:login1.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>登录实例</title>
</head>
<body>
<form action = "MyParaAction" method="post">
<p>用户名 <input type = "text" name="username"/></p>
<p>密码 <input type = "text" name="password"/></p>
<input type = "submit" value = "登录"/>
</form>
</body>
</html>

在浏览器输入:http://localhost:8080/Struts2Demo/login1.jsp, 浏览器输出:

struts2各个功能详解(1)----参数自动封装和类型自动转换struts2各个功能详解(1)----参数自动封装和类型自动转换

在输入框输入用户名和密码,然后看到控制台输出:username : zxl, password : 123

这个地方注意了,我没有修改struts.xml,也就是说里面action还是配置了静态参数的。但结果是动态参数会直接覆盖静态参数的传递。

此方式简单易懂,但是在实际开发中,用的不是很多,局限性大,并且数据模型和动作类写在一个类中,不利于解耦管理。由此出现了动态参数封装的第二种方式。

1.2.1.2  ognl表达式来封装数据: 数据模型和动作类分别写在不同类中(即数据模型建立javabean)

就按照前面第二个action,即:MyParaAction2.java, 里面User 和Action不在同一个class中。

 package action;

 import com.opensymphony.xwork2.ActionSupport;

 import login.User;

 public class MyParaAction2 extends ActionSupport {
//动作类中只有一个javabean对象。通过set.get方法进行管理
private User user; /**
* @return the user
*/
public User getUser() {
return user;
} /**
* @param user the user to set
*/
public void setUser(User user) {
this.user = user;
} public String test01(){ System.out.println("user info:"+ user.getUsername() +" " + user.getPassword());
return "success";
}
} //所需要的数据模型:
package login; public class User { private String username;
private String password; /**
* @return the username
*/
public String getUsername() {
return username;
} /**
* @param username the username to set
*/
public void setUsername(String username) {
this.username = username;
}
/**
* @return the password
*/
public String getPassword() {
return password;
}
/**
* @param password the password to set
*/
public void setPassword(String password) {
this.password = password;
} }

然后看我们的表单页面:login2.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>登录实例</title>
</head>
<body>
<form action = "MyParaAction2" method="post">
<p>用户名 <input type = "text" name="user.username"/></p>
<p>密码 <input type = "text" name="user.password"/></p>
<input type = "submit" value = "登录"/>
</form>
</body>
</html>

同样在浏览器输入:http://localhost:8080/Struts2Demo/login2.jsp  在输入框输入信息:

struts2各个功能详解(1)----参数自动封装和类型自动转换struts2各个功能详解(1)----参数自动封装和类型自动转换

控制台输出:user info:qwert 1234567。

同样可以看出,也没有修改struts.xml   里面同样还是配置了静态参数, 但是动态参数依然会覆盖掉静态参数。

表单中的name属性值必须是javabean的对象的属性,不是简单的username了,变成了user.username。

还有动作类中set.get方法的执行顺序:

get方法:struts2先调用get方法,判断对象是否存在,如果不存在,使用反射创建一个对象。
set方法:不存在的时候,创建一个对象,把它set进去
get方法:再调用get方法得到对象,调用set方法得到对象的各种属性,为属性赋值。

在jsp页面中的user.name和user.age其实就是ognl表达式,代表着往根(root,值栈valueStack)中存放值,而值栈中的栈顶元素也就是为当前action,我们在action中设置user的get、set属性,即可以让存进来的值匹配到,进而将对应属性赋值成功。

上面这种参数封装属于OGNL中的封装对象。

下面看一下封装列表和map

下面先看OGNL封装List 例子:

 package action;

 import java.util.List;

 import com.opensymphony.xwork2.ActionSupport;

 import login.User;

 public class MyParaAction2 extends ActionSupport {

     //创建用户对象,在JSP中用OGNL封装对象来获取参数
private User user;
//创建List对象,在JSP中用OGNL封装列表list来获取参数
private List<User> users; /**
* @return the user
*/
public User getUser() {
return user;
} /**
* @param user the user to set
*/
public void setUser(User user) {
this.user = user;
} /**
* @return the users
*/
public List<User> getUsers() {
return users;
} /**
* @param users the users to set
*/
public void setUsers(List<User> users) {
this.users = users;
} public String test01(){ System.out.println("user info:"+ user.getUsername() +" " + user.getPassword());
return "success";
} public String test03(){
System.out.println("test03");
System.out.println("user1 info:"+ users.get(0).getUsername() +" " + users.get(0).getPassword());
System.out.println("user2 info:"+ users.get(1).getUsername() +" " + users.get(1).getPassword());
return "success";
} public String test04(){
System.out.println("test04");
System.out.println("user1 info:"+ users.get(0).getUsername() +" " + users.get(0).getPassword());
System.out.println("user2 info:"+ users.get(1).getUsername() +" " + users.get(1).getPassword());
return "success";
}
}

然后我们来看一下表单页面:login3.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>登录实例</title>
</head>
<body>
<form action = "Login3!test03" method="post">
<p>用户名1 <input type = "text" name="users[0].username"/></p>
<p>密码 <input type = "text" name="users[0].password"/></p>
<p>用户名2 <input type = "text" name="users[1].username"/></p>
<p>密码 <input type = "text" name="users[1].password"/></p>
<input type = "submit" value = "登录"/>
</form>
</body>
</html>

这个表单页面是不是和前面有点不一样了:

首先,后面传递的参数users[0].username,users[0].password,users[1].username,users[1].password就是用OGNL对List进行的封装。

  这个地方的list必须与动作类中定义的list完全对应。

其次action处是:Login3!test03,看到这个要想到这个是动态函数调用。和struts.xml配合使用。

我们看一下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> <constant name="struts.enable.DynamicMethodInvocation" value="true" />
<constant name="struts.devMode" value="false" /> <package name="zxl" namespace="/" extends="struts-default"> <action name="MyParaAction" class="action.MyParaAction" method="test01">
<result name="success">/index.jsp</result>
<param name="username">zhangsan</param>
<param name="password">12345</param>
</action> <action name="Login3" class="action.MyParaAction2" >
<result name="success">/index.jsp</result>
</action> <action name="Login4_*" class="action.MyParaAction2" method="{1}">
<result name="success">/index.jsp</result>
</action> </package> <include file="example.xml"/>
<include file="struts-constant.xml"/>
<include file="struts-dynamic.xml"/>
<include file="struts-actionsupport.xml"/>
<!-- Add packages here -->
</struts>

此处看到了OGNL封装List. 在此添加一个知识点:动态函数调用

动态函数调用主要有三种方式:

方式一:我们很常见,在struts.xml中显示的指示出来method。

         <action name="MyParaAction2" class="action.MyParaAction" method="test01">
<result name="success">/index.jsp</result>
<param name="username">zhangsan</param>
<param name="password">12345</param>
</action>

也就是说通过在struts.xml文件中通过配置action标签的method属性来设置即可。
但是这个方法有一个缺陷,当一个action中有很多方法的时候就需要为每个方法配置一遍action,同时通过分配不同的name属性来指定到对应的method,因此这种方法很麻烦

方式二:感叹号方式(需要在struts.xml中配置常量,启动动态方法调用)

前面的例子就是通过这种方式来动态调用test03的。

表单页面:需要在调用的时候在action名字加上感叹号加上你要调用的方法名即可。

 <form action = "Login3!test03" method="post">

在struts2.xml配置文件中需要添加常量指明可以动态调用方法才可以。

<constant name="struts.enable.DynamicMethodInvocation" value="true" />

在配置action的地方就不用写method参数了。这样test03()就会运行了。

上面那个常量属性在哪儿呢?
struts2各个功能详解(1)----参数自动封装和类型自动转换

方式三:通配符方法调用

也就是说name属性中的占位符*可以用来指定你想指定的值。第一个通配符匹配的就是属性值为{1}的,第二个通配符就是指定属性值为{2}的值。
看下面表单定义:在action后面加上“_”+函数名
表单login4.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>登录实例</title>
</head>
<body>
<form action = "Login4_test04" method="post">
<p>用户名1 <input type = "text" name="users[0].username"/></p>
<p>密码 <input type = "text" name="users[0].password"/></p>
<p>用户名2 <input type = "text" name="users[1].username"/></p>
<p>密码 <input type = "text" name="users[1].password"/></p>
<input type = "submit" value = "登录"/>
</form>
</body>
</html>

然后在struts.xml中进行匹配:

         <action name="Login4_*" class="action.MyParaAction2" method="{1}">
<result name="success">/index.jsp</result>
</action>

运行效果同上。

OGNL封装MAP

给出例子如下:

 package action;

 import java.util.List;
import java.util.Map; import com.opensymphony.xwork2.ActionSupport; import login.User; public class MyParaAction2 extends ActionSupport { //创建用户对象,在JSP中用OGNL封装对象来获取参数
private User user;
//创建List对象,在JSP中用OGNL封装列表list来获取参数
private List<User> users;
//创建Map对象,在JSP中用OGNL封装Map来获取参数
private Map<String, User> userMap; /**
* @return the user
*/
public User getUser() {
return user;
} /**
* @param user the user to set
*/
public void setUser(User user) {
this.user = user;
} /**
* @return the users
*/
public List<User> getUsers() {
return users;
} /**
* @param users the users to set
*/
public void setUsers(List<User> users) {
this.users = users;
} /**
* @return the userMap
*/
public Map<String, User> getUserMap() {
return userMap;
} /**
* @param userMap the userMap to set
*/
public void setUserMap(Map<String, User> userMap) {
this.userMap = userMap;
} public String test01(){ System.out.println("user info:"+ user.getUsername() +" " + user.getPassword());
return "success";
} public String test03(){
System.out.println("test03");
System.out.println("user1 info:"+ users.get(0).getUsername() +" " + users.get(0).getPassword());
System.out.println("user2 info:"+ users.get(1).getUsername() +" " + users.get(1).getPassword());
return "success";
} public String test04(){
System.out.println("test04");
System.out.println("user1 info:"+ users.get(0).getUsername() +" " + users.get(0).getPassword());
System.out.println("user2 info:"+ users.get(1).getUsername() +" " + users.get(1).getPassword());
return "success";
} public String test05(){
System.out.println("test05");
System.out.println("user1 info:"+ userMap.get("china").getUsername() +" " + userMap.get("china").getPassword());
System.out.println("user2 info:"+ userMap.get("Japan").getUsername() +" " + userMap.get("Japan").getPassword());
return "success";
}
}

看表单login5.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>登录实例</title>
</head>
<body>
<form action = "Login5_test05" method="post">
<p>用户名1 <input type = "text" name="userMap['china'].username"/></p>
<p>密码 <input type = "text" name="userMap['china'].password"/></p>
<p>用户名2 <input type = "text" name="userMap['Japan'].username"/></p>
<p>密码 <input type = "text" name="userMap['Japan'].password"/></p>
<input type = "submit" value = "登录"/>
</form>
</body>
</html>
userMap['china'].username来匹配动作类中的map
map集合和上面的list集合类似,只不过在编写ognl表达式有些不同,userMap['china'].username、userMap['china'].password,userMap['china']代表的是map中key为China的value,也就找到了key为China的User对象,然后在进行封装数据即可。看struts.xml配置:同样采用模式匹配来进行动态函数调用。
         <action name="Login5_*" class="action.MyParaAction2" method="{1}">
<result name="success">/index.jsp</result>
</action>

在浏览器输入:http://localhost:8080/Struts2Demo/login5.jsp

struts2各个功能详解(1)----参数自动封装和类型自动转换struts2各个功能详解(1)----参数自动封装和类型自动转换

在控制台输出:test05
user1 info:qaz edc
user2 info:rfv tgb。

到此属性驱动的参数封装结束。下面看模型驱动的参数封装:

1.2.1 模型驱动

使用模型驱动进行参数封装时,数据模型必须和动作类方法不在同一个类中。

使用步骤如下:
1. 动作类实现ModelDriven的接口
2. 实现接口中的抽象方法getModel
3. 使用模型驱动时,数据模型必须由我们自己实例化。即
private User user = new User();
此时在form表单中可以直接使用username进行参数传递了~
先看下动作类:MyParaAction3.java

 package action;

 import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven; import login.User; public class MyParaAction3 extends ActionSupport implements ModelDriven<User> {//动作类实现ModelDriven的接口
//使用模型驱动时,数据模型必须由我们自己实例化
private User user = new User();
//实现接口中的抽象方法getModel
@Override
public User getModel() { return user;
} public String test01(){
System.out.println("user info:" + user.getUsername() +" , " + user.getPassword()); return "success";
} }

看表单数据login6.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>登录实例</title>
</head>
<body>
<form action = "Login6_test01" method="post">
<p>用户名1 <input type = "text" name="username"/></p>
<p>密码 <input type = "text" name="password"/></p>
<input type = "submit" value = "登录"/>
</form>
</body>
</html>

上面是动态参数传递。下面看struts.xml配置:

         <action name="Login6_*" class="action.MyParaAction3" method="{1}">
<result name="success">/index.jsp</result>
</action>

在浏览器输入:http://localhost:8080/Struts2Demo/login6.jsp

struts2各个功能详解(1)----参数自动封装和类型自动转换struts2各个功能详解(1)----参数自动封装和类型自动转换

控制台输出:user info:zxl , 123。

这个地方有个主意:如果在jsp中不直接写username, 而是写user.username, 发现action 得不到参数。参数传递失败。

模型驱动方式通过JavaBean模型进行数据传递。只要是普通的JavaBean,就可以充当模型部分。采用这种方式,JavaBean所封装的属性与表单的属性一一对应,JavaBean将成为数据传递的载体。

记住:通过模型驱动时,在表单页面中必须直接按照JavaBean中数据模型来填写参数!

二:struts2参数自动类型转换

上面我们知道了struts2的方便之处,不用我们自己手动来获取请求参数了,struts2中的某些拦截器已经帮我们全部解决好了,我们只需要写get、set方法即可,真是非常方便。不知道大家发现了没有,从表单元素提交过来的都是String类型的,而我们在servlet中获取到表单元素后,得到的是Object类型,也就是需要我们自己手动转型。但是在struts2中,我们却不需要,是因为有这么一个机制,参数类型自动转型,获取过来的参数都是String类型的,但是如果我们需要int型,double型等,都会帮我们自己转换。

下面我们看一个例子:首先给出动作类:定义了不同的数据类型

 package action;

 import java.util.Date;

 import com.opensymphony.xwork2.ActionSupport;

 public class MyParaAction4 extends ActionSupport {
private int age;
private String name;
private float money;
private boolean married;
private char sex;
private Date date; /**
* @return the date
*/
public Date getDate() {
return date;
} /**
* @param date the date to set
*/
public void setDate(Date date) {
this.date = date;
} /**
* @return the age
*/
public int getAge() {
return age;
} /**
* @param age the age to set
*/
public void setAge(int age) {
this.age = age;
} /**
* @return the name
*/
public String getName() {
return name;
} /**
* @param name the name to set
*/
public void setName(String name) {
this.name = name;
} /**
* @return the money
*/
public float getMoney() {
return money;
} /**
* @param money the money to set
*/
public void setMoney(float money) {
this.money = money;
} /**
* @return the married
*/
public boolean isMarried() {
return married;
} /**
* @param married the married to set
*/
public void setMarried(boolean married) {
this.married = married;
} /**
* @return the sex
*/
public char getSex() {
return sex;
} /**
* @param sex the sex to set
*/
public void setSex(char sex) {
this.sex = sex;
} public String test01(){ System.out.println("user info:" + name +","+ age +","+ money +","+ sex +","+ married +","+ date); return "success";
} }

下面给出表单页面login7.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>登录实例</title>
</head>
<body>
<form action = "Login7_test01" method="post">
<p>int <input type = "text" name="age"/></p>
<p>String <input type = "text" name="name"/></p>
<p>float <input type = "text" name="money"/></p>
<p>boolean <input type = "radio" name="married" value=true checked="checked"/>是
<input type = "radio" name="married" value=false />否</p>
<p>char <input type = "radio" name="sex" value="男" checked="checked"/>男
<input type = "radio" name="sex" value="女" />女</p>
<p>日期 <input type = "text" name="date"/></p> <input type = "submit" value = "登录"/>
</form>
</body>
</html>

struts配置就不贴出来。在浏览器输入:http://localhost:8080/Struts2Demo/login7.jsp

struts2各个功能详解(1)----参数自动封装和类型自动转换struts2各个功能详解(1)----参数自动封装和类型自动转换

点击登陆,

在浏览器页面输出:Hi, Struts2!!!

在控制台输出:user info:zhangsan,30,100000.0,男,true,Thu Sep 13 00:00:00 CST 2018.

这个地方注意了:上面输入日期的格式必须是:2018-09-13。也就是说,必须是:年-月-日。如果我们按照下面格式输入:

struts2各个功能详解(1)----参数自动封装和类型自动转换

点击登录:会报错。

struts2各个功能详解(1)----参数自动封装和类型自动转换

看上面例子,全部都自动转型了,这里需要注意一点,在使用struts2中的日期自动转型时,表单中的日期字符串的格式是固定的,也就是说按照上面那样编程,日期格式必须是那样,没法进行自动转换。但是如果给客户使用,客户就是没按照那种格式来书写,怎么办?

struts2能够让我们自定义类型转换器,格式让我们自己来决定。自定义日期转换器:

只需要两步即可完成:1、继承DefaultTypeConverter类,重写convertValue方法 

          2、注册转换器。也就是该转换器的作用范围。局部配置和全局配置。

下面给出例子:动作类还是上面那个,只是输入日期可以有好多个格式:

自定义转换器:MyConvert.java

 package util;

 import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date; import com.opensymphony.xwork2.conversion.TypeConversionException;
import com.opensymphony.xwork2.conversion.impl.DefaultTypeConverter; public class MyConvert extends DefaultTypeConverter {
//支持转换的多种日期格式,可增加时间格式
private final DateFormat[] dfs={
new SimpleDateFormat("yyyy年MM月dd日"),
new SimpleDateFormat("yyyy-MM-dd"),
new SimpleDateFormat("MM/dd/yy"),
new SimpleDateFormat("yyyy.MM.dd"),
new SimpleDateFormat("yy.MM.dd"),
new SimpleDateFormat("yyyy/MM/dd")
}; /* (non-Javadoc)
* @see com.opensymphony.xwork2.conversion.impl.DefaultTypeConverter#convertValue(java.lang.Object, java.lang.Class)
*/
@Override
public Object convertValue(Object value, Class toType) {
//用特定格式转换,也就是说输入格式必须是2018/09/13,也即是说字符串的格式只能是这个才可以转换
SimpleDateFormat sf = new SimpleDateFormat("yyyy-mm-dd"); if(toType == java.util.Date.class){
//获得数据
String[] param = (String[])value;//获取日期的字符串 for(int i=0; i < dfs.length ; i++){//遍历日期支持格式,进行转换 try {
return dfs[i].parse(param[0]);//转化为特定格式的date类型
} catch (ParseException e) {
continue;
}
}
//如果遍历完毕后仍没有转换成功,表示出现转换异常
throw new TypeConversionException();
}
//将日期转换为指定的字符串格式
if(toType == String.class){
java.util.Date date = (Date) value;
return sf.format(date); //输出格式是yyyy-MM-dd
} return null;
}
}

然后注册转换器:分两种情况:一种是局部注册,一种是全局注册

局部注册:

位置:action类同包

名称:actionClass-conversion.properties

actionClass:action类的类名

conversion.properties:固定名

struts2各个功能详解(1)----参数自动封装和类型自动转换

内容:属性=转换器类的全限定类名

date=util.MyConvert

这样一来,我们自定义的转换器就只能在Demo01Action中属性名为date身上使用了,超过了该范围,就会使用struts2默认的转换器。

 全局注册:

注册,全局配置

位置:src

名称:xwork-conversion.properties

struts2各个功能详解(1)----参数自动封装和类型自动转换

内容:需要转换得类=转换器

全局配置后,所有在struts2中使用Date型的都会用我们写的转换器进行转换。

本测试中用的是局部注册,然后我们在访问浏览器:http://localhost:8080/Struts2Demo/login7.jsp

在日期那一行就可以输入各种自定义的日期格式了。

到此关于struts的参数封装和自动转换学习完了。有个疑问就是struts在动作类中的参数又是怎么回显到表单的呢?这个是在哪个模块呢?struts标签????

主要参考的帖子有:在此感谢!!!

https://www.cnblogs.com/jingpeipei/p/5945724.html-----日期转换

https://www.cnblogs.com/whgk/category/964133.html------各个功能介绍

https://blog.csdn.net/wjw0130/article/category/2503465-----各个功能介绍

https://blog.csdn.net/q547550831/article/category/6532892-----各个功能介绍

https://blog.csdn.net/xtayfjpk/article/details/14133589-----专门介绍拦截器