在JavaWeb程序的開發(fā)過程中,接口是前后端對接的主要窗口,而接口參數(shù)的接收有時候是一個令人頭疼的事情,這其中最困擾程序猿的,應(yīng)該是時間參數(shù)的接收。
站在用戶的角度思考問題,與客戶深入溝通,找到吳興網(wǎng)站設(shè)計與吳興網(wǎng)站推廣的解決方案,憑借多年的經(jīng)驗,讓設(shè)計與互聯(lián)網(wǎng)技術(shù)結(jié)合,創(chuàng)造個性化、用戶體驗好的作品,建站類型包括:成都做網(wǎng)站、成都網(wǎng)站設(shè)計、企業(yè)官網(wǎng)、英文網(wǎng)站、手機端網(wǎng)站、網(wǎng)站推廣、域名注冊、網(wǎng)頁空間、企業(yè)郵箱。業(yè)務(wù)覆蓋吳興地區(qū)。
比如:設(shè)置一個用戶的過期時間,前端到底以什么格式傳遞參數(shù)呢?時間戳?還是2019-12-01 22:13:00這種格式?還是其他格式?
今天我就來總結(jié)一下SpringBoot Web應(yīng)用接口接收時間類型參數(shù)的問題解決方案。
注:目前我對Spring源碼的掌握還不是很好,所以這一篇僅僅總結(jié)一下解決方法,后面感悟多了會重寫一下!
示例代碼請前往:https://github.com/laolunsi/spring-boot-examples
經(jīng)過簡單的測試,我們知道:
之前有接觸過類似的解決辦法,在類的屬性上加上@DateFormat注解,解決單個時間參數(shù)問題。
但是局限較多。
理想的解決方案是:一次配置,全局通用,多種格式,自動轉(zhuǎn)換(朗朗上口嗷)
一、源碼簡要分析
首先我們來簡單分析一下源碼:
深入的就不解釋了(我現(xiàn)在也不懂🤦♂️)
簡單來說,接口接收的參數(shù),首先被HandlerMethodArgumentResolver的實現(xiàn)類處理了一遍,將其轉(zhuǎn)換為我們需要的格式。
這里主要分為兩種情況:
二、解決方法
2.1 自定義converter
針對第一種情況,我們需要配置converter,這里介紹兩種方法:
首先我們這里需要一個DateConverter類,這個類實現(xiàn)了Converter接口,重寫了其中的convert方法,將String轉(zhuǎn)成Date類型:
我們這里定義了三種處理格式:
/** * 日期轉(zhuǎn)換類 * 將標準日期、標準日期時間、時間戳轉(zhuǎn)換成Date類型 */ /*@Deprecated*/ public class DateConverter implements Converter{ private Logger logger = LoggerFactory.getLogger(DateConverter.class); private static final String dateFormat = "yyyy-MM-dd HH:mm:ss"; private static final String shortDateFormat = "yyyy-MM-dd"; private static final String timeStampFormat = "^\\d+$"; @Override public Date convert(String value) { logger.info("轉(zhuǎn)換日期:" + value); if(value == null || value.trim().equals("") || value.equalsIgnoreCase("null")) { return null; } value = value.trim(); try { if (value.contains("-")) { SimpleDateFormat formatter; if (value.contains(":")) { formatter = new SimpleDateFormat(dateFormat); } else { formatter = new SimpleDateFormat(shortDateFormat); } return formatter.parse(value); } else if (value.matches(timeStampFormat)) { Long lDate = new Long(value); return new Date(lDate); } } catch (Exception e) { throw new RuntimeException(String.format("parser %s to Date fail", value)); } throw new RuntimeException(String.format("parser %s to Date fail", value)); } }
注:這個DateConverter類在下面都會用到。
import com.aegis.yqmanagecenter.config.date.DateConverter; import com.aegis.yqmanagecenter.model.bean.common.JsonResult; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.propertyeditors.CustomDateEditor; import org.springframework.core.convert.support.GenericConversionService; import org.springframework.http.HttpStatus; import org.springframework.web.bind.WebDataBinder; import org.springframework.web.bind.annotation.*; import java.beans.PropertyEditorSupport; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Date; @ControllerAdvice public class ControllerHandler { private Logger logger = LoggerFactory.getLogger(ControllerHandler.class); @InitBinder public void initBinder(WebDataBinder binder) { // 方法1,注冊converter GenericConversionService genericConversionService = (GenericConversionService) binder.getConversionService(); if (genericConversionService != null) { genericConversionService.addConverter(new DateConverter()); } // 方法2,定義單格式的日期轉(zhuǎn)換,可以通過替換格式,定義多個dateEditor,代碼不夠簡潔 DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); CustomDateEditor dateEditor = new CustomDateEditor(df, true); binder.registerCustomEditor(Date.class, dateEditor); // 方法3,同樣注冊converter binder.registerCustomEditor(Date.class, new PropertyEditorSupport() { @Override public void setAsText(String text) throws IllegalArgumentException { setValue(new DateConverter().convert(text)); } }); } }
注:上面的三個方法都是利用@ControllerAdvice+@InitBinder來設(shè)置時間參數(shù)處理的,其中1和3都可以設(shè)置DateConverter,而方法2只能一個一個手動設(shè)置格式。
這里需要注意,上述配置方法都無法解決Json格式數(shù)據(jù)中的時間參數(shù)接收問題。下面我們直接看完整的解決方案——將DateConverter注冊為組件,并使用ObjectMapper來配置時間參數(shù)的序列化(接口返回值)和反序列化形式(接口接收參數(shù))。
2.2 配置ObjectMapper以及完整解決方案
完整的解決方案:
/** * 日期轉(zhuǎn)換配置 * 解決@RequestAttribute、@RequestParam和@RequestBody三種類型的時間類型參數(shù)接收與轉(zhuǎn)換問題 */ @Configuration public class DateConfig { /** * 默認日期時間格式 */ public static final String DEFAULT_DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss"; /** * Date轉(zhuǎn)換器,用于轉(zhuǎn)換RequestParam和PathVariable參數(shù) */ @Bean public ConverterdateConverter() { return new DateConverter(); } /** * Json序列化和反序列化轉(zhuǎn)換器,用于轉(zhuǎn)換Post請求體中的json以及將我們的對象序列化為返回響應(yīng)的json * 使用@RequestBody注解的對象中的Date類型將從這里被轉(zhuǎn)換 */ @Bean public ObjectMapper objectMapper(){ ObjectMapper objectMapper = new ObjectMapper(); objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); objectMapper.disable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE); JavaTimeModule javaTimeModule = new JavaTimeModule(); //Date序列化和反序列化 javaTimeModule.addSerializer(Date.class, new JsonSerializer () { @Override public void serialize(Date date, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException { SimpleDateFormat formatter = new SimpleDateFormat(DEFAULT_DATE_TIME_FORMAT); String formattedDate = formatter.format(date); jsonGenerator.writeString(formattedDate); } }); javaTimeModule.addDeserializer(Date.class, new JsonDeserializer () { @Override public Date deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException { return new DateConverter().convert(jsonParser.getText()); } }); objectMapper.registerModule(javaTimeModule); return objectMapper; } }
參考:簡書-Spring中使用LocalDateTime、LocalDate等參數(shù)作為入?yún)?/p>
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持創(chuàng)新互聯(lián)。