springmvc 如何返回自定义异常出去_SpringMvc自定义参数解析器和返回值处理器

说明

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

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

56067c2bcac0262cdefc80f5c3a3b6e9.png

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

默认的内建处理器

参数解析:

d6c9edd920f090368281ca3deda5beb7.png

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

eaa9f30aad2a486c66f84e56670f0186.png

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

返回值处理:

a97d8288863c7a6059d9bac9eedbdd87.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("李四");
    }
}

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

@Configuration
public class MyWebMvcConfigurer {
    @Autowired
    private RequestMappingHandlerAdapter requestMappingHandlerAdapter;

    @PostConstruct
    public void init() {
        // 获取内建的resolvers
        List<HandlerMethodArgumentResolver> buildInList = requestMappingHandlerAdapter.getArgumentResolvers();
        // 重建resolvers
        List<HandlerMethodArgumentResolver> newResolvers = new ArrayList<>(buildInList.size() + 1);
        // 自定义的放到第一位
        newResolvers.add(new MyHandlerMethodArgumentResolver());
        // 再放内建的
        newResolvers.addAll(buildInList);
        // 重设resolvers
        requestMappingHandlerAdapter.setArgumentResolvers(newResolvers);
    }
}
因为内建的解析器会在自定义的解析器之前调用,所以需要重新调整顺序。

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

f2f80b7d64f59932ad0b80991b816af2.png

1b4057012e3cfa56328daf1ef011cd10.png

96398f9ad90dbf404151f23da9eec256.png

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

自定义返回值处理器

public class MyHttpMessageConverter extends AbstractGenericHttpMessageConverter<User> {

    @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();
    }
}

添加我们自定义的处理器

@Configuration
public class MyWebMvcConfigurer implements WebMvcConfigurer {

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

启动服务观察执行结果:

a87ccaa94275b2629093bfcfdf10ca2c.png

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值