说明
@RestController
public class HelloController {
@PostMapping("/sayFrom")
public User sayFrom(User user) {
return user;
}
}
上面代码定一个了一个接口,参数上User对象,参数值也是User对象,客户端请求如下:
![56067c2bcac0262cdefc80f5c3a3b6e9.png](https://i-blog.csdnimg.cn/blog_migrate/d91f494f71ac4b96c324433c346693d5.jpeg)
上面的参数解析和返回值处理默认都是使用Spring内建的解析器和处理器处理的。
默认的内建处理器
参数解析:
![d6c9edd920f090368281ca3deda5beb7.png](https://i-blog.csdnimg.cn/blog_migrate/21d772197c51be1379d458d52057f7f6.jpeg)
上面可以看到,Spring内建的参数解析器有26个,根据具体的参数类型选择对应的解析器(根据supportsParameter方法进行判断),此时获取的对应的解析器为 ServletModelAttributeMethodProcessor,参数解析如下:
![eaa9f30aad2a486c66f84e56670f0186.png](https://i-blog.csdnimg.cn/blog_migrate/585a6367a53ead4d632ef95a04a9ce1f.jpeg)
具体解析过程,大家可以自行看下。
返回值处理:
![a97d8288863c7a6059d9bac9eedbdd87.png](https://i-blog.csdnimg.cn/blog_migrate/fcf66092e6aa3d5e0c479fd45f41d268.jpeg)
从代码中可以看到返回值最终是使用内建的处理器 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](https://i-blog.csdnimg.cn/blog_migrate/aefbd620efe29f6238f3edf177e07d9b.jpeg)
![1b4057012e3cfa56328daf1ef011cd10.png](https://i-blog.csdnimg.cn/blog_migrate/2237e4d9724339fe7cb776805fc1d0a6.jpeg)
![96398f9ad90dbf404151f23da9eec256.png](https://i-blog.csdnimg.cn/blog_migrate/3625ef900b5c117b7b41c1c7b1f3a441.jpeg)
上面执行结果中可以看出自定义解析器已经生效了,下面我们看下返回值如何处理的。
自定义返回值处理器
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](https://i-blog.csdnimg.cn/blog_migrate/f2ca919f0bf422ab9b8c7d0403abaaf1.jpeg)
从结果中可以看出我们自定义的返回值处理器已经生效了。