在springmvc當中@ResponseBody的做用估計不少人都知道,在controller中使用了@ResponseBody就會返回對應的數據結果(json格式),而不是jsp頁面或者其餘視圖。若是不加,那麼它就返回了一個具體的視圖,如jsp/html等。springmvc是如何作到這個效果的呢?其實springmvc爲處理各類返回值提供了不少的處理類,這些處理類大多類都是已ReturnValueHandler或者Processor(包含了參數處理)結尾,這些處理類的核心接口就是:html
org.springframework.messaging.handler.invocation.HandlerMethodReturnValueHandlerweb
/**spring
* Strategy interface to handle the value returned from the invocation of ajson
* handler method .mvc
*app
* @author Arjen Poutsmajsp
* @since 3.1ide
*/ui
public interface HandlerMethodReturnValueHandler {this
/**
* Whether the given {@linkplain MethodParameter method return type} is
* supported by this handler.
* @param returnType the method return type to check
* @return {@code true} if this handler supports the supplied return type;
* {@code false} otherwise
*/
boolean supportsReturnType(MethodParameter returnType);
/**
* Handle the given return value by adding attributes to the model and
* setting a view or setting the
* {@link ModelAndViewContainer#setRequestHandled} flag to {@code true}
* to indicate the response has been handled directly.
* @param returnValue the value returned from the handler method
* @param returnType the type of the return value. This type must have
* previously been passed to
* {@link #supportsReturnType(org.springframework.core.MethodParameter)}
* and it must have returned {@code true}
* @param mavContainer the ModelAndViewContainer for the current request
* @param webRequest the current request
* @throws Exception if the return value handling results in an error
*/
void handleReturnValue(Object returnValue, MethodParameter returnType,
ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception;
}
HandlerMethodReturnValueHandler包含2個方法:
1.supportsReturnType()決定了哪類類型的返回值將將使用該返回值處理器
2.handleReturnValue()則是主要處理返回值的處理邏輯,而且將處理好的值返回給model,還能夠處理該返回什麼視
HandlerMethodReturnValueHandler是初始化過程:
在初始化RequestMappingHandlerAdapter時候,springmvc默認初始化了一系列返回值處理器,而且提供了自定義的HandlerMethodReturnValueHandler的入口(因此咱們能夠開發本身的HandlerMethodReturnValueHandler)。
private List<HandlerMethodReturnValueHandler> getDefaultReturnValueHandlers() {
List<HandlerMethodReturnValueHandler> handlers = new ArrayList<HandlerMethodReturnValueHandler>();
// Single-purpose return value types
handlers.add(new ModelAndViewMethodReturnValueHandler());
handlers.add(new ModelMethodProcessor());
handlers.add(new ViewMethodReturnValueHandler());
handlers.add(new HttpEntityMethodProcessor(getMessageConverters(), this.contentNegotiationManager));
handlers.add(new CallableMethodReturnValueHandler());
handlers.add(new DeferredResultMethodReturnValueHandler());
handlers.add(new AsyncTaskMethodReturnValueHandler(this.beanFactory));
// Annotation-based return value types
handlers.add(new ModelAttributeMethodProcessor(false));
handlers.add(new RequestResponseBodyMethodProcessor(getMessageConverters(), this.contentNegotiationManager));
// Multi-purpose return value types
handlers.add(new ViewNameMethodReturnValueHandler());
handlers.add(new MapMethodProcessor());
// Custom return value types
if (getCustomReturnValueHandlers() != null) {
handlers.addAll(getCustomReturnValueHandlers());
}
// Catch-all
if (!CollectionUtils.isEmpty(getModelAndViewResolvers())) {
handlers.add(new ModelAndViewResolverMethodReturnValueHandler(getModelAndViewResolvers()));
}
else {
handlers.add(new ModelAttributeMethodProcessor(true));
}
return handlers;
}
HandlerMethodReturnValueHandler的匹配是按照初始化的順序,請看下面的處理器以及對應的處理類型。
處理器 處理類型
針對一種類型
ModelAndViewMethodReturnValueHandler ModelAndView
ModelMethodProcessor Model
ViewMethodReturnValueHandler View
ResponseBodyEmitterReturnValueHandler ResponseEntity<ResponseBodyEmitter>
StreamingResponseBodyReturnValueHandler ResponseEntity<StreamingResponseBody>
HttpHeadersReturnValueHandler HttpHeaders
CallableMethodReturnValueHandler Callable
DeferredResultMethodReturnValueHandler DeferredResult、ListenableFuture、CompletionStage
AsyncTaskMethodReturnValueHandler WebAsyncTask
針對註解
ModelAttributeMethodProcessor @ModelAttribute(require=false)
RequestResponseBodyMethodProcessor @ResponseBody
處理多種類型
ViewNameMethodReturnValueHandler void、CharSequence(V4.2)
MapMethodProcessor Map
自定義返回值處理器
ModelAndViewResolverMethodReturnValueHandler 默認處理,若是以上的都不知足就會進入
ModelAttributeMethodProcessor @ModelAttribute(require=true)
下面以@ResponseBody進行講解一下
@ResponseBody的處理類是RequestResponseBodyMethodProcessor
public boolean supportsReturnType(MethodParameter returnType) {
//處理支持的類型,也就是帶ResponseBody註解的controller
return (returnType.getMethodAnnotation(ResponseBody.class) != null);
}
mavContainer.setRequestHandled(true);//請求是否已經徹底在處理程序中處理過,這裏設置爲true代表已經處理過,無需其餘處理器處理。若是爲fasle,則繼續流轉到對應的視圖,若是設置爲true,則不會再流轉到其餘處理器,默認是false。
public void handleReturnValue(Object returnValue, MethodParameter returnType,
ModelAndViewContainer mavContainer, NativeWebRequest webRequest)
throws IOException, HttpMediaTypeNotAcceptableException {
//若是沒有視圖,則必須設置爲true,不然會返回視圖層
mavContainer.setRequestHandled(true);
if (returnValue != null) {
writeWithMessageConverters(returnValue, returnType, webRequest);
}
}
使用案例:
1、定義一個註解(加了註解就進行加密處理)
@Target ( {ElementType.TYPE, ElementType.METHOD})
@Retention (RetentionPolicy.RUNTIME)
@Documented
public @interface ResponseBodyModel {
String encrypt() default true;
}
2、自定義處理器
CustomerHandlerMethodReturnValueHandler
public class CustomerHandlerMethodReturnValueHandler implements HandlerMethodReturnValueHandler {
@Override
public boolean supportsReturnType(MethodParameter returnType) {
return (returnType.getMethodAnnotation(ResponseBodyModel.class) != null);
}
@Override
public void handleReturnValue(Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {
KingsResponseBody anno = returnType.getMethodAnnotation(KingsResponseBody.class);
mavContainer.setRequestHandled(true);
boolean encrypt = anno.encrypt();
HttpServletResponse response = webRequest.getNativeResponse(HttpServletResponse.class);
response.setContentType("text/json;charset=UTF-8");
try (PrintWriter out = response.getWriter()) {
if(encrypt){
//TODO 加密返回
}else{
//不加密返回
Gson jb = new Gson();
out.write(jb.toJson(returnValue));
out.flush();
}
} catch (IOException e) {
throw e;
}
}
}
3、在spring的配置文件中註冊CustomerHandlerMethodReturnValueHandler處理器
<bean id="handler" class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="customReturnValueHandlers">
<list>
<bean class="com.customer.mvc.CustomerHandlerMethodReturnValueHandler"></bean>
</list>
</property>
</bean>
4、在controller使用該註解
@Controller
public class HandlerMethodReturnValueHandlerDemoController {
@RequestMapping (value="encrypt",method=GET)
@ResponseBodyModel(encrypt=false)
public List<Person> demo() {
Person p = new Person();
p.setName("huangjinjin");
Person p = new Person();
p.setName("huangzl");
return Lists.newArrayList(p,p);
}
}
參考:https://my.oschina.net/kings0/blog/735449
更多技術分享