今天跑程序的时候莫名其妙的出现了下面的一个异常:
java.lang.NoSuchMethodException:com.ca.agent.model.mybatis.ApprovalInforCangra.setSubDate([Ljava.lang.String;)
这类异常信息在以前是处理过的,按照以前的思路在eclipse的调试模式下看看具体的情况,不过这次比较奇怪,根本没进入到对应的Action类中就抛出了此异常信息,进一步查找发现,在调用拦截器方法的时候就抛出了此异常信息,还有没有想明白的就是对应的功能我是测试过好多次的,之前这一块是没有任何问题的!不过现在事实是却抛出了异常信息,一定是那里出错了,到底是那里哪?查找了大半个下午也没找到对应的解决方案,应该是我忽略了什么地方,一时半会可能也想不起来了,找位同事帮忙吧!于是找来同事G来帮忙,最终找到了问题的原因!Struts2默认可支持String和Date的转换,但仅支持短格式和本地化有关日期格式转换,前几天我将自己的IE浏览器的语言环境改成了英语的!而对于yyyy-MM-dd这种日期类型,在英语语言中是没法匹配的,由于Struts2匹配日期时,使用了Locale,所以使用英文的语言环境,就导致了此问题的出现,把中文设置为默认语言环境后,再测试,没问题了!
转载自:
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; }
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; } }
参看: