使用场景:
有时我们针对特定的返回值类型,希望在Controller处理之后再对结果进行某些特殊的处理,比如修改HTTP的头,或者修改对象等等,这时我们可以采用如下的方式进行统一的处理
1.定义特定的返回值对象
public class Pet {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Pet{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
2.定义返回值类型拦截处理器
public class ReturnHandler implements HandlerMethodReturnValueHandler {
/**
* 该处理程序是否支持给定的方法返回类型(只有返回true才回去调用handleReturnValue)
*/
@Override
public boolean supportsReturnType(MethodParameter methodParameter) {
return methodParameter.getParameterType() == Pet.class;
}
/**
* 处理给定的返回值
* 通过向 ModelAndViewContainer 添加属性和设置视图或者
* 通过调用 ModelAndViewContainer.setRequestHandled(true) 来标识响应已经被直接处理(不再调用视图解析器)
*/
@Override
public void handleReturnValue(Object o, MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer, NativeWebRequest nativeWebRequest) throws Exception {
Assert.isInstanceOf(Pet.class, o);
Pet p=((Pet)o);
p.setName("拦截成功");
/**
* 标识请求是否已经在该方法内完成处理
*/
modelAndViewContainer.setRequestHandled(true);
HttpServletResponse response = nativeWebRequest.getNativeResponse(HttpServletResponse.class);
response.setContentType("text/plain;charset=UTF-8");
response.getWriter().append(JSON.toJSONString(p)).flush();
}
}
3.将返回值拦截器注册到Spring MVC的返回值处理器
@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {
@Override
public void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> returnValueHandlers) {
ReturnHandler returnHandler=new ReturnHandler();
returnValueHandlers.add(returnHandler);
super.addReturnValueHandlers(returnValueHandlers);
}
}
4.编写测试controller
@RequestMapping(value = "h3")
public Object testHeader() {
Pet pet=new Pet();
pet.setName("hello");
return pet;
}
注意点就是 controller的方法不能使用 @RequestBody修饰 ,因为@RequestBody就是告诉Spring MVC使用Map类型的解析器来解析返回值,这样我们自定义的解析器就没有机会被调用了。