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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值