Advanced application of spring MVC -- transform the handwritten spring MVC into a real spring MVC

Posted by MilesWilson on Sun, 20 Feb 2022 19:02:24 +0100

Source code (code cloud):

1, Handwritten spring MVC

For length reasons, I put it in this article

2, Spring MVC advanced application

Spring MVC
  1. Encapsulate the servlet and simplify the framework of servlet development
  2. It can receive requests, return responses, jump to pages, and whatever Servlet can do
  3. It is a derivative function of the Spring Framework. Due to its perfect functions, we generally regard it as a separate framework
  4. It is now one of the most mainstream MVC frameworks. After the release of Spring 3.0, it has comprehensively surpassed struts 2 and become the best MVC framework
Differences from native servlets
  1. Native Servlet: when the current end sends a request, it finds the corresponding Servlet according to the url. How many services are there and how many servlets are written
  2. In spring MVC, there is only one Servlet called DispatchServlet in the world. It calls the corresponding method only through the url and parameters we request. We don't need to write any servlets. We just need to write relevant business methods and annotate them (@ RequestMapping, @ GetController, etc.)
  3. The advantage of spring MVC is that we don't need to write servlets. We only need to maintain one DispatchServlet globally. Any international configuration and extended configuration are only aimed at one Servlet

1. Environment construction (it is very important to know why it is used)

  1. Create Maven's web project and introduce relevant dependencies

  <name>advanced_application_of_springmvc Maven Webapp</name>
  <!-- FIXME change it to the project's website -->


    <!--spring MVC-->
      <scope>provided</scope><!--tomcat If so, do not use this, use your own, and avoid conflicts-->

      <!--Specify compilation level-->
        <artifactId>maven-compiler-plugin</artifactId><!--Add a plug-in-->
<!--          <compilerArgs>-->
<!--            <arg>-parameters</arg>&lt;!&ndash;Tell the compiler to record the real name of the formal parameter at compile time&ndash;&gt;-->
<!--          </compilerArgs>-->
      <!--tomcat 7 plug-in unit-->
  1. As we said, spring MVC has only one Servlet, DispatchServlet. So we need to be on the web Configure the mapping of this Servlet in XML. In addition, we need to configure which requests this Servlet intercepts (it will parse in the source code and then intercept the corresponding requests)
  2. We write a jsp page to jump to
  3. To write a controller, we only need to identify it through the spring MVC annotation. We have made it clear in the previous handwriting framework that it scans the corresponding annotated components according to our configured scanning path, adds them to the spring IOC container, and establishes the mapping of url and method (initHandlerMapping and Handler)
  1. We found that when we jump to the view below, the directory structure is written dead, and the suffix is also written dead, which is very coupled. We'd better unify these configurations in one place, so that once they change, only one place needs to be modified
  2. Spring MVC provides the function of configuring the view parser
  3. At the same time, we also have to configure the spring MVC scanning path. We write the class here. Spring MVC doesn't know that this is the class that needs to scan annotations
  4. We hope it can be written like this
  1. To write spring configuration files and configure spring MVC, we need to know the scanning path of spring MVC, because we identify the Controller class through annotations, and we have to tell spring MVC where to find these classes. You also have to configure the view parser to decouple
  1. Opening annotation scanning is spring. Spring MVC is based on spring. There's nothing to say
  2. Configure the view resolver, InternalResourceViewResolver, which is an entity class. As long as it is configured, it can take effect, because after configuration, it will be loaded into the ioc container. When spring MVC is parsed, check the ioc container, and if so, perform view parsing
  3. InternalResourceViewResolver has two important properties, prefix and suffix, which represent the prefix and suffix to be resolved. We can assign values to them through setter method. spring uses setter to assign values in the form of < property name = "prefix" value = "/ WEB-INF / JSP / / >
  1. Optional configuration, processor mapper and processor adapter. Both of them have default implementations. If you don't configure them, use the default ones. We can configure them ourselves and choose the one that suits us best. We can add an annotation driver
<beans xmlns=""

    <!--Give Way spring Scan annotation-->
    <context:component-scan base-package="com.yzpnb.controller"></context:component-scan>
    <!--spring mvc view resolver -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/"></property>
        <property name="suffix" value=".jsp"></property>
    <!--Processor adapter
        -   Automatic registration is the most appropriate
  1. web.xml load configuration file. First, after spring MVC, we know that the dispatcher servlet will read the servlet configuration, get the location of our spring MVC configuration file, and then initialize spring MVC according to the configuration file, so we need to Specify the location of the configuration file in XML
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "" >

  <display-name>Archetype Created Web Application</display-name>
  <!--to configure SpringMVC Unique Servlet๏ผŒDispatchServlet-->
    <init-param><!--This configuration can be initialized Servlet Time acquisition-->
      <param-name>contextConfigLocation</param-name><!--springMvc The specified parameter name is the path of the configuration file-->
      Intercept request
      Mode 1:*.action   *.do .....With suffix, you can accurately intercept requests with suffix
      Mode 2:/    Intercept all URL request
      Mode 3:/*   Except interception URL๏ผŒIt also intercepts, for example.jsp This kind of document, jsp Documents are generally handled by themselves rather than needed springmvc handle
Start the server and test

2. Spring MVC request processing flow and nine components

Request processing flow

  1. The user sends a request to the front-end controller DispatcherServlet
  2. The dispatcher servlet receives a request to call the handler mapping processor mapper
  3. The processor mapper finds the specific Handler (back-end controller) according to the request URL, generates the processor object and the processor interceptor (if any), and returns the dispatcher servlet together
  4. Dispatcher servlet calls Handler adapter to call Handler
  5. Processor adapter execution Handler
  6. The Handler returns ModelAndView to the processor adapter after execution
  7. The processor adapter returns ModelAndView to the front controller. ModelAndView is an underlying object of Spring MVC framework, including Model and View
  8. The front-end controller requests the view parser to parse the view, and parses the real view according to the logical view name.
  9. The View parser returns View to the front controller
  10. The front-end controller performs view rendering by filling the model data (in the ModelAndView object) into the request field
  11. The front-end controller responds to the user
9 major components( ๐Ÿ† Need to master/ ๐Ÿ… (just understand)
  1. ๐Ÿ† HandlerMapping processor mapper
  1. Handle handler (mapping of processor and url). It is used to find handler. Handler is a processor, which can be a class or a method. For example, each method marked with @ RequestMapping can be regarded as a handler. The handler is responsible for the actual request processing business. The function of HandlerMapping is to find the handler and Interceptor corresponding to the request
  1. ๐Ÿ† HandlerAdapter processor adapter
  1. The decoration design pattern adapts the Handler according to different types. The Handler in spring MVC can be in any form as long as it can handle requests
  2. When submitting a request to a Servlet, because the Servlet method structure is in the form of doService(HttpServletRequest req,HttpServletResponse resp), it is the responsibility of the HandlerAdapter to make the fixed Servlet processing method call the Handler for processing
  1. ๐Ÿ† Handler exception resolver handler exception resolver
  1. It is used to handle the exceptions generated by the Handler. It is used to set the ModelAndView according to the exceptions, and then hand it to the rendering method for rendering. The rendering method will render the ModelAndView into a page
  1. ๐Ÿ† ViewResolver view resolver
  1. The View parser is used to resolve the View name and Locale of String type to View type View. There is only one resolveViewName() method.
  2. The String type View name viewName returned by the Controller layer will eventually be resolved here as View (for rendering pages, the parameters and data returned by the program will be filled into the template to generate html files)
  3. Complete the work: find the template used for rendering, find the technology used (view type, such as JSP) and fill in the parameters
  4. Spring MVC automatically assembles the InternalResourceViewResolver for JSP type views
  1. ๐Ÿ… RequestToViewNameTranslator request to view name translator
  1. Get the ViewName from the request. We know that the ViewResolver finds the View according to the ViewName, but some handlers do not set the View or ViewName after processing, so this component can find the ViewName from the request
  2. That is, we do not specify modelandview setViewName(“success”); At this time, the address spliced by the view parser is / WEB-INF/jsp / request name jsp, that is, the request is interpreted as ViewName.
  1. ๐Ÿ… LocalResolver address resolver
  1. It mainly deals with some things of internationalization. The core method resolveViewName requires two parameters, view name and Locale
  2. It is used to parse the Locale from the request. For example, Chinese Locale is zh CN, which is used to represent a region. This component is the basis of i18n
  1. ๐Ÿ… ThemeResolver theme processor
  1. Resolve the theme (a collection of styles, pictures, and the display effects they form). A set of topics in spring MVC corresponds to a properties file, which stores all resources related to the current topic.
  2. To create a topic, you only need to prepare resources, create a "topic name. properties" file, set the resources in it, and put them under the classpath, which can be used in the page
  3. Spring MVC topic related classes include ThemeResolver (responsible for resolving the topic name from the request), ThemeSource (responsible for finding a specific topic according to the topic name, and the specific abstraction is Theme) and Theme (you can get the topic and specific resources through Theme)
  1. ๐Ÿ† MultipartResolver composite parser
  1. Encapsulate the ordinary request and make it have the function of file upload, which is realized by wrapping the ordinary request into MultipartHttpServletRequest
  2. You can get the file directly through the getFile() method. If you upload more than one, you can call the getFileMap() method to get the map < filename, file > structure
  1. ๐Ÿ… FlashMapManager: FlashMap Manager
  1. Manage FlashMap. FlashMap is used to pass parameters during redirection. For example, in order to avoid repeated submission when users process orders, they redirect to get request after processing Post request to display order details and other information.
  2. During redirection, you can write parameters into the URL (very low, not recommended). It can be delivered through FlashMap. It only needs to write the data to be delivered to the output of the request during redirection_ FLASH_ MAP_ Attribute attribute (the request can be obtained through ServletRequestAttributes.getRequest())
  3. After such redirection, Spring in the Handler will automatically set it to the Model, and the data can be directly obtained from the Model on the display order information page

3. URL pattern configuration and principle

In front of us, web XML is configured with DispatcherServlet, and the interception path is < URL pattern > / < / url pattern >, which can intercept all URL requests. Next, this configuration is introduced in detail and its principle is analyzed
  1. < URL pattern > / < / url pattern > although not intercepted jsp, but it will intercept all static resources (css, js, html) for the following reasons
  1. Because tomcat has a web xml can be understood as parent xml, while we write child xml, which belongs to inheritance relationship
  2. We can see tomcat's web XML has a DefaultServlet mapping. According to the annotation, it provides static resource services
  3. Its URL pattern is a / of the configuration. Instead, JSPS are handled separately
  4. While we are writing "/" is also configured in XML, so the subclass overrides the parent class. When the url request comes, we will not go to the DefaultServlet to process the static resources, but directly to the web XML, let's go DispatcherServlet
  5. This is why static resources cannot be accessed, but JSPS can
So since configuring "/" will intercept static resources, how should we solve the problem? Scheme 1: configure < MVC: default servlet handler / > in the configuration file, which means that when a static resource request url is encountered, it will be handed over to the defaultServlet for processing (Tomcat)
  1. Configure static resources in spring MVC to solve the problem < MVC: default servlet handler / >. This annotation can define a DefaultServletHttpRequestHandler object in the spring MVC context. It will check the url entering the dispatcher servlet. If it is a static resource, it will be handed over to the DefaultServlet of the web server tomcat for processing. If not, it will continue to be processed by spring MVC
  2. test
  1. Provide html
  2. test
The above method has great limitations. Static files can only be placed in the webapp folder (it is OK to establish a directory) and cannot be placed in the WEB-INF directory. Therefore, there is scheme 2: Spring MVC handles static resources by itself < MVC: resources mapping = "/ resources / * *" location = "classpath: / / >

    <!--Static resource allocation scheme-->
        If requested url yes/resources/******   Just go classpath/Let's find it. That's it resources
        If there are more than one, they can be separated by commas
    <mvc:resources mapping="/static/**,/resources/**" location="classpath:/"/>

4. Data output Model, Map, ModelMap, request parameter binding

Generally, when we use springboot, we rarely directly use ModelAndView to process Model data, and it also uses BindingAwareModelMap to process data. Reflection does a lot of things through BindingAwareModelMap
  1. Let's look at the definition in the source code of ModeAndView. The corresponding data is actually ModelMap
  2. In other words, you can use ModelMap directly, but with the help of the mechanism of spring MVC
  1. We can directly pass modelmap as a parameter. After handwritten spring MVC, we know that when DispatcherServlet reflects the method, it will get the method parameters from the Handler. When it is found that the parameters are special objects such as request, response and modelmap, it will help us pass them
  2. In addition, when we return the value, we will also carry out corresponding processing. For example, we can complete the view jump rendering by directly returning the string
  1. You can also use Model
  2. Even use Map
In fact, they are all instances of BindingAwareModelMap. As long as the contents saved for BindingAwareModelMap are saved to the request field
  1. First, when the spring MVC reflection method finds parameters such as Model, it will directly pass a BindingAwareModelMap. For details, please refer to the class diagram
Next, let's look at the binding of request parameters. When we previously handwritten the spring MVC framework, when binding request parameters, we bound them to the corresponding method parameters (in the parameter mapping container in the Handler) through the location and parameter name, and directly passed them to the Servlet API (request and response) (dispatcher servlet's req and resp)
  1. By default, Servlet API is supported as method parameters. When reflecting methods, if necessary, directly wait for Servlet API to pass in request, response and httpSession
  2. For the support of simple type parameters, it is recommended to use the wrapped data type, because the basic data type cannot be null, which is very troublesome
  1. Integer, String, float, double and Boolean are all supported. And we do not recommend int, float, double and Boolean
  2. The parameter value of boolean type is true or false, or 1 or 0 can be used
  3. When in use, the formal parameter can be declared directly, but the parameter name and the parameter name passed by the front end need to be consistent. If inconsistent, you can use the @ RequestParam annotation for manual mapping
  1. Support entity class parameters (Pojo,java class)
  2. Support some classes encapsulated by spring MVC, such as receiving files uploaded by users, such as ModelMap
  3. The principle is that after receiving the request, the dispatcher servlet obtains the transmitted parameters (such as request.getParameter("xxxx") from the request) and obtains json data. Then, according to the parameter information saved in the Handler, it is encapsulated reasonably
Then the parameter binding that spring MVC does not support cannot be automatically converted. For example, if the front end gives a date type string, we cannot resolve it into a date type. At this time, the spring MVC type converter is needed. We need to inherit the interface and implement it, and then register it in the configuration file
  1. It can be seen that the string cannot be directly converted to date. What we need to do is to let spring MVC automatically call our converter to convert when this happens
  1. String to date type converter needs to implement the converter < source type, target type > interface
import org.springframework.core.convert.converter.Converter;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

 * Converter<Source type, target type >
public class DateConverter implements Converter<String, Date> {
     * Logic to convert source type to target type
    public Date convert(String source) {
        //String to date
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        try {
            Date parse = simpleDateFormat.parse(source);
            return parse;
        } catch (ParseException e) {
        return null;
  1. Register it through the FormattingConversionServiceFactoryBean factory, which can be annotated with @ Bean or configured in the xml configuration file. We will configure it with xml
  1. First of all, this is the factory Bean, which has a set set to store all the converters
  2. xml to configure our converter
    <bean id="conversionServiceBean" class="">
        <property name="converters">
                <bean class="com.yzpnb.converter.DateConverter"></bean>
  1. It's not enough to just configure it. We have to specify the processor adapter to use, because the processor adapter is responsible for binding the Handler, and we need to associate it
    <mvc:annotation-driven conversion-service="conversionServiceBean"></mvc:annotation-driven>
  1. test

5. Filter handles Post request garbled code and request mode conversion

It's too basic. I won't talk about how to do Post. Here we mainly talk about how to use Filter to deal with Post garbled code
  1. Like servlets, we can You can also configure filters in xml through annotations. Here, you can configure them in xml. But we use spring MVC encapsulated filter RG springframework. web. filter. CharacterEncodingFilter
The get request is garbled. You need to modify the server under tomcat Configuration of XML file
<Connector URIEncoding="utf-8" connectionTimeout="2000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>
Generally, we specify the request_ method parameter to represent the current request type, such as put and delete. This also requires filters to parse

  <!--springMVC Request mode conversion filter, check whether the request parameters have_method Parameters, if any, are converted according to the specified request mode-->

6. Listener, Spring MVC interceptor and filter

Three differences
  1. The Servlet handles the Request and Response
  2. Filter: filter the Request and filter it in front of the Servlet
  3. Listener listener: implementation class javax servlet. The server-side component of the servletcontextlistener interface starts with the start of the Web application, initializes only once, and then listens all the time. When the Web application stops, it will be destroyed
  1. Usually do some initialization work. The spring container in the web application starts the ContextLoaderListener listener
  2. It can also be used to monitor specific events in the web, such as the creation and destruction of HttpSession and ServletRequest, and the creation, destruction and modification of variables. Processing can be added before and after some actions to realize monitoring, such as counting the number of online people, using httpsessionliser, etc
  1. Interceptor: Spring MVC, Struts and other presentation layer frameworks are unique. They do not intercept resource access such as jsp/html/css/image, but only the controller method (Handler) that will intercept access
  1. The Handler service is intercepted once before execution
  2. The Handler service is intercepted once after execution but before jumping to the page
  3. Intercept once after jumping to the page
  1. Servlet, filter and listener are configured on the web XML, interceptor is configured in the presentation layer framework configuration file

6.1 execution process of single interceptor

The execution process is as follows. It is recommended to see the following to know how to implement a single interceptor, and then come back to the process

  1. First, the preHandle method of the custom interceptor is used to intercept the spring MVC requests that have just arrived
  2. When the preHandle is true, match the HandlerAdapter downward to match the appropriate processor for logical processing, that is, the execution of the Handler method
  3. Then there is the postHandle of the custom interceptor. The result is intercepted before being returned to the dispatcher servlet
  4. Then it is handed over to the dispatcher servlet to respond to the request result
  5. After the response is completed, execute the afterCompletion of the custom interceptor
Single interceptor
  1. Inherit the HandlerInterceptor interface and implement relevant methods
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class MyInterceptorOne implements HandlerInterceptor {
     * handler Intercept before execution, which is often used for permission verification
     * @return true Indicates release, and false indicates no release
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        return true;
    /**Neither of the following methods is commonly used**/
    //The handler has finished executing and has not been intercepted before jumping to the page
    //modelAndView allows us to modify the data before jumping. Generally, there is no such demand
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
    //After the handler is executed, jump to the page and intercept it
    //ex allows us to catch exceptions, but we have an exception handler that we can't use at all
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
  1. Spring MVC configuration file configuration interceptor
        <!--Intercept all-->
<!--        <bean class="com.yzpnb.interceptor.MyInterceptorOne"></bean>-->
        <!--Intercept specified requests-->
            <mvc:mapping path="/dome/**"/>
            <!--Exclude certain or some non interceptors-->
<!--            <mvc:exclude-mapping path="/dome/methosd0222"/>-->
            <bean class="com.yzpnb.interceptor.MyInterceptorOne"></bean>
  1. test

6.2 execution process of multiple interceptors

If there are multiple interceptors, how to execute them? The code is the same, so I won't repeat it

  1. As long as you understand it in this way, you can easily remember that interceptor execution is like a stack data structure, first in first out, last in first out
  2. For example, the first preHandle interception is interceptor 1 and then interceptor 2. The second postHandle interception is interceptor 2, then interceptor 1, and the third afterCompletion is interceptor 2, then interceptor 1
  3. Take the first interception as entering the stack, and the remaining two interceptions as leaving the stack.

7. Process files and upload Multipart data

Traditional SSM projects need jar package dependency, but spingboot does not

    <!--File upload-->
The second step is to upload the Bean instance of the parser from the configuration file. The id is a fixed multipartResolver. Don't name it at will

    <!--File upload parser, multi-element parser-->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <!--Set the maximum upload limit in bytes.-1 Indicates that there are no restrictions-->
        <property name="maxUploadSize" value="1000000000"></property>
The third step is to specify MultipartFile in the parameter list. Like ModelMap, springMVC will encapsulate parameters during reflection, while requests and multipartfiles will be specially processed. Note that the parameter name needs to correspond to the front end, otherwise the annotation needs to be specified to correspond to the front end parameter name, such as @ RequestParam("fileUpload") MultipartFile

8. Exception handling mechanism

(not recommended method) we can capture the corresponding exception by annotating @ exceptionhandler (exception type. class) in the controller

Declare a class with the annotation @ ControllerAdvice

import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;

import javax.servlet.http.HttpServletResponse;

public class ExceptionAdvice {
     * @ExceptionHandler(The type of exception to catch class)
     * @param exception The caught exception must be larger (or equal to) than the type specified in the ExceptionHandler annotation. Otherwise, it cannot be cast
    public void handleException(ArithmeticException exception, HttpServletResponse response){
        }catch (IOException e){

9. Pass the flash attribute with the spring MVC redirection parameter

Although it is not used much, it also needs to be understood. The redirection url will change, the parameters will be lost, and two requests will be sent. Forward, the url will not change, the parameters will not be lost, and a request
  1. Requirements, A redirects to B method, and the parameters are not lost
    public String A(String name, RedirectAttributes redirectAttributes){
        //Method 1: direct string splicing
//        return "redirect:B?name="+name;

        //Method 2: the flash attribute is temporarily stored in the session. After jumping to the page, the attribute is destroyed
        return "redirect:B";

    public void B(@ModelAttribute("name") String name){

3, Spring MVC source code

For length reasons, I put it in this article

Topics: Java git Framework Spring MVC source code