SpringMVC自定义ArgumentResolver实现自定义消息类型转换

上篇的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的课程,收获颇多,感谢大佬

发布了98 篇原创文章 · 获赞 9 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/Mutou_ren/article/details/104083988
今日推荐