How to convert the Date type in Struts2

Source: Internet
Author: User

Web development involves many types of conversions. We know that all values on the page are of the string type, and to the background, we may need other types. At the same time, the page display is also of the string type. This involves the basic type conversion problem in the Web: Converting from string to various types and from various types to string types.

In Java Web development, there are generally the following types of conversions:
1. In servlet, we have to write code to complete all the conversions;
2. In struts1.x, we use converters in Apache commons-beanutils to help with these tasks;
3. In struts2, ongl-based type conversion is used;
......

Because of the versatility of type conversion, the Web framework implements most types of conversion functions without coding. However, for the conversion of Java. util. date type, the major frameworks seem to be not doing well. For example, in struts1.x, conversions of this type may be problematic. Many people suggest using Java. SQL. the date type solves the problem of date conversion (in fact, a type converter can be customized to solve this problem ). In struts2, this problem still exists, maybe you have never encountered it. Indeed, the average person does not encounter this problem, and will feel that this problem does not exist. The following are my problems and solutions.

The conversion of date types is almost always encountered in web development, and projects I have done are no exception. In the development process, maybe like you, I didn't perform any special processing on the date type conversion, and struts2 also helped me complete the conversion. However, during the test, my colleagues encountered an "inexplicable" problem: enter a date type in the common format of yyyy-mm-dd, but an error is reported in the background: the corresponding Set Method -- seteffdate (ljava. lang. string ). Indeed, the program only uses the seteffdate (Java. util. Date) method. There is no seteffdate (ljava. Lang. String) method. From ljava. Lang. String, we can see that the string type uploaded to the background is not converted to the date type, so an error is returned.

At first, I thought I was not doing well with UT, So I simulated my colleagues' tests on my computer, and there was no problem at all. This is strange. After analysis, I think it may be the reason for IE browser, because my colleague tested IE and I used Firefox. Therefore, I used ie for testing on my machine and Firefox for testing on my colleague's machine. As a result, none of the above problems occurred during the two tests. Although I have not found the problem, I can make a preliminary affirmation: The problem with IE does not seem to be completely a problem with IE, because IE on my computer (the version is the same as that of my colleagues, all are IE6. This is strange. What is the problem? It is really hard to understand.

At this time, I think of a problem that I encountered before: When the date type obtained from the background is displayed on the page, like the above, in my colleague's IE, the date display format is yyyy-mm-ddthh: mm: Ss. It is really inexplicable to have a T more, and it only appears in the IE browser of a colleague (at that time, the solution was to replace 'T' with a space in JS without going further into it, but now we have to go further ). Yyyy-mm-ddthh: mm: Is there a date format LiKe SS? Query JDK: this date format is found in the simpledateformat class. This format is "one of the date and time modes in the U.S. language environment ". This format is actually available. It turns out that this is the date format used in the American language, and struts2 is developed by Americans. It may be related to this. View the source code about date type conversion in struts2.
In the xworkbasicconverter class

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;        }

Here, short, medium, and long are described in the dateformat class in JDK.
From this statement, dateformat rfc3399 = new simpledateformat ("yyyy-mm-dd't'hh: mm: SS"); we can see that struts2 uses this format for hard encoding. However, in struts2, this format is placed at the end. Why is this format used only for testing by a colleague's IE browser? (When debugging, it's okay to use both IE and Date input in this format.) This means that none of the first six dateformats match in the same computer, check the description of short, medium, and long in dateformat. We can see that the date type yyyy-mm-dd cannot be matched in the English language because struts2 matches the date, locale is used. It can be seen that the default language environment of my colleague's IE browser is English. Once viewed, we set the Chinese language to the default language environment and then test the language. The reason is finally known.

In my opinion, in struts2, the last date mode is written to American standards, which is not very good.

To solve this problem, we cannot require customers to set Chinese as the language environment of the default browser. Therefore, you can define a converter for date type conversion. The following is a type converter definition from the http://www.javaeye.com/wiki/struts2/1365-passing-parameters-in-struts2 (not suitable for international environments), you can define your own converter as needed:

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;        }}

You can register this converter as a global: Create a xwork-conversion.properties file under classpath with the following content: Java. util. Date = the full qualified class name of your type converter

Since then, the problem has been solved successfully.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.