SpringMvc HttpMessageConverter之@ResponseBody

我们先看HttpMessageConverter的示意图,从图片可以看出它是多么的重要。在一条必经之路截道了的感觉。

先上我的测试例子:

jsp页面:

<%@ page language="java contentTypetext/html; charset=UTF-8
    pageEncodingUTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<htmlheadmeta http-equiv="Content-Type" content="text/html; charset=UTF-8"title>Insert title here</script type="text/javascript" src="<%=request.getContextPath() %>/js/jquery-3.1.1.min.js"></scriptbody>
    ="text/javascript">
    $(function(){
        var args{};
         url<%=request.getContextPath()%>/testJson;
        $.post(url,args,(result){
            alert(result)
        })
    })
    >

 

java代码:

@Controller
public class TestJson {
    /**
     * 如何返回json数据
     * 1,加入3个jackson的jar包
     * 2,编写对应的方法,使其返回json对应的对象或方法
     * 3,在方法中加入@ResponseBody注解
     */
    
    @Autowired
    private EmployeeDAO employeeDao;
    
    @RequestMapping("testJson")
    @ResponseBody
    public Collection<Employee> testJson(){
        return employeeDao.getAll().values();
    }
}

首先我们要知道HttpMessageConverter和@ResponseBody之间有什么联系。

  如果不使用@ResponseBody注解,那么我在业务方法(@RequestMapping注解)的Model中,或者Map中放入的值和我返回的字符串将组成ModelAndView对象。然后渲染视图。

  使用了@ResponseBody之后,会选择适当的处理器,比如json处理器,将我返回的值转换成相应的格式,写入到HttpOutputMessage中,写入到Response的body中去。

下面我们就先看看使用了@ResponseBody时,SpringMvc为我们做了什么?

从DispatcherServlet的handle方法

mv = ha.handle(processedRequest,response,mappedHandler.getHandler());

开始-->AbstractHandlerMethodAdapter类的handleInternal方法-->RequestMappingHandlerAdapter类的invokeHandleMethod方法-->ServletInvocableHandlerMethod类的invokeAndHandle方法

final void invokeAndHandle(ServletWebRequest webRequest,ModelAndViewContainer mavContainer,Object... providedArgs) throws Exception {

        Object returnValue = invokeForRequest(webRequest,mavContainer,providedArgs);

        setResponseStatus(webRequest);

        if (returnValue == null) {
            if (isRequestNotModified(webRequest) || hasResponseStatus() || mavContainer.isRequestHandled()) {
                mavContainer.setRequestHandled(true);
                ;
            }
        }
        else if (StringUtils.hasText(this.responseReason)) {
            mavContainer.setRequestHandled();
            ;
        }

        mavContainer.setRequestHandled(false);

        try {
       //处理返回的Map集合
.returnValueHandlers.handleReturnValue(returnValue,getReturnValueType(returnValue),webRequest); } catch (Exception ex) { if (logger.isTraceEnabled()) { logger.trace(getReturnValueHandlingErrorMessage("Error handling return value",returnValue),ex); } throw ex; } }

从标红部分点进去,

    @Override
     handleReturnValue(
            Object returnValue,MethodParameter returnType,NativeWebRequest webRequest)
             Exception {
        //匹配到的返回值处理器是RequestResponseBodyMethodProcessor
        HandlerMethodReturnValueHandler handler = getReturnValueHandler(returnType);
        Assert.notNull(handler,"Unknown return value type [" + returnType.getParameterType().getName() + "]");
//处理器处理集合 handler.handleReturnValue(returnValue,returnType,webRequest); }

在从标红行点进去,

@Override
     handleReturnValue(Object returnValue,1)"> IOException,HttpMediaTypeNotAcceptableException {
        //表示是直接返回页面的body,个人理解,不够准确
        mavContainer.setRequestHandled();
        if (returnValue != ) {
       //把map转为json写到outputMessage writeWithMessageConverters(returnValue,webRequest); } }

再往后就是调用系统默认处理json的类MappingJackson2HttpMessageConverter来转换成json数据。

至于如何返回给页面,等下回填坑吧。

相关文章

这篇文章主要介绍了spring的事务传播属性REQUIRED_NESTED的原...
今天小编给大家分享的是一文解析spring中事务的传播机制,相...
这篇文章主要介绍了SpringCloudAlibaba和SpringCloud有什么区...
本篇文章和大家了解一下SpringCloud整合XXL-Job的几个步骤。...
本篇文章和大家了解一下Spring延迟初始化会遇到什么问题。有...
这篇文章主要介绍了怎么使用Spring提供的不同缓存注解实现缓...