解决如何在springMVC前台传递Date类型日期类型到后台并且回显
在使用SpringMVC的时候,经常会遇到表单中的日期字符串和JavaBean的Date类型的转换,而SpringMVC默认不支持这个格式的转换,所以需要手动配置,自定义数据的绑定才能解决这个问题。
在需要日期转换的Controller中使用SpringMVC的注解@initbinder
和Spring自带的WebDateBinder
类来操作。 WebDataBinder
是用来绑定请求参数到指定的属性编辑器.由于前台传到controller里的值是String类型的,当往Model里Set这个值的时候,如果set的这个属性是个对象,Spring就会去找到对应的editor进行转换,然后再set进去。
代码如下:在自己的Controller代码中加入:
@InitBinder
protected void initBinder(HttpServletRequest request, ServletRequestDataBinder binder) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
simpleDateFormat.setLenient(false);
CustomDateEditor dateEditor = new CustomDateEditor(simpleDateFormat, true);
binder.registerCustomEditor(Date.class, dateEditor);
}
ServletRequestDataBinder
是WebDataBinder
的子类。
对于springboot
应用,上面的操作就可以了。
如果是传统的 spring xml 配置方式,需要:
需要在SpringMVC的配置文件加上,其中经过验证:SpringMVC也不需要加入 如下配置方式:
第一种写法:
<!-- 解析器注册 -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="messageConverters">
<list>
<ref bean="stringHttpMessageConverter"/>
</list>
</property>
</bean>
<!-- String类型解析器,允许直接返回String类型的消息 -->
<bean id="stringHttpMessageConverter" class="org.springframework.http.converter.StringHttpMessageConverter"/>
第二种写法:
<mvc:annotation-driven>
<mvc:message-converters>
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<constructor-arg value="UTF-8"/>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
拓展:
spring mvc在绑定表单之前,都会先注册这些编辑器,Spring自己提供了大量的实现类,诸如CustomDateEditor
,CustomBooleanEditor
,CustomNumberEditor
等许多,基本上够用。
使用时候调用WebDataBinder
的registerCustomEditor
方法 registerCustomEditor
源码:
public void registerCustomEditor(Class<?> requiredType, PropertyEditor propertyEditor) {
getPropertyEditorRegistry().registerCustomEditor(requiredType, propertyEditor);
}
第一个参数requiredType是需要转化的类型。
第二个参数PropertyEditor是属性编辑器,它是个接口,以上提到的如CustomDateEditor等都是继承了实现了这个接口的PropertyEditorSupport类。
我们也可以不使用他们自带的这些编辑器类。
我们可以自己构造:
import org.springframework.beans.propertyeditors.PropertiesEditor;
public class DoubleEditor extends PropertyEditorSupport {
@Override
public void setAsText(String text) throws IllegalArgumentException {
if (text == null || text.equals("")) {
text = "0";
}
setValue(Double.parseDouble(text));
}
@Override
public String getAsText() {
return getValue().toString();
}
}
实例中java代码:
@InitBinder
protected void initBinder(HttpServletRequest request, ServletRequestDataBinder binder) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
simpleDateFormat.setLenient(false);
CustomDateEditor dateEditor = new CustomDateEditor(simpleDateFormat, true);
binder.registerCustomEditor(Date.class, dateEditor);
}
@RequestMapping("accountReceiptManager.do")
public ModelAndView accountReceiptManager(ReceiptReqPage reqPage, HttpServletRequest request) throws Exception{
ModelAndView model = new ModelAndView();
ReceiptReqDto reqDto = new ReceiptReqDto();
String traceLogId = MDC.get(SystemMarker.TRACE_LOG_ID);
Result<PageDTO<ReceiptResPage>> resPage = new Result<>();
AccountReceiptResModel queryModel = new AccountReceiptResModel();
reqPage.setPageSize(20);
if(reqPage.getCurrentPage() == null){
reqPage.setCurrentPage(0);
}
try{
// 分页参数
int pageNo = Math.max(reqPage.getCurrentPage(), 1);
// 分页条数
int pageSize = reqPage.getPageSize();
log.info("call pageFacade.pageReceipt params:{},traceLogId:{}",
ToStringBuilder.reflectionToString(reqPage),traceLogId);
// 交易凭证分页查询
resPage = pageFacade.pageReceipt(reqPage, traceLogId);
log.info("call pageFacade.pageReceipt result :{}", resPage.toString());
BasePageEntity<ReceiptResPage> pageInfo = new BasePageEntity<ReceiptResPage>();
if(resPage.getResult() != null){
pageInfo.setPageEnity(pageNo, pageSize, resPage.getResult().getTotalSize(), resPage.getResult().getResults());
}
queryModel.setPageInfo(pageInfo);
}catch (Exception e){
log.error("查询页面显示错误:call pageFacade.pageReceipt Exception : {}", e);
}
PagePrompts.outPagePrompts(model, request);
if(null != reqPage.getAccDateStart()){
reqDto.setAccDateStart(DateExtendUtil.formatDate2SmallDateString(reqPage.getAccDateStart()));
}
if(null != reqPage.getAccDateEnd()){
reqDto.setAccDateEnd(DateExtendUtil.formatDate2SmallDateString(reqPage.getAccDateEnd()));
}
model.addObject("reqDto",reqDto);
model.addObject("queryForm", reqPage);
model.addObject("queryModel", queryModel);
return model;
}
其中回显搜索日期框处理为:
if(null != reqPage.getAccDateStart()){
reqDto.setAccDateStart(DateExtendUtil.formatDate2SmallDateString(reqPage.getAccDateStart()));
}
if(null != reqPage.getAccDateEnd()){
reqDto.setAccDateEnd(DateExtendUtil.formatDate2SmallDateString(reqPage.getAccDateEnd()));
}
前台请求页面搜索框为:
<div class="span" style="width:100px;">请求时间Start</div>
<div class="span" style="width:15%;">
<input type="text" autocomplete="off" name="requestDateStart" id="requestDateStart" class="datepicker"
value="${reqDto.requestDateStart}"/>
</div>
<div class="span" style="width:100px;">请求时间End</div>
<div class="span" style="width:15%;">
<input type="text" autocomplete="off" name="requestDateEnd" id="requestDateEnd" class="datepicker"
value="${reqDto.requestDateEnd }"/>
</div>
第二种方法:
不需要如下后台java代码转换:
if(null != reqPage.getAccDateStart()){
reqDto.setAccDateStart(DateExtendUtil.formatDate2SmallDateString(reqPage.getAccDateStart()));
}
if(null != reqPage.getAccDateEnd()){
reqDto.setAccDateEnd(DateExtendUtil.formatDate2SmallDateString(reqPage.getAccDateEnd()));
}
if(null != reqPage.getRequestDateStart()){
reqDto.setRequestDateStart(DateExtendUtil.formatDate2SmallDateString(reqPage.getRequestDateStart()));
}
if(null != reqPage.getRequestDateEnd()){
reqDto.setRequestDateEnd(DateExtendUtil.formatDate2SmallDateString(reqPage.getRequestDateEnd()));
}
前台html页面日期搜素框改为:
<div class="span" style="width:100px;">会计日Start</div>
<div class="span" style="width:15%;">
<input type="text" autocomplete="off" name="accDateStart" id="accDateStart" class="datepicker"
value="<fmt:formatDate value="${queryForm.accDateStart }" pattern="yyyy-MM-dd"/>" />
</div>
<div class="span" style="width:100px;">会计日End</div>
<div class="span" style="width:15%;">
<input type="text" autocomplete="off" name="accDateEnd" id="accDateEnd" class="datepicker"
value="<fmt:formatDate value="${queryForm.accDateEnd }" pattern="yyyy-MM-dd"/>"/>
</div>
(二)另外一种做法:
@DateTimeFormat()绑定Date类型
@DateTimeFormat()实现数据的绑定比较简单,只需要在需要绑定类的属性上或者setter()方法上添加注解:@DateTimeFormat(pattern=“yyyy-MM-dd HH:mm:ss”)。此外该方法需要依赖单独的jar包:joda-time
<!-- 注解实例:-->
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date birthday;
<!-- 坐标依赖:-->
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>1.3</version>
</dependency>
但是,不建议使用这种方法:
【原因】:在企业开发中的pojo类都是反向生成的,一般不会在pojo类中直接添加注释。因为如果业务需要重新生成pojo类,就会有可能覆盖该注解,会造成不必要的麻烦。
建议使用上述第一种方案:可以针对整个项目,像实例一样抽出公共BaseController,让所有的controller继承BaseController,即可
【BaseController.java】:
package com.baofu.admin.ma.controller;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.propertyeditors.PropertiesEditor;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import java.beans.PropertyEditorSupport;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* Created by nazi on 2018/7/24.
*/
@Slf4j
@Controller
public class BaseController {
@InitBinder
protected void initBinder(WebDataBinder binder) {
binder.registerCustomEditor(Date.class, new MyDateEditor());
/*
从PropertyEditorSupport 实现的方法可以看出,这里的绑定是为了处理空和null的数据,
开发者可根据实际情况绑定
*/
binder.registerCustomEditor(Double.class, new DoubleEditor());
binder.registerCustomEditor(Integer.class, new IntegerEditor());
}
private class MyDateEditor extends PropertyEditorSupport {
@Override
public void setAsText(String text) throws IllegalArgumentException {
//通过两次异常的处理可以,绑定两次日期的格式
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date date = null;
try {
date = format.parse(text);
} catch (ParseException e) {
format = new SimpleDateFormat("yyyy-MM-dd");
try {
date = format.parse(text);
} catch (ParseException e1) {
log.error("系统异常:"+e1);
}
}
setValue(date);
}
}
public class DoubleEditor extends PropertiesEditor {
@Override
public void setAsText(String text) throws IllegalArgumentException {
try {
if (text == null || text.equals("")) {
text = "0";
}
} catch (Exception e) {
log.error("系统异常:"+e);
}
setValue(Double.parseDouble(text));
}
@Override
public String getAsText() {
return getValue().toString();
}
}
public class IntegerEditor extends PropertiesEditor {
@Override
public void setAsText(String text) throws IllegalArgumentException {
try {
if (text == null || text.equals("")) {
text = "0";
}
} catch (Exception e) {
log.error("系统异常:"+e);
}
setValue(Integer.parseInt(text));
}
@Override
public String getAsText() {
return getValue().toString();
}
}
}