- 浏览: 133735 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
Mr_sqw:
bonny 写道这个问题我大 ...
用if、Exception还是assert? ——看JavaEye论坛帖子:《面试题:用Exception异常还是if判断》的感想 -
Mr_sqw:
IcedCoffee 写道awfe 写道Checked Exc ...
用if、Exception还是assert? ——看JavaEye论坛帖子:《面试题:用Exception异常还是if判断》的感想 -
jinianjun:
表示感谢!@
CSS选择器、优先级与匹配原理 -
yuming805796:
986065785@qq.com
jQuery学习之:jqGrid表格插件——从Struts2获得数据 -
yuming805796:
你好,能共享下吗,代码没分页功能,,少了点东西!
jQuery学习之:jqGrid表格插件——从Struts2获得数据
好久没有写Blog了,最近似乎变懒了。今天上班没有很多事,于是把之前遇到的一个问题记录下来。
Web开发会涉及到很多类型转换的情况。我们知道,页面中的一切值都是字符串类型,而到后台,我们需要的可能是其他各种类型;同时,页面显示也是字符串类型。这就涉及到Web中基本的类型转换问题:从String转换为各种类型与从各种类型转换为String类型。
在Java Web开发中,进行上述转换一般有以下几种:
1、在Servlet中,这一切的转换我们得自己写代码完成;
2、在Struts1.x中,我们通过apache commons-beanutils中的converters来帮助完成这些事情;
3、在Struts2中,使用的则是基于ongl的类型转换;
……
由于类型转换的通用性,因而Web框架都会实现大多数类型的转换功能,而不需要程序员编码实现。然而,对于java.util.Date这种类型的转换,各大框架似乎做得都不尽如人意。如:在Struts1.x中,该类型的转换就会有问题,很多人建议使用java.sql.Date这种类型来解决日期转换的问题(实际上可以自定义一个类型转换器来解决该问题)。在Struts2中,这个问题似乎依然存在,也许你从来没有遇到过。的确,一般人确实不会遇到,会觉得没有这个问题。下面就是我遇到的问题与解决方法。
日期类型的转换,Web开发中几乎都会遇到,我现在做得项目也不例外。在开发的过程中,也许就像你一样,我没有对日期类型的转换做任何特殊的处理,而且Struts2也很好的帮我完成了转换。然而同事测试的时候却出现了一个“莫名其妙”的问题:输入一个常用格式的日期类型yyyy-MM-dd,到后台却报错:找不到对应的set方法——setEffDate(Ljava.lang.String)。的确,程序中只有setEffDate(java.util.Date)这个方法,没有setEffDate(Ljava.lang.String)这个方法。从Ljava.lang.String可以看出,传到后台的String类型并没有转换成Date类型,因而报错。
一开始,我以为是我UT没做好,于是在自己的电脑上模拟同事的测试,结果一点问题也没有。这就奇怪了。经过自己分析,觉得可能是IE浏览器的原因,因为同事测试用的是IE,而我用的是FireFox。于是在自己的机子上用IE测试,同时在同事机子上用FireFox测试,结果这两次测试都没有出现上面的问题。虽然没有找到问题所在,但可以初步肯定:IE的问题,但似乎又不完全是IE的问题,因为在我的电脑上的IE(版本与同事一样,都是IE6)没有上述问题。这就奇怪了,是什么问题呢,真是百思不得其解。
这个时候,我想起了之前遇到的一个不解得情况:从后台获得的日期类型在页面上显示时,跟上面情况一样,在同事的IE中,日期显示的格式竟然是:yyyy-MM-ddTHH:mm:ss。多了一个T,真是莫名其妙,而且只在同事的IE浏览器中出现(当时解决方法是在JS中将'T'替换为空格,没有去深究,但现在必须的深究了)。yyyy-MM-ddTHH:mm:ss这种日期格式有吗?于是查询JDK:在SimpleDateFormat类中找到了该日期格式,这种格式是“美国语言环境中日期和时间的模式之一”。原来还真有这种格式。竟然这是美国语言中使用的日期格式,而Struts2是美国人开发的,也许跟这个有点关系。于是查看Struts2中关于Date类型转换的源码。
在XWorkBasicConverter类中
其中SHORT、MEDIUM、LONG在JDK中的DateFormat类中有说明。
从这句DateFormat rfc3399 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");可以看出,Struts2硬编码使用了这样一种格式。然而,Struts2中这种格式是放在最后的,为啥只有同事的IE浏览器测试时使用的是这种格式呢?(在调试时,用同时IE,日期输入中按这种格式输入,还真的没有问题了)这说明,同时的电脑中,前面六种DateFormat都没有匹配,查看DateFormat中关于SHORT、MEDIUM、LONG的说明,可以知道,对于yyyy-MM-dd这种日期类型,在英语语言中是没法匹配的,由于Struts2匹配日期时,使用了Locale,可见,同事的IE浏览器默认的语言环境是英语。一经查看,果然如此,把中文设置为默认语言环境,再测试,没问题了。终于知道了原因。
个人觉得,Struts2中,最后一种日期模式写死成美国标准,不是很好。
针对这个问题,我们没法要求客户一定设置中文为默认浏览器的语言环境。因而对于Date类型的转换,可以自己定义一个转换器。以下来自http://www.iteye.com/wiki/struts2/1365-passing-parameters-in-struts2 中的一个类型转换器定义(不适合国际化的环境),如需要,你可以定义自己的转换器:
可以将该转换器注册为全局的:在classpath下建立xwork-conversion.properties文件,内容为:java.util.Date=你的类型转换器的完整限定类名
自此,该问题圆满解决。
客气了
Web开发会涉及到很多类型转换的情况。我们知道,页面中的一切值都是字符串类型,而到后台,我们需要的可能是其他各种类型;同时,页面显示也是字符串类型。这就涉及到Web中基本的类型转换问题:从String转换为各种类型与从各种类型转换为String类型。
在Java Web开发中,进行上述转换一般有以下几种:
1、在Servlet中,这一切的转换我们得自己写代码完成;
2、在Struts1.x中,我们通过apache commons-beanutils中的converters来帮助完成这些事情;
3、在Struts2中,使用的则是基于ongl的类型转换;
……
由于类型转换的通用性,因而Web框架都会实现大多数类型的转换功能,而不需要程序员编码实现。然而,对于java.util.Date这种类型的转换,各大框架似乎做得都不尽如人意。如:在Struts1.x中,该类型的转换就会有问题,很多人建议使用java.sql.Date这种类型来解决日期转换的问题(实际上可以自定义一个类型转换器来解决该问题)。在Struts2中,这个问题似乎依然存在,也许你从来没有遇到过。的确,一般人确实不会遇到,会觉得没有这个问题。下面就是我遇到的问题与解决方法。
日期类型的转换,Web开发中几乎都会遇到,我现在做得项目也不例外。在开发的过程中,也许就像你一样,我没有对日期类型的转换做任何特殊的处理,而且Struts2也很好的帮我完成了转换。然而同事测试的时候却出现了一个“莫名其妙”的问题:输入一个常用格式的日期类型yyyy-MM-dd,到后台却报错:找不到对应的set方法——setEffDate(Ljava.lang.String)。的确,程序中只有setEffDate(java.util.Date)这个方法,没有setEffDate(Ljava.lang.String)这个方法。从Ljava.lang.String可以看出,传到后台的String类型并没有转换成Date类型,因而报错。
一开始,我以为是我UT没做好,于是在自己的电脑上模拟同事的测试,结果一点问题也没有。这就奇怪了。经过自己分析,觉得可能是IE浏览器的原因,因为同事测试用的是IE,而我用的是FireFox。于是在自己的机子上用IE测试,同时在同事机子上用FireFox测试,结果这两次测试都没有出现上面的问题。虽然没有找到问题所在,但可以初步肯定:IE的问题,但似乎又不完全是IE的问题,因为在我的电脑上的IE(版本与同事一样,都是IE6)没有上述问题。这就奇怪了,是什么问题呢,真是百思不得其解。
这个时候,我想起了之前遇到的一个不解得情况:从后台获得的日期类型在页面上显示时,跟上面情况一样,在同事的IE中,日期显示的格式竟然是:yyyy-MM-ddTHH:mm:ss。多了一个T,真是莫名其妙,而且只在同事的IE浏览器中出现(当时解决方法是在JS中将'T'替换为空格,没有去深究,但现在必须的深究了)。yyyy-MM-ddTHH:mm:ss这种日期格式有吗?于是查询JDK:在SimpleDateFormat类中找到了该日期格式,这种格式是“美国语言环境中日期和时间的模式之一”。原来还真有这种格式。竟然这是美国语言中使用的日期格式,而Struts2是美国人开发的,也许跟这个有点关系。于是查看Struts2中关于Date类型转换的源码。
在XWorkBasicConverter类中
private Object doConvertToDate(Map<String, Object> context, Object value, Class toType) { Date result = null; if (value instanceof String && value != null && ((String) value).length() > 0) { String sa = (String) value; Locale locale = getLocale(context); DateFormat df = null; if (java.sql.Time.class == toType) { df = DateFormat.getTimeInstance(DateFormat.MEDIUM, locale); } else if (java.sql.Timestamp.class == toType) { Date check = null; SimpleDateFormat dtfmt = (SimpleDateFormat) DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.MEDIUM, locale); SimpleDateFormat fullfmt = new SimpleDateFormat(dtfmt.toPattern() + MILLISECOND_FORMAT, locale); SimpleDateFormat dfmt = (SimpleDateFormat) DateFormat.getDateInstance(DateFormat.SHORT, locale); SimpleDateFormat[] fmts = {fullfmt, dtfmt, dfmt}; for (SimpleDateFormat fmt : fmts) { try { check = fmt.parse(sa); df = fmt; if (check != null) { break; } } catch (ParseException ignore) { } } } else if (java.util.Date.class == toType) { Date check = null; DateFormat[] dfs = getDateFormats(locale); for (DateFormat df1 : dfs) { try { check = df1.parse(sa); df = df1; if (check != null) { break; } } catch (ParseException ignore) { } } } //final fallback for dates without time if (df == null) { df = DateFormat.getDateInstance(DateFormat.SHORT, locale); } try { df.setLenient(false); // let's use strict parsing (XW-341) result = df.parse(sa); if (!(Date.class == toType)) { try { Constructor constructor = toType.getConstructor(new Class[]{long.class}); return constructor.newInstance(new Object[]{Long.valueOf(result.getTime())}); } catch (Exception e) { throw new XWorkException("Couldn't create class " + toType + " using default (long) constructor", e); } } } catch (ParseException e) { throw new XWorkException("Could not parse date", e); } } else if (Date.class.isAssignableFrom(value.getClass())) { result = (Date) value; } return result; } private DateFormat[] getDateFormats(Locale locale) { DateFormat dt1 = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.LONG, locale); DateFormat dt2 = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.MEDIUM, locale); DateFormat dt3 = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, locale); DateFormat d1 = DateFormat.getDateInstance(DateFormat.SHORT, locale); DateFormat d2 = DateFormat.getDateInstance(DateFormat.MEDIUM, locale); DateFormat d3 = DateFormat.getDateInstance(DateFormat.LONG, locale); DateFormat rfc3399 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); DateFormat[] dfs = {dt1, dt2, dt3, rfc3399, d1, d2, d3}; //added RFC 3339 date format (XW-473) return dfs; }
其中SHORT、MEDIUM、LONG在JDK中的DateFormat类中有说明。
从这句DateFormat rfc3399 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");可以看出,Struts2硬编码使用了这样一种格式。然而,Struts2中这种格式是放在最后的,为啥只有同事的IE浏览器测试时使用的是这种格式呢?(在调试时,用同时IE,日期输入中按这种格式输入,还真的没有问题了)这说明,同时的电脑中,前面六种DateFormat都没有匹配,查看DateFormat中关于SHORT、MEDIUM、LONG的说明,可以知道,对于yyyy-MM-dd这种日期类型,在英语语言中是没法匹配的,由于Struts2匹配日期时,使用了Locale,可见,同事的IE浏览器默认的语言环境是英语。一经查看,果然如此,把中文设置为默认语言环境,再测试,没问题了。终于知道了原因。
个人觉得,Struts2中,最后一种日期模式写死成美国标准,不是很好。
针对这个问题,我们没法要求客户一定设置中文为默认浏览器的语言环境。因而对于Date类型的转换,可以自己定义一个转换器。以下来自http://www.iteye.com/wiki/struts2/1365-passing-parameters-in-struts2 中的一个类型转换器定义(不适合国际化的环境),如需要,你可以定义自己的转换器:
public class DateConverter extends DefaultTypeConverter { private static final Logger logger = Logger.getLogger(DateConverter.class); private static final String DATETIME_PATTERN = "yyyy-MM-dd HH:mm:ss"; private static final String DATE_PATTERN = "yyyy-MM-dd"; private static final String MONTH_PATTERN = "yyyy-MM"; /** * Convert value between types */ @SuppressWarnings("unchecked") public Object convertValue(Map ognlContext, Object value, Class toType) { Object result = null; if (toType == Date.class) { result = doConvertToDate(value); } else if (toType == String.class) { result = doConvertToString(value); } return result; } /** * Convert String to Date * * @param value * @return */ private Date doConvertToDate(Object value) { Date result = null; if (value instanceof String) { result = DateUtils.parseDate((String) value, new String[] { DATE_PATTERN, DATETIME_PATTERN, MONTH_PATTERN }); // all patterns failed, try a milliseconds constructor if (result == null && StringUtils.isNotEmpty((String)value)) { try { result = new Date(new Long((String) value).longValue()); } catch (Exception e) { logger.error("Converting from milliseconds to Date fails!"); e.printStackTrace(); } } } else if (value instanceof Object[]) { // let's try to convert the first element only Object[] array = (Object[]) value; if ((array != null) && (array.length >= 1)) { value = array[0]; result = doConvertToDate(value); } } else if (Date.class.isAssignableFrom(value.getClass())) { result = (Date) value; } return result; } /** * Convert Date to String * * @param value * @return */ private String doConvertToString(Object value) { SimpleDateFormat simpleDateFormat = new SimpleDateFormat(DATETIME_PATTERN); String result = null; if (value instanceof Date) { result = simpleDateFormat.format(value); } return result; } }
可以将该转换器注册为全局的:在classpath下建立xwork-conversion.properties文件,内容为:java.util.Date=你的类型转换器的完整限定类名
自此,该问题圆满解决。
评论
3 楼
polaris1119
2010-10-25
HK.Night 写道
谢谢啦,正好解决了我的问题!
客气了
2 楼
HK.Night
2010-10-25
谢谢啦,正好解决了我的问题!
1 楼
cpy9981
2010-08-28
谢谢你的文章。struts2时间转换问题又有一种认识了
发表评论
-
深入理解String——之前六个题目答案解析
2010-10-20 14:51 1153此前polaris给出了六道关于String的题目,本来没有打 ... -
Struts2 Error filterStart异常的解决方法总结
2010-09-27 01:00 1455今天一位网友让polaris帮忙解决一些jqGrid的问 ... -
几个笔试题目(2010-09-18)
2010-09-18 23:46 2977感谢大家,一些问题 ... -
用if、Exception还是assert? ——看JavaEye论坛帖子:《面试题:用Exception异常还是if判断》的感想
2010-08-25 23:31 2529用if、Exception还是assert? ... -
《Java并发编程实践》学习笔记之二:线程安全性(thread-safe)
2010-08-24 13:11 3324《Java并发编程实践 ... -
《Java并发编程实践》学习笔记之一:基础知识
2010-08-20 23:44 972《Java并发编程实践 ... -
Java环境变量配置问题
2010-08-14 13:17 1177昨晚在写《第三篇 打造 ... -
第二篇 多线程的使用——中断线程详解(Interrupt)
2010-08-11 15:50 2567在上篇文章《多线程的使用——Thread类和Runnab ... -
第一篇 多线程的使用——Thread类和Runnable接口
2010-08-10 16:19 1614进行并发程序设计,首先必须对多线程有足够的了解。在JAV ... -
JAVA并发程序设计序列文章
2010-08-10 16:15 1014在程序设计中,很多时候都会涉及到并发性问题。在一般的操作 ... -
【转】java反射与内省(Introspector)
2010-02-02 21:22 925一、java反射机制 JAVA反射机制是在运行状态中 ... -
【转】Java EE 6数据验证新框架:Bean验证
2010-01-14 21:17 1048【51CTO精选译文】对于Sun最新发布的Java EE 6平 ... -
【转】面向Java EE 6平台的上下文和依赖性注入
2010-01-14 21:16 1155【51CTO精选译文】Java EE 6平台的发布带来了几个新 ... -
【转】Java EE 6引入的三大新技术之JAX-RS
2010-01-12 22:50 1239【51CTO精选译文】上周我们介绍了Java EE 6平台的主 ... -
【转】Java EE 6总览:平台的主要目标
2010-01-06 19:58 916【51CTO精选译文】Java EE ...
相关推荐
1. 使用内置的类型转换器:Struts2已经内置了一些常见的类型转换器,如String到Integer、Date等。当Struts2发现需要的转换器时,会自动查找并使用。 2. 自定义类型转换器:如果内置的转换器不能满足需求,可以创建...
这篇名为“Struts2 Date转换问题”的博文可能探讨了以下关键知识点: 1. **类型转换**:Struts2中,Action类的属性与用户表单提交的数据进行绑定时,会自动尝试将请求参数转化为相应的类型,包括Date。这个过程由`...
Struts2是一个流行的Java web开发框架,其核心是Action,而类型转换是Struts2处理用户输入数据的一个重要环节。Struts2内置了多种类型转换,可以将HTTP请求中的字符串数据转换为各种基本类型和复杂类型,如日期、...
Struts2是一个强大的MVC框架,它在处理Web应用程序时提供了许多便利,其中包括类型转换功能。类型转换是将用户输入的数据自动转化为服务器端处理所需的类型,这样可以避免手动转换带来的繁琐工作。本篇文章将深入...
struts2学习笔记3数据类型转换struts2学习笔记3数据类型转换struts2学习笔记3数据类型转换struts2学习笔记3数据类型转换struts2学习笔记3数据类型转换struts2学习笔记3数据类型转换struts2学习笔记3数据类型转换
本实例主要探讨了在Struts2中进行类型转换的三种方法:局部类型转换、全局类型转换以及大量数据类型的转换。对于初学者来说,理解并掌握这些转换方式至关重要,因为它们能够帮助我们处理用户输入的数据,并将其转化...
Struts2提供了一种机制,能够自动将这些字符串转换为相应的数据类型,如Integer、Date、Boolean等。 2. **Struts2类型转换器** Struts2的核心组件`ValueStack`负责管理Action对象,并使用`ConversionService`接口...
这个实例项目展示了如何在实际应用中结合Struts2、国际化、类型转换以及Struts2自定义标签来实现用户管理功能,包括用户数据的增删改查。 首先,我们来看Struts2的核心概念。Struts2作为MVC框架,它负责处理HTTP...
例如,如果你有一个`java.util.Date`类型的属性,但用户输入了一个无效的日期字符串,Struts2在尝试将字符串转换为日期时会抛出异常。 2. **Struts2的类型转换机制** Struts2使用OGNL(Object-Graph Navigation ...
本练习主要关注如何在Struts2中实现自定义的数据类型转换,以满足特定业务需求。 首先,我们需要了解Struts2的数据转换机制。当用户提交表单数据时,Struts2会通过ActionContext获取到这些数据,并尝试将其转换为...
Struts2是一个强大的Java web框架,它为开发者提供了丰富的功能,包括类型转换、拦截器和校验机制。本文将深入探讨这些关键知识点,并通过实际例子来帮助你理解它们的工作原理和应用。 首先,我们来看看**类型转换...
在实际开发中,Struts2的类型转换有时会遇到一些问题,例如空值处理、格式错误等。对于空值,Struts2会提供默认值或允许字段为空;对于格式错误,Struts2会抛出`ConversionException`,开发者可以捕获并处理这个异常...
然而,有一个常见的问题出现在尝试初始化`java.util.Date`类型的字段时,即“Struts的form不能初始化java.util.Date类型”。这个问题通常是由于日期对象的序列化和反序列化机制导致的,以及Struts默认的数据绑定策略...
### Struts2自定义类型转换:深入解析与实践 #### 引言 在Web开发中,数据类型转换是一项常见的需求,特别是在用户输入的数据与后端处理的数据类型不一致时。Struts2框架提供了强大的类型转换机制,允许开发者...
Struts2提供了一系列内置的类型转换器,可以处理基本类型如`int`、`double`、`boolean`以及Java集合类型如`List`、`Map`等。此外,还支持日期和时间的转换,如`java.util.Date`。 4. **类型转换的优先级** 类型...
这个过程涉及到了类型转换,Struts2内置了一套转换器机制,能够自动处理基本类型和一些常见类型的转换。然而,对于如Date这样的复杂类型,需要自定义转换器来处理。 创建自定义类型转换器的步骤如下: 1. **定义...
熟悉和掌握Struts2自定义类型转换。 熟悉和掌握Struts2内建校验的操作方法 实验环境与设备: 已经接入局域网的网络实验室,机器上装有IE浏览器等; strtus2.5.8 实验内容: (1) 编写一个...
在Struts2中,类型转换和数据校验是两个关键的特性,它们确保了用户输入的数据能够准确无误地被处理和验证,从而提高了应用的安全性和可靠性。 **类型转换(Type Conversion)** 在Struts2中,类型转换是自动进行...