Bri*_*ace 18 java spring jsp el spring-mvc
这是一个简单的值bean,使用Spring的新版本(3.0版本) @DateTimeFormat注释(根据我的理解PropertyEditor,根据此SO问题替换了3.0之前的自定义需求):
import java.time.LocalDate;
import org.springframework.format.annotation.DateTimeFormat;
public class Widget {
private String name;
@DateTimeFormat(pattern = "MM/dd/yyyy")
private LocalDate created;
// getters/setters excluded
}
Run Code Online (Sandbox Code Playgroud)
将表单提交中的值与此窗口小部件结合使用时,日期格式可以正常运行.也就是说,只有MM/dd/yyyy格式中的日期字符串才能成功转换为实际LocalDate对象.太棒了,我们就在那里.
然而,我也想能够还显示所创建的LocalDate在同一个JSP视图属性MM/dd/yyyy格式使用JSP EL像这样(假设我的弹簧控制器添加小窗口属性的模型):
${widget.created}
Run Code Online (Sandbox Code Playgroud)
不幸的是,这只会显示默认toString格式LocalDate(yyyy-MM-dd格式).我知道如果我使用spring的表单标签,日期会根据需要显示:
<form:form commandName="widget">
Widget created: <form:input path="created"/>
</form:form>
Run Code Online (Sandbox Code Playgroud)
但我想在不使用spring form标签的情况下显示格式化的日期字符串.甚至是JSTL的fmt:formatDate标签.
来自Struts2,HttpServletRequest包含在一个StrutsRequestWrapper启用这样的EL表达式实际上询问OGNL值栈.所以我想知道spring是否提供类似的东西以允许转换器执行?
编辑
我也意识到,当使用spring的eval标签时,日期将根据@DateTimeFormat注释中定义的模式显示:
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<spring:eval expression="widget.created"/>
Run Code Online (Sandbox Code Playgroud)
有趣的是,使用自定义当PropertyEditor格式化日期,该标签不会调用该PropertyEditor的getAsText方法,因此默认为DateFormat.SHORT如在该文档中描述.无论如何,我仍然想知道是否有办法实现日期格式化而不必使用标记 - 仅使用标准JSP EL.
小智 8
您可以使用标记为您提供这些格式,例如金钱,数据,时间和许多其他格式.
您可以在JSP上添加引用:
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
并使用格式为:
<fmt:formatDate pattern="yyyy-MM-dd" value="${now}" />
以下是参考:
http://www.tutorialspoint.com/jsp/jstl_format_formatdate_tag.htm
当我得知Spring 开发人员决定不将 Unified EL(JSP 2.1+ 中使用的表达式语言)与 Spring EL集成时,我感到很沮丧,声明如下:
JSP 和 JSF 在我们的开发重点方面都不再占据强势地位。
但从引用的 JIRA 票证中汲取灵感,我创建了一个自定义ELResolver,如果解析的值为 ajava.time.LocalDate或java.time.LocalDateTime,它将尝试拉取@DateTimeFormat模式值以格式化返回String值。
这是ELResolver(以及ServletContextListener用于引导它的):
public class DateTimeFormatAwareElResolver extends ELResolver implements ServletContextListener {
private final ThreadLocal<Boolean> isGetValueInProgress = new ThreadLocal<>();
@Override
public void contextInitialized(ServletContextEvent event) {
JspFactory.getDefaultFactory().getJspApplicationContext(event.getServletContext()).addELResolver(this);
}
@Override
public void contextDestroyed(ServletContextEvent sce) {}
@Override
public Object getValue(ELContext context, Object base, Object property) {
try {
if (Boolean.TRUE.equals(isGetValueInProgress.get())) {
return null;
}
isGetValueInProgress.set(Boolean.TRUE);
Object value = context.getELResolver().getValue(context, base, property);
if (value != null && isFormattableDate(value)) {
String pattern = getDateTimeFormatPatternOrNull(base, property.toString());
if (pattern != null) {
return format(value, DateTimeFormatter.ofPattern(pattern));
}
}
return value;
}
finally {
isGetValueInProgress.remove();
}
}
private boolean isFormattableDate(Object value) {
return value instanceof LocalDate || value instanceof LocalDateTime;
}
private String format(Object localDateOrLocalDateTime, DateTimeFormatter formatter) {
if (localDateOrLocalDateTime instanceof LocalDate) {
return ((LocalDate)localDateOrLocalDateTime).format(formatter);
}
return ((LocalDateTime)localDateOrLocalDateTime).format(formatter);
}
private String getDateTimeFormatPatternOrNull(Object base, String property) {
DateTimeFormat dateTimeFormat = getDateTimeFormatAnnotation(base, property);
if (dateTimeFormat != null) {
return dateTimeFormat.pattern();
}
return null;
}
private DateTimeFormat getDateTimeFormatAnnotation(Object base, String property) {
DateTimeFormat dtf = getDateTimeFormatFieldAnnotation(base, property);
return dtf != null ? dtf : getDateTimeFormatMethodAnnotation(base, property);
}
private DateTimeFormat getDateTimeFormatFieldAnnotation(Object base, String property) {
try {
if (base != null && property != null) {
Field field = base.getClass().getDeclaredField(property);
return field.getAnnotation(DateTimeFormat.class);
}
}
catch (NoSuchFieldException | SecurityException ignore) {
}
return null;
}
private DateTimeFormat getDateTimeFormatMethodAnnotation(Object base, String property) {
try {
if (base != null && property != null) {
Method method = base.getClass().getMethod("get" + StringUtils.capitalize(property));
return method.getAnnotation(DateTimeFormat.class);
}
}
catch (NoSuchMethodException ignore) {
}
return null;
}
@Override
public Class<?> getType(ELContext context, Object base, Object property) {
return null;
}
@Override
public void setValue(ELContext context, Object base, Object property, Object value) {
}
@Override
public boolean isReadOnly(ELContext context, Object base, Object property) {
return true;
}
@Override
public Iterator<FeatureDescriptor> getFeatureDescriptors(ELContext context, Object base) {
return null;
}
@Override
public Class<?> getCommonPropertyType(ELContext context, Object base) {
return null;
}
}
Run Code Online (Sandbox Code Playgroud)
在 web.xml 中注册ELResolver:
<listener>
<listener-class>com.company.el.DateTimeFormatAwareElResolver</listener-class>
</listener>
Run Code Online (Sandbox Code Playgroud)
现在,当我${widget.created}在 jsp 中时,显示的值将根据@DateTimeFormat注释进行格式化!
此外,如果jsp 需要LocalDateorLocalDateTime对象(而不仅仅是格式化的字符串表示形式),您仍然可以使用直接方法调用来访问对象本身,例如:${widget.getCreated()}
| 归档时间: |
|
| 查看次数: |
21131 次 |
| 最近记录: |