有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

jsp使用java。时间带有JSTL的LocalDate<fmt:formatDate>操作

我还没有弄清楚如何在JSP中显示java.time.LocalDate

在我的JSP中,我有以下内容:

<fmt:formatDate value="${std.datum}" type="date" pattern="dd.MM.yyyy" var="stdDatum" />


std.datum是类型java.time.LocalDate。呈现JSP时,我会遇到以下异常:

javax.el.ELException:
Cannot convert 2015-02-14 of type class java.time.LocalDate to class java.util.Date

我想是转换吧

那么,是否可以使用<fmr:formatDate>操作格式化LocalDate类的实例


共 (4) 个答案

  1. # 1 楼答案

    I'm assuming it's the conversion?

    是的,这是一个与转换相关的异常


    解决方案

    您可以首先使用JSTL的“支持I18n的格式化标记库”中的^{}操作执行转换然后使用^{}操作执行格式化

    以下是一个例子:

    <fmt:parseDate  value="${std.datum}"  type="date" pattern="yyyy-MM-dd" var="parsedDate" />
    <fmt:formatDate value="${parsedDate}" type="date" pattern="dd.MM.yyyy" var="stdDatum" />
    


    该解决方案也在"JavaServer Pages™ Standard Tag Library (JSTL)"规范1.2版中给出(参见第109页)

  2. # 2 楼答案

    我想避免改变所有地方<;fmt:formatDate/>;在使用时,我创建了以下两个类:

    首先,一个转换器,用于转换(部分)java。时间课。它检查java。util。Date是目标类型,如果不是,则不起任何作用。它支持源时间作为java。util。日期(包括java.sql.Timestamp和java.sql.Date)、LocalDate、LocalDateTime、ZonedDateTime、Instant或Long(时间单位为毫秒)

    package com.example.elresolvers;
    
    import javax.el.ELContext;
    import javax.el.TypeConverter;
    import java.time.Instant;
    import java.time.LocalDate;
    import java.time.LocalDateTime;
    import java.time.ZoneId;
    import java.time.ZonedDateTime;
    import java.util.Date;
    
    @SuppressWarnings("UseOfObsoleteDateTimeApi")
    public class DateFromJavaTimeResolver extends TypeConverter {
        @Override
        public Object convertToType(ELContext context, Object obj, Class<?> type) {
            Date date = null;
            if (Date.class.isAssignableFrom(type)) {
                if (obj instanceof Date) {
                    date = (Date) obj;
                } else {
                    ZonedDateTime zdt = null;
                    if (obj instanceof LocalDate) {
                        zdt = ((LocalDate) obj).atStartOfDay(ZoneId.systemDefault());
                    } else if (obj instanceof LocalDateTime) {
                        zdt = ((LocalDateTime) obj).atZone(ZoneId.systemDefault());
                    } else if (obj instanceof ZonedDateTime) {
                        zdt = (ZonedDateTime) obj;
                    } else if (obj instanceof Instant) {
                        date = Date.from((Instant) obj);
                    } else if (obj instanceof Long) {
                        date = new Date((Long) obj);
                    }
                    if (zdt != null) {
                        date = Date.from(zdt.toInstant());
                    }
                }
                context.setPropertyResolved(date != null);
            }
            return date;
        }
    }
    

    接下来是一个ServletContextListener类,用于注册用于JSP的转换器:

    package com.example.web;
    
    import com.example.elresolvers.DateFromJavaTimeResolver;
    
    import javax.servlet.ServletContext;
    import javax.servlet.ServletContextEvent;
    import javax.servlet.ServletContextListener;
    import javax.servlet.jsp.JspApplicationContext;
    import javax.servlet.jsp.JspFactory;
    
    public class JspElResolverInitListener implements ServletContextListener {
        @Override
        public void contextInitialized(ServletContextEvent sce) {
            ServletContext servletContext = sce.getServletContext();
            JspApplicationContext context = JspFactory.getDefaultFactory().getJspApplicationContext(servletContext);
            context.addELResolver(new DateFromJavaTimeResolver());
        }
    
        @Override
        public void contextDestroyed(ServletContextEvent sce) {
        }
    }
    

    最后,在web中创建一个条目。xml(如果不使用注释或其他方式):

    <listener>
        <listener-class>com.example.web.JspElResolverInitListener</listener-class>
    </listener>
    
  3. # 3 楼答案

    爪哇:

    public class DateTimeUtil {
        private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("dd.MM.yyyy");
    
        public static String toString(LocalDateTime ldt) {
            return ldt.format(DATE_FORMATTER);
        }
    

    JSP:

    <%@ page import="ru.javaops.topjava.util.DateTimeUtil" %>
    ...
    <%=DateTimeUtil.toString(std.getDatum())%>
    
  4. # 4 楼答案

    这是一个老问题,但我发现在这种情况下最好使用自定义tld:不需要对字符串进行任何双重转换

    创建自己的tld文件,然后重写FormatDate类。最后,声明您自己的自定义前缀并使用custom:formatDate而不是fmt:formatDate

    这是一个简化的版本

    JSP中的用法:

    <%@ taglib uri="/WEB-INF/custom" prefix="custom" %>
    ...
    <custom:formatDate value="${std.datum}" pattern="dd/MM/yyyy" />
    

    WEB-INF/自定义。tld文件

    <?xml version="1.0" encoding="UTF-8"?>
    <tag ib version="2.0" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee web-jsptaglibrary_2_0.xsd">
    
    <tag>
        <description>
            FormatDate with java8 type
        </description>
        <name>formatDate</name>
        <tag-class>com.custom.tag.FormatDateTag</tag-class>
        <body-content>empty</body-content>
        <attribute>
            <description>
                Date and/or time to be formatted.
            </description>
            <name>value</name>
            <required>true</required>
            <rtexprvalue>true</rtexprvalue>
        </attribute>
    
        <attribute>
            <description>
                Custom formatting style for dates and times.
            </description>
            <name>pattern</name>
            <required>false</required>
            <rtexprvalue>true</rtexprvalue>
        </attribute>
    </tag>
    </taglib>
    

    然后是java类标记文件

    public class FormatDateTag extends TagSupport  {
    
        protected Temporal value;
        protected String pattern; 
        private String var; 
        private int scope; 
    
    
        public FormatDateTag()
        {
            super ();
            init ();
        }
    
        private void init()
        {
    
            this.pattern = this.var = null;
            this.value = null;
            this.scope = PageContext.PAGE_SCOPE;
        }
    
    
        public void setVar(final String var)
        {
            this.var = var;
        }
    
        public void setScope(final String scope)
        {
            this.scope = Util.getScope (scope);
        }
    
    
        public void setValue(final Temporal value)
        {
            this.value = value;
        }
    
    
        public void setPattern(final String pattern)
        {
            this.pattern = pattern;
        }
    
    
        @Override
        public int doEndTag() throws JspException
        {
    
            String formatted = null;
    
            if (this.value == null)
            {
                if (this.var != null)
                {
                    this.pageContext.removeAttribute (this.var, this.scope);
                }
                return EVAL_PAGE;
            }
    
            // Create formatter
            if (this.pattern != null)
            {
                final DateTimeFormatter formatter = DateTimeFormatter.ofPattern (this.pattern);
                formatted = formatter.format (this.value);
            }
            else
            {
                // no formatting locale available, use Date.toString()
                formatted = this.value.toString ();
            }
    
            if (this.var != null)
            {
                this.pageContext.setAttribute (this.var, formatted, this.scope);
            }
            else
            {
                try
                {
                    this.pageContext.getOut ().print (formatted);
                }
                catch (final IOException ioe)
                {
                    throw new JspTagException (ioe.toString (), ioe);
                }
            }
    
            return EVAL_PAGE;
        }
    
    
        @Override
        public void release()
        {
            init ();
        }
    
    }