上篇的convert是基于RequestResponseBodyMethodProcessor
的,因此入参和返回需要加@RequestBody
和@ResponseBody
这里我自己写一个MyArgumentResolver
来摒弃@RequestBody
的限制
@PostMapping(value = "/properties2",
consumes = "text/properties;charset=utf-8")
public Properties properties2(Properties properties){
return properties;
}
public class MyArgumentResolver implements HandlerMethodArgumentResolver {
@Override
public boolean supportsParameter(MethodParameter parameter) {
return parameter.getParameterType().equals(Properties.class);
}
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
String contentType = request.getContentType();
MediaType mediaType = MediaType.parseMediaType(contentType);
Charset charset = mediaType.getCharset()== null ? Charset.forName("utf-8") : mediaType.getCharset();
InputStream inputStream = request.getInputStream();
Reader reader = new InputStreamReader(inputStream,charset);
Properties properties = new Properties();
properties.load(reader);
return properties;
}
}
我们的解析器支持所有入参参数为Properties
类型的解析,具体转换逻辑与上一节的convert基本是一致的,这里其实可以委托给convert进行,SpringMVC内部也是委托进行解析的,这里方便起见直接这里实现了
之后进行注册,但由于自定义的解析器在添加时是在内置解析器的后面的,如下图注释:
因此单纯的使用以下方法注册是行不通的
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
argumentResolvers.add(0,new MyArgumentResolver());
}
这里注册并不会让我们自定义的解析器位于所有解析器的首位,而是在所有自定义解析器的首位,但仍在内置解析器的后面。
由于properties属于map类型,而map类型的解析器是内置解析器,因此我们无法按照预期调用到自己的解析器。
这里采用另一张方法进行解析
@Autowired
private RequestMappingHandlerAdapter adapter;
@PostConstruct
public void init(){
List<HandlerMethodArgumentResolver> old = adapter.getArgumentResolvers();
List<HandlerMethodArgumentResolver> newList = new ArrayList<>(old.size()+1);
newList.add(new MyArgumentResolver());
newList.addAll(old);
adapter.setArgumentResolvers(newList);
}
使用初始化的方法对已经注册过的解析器列表进行覆盖,由于返回的列表是不可更改的,因此要新建数组拷贝实现添加
PS 最近几篇关于SpringMVC转换器的文章都是参考小马哥的SpringBoot的课程,收获颇多,感谢大佬