spring注解@ResponseBody

今天工作的时候,一不小心就对spring如何通过注解来解析请求好奇了。
查询了资料,spring mvc请求处理大致是这样子的,由DispatcherServlet截获请求,DispatcherServlet通过handlerMappng得到HandlerExecutionChain。然后获得HandlerAdapter。
HandlerAdapter内部对于每个请求生成一个ServletInvocableHandlerMethod进行处理。而ServletInvocableHandlerMethod处理时会分成请求和响应两部分进行。然后ServletInvocableHandlerMethod得到ModelAndView进行处理。
1. 处理请求的时候,会根据ServletInvocableHandlerMethod的属性argumentResolvers(这个属性是它的父类InvocableHandlerMethod中定义的)进行处理,其中argumentResolvers属性是一个HandlerMethodArgumentResolverComposite类(这里使用了组合模式的一种变形),这个类是实现了HandlerMethodArgumentResolver接口的类,里面有各种实现了HandlerMethodArgumentResolver的List集合。

  1. 处理响应的时候,会根据ServletInvocableHandlerMethod的属性returnValueHandlers(自身属性)进行处理,returnValueHandlers属性是一个HandlerMethodReturnValueHandlerComposite类(这里使用了组合模式的一种变形),这个类是实现了HandlerMethodReturnValueHandler接口的类,里面有各种实现了HandlerMethodReturnValueHandler的List集合。

ServletInvocableHandlerMethod的returnValueHandlers和argumentResolvers这两个属性都是在ServletInvocableHandlerMethod进行实例化的时候被赋值的(使用RequestMappingHandlerAdapter的属性进行赋值)。

RequestMappingHandlerAdapter的argumentResolvers和returnValueHandlers这两个属性是在RequestMappingHandlerAdapter进行实例化的时候被Spring容器注入的。
其中默认的ArgumentResolvers:

默认的returnValueHandlers:

使用@ResponseBody注解的话最终返回值会被RequestResponseBodyMethodProcessor这个HandlerMethodReturnValueHandler实现类处理。

我们通过源码发现,RequestResponseBodyMethodProcessor这个类其实同时实现了HandlerMethodReturnValueHandler和HandlerMethodArgumentResolver这两个接口。

RequestResponseBodyMethodProcessor支持的请求类型是Controller方法参数中带有@RequestBody注解,支持的响应类型是Controller方法带有@ResponseBody注解。

RequestResponseBodyMethodProcessor响应的具体处理是使用消息转换器。

处理请求的时候使用内部的readWithMessageConverters方法。

然后会执行父类(AbstractMessageConverterMethodArgumentResolver)的readWithMessageConverters方法。

“`java
protected Object readWithMessageConverters(NativeWebRequest webRequest,
MethodParameter methodParam, Type paramType) throws IOException, HttpMediaTypeNotSupportedException {

    final HttpServletRequest servletRequest = webRequest.getNativeRequest(HttpServletRequest.class);
    HttpInputMessage inputMessage = new ServletServerHttpRequest(servletRequest);

    InputStream inputStream = inputMessage.getBody();
    if (inputStream == null) {
        return handleEmptyBody(methodParam);
    }
    else if (inputStream.markSupported()) {
        inputStream.mark(1);
        if (inputStream.read() == -1) {
            return handleEmptyBody(methodParam);
        }
        inputStream.reset();
    }
    else {
        final PushbackInputStream pushbackInputStream = new PushbackInputStream(inputStream);
        int b = pushbackInputStream.read();
        //如果返回的值是空的
        if (b == -1) {
            //检查有没有Responsebody注解,有抛出一个异常
            return handleEmptyBody(methodParam);
        }
        else {
            pushbackInputStream.unread(b);
        }
        inputMessage = new ServletServerHttpRequest(servletRequest) {
            @Override
            public InputStream getBody() throws IOException {
                // Form POST should not get here
                return pushbackInputStream;
            }
        };
    }

//有数据,则调用父类的方法
return super.readWithMessageConverters(inputMessage, methodParam, paramType);
}

父类的方法readWithMessageConverters,通过对应的media的类型调用HttpMessageConverter方法,遍历并且使用了Read方法。
java
protected Object readWithMessageConverters(HttpInputMessage inputMessage,
MethodParameter methodParam, Type targetType) throws IOException, HttpMediaTypeNotSupportedException {

    MediaType contentType;
    try {
        contentType = inputMessage.getHeaders().getContentType();
    }
    catch (InvalidMediaTypeException ex) {
        throw new HttpMediaTypeNotSupportedException(ex.getMessage());
    }
    if (contentType == null) {
        contentType = MediaType.APPLICATION_OCTET_STREAM;
    }

    Class<?> contextClass = methodParam.getContainingClass();

    for (HttpMessageConverter<?> converter : this.messageConverters) {
        if (converter instanceof GenericHttpMessageConverter) {
            GenericHttpMessageConverter<?> genericConverter = (GenericHttpMessageConverter<?>) converter;
            if (genericConverter.canRead(targetType, contextClass, contentType)) {
                if (logger.isDebugEnabled()) {
                    logger.debug("Reading [" + targetType + "] as \"" +
                            contentType + "\" using [" + converter + "]");
                }
                return genericConverter.read(targetType, contextClass, inputMessage);
            }
        }
        Class<T> targetClass = (Class<T>)
                ResolvableType.forMethodParameter(methodParam, targetType).resolve(Object.class);
        if (converter.canRead(targetClass, contentType)) {
            if (logger.isDebugEnabled()) {
                logger.debug("Reading [" + targetClass.getName() + "] as \"" +
                        contentType + "\" using [" + converter + "]");
            }
            return ((HttpMessageConverter<T>) converter).read(targetClass, inputMessage);
        }
    }

    throw new HttpMediaTypeNotSupportedException(contentType, this.allSupportedMediaTypes);
}

“`

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值