struts2数据类型转换DefaultTypeConverter
转https://www.cnblogs.com/IT-1994/p/5998458.html
一、前言
笔者一直觉得,学习一个知识点,你首先要明白,这东西是什么?有什么用?这样你才能了解。好了,不说废话。
1.1、类型转换为何存在?什么是类型转换?
在MVC框架中,都是属于表示层解决方案,都需要负责收集用户请求的参数,并且将请求参数传给应用的控制器组件,但是,这里有一个问题,客户端提交的请求参数都是字符串数据类型,而java这门语言本身就是强类型语言,所以我们需要类型转换,就是把字符串类型转化为你所需要的类型。
在MVC框架中,表示层数据处理分为两个方法:客户端输入数据,服务端输出数据;客户端输入数据需要进行类型转换才能确保我们的数据类型是正确的,服务端输出数据无需经过类型转换。
简单说就是:
在javaweb中,当你在jsp页面提交一个username到servlet中,你是否在通过request.getParameter("username")去获取数据;但是
如果是一个Date时间类型呢?你是否要先指定时间的转换格式,然后再根据request.getParameter("date");获取数据之后再去转换呢?但是,你想过没有?如果是多个页面请求数据的话,那你每次打getParameter();这个方法,累吗?你不累,程序都累了。所以,Struts2 为我们提供了一种类型转换器,只需要编写固定的操作就能得到你想要的数据,简单说来,就是把表单的数据赋值给实体类。
1.2、类型转换器简单介绍
1.2.1、类型转换器需要继承DefaultTypeConverter类,需要重写该类的convertType方法。
convertType方法的作用:
1、负责对类型的转换,不过这种转换是双向的,我们可以通过判断数据的类型判断转换的方向
2、该方法有三个参数:
context:是类型转换环境的上下文
value: 是需要转换的参数(随转换方向不同,如果字符串向实例转换时,它是字符串数组;如果实例字符串转换时,它是实例)
toType: 是转换后的目标参数
1.2.2、当然,你也可以继承StrutsTypeConverter是,它是Struts2为我们简化的类型转换器,是DefaultTypeConverter的子类,默认产生两个方法,更加明确的告诉你你要在哪个方法进行转换,这样就不用跟继承DefaultTypeConverter类一样,通过convertType方法里的参数toType每次去判断。继承StrutsTypeConveter该类比较简单。这里两种继承都有说到。
二、类型转换器
2.1、类型转换器有两种:局部类型转换器和全局类型转换器,就字面上的意思一样,全局和局部的。
关于类型转换器的注册方式有三种:
1、局部类型转换器仅仅对某个Action起作用
2、全局类型转换器对所有Action特定类型的属性都会起作用
3、我们可以通过注解的方式来生成类型转换器(JDK1.5以上的注解)
2.2、局部类型转换器:
新建实体类userbean:
package com.TypeConverter;
import java.util.Date;
public class userbean {
    private String uname;
    private String upwd;
    private int uage;
    private Date udate;
    public String getUname() {
        return uname;
    }
    public void setUname(String uname) {
        this.uname = uname;
    }
    public String getUpwd() {
        return upwd;
    }
    public void setUpwd(String upwd) {
        this.upwd = upwd;
    }
    public int getUage() {
        return uage;
    }
    public void setUage(int uage) {
        this.uage = uage;
    }
    public Date getUdate() {
        return udate;
    }
    public void setUdate(Date date) {
        this.udate = date;
    }
    public userbean(){
}
    public userbean(String uname, String upwd, int uage, Date udate) {
        this.uname = uname;
        this.upwd = upwd;
        this.uage = uage;
        this.udate = udate;
    }
}   
建立jsp视图:这里的是Test.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>
<h2>请输入您的注册信息</h2>
<form action="user">
<!-- 注意:name的名字必须是userbean1,跟useraction里面属性名字一样 -->
<label>用户名:</label><input type="text" name="userbean1"><br/>
<label>密 码:</label><input type="text" name="userbean1"><br/>
<label>年 龄:</label><input type="text" name="userbean1"><br/>
<label>生 日:</label><input type="text" name="userbean1"><br/>
<input type="submit">
</form>
</body>
</html>
在struts.xml配置信息。我们只需要配置这个

这里的<result name="input">是错误机制处理程序,就是说当页面跳转错误或者异常问题的时候,会跳转到你指定的页面,这里笔者是让其自动跳转到原来的页面。
我们可以定义一个局部的错误处理消息提示,这里笔者没有做,但是可以了解下:
新建useraction.properties,放在同级目录下,
这里的useraction是值你继承ActionSupport的类,然后往该文件中写入:
invalid.fieldvalue.属性名=提示消息(其中属性名可以是:uname或者upwd等)
当类型转换错误就会跳转,你可以在页面上使用JSTL打印,如:
<%@ taglib uri="/struts-tags" prefix="s"%>
然后使用<s:fielderror/>该标签显示出你的提示消息
新建useraction类,继承ActionSupport。
package com.TypeConverter; import com.opensymphony.xwork2.ActionSupport; //使用的是局部的类型转化器
public class useraction extends ActionSupport {
private userbean userbean1;
public userbean getUserbean1() {
return userbean1;
}
public void setUserbean1(userbean userbean1) {
this.userbean1 = userbean1;
}
public String execute(){
System.out.println(userbean1.getUname());
System.out.println("useraction");
return SUCCESS;
}
}
重点来了:我们需要新建类去继承DefaultTypeConverter,然后重写里面的方法。
这里的类名是TestType
package com.TypeConverter; import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Map; import com.opensymphony.xwork2.conversion.impl.DefaultTypeConverter; //
public class TestType extends DefaultTypeConverter {
@Override
public Object convertValue(Map<String, Object> context, Object value, Class toType) {
//需要将字符串向userbean类型转换时
if(toType==userbean.class){
//系统的请求参数是一个字符串数组
System.out.println("TestType");
String params[] = (String[]) value;
userbean user = new userbean();
user.setUname(params[0]);
user.setUpwd(params[1]);
user.setUage(Integer.parseInt(params[2]));
SimpleDateFormat s = new SimpleDateFormat("yyyy-MM-dd");
try {
user.setUdate(s.parse(params[3]));
} catch (ParseException e) {
e.printStackTrace();
}
return user;
}else if(toType==String.class){
userbean user = (userbean) value;
System.out.println("--------------------");
return "<"+user.getUname()+">";
}
System.out.println("--------------------");
return null;
}
}
在这里笔者遇到一点小问题:就是使用
SimpleDateFormat s = new SimpleDateFormat("yyyy-MM-dd");
s.format(param[3]);
一直报错误:Unexpected Exception caught setting 'userbean1' on 'class com.TypeConverter.useraction: Error setting expression 'userbean1' with value ['admin', '123', '20', '1992-1-2', ],直到我把userbean中的udate类型改为Date类型才能够正常走,并且把s.format换成s.parse(param[3])。疑惑。
笔者测试代码走的顺序:

先走继承DefaultTypeConverter类的TestType,然后跳转到useraction类中的execute方法。
在处理类型转换的时候可能是ajax直接提交的可能value就是一个字符串,不是字符串数字了,所以最好增加一个判断
package com.xuan; import ognl.DefaultTypeConverter; import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map; public class DateConverter extends DefaultTypeConverter {
private static final DateFormat[] ACCEPT_DATE_FORMATS = {
new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"),
new SimpleDateFormat("yyyy-MM-dd HH:mm"),
new SimpleDateFormat("yyyy-MM-dd"),
new SimpleDateFormat("dd/MM/yyyy"),
new SimpleDateFormat("yyyy/MM/dd")}; //支持转换的日期格式 @SuppressWarnings({"rawtypes"})
@Override
public Object convertValue(Map context, Object value, Class toType) {
if (toType == Date.class) { //浏览器向服务器提交时,进行String to Date的转换
String dateString = "";
String[] str = {};
if (value instanceof String[]) {
//通过from直接提交的时候可能是一个对象,里面有对应多个值,所以用字符串数组
str = (String[]) value;
}else {
//通过ajax提交的时候
dateString = (String) value;
}
dateString = str[0];
for (DateFormat format : ACCEPT_DATE_FORMATS) {
try {
return format.parse(dateString);//遍历日期支持格式,进行转换
} catch (Exception e) {
continue;
}
}
return null;
}return null;
}
}
也可以直接在bean的setXXX里面设置
    public void setPay_time(Object pay_time) {
        if (pay_time instanceof String[]) {
            String time = ((String[]) pay_time)[0];
            try {
                this.pay_time = DateUtils.getDateFromString(time);
            } catch (Exception e) {
                e.printStackTrace();
                this.pay_time = new Date();
            }
        } else if (pay_time instanceof Date) {
            this.pay_time = (Date) pay_time;
        }
    }
注意:我们还需要在建一个文件,告诉程序说,我们要把数据填充到类是哪一个?新建Actionname-conversion.properties
其中-conversion.properties是固定的,需要改变只是Actionname(表示继承ActionSupport的类,这里是useraction。对应struts.xml的class)
新建useraction-conversion.properties。放在同级目录下:

该文件的内容有:

这里的userbean1是你在useraction中实例化的名字。
后面的TestType是你继承DefaultTypeConverter类的名字。这里是TestType
代码运行结果如下:
Test.jsp界面

target.jsp界面效果:

target.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>
用户名:${userbean1.uname }<br/>
密码:${userbean1.upwd }<br/>
年龄:${userbean1.uage }<br/>
生日:${userbean1.udate }<br/>
</body>
</html>
2.3、全局类型转换
2.3.1、对指定的类型的全部属性有效。基本操作一样,只是有一点不同,properties文件放的位置和名字不同。
新建jsp页面,页面名:Test1.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>
<h2>使用全局的类型转换器</h2>
<form action="Stubean">
<label>用户名:</label><input type="text" name="stu"><br/>
<label>年 龄:</label><input type="text" name="stu"><br/>
<input type="submit">
</form>
</body>
</html>
新建实体类StuBean:
package com.TypeConverter.global;
public class StuBean {
    private String uname;
    private int uage;
    public String getUname() {
        return uname;
    }
    public void setUname(String uname) {
        this.uname = uname;
    }
    public int getUage() {
        return uage;
    }
    public void setUage(int uage) {
        this.uage = uage;
    }
}
配置struts.xml

新建StuAction类继承ActionSupport
package com.TypeConverter.global; import com.opensymphony.xwork2.ActionSupport; //使用全局的类型转换器
//执行顺序:类型转换器——>execute public class StuAction extends ActionSupport {
private StuBean stu; public StuBean getStu() {
return stu;
} public void setStu(StuBean stu) {
this.stu = stu;
} public String execute(){
System.out.println("StuAction");
System.out.println(stu.getUname());
return SUCCESS;
}
}
新建GlobalTypeConverter类继承StrutsTypeConverter,这里的StrutsTypeConverter是简化类型转换器,它是DefaultTypeConverter的子类。以下是代码:
package com.TypeConverter.global;
import java.util.Map;
import org.apache.struts2.util.StrutsTypeConverter;
public class GlobalTypeConverter extends StrutsTypeConverter {
    //转化为javabean对象
    @Override
    public Object convertFromString(Map arg0, String[] arg1, Class arg2) {
        System.out.println("Global...");
        StuBean stu = new StuBean();
        stu.setUname(arg1[0]);
        stu.setUage(Integer.parseInt(arg1[1]));
        return stu;
    }
    //转化为String对象
    @Override
    public String convertToString(Map arg0, Object arg1) {
        StuBean s = (StuBean)arg1;
        return s.getUname()+"!!";
    }
}
注意:全局与局部不同的地方在于properties文件名和放的位置不同,全局的文件名为:xwork-conversion.properties
位置在:

放在classes之下,有些没有classes文件,需要自己创建。
内容为:

前面的是该StuBean实体类的路径,后面的是继承StrutsTypeConverter类的类型转换器
如果要设置错误处理消息的话,我们可以添加一行代码,当页面出错的时候提示,这里笔者没有做,但是可以了解,添加代码为:
xwork.default.invalid.fieldvalue=提示消息
显示效果上面有介绍。如果你需要的话可以使用。
代码运行结果为:
Test1.jsp界面

target1.jsp界面

有谁能介绍一个录制操作的软件,谢谢。
以上就是Struts2 类型转换器的基本知识,有不足的请下方留言。谢谢。
struts2数据类型转换DefaultTypeConverter的更多相关文章
- struts2数据类型转换详解
		
Web应用程序的交互都是建立在HTTP之上的,互相传递的都是字符串.也就是说服务器接收到的来自用户的数据只能是字符串或者是字符数组,而在Web应用的对象中,往往使用了多种不同的类型,如整数(int). ...
 - Struts2数据类型转换之批量数据转换
		
前面我们实现了从字符串到User对象的转换.如果表单中有多个User数据,我们可以批量转换. 我们把input.jsp修改为: <h1>使用分号隔开username password< ...
 - Struts2(接受表单参数)请求数据自动封装和数据类型转换
		
Struts2请求数据自动封装: (1)实现原理:参数拦截器 (2)方式1:jsp表单数据填充到action中的属性: 普通的成员变量,必须给set,get可以不给的. 注意点,A ...
 - Struts2中的数据类型转换
		
Struts2对数据的类型转换 一.Struts2中自带类型转换拦截器 Struts2内部提供了大量转换器,用来完成数据类型转换的问题,有如下 * boolean 和 Boolean * char和 ...
 - struts2学习笔记(4)——数据类型转换
		
回过头来看昨天的那个例子. 在昨天的例子中,只转换了一个Point类,如果想转换多个Point类怎么办呢?在昨天的例子上面做一个小的修改. 首先在input.jsp页面中修改几个输入框. <s: ...
 - Struts2(二)之封装请求正文、数据类型转换、数据验证
		
一.封装请求正文到对象中(重点) 1.1.静态参数封装 在struts.xml文件中,给动作类注入值,使用的是setter方法 1.2.动态参数封装 通过用户表单封装请求正文参数 1.2.1.动作类作 ...
 - Struts2自定义类型转换,和处理类型转换错误
		
Struts2自定义类型转换: 从前台接受到的类型全部是字符串,Struts2自带的一些基本类型转换有时不能满足我们的特别需要,如:日期字符串输入格式,还有一些自定义的类,直接传到后台,我们需要一些自 ...
 - 关于Struts2的类型转换详解
		
详细出处参考:http://www.jb51.net/article/35465.htm 一.类型转换的意义 对于一个智能的MVC框架而言,不可避免的需要实现类型转换.因为B/S(浏览器/服务器)结构 ...
 - Struts2之类型转换
		
jsp提交的数据全部是String类型,Struts2也是通过request.getParameter(name)取得String类型的数据,并通过拦截器将String转换成各种类型的数据,然后通过g ...
 
随机推荐
- OnMouseWheel的通常处理
			
BOOL CMainWindow::OnMouseWheel(UINT nFlags, short zDelta, CPoint point) { BOOL bUp = TRUE; int nDelt ...
 - 2-Perl 环境安装
			
1.Perl 环境安装在我们开始学习 Perl 语言前,我们需要先安装 Perl 的执行环境.Perl 可以在以下平台下运行:Unix (Solaris, Linux, FreeBSD, AIX, H ...
 - 异常-Throwable的几个常见方法
			
package cn.itcast_04; import java.text.ParseException; import java.text.SimpleDateFormat; import jav ...
 - Springboot Hikari Centos 首次连数据库很慢
			
前言: springboot项目默认使用了hikari作为数据库连接池,在开发机器上一切正常. 但是把程序部署到Centos7 x64上之后发现,每次首页登录的时候都要停顿几十秒. 于是,在程序启动后 ...
 - cube打包后css顺序错误
			
先说下解决办法: 把import {...} from cube-ui放在 import App from './App.vue'的前面 不然会产生如下错误 正确的顺序
 - vue入门:(class与style绑定)
			
对象语法 数组语法 一.对象语法 1.1对象语法绑定HTML Class 语法:v-bind:class="{'className1':boolean1,'className2':boole ...
 - JS和JS是IE上JavaScript或JScript的缩写。
			
JS和JS是IE上JavaScript或JScript的缩写.javascript是所有浏览器的开放式标准脚本语言JScript是微软自己的开放式脚本语言标准,只有微软的IE浏览器遵循.JScript ...
 - ConfigurableApplicationContext
			
转自:https://blog.csdn.net/weixin_39165515/article/details/77169231 此接口结合了所有ApplicationContext需要实现的接口. ...
 - Python 之 random模块
			
Python中的random模块用于生成随机数.1.random.random() #用于生成一个0到1的随机浮点数:0<= n < 1.0>>> random.ran ...
 - Nginx 无法重启
			
报错如下 Starting nginx... nginx (pid)already running. 重启nginx时,说多个进程已存在,,, 执行 ps -ef | grep nginx 发现 有多 ...