自定义参数_SpringMvc如何自定义参数解析器和返回值处理器

说明

@RestControllerpublic class HelloController {​    @PostMapping("/sayFrom")    public User sayFrom(User user) {        return user;    }​}

上面代码定一个了一个接口,参数上User对象,参数值也是User对象,客户端请求如下:

3982a760b9b488f724dd9abdebebd555.png

上面的参数解析和返回值处理默认都是使用Spring内建的解析器和处理器处理的。

默认的内建处理器

参数解析:

9b722652c0b14b67d4f89f04ac41b529.png

上面可以看到,Spring内建的参数解析器有26个,根据具体的参数类型选择对应的解析器(根据supportsParameter方法进行判断),此时获取的对应的解析器为 ServletModelAttributeMethodProcessor ,参数解析如下:

09abcd4a175e19960735bcbca82a7471.png

具体解析过程,大家可以自行看下。

返回值处理:

2bf608208eb70d787751171cb7d7254d.png

从代码中可以看到返回值最终是使用内建的处理器 MappingJackson2HttpMessageConverter进行处理,而且返回的 Content-Type=applicationo/json.

所以,我们要自定义两个东西,一个参数解析器,一个返回值的处理器。

自定义参数解析器

public class MyHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver {    @Override    public boolean supportsParameter(MethodParameter parameter) {        // 参数类型判断        return User.class.isAssignableFrom(parameter.getParameterType());    }    @Override    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {        // TODO do resolve        // 这里参数解析暂时写死        return new User("李四");    }}

定义好解析器之后,要将自定义的解析器放到内建的解析器之前,具体代码如下:

@Configurationpublic class MyWebMvcConfigurer {    @Autowired    private RequestMappingHandlerAdapter requestMappingHandlerAdapter;    @PostConstruct    public void init() {        // 获取内建的resolvers        List buildInList = requestMappingHandlerAdapter.getArgumentResolvers();        // 重建resolvers        List newResolvers = new ArrayList<>(buildInList.size() + 1);        // 自定义的放到第一位        newResolvers.add(new MyHandlerMethodArgumentResolver());        // 再放内建的        newResolvers.addAll(buildInList);        // 重设resolvers        requestMappingHandlerAdapter.setArgumentResolvers(newResolvers);    }}

因为内建的解析器会在自定义的解析器之前调用,所以需要重新调整顺序。

启动服务观察接口调用情况:

a2b54264b8b3364b9049eedf79798de7.png

参数解析

45a0331d69a6f50b60aaa1ed9f9475c6.png
9c3b914811a9fa623ce0b36250364dad.png

上面执行结果中可以看出自定义解析器已经生效了,下面我们看下返回值如何处理的。

自定义返回值处理器

public class MyHttpMessageConverter extends AbstractGenericHttpMessageConverter {    @Override    public boolean canWrite(Type type, Class> clazz, MediaType mediaType) {        // 判断支持处理哪些类型        return User.class.isAssignableFrom(clazz);    }    @Override    protected void writeInternal(User user, Type type, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {        // 测试        user = new User("王五");        // 这里参照 MappingJackson2HttpMessageConverter        ObjectMapper objectMapper = Jackson2ObjectMapperBuilder.json().build();        JsonGenerator generator = objectMapper.getFactory().createGenerator(outputMessage.getBody(), JsonEncoding.UTF8);        ObjectWriter objectWriter = objectMapper.writer();        objectWriter.writeValue(generator, user);        generator.flush();    }}

添加我们自定义的处理器

@Configurationpublic class MyWebMvcConfigurer implements WebMvcConfigurer {    @Override    public void extendMessageConverters(List> converters) {        // 添加自定义处理器,且放到首位        converters.add(0, new MyHttpMessageConverter());    }    ...}

启动服务观察执行结果:

b53052254f9454897580409b719729bc.png

处理器处理之后的结果

从结果中可以看出我们自定义的返回值处理器已经生效了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值