preface

As we all know, Java development is called Spring development by the old master subroutine apes, which shows the status of Spring in Java development. Without the Spring framework, most people’s code would be shit.

Spring MVC is one of the most important of Spring’s seven modules.

The MVC framework is a full-featured implementation of MVC for building Web applications. The MVC framework becomes highly configurable through the policy interface

If you are interested in the other 6 modules of the Spring framework, you can directly click and get the complete Spring learning notes I organized. There are a lot of source code analysis and project practice, you can communicate with me.

MVC Design Overview

In the early development of Java Web, the operations of display layer, control layer and data layer were all handed over to JSP or JavaBeans for processing, which we called Model1:

  • Disadvantages:
  • There is a strong coupling between JSPs and Java beans, as well as between Java code and HTML code
  • Developers are required not only to master Java, but also to have a superb front-end level
  • The front end and the back end depend on each other, with the front end waiting for the back end to complete and the back end depending on the front end to complete effective testing
  • Code is hard to reuse

Due to these disadvantages, this approach was quickly replaced by Servlets + JSPs + Java Beans. The early MVC model (Model2) looked something like this:

First, the user’s request will arrive at the Servlet, then call the corresponding Java Bean according to the request, and hand over all the display results to the JSP to complete the pattern, which is called the MVC pattern.

  • M is for Model, what is a Model? The model is the data, the DAO, the bean
  • V is for View, so what’s a View? It’s the Web page, the JSP, that presents the data in the model
  • C is for controller. What’s a controller? The role of the controller is to display different models of data in different views. Servlets play this role.

Spring MVC architecture

In order to solve the persistent layer has not been processed database transactions programming, and to cater to the strong rise of NoSQL, Spring MVC provides a solution:

The traditional model layer is split into Service layer (Service) and Data Access layer (DAO). Spring’s declarative transactions can be used to manipulate the data access layer under the Service, and NoSQL can be accessed on the business layer, which can meet the needs of NoSQL, which can greatly improve the performance of Internet systems.

  • Features: Loose structure, almost all kinds of views can be loosely coupled in Spring MVC, and each module is separated and seamlessly integrated with Spring
    • *

Hello Spring MVC

Let’s write our first Spring MVC program:

Step 1: Create a new Spring MVC project in IDEA

And call it HelloSpringMVC, click [Finish] :

IDEA will automatically help us download the necessary JAR packages, and create some default directories and files for us. After the creation of the project structure is as follows:

Step 2: Modify web.xml

Let’s open the web.xml and complete the modification as shown in the following image:

Change the

element to /, indicating that all requests are to be intercepted and handled by the Spring MVC background controller. After this change:

<servlet-mapping>
    <servlet-name>dispatcher</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

Step 3: Edit dispatcher-servlet.xml

The beginning dispatcher of this filename corresponds to the dispatcher configured by the

element in the web.xml above. This is the mapping configuration file of Spring MVC (XXX -servlet.xml). We edit it as follows:

<? The XML version = "1.0" encoding = "utf-8"? > <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="simpleUrlHandlerMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> <property name="mappings"> <props> <! > <prop key="/hello"> HelloController </prop> </props> </property> </bean> <bean id="helloController" class="controller.HelloController"></bean> </beans>

Step 4: Write the HelloController

In Package created under the controller 】 【 【 HelloController 】 classes, and realize the org. Springframework. Web. Servlet. MVC. Controller interface:

package controller; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.mvc.Controller; public class HelloController implements Controller{ @Override public ModelAndView handleRequest(javax.servlet.http.HttpServletRequest httpServletRequest, javax.servlet.http.HttpServletResponse httpServletResponse) throws Exception { return null; }}
  • Problem: The javax.servlet package cannot be found
  • Solution: Copy the servlet-api.jar package from the directory [lib] of the local Tomcat server to the project [lib] folder and add dependencies

Spring MVC brings the ModelAndView together through the ModelAndView object

ModelAndView mav = new ModelAndView("index.jsp");
mav.addObject("message", "Hello Spring MVC");

So in this case the view is the index.jsp model and the data is a message that says “Hello Spring MVC.”

package controller; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.mvc.Controller; public class HelloController implements Controller { public ModelAndView handleRequest(javax.servlet.http.HttpServletRequest httpServletRequest, javax.servlet.http.HttpServletResponse httpServletResponse) throws Exception { ModelAndView mav = new ModelAndView("index.jsp"); mav.addObject("message", "Hello Spring MVC"); return mav; }}

Step 5: Prepare index.jsp

Change the contents of index.jsp to:

<%@ page language="java" contentType="text/html; charset=UTF-8"
   pageEncoding="UTF-8" isELIgnored="false"%>

<h1>${message}</h1>

The content is very simple, using an EL expression to display the contents of Message.

Step 6: Deploy Tomcat and its associated environment

Go to “Edit Configurations” under the “Run” menu.

Configure the Tomcat environment:

Select the local Tomcat server and change the name:

Under the Deployment TAB, complete the following:

Click OK and we’ll get the Tomcat server up and running by clicking the triangle in the upper right corner.

  • Problem: The Tomcat server failed to start properly
  • Cause: The Tomcat server could not find the associated JAR package
  • Clip-and-paste the entire [lib] folder to [WEB-INF] and re-create the dependency:

Step 7: Restart the server

Restart the server and enter the address: localhost/hello

Click to receiveComplete Spring Learning Notes

Tracking Spring MVC requests

Each time the user click the link in your Web browser or submit the form, the request to work, like the postman, returning from leave the browser to get a response, it will experience a lot of sites, leaving some of the information on every site will also bring other information, the image below for the request of the Spring MVC process:

First stop: DispatcherServlet

When the request leaves the browser, the first stop is the DispatcherServlet, look at the name and this is a Servlet that we learned from J2EE that servlets can intercept and process HTTP requests, The DispatcherServlet intercepts all requests and sends them to the Spring MVC controller.

<servlet> <servlet-name>dispatcher</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dispatcher</servlet-name> <! > <url-pattern>/</url-pattern> </servlet-mapping> -- intercept all requests --> <url-pattern>/</url-pattern> </servlet-mapping>
  • The task of the DispatcherServlet is to intercept requests sent to the Spring MVC controller.

Stop 2: HandlerMapping

  • Question: There may be multiple controllers in a typical application. Which controller should these requests be directed to?

So the DispatcherServlet will query one or more processor mappings to determine the next stop of the request, and the processor mappings will make decisions based on the URL information carried by the request, such as in the example above, Let’s assign the /hello address to the HelloController by configuring SimpleLHandlerMapping:

<bean id="simpleUrlHandlerMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> <property name="mappings"> <props> <! > <prop key="/hello"> HelloController </prop> </props> </property> </bean> <bean id="helloController" class="controller.HelloController"></bean>

Third stop: the controller

Once the appropriate controller has been selected, the DispatcherServlet sends the request to the selected controller, where the request is unloaded (the user-submitted request) and waits for the controller to process the information:

public ModelAndView handleRequest(javax.servlet.http.HttpServletRequest httpServletRequest, Javax.mail. Servlet. HTTP. HttpServletResponse HttpServletResponse) throws the Exception {/ / processing logic... }

Stop 4: Return the DispatcherServlet

When the controller has finished the logical processing, it usually produces some information, which is the information that needs to be returned to the user and displayed in the browser, which is called the Model. It’s not enough to just return the raw information — the information needs to be formatted in a user-friendly way, usually HTML, so the information needs to be sent to a view, usually a JSP.

The last thing the controller does is wrap up the model data and represent the view name (logical view name) that will be used for rendering output. It then sends the request back to the DispatcherServlet, along with the model and view name.

public ModelAndView handleRequest(javax.servlet.http.HttpServletRequest httpServletRequest, Javax.mail. Servlet. HTTP. HttpServletResponse HttpServletResponse) throws the Exception {/ / processing logic... // Return mav to DispatcherServlet; }

Fifth stop: View parser

This way, the controller is not coupled to a particular view, and the view name passed to the DispatcherServlet does not directly represent a particular JSP. (In fact, it’s not even sure that the view is a JSP.) Instead, it just passes a logical name that will be used to find the real view that produced the result.

The DispatcherServlet will use the View Resolver to match the logical view name to a specific view implementation, which may or may not be a JSP

The example above is directly bound to the index.jsp view

Stop 6: View

Now that the DispatcherServlet already knows which view to render the results from, the requested task is basically done.

Its last stop is the implementation of the view, where it delivers the model data and the requested task is done. The view renders the result using the model data, and the output is passed to the client via the response object.

<%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8" isELIgnored="false"%>

<h1>${message}</h1>

Configure Spring MVC using annotations

Now that we know a little bit about Spring MVC and have created our first Spring MVC application using XML configuration, let’s look at how to configure the application based on annotations:

Step 1: Add annotations for the HelloController

package controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; @Controller public class HelloController{ @RequestMapping("/hello") public ModelAndView handleRequest(javax.servlet.http.HttpServletRequest httpServletRequest, javax.servlet.http.HttpServletResponse httpServletResponse) throws Exception { ModelAndView mav = new ModelAndView("index.jsp"); mav.addObject("message", "Hello Spring MVC"); return mav; }}

The implementation of the interface is also removed.

  • A brief explanation:
  • @ControllerComments:

    Obviously, this annotation is used to declare controllers, but in fact this annotation has little effect on Spring MVC itself. Spring Acts says that it is only to assist the implementation of component scanning, can be used@ComponentThe above example does not have a JSP view parser configured. I even have one of my own, but it still doesn’t work.
  • @RequestMappingComments:

    Obviously, this is the path/helloWill map to the method

Step 2: Uncomment the previous XML

In the dispatcher-servlet.xml file, comment out the previous configuration and add a component scan:

<? The 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:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <! --<bean id="simpleUrlHandlerMapping"--> <! --class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">--> <! --<property name="mappings">--> <! --<props>--> <! --&lt; ! &ndash; The request for the /hello path is handed to the controller with id HelloController &ndash; &gt; -- > <! --<prop key="/hello">helloController</prop>--> <! --</props>--> <! --</property>--> <! --</bean>--> <! --<bean id="helloController" class="controller.HelloController"></bean>--> <! > <context:component-scan base-package="controller"/> </beans>

Step 3: Restart the server

When the configuration is complete, restart the server and type localhost/hello address to still see the result:

@RequestMapping annotates details

If @RequestMapping is applied to a class, it is equivalent to appending an address to all configured mapping addresses of the class, for example:

@Controller @RequestMapping("/wmyskxz") public class HelloController { @RequestMapping("/hello") public ModelAndView handleRequest(....) throws Exception { .... }}
  • Then access address:localhost/wmyskxz/hello
    • *

Configure the view parser

Remember our Spring MVC request flow, the view parser is responsible for locating the view, and it accepts a logical view name passed by the DispaterServlet to match a particular view.

  • Requirements: There are some pages that we do not want users to access directly, such as pages with important data, such as pages supported by model data.
  • Caused problems:

    We can place [test. JSP] in the root directory of [web] to simulate a page of important data, we don’t have to do anything, restart the server, and type in the pagelocalhost/test.jspI’ll be able to access it directly, and that will causeThe data reveal that.

    Or we can just type it inlocalhost/index.jspTry, according to our above procedure, this will be a blank page, because it is not retrieved${message}Parameter is accessed directly. This willImpact on user experience

The solution

We configured our JSP files in the [PAGE] folder in the [WEB-INF] folder, which is the default secure directory in the Java Web, You will not be able to access it directly (i.e. you say you will never be able to access it via localhost/ web-inf/etc)

But we need to tell this to the view parser, so we do the following configuration in the dispatcher-servlet.xml file:

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

A view parser built into Spring MVC is configured here, which follows the convention of adding prefixes and suffixes to view names to determine the physical path of view resources in a Web application. Let’s actually look at the effect:

Step 1: Modify the HelloController

Let’s modify the code:

Step 2: Configure the view parser:

According to the above configuration, complete:

<? The 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:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <! --<bean id="simpleUrlHandlerMapping"--> <! --class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">--> <! --<property name="mappings">--> <! --<props>--> <! --&lt; ! &ndash; The request for the /hello path is handed to the controller with id HelloController &ndash; &gt; -- > <! --<prop key="/hello">helloController</prop>--> <! --</props>--> <! --</property>--> <! --</bean>--> <! --<bean id="helloController" class="controller.HelloController"></bean>--> <! > <context:component-scan base-package="controller"/> <bean id=" ViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/page/" /> <property name="suffix" value=".jsp" /> </bean> </beans>

Step 3: Cut and paste the index.jsp file

Create a new [Page] folder under the [WEP-INF] folder and cut and paste the [index.jsp] file into it:

Step 4: Update resources and restart the server

accesslocalhost/helloPath to see the correct effect:

  • Principle:

The logical view we pass in is called index, plus the prefix “/ web-inf /page/” and the suffix “.jsp “to determine the path to the physical view, so that we can later put all the views in the [pages] folder!

  • Note: The configuration at this point is only under dispatcher-servlet.xml
    • *

The controller receives the requested data

Receiving parameters using a controller is often the first step in developing business logic for Spring MVC. To explore how Spring MVC passes parameters, let’s start by creating a simple form for submitting data:

<! DOCTYPE html> <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" import="java.util.*" isELIgnored="false"%> <html> <head> <meta charset="utf-8"> </title> </head> <body> <form action="/param" role="form" <input type="text" name="userName"><br/ BBB > <input type="text" name="password"><br/> <input type="submit" value=" >< /form> </body> </ HTML >

To be ugly, here’s the test:

Using the Servlet native API:

We can easily see that the form will be submitted to the /param directory, so let’s use the Servlet native API first to see if we can get the data:

@RequestMapping("/param")
public ModelAndView getParam(HttpServletRequest request,
                        HttpServletResponse response) {
   String userName = request.getParameter("userName");
   String password = request.getParameter("password");

   System.out.println(userName);
   System.out.println(password);
   return null;
}

Test successful:

Use the same name matching rule

We can get the data (matching rule with the same name) by setting the parameter name of the method definition to be the same as the parameter name passed in the foreground:

@RequestMapping("/param")
public ModelAndView getParam(String userName,
                            String password) {
   System.out.println(userName);
   System.out.println(password);
   return null;
}

Test successful:

  • Problem: This creates a strong coupling with the front desk, which we don’t want
  • Solution:use@requestParam (" foreground parameter name ")To infuse:

  • @RequestParamNotes details:

    This annotation has three variables:value,required,defaultvalue
  • value: specifynameWhat’s the name of the property,valueProperties can be left unwritten by default
  • required: Whether this parameter is required, can be set to true or false.
  • defaultvalue: Set default values

Passing parameters using models

  • Requirement: The foreground parameter name must be the same as the field name in the model

Let’s start by creating a User model for our form:

package pojo;

public class User {
   
   String userName;
   String password;

   /* getter and setter */
}

Then the test is still successful:

Chinese garbled code problem

  • Note: As in servlets, this method only works with POST methods (because it is a direct request).

We can do this by configuring the Spring MVC character encoding filter by adding:

<filter> <filter-name>CharacterEncodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <! > <param-value>utf-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>CharacterEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>

The controller echoes the data

So we know how to accept the request data and solve the POST mess problem, so how do we echo the data? To do this we create a [test2.jsp] under [page] :

<! DOCTYPE html> <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" import="java.util.*" isELIgnored="false" %> <html> <head> <title>Spring MVC Echo data < / title > < / head > < body > < h1 > echo data: ${message} < / h1 > < / body > < / HTML >

Use the Servlet native API to implement

Let’s test the Servlet native API to see if it does the job:

@RequestMapping("/value") public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse Response) {request.setAttribute("message"," Success!" ); return new ModelAndView("test1"); }

In the browser address bar, type: localhost/value test

Use the ModelAndView object provided by Spring MVC

Using the Model object

In Spring MVC, we usually bind data in this way,

  • use@ModelAttributeComments:

    @modelAttribute public void model(model model) {model.addAttribute(" Message ", "Attribute successfully "); } @RequestMapping("/value") public String handleRequest() { return "test1"; }

When you access the controller’s handleRequest() method, it will call the model() method first to add message to the page parameter, which can be called directly from the view, but it will cause all of the controller’s methods to call the model() method first. But it’s also convenient, because you can add all kinds of data.


Client jump

JSP, or /test to test.jsp. These are server-side jumps, Is the request. GetRequestDispatcher (” address “). The forward (request, response);

So how do we do a client-side jump? Let’s go ahead and write it in HelloController:

@RequestMapping("/hello")
public ModelAndView handleRequest(javax.servlet.http.HttpServletRequest httpServletRequest, javax.servlet.http.HttpServletResponse httpServletResponse) throws Exception {
    ModelAndView mav = new ModelAndView("index");
    mav.addObject("message", "Hello Spring MVC");
    return mav;
}

@RequestMapping("/jump")
public ModelAndView jump() {
    ModelAndView mav = new ModelAndView("redirect:/hello");
    return mav;
}

If we use redirect:/hello to indicate that we want to jump to the /hello path, we restart the server and enter: localhost/jump in the address bar. It will automatically jump to the /hello path:

It can also be used like this:

@RequestMapping("/jump")
public String jump() {
    return "redirect: ./hello";
}

File upload

Let’s review traditional file uploads and downloads first: here

Let’s take a look at how to upload and download files in Spring MVC

  • Note:Need pilot entryCommons - IO - 1.3.2. The jar 和 Commons fileupload - 1.2.1 jarTwo packages

Step 1: Configure the upload parser

Add a new line to dispatcher-servlet.xml:

<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"/>

Enable support for uploading

Step 2: Write the JSP

The file is called Upload.jsp and is still created under [page] :

<%@ page contentType="text/html; Charset = utf-8 "language=" Java" %> < HTML > <head> <title> </head> <form action="/upload" Method ="post" encType ="multipart/form-data"> <input type="file" name="picture"> <input type="submit" value=" post" > <input type="file" name="picture </form> </body> </html>

Step 3: Write the controller

Create a new UploadController class under Package [Controller] :

package controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.multipart.MultipartFile; import org.springframework.web.servlet.ModelAndView; @Controller public class UploadController { @RequestMapping("/upload") public void upload(@RequestParam("picture") MultipartFile picture) throws Exception { System.out.println(picture.getOriginalFilename()); } @RequestMapping("/test2") public ModelAndView upload() { return new ModelAndView("upload"); }}

Step 4: Test

Enter localhost/test2 in the browser address bar, select file and click upload. The test is successful:


This article is mainly for those who are not familiar with Spring MVC, so there must be a lot of things not written, including other modules of the Spring framework, I will update it when there is time, so interested friends can point to follow, by the way, point to like it!

Of course, if you can’t wait, you can click to get the complete Spring learning notes

end