preface

As we all know, Java development is nicknamed Spring development by the old subroutine geeks, which shows the status of Spring in Java development. Without the Spring framework, most people write shit.

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

The MVC framework is a full-featured MVC implementation for building Web applications that is made highly configurable through policy interfaces

Friends who are interested in the other six modules of the Spring framework can directly click on the complete Spring study notes I organized, which has a large number of source code analysis and project practice, you can communicate with them.

Overview of MVC Design

In the early development of Java Web, the unified display layer, control layer, data layer operations are all handed over to JSP or JavaBean for processing, we call Model1:

  • Disadvantages:
  • There is heavy coupling between JSPS and Java beans, and Java code and HTML code are also coupled together
  • Developers are required not only to master Java, but also to have advanced front-end skills
  • The front end and the back end depend on each other. The front end needs to wait for the back end to complete, and the back end also depends on the front end to complete in order to conduct effective testing
  • Code is hard to reuse

Because of these drawbacks, this approach was soon replaced by servlets + JSP + Java beans. The early MVC model ** (Model2) ** looks like this:

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

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

The Architecture of Spring MVC

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

** The traditional model layer is split into a Business layer (Service) and a Data Access Object (DAO). ** The data access layer is operated under Service through Spring’s declarative transactions, while the business layer also allows us to access NoSQL, which can meet the burgeoning use of NoSQL, which can greatly improve the performance of Internet systems.

  • Features: Loose structure, almost all views can be loosely coupled in Spring MVC, module separation and seamless integration with Spring

Hello Spring MVC

Let’s write our first Spring MVC application:

Step 1: Create a New Spring MVC project in IDEA

Call it HelloSpringMVC and click Finish:

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

Step 2: Modify web.xml

Let’s open web.xml and modify it as shown below:

Change the

element to/to block all requests and submit them to Spring MVC’s background controller for processing.

<servlet-mapping>
    <servlet-name>dispatcher</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>
Copy the code

Step 3: Edit dispatcher-servlet.xml

This is the Spring MVC mapping configuration file (xxx-servlet.xml), which we edited 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</ props> </property> </bean> <bean id="helloController" class="controller.HelloController"></bean> </beans>Copy the code

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; }}Copy the code
  • There is a problem: javax. Servlet package cannot be found
  • Solution: Copy the servlet-api.jar package from the [lib] folder on the local Tomcat server to the project [lib] folder and add dependencies

Spring MVC combines the ModelAndView through the ModelAndView object

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

In this case, the view is the index.jsp model and the data is the message, and the content is “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; }}Copy the code

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>
Copy the code

The content is simple, showing the content of message with an El expression.

Step 6: Deploy Tomcat and its environment

Find Edit Configurations under the [Run] menu item.

Configuring the Tomcat environment:

Select the local Tomcat server and change the name:

Under the Deployment TAB do the following:

Click OK and let’s click on the triangle in the upper right to get the Tomcat server running.

  • Problem: The Tomcat server does not start properly
  • Cause: The Tomcat server could not find the related JAR package
  • Cut and paste the [lib] folder into the [WEB-INF] folder and re-create the dependency:

Step 7: Restart the server

Restart the server and enter localhost/hello

Click to receiveComplete Spring learning Notes

Trace 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

After the request leaves the browser, the first destination is DispatcherServlet, which is a Servlet. We know 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> <! -- Block all requests --> <url-pattern>/</url-pattern> </ servle-mapping >Copy the code
  • The job of the DispatcherServlet is to intercept the request and send it to the Spring MVC controller.

Second stop: HandlerMapping

  • ** Question: ** A typical application may have multiple controllers. Which controller should these requests go to?

So the DispatcherServlet queries one or more processor maps to determine the next stop for the request, and the processor map makes its decision based on the URL information carried by the request, such as in the example above, We pass the/Hello address to the helloController by configuring simpleUrlHandlerMapping:

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

Third stop: controllers

Once the appropriate controller is selected, the DispatcherServlet will send the request to the selected controller, where the request will unload its load (user-submitted requests) and wait for the controller to finish processing the information:

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

Fourth stop: Return to DispatcherServlet

When the controller completes its logical processing, it usually generates some information that needs to be returned to the user and displayed on the browser, which is called a Model. It’s not enough to just return the raw information — the information needs to be formatted in a user-friendly way, typically 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) used to render the output. It then sends the request back to the DispatcherServlet 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; }Copy the code

Fifth stop: View resolver

In 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 can’t even determine that the view is a JSP.) Instead, it passes just 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 binds directly to the index.jsp view

Sixth stop: Views

Now that the DispatcherServlet knows which view renders the result, the requested task is basically done.

Its final stop is the implementation of the view, where it delivers model data and the requested task is completed. The view uses the model data to render the result, which is passed to the client through the response object.

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

<h1>${message}</h1>
Copy the code

Configure Spring MVC with annotations

Now that we have some knowledge of Spring MVC and 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 to 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; }}Copy the code

Remove the implemented interface as well.

  • A quick explanation:
  • @ControllerAnnotation: Obviously, this annotation is used to declare the controller, but it doesn’t really have much impact on Spring MVC itself. It is only an aid to implement component scanning and can be used@ComponentAnnotations instead, but I tried it myself and it didn’t work because the above example didn’t have a JSP view parser configured.
  • @RequestMappingNote: Obviously, this means path/helloIs mapped to that method

Step 2: Uncomment the previous XML comment

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

<? 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; /hello path request to 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>Copy the code

Step 3: Restart the server

When the configuration is complete, restart the server and enter localhost/hello.

@requestMapping annotate details

If @requestMapping is applied to a class, then you add an address to all configured mapping addresses for that class, for example:

@Controller @RequestMapping("/wmyskxz") public class HelloController { @RequestMapping("/hello") public ModelAndView handleRequest(....) throws Exception { .... }}Copy the code
  • Access address:localhost/wmyskxz/hello

Configure the view resolver

Remember our Spring MVC request flow, the view parser is responsible for locating the view, and it accepts a logical view name passed by a 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.
  • Problems caused:We can put a [test.jsp] page in the [web] root directory that simulates an important data, we don’t have to do anything, restart the server, type in the web pagelocalhost/test.jspI would be able to access it directly, which would causeThe data reveal that. And we can just type it inlocalhost/index.jspTry, according to our program above, this will be a blank page, because it is not retrieved${message}The parameter is directly accessed, which will beAffecting user experience

The solution

We configured our JSP files in the page folder of the WEB-INF folder, which is the default secure directory in the Java WEB. Is not allowed to be accessed directly * (i.e. you say you can never access it via localhost/WEB-INF/) *

But we need to tell this to the view parser, which we do 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>
Copy the code

A view parser built into Spring MVC is configured here. The parser follows a convention that prefixes and suffixes view names to determine the physical path of view resources in a Web application. ** Let’s actually see the effect:

Step 1: Modify the HelloController

Let’s change 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; /hello path request to 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>Copy the code

Step 3: Clip the index.jsp file

Create a new page folder under web-INF 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:

We pass in the logical view name index with the prefix “/WEB-INF/page/” and the suffix “.jsp “to determine the path of the physical view, so that we can put all the views in the page folder later!

  • ** Note: ** this configuration is only for dispatcher-servlet.xml

The controller receives the request data

Receiving parameters with a controller is often the first step in developing Spring MVC business logic. To explore the way Spring MVC passes parameters, let’s create 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"> <input type="text" name="password"><br/> < form> < body> </ HTML >Copy the code

If it’s ugly, let’s put it to the test:

Using the Servlet native API:

It’s easy to know that the form will be submitted to the /param directory, so let’s use the Servlet native API 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;
}
Copy the code

Test success:

Use a matching rule of the same name

We can set the parameter name of the method definition to the same as the parameter name passed to the foreground to get the data (namesake matching rule) :

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

Test success:

  • Problem: This leads to strong coupling with the foreground, which we don’t want
  • Solution:use@requestParam (" Foreground parameter name ")To infuse:

  • @RequestParamNote details:This annotation has three variables:value,required,defaultvalue
  • value: specifynameWhat is the name of the property,valueProperties can be left unwritten by default
  • required: Specifies whether this parameter is required. It can be set to true or false.
  • defaultvalue: Sets the default value

Use model to pass parameters

  • 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 */
}
Copy the code

Then the test is still successful:

Chinese garbled characters

  • Note: As in the Servlet, this method only works with the POST method (since it is a request being processed directly)

We can do this by configuring the Spring MVC character encoding filter to add to web.xml:

<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>Copy the code

The controller displays data

Now that we know how to accept request data, and can solve the problem of POST garbled characters, how to echo data? To do this, create 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 >Copy the code

This is done using the Servlet native API

Let’s test whether the Servlet native API can do the job:

@RequestMapping("/value") public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse Response) {request.setattribute ("message"," success!" ); return new ModelAndView("test1"); }Copy the code

Enter localhost/value in the address bar of the browser to test it

Use the ModelAndView object provided by Spring MVC

Working with Model objects

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

  • use@ModelAttributeComments:
@modelAttribute public void model(model model) {model.addattribute ("message", "annotation succeeded "); } @RequestMapping("/value") public String handleRequest() { return "test1"; }Copy the code

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


Client Redirect

Whether address /hello goes to index.jsp or /test goes to test.jsp, these are server-side jumps. Is the request. GetRequestDispatcher (” address “). The forward (request, response);

So how do we do client jump? Let’s go ahead and write 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;
}
Copy the code

Redirect :/hello we use redirect:/hello to redirect to /hello. Restart the server and type localhost/jump into the address bar. This automatically redirect to /hello:

It can also be used like this:

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

File upload

Let’s start by reviewing traditional file uploads and downloads: here

How do you implement file upload and download in Spring MVC

  • Note:First entry requiredCommons - IO - 1.3.2. The jar 和 Commons fileupload - 1.2.1 jarTwo packages

Step 1: Configure the upload resolver

Add a new sentence to dispatcher-servlet.xml:

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

Copy the code

Enable the upload function

Step 2: Write the JSP

The file name is upload.jsp, and it will still be created under [page] :

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

Step 3: Write the controller

Create class UploadController 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"); }}Copy the code

Step 4: Test

Enter localhost/test2 in the address bar, select the file, and click Upload. The test succeeds.


This article is mainly for those who do not know about Spring MVC, so there must be a lot of things that have not been written, including other modules of the Spring framework, I will update when I have time, so interested friends can click attention, by the way, click a like it!

Of course, if you can’t wait, you can click on the complete Spring study notes

end