SpringMVC-View和ViewResolver

2020-07-26  本文已影响0人  张明学

springmvc由HandlerAdapter执行具体的handler后,返回的是ModelAndView对象,如何映射到具体的视图,生成页面返回到浏览器,就需要ViewResolver和View来操作了。

View的解析流程

1、org.springframework.web.servlet.DispatcherServlet#doDispatch

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
   
   try {
      ModelAndView mv = null;
      Exception dispatchException = null;
      try {
         ...
         // Actually invoke the handler.
         mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
                ...
      }
      // 目标方法执行完成后的视图处理
      processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
      ...
   }
   ....
}

2、在processDispatchResult方法中调用了DispatcherServlet#render方法

private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,
      @Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv,
      @Nullable Exception exception) throws Exception {
   ....
   // Did the handler return a view to render?
   if (mv != null && !mv.wasCleared()) {
      render(mv, request, response);
      ...
   }
}

3、org.springframework.web.servlet.DispatcherServlet#render

protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {
     ...
   View view;
   String viewName = mv.getViewName();
   if (viewName != null) {
      // 根据viewName找查resolve
      view = resolveViewName(viewName, mv.getModelInternal(), locale, request);
     ...
   }
   else {
      // No need to lookup: the ModelAndView object contains the actual View object.
      view = mv.getView();
   }
     ...
   try {
      if (mv.getStatus() != null) {
         response.setStatus(mv.getStatus().value());
      }
      // 获取渲染的视图
      view.render(mv.getModelInternal(), request, response);
   }
   ...
}

resolveViewName方法如下:

protected View resolveViewName(String viewName, @Nullable Map<String, Object> model,
      Locale locale, HttpServletRequest request) throws Exception {

   if (this.viewResolvers != null) {
      for (ViewResolver viewResolver : this.viewResolvers) {
         View view = viewResolver.resolveViewName(viewName, locale);
         if (view != null) {
            return view;
         }
      }
   }
   return null;
}

viewResolvers则是DispatcherServlet初始化时设置的,并且经过order排序之后的

4、org.springframework.web.servlet.view.AbstractView#render

public void render(@Nullable Map<String, ?> model, HttpServletRequest request,
      HttpServletResponse response) throws Exception {
   Map<String, Object> mergedModel = createMergedOutputModel(model, request, response);
   prepareResponse(reuest, response);
   // 获取OutputStreaml输出的内容,不用同视图解决有不同的实现
   renderMergedOutputModel(mergedModel, getRequestToExpose(request), response);
}

FastJsonJsonView的renderMergedOutputModel实现

protected void renderMergedOutputModel(Map<String, Object> model, //
                                       HttpServletRequest request, //
                                       HttpServletResponse response) throws Exception {

    ByteArrayOutputStream outnew = new ByteArrayOutputStream();
        
    int len = JSON.writeJSONString(outnew, //
            fastJsonConfig.getCharset(), //
            value, //
            fastJsonConfig.getSerializeConfig(), //
            fastJsonConfig.getSerializeFilters(), //
            fastJsonConfig.getDateFormat(), //
            JSON.DEFAULT_GENERATE_FEATURE, //
            fastJsonConfig.getSerializerFeatures());
  
    ServletOutputStream out = response.getOutputStream();
    outnew.writeTo(out);
    outnew.close();
    out.flush();
}

InternalResourceView的renderMergedOutputModel的实现

protected void renderMergedOutputModel(
      Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
   exposeModelAsRequestAttributes(model, request);
   exposeHelpers(request);
   String dispatcherPath = prepareForRendering(request, response);
   RequestDispatcher rd = getRequestDispatcher(request, dispatcherPath);
   if (useInclude(request, response)) {
      response.setContentType(getContentType());
      rd.include(request, response);
   }else {
      rd.forward(request, response);
   }
}

常用的ViewResolver

ViewResolver的主要作用是把一个逻辑上的视图名称解析为一个真正的视图,SpringMVC中用于把View对象呈现给客户端的是View对象本身,而ViewResolver只是把逻辑视图名称解析为对象的View对象。View接口的主要作用是用于处理视图,然后返回给客户端。

IDE根据一个接口生产它的关系图方法:接口下右键Diagrams->Show Diagram,然后选中接口右键Show Implementations

ViewResolver.png
上一篇 下一篇

猜你喜欢

热点阅读