Struts2 入门学习笔记(三)——数据转换

Struts入门学习笔记(三)——数据转换

一.基于OGNL的类型转换

1. 针对复合类的类型转换  

       借助内置的类型转换器,Struts2可以完成字符串和基本类型之间的类型转换,除此之外借助OGNL表达式的支持,Struts2允许另一种简单的方式将请求参数转换成复合类型,首先我们先看一下这样一个action.java
    
    
    
    
  1. package cn.green.action;
  2. import cn.green.bean.User;
  3. import com.opensymphony.xwork2.ActionSupport;
  4. public class LoginAction extends ActionSupport{
  5. private User user;
  6. public User getUser() {
  7. return user;
  8. }
  9. public void setUser(User user) {
  10. this.user = user;
  11. }
  12. public String execute(){
  13. if(getUser().getName().equals("tom") && getUser().getPass().equals("1234")){
  14. addActionMessage("转换成功");
  15. return SUCCESS;
  16. }
  17. addActionMessage("转换失败");
  18. return ERROR;
  19. }
  20. }
以下是input.jsp表单:
    
    
    
    
  1. <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
  2. <%@taglib prefix="s" uri="/struts-tags" %>
  3. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
  4. <html>
  5. <head>
  6. </head>
  7. <body>
  8. <s:form action="login">
  9. <s:textfield name="user.name" label="用户名:" />
  10. <s:textfield name="user.pass" label="密 码:" />
  11. <tr>
  12. <td colspan="2">
  13. <s:submit value="转换" theme="simple" />
  14. <s:reset calue="重置" theme="simple"></s:reset>
  15. </td>
  16. </tr>
  17. </s:form>
  18. </body>
  19. </html>
          这里就不写在struts.xml中配置的信息了,但我们写出以上的形式之后很容易发现程序是可以运行的,我们知道基本数据类型是可以默认转换的,那么这种User类的实例又是为什么自己自动完成装配了呢,就是因为OGNL表达式,具体应用如上所示,改变的是在输入表单input.jsp中的写法,然后它会自动地将表单中user.name的值赋值给action中的user实例的name变量,以此类推,最后就可以在action中直接用了。
         这里有几个问题需要注意,因为这种方式其实就是运用反射来创建复合类User,所以必须为他提供无参构造器,除此之外在action中必须配备复合类的get、set方法

2. 针对Collction或Map的转换

同样我们这里直接贴代码,主要不同点在于jsp页面的name标签写法而已,action与上面相同,即可实现自动转换。
input.jsp页面:
    
    
    
    
  1. <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
  2. <%@taglib prefix="s" uri="/struts-tags" %>
  3. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
  4. <html>
  5. <head>
  6. </head>
  7. <body>
  8. <s:form action="login">
  9. <s:textfield name="users['one'].name" label="第一个用户名:" />
  10. <s:textfield name="users['one'].pass" label="第一个密 码:" />
  11. <s:textfield name="users['two'].name" label="第二个用户名:" />
  12. <s:textfield name="users['two'].pass" label="第二个密 码:" />
  13. <tr>
  14. <td colspan="2">
  15. <s:submit value="转换" theme="simple" />
  16. <s:reset calue="重置" theme="simple"></s:reset>
  17. </td>
  18. </tr>
  19. </s:form>
  20. </body>
  21. </html>
执行的action如下:
    
    
    
    
  1. package cn.green.action;
  2. import java.util.Map;
  3. import cn.green.bean.User;
  4. import com.opensymphony.xwork2.ActionSupport;
  5. public class LoginAction extends ActionSupport{
  6. private Map<String, User> users;
  7. public Map<String, User> getUsers() {
  8. return users;
  9. }
  10. public void setUsers(Map<String, User> users) {
  11. this.users = users;
  12. }
  13. public String execute(){
  14. if(getUsers().get("one").getName().equals("tom") && getUsers().get("one").getPass().equals("1234")){
  15. addActionMessage("登陆成功");
  16. return SUCCESS;
  17. }
  18. addActionMessage("登陆失败");
  19. return ERROR;
  20. }
  21. }
当然,我们需要访问这些action中的属性时,也可以用以下的方式:
    
    
    
    
  1. <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
  2. <%@taglib prefix="s" uri="/struts-tags" %>
  3. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
  4. <html>
  5. <head>
  6. </head>
  7. <body>
  8. 第一个用户名:<s:property value="users['one'].name"/><br>
  9. 第一个密 码:<s:property value="users['two'].name"/><br>
  10. 第二个用户名:<s:property value="users['one'].pass"/><br>
  11. 第二个密 码:<s:property value="users['two'].pass"/><br>
  12. </body>
  13. </html>

3. 针对List类型的转换

其实道理和上面都一样,只不过方式换成了List而已,List可以依据顺序去提取和赋值:
    
    
    
    
  1. <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
  2. <%@taglib prefix="s" uri="/struts-tags" %>
  3. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
  4. <html>
  5. <head>
  6. </head>
  7. <body>
  8. <s:form action="login">
  9. <s:textfield name="users[0].name" label="第一个用户名:" />
  10. <s:textfield name="users[0].pass" label="第一个密 码:" />
  11. <s:textfield name="users[1].name" label="第二个用户名:" />
  12. <s:textfield name="users[1].pass" label="第二个密 码:" />
  13. <tr>
  14. <td colspan="2">
  15. <s:submit value="转换" theme="simple" />
  16. <s:reset calue="重置" theme="simple"></s:reset>
  17. </td>
  18. </tr>
  19. </s:form>
  20. </body>
  21. </html>
其他省略,都是一样的。

二.指定集合元素的类型

         我们知道实现上面第一种的原理就是泛型和反射,通过泛型实现了关键步骤,Struts2还允许另外一种方式去实现它,通过一个叫类型转换文件(*.properties)的方式,请看下面的action:
    
    
    
    
  1. package cn.green.action;
  2. import java.util.List;
  3. import java.util.Map;
  4. import cn.green.bean.User;
  5. import com.opensymphony.xwork2.ActionSupport;
  6. public class LoginAction extends ActionSupport{
  7.     
  8.     private List users;
  9. public List getUsers() {
  10. return users;
  11. }
  12. public void setUsers(List users) {
  13. this.users = users;
  14. }
  15. @Override
  16. public String execute() throws Exception {
  17. System.out.println(getUsers());
  18. User firstUser = (User) getUsers().get(0);
  19. if(firstUser.getName().equals("jerry") && firstUser.getPass().equals("1234")){
  20. addActionMessage("登陆成功");
  21. return SUCCESS;
  22. }
  23. addActionMessage("登陆失败");
  24. return ERROR;
  25. }
  26. }
         当然,如果只是凭借上面的写法,程序运行时还是不知道该怎么转,这里就需要一个配置文件去写入定义的类型才行(局部类型转换文件),这个文件有着专门的写法:ActionName-conversion.properties,这里我们写成LoginAction-conversion.properties,将文件放到与action同一个目录下才行,为了指定List里面元素的数据类型,我们是这样定义的:
         List集合属性的名称  List集合里元素的类型
    
    
    
    
  1. Element_<ListPropName>=<ElementType>
         本例中这样书写:
    
    
    
    
  1. Element_users = cn.green.bean.User
         这样的话程序有可以正常运行了,达到了相同的效果。
         如果是Map类型,由于它属于key-value性质,我们可以这样写:
    
    
    
    
  1. <!--指定key-->
  2. key_<MapPropName>=<KeyType>
  3. <!--指定value-->
  4. Element_<MapPropName>=<VauleType>

三.自定义类型转换器

             还是接着上面的讲,LoginAction使用如下:
    
    
    
    
  1. package cn.green.action;
  2. import cn.green.bean.User;
  3. import com.opensymphony.xwork2.ActionSupport;
  4. public class LoginAction extends ActionSupport{
  5. private User user;
  6. public User getUser() {
  7. return user;
  8. }
  9. public void setUser(User user) {
  10. this.user = user;
  11. }
  12. public String execute(){
  13. if(getUser().getName().equals("tom") && getUser().getPass().equals("1234")){
  14. addActionMessage("转换成功");
  15. return SUCCESS;
  16. }
  17. addActionMessage("转换失败");
  18. return ERROR;
  19. }
  20. }
           但是表单提交却不是按照要求填写的,如果我们从表单接受的仅仅是一个字符串,如tom,1234 的样式,那我们如何封装想要的复合类型,我们知道机器不可以自己去给你用逗号分开,所以需要我们自己做一个类型转换器,在里面告诉它怎么转,这个自定义的类型转换器要有一定的规则,必须继承自DefaultTypeConverter
    
    
    
    
  1. package cn.green.converter;
  2. import java.util.Map;
  3. import cn.green.bean.User;
  4. import ognl.DefaultTypeConverter;
  5. public class UserConverter extends DefaultTypeConverter {
  6. @Override
  7. public Object convertValue(Map context, Object value, Class toType) {
  8. //字符串向User类型转换
  9. if(toType == User.class){
  10. String[] params = (String[]) value;
  11. User user = new User();
  12. String[] userValues = params[0].split(",");
  13. user.setName(userValues[0]);
  14. user.setPass(userValues[1]);
  15. return user;
  16. }
  17.         //User类型向字符串转换
  18. else if(toType == String.class){
  19. User user = (User) value;
  20. return "<"+user.getName()+","+user.getPass()+">";
  21. }
  22. reutrn null;
  23. }
  24. }
         注意一点,写转换器时是双向的,从A->B,也从B->A

四.注册类型转换器

         以上我们定义了自己的类型转换器,但是可以直接用么?当然不是,Struts2不知道怎么去用它们,我们需要将这些类型转换器注册在web应用中,这样才能应用。
         Struts2有三种注册方式: 
                      注册局部类型转换器:仅对某个action的属性起作用
                     注册全局类型转换器:对所有action的特定类型的属性都会生效
                   使用jdk1.5的注解来注册类型转换器

   1.局部类型转换器

        只需要在局部类型转换器中加入下列即可:本例中
    
    
    
    
  1. <propName>=<ConverterName>
        本例中我们这样设置即可:
     
     
     
     
  1. <!--执行action的user属性需要使用UserConverter类来完成转换-->
  2. user=cn.green.converter.UserConverter

    2.全局类型转换器

        全局类型转换器不是对指定Action起作用,而是对指定类型起作用,注册全局类型转换文件xwork-conversion.properties,将其放到根目录下即可
           同样的注册写入:
    
    
    
    
  1. <propType>=<ConvertClass>
               本例中我们注册如下:
   
   
   
   
   
  1. cn.green.bean.User=cn.green.converter.UserConverter

五.基于Struts2的自定义类型转换器

         Struts2中给我们放了一个strutsTypeConverter抽象类,他其实就是 DefaultTypeConverter的子类,只不过默认的需要自己去判断转换成哪种类型,而这个直接有方法调用,具体如下:
    
    
    
    
  1. package cn.green.converter;
  2. import java.util.Map;
  3. import org.apache.struts2.util.StrutsTypeConverter;
  4. import cn.green.bean.User;
  5. public class UserConverterByStruts extends StrutsTypeConverter{
  6. @Override
  7. public Object convertFromString(Map context, String[] values, Class toClass) {
  8. User user = new User();
  9. String[] userValues = values[0].split(",");
  10. user.setName(userValues[0]);
  11. user.setPass(userValues[1]);
  12. return user;
  13. }
  14. @Override
  15. public String convertToString(Map context, Object value) {
  16. User user = (User) value;
  17. return "<"+user.getName()+","+user.getPass()+">";
  18. }
  19. }
注册方式和上面的一样,这里不再赘述。

六.处理Set集合

此处不详细介绍了,大致方法如上,唯一需要注意的就是由于Set的 无序性会造成一些额外的设置。

七.类型转换中的错误处理

         1.处理类型转换错误
         Struts自带默认的转换错误拦截器,单为了让Strtuts2类型转换的错误处理机制生效,包括【输入检验】生效,都必须让Action继承Struts2 的ActionSupport基类,因为这个基类负责收集类型转换错误,输入校验错误,并将它们封装到FieldError对象,添加到ActionContext中,这样做之后我们可以很容易的在视图层使用<s:fielderror/>标签输出相应的错误
         此处如果想添加对中文错误提示的信息,可在国际化资源文件中加入下列代码:
    
    
    
    
  1. xwork.default.invalid.fieldvalue={0}

         相应错误提示:
    
    
    
    
  1. <s:fielderror />

         2.处理集合属性的转换错误
                   大致原理如上,只不过对OGNL的应用可以多一些。




你可能感兴趣的:(Struts2 入门学习笔记(三)——数据转换)