需求: 为 @RequestBody 添加 application/x-www-form-urlencoded 解析
根据源码得到
在 HandlerMethodArgumentResolverComposite 类中做循环判断,解析指定数据类型。
所有解析类型都实现自接口 HandlerMethodArgumentResolver
系统中默认共有38中数据解析类,我们添加自己的解析类即可
根据源码所得:
解析 application/json 的类为 RequestResponseBodyMethodProcessor
解析 application/x-www-form-urlencoded 的类为 RequestParamMapMethodArgumentResolver
解析类 RequestBodyHandlerMethodArgumentResolver.java
package top.luoqiz.common.web.resolver;import cn.hutool.http.ContentType;import org.springframework.core.MethodParameter;import org.springframework.web.bind.annotation.RequestBody;import org.springframework.web.bind.support.WebDataBinderFactory;import org.springframework.web.context.request.NativeWebRequest;import org.springframework.web.method.annotation.RequestParamMapMethodArgumentResolver;import org.springframework.web.method.support.HandlerMethodArgumentResolver;import org.springframework.web.method.support.ModelAndViewContainer;import org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor;import javax.servlet.http.HttpServletRequest;/*** 描述: @RequestBody 注解默认只处理 content-type=application/json 的参数,其解析器为 {@link org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor}* 在此重写,使其支持 content-type=application/x-www-form-urlencoded 的参数 ,其默认解析器为 {@link org.springframework.web.method.annotation.RequestParamMapMethodArgumentResolver}* <p>* 思路 : 通过判断 content-type ,调用其相对应的默认解析器** @author luoqiz*/public class RequestBodyHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver {final String formUrlencoded = ContentType.FORM_URLENCODED.getValue();/*** 解析 content-type=application/json 的默认解析器是RequestResponseBodyMethodProcessor*/private RequestResponseBodyMethodProcessor requestResponseBodyMethodProcessor;/*** 解析 content-type=application/x-www-form-urlencoded 的默认解析器是 RequestParamMapMethodArgumentResolver*/private RequestParamMapMethodArgumentResolver requestParamMapMethodArgumentResolver;/*** 全参构造*/public RequestBodyHandlerMethodArgumentResolver(RequestResponseBodyMethodProcessor requestResponseBodyMethodProcessor,RequestParamMapMethodArgumentResolver requestParamMapMethodArgumentResolver) {this.requestResponseBodyMethodProcessor = requestResponseBodyMethodProcessor;this.requestParamMapMethodArgumentResolver = requestParamMapMethodArgumentResolver;}/*** 当参数前有 @RequestBody 注解时, 解析该参数 会使用此 解析器* <p>* 注:此方法的返回值将决定:是否使用此解析器解析该参数*/@Overridepublic boolean supportsParameter(MethodParameter methodParameter) {return methodParameter.hasParameterAnnotation(RequestBody.class);}/*** 解析参数*/@Overridepublic Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer,NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory)throws Exception {HttpServletRequest request = nativeWebRequest.getNativeRequest(HttpServletRequest.class);if (request == null) {throw new RuntimeException(" request must not be null!");}String contentType = request.getContentType();/** 如果ContentType是application/x-www-form-urlencoded,那么使用ServletModelAttributeMethodProcessor解析器** 注:其实默认的,当系统识别到参数前有@RequestBody注解时,就会走RequestResponseBodyMethodProcessor解析器;这里就* 相当于在走默认的解析器前走了个判断而已。*/if (formUrlencoded.equals(contentType)) {return requestParamMapMethodArgumentResolver.resolveArgument(methodParameter,modelAndViewContainer, nativeWebRequest, webDataBinderFactory);}return requestResponseBodyMethodProcessor.resolveArgument(methodParameter,modelAndViewContainer, nativeWebRequest, webDataBinderFactory);}}
配置解析类 HandlerMethodArgumentResolverConfig.java
package top.luoqiz.common.web.resolver;import org.springframework.context.annotation.Configuration;import org.springframework.web.method.annotation.RequestParamMapMethodArgumentResolver;import org.springframework.web.method.support.HandlerMethodArgumentResolver;import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;import org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor;import javax.annotation.PostConstruct;import java.util.ArrayList;import java.util.List;/*** 参数解析配置** @author luoqiz*/@Configurationpublic class HandlerMethodArgumentResolverConfig {private final RequestMappingHandlerAdapter requestMappingHandlerAdapter;public HandlerMethodArgumentResolverConfig(RequestMappingHandlerAdapter requestMappingHandlerAdapter) {this.requestMappingHandlerAdapter = requestMappingHandlerAdapter;}@PostConstructprivate void addArgumentResolvers() {// 获取到的是不可变的集合List<HandlerMethodArgumentResolver> argumentResolvers =requestMappingHandlerAdapter.getArgumentResolvers();RequestBodyHandlerMethodArgumentResolver requestBodyHandlerMethodArgumentResolver =requestBodyHandlerMethodArgumentResolver(argumentResolvers);// ha.getArgumentResolvers()获取到的是不可变的集合,所以我们需要新建一个集合来放置参数解析器List<HandlerMethodArgumentResolver> myArgumentResolvers =new ArrayList<>(argumentResolvers.size() + 1);// 将自定义的解析器,放置在第一个,并保留原来的解析器myArgumentResolvers.add(requestBodyHandlerMethodArgumentResolver);myArgumentResolvers.addAll(argumentResolvers);requestMappingHandlerAdapter.setArgumentResolvers(myArgumentResolvers);}public RequestBodyHandlerMethodArgumentResolver requestBodyHandlerMethodArgumentResolver(List<HandlerMethodArgumentResolver> resolvers) {// 解析 content-type=application/json 的默认解析器RequestResponseBodyMethodProcessor requestResponseBodyMethodProcessor = null;// 解析 content-type=application/x-www-form-urlencoded 的默认解析器RequestParamMapMethodArgumentResolver requestParamMapMethodArgumentResolver = null;if (resolvers == null) {throw new RuntimeException("argumentResolverList must not be null!");}for (HandlerMethodArgumentResolver argumentResolver : resolvers) {if (requestResponseBodyMethodProcessor != null && requestParamMapMethodArgumentResolver != null) {break;}if (argumentResolver instanceof RequestResponseBodyMethodProcessor) {requestResponseBodyMethodProcessor = (RequestResponseBodyMethodProcessor) argumentResolver;continue;}if (argumentResolver instanceof RequestParamMapMethodArgumentResolver) {requestParamMapMethodArgumentResolver = (RequestParamMapMethodArgumentResolver) argumentResolver;}}if (requestResponseBodyMethodProcessor == null || requestParamMapMethodArgumentResolver == null) {throw new RuntimeException("requestResponseBodyMethodProcessor and "+ " requestParamMapMethodArgumentResolver must not be null!");}return new RequestBodyHandlerMethodArgumentResolver(requestResponseBodyMethodProcessor,requestParamMapMethodArgumentResolver);}}
备注:
RequestResponseBodyMethodProcessor (RequestBody—-map) application/json
RequestParamMapMethodArgumentResolver (RequestParam—-map) application/x-www-form-urlencoded
MapMethodProcessor (no annotion —- map)
RequestParamMethodArgumentResolver (no annotion —-string)

