完成自定义的参数配置器替换默认的参数配置器之后,一个后台接口,既可以处理表单中的参数,也可以处理请求体中的json参数。但有些业务场景,要求一个后台接口,只能处理表单中的参数数据。这时,自定义的参数解析器将无法满足这个业务需求。因此,需要对其进行进一步的改造。
实现方案:增加自定义注解,来区分默认配置和增强配置。如果后台接口标注了自定义的注解,将保持springmvc的原有功能,即只有标注了@RequestBody注解的接口才能处理json数据。
实现步骤:
1、自定义注解
@Target(ElementType.PARAMETER) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface Maintain { }
2、升级参数处理器
public class MyHandlerMethodArgumentResolverV2 implements HandlerMethodArgumentResolver { private final String CONTENT_TYPE_JSON = "application/json"; private RequestResponseBodyMethodProcessor json; private ServletModelAttributeMethodProcessor defaultResolver; public MyHandlerMethodArgumentResolverV2(RequestResponseBodyMethodProcessor json, ServletModelAttributeMethodProcessor defaultResolver ) { this.json = json; this.defaultResolver = defaultResolver; } @Override public boolean supportsParameter(MethodParameter parameter) { return true; } @Override public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception { boolean hasMaintainAnnotation = parameter.hasParameterAnnotation(Maintain.class); if (hasMaintainAnnotation ){ //标注了Maintain注解,表示恢复原样功能 return keepMaintain(parameter,mavContainer,webRequest,binderFactory); }else { return keepEnhance(parameter,mavContainer,webRequest,binderFactory); } } /** * * 保持原有功能 */ protected Object keepMaintain(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory)throws Exception{ if (json.supportsParameter(parameter)){ return json.resolveArgument(parameter,mavContainer,webRequest,binderFactory); } return defaultResolver.resolveArgument(parameter,mavContainer,webRequest,binderFactory); } /** * 省略RequestBody注解 */ protected Object keepEnhance(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory)throws Exception{ String contentType = webRequest.getHeader("Content-Type"); if (StringUtils.startsWithIgnoreCase(contentType,CONTENT_TYPE_JSON)) { return json.resolveArgument(parameter,mavContainer,webRequest,binderFactory); } return defaultResolver.resolveArgument(parameter,mavContainer,webRequest,binderFactory); } }
3、测试类
@RestController @RequestMapping("test02") public class TestController2 { @RequestMapping("test1") public Student test1(@Maintain Student s){ System.out.println(s); return s; } }
4、测试参数