虽然Spring提供了比较完善的参数解析器,但是对于一些特殊的数据类型我们还是需要进行特殊处理,这样会提高代码的复杂度,增加冗余的代码,降低代码可读性和可维护性。所以自定义参数解析器是一个很好的解决方案,是的时候对编码人员也是透明的,非常方便。
还有一点需要注意的是,本篇博客自定义参数解析器使用的方法是通过继承AbstractNamedValueMethodArgumentResolver类实现的,而我们经常使用的注解@RequestParam的参数解析器也是继承自AbstractNamedValueMethodArgumentResolver类。当然还有一种解决方案是通过实现HandlerMethodArgumentResolver接口来实现,但是区别的是如果通过HandlerMethodArgumentResolver接口来实现的话,在解析器中会获取到所有的参数,而我们还需要另外写代码在一串参数中的到我们需要处理的参数再进行处理。而通过继承AbstractNamedValueMethodArgumentResolver类来实现的话,因为AbstractNamedValueMethodArgumentResolver类本身就实现了HandlerMethodArgumentResolver接口,所以我们在参数解析器中得到的是一个一个的参数,处理起来相对简单。
本项目是用SpringBoot写的,自定义用于将字符串解析为Date时间类型的参数解析器。
1、项目目录结构
2、RequestDateParam
package com.xyc.argumentresolver.annotation;import com.xyc.argumentresolver.constant.DateFormatPattern;import java.lang.annotation.*;/*** Created by xyc on /7/27 0027.*/@Documented@Target({ElementType.PARAMETER})@Retention(RetentionPolicy.RUNTIME)public @interface RequestDateParam {String value() default "";DateFormatPattern pattern() default DateFormatPattern.YYYY_MM_DD_HH_MM_SS;boolean required() default true;}
3、DateFormatPattern
package com.xyc.argumentresolver.constant;/*** Created by xyc on /7/29 0029.*/public enum DateFormatPattern {YYYY_MM_DD("yyyy-MM-dd"), YYYY_MM_DD_HH_MM_SS("yyyy-MM-dd hh:mm:ss");private String value;DateFormatPattern(String value) {this.value = value;}public String getValue() {return value;}public void setValue(String value) {this.value = value;}}
4、ArgumentResolverApplication
package com.xyc.argumentresolver;import com.xyc.argumentresolver.resolver.RequestDateParamMethodArgumentResolver;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.web.method.support.HandlerMethodArgumentResolver;import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;import java.util.List;@SpringBootApplicationpublic class ArgumentResolverApplication extends WebMvcConfigurerAdapter {public static void main(String[] args) {SpringApplication.run(ArgumentResolverApplication.class, args);}@Overridepublic void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {argumentResolvers.add(new RequestDateParamMethodArgumentResolver()); //添加自定义参数解析器}}
5、ArgumentResolverController
package com.xyc.argumentresolver.controller;import com.xyc.argumentresolver.annotation.RequestDateParam;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;import org.springframework.web.bind.annotation.RestController;import java.util.Date;/*** Created by xyc on /7/27 0027.*/@RestController@RequestMapping("/argumentResolver")public class ArgumentResolverController {@RequestMapping(value = "/requestDateParamTest", method = RequestMethod.GET)public String requestDateParamTest(@RequestDateParam Date date) {System.out.println(date);return "success value is " + date;}}
6、RequestDateParamMethodArgumentResolver
package com.xyc.argumentresolver.resolver;import com.xyc.argumentresolver.annotation.RequestDateParam;import org.springframework.core.MethodParameter;import org.ponent;import org.springframework.web.bind.MissingServletRequestParameterException;import org.springframework.web.context.request.NativeWebRequest;import org.springframework.web.method.annotation.AbstractNamedValueMethodArgumentResolver;import javax.servlet.ServletException;import java.text.SimpleDateFormat;/*** Created by xyc on /7/29 0029.*/@Componentpublic class RequestDateParamMethodArgumentResolver extends AbstractNamedValueMethodArgumentResolver {/*** 获取当前参数的注解信息** @param methodParameter 需要被解析的Controller参数* @return*/@Overrideprotected NamedValueInfo createNamedValueInfo(MethodParameter methodParameter) {RequestDateParam annotation = (RequestDateParam) methodParameter.getParameterAnnotation(RequestDateParam.class);return new NamedValueInfo(annotation.value(), annotation.required(), (String) null);}/*** 在这里进行参数的类型转换** @param s* @param methodParameter 需要被解析的Controller参数* @param nativeWebRequest 当前request* @return 转换后的参数值* @throws Exception*/@Overrideprotected Object resolveName(String s, MethodParameter methodParameter, NativeWebRequest nativeWebRequest) throws Exception {String content = nativeWebRequest.getParameter(s);if (content == null) {return null;} else {try {RequestDateParam annotation = methodParameter.getParameterAnnotation(RequestDateParam.class);SimpleDateFormat dateFormat = new SimpleDateFormat(annotation.pattern().getValue());return dateFormat.parse(content);} catch (Exception e) {throw new IllegalArgumentException("Date format conversion error", e);}}}/*** 解析器是否支持当前参数** @param methodParameter 需要被解析的Controller参数* @return*/@Overridepublic boolean supportsParameter(MethodParameter methodParameter) {return methodParameter.hasParameterAnnotation(RequestDateParam.class);}/*** 当前参数值为空且注解的默认值也为空则抛出异常** @param name参数名* @param parameter 需要被解析的Controller参数* @throws ServletException*/@Overrideprotected void handleMissingValue(String name, MethodParameter parameter) throws ServletException {throw new MissingServletRequestParameterException(name, parameter.getParameterType().getSimpleName());}}
注意:如果是SpringMVC项目,则需要将参数解析器注册到HandlerAdapter中
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"><property name="requestDateParamMethodArgumentResolver"><list><bean class="com.xyc.argumentresolver.resolver.RequestDateParamMethodArgumentResolver" /></list></property><property name="order" value="0" /></bean>
github地址:/xiayongchao/ArgumentResolver