Spring MVC view parser

What is a view parser

When we learn Spring MVC, when we send a request to a resource controlled by Spring MVC, it will be handled by DispatcherServlet. Spring will analyze the most reasonable Handle among all the request mappings defined in HandleMapping. The Handle is obtained by HandleMapping and handed to the HandleAdapter to Handle the Handle and return a ModelAndView object. After obtaining the ModelAndView object, Spring renders the View to the user. It is the ViewResolver and View that play a role in rendering the View. Sometimes when ModelAndView does not contain a real View, but a logical View name, the ViewResolver will parse the logical View name into the real View object according to the rules. The View object is actually rendered and returns the result to the browser.

From the above flow explanation, we learned that ViewResolver and View are the most important interfaces in Spring MVC View parsing. Spring MVC gives us a lot of view parsers, so let’s start by talking about what is a view?

An important implementation class for the View interface

The view-based interface, whose various implementation classes are stateless and therefore thread-safe

RenderMergedOutputModel (renderMergedOutputModel, renderMergedOutputModel, renderMergedOutputModel, renderMergedOutputModel, renderMergedOutputModel, renderMergedOutputModel, renderMergedOutputModel, renderMergedOutputModel, renderMergedOutputModel, renderMergedOutputModel)

Redirection: RedirectView

This view is related to redirection and is at the heart of the redirection problem. First look at the rendering process from source code:

protected void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws IOException {
        String targetUrl = this.createTargetUrl(model, request);
        targetUrl = this.updateTargetUrl(targetUrl, model, request, response);
        FlashMap flashMap = RequestContextUtils.getOutputFlashMap(request);
        if(! CollectionUtils.isEmpty(flashMap)) { UriComponents uriComponents = UriComponentsBuilder.fromUriString(targetUrl).build(); flashMap.setTargetRequestPath(uriComponents.getPath()); flashMap.addTargetRequestParams(uriComponents.getQueryParams()); FlashMapManager flashMapManager = RequestContextUtils.getFlashMapManager(request);if (flashMapManager == null) {
                throw new IllegalStateException("FlashMapManager not found despite output FlashMap having been set");
            }

            flashMapManager.saveOutputFlashMap(flashMap, request, response);
        }

        this.sendRedirect(request, response, targetUrl, this.http10Compatible);
    }
Copy the code

See String targetUrl = this.createTargeturl (model, request); This creates a Url redirect path.

This. SendRedirect (request, response, targetUrl, this.http10Compatible); The original was redirected to targetUrl using sendRedirect.

One of the important is the process of constructing the path, interested can go to study the source code, there is a need to transfer data in the redirection, display in the URL, this is in the construction of the path to achieve.

Request forwarding: InternalResourceView

View the rendering process:

protected void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
        this.exposeModelAsRequestAttributes(model, request);
        this.exposeHelpers(request);
        String dispatcherPath = this.prepareForRendering(request, response);
        RequestDispatcher rd = this.getRequestDispatcher(request, dispatcherPath);
        if (rd == null) {
            throw new ServletException("Could not get RequestDispatcher for [" + this.getUrl( ) + "]: Check that the corresponding file exists within your web application archive!");
        } else {
            if (this.useInclude(request, response)) {
                response.setContentType(this.getContentType());
                if (this.logger.isDebugEnabled()) {
                    this.logger.debug("Including resource [" + this.getUrl() + "] in InternalResourceView '" + this.getBeanName() + "'");
                }

                rd.include(request, response);
            } else {
                if (this.logger.isDebugEnabled()) {
                    this.logger.debug("Forwarding to resource [" + this.getUrl() + "] in InternalResourceView '" + this.getBeanName() + "'"); } rd.forward(request, response); }}}Copy the code

Rd. include(request, response); And rd., forward (request, response); The two methods, based on judgment criteria, decide which method to execute to the specified JSP page.

ViewResolver Interface of the view interpreter

The ViewResolver interface has only one method: View resolveViewName(String viewName, Locale Locale) throws Exception; Get the View object based on the View name viewName and the Local object, and that’s what the View interpreter does. Then we explained ViewResolver interface of a common implementation class InternalResourceViewResolver

InternalResourceViewResolver

Inherited from UrlBasedViewResolver to InternalResourceView as the view, if the existing in the project “javax.mail. Servlet. JSP. JSTL. Core. Config” this class, then to JstlView as view. The buildView method was overridden primarily to set the properties for the InternalResourceView view.

So we learned about InternalResourceViewResolver as InternalResourceView view, which means it can handle only forward requests, processing not redirected! And then what is url Base ViewResolver?

UrlBasedViewResolver

UrlBasedViewResolver inherited from AbstractCachingViewResolver abstract class, and implement Ordered interface classes

AbstractCachingViewResolver abstract class:

  1. AbstractCachingViewResolver is an abstract class, this kind of view parser will keep it ever parsing view, then every time to parse the view from the cache first find, if found the corresponding view is returned directly, if you don’t just create a new view object, It then puts it into a cache map and returns the new view. Using this approach to view caching minimizes the performance issues associated with parsing views.
  2. AbstractCachingViewResolver is with the function of cache ViewResolver interface foundations for an abstract class, the class has a property called viewAccessCache “viewName_locale” as the key, View Map whose interface is Value. The createView method is called inside the resolveViewName method and the loadView abstract method is called inside the method.

Ordered interface

The implementation class priority problem that implements the same interface, that is, the implementation class of the same interface is sorted. You’ll understand it when you learn how it works.

OK now that we know about UrlBasedViewResolver, let’s look at its properties and methods

  • ViewClass Indicates the type of a view
  • Prefix Prefix of the view name
  • Suffix Indicates the suffix of the view name

These three properties are important, and the view type is understandable, but what do prefixes and suffixes mean? This is where the importance of the UrlBasedViewResolver comes in. When we get the ModelAndView on request, only the logical path may not be complete, such as the real path/a/b/c/d/e.jspThe UrlBasedViewResolver prefix suffix comes into play when “e” is specified:Prefix +viewName+ suffix, so prefix can be set to/a/b/c/d/The suffix can be set to.jspThis solves the problem when encountering multiple JSP files placed at the same timeWEB-INFIn the multilevel directory, this time is very useful, save code,But you have to specify viewClass. Can read the source codecreateView()Core methods to understand how views are generatedAt first glance, there are two main types of views generated,One is prefixed with “Redirect :” and is of type RedirectView. The other is prefixed with “forward:” and is of type InternalResourceView.


And we’ll often USES the view InternalResourceViewResolver parser, it inherits the UrlBasedViewResolver, initialization of the source code:Which is set in the no-parameter constructorClass<? > viewClass=this.requiredViewClass();

protectedClass<? > requiredViewClass() {return InternalResourceView.class;
}
Copy the code

It is not difficult to see the InternalResourceViewResolver has ruled it can only handle InternalResourceView type of view, is the only resolution forward requests, and redirect cannot do. A parametrized construct is a prefix and a suffix. Use the InternalResourceViewResolver case is not demonstrated, online a lot. I’m just taking notes on learning the view parser.

conclusion

The View resolver is an important part of Spring MVC and relies on ViewResolver and View

  • The ViewResolver resolves the View object based on the logical View name of the ModelAndView
  • View renders the View back to the browser for the user

So much for the surface meaning of view parsers, a deeper understanding requires a deeper source code. Please point out any mistakes.