上一章中介紹了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
友情連接: