springmvc自定义参数解析器/类型转换器
Posted 好大的月亮
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了springmvc自定义参数解析器/类型转换器相关的知识,希望对你有一定的参考价值。
概述
有些时候我们需要对请求的入参做自定义的处理,比较常见的就是字符串反序列化时间类型了,常用的像@DateTimeFormat
注解,但是这需要在每个入参的属性上都加上这个注解,比较费手,那么我们就可以注册一个通用的自定义类型转换器来做这个时间的转换。
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime startTime;
自定义类型转换器demo入门认识
使用类型转换器org.springframework.core.convert.converter.Converter
做统一时间处理
一个普通的get请求
package com.fchan.controller;
import com.fchan.params.TestDateParams;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("selfSpringMVC")
public class SelfSpringMVCController
@GetMapping("testDate")
public Object testDate(TestDateParams params)
System.out.println(params);
return null;
一个普通的入参
package com.fchan.params;
import lombok.Data;
import java.io.Serializable;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Date;
@Data
public class TestDateParams implements Serializable
private static final long serialVersionUID = -6513336502447867393L;
private Date date;
private LocalDateTime localDateTime;
private LocalDate localDate;
自定义类型转换
package com.fchan.convert;
import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
@Component
public class SelfDateConvert implements Converter<String, Date>
@Override
public Date convert(String source)
Assert.notNull(source, "时间不能为空");
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
try
return df.parse(source);
catch (ParseException e)
e.printStackTrace();
return null;
package com.fchan.convert;
import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Date;
@Component
public class SelfLocalDateConvert implements Converter<String, LocalDate>
@Override
public LocalDate convert(String source)
Assert.notNull(source, "时间不能为空");
DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd");
return LocalDate.parse(source, df);
package com.fchan.convert;
import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
@Component
public class SelfLocalDateTimeConvert implements Converter<String, LocalDateTime>
@Override
public LocalDateTime convert(String source)
Assert.notNull(source, "时间不能为空");
DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
return LocalDateTime.parse(source, df);
将我们的自定义参数转换添加到spring的参数解析链中
package com.fchan.config;
import com.fchan.convert.SelfDateConvert;
import com.fchan.convert.SelfLocalDateConvert;
import com.fchan.convert.SelfLocalDateTimeConvert;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.format.FormatterRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
@Configuration
public class WebMvcConfigurerAdapter implements WebMvcConfigurer
@Autowired
private SelfDateConvert selfDateConvert;
@Autowired
private SelfLocalDateConvert selfLocalDateConvert;
@Autowired
private SelfLocalDateTimeConvert selfLocalDateTimeConvert;
@Override
public void addFormatters(FormatterRegistry registry)
registry.addConverter(selfDateConvert);
registry.addConverter(selfLocalDateConvert);
registry.addConverter(selfLocalDateTimeConvert);
SpringMVC 执行流程
套用一张网图
参数解析器
所有的参数解析器都实现了HandlerMethodArgumentResolver
这个接口
这是一个典型的策略模式接口,判断当前的方法形参类型是否支持,如果支持就使用该实现类的参数解析器对其解析.
在org.springframework.web.servlet.DispatcherServlet
调用方法前肯定需要解析一下请求中的参数,转成实际controller
中的类型
自定义参数解析器demo
平时接收post
请求我们都是用的@requestBody
接收的请求体,但有些时候想对请求体中的参数在进入controller
之前做一些自定义的转换,这个时候我们就可以自己实现一个注解来解析请求体中的参数。
还是以上面类型转换器中的入参为例,只是这回把入参放入http body
中去.
自定义注解
package com.fchan.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface CurrentTime
自定义解析器解析http body
package com.fchan.methodArgumentResolver;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fchan.annotation.CurrentTime;
import com.fchan.params.TestDateParams;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.MethodParameter;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
@Component
public class CurrentTestTimeHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver
@Autowired
private ObjectMapper myObjectMapper;
/**
* 用于判定是否需要处理该参数分解,返回 true 为需要,并会去调用下面的方法resolveArgument。
*/
@Override
public boolean supportsParameter(MethodParameter parameter)
return parameter.hasParameterAnnotation(CurrentTime.class)
&&
parameter.getParameterType().isAssignableFrom(TestDateParams.class);
/**
* 真正用于处理参数分解的方法,返回的 Object 就是 controller 方法上的形参对象。
*/
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception
//webRequest.getHeader("xxx")
//Map<String, String[]> parameterMap = webRequest.getParameterMap();
String requestBody = getRequestBody(webRequest);
return myObjectMapper.readValue(requestBody, TestDateParams.class);
private static final String JSONBODYATTRIBUTE = "JSON_REQUEST_BODY";
private String getRequestBody(NativeWebRequest webRequest)
HttpServletRequest servletRequest = webRequest.getNativeRequest(HttpServletRequest.class);
String jsonBody = (String) webRequest.getAttribute(JSONBODYATTRIBUTE, NativeWebRequest.SCOPE_REQUEST);
if (jsonBody == null)
try
jsonBody = IOUtils.toString(servletRequest.getInputStream());
webRequest.setAttribute(JSONBODYATTRIBUTE, jsonBody, NativeWebRequest.SCOPE_REQUEST);
catch (IOException e)
throw new RuntimeException(e);
return jsonBody;
注册解析器
成功解析
以上是关于springmvc自定义参数解析器/类型转换器的主要内容,如果未能解决你的问题,请参考以下文章
Spring自定义argumentResolver参数解析器
SpringMVC—— 视图视图解析器自定义转换器格式化转换