解决axis2处理java.util.Date类型对象时丢弃时间部分的问题
2015-09-21 09:46
1041 查看
我目前在做的一个项目以axis2为webservice框架,客户端和服务器端要传输很多复杂对象,在这方面,axis2做得不错,基本满足了我的需要,但当我把客户端提供给要使用的同事时,同事发现了一个问题:就是所有java.util.Date类型的对象,不论从服务器发到客户端的还是从客户端发送到服务器的,都只剩下日期部分(年/月/日),时间部分(时/分/秒)则被抹掉了。。。百思不得其姐啊。。。
这是几个月前的事儿了,那时,这个问题并不影响整个系统的开发,所以一直搁置在那里,最近整个系统接近完成了。做为一个重要但不紧急的问题,我又重新开始研究axis2的代码,着手解决这个问题。
很多人遇到这个问题,把这归结为axis2的bug,但我认为,这是axis2遵循WSDL规范设计的,这个设计的确有些反人类,异于通常技术人员对Date的理解和使用习惯,其实也可以说我们是对webservice的理解不足导致,对于这个问题的理解我也是一点一点加深的。
webservice设计的目标是跨平台的数据交换,所以描述webservice的WSDL( Web Services Description Language)定义了很多基本数据类型(byte,int,long,short,…..),而对于日期时间则分别定义了date,time和dateTime三种不同的类型。
wsdl使用xmlshcema约束文档,这些基本数据类型都是在xmlschema中定义的,
关于wsdl与xmlschema的关系,参见这个博客:(http://blog.csdn.net/ljfbest/article/details/12135035)
顾名思义,date中只包含日期,time中只包含时间(时分秒),dateTime中包含完整的日期和时间。
我们再来看看org.apache.axis2.description.java2wsdl.TypeTable类(axis2-kernel-1.6.2.jar)中java类对date,time,dateTime的映射关系
从上面代码片段中可以看出,axis2将java.util.Date是做为date处理的,java.util.Calendar和java.sql.Timestamp对应的才是完整的日期。
也就是说,这个问题最简单的
解决方案一
就是你需要在webservice中使用java.util.Calendar代替java.util.Date来传递完整日期时间数据。
那么你可能会问了:java.util.Calendar和java.sql.Timestamp对应的都是dateTime,为什么不能用java.sql.Timestamp来代替java.util.Date?java.sql.Timestamp是java.util.Date子类,用它不是更方便?
这个。。。就是因为java.sql.Timestamp是java.util.Date子类,用它才比较麻烦。。。
看看方案二的第一段代码中的中文注释你就明白了。
如果因为各种原因你不想修改自己的项目代码,坚持要用Date来传递完整的日期时间,怎么办?
下面来说解决方案二:
从修改axis2源代码着手,让Date在转换成字符串时包含时间
这个方案要修改axis2的几处源代码,建议做之前先用svn,git等工具做一个原始备份,以方便对照检查。
请先从axis2官网下载 axis2-1.6.2源代码
在网上找到一些关于这个问题的一些提示(https://issues.apache.org/jira/browse/AXIS2-4075):
从这里我们可以得知所有基本数据类型(String,byte[],int,boolean,long,Date…)的序列化和反序列化都是在org.apache.axis2.databinding.typemapping.SimpleTypeMapper这个类(axis2-adb-1.6.2.jar)中完成的。在这里我们找到了Date转String的代码
请注意看这一行
SimpleDateFormat zulu = new SimpleDateFormat(“yyyy-MM-dd”);
看到这里就明白了吧?就是这里,将一个Date对象转为String时,有意丢弃了时间部分。
所以把这一行改为
SimpleDateFormat zulu = new SimpleDateFormat(“yyyy-MM-dd’T’HH:mm:ss.SSSZ”);
Date转换的String就有了时间和时区信息。
那么到这里,这事儿就完了吗?no,no,no事情还远未结束呢!
上面的修改使Date转String已经包含了时间和时区信息,但通过xml传送到客户端/服务器端时,String还要被解析成Date。
显然,经过上面的修改后,转换的String格式与原来已经不同了(多了时间部分),能不能也同样被正确转换成Date呢?
答案是不能。
原因还在org.apache.axis2.databinding.typemapping.SimpleTypeMapper这个类(axis2-adb-1.6.2.jar)中,见下面的代码
上面的代码中getSimpleTypeObject这个方法在将String转为Date时,调用了makeDate方法,而makeDate则是调用org.apache.axis2.databinding.utils.ConverterUtil中的convertToDate方法实现的,所以我们的目光要转到ConverterUtil这个类了,下面是ConverterUtil中convertToDate方法的原始代码(注意代码中我添加的中文注释):
从上面的代码及注释,可以看出,axis2在对Date转成的String重新解析成Date时,只识别 yyyy-MM-dd(Z)?这种格式,Z在这里代表时区信息,如果遇到yyyy-MM-dd’T’HH:mm:ss.SSSZ格式的时间,是不能正常解析的。所以必须修改convertToDate方法,下面是修改后的convertToDate方法:
这代码利用正则表达式重写了convertToDate方法(话说用正则表达式解析灵活多了,原来那种一个个字符判断的方式,好辛苦,数字符数的好累啊),既可以支持原来所支持的yyyy-MM-ddZ格式的时间,也支持yyyy-MM-dd’T’HH:mm:ss.SSSZ格式的时间String解析,而且这其中时间(‘T’HH:mm:ss)毫秒(.SSS)和时区(.Z)都是可选的(时区格式同时支持0800和08:00),
也就是说
“2015-09-18”,
“2015-09-18T12:32:22”,
“2015-09-18T12:32:22.798”,
“2015-09-18T12:32:22.798+0800”,
“2015-09-18T12:32:22.798+08:00”
这些代表时间的String都能被正确解析了。
好了,到这一步,问题算是基本解决了,但这就完了么?未必哦。
如果你的客户端是使用RPC方式调用(org.apache.axis2.rpc.client.RPCServiceClient),那么到这一步,你已经可以收工了。如果你是用Stub方式,那么这个坑还没填完呢。
如果你不清楚什么是RPC方式什么时Stub方式,参见这个blog Axis2开发WebService客户端 的3种方式
下面是一段axis2的wsdl2java工具生成的Stub代码的片段:
,在这段代码中可以看到,Stub方式调用webservice时,Date转String是用org.apache.axis2.databinding.utils.ConverterUtil.convertToString(Date value)方法。
再对比处理java.util.Calendar的convertToString(Calendar value)方法
对比可以发现convertToString(Date value)方法比convertToString(Calendar value)方法果然没有把时间部分加入String.所以结论很简单,还要修改convertToString(Date value)方法:
只需要照猫画虎,参照convertToString(Calendar value)在日期后添加时间就好了:
到这里,所有的代码修改就结束了,剩下的,就是用修改后代码生成的两个class文件(org.apache.axis2.databinding.typemapping.SimpleTypeMapper和org.apache.axis2.databinding.utils.ConverterUtil)替代掉axis2-adb-1.6.2.jar中对应的同名文件就大功告成啦。
这是几个月前的事儿了,那时,这个问题并不影响整个系统的开发,所以一直搁置在那里,最近整个系统接近完成了。做为一个重要但不紧急的问题,我又重新开始研究axis2的代码,着手解决这个问题。
很多人遇到这个问题,把这归结为axis2的bug,但我认为,这是axis2遵循WSDL规范设计的,这个设计的确有些反人类,异于通常技术人员对Date的理解和使用习惯,其实也可以说我们是对webservice的理解不足导致,对于这个问题的理解我也是一点一点加深的。
webservice设计的目标是跨平台的数据交换,所以描述webservice的WSDL( Web Services Description Language)定义了很多基本数据类型(byte,int,long,short,…..),而对于日期时间则分别定义了date,time和dateTime三种不同的类型。
wsdl使用xmlshcema约束文档,这些基本数据类型都是在xmlschema中定义的,
关于wsdl与xmlschema的关系,参见这个博客:(http://blog.csdn.net/ljfbest/article/details/12135035)
顾名思义,date中只包含日期,time中只包含时间(时分秒),dateTime中包含完整的日期和时间。
我们再来看看org.apache.axis2.description.java2wsdl.TypeTable类(axis2-kernel-1.6.2.jar)中java类对date,time,dateTime的映射关系
simpleTypetoxsd.put("java.util.Date", new QName(Java2WSDLConstants.URI_2001_SCHEMA_XSD, "date", "xs")); simpleTypetoxsd.put("java.util.Calendar", new QName(Java2WSDLConstants.URI_2001_SCHEMA_XSD, "dateTime", "xs")); // SQL date time simpleTypetoxsd.put("java.sql.Date", new QName(Java2WSDLConstants.URI_2001_SCHEMA_XSD, "date", "xs")); simpleTypetoxsd.put("java.sql.Time", new QName(Java2WSDLConstants.URI_2001_SCHEMA_XSD, "time", "xs")); simpleTypetoxsd.put("java.sql.Timestamp", new QName(Java2WSDLConstants.URI_2001_SCHEMA_XSD, "dateTime", "xs"));
从上面代码片段中可以看出,axis2将java.util.Date是做为date处理的,java.util.Calendar和java.sql.Timestamp对应的才是完整的日期。
也就是说,这个问题最简单的
解决方案一
就是你需要在webservice中使用java.util.Calendar代替java.util.Date来传递完整日期时间数据。
那么你可能会问了:java.util.Calendar和java.sql.Timestamp对应的都是dateTime,为什么不能用java.sql.Timestamp来代替java.util.Date?java.sql.Timestamp是java.util.Date子类,用它不是更方便?
这个。。。就是因为java.sql.Timestamp是java.util.Date子类,用它才比较麻烦。。。
看看方案二的第一段代码中的中文注释你就明白了。
如果因为各种原因你不想修改自己的项目代码,坚持要用Date来传递完整的日期时间,怎么办?
下面来说解决方案二:
从修改axis2源代码着手,让Date在转换成字符串时包含时间
这个方案要修改axis2的几处源代码,建议做之前先用svn,git等工具做一个原始备份,以方便对照检查。
请先从axis2官网下载 axis2-1.6.2源代码
在网上找到一些关于这个问题的一些提示(https://issues.apache.org/jira/browse/AXIS2-4075):
从这里我们可以得知所有基本数据类型(String,byte[],int,boolean,long,Date…)的序列化和反序列化都是在org.apache.axis2.databinding.typemapping.SimpleTypeMapper这个类(axis2-adb-1.6.2.jar)中完成的。在这里我们找到了Date转String的代码
public static String getStringValue(Object obj) { if (obj instanceof Float || obj instanceof Double) { double data; if (obj instanceof Float) { data = ((Float)obj).doubleValue(); } else { data = (Double)obj; } if (Double.isNaN(data)) { return "NaN"; } else if (data == Double.POSITIVE_INFINITY) { return "INF"; } else if (data == Double.NEGATIVE_INFINITY) { return "-INF"; } else { return obj.toString(); } } else if (obj instanceof Calendar) { Calendar calendar = (Calendar) obj; return ConverterUtil.convertToString(calendar); } else if (obj instanceof Date) { //因为java.sql.Timestamp是java.util.Date子类所以在这里java.sql.Timestamp被当做Date处理了,所以如果不修改axis2的代码,而只简单地把你项目中代码中的java.util.Date替换成java.sql.Timestamp,还是不能解决问题,我觉得这算是axis2的一个bug SimpleDateFormat zulu = new SimpleDateFormat("yyyy-MM-dd"); //请注意,上面这行中生成的SimpleDateFormat对象的格式中没有时间部分哦 MessageContext messageContext = MessageContext.getCurrentMessageContext(); if (messageContext != null) { AxisService axisServce = messageContext.getAxisService(); // if the user has given a pirticualr timezone we use it. if (axisServce.getParameter("TimeZone") != null) { zulu.setTimeZone(TimeZone.getTimeZone((String) axisServce.getParameter("TimeZone").getValue())); } } return zulu.format(obj); } else if (obj instanceof URI){ return obj.toString(); } return obj.toString(); }
请注意看这一行
SimpleDateFormat zulu = new SimpleDateFormat(“yyyy-MM-dd”);
看到这里就明白了吧?就是这里,将一个Date对象转为String时,有意丢弃了时间部分。
所以把这一行改为
SimpleDateFormat zulu = new SimpleDateFormat(“yyyy-MM-dd’T’HH:mm:ss.SSSZ”);
Date转换的String就有了时间和时区信息。
那么到这里,这事儿就完了吗?no,no,no事情还远未结束呢!
上面的修改使Date转String已经包含了时间和时区信息,但通过xml传送到客户端/服务器端时,String还要被解析成Date。
显然,经过上面的修改后,转换的String格式与原来已经不同了(多了时间部分),能不能也同样被正确转换成Date呢?
答案是不能。
原因还在org.apache.axis2.databinding.typemapping.SimpleTypeMapper这个类(axis2-adb-1.6.2.jar)中,见下面的代码
public static Object getSimpleTypeObject(Class parameter, String text) { String name = parameter.getName(); if(name.equals(STRING)) { return text; } else if (text == null || text.length() == 0) { return null; } else if (name.equals(INT)) { return new Integer(text); } else if (name.equals(BOOLEAN)) { return ConverterUtil.convertToBoolean(text); } else if (name.equals(BYTE)) { return new Byte(text); } else if (name.equals(DOUBLE)) { return new Double(text); } else if (name.equals(SHORT)) { return new Short(text); } else if (name.equals(LONG)) { return new Long(text); } else if (name.equals(FLOAT)) { return new Float(text); } else if (name.equals(CHAR)) { return text.toCharArray()[0]; } else if (name.equals(W_INT)) { return new Integer(text); } else if (name.equals(W_BOOLEAN)) { return Boolean.valueOf(text); } else if (name.equals(W_BYTE)) { return new Byte(text); } else if (name.equals(W_DOUBLE)) { return new Double(text); } else if (name.equals(W_SHORT)) { return new Short(text); } else if (name.equals(W_LONG)) { return new Long(text); } else if (name.equals(W_FLOAT)) { return new Float(text); } else if (name.equals(W_CHAR)) { return text.toCharArray()[0]; } else if (name.equals(W_CALENDAR)) { return makeCalendar(text); } else if (name.equals(W_DATE)) { return makeDate(text); }/* * return the correpsonding object for adding data type */ else if(name.equals(BIG_DECIMAL)) { return new java.math.BigDecimal(text); } else if(name.equals(BIG_INTEGER)) { return new java.math.BigInteger(text); } else if(name.equals(DAY)) { return new org.apache.axis2.databinding.types.Day(text); } else if(name.equals(DURATION)) { return new org.apache.axis2.databinding.types.Duration(text); } else if(name.equals(MONTH)) { return new org.apache.axis2.databinding.types.Month(text); } else if(name.equals(MONTH_DAY)) { return new org.apache.axis2.databinding.types.MonthDay(text); } else if(name.equals(TIME)) { return new org.apache.axis2.databinding.types.Time(text); } else if(name.equals(YEAR)) { return new org.apache.axis2.databinding.types.Year(text); } else if(name.equals(YEAR_MONTH)) { return new org.apache.axis2.databinding.types.YearMonth(text); } else if(name.equals(W_URI)) { try { return new URI(text); } catch (URISyntaxException e) { throw new RuntimeException(" Invalid URI " + text, e); } } else { return null; } }
public static Object makeDate(String source) { return ConverterUtil.convertToDate(source); }
上面的代码中getSimpleTypeObject这个方法在将String转为Date时,调用了makeDate方法,而makeDate则是调用org.apache.axis2.databinding.utils.ConverterUtil中的convertToDate方法实现的,所以我们的目光要转到ConverterUtil这个类了,下面是ConverterUtil中convertToDate方法的原始代码(注意代码中我添加的中文注释):
//convertToDate方法的原始代码 public static Date convertToDate(String source) { // the lexical form of the date is '-'? yyyy '-' mm '-' dd zzzzzz? if ((source == null) || source.trim().equals("")) { return null; } source = source.trim(); boolean bc = false; if (source.startsWith("-")) { source = source.substring(1); bc = true; } int year = 0; int month = 0; int day = 0; int timeZoneOffSet = TimeZone.getDefault().getRawOffset(); if (source.length() >= 10) { //first 10 numbers must give the year if ((source.charAt(4) != '-') || (source.charAt(7) != '-')){ throw new RuntimeException("invalid date format (" + source + ") with out - s at correct place "); } //解析标准的日期格式yyyy-mm-dd year = Integer.parseInt(source.substring(0,4)); month = Integer.parseInt(source.substring(5,7)); day = Integer.parseInt(source.substring(8,10)); if (source.length() > 10) {//>10代表有时区信息 String restpart = source.substring(10); //没有解析 HH:mm:ss.SSS,直接解析时区(timeZone),所以如果参数source中包含了时间部分,会抛出RuntimeException异常 if (restpart.startsWith("Z")) { // this is a gmt time zone value timeZoneOffSet = 0; } else if (restpart.startsWith("+") || restpart.startsWith("-") || restpart.startsWith("T")) { // this is a specific time format string //注意这里,所识别时区数字格式为08:00,而不是我们常见的0800 if (restpart.charAt(3) != ':'){ throw new RuntimeException("invalid time zone format (" + source + ") without : at correct place"); } int hours = Integer.parseInt(restpart.substring(1,3)); int minits = Integer.parseInt(restpart.substring(4,6)); timeZoneOffSet = ((hours * 60) + minits) * 60000; if (restpart.startsWith("-")){ timeZoneOffSet = timeZoneOffSet * -1; } } else { throw new RuntimeException("In valid string sufix"); } } } else { throw new RuntimeException("In valid string to parse"); } Calendar calendar = Calendar.getInstance(); calendar.clear(); calendar.setLenient(false); calendar.set(Calendar.YEAR, year); //xml month stars from the 1 and calendar month is starts with 0 calendar.set(Calendar.MONTH, month - 1); calendar.set(Calendar.DAY_OF_MONTH, day); calendar.set(Calendar.ZONE_OFFSET, timeZoneOffSet); // set the day light off set only if time zone if (source.length() >= 10) { calendar.set(Calendar.DST_OFFSET, 0); } calendar.getTimeInMillis(); if (bc){ calendar.set(Calendar.ERA, GregorianCalendar.BC); } return calendar.getTime(); }
从上面的代码及注释,可以看出,axis2在对Date转成的String重新解析成Date时,只识别 yyyy-MM-dd(Z)?这种格式,Z在这里代表时区信息,如果遇到yyyy-MM-dd’T’HH:mm:ss.SSSZ格式的时间,是不能正常解析的。所以必须修改convertToDate方法,下面是修改后的convertToDate方法:
//修改后的convertToDate方法代码 /** * 针对可变长格式的日期的正则表达式 */ private static final Pattern DATE_PATTERN=Pattern.compile("^(\\d{4})(\\-|\\/|\\.)(\\d{1,2})\\2(\\d{1,2})((T((\\d{2}):(\\d{2}):(\\d{2})))?(\\.(\\d{3}))?)((([\\+-])((\\d{2}):?(\\d{2})))|Z)?$"); /** * Converts a given string into a date. Code from Axis1 DateDeserializer. * * @param source * @return Returns Date. */ public static Date convertToDate(String source) { // the lexical form of the date is '-'? yyyy '-' mm '-' dd zzzzzz? if ((source == null) || source.trim().equals("")) { return null; } source = source.trim(); Calendar calendar = Calendar.getInstance(); calendar.clear(); calendar.setLenient(false); boolean bc = false; if (source.startsWith("-")) { source = source.substring(1); bc = true; } int year = 0; int month = 0; int day = 0; int timeZoneOffSet = TimeZone.getDefault().getRawOffset(); int hour = 0; int minute = 0; int second = 0; int miliSecond = 0; Matcher matcher=DATE_PATTERN.matcher(source); if(matcher.find()){//正则表达式匹配,不匹配则抛出RuntimeException异常 //date part yyyy-MM-dd 日期部分必须有 year = Integer.parseInt(matcher.group(1)); month = Integer.parseInt(matcher.group(3)); day = Integer.parseInt(matcher.group(4)); if(matcher.group(5)!=null&&!matcher.group(5).isEmpty()){//如果有时间部分,就解析,没有就跳过 // HH:mm:ss hour = Integer.parseInt(matcher.group(8)); minute = Integer.parseInt(matcher.group(9)); second = Integer.parseInt(matcher.group(10)); if(matcher.group(11)!=null&&!matcher.group(11).isEmpty())//如果有毫秒部分就解析,没有就跳过 // .SSS miliSecond=Integer.parseInt(matcher.group(12)); } // timeZone if(matcher.group(13)!=null&&!matcher.group(13).isEmpty()){//如果有时区部分,就解析,没有就跳过 if(matcher.group(13).equals("Z")){// Z结尾,代表GMT 0时区 timeZoneOffSet = 0; calendar.setTimeZone(TimeZone.getTimeZone("GMT")); }else{ //数字表示的时区 // +0800或+08:00 int zhour,zminute; zhour = Integer.parseInt(matcher.group(17)); zminute = Integer.parseInt(matcher.group(18)); timeZoneOffSet = ((zhour * 60) + zminute) * 60000; if (matcher.group(15).startsWith("-")) { timeZoneOffSet = timeZoneOffSet * -1; } } } }else throw new RuntimeException(String.format("Invalid date string[%s] to parse",source)); calendar.set(Calendar.YEAR, year); //xml month stars from the 1 and calendar month is starts with 0 calendar.set(Calendar.MONTH, month - 1); calendar.set(Calendar.DAY_OF_MONTH, day); calendar.set(Calendar.HOUR_OF_DAY, hour); calendar.set(Calendar.MINUTE, minute); calendar.set(Calendar.SECOND, second); calendar.set(Calendar.MILLISECOND, miliSecond); calendar.set(Calendar.ZONE_OFFSET, timeZoneOffSet); // set the day light off set only if time zone if (source.length() >= 10) { calendar.set(Calendar.DST_OFFSET, 0); } calendar.getTimeInMillis(); if (bc){ calendar.set(Calendar.ERA, GregorianCalendar.BC); } return calendar.getTime(); }
这代码利用正则表达式重写了convertToDate方法(话说用正则表达式解析灵活多了,原来那种一个个字符判断的方式,好辛苦,数字符数的好累啊),既可以支持原来所支持的yyyy-MM-ddZ格式的时间,也支持yyyy-MM-dd’T’HH:mm:ss.SSSZ格式的时间String解析,而且这其中时间(‘T’HH:mm:ss)毫秒(.SSS)和时区(.Z)都是可选的(时区格式同时支持0800和08:00),
也就是说
“2015-09-18”,
“2015-09-18T12:32:22”,
“2015-09-18T12:32:22.798”,
“2015-09-18T12:32:22.798+0800”,
“2015-09-18T12:32:22.798+08:00”
这些代表时间的String都能被正确解析了。
好了,到这一步,问题算是基本解决了,但这就完了么?未必哦。
如果你的客户端是使用RPC方式调用(org.apache.axis2.rpc.client.RPCServiceClient),那么到这一步,你已经可以收工了。如果你是用Stub方式,那么这个坑还没填完呢。
如果你不清楚什么是RPC方式什么时Stub方式,参见这个blog Axis2开发WebService客户端 的3种方式
下面是一段axis2的wsdl2java工具生成的Stub代码的片段:
if (localCreateTime==null){ // write the nil attribute writeAttribute("xsi","http://www.w3.org/2001/XMLSchema-instance","nil","1",xmlWriter); }else{ xmlWriter.writeCharacters(org.apache.axis2.databinding.utils.ConverterUtil.convertToString(localCreateTime)); }
,在这段代码中可以看到,Stub方式调用webservice时,Date转String是用org.apache.axis2.databinding.utils.ConverterUtil.convertToString(Date value)方法。
//convertToString(Date value)方法代码原始代码,中文注释是本文作者添加 public static String convertToString(Date value) { if (isCustomClassPresent) { // this means user has define a seperate converter util class return invokeToStringMethod(value,Date.class); } else { // lexical form of the date is '-'? yyyy '-' mm '-' dd zzzzzz? Calendar calendar = Calendar.getInstance(); calendar.clear(); calendar.setTime(value); if (!calendar.isSet(Calendar.ZONE_OFFSET)){ calendar.setTimeZone(TimeZone.getDefault()); } StringBuffer dateString = new StringBuffer(16); appendDate(dateString, calendar);//添加日期 yyyy-MM-dd appendTimeZone(calendar, dateString);//添加时区 +08:00 return dateString.toString(); } }
再对比处理java.util.Calendar的convertToString(Calendar value)方法
public static String convertToString(Calendar value) { if (isCustomClassPresent) { return invokeToStringMethod(value,Calendar.class); } else { // lexical form of the calendar is '-'? yyyy '-' mm '-' dd 'T' hh ':' mm ':' ss ('.' s+)? (zzzzzz)? if (value.get(Calendar.ZONE_OFFSET) == -1){ value.setTimeZone(TimeZone.getDefault()); } StringBuffer dateString = new StringBuffer(28); appendDate(dateString, value); dateString.append("T"); //adding hours appendTime(value, dateString); appendTimeZone(value, dateString);//添加时间部分 'T'HH:mm:ss.SSS return dateString.toString(); } }
对比可以发现convertToString(Date value)方法比convertToString(Calendar value)方法果然没有把时间部分加入String.所以结论很简单,还要修改convertToString(Date value)方法:
只需要照猫画虎,参照convertToString(Calendar value)在日期后添加时间就好了:
//修改后的convertToString(Date value)方法 public static String convertToString(Date value) { if (isCustomClassPresent) { // this means user has define a seperate converter util class return invokeToStringMethod(value,Date.class); } else { // lexical form of the date is '-'? yyyy '-' mm '-' dd zzzzzz? Calendar calendar = Calendar.getInstance(); calendar.clear(); calendar.setTime(value); if (!calendar.isSet(Calendar.ZONE_OFFSET)){ calendar.setTimeZone(TimeZone.getDefault()); } StringBuffer dateString = new StringBuffer(16); appendDate(dateString, calendar); //adding HH:mm:ss.SSS //modified by guyadong 2015/09/20 增加时间部分 dateString.append("T"); appendTime(calendar, dateString); appendTimeZone(calendar, dateString); return dateString.toString(); } }
到这里,所有的代码修改就结束了,剩下的,就是用修改后代码生成的两个class文件(org.apache.axis2.databinding.typemapping.SimpleTypeMapper和org.apache.axis2.databinding.utils.ConverterUtil)替代掉axis2-adb-1.6.2.jar中对应的同名文件就大功告成啦。
相关文章推荐
- Aixs2开发Web service操作数据库demo
- ubuntu下安装 gSOAP 用于C/C++开发web service服务端与客户端
- Linux下用gSOAP开发Web Service服务端和客户端程序(一)
- Linux下用gSOAP开发Web Service服务端和客户端程序(二)
- web service, wcf, web api
- 使用axis2生成客户端(异步/同步)调用代码
- arcengine发布webservice编辑sde
- axis2调用webservice接口核心代码
- axis2发布的webservices在flex中调用出错的解决方案(通过代理服务器发布)
- High scalability - Harvard notes.
- 使用 CXF 做 webservice 简单例子
- Axis 配置webService 配置文件未找到
- web service与wcf的区别
- java调用C# webservice短信猫发送短信
- 安卓Web Service实现天气预报功能
- 使用MyEclipse开发基于JAX-WS的Web service实例
- axis2 WebService的发布与调用
- IIS发布web service 相关问题
- php的webservice使用
- Android平台调用Web Service实例解析