Spring MVChelloworld, components, architecture

Keywords: Spring Tomcat xml Maven

Catalog

I. create project

  1. Create a maven project with idea, select Maven archetype webapp, and add two directories of java and resources.
  2. Introducing maven dependency into pom
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>


    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-web</artifactId>
      <version>4.2.6.RELEASE</version>
      <exclusions>
        <exclusion>
          <artifactId>commons-logging</artifactId>
          <groupId>commons-logging</groupId>
        </exclusion>
      </exclusions>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>4.2.6.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>4.2.6.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-test</artifactId>
      <version>4.2.6.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-jdbc</artifactId>
      <version>4.2.6.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>com.github.stefanbirkner</groupId>
      <artifactId>system-rules</artifactId>
      <version>1.16.1</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjweaver</artifactId>
      <version>1.8.9</version>
    </dependency>

    <!--Journal-->
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-api</artifactId>
      <version>1.7.13</version>
    </dependency>
    <!--logback-classic rely on logback-core,Will be automatically cascaded in-->
    <dependency>
      <groupId>ch.qos.logback</groupId>
      <artifactId>logback-classic</artifactId>
      <version>1.2.3</version>
    </dependency>
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-jcl</artifactId>
      <version>1.7.25</version>
    </dependency>
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>jcl-over-slf4j</artifactId>
      <version>1.8.0-beta2</version>
    </dependency>

    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.9.8</version>
    </dependency>

  </dependencies>
  1. Configure the configuration file of spring mvc
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-4.0.xsd">

    <context:component-scan base-package="com.zyc.controller"/>
    <mvc:annotation-driven />
</beans>
  1. Configure web.xml
<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
  <display-name>Archetype Created Web Application</display-name>


  <!-- Configure front end controller -->
  <servlet>
    <servlet-name>springmvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <!-- Appoint springmvc The path to the configuration file. If not specified, the default is:/WEB-INF/${servlet-name}-servlet.xml -->
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:springmvc.xml</param-value>
    </init-param>
  </servlet>
  <servlet-mapping>
    <servlet-name>springmvc</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>

</web-app>

II. Pit encountered

Using tomcat in idea

Be sure to add the configured tomcat

Use @ responseBody service

Be sure to add this configuration to the spring mvc configuration file, or 406 errors will be reported. The reason is discussed in Section 3.

<mvc:annotation-driven />

tomcat console garbled

Reference resources: https://blog.csdn.net/u012611878/article/details/80723491

III. architecture and components

Frame structure

Technological process

  1. The user sends the request to the front controller dispatcher servlet.
  2. The dispatcher servlet receives a request to call the HandlerMapping processor mapper.
  3. The processor mapper finds the specific processor according to the request url, generates the processor object and the processor interceptor (if any) and returns them to the dispatcher servlet.
  4. DispatcherServlet calls the processor through the HandlerAdapter processor adapter.
  5. The execution processor (Controller, also called back-end Controller).
  6. The Controller completes execution and returns to ModelAndView.
  7. The HandlerAdapter returns the controller execution result ModelAndView to the dispatcher servlet.
  8. The dispatcher servlet passes the ModelAndView to the viewreslower view parser.
  9. The View Explorer returns the specific View after parsing.
  10. The DispatcherServlet renders the View (that is, the model data is populated into the View).
  11. The dispatcher servlet responds to the user.

Attention points

  1. HandlerMapping returns a Handler execution chain, in which there are not only handlers but also interceptors (here we can develop our own interceptors), which are then returned to the front-end controller.
  2. The handler in the execution chain of the processor. The front-end processor cannot directly execute it. So we need to find a HandlerAdapter to execute the handler.

assembly

HandlerMapping

The function is to find the corresponding Handler according to the current request, and encapsulate the Handler and a bunch of handlerinterceptors into the HandlerExecutionChain object. There is only one method inside the HandlerMapping interface.

public interface HandlerMapping {
    String PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE = HandlerMapping.class.getName() + ".pathWithinHandlerMapping";
    String BEST_MATCHING_PATTERN_ATTRIBUTE = HandlerMapping.class.getName() + ".bestMatchingPattern";
    String INTROSPECT_TYPE_LEVEL_MAPPING = HandlerMapping.class.getName() + ".introspectTypeLevelMapping";
    String URI_TEMPLATE_VARIABLES_ATTRIBUTE = HandlerMapping.class.getName() + ".uriTemplateVariables";
    String MATRIX_VARIABLES_ATTRIBUTE = HandlerMapping.class.getName() + ".matrixVariables";
    String PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE = HandlerMapping.class.getName() + ".producibleMediaTypes";

    HandlerExecutionChain getHandler(HttpServletRequest var1) throws Exception;
}

There are many implementation classes for HandlerMapping. The default loading is as follows (spring mvc4.2.6.RELEASE version)

Common HandlerMapping implementation

  1. Simpleurhandlermapping: establish a relationship between the configuration request path and the Controller mapping to find the corresponding Controller
  2. ControllerClassNameHandlerMapping: find the requested Controller through the Controller's class name
  3. BeanNameUrlHandlerMapping: find the Controller to request through the defined beanName
  4. DefaultAnnotationHandlerMapping: find the corresponding Controller by annotating @ RequestMapping("/userlist") (obsolete)
  5. RequestMappingHandlerMapping: replaces the previous one

Note:

  1. Introduction of BeanNameUrlHandlerMapping and simpleurhandlermapping. The resolution of < MVC: default servlet handler / > will introduce simpleurhandlermapping. You need to be careful about re instantiation.
    Reference resources: https://blog.csdn.net/gaoshan12345678910/article/details/81778587

HandlerAdapter

Adapter mode adopted
Spring MVC's handler (Controller, HttpRequestHandler, Servlet, etc.) can be implemented in many ways, such as inheriting Controller, annotation based Controller, HttpRequestHandler. Because of the different ways of implementation, the way of calling is uncertain.
If you write the call normally, you need to use multiple if else to judge instance of, and then add the implementation method, you need to modify the source code, which does not conform to the principle of opening to extension and closing to modification.
The HandlerAdapter interface has three methods:

public interface HandlerAdapter {
    boolean supports(Object var1);

    ModelAndView handle(HttpServletRequest var1, HttpServletResponse var2, Object var3) throws Exception;

    long getLastModified(HttpServletRequest var1, Object var2);
}

The first method is to determine whether the adapter supports the HandlerMethod, that is, when a handler is obtained, the interface subclass uses the method to determine (that is, the judgment method similar to the handler instanceof Controller) to get the adapter subclass that adapts to the handler.
The second method is used to execute the controller processing function and get the ModelAndView. The handler method is executed according to the adapter call rule.

Handlermapping and HandlerAdapter should be used in a complete set

<mvc:default-servlet-handler />

Mainly register:

  1. DefaultServletHttpRequestHandler: default Servlet request handler
  2. SimpleUrlHandlerMapping: url - handler mapper
  3. HttpRequestHandlerAdapter: processor adapter

If only < MVC: default servlet handler / > is configured, in addition to the above three components, the components loaded by the container by default will also be loaded:

registerBeanNameUrlHandlerMapping(parserContext, source);
registerHttpRequestHandlerAdapter(parserContext, source);
registerSimpleControllerHandlerAdapter(parserContext, source);

After the < MVC: default Servlet handler / > is configured in springMVC-servlet.xml, an org.springframework.web.servlet.resource.DefaultServletHttpRequestHandler will be defined in the context of Spring MVC. It will act as an inspector to screen the URL entering the DispatcherServlet. If the request is a static resource, the request will be transferred to the default se of the Web application server. Rvlet processing, if not a static resource request, the dispatcher Servlet continues to process.

In general, the default servlet name of Web application server (this servlet is provided by the container) is "default", so the DefaultServletHttpRequestHandler can find it. If the default servlet name of all your Web application servers is not "default", you need to specify it through the default servlet name attribute display:

< MVC: default Servlet handler default Servlet name = "default Servlet name used by Web server" / >
Reference resources:

  1. https://www.cnblogs.com/dflmg/p/6393416.html
  2. https://blog.csdn.net/abc997995674/article/details/80513203

<mvc:annotation-driven/>

1. Three bean s, RequestMappingHandlerMapping, RequestMappingHandlerAdapter and ExceptionHandlerExceptionResolver, will be automatically registered to support the controller method with annotations like @ RquestMapping, ExceptionHandler, etc. to process the request.
2. It supports the use of an instance of ConversionService for type conversion of form parameters.
3. Support @ NumberFormat and @ NumberFormat annotation to format data types.
4. Support JSR-303 verification of JavaBeans with @ Valid.
5. Support @ RequestBody, @ ResponseBody.

ViewReslover

The most commonly used is the internal resource view resolver

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

Reference resources: Spring MVC view parser

Configure BeanNameViewResolver

    	<! -- configure the view BeanNameViewResolver resolver: use the view name to resolve the view -- >
    	<! -- define the priority of the view parser through the order attribute. The lower the order value, the higher the priority -- >
    	<bean class="org.springframework.web.servlet.view.BeanNameViewResolver">
    		<property name="order" value="100"></property>
    	</bean>

Summary: when there are multiple view parsers, they will try to parse the views one by one according to the order value. For example, in the above case, BeanNameViewResolver will first go to the bean container to find the view object with the same name as the required view. If not, let InternalResourceViewResolver find it. If all view parsers fail to parse, an exception is thrown.

Reference:

  1. Spring MVC learning (2) - spring MVC architecture and components
  2. Two principles of spring MVC: HandlerMapping and HandlerAdapter
  3. Look at the spring MVC adapter pattern - HandlerAdapter
  4. mvc:annotation-driven/ Effect
  5. idea creates spring MVC project based on maven

Posted by artiemus on Sat, 26 Oct 2019 22:08:50 -0700