解决如何在springMVC前台传递Date类型日期类型到后台并且回显

解决如何在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 ,CustomBooleanEditorCustomNumberEditor等许多,基本上够用。 
使用时候调用WebDataBinderregisterCustomEditor方法 
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();
        }
    }
}

猜你喜欢

转载自blog.csdn.net/caox_nazi/article/details/80899922