SpringMVC view mechanism details [with source code analysis]

Source: Internet
Author: User

Directory

  • Preface
  • Important interfaces and Classes
  • Source code analysis
  • Custom encoded ViewResolver
  • Summary
  • References
Preface

SpringMVC is one of the mainstream Web MVC frameworks.

If you are not familiar with it, please refer to its entry blog: http://www.cnblogs.com/fangjian0423/p/springMVC-introduction.html

This article will analyze the SpringMVC view, so that readers can understand the design principles of SpringMVC view.

Important interfaces and Classes

1. View Interface

The basic interface of the view. Its implementation classes are stateless and therefore thread-safe. This interface defines two methods:

2. AbstractView abstract class

  Basic implementation class of the View Interface. Let's introduce this abstract class A Little.

First, let's take a look at the attributes of this class:

Let's look at the implementation of the interface methods in the abstract class:

The getContentType method returns the contentType attribute directly.

Render method:

3. AbstractUrlBasedView abstract class

Inherited from the AbstractView abstract class, adding a url parameter of the String type.

4. InternalResourceView class

Class inherited from the AbstractUrlBasedView abstract class, indicating the JSP view.

Let's take a look at the renderMergedOutputModel method of this class (the abstract method defined by the AbstractView abstract class, the render method service provided by the View Interface ).

5. JstlView class

The JSTL view inherits from InternalResourceView, which is basically the same as the InternalResourceView class.

6. AbstractTemplateView abstract class

The class inherits from the AbstractUrlBasedView abstract class and overwrites the renderMergedOutputModel method. In this method, the renderMergedTemplateModel method is called, and the renderMergedTemplateModel method is the newly defined abstract method.

This abstract class has several boolean attributes: exposeSessionAttributes and exposeRequestAttributes. If it is set to true, the key value and value in the request and session will be thrown into the Map parameter of the model in the renderMergedTemplateModel method.

This class is the parent class of some template engine view classes. For example, FreemarkerView and VelocityView.

7. FreeMarkerView class

Inherited from AbstractTemplateView abstract class.

Let's look at the renderMergedTemplateModel method. renderMergedTemplateModel calls the doRender method internally:

8. RedirectView class

Inherits from AbstractUrlBasedView and implements the SmartView interface. The SmartView interface defines a boolean isRedirectView (); method.

The renderMergedOutputModel method of this view is mainly to redirect through response. sendRedirect.

9. ViewResolver Interface

View interpreter, used to parse the View and use it with the View interface.

This interface has only one method, and the View Interface implementation class is obtained through the View name viewName and Locale object:

  View resolveViewName(String viewName, Locale locale) throws Exception;

10. AbstractCachingViewResolver abstract class

The base implementation abstract class of the ViewResolver interface with the caching function. This class has a Map with the attribute name "viewName_locale" as the key and the View Interface as the value.

The createView method is called internally in the resolveViewName method implemented by this abstract class, And the loadView abstract method is called internally.

11. UrlBasedViewResolver class

The class inherited from the AbstractCachingViewResolver abstract class and implemented the Ordered interface is a simple implementation class of the ViewResolver interface.

This class rewrites the createView method:

The createView method of the parent class (AbstractCachingViewResolver) calls the loadView abstract method internally. UrlBasedViewResolver implements this abstract method:

Perform a test on UrlBasedViewResolver. The configuration is as follows:

<bean class="org.springframework.web.servlet.view.UrlBasedViewResolver">  <property name="prefix" value="/WEB-INF/view/"/>  <property name="suffix" value=".jsp"/>  <property name="viewClass" value="org.springframework.web.servlet.view.InternalResourceView"/>  <property name="viewNames">    <array>        <value type="java.lang.String">*</value>      </array>      </property>    <property name="contentType" value="text/html;charset=utf-8"/>  <property name="attributesMap">    <map>      <entry key="mytest" value="mytestvalue"/>    </map>  </property>  <property name="attributes">    <props>      <prop key="test">testvalue</prop>    </props>  </property></bean>

We can see that the JSP view of InternalResourceView is used as the view. viewNames we set *. Here * represents the name of all views (this viewNames attribute is not set, which means all view names are processed ); http Response Header contentType information: text/html; charset = UTF-8; attributesMap and attributes input Map and Properties parameters will be thrown into the staticAttributes attribute, this staticAttributes will be set to the staticAttributes attribute of the AbstractView, that is, the parameters in the request field.

 

 

We can see that the values of mytest and testvalue are not set in the request field. However, it will be displayed on the page because the attributesMap and attributes parameters are configured.

If we change "*" in viewNames to "index1 ". An error is reported because the index cannot match index1 when processing the view name.

12. InternalResourceViewResolver class

Inherits from UrlBasedViewResolver and uses InternalResourceView as the view. If the "javax. servlet. jsp. jstl. core. Config" class exists in the project, JstlView is used as the view. The buildView method is rewritten to set attributes for the InternalResourceView.

13. AbstractTemplateViewResolver class

Inherited from UrlBasedViewResolver and rewritten the buildView method, which is mainly used to construct AbstractTemplateView and set corresponding attributes for it.

14. FreeMarkerViewResolver class

Inherits from AbstractTemplateViewResolver and sets the view to FreeMarkerView.

15. ModelAndView object

As the name implies, a Model and View class with the view and Model attributes.

It is worth noting that this View attribute is an Object-type data that can be directly an implementation class or View name (string) of the View Interface ).

Source code analysis

Next we will analyze the source code of SpringMVC's processing view.

When processing the request, SpringMVC obtains the HandlerExecutionChain through RequestMappingHandlerMapping, obtains one ModelAndView object through RequestMappingHandlerAdapter, and then processes it using the processDispatchResult method.

The processDispatchResult method is as follows:

If the configured ViewResolver is as follows:

<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">  <property name="prefix" value="/WEB-INF/view/"/>  <property name="suffix" value=".jsp"/></bean>

InternalResourceViewResolver is used to parse the view.

Previously analyzed, InternalResourceViewResolver overrides UrlBasedViewResolver's buildView method. However, the buildView method of UrlBasedViewResolver is still called.

The InternalResourceView or JstlView is obtained. The render method of these two views has been analyzed when this article introduces important interfaces and classes.

 

PS: The viewResolvers attribute in DispathcerServlet is a set. If there are multiple ViewResolver objects, there must be a priority problem. For details about this part, refer to another blog:

Http://www.cnblogs.com/fangjian0423/p/spring-Ordered-interface.html

Custom encoded ViewResolver

Next, we will compile the custom ViewResolver.

When the custom ViewResolver processes the view name, it will find the jsp page starting with "jsp:" and find the freemarker page starting with "freemarker.

Public class CustomViewResolver extends {public static final String JSP_URL_PREFIX = "jsp:"; public static final String FTL_URL_PREFIX = "freemarker:"; private static final boolean jstlPresent = ClassUtils. isPresent ("javax. servlet. jsp. jstl. core. config ", CustomViewResolver. class. getClassLoader (); private Boolean exposePathVariables = false; private boolean exposeRequestAttrib Utes = false; private boolean allowRequestOverride = false; private boolean exposeSessionAttributes = false; private boolean allowSessionOverride = false; private boolean exposeSpringMacroHelpers = true; public CustomViewResolver () {this. setViewClass (FreeMarkerView. class) ;}@ Override protected into acturlbasedview buildView (String viewName) throws Exception {if (viewName. startsWith (FTL_URL_PREFI X) {return buildFreemarkerView (viewName. substring (FTL_URL_PREFIX.length ();} else if (viewName. startsWith (JSP_URL_PREFIX) {Class viewCls = jstlPresent? JstlView. class: InternalResourceView. class; return buildView (viewCls, viewName. substring (JSP_URL_PREFIX.length (), getPrefix (),". jsp ");} else {// return buildFreemarkerView (viewName) by default;} private response acturlbasedview build (Class viewClass, String viewName, String prefix, String suffix) {AbstractUrlBasedView view = (AbstractUrlBasedView) BeanUtils. instantiateClass (viewClass); vi Ew. setUrl (prefix + viewName + suffix); String contentType = getContentType (); if (contentType! = Null) {view. setContentType (contentType);} view. setRequestContextAttribute (getRequestContextAttribute (); view. setAttributesMap (getAttributesMap (); if (this. exposePathVariables! = Null) {view. setExposePathVariables (exposePathVariables);} return view;} private AbstractUrlBasedView buildFreemarkerView (String viewName) throws Exception {AbstractTemplateView view = (AbstractTemplateView) build (FreeMarkerView. class, viewName, "", getSuffix (); view. setExposeRequestAttributes (this. exposeRequestAttributes); view. setAllowRequestOverride (this. allowRequestOverride); view. setExposeSessionAttributes (this. exposeSessionAttributes); view. setAllowSessionOverride (this. allowSessionOverride); view. setExposeSpringMacroHelpers (this. exposeSpringMacroHelpers); return view;} // The get set method is omitted}

Xml configuration:

<bean class="org.format.demo.support.viewResolver.CustomViewResolver">  <property name="prefix" value="/WEB-INF/view/"/>  <property name="suffix" value=".ftl"/>  <property name="contentType" value="text/html;charset=utf-8"/>  <property name="exposeRequestAttributes" value="true"/>  <property name="exposeSessionAttributes" value="true"/>  <property name="exposeSpringMacroHelpers" value="true"/>  <property name="requestContextAttribute" value="request"/></bean>
<bean id="freemarkerConfig" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">  <property name="templateLoaderPath" value="/WEB-INF/view/"/>  <property name="defaultEncoding" value="utf-8"/>  <property name="freemarkerSettings">    <props>      <prop key="template_update_delay">10</prop>      <prop key="locale">zh_CN</prop>      <prop key="datetime_format">yyyy-MM-dd</prop>      <prop key="date_format">yyyy-MM-dd</prop>      <prop key="number_format">#.##</prop>    </props>  </property></bean>

For a brief explanation, when mviewresolver parses the view name, it determines the name starting with "jsp:" and "freemarker:". If it starts with "jsp:", if there is a JSTL dependency, construct the JSTLView; otherwise, construct the InternalResourceView. If "freemarker:" is used to construct FreemarkerView. Some attributes are set before the view is constructed.

Xml configuration: prefix is configured for the jsp view. The freemarker view does not require a prefix, because FreemarkerView uses the configured FreeMarkerConfigurer internally and uses the templateLoaderPath attribute inside FreeMarkerConfigurer as the prefix, the suffix configuration is used as the suffix for FreemarkerView.

Add the Controller code:

@Controller@RequestMapping(value = "/tvrc")public class TestViewResolverController {      @RequestMapping("jsp")    public ModelAndView jsp(ModelAndView view) {        view.setViewName("jsp:trvc/index");        return view;    }    @RequestMapping("/ftl")    public ModelAndView freemarker(ModelAndView view) {        view.setViewName("freemarker:trvc/index");        return view;    }  }

The contents in view/WEB-INF/view/trvc/index. jsp are output

The contents in view/WEB-INF/view/trvc/index. ftl are output

Summary

This article analyzes the View mechanism in SpringMVC. The View and ViewResolver interfaces are the core of the View mechanism, and analyzes several important View and ViewResolver interface implementation classes, finally, we wrote a ViewResolver implementation class that distinguishes jsp and freemarker views, so that readers can better understand the view mechanism.

I hope this article will help readers understand the SpringMVC view mechanism.

 

Errors are inevitable in this article, and readers are expected to specify them.

References

Http://my.oschina.net/HeliosFly/blog/221392

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.