上一章中介绍了HandlerMethodArgumentResolver
来处理controller方法的参数绑定问题。一个请求中有入参的绑定处理,那么固然也会有响应参数的处理,这一章就来说讲处理返回对象的接口——org.springframework.web.method.support.HandlerMethodReturnValueHandler
。java
public interface HandlerMethodReturnValueHandler { //检验是否支持本处理器处理,返回true会执行handleReturnValue boolean supportsReturnType(MethodParameter returnType); //处理返回值的方法,returnValue便是controller方法中的返回值 void handleReturnValue(Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception;
controllerweb
package com.demo.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; import com.demo.domain.Person; @Controller @RequestMapping("demo2") public class HandlerMethodReturnValueHandlerDemoController { @ResponseBody @RequestMapping(method = RequestMethod.GET) public Person getPerson() { Person person = new Person("Bill", "Gates"); return person; } }
这个controller方法中返回了Person对象,若是使用默认的配置,将会把Person对象以json格式输出。spring
{ "firstName": "Bill", "lastName": "Gates" }
那是由于使用了@ResponseBody
注解,springmvc调用了RequestResponseBodyMethodProcessor
,而RequestResponseBodyMethodProcessor
实现了HandlerMethodReturnValueHandler
接口的handleReturnValue
方法。json
@Override public void handleReturnValue(Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws IOException, HttpMediaTypeNotAcceptableException, HttpMessageNotWritableException { mavContainer.setRequestHandled(true); // Try even with null return value. ResponseBodyAdvice could get involved. writeWithMessageConverters(returnValue, returnType, webRequest); }
看源码可知,RequestResponseBodyMethodProcessor
转交给了HttpMessageConverter
去处理,具体的是转交给了MappingJackson2HttpMessageConverter
,使用Jackson框架把person对象序列化成了json。mvc
实现本身的HandlerMethodReturnValueHandler
:app
package com.demo.mvc.component; import javax.servlet.http.HttpServletResponse; import org.springframework.core.MethodParameter; import org.springframework.util.Assert; import org.springframework.web.context.request.NativeWebRequest; import org.springframework.web.method.support.HandlerMethodReturnValueHandler; import org.springframework.web.method.support.ModelAndViewContainer; import com.demo.domain.Person; public class PersonReturnValueHandler implements HandlerMethodReturnValueHandler { @Override public boolean supportsReturnType(MethodParameter returnType) { return returnType.getParameterType() == Person.class; } @Override public void handleReturnValue(Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception { Assert.isInstanceOf(Person.class, returnValue); mavContainer.setRequestHandled(true); HttpServletResponse response = webRequest.getNativeResponse(HttpServletResponse.class); response.setContentType("text/plain;charset=utf-8"); Person person = (Person) returnValue; response.getWriter().write("通过HandlerMethodReturnValueHandler输出的person:" + person); } }
其中mavContainer.setRequestHandled(true);
标志着这次请求是不是由handler本身控制的,true表示本方法会响应请求。框架
使用本身的实现后,须要去除controller方法上的@ResponseBody
注解,由于咱们再也不须要使用默认的处理器。dom
@RequestMapping(method = RequestMethod.GET) public Person getPerson() { Person person = new Person("Bill", "Gates"); return person; }
发送请求GET http://localhost:8080/demo2ide
响应获得.net
通过HandlerMethodReturnValueHandler输出的person:Bill Gates
发挥想象,给controller的方法加上自定义注解辅助返回值响应。
设置Person前缀注解:
package com.demo.mvc.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface PersonPrefix { public String value() default ""; }
controller
@PersonPrefix("rich man") @RequestMapping(method = RequestMethod.GET) public Person getPerson() { Person person = new Person("Bill", "Gates"); return person; }
handleReturnValue
方法:
@Override public void handleReturnValue(Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception { Assert.isInstanceOf(Person.class, returnValue); mavContainer.setRequestHandled(true); // 获取方法上的注解 PersonPrefix annotation = returnType.getMethodAnnotation(PersonPrefix.class); HttpServletResponse response = webRequest.getNativeResponse(HttpServletResponse.class); response.setContentType("text/plain;charset=utf-8"); Person person = (Person) returnValue; response.getWriter().write(annotation.value() + " : " + person); }
最后响应:
rich man : Bill Gates
友情连接: