After coding for a period of time, I looked at the framework I had learned before and found a new cognition, such as Spring. I relearned it:

  • Welcome to the Spring era – Introduction
  • Welcome to the Spring era
  • Proxy pattern – Introduction to AOP
  • Welcome to the Spring era (ii) AOP

I learned Spring MVC again this time. I watched the video at STATION B when I learned Spring MVC before, which was really good and allowed me to get started quickly. However, I still felt that it was not very systematic and the knowledge points were fragmented. If you don’t have the basics of Java EE, refer to the JavaWeb video tutorial. If you don’t have the basics of Spring Framework, refer to my article above. If four is too many, Welcome to the Spring era (a) IOC list, if you can, or suggest to read the above four articles to see these four articles.

Problems in the age of native servlets

Simply put, a Servlet is an interface in Java, located under Javax. Servlet. Let’s take a look at the comments on the Servlet:

A servlet is a small Java program that runs within a Web server. Servlets receive and respond to requests from Web clients,usually across HTTP, the HyperText Transfer Protocol.

A Servlet is a small Java program that runs on a Web server. A Servlet receives and processes requests from Web clients, usually using the Http protocol. We usually use its implementation class, HttpServlet, and override the doGet and doPost methods as follows:

WebServlet(name ="/servlet") public class ServletDemo extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { req.getParameterNames(); req.getParameter("username"); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// Process the POST request super.dopost (req, resp); }}Copy the code

What are its pain points? HttpServletRequest () : HttpServletRequest () : HttpServletRequest () : HttpServletRequest () : HttpServletRequest () :So where does getParameterNames go? HttpServletRequest is an interface, and getParameterNames inherits from ServletRequest.Can programmers focus more on business logic and make it easier to get parameters? For example, I want to use student object to receive parameters, and for example, I need only a Long id to receive parameters, can I directly use Long ID to receive parameters? That’s the first question we asked, can we make it easier to take parameters. In addition to taking parameters, Ajax technology has been widely used today, can LET me respond to the front-end Ajax request in a simpler? In the native Servlet, we handle Ajax, we code the Settings in the response, set the type of response, and then use some Java JSON library to convert our object into JSON form and send it to the front end, roughly like this:

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    Student student = new Student(13."223".null);
    Gson gson = new Gson();
    resp.setContentType("application/json; charset=utf-8");
    System.out.println("Handle GET requests");
    PrintWriter writer = resp.getWriter();
Copy the code

This is the second question we raised. There are also file upload and download, native Servlet file name garbled problem, unified handling of exceptions, the system error directly return the error log to the web page? The user looks stunned. What’s going on? Can we handle exceptions uniformly? For example, if a fault occurs on the server, you can send a message indicating that an error occurs on the server. Contact system engineers. Maybe it would be friendlier.

To summarize

Let’s recap some of the pain points we’ve encountered with native servlets for Web programming:

  • Handling parameters is troublesome and does not conform to object-oriented principles
  • Dealing with Ajax is cumbersome, and some of the processes are generic but repetitive
  • Upload and download files Chinese name garbled
  • No unified exception handling mechanism is provided

These four things let’s focus on business logic at the same time, also want to spend it on take parameters, these problems is to use native Servlet, general will meet naturally we encounter these problems to the native extensions to the Servlet, so now that you can use, then someone will or community according to the above problem, This type of framework is commonly referred to as a Web framework, and is commonly used in the Java Web domain:

  • Spring MVC

Spring Web MVC is produced by Spring Company. It is actually called Spring Web MVC, but we prefer to call it Spring MVC. It has powerful performance and can integrate seamlessly with the Spring Framework.

  • Apache Struts 2.x

Apache, but not as high performance as Spring MVC, which is more widely used

  • Apache Tapestry 5.x

Apache, this is the first time I saw this framework, when I was learning Spring MVC again, I went to the official document to see this framework, check, found that there is not much information. Here is the understanding.

This article is about Spring MVC. When you are studying, you should pay attention to your ideas. Technology develops very fast. That is the idea, problem solving, maybe the idea is the same, but there may be some small differences in the concrete implementation, which is to learn a hundred. That’s why I’m going to spend a lot of time at the beginning of this article talking about the reasons for this technology and the ideas. It’s easy to talk about frameworks, but it’s harder to talk about ideas.

Here I also want to talk about how to learn knowledge, usually if the official document is written well, I will directly read the official document, because the official document is relatively more authoritative, but also first-hand information. I am relearning Spring MVC. I went to the official documentation of Spring MVC and found it is quite good. If you are interested, you can also read the official documentation.

  1. IO /projects/sp… Go to the Spring official website.

The preparatory work

In this article, we still use Maven to build projects. If you don’t know Maven, you still want to download JAR packages. In the article welcome to Spring era (I), I also introduced the method of downloading JAR packages. Welcome to the Spring era. We need to continue to use the new dependencies as follows:

			<version>5.2.8. RELEASE</version>
Copy the code

First to use

The Web framework for the Java Web domain described above solves the problem we raised above by extending native servlets. How do you use the set of extended servlets provided by Spring MVC? The first thing to do is to let Tomcat know when it starts, which is to configure it in web.xml:

       <! , the parameters of the initial dispatcherServlet needs contextConfigLocation, dispatcherServlet have this property - >
			<! Load configuration file, specify location of configuration file -->
        <! The element marks whether the container should load the servlet when the Web application starts (instantiate and call its init() method). -->
         <! Intercept all requests -->
        <! -- /user: block all requests starting with /user -->
        <! -- /user/ block only the request -->
        <! --.action: intercepts only.action requests -->
Copy the code

ContextConfigLocation = DispatcherServlet contextConfigLocation = DispatcherServletIf it is not found, let’s go to its parent class:When we initialize the DispatcherServlet, we specify the location of the configuration file. What should we configure in the configuration file? In addition to database connection pooling and the like, remember when we were programming with native Servelt+ JSP, we could also control the jump to the page. Although the jump to the page was taken away by the front-end in the days of front end separation, Spring MVC still provides this feature, which is called the View parser in Spring. So add this configuration file to the configuration file, which is the IOC container. Writing here may seem a bit like Spring integrating Spring MVC, but in the Java Web world Spring is the center of managed objects, and no matter what framework you use, you need to incorporate core objects into the IOC container so we can use them elegantly. So at the beginning we emphasize that we should learn this article on the basis of Spring. The following items need to be configured in the configuration file:

  <! -- Configure the scanner -->
    <context:component-scan base-package="org.example"/>
    <! -- Configure the view parser -->
    <bean id = "internalResourceViewResolver" class = "org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name = "prefix" value = "view/"></property>
        <property name = "suffix" value = ".jsp"></property>
Copy the code

Those of you who have studied Spring will know the utility of configuring the scanner to add spring-annotated classes (@Controller, @Service, @Repository, @Component) to the IOC container. What does the configured view parser do? This class is used to control the jump to the page, so what does this prefix mean? Suppose Spring MVC thinks you are returning a view (i.e. a page), as follows:

// This annotation changes the class to handle HTTP requests
public class StudentController {
    // Requests with GET and servlet URIs will be processed
    @RequestMapping(value = "/servlet", method = RequestMethod.GET)
    public String testGet(a) {
        System.out.println("hello world");
        return "success";
     // Requests with post and servlet URIs will be processed
    @RequestMapping(value = "/servlet", method = RequestMethod.POST)
    public String testPost(a) {
        System.out.println("hello world");
        return "success"; }}Copy the code

If the return value is String, Spring MVC will assume you want to jump to the view/success.jsp page. Let’s create one called success.jsp under webApp.Let’s test it out:


To use the extended Servlet provided by Spring MVC, we first need to have Spring MVC’s DispatcherServlet take over all our requests in the web. XML configuration file. To do this, We need to have Tomcat initialize the DispatcherServlet at startup.

When a class has the @Controller annotation on it, it is treated as a request-handling class in the Spring MVC framework, and it has the @RequestMapping method to handle HTTP requests. The value attribute in @requestMapping specifies the URI. If the HTTP request URI matches the value attribute in @RequestMapping, the request will enter the method. Method in @requestMapping is used to restrict the request type. The value of method must be the RequestMethod type, and RequestMethod is method.

Due to the Spring MVC in the beginning of design, separation time hasn’t come before and after the end, Java can also control page jump at that time, so the Spring MVC made view internalResourceViewResolver parsing. But there’s not much to be said about page-jumping or static resource handling, which is no longer appropriate in this era of back-end separation.

Simplify the way you take parameters

It seems that the classes that handle requests under Spring MVC have changed a little bit and don’t make fetching parameters easier. Let’s take a look at some of the elegant arguments in Spring MVC with a few comments.

Direct contact object

Spring MVC can convert front-end parameters directly into an object. If the parameter name can be matched, first we prepare a simple object:

// To save space, Lombok is introduced here. These annotations can generate constructors, get, set, and override toString
public class User {
    private String userName;
    private String password;
Copy the code

@Controller public class StudentController { @RequestMapping(value = “/obj”, method = RequestMethod.GET) public String testOBj(User user) { System.out.println(user); return “success”; }}The test results


public class StudentController {
    @RequestMapping(value = "/servlet", method = RequestMethod.GET)
    public String testGet(@RequestParam(value = "name") String userName, @RequestParam(value = "password") String password) {
        System.out.println("username:" + userName);
        System.out.println("password:" + password);
        return "success"; }}Copy the code

If the HTTP request parameter name is the same as the method parameter name, the Spring MVC request method’s method parameters can be received directly when the request enters the method. RequestParam (@requestParam, @requestParam, @requestParam, @requestParam, @requestParam, @requestParam, @requestParam) Let’s test it out:

This parameter can be removed by setting the @requestParam required attribute to false. The default @requestParam request must have a parameter.

@ RequestHeader and @ CookieValue

  • RequestHeader: complete binding of RequestHeader data to processor function processing method parameters
  • CookieValue: Complete binding of Cookie data to method parameters of processor function processing methods

Let’s first look at what’s in the request header:As HTTP is a stateless protocol, when the server needs to record the status of the user, it needs to use some mechanism to identify the specific user, and this mechanism is Session. This mechanism is called Session. In a typical scenario like a shopping cart, when you place a button on your computer, because of the stateless HTTP protocol, you don’t know which user is doing it, so the server creates a special Session for that particular user, to identify that particular user, and that Session is stored on the server. Cookies are needed when a server identifies a specific user. Each TIME an HTTP request is made, the client sends a Cookie to the server. In fact, most applications use cookies to realize Session tracking. When a Session is created for the first time, the server will tell the client in the HTTP protocol that it needs to record a Session Id in the Cookie, and then send this reply Id to the server for each subsequent request. I knew who you were. Then let’s look at what’s in the Cookie:


public class StudentController {
    @RequestMapping(value = "info", method = RequestMethod.GET)
    public void test(@RequestHeader("User-Agent") String useAgent, @CookieValue("JSESSIONID") String jsesionId) { System.out.println(useAgent); System.out.println(jsesionId); }}Copy the code


We know that for get requests, the request parameters are placed after the URI and there is no request body. For POST requests, the request parameters can be placed after the URI or in the request body. Spring MVC encapsulates the request parameter as an object if the request parameter is get and the parameter name matches the request method parameter attribute name. I put the request parameters in the body of the request, and we need @RequestBody to convert the JSON-formatted data sent by the POST request into objects in Java.

Simplify file uploading

Upload of native servlets

Foreground code:

 <form action="upload" method = "post" enctype = "multipart/form-data"> User name :<input type ="text" name = "userName"/> Password :<input type ="text" name = "password"/> file :<input type ="file" name = "pic">
       <input type = "submit" value = "Submit">
Copy the code

In the days of native servlets, we did file uploads using components provided by Apache, and the logic in the background looked something like this:

 protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // unified encoding
        resp.setContentType("text/html; charset=UTF-8");
        boolean isMultipartContent = ServletFileUpload.isMultipartContent(req);
        Method must have an encType attribute
        if (isMultipartContent) {
            FileItemFactory fileItemFactory = new DiskFileItemFactory();
            ServletFileUpload servletFileUpload = new ServletFileUpload(fileItemFactory);
            List<FileItem> items = servletFileUpload.parseRequest(req);
            for (FileItem item : items) {
                if (item.isFormField()){
                    // Process the form's non-file fields
                    // Write the uploaded file to the file server
                    item.write(new File("Server path /")); }}}}Copy the code

Spring MVC uses the Apache component to upload files

  • Uploads using Apache components look like this

First in the config file, we will configure the file parser:

 <bean id = "commonsMultipartResolver" class = "org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <property name="maxUploadSize"> <! It's in B1048576 = 1024 * 1024 -->
Copy the code
 // With MultipartFile as the parameter, SpringMVC automatically injects the file object from the form into this parameter
 // SpringMVC also tries to put the form's non-file object into the User object
 // Post request It is customary to put file objects in the request body
 @RequestMapping(value = "mvcUpload" , method = RequestMethod.POST)
  public void testUpload1(@RequestBody  User u , MultipartFile pic){}Copy the code

I forgot to mention that the two Apache components have the following dependencies:

Copy the code

Servlet3 implements file uploads

First configure the upload location in web.xml:

        <! , the parameters of the initial dispatcherServlet needs contextConfigLocation, dispatcherServlet have this property - >
        <! Load configuration file, specify location of configuration file -->
        <! The element marks whether the container should load the servlet when the Web application starts (instantiate and call its init() method). -->
            <! -- Single data size -->
Copy the code

It’s important to note the version of the Servlet:Then add to the IOC container:

   <bean  id = "multipartResolver" class = "">
Copy the code

The back-end code is unchanged.

Simplified file download

It doesn’t feel like much of a simplification, and it’s not that much of a hassle to use native servlets. Spring MVC here just gives us another option. Here’s an example:

 @RequestMapping(value = "testUpload")
    public void downloadFile(Long id, HttpServletResponse resp, HttpServletRequest request) throws IOException {
        // Check the location of the file by id
        String userAgent = request.getHeader("User-Agent");
        if (userAgent.contains("IE")) {
            resp.setHeader("Content-Disposition"."attachment; filename=" + URLEncoder.encode("File name",;
        } else {
            resp.setHeader("Content-Disposition"."attachment; filename=" + new String("File name".getBytes("UTF-8"),;
        Files.copy(Paths.get("Folder"."File name"), resp.getOutputStream());

    @RequestMapping(value = "testUpload2")
    public ResponseEntity<byte[]> testUpload(Long id, HttpServletResponse resp, HttpServletRequest request) throws IOException {
        // Check the location of the file by id
        String userAgent = request.getHeader("User-Agent");
        HttpHeaders httpHeaders = new HttpHeaders();
        if (userAgent.contains("IE")) {
            resp.setHeader("Content-Disposition"."attachment; filename=" + URLEncoder.encode("File name",;
        } else {
            resp.setHeader("Content-Disposition"."attachment; filename=" + new String("File name".getBytes("UTF-8"),;
        Files.copy(Paths.get("Folder on the server"."File name"), resp.getOutputStream());
        byte[] array = FileUtils.readFileToByteArray(new File("Folder"."File name"));
        return new ResponseEntity<byte[]>(array,httpHeaders, HttpStatus.CREATED);
Copy the code

Support for Restful styles

What is Restful style

Restfu is a software style, strictly speaking, Restfu is a coding style. To put it simply, usually we design a back-end interface that can correspond to four operations, namely, add, delete, check and modify. This is why server engineers are often called CRUDS. A friend unfamiliar with the Restful style might say, aren’t there only two ways to request something? How does that correspond to the four operations? There are actually more than four HTTP requests, some say 14, but I only found eight in the Firefox developer documentation, and the browser only supports two, so we just overwrote the doGet and doPost methods of HttpServlet when programming with native servlets. Four of the eight types of requests can be identified:

  • GET
  • POST
  • PUT

Roughly speaking, in the Restful style, DELETE means to DELETE a resource, GET means to obtain a resource from the server, POST means to add a resource to the server, and PUT means to request the server to update a resource. Instead of adding a verb to an interface to identify what the interface is supposed to do, it’s easier to maintain and implement a single design responsibility, and subsequent developers can see from the interface what the request is doing, which is why Restful style prevails.

But when I looked through the Firefox developer documentation, I noticed that the browser supports all eight types of requests:

However, I read a lot of information on the Internet, which said that browsers only support GET and POST requests. On reflection, this may depend on the browser version. HTTP: / / HTTP: / / HTTP: / / HTTP: / / HTTP1.1

  • HEAD
  • PUT

Browser support is supported, but when a client makes a request, how to let the server know that you are using a PUT or DELETE request is common practice is to add hidden attributes to the form code, wrapping the POST request as a PUT request. By the way, the Developer documentation for Firefox is quite good, including an introduction to HTTP. If you want to learn the HTTP protocol, you can check it out if you can’t find authoritative references. There are links to references at the end of this article.

Support for Restful

  • @ResponseBody

In today’s era of front and back end separation, the jump page has been controlled by the front end, the way of front and back end communication is also through Ajax to achieve partial refresh, but SpringMVC still has the concept of jump view, so how to tell SpringMVC, I do not jump to the page, I just sent data to the front end page? That’s done by putting @responseBody on the request method. Something like this:

  • @RestController

If you feel like every method has an @responseBody comparison method, you can put this annotation on your class, plus

  • @GetMapping,@PostMapping,@PutMapping,@DeleteMapping

RequestMapping (@requestMapping) supports different request methods. Collectively, these five annotations are called requested annotations.

  • @PathVariable

After the server uses the request annotation, it can pass the parameter like {parameter name} station symbol. In this case, the @pathvariable annotation is needed to bind the station parameter in the URL to the parameter of the controller processing method.

The client request to address such as: http://localhost:8080/studySpringFrameWork_war_exploded/delete/1 server code:

@RequestMapping(value = "delete/{id}", method = RequestMethod.GET)
public String getInfo(@PathVariable(value = "id") String id) {
    System.out.println("id:" + id);
    return id;
Copy the code

{parameter value} and @pathVariable (value = “id”) must be consistent.

Unified exception handling

Introduction to the

Spring MVC handles exceptions in three ways: (1) using the Spring MVC provides simple exception handler SimpleMappingExceptionResolver (2) the Spring’s exception handling interface HandlerExceptionResolver custom own exception handler (3) to use@ExceptionHandler + @ControllerAdviceThe top-level exception handling is HandlerExceptionResolver, and the inheritance structure is as follows:In general, the first and third methods are commonly used.

The first way to deal with it

The first way is to specify which exceptions to handle and which pages to jump to in the configuration file, as follows:

   <bean id="simpleMappingExceptionResolver"  class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
        <! -- Define the default exception handling page, jump to error page when the exception type occurs -->
        <property name="defaultErrorView" value="error"/>
        <! -- Define the name of the variable used by the exception handling page to obtain the exception information. Default is exception-->
        <property name="exceptionAttribute" value="ex"/>
        <! To define exceptions that need to be handled in a special way, there are two methods: 1. Value tag method 2.
        <property name="exceptionMappings">
            <! -- value tag multiple exceptions separated by commas -->
<! -- <value>-->
<! -- java.lang.ArithmeticException=error,-->
<! -- java.lang.NullPointerException=exception-->
<! -- </value>-->
            <! -- props TAB, each prop TAB key represents an exception, and the prop TAB represents the specific page to jump to -->
                <prop key="java.lang.ArithmeticException">
Copy the code

The third way to deal with it

// This annotation handles all method exceptions
public class ExceptionHandlerControllerAdvice {
    // This annotation declares which exceptions to handle
    public  String error(Exception ex , Model model){
        // Add exception information to the request field
        // Jump to the error page
        return "error"; }}Copy the code

The interceptor

Introduction to the

Before the user’s request reaches the request method, it enters the interceptor, where we can do some general operations, such as authentication, determining the user’s login, and so on. Folding reminds me of AOP, which also allows method execution before method execution after method execution. What’s the difference between interceptors and AOP? In a sense interceptors can be counted as part of AOP, but interceptors cannot be counted as part of AOP. To DispacherServlet, the request is sent. DispacherServlet checks to see if the request is intercepted by an interceptor. If intercepted, pass the request to the interceptor, as shown in the figure below:AOP, on the other hand, does this through dynamic proxies, which generate subclasses of the classes that need enhanced methods at run time. Interceptors are part of the whole Spring MVC execution process and can only block urls. AOP is more nuanced. Interceptors are executed before AOP in order of execution.

How does it work?

Implement org. Springframework. Web. Servlet. HandlerInterceptor interface. Let’s take a quick look at the method:PreHandle is executed before the request is sent to the handler, postHandle is executed after the methods that handle the request are completed, and before the view is rendered. AfterCompletion is executed after the view is rendered. What do I mean by view here? The V view layer of Spring MVC, when the page is rendered, the page is formed and then you configure the interceptor in the configuration file or in the configuration class. First implement the HandlerInterceptor interface:

public class MyHandlerInterceptor implements HandlerInterceptor {
    /** * Returns true to pass the request to the real controller * False to pass the request to the next interceptor. If the next interceptor is not found, the request will not reach the real interceptor *@param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("Execute................ before method execution");
        return true;
    /** * This method will not be triggered because the ModelAndView held the data returned by the method and the view to jump to did not execute successfully@param request
     * @param response
     * @param handler
     * @param modelAndView
     * @throws Exception
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("Execute................ after method execution");

    /** * gets * after the page is rendered@param request
     * @param response
     * @param handler
     * @param ex
     * @throws Exception
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        // Prints exception information about the method
        System.out.println("Execute................ after the view is rendered and executed"); }}Copy the code

Configuration file:

<mvc:interceptors> <mvc:interceptor> <! --/*: only one path can be intercepted --> <! - / * * : You can intercept one or more paths --> < MVC :mapping path=" /**"/> < MVC :exclude-mapping path="login"/> <bean class="org.example.mvc.MyHandlerInterceptor"></bean> </mvc:interceptor> </mvc:interceptors>Copy the code

Supplement to introduce

Spring MVC M(Model), V(View), C(Controller), above we seem to focus on C, that is, to receive parameters, processing parameters. And we’re not going to go into detail here, because we don’t use that much anymore, because the server doesn’t have control over the page anymore, and the data that’s returned is mostly JSON data that the front end returns. It seems that Model has been mentioned above, which is a class that fetches data after jumping to the corresponding page. After the Controller fetches data, it puts the data into the Model, and then indicates which page to jump to, and then fetches the data stored in the Model on the corresponding page. Model is the class provided by Spring MVC. And then there’s a ModelAndView, which can hold both data and view, and when the return type is this, SpringMVC will ModelAndView to the view, and then we can fetch the data on the corresponding page. But these are not commonly used, so I don’t spend much time on them. This article focuses on the common use of Spring MVC in the era of back-end separation, in fact, it is intended to introduce the web.

        <url-pattern>/ *</url-pattern>
Copy the code

But I don’t know what happened, maybe the version of Spring MVC I was using was too new, and the garbled problem was solved. If some students find Chinese garble problem when coding, you can add the above configuration in web.xml.

Write in the last

This article focuses on the frequent use points of Spring MVC. Spring MVC enhances native servlets. In order to use the enhanced servlets provided by Spring MVC, We need Spring MVC’s DispatcherServlet to take over all requests. This is how Tomcar’s web.xml configuration initializes DispatcherServlet at startup. Since Spring MVC was just designed, Server can control page jump, so we are in a configuration file parser configuration view, namely InternalResourceViewResolver. Then we can feel the traversal provided by Spring MVC. The simplified way of taking parameters enables us to focus more on business logic. The unified exception handling prevents our page from directly exporting error information to the page. And friendly support for RESTful styles. I hope it will be helpful to you.

The resources

  • SpringMVC video tutorial yan qun
  • What’s the difference between cookies and sessions?
  • RESTful API design Guide
  • 14 request methods in THE HTTP protocol
  • Firefox Developer Documentation
  • This section describes the eight HTTP request modes
  • Rfc2068 – HTTP1.1 standard documentation