前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >springmvc核心之HandlerMethodReturnValueHandler

springmvc核心之HandlerMethodReturnValueHandler

作者头像
BUG弄潮儿
发布2022-06-30 14:40:09
3400
发布2022-06-30 14:40:09
举报
文章被收录于专栏:JAVA乐园

在springmvc当中@ResponseBody的作用估计很多人都知道,在controller中使用了@ResponseBody就会返回对应的数据结果(json格式),而不是jsp页面或者其他视图。如果不加,那么它就返回了一个具体的视图,如jsp/html等。springmvc是如何做到这个效果的呢?其实springmvc为处理各种返回值提供了很多的处理类,这些处理类大多类都是已ReturnValueHandler或者Processor(包含了参数处理)结尾,这些处理类的核心接口就是:

org.springframework.messaging.handler.invocation.HandlerMethodReturnValueHandler

/**

* Strategy interface to handle the value returned from the invocation of a

* handler method .

*

* @author Arjen Poutsma

* @since 3.1

*/

public interface HandlerMethodReturnValueHandler {

/**

* 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);

}

}

使用案例:

一、定义一个注解(加了注解就进行加密处理)

@Target ( {ElementType.TYPE, ElementType.METHOD})

@Retention (RetentionPolicy.RUNTIME)

@Documented

public @interface ResponseBodyModel {

String encrypt() default true;

}

二、自定义处理器

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;

}

}

}

三、在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>

四、在ctroller使用该注解

@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);

}

}

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2017-12-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 BUG弄潮儿 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档