Spring 支持 Restful风格 源码分析

Spring 支持 Restful风格 源码分析

Restful风格API接口开发springMVC -- json
Restful 请求处理 和 响应

RequestResponseBodyMethodProcessor 
    return parameter.hasParameterAnnotation(RequestBody.class); //解析方法-属性带有@RequestBody的参数

for (HttpMessageConverter<?> converter : this.messageConverters) { } //遍历所有的消息转换器,包括我们自定义的

this.messageConverters // 在什么时候初始化的??

AnnotationMethodHandlerAdapter -- RequestMappingHandlerAdapter //配置文件 -- 实际操作的

RequestMappingHandlerAdapter.afterPropertiesSet() //由于RequestMappingHandlerAdapter实现InitializingBean接口,
所以容器初始化时(启动的时候) 就会去执行这个方法,完成一些初始化的工作

RequestMappingHandlerAdapter.getDefaultArgumentResolvers() //完成如下一些参数解析器类的初始化

resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), false));
resolvers.add(new RequestParamMapMethodArgumentResolver());
resolvers.add(new PathVariableMethodArgumentResolver());
resolvers.add(new PathVariableMapMethodArgumentResolver());
resolvers.add(new MatrixVariableMethodArgumentResolver());
resolvers.add(new MatrixVariableMapMethodArgumentResolver());
resolvers.add(new ServletModelAttributeMethodProcessor(false));
resolvers.add(new RequestResponseBodyMethodProcessor(getMessageConverters()));
resolvers.add(new RequestPartMethodArgumentResolver(getMessageConverters()));
resolvers.add(new RequestHeaderMethodArgumentResolver(getBeanFactory()));
resolvers.add(new RequestHeaderMapMethodArgumentResolver());
resolvers.add(new ServletCookieValueMethodArgumentResolver(getBeanFactory()));
resolvers.add(new ExpressionValueMethodArgumentResolver(getBeanFactory()));

// Type-based argument resolution
resolvers.add(new ServletRequestMethodArgumentResolver());
resolvers.add(new ServletResponseMethodArgumentResolver());
resolvers.add(new HttpEntityMethodProcessor(getMessageConverters()));
resolvers.add(new RedirectAttributesMethodArgumentResolver());
resolvers.add(new ModelMethodProcessor());
resolvers.add(new MapMethodProcessor());
resolvers.add(new ErrorsMethodArgumentResolver());
resolvers.add(new SessionStatusMethodArgumentResolver());
resolvers.add(new UriComponentsBuilderMethodArgumentResolver());


RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter //同时该类还继承 

private List<HttpMessageConverter<?>> messageConverters; //且有成员变量消息转换器的list集合

//并完成默认构造器来注册默认的消息转换器
public RequestMappingHandlerAdapter() {
    StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter();
    stringHttpMessageConverter.setWriteAcceptCharset(false); // See SPR-7316

    this.messageConverters = new ArrayList<HttpMessageConverter<?>>();
    this.messageConverters.add(new ByteArrayHttpMessageConverter());
    this.messageConverters.add(stringHttpMessageConverter);
    this.messageConverters.add(new SourceHttpMessageConverter<Source>());
    this.messageConverters.add(new AllEncompassingFormHttpMessageConverter());
}

//而对应自定义的AnnotationMethodHandlerAdapter 依赖的MappingJacksonHttpMessageConverter,通过xml文件的解析可以将消息转换器注册到RequestMappingHandlerAdapter

//判断给定的类是否可以由这个转换器读取。
if (converter.canRead(targetClass, contentType)) { 
    //使用这个消息转换器去转换
    return ((HttpMessageConverter<T>) converter).read(targetClass, inputMessage);
}

StringHttpMessageConverter //String请求的消息转换器

//去解析处理clazz:是一个String的类型,inputMessage:是一个请求输入流的类型
StringHttpMessageConverter{return readInternal(clazz, inputMessage);} 

//把HttpRequest请求参数解析成一个StringBuilder,并返回
return StreamUtils.copyToString(inputMessage.getBody(), charset);

//回去socket请求的输入流,解析输入流于StringBuilder,并返回给调用者
public static String copyToString(InputStream in, Charset charset) throws IOException {
    Assert.notNull(in, "No InputStream specified");
    StringBuilder out = new StringBuilder();
    InputStreamReader reader = new InputStreamReader(in, charset);
    char[] buffer = new char[BUFFER_SIZE];
    int bytesRead = -1;
    while ((bytesRead = reader.read(buffer)) != -1) {
        out.append(buffer, 0, bytesRead);
    }
    return out.toString();
}


//前台请求虽然有多个消息转换器,但实际就只有一个去处理请求,StringHttpMessageConverter,所以我们经常说前后台交互就是String类型
//当StringHttpMessageConverter处理完了就直接返回处理结果了,就不会再执行别的消息转换器了
//所以在controller配置入参转换器是没有意义的,如:@ResponeBody String param,是体现不了json转换器的

//拿到通过请求参数数组args来调用具体Method的invok(),调用成功后返回调用结果,returnValue为值
ServletInvocableHandlerMethod.invokeAndHandle(){ Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);}


//如:public Map | String | List xxx 代表了请求后响应也对应了有多种情况,对应各种类型
//处理返回值,也对应了返回值类型的装换
HandlerMethodReturnValueHandlerComposite.handleReturnValue()

//还是对应了Handler来处理返回值,还是采用相同的策略模式来处理
HandlerMethodReturnValueHandler handler = getReturnValueHandler(returnType);
handler.handleReturnValue(returnValue, returnType, mavContainer, webRequest);

//这是RequestMappingHandlerAdapter在初始化的时候所注册的一些实例,就包括了方法参数解析器和方法返回参数解析器相关类的初始化
public void afterPropertiesSet() {
    if (this.argumentResolvers == null) {
        List<HandlerMethodArgumentResolver> resolvers = getDefaultArgumentResolvers();
        this.argumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
    }
    if (this.initBinderArgumentResolvers == null) {
        List<HandlerMethodArgumentResolver> resolvers = getDefaultInitBinderArgumentResolvers();
        this.initBinderArgumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
    }
    if (this.returnValueHandlers == null) {
        List<HandlerMethodReturnValueHandler> handlers = getDefaultReturnValueHandlers();
        this.returnValueHandlers = new HandlerMethodReturnValueHandlerComposite().addHandlers(handlers);
    }
    initControllerAdviceCache();
}


//当返回值是String类型的,对应的HandlerMethodReturnValueHandler就会去处理对应返回类型
//将返回值包装到ModelAndViewContainer容器中
ViewNameMethodReturnValueHandler.handleReturnValue(){ //其中ModelAndViewContainer mavContainer
    else if (returnValue instanceof String) {
        String viewName = (String) returnValue;
        mavContainer.setViewName(viewName); //返回的值就是一个视图的名称,就是一个具体的页面,
        if (isRedirectViewName(viewName)) {
            mavContainer.setRedirectModelScenario(true);
        }
}


//这个方法是支持@ResponeBody Map | String | List 以json类型返回的调用方法
RequestResponseBodyMethodProcessor.handleReturnValue(){
    public void handleReturnValue(Object returnValue, MethodParameter returnType,
            ModelAndViewContainer mavContainer, NativeWebRequest webRequest)
            throws IOException, HttpMediaTypeNotAcceptableException {

        mavContainer.setRequestHandled(true); //*****很重要
        if (returnValue != null) {
            writeWithMessageConverters(returnValue, returnType, webRequest);
        }
    }
}

//遍历消息转换器
for (HttpMessageConverter<?> messageConverter : messageConverters) { //和入参使用的消息转换器是一致的
    //判断是否写 
    if (messageConverter.canWrite(returnValueClass, selectedMediaType)) { 
        //使用消息转换器回写给调用者
        ((HttpMessageConverter<T>) messageConverter).write(returnValue, selectedMediaType, outputMessage);
        return;
    }
}

//创建ServletServerHttpRequest和ServletServerHttpResponse
AbstractMessageConverterMethodProcessor.writeWithMessageConverters(T returnValue, //调用方法返回的值,如string | "5555" map | "name:55"
                                                MethodParameter returnType, //HandlerMethodReturnValueHandler
                                        NativeWebRequest webRequest)
    throws IOException, HttpMediaTypeNotAcceptableException {
ServletServerHttpRequest inputMessage = createInputMessage(webRequest); 
ServletServerHttpResponse outputMessage = createOutputMessage(webRequest);
writeWithMessageConverters(returnValue, returnType, inputMessage, outputMessage);
}

//object:是调用方法后的返回值 outputMessage:HttpOutputMessage 响应值
MappingJacksonHttpMessageConverter.writeInternal(Object object, HttpOutputMessage outputMessage)

//调用jackson api 
this.objectMapper.writeValue(jsonGenerator, object);

//调用jackson api后将调用后的数据刷入outputMessage实体中(相当于给调用者的返回)
writeInternal(t, outputMessage);
outputMessage.getBody().flush();

//重要,负者参数的解析和参数的返回
RequestMappingHandlerAdapter.invokeAndHandle(){
    Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);//参数解析***
    setResponseStatus(webRequest);
    if (returnValue == null) {
        if (isRequestNotModified(webRequest) || hasResponseStatus() || mavContainer.isRequestHandled()) {
            mavContainer.setRequestHandled(true);
            return;
        }
    }
    else if (StringUtils.hasText(this.responseReason)) {
        mavContainer.setRequestHandled(true); //请求类别***
        return;
    }

    mavContainer.setRequestHandled(false);

    try {
        //参数返回***
        this.returnValueHandlers.handleReturnValue(returnValue, getReturnValueType(returnValue), mavContainer, webRequest);
    }
}

//很重要** 相当于包装成ModelAndView返回给调用者
return RequestMappingHandlerAdapter.getModelAndView(mavContainer, modelFactory, webRequest);

//获取视图和实体信息
private ModelAndView getModelAndView(ModelAndViewContainer mavContainer,
        ModelFactory modelFactory, NativeWebRequest webRequest) throws Exception {

    modelFactory.updateModel(webRequest, mavContainer);
    if (mavContainer.isRequestHandled()) { //当为@ResponeBody的时候为true,就直接返回给了数据,没有返回对应的页面
        return null;
    }
    ModelMap model = mavContainer.getModel();
    ModelAndView mav = new ModelAndView(mavContainer.getViewName(), model); // 构造视图响应
    if (!mavContainer.isViewReference()) {
        mav.setView((View) mavContainer.getView());
    }
    if (model instanceof RedirectAttributes) {
        Map<String, ?> flashAttributes = ((RedirectAttributes) model).getFlashAttributes();
        HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
        RequestContextUtils.getOutputFlashMap(request).putAll(flashAttributes);
    }
    return mav;
}

//在此之前已经完成了ModelAndView实体的构建,接下来要完成视图的解析和渲染
DispatcherServlet.processDispatchResult() //进程调度的结果
{
    render(mv, request, response); //渲染
}

// 解析视图
view = resolveViewName(mv.getViewName(), mv.getModelInternal(), locale, request);

// 遍历所有的视图解析器去解析视图,如internalResolverView
for (ViewResolver viewResolver : this.viewResolvers) {
    View view = viewResolver.resolveViewName(viewName, locale); //viewName : 就是对应的返回页面
    if (view != null) {
        return view;
    }
}

InternalResourceView.renderMergedOutputModel(){
    // 确定请求调度程序的路径。如:WEB-INFO/index.jsp
    String dispatcherPath = prepareForRendering(requestToExpose, response);
    //为目标资源获取一个RequestDispatcher(通常是一个JSP)。
    RequestDispatcher rd = getRequestDispatcher(requestToExpose, dispatcherPath);
}

RequestDispatcher //就相当于一个servlet
rd.forward(requestToExpose, response); //可以做相应的转发工作,转发到一个页面


mappedHandler.triggerAfterCompletion(request, response, null); //接着调用后置过滤器

MappingJacksonHttpMessageConverter 的定义的作用,如果在配置文件中没有定义消息转换器,并且spring也没给你做消息转换
这样在controller中使用@ResponeBody 是不支持Restful - json 风格的响应的

//在实际返回值的时候是交给具体的自定义messageConverters消息转换器来转换的,不注册这个消息装换器是无法正常解析给调用者返回值的json
for (HttpMessageConverter<?> messageConverter : messageConverters) {
    if (messageConverter.canWrite(returnValueClass, selectedMediaType)) {
        ((HttpMessageConverter<T>) messageConverter).write(returnValue, selectedMediaType, outputMessage);
        if (logger.isDebugEnabled()) {
            logger.debug("Written [" + returnValue + "] as \"" + selectedMediaType + "\" using [" +
                    messageConverter + "]");
        }
        return;
    }
}

//不加这个MappingJacksonHttpMessageConverter 是无法直接支持restful - json格式的

//处理给前端返回map,list,string 还可以直接返回一个实体,这个实体可以用@ResponeBody+配置json装换器,来让它支持restful的响应

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值