06_ 03_ Spring MVC task 2: advanced spring MVC (ajax asynchronous interaction, RESTful programming style, file upload, exception handling, interceptor)

Posted by ipwnzphp on Sun, 27 Feb 2022 05:15:03 +0100

Task 2: Spring MVC advanced

Main contents of course tasks:

  • ajax asynchronous interaction
  • RESTful
  • File upload
  • exception handling
  • Interceptor

An ajax asynchronous interaction

By default, spring MVC uses MappingJackson2HttpMessageConverter to convert json data, which needs to be added to jackson's package; Use < MVC: annotation driven / >

Project tip: Spring MVC in the previous phase_ Continue writing in the QuickStart project

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

1.1 @RequestBody

This annotation is used for the formal parameter declaration of the Controller's method. When the content type is submitted using ajax and specified as json, it is converted to the corresponding POJO object through the HttpMessageConverter interface.
Create Ajax jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<script src="${pageContext.request.contextPath}/js/jquery-3.5.1.js"></script>
    <%--ajax Asynchronous interaction--%>
    <button id="btn1">ajax Asynchronous commit</button>

    <script>
        $("#btn1").click(function () {

            let url = '${pageContext.request.contextPath}/user/ajaxRequest';
            let data = '[{"id":1,"username":"Zhang San"},{"id":2,"username":"Li Si"}]';

            $.ajax({
                type: 'POST',
                url: url,
                data : data,
                contentType : 'application/json;charset=utf-8',
                success: function (resp) {
                    alert(JSON.stringify(resp));
                }
            })
        })
    </script>
</body>
</html>
@RequestMapping(value = "/ajaxRequest") 
public void ajaxRequest(@RequestBody List<User>list) {
 System.out.println(list); 
}

1.2 @ResponseBody

This annotation is used to convert the object returned by the Controller method into data in the specified format through the HttpMessageConverter interface, such as json,xml, etc., and respond to the client through Response.

	/*
	@RequestMapping 
	produces = "application/json;charset=utf-8" 
	The mime type and code of the data returned by the response. The default is json 
	*/
	@RequestMapping(value = "/ajaxRequest") 
	@ResponseBody 
	public List<User> ajaxRequest(@RequestBody List<User> list) {
	 System.out.println(list); 
	 return list; 
	}

II. RESTful

2.1 what is RESTful

Restful is a software architecture style and design style, not a standard, but provides a set of design principles and constraints. It is mainly used for the interactive software between client and server. The software designed based on this style can be more concise, more hierarchical, and easier to implement the cache mechanism.
Restful style requests use "url + request method" to indicate the purpose of a request. The four verbs in the HTTP protocol indicating the operation method are as follows:

  • GET: Read
  • POST: Create
  • PUT: Update
  • Delete: delete
client requestOriginal style URL addressRESTful style URL address
Query all/user/findAllGET /user
Query by ID/user/findById?id=1GET /user/{1}
newly added/user/savePOST /user
modify/user/updatePUT /user
delete/user/delete?id=1DELETE /user/{1}

If you want to test, modify and delete operations, Download postman to simulate

2.2 code implementation

@PathVariable
Used to receive the value of the placeholder in the RESTful style request address

@RestController
RESTful style is mostly used for front-end and back-end separated project development. The front end interacts asynchronously with the server through ajax. Our processor usually returns json data, so @ RestController is used to replace the two annotations @ Controller and @ ResponseBody.

@RestController //Combined PK: combined @ Controller + @ResponseBody
@RequestMapping("/restful")
public class RestfulController {

    /*
        Query by id
        localhost:8080/Project name / restful/user/2 + get request method 404 findbyid: 2
     */
     
    @GetMapping("/user/{id}") // @RequestMapping(value = "/user/{id}",method = RequestMethod.GET)
    public String findById(@PathVariable Integer id){
        // Call the service method to query the record with id 2
        // Question: how can I get the value of placeholder in url in restful programming style in findById method
        return "findById: "+ id ;
    }
    
    /*
        New method
     */
    @PostMapping("/user") // @RequestMapping(value = "/user",method = RequestMethod.POST)
    public String post(){
        // newly added
        return "post";
    }

    /*
        Update method
     */
    @PutMapping("/user")
    public String put(){
        // update operation
        return "put";
    }

    /*
        Delete method
     */
    @DeleteMapping("/user/{id}")
    public String delete(@PathVariable Integer id){

        return "delete" + id;
    }

}

III. file upload

3.1 three elements of file upload

  • Form item type = "file"
  • Submission method of form method = "POST"
  • The enctype attribute of a form is a multi part form, enctype = "multipart / form data"“

3.2 file upload principle

  • When the form is modified to a multi part form, request Getparameter() will fail.
  • When the enctype value of the form is application/x-www-form-urlencoded,
    • The format of the body content of the form is: name = value & name = value
  • When the enctype value of the form is mutilpart / form data, the content of the request body becomes multi part:

3.3 single file upload

Step analysis

  1. Import fileupload and io coordinates
  2. Profile upload parser
  3. Write file upload code

1) Import fileupload and io coordinates

		<!--Import fileupload and io coordinate-->
  		<dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.3.3</version>
        </dependency>
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.6</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>compile</scope>
        </dependency>

2) Profile upload parser
spring-mvc.xml

    <!--Profile upload parser-->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <!-- Set the maximum value of file upload to 5 MB,5*1024*1024 -->
        <property name="maxUploadSize"  value="5242880"></property>
        <!-- Set the maximum value to be written into memory during file upload. If it is less than this parameter, no temporary file will be generated. The default value is 10240 -->
        <property name="maxInMemorySize" value="40960"></property>
    </bean>

3) Write file upload code
Create fileUpload jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <%--Write a form that meets the three elements of file upload
        1.The form must be submitted by post
        2.Tabular enctype Property must be modified to multipart/form-data
        3.There must be a file upload item in the form
    --%>
    <form action="${pageContext.request.contextPath}/fileupload" method="post" enctype="multipart/form-data">

        name:<input type="text" name="username"> <br>
        File:<input type="file" name="filePic"> <br>
            <input type="submit" value="Single file upload">
    </form>
</body>
</html>

controller.FileUploadController.java

@Controller
public class FileUploadController {

    /*
        Single file upload
     */
    @RequestMapping("/fileupload")
    public String fileUpload(String username, MultipartFile filePic) throws IOException {

        //Obtain the submission parameters of the form and complete the file upload
        System.out.println(username);

        // Get the original file upload name a.txt ABC
        String originalFilename = filePic.getOriginalFilename();
        filePic.transferTo(new File("D:/upload/"+originalFilename));

        return "success";
    }
}

3.4 multi file upload

fileupload.jsp

 <%--Realize multi file upload--%>
    <form action="${pageContext.request.contextPath}/filesupload" method="post" enctype="multipart/form-data">

        name:<input type="text" name="username"> <br>
        Document 1:<input type="file" name="filePic"> <br>
        Document 2:<input type="file" name="filePic"> <br>
        <input type="submit" value="Multi file upload">
    </form>

controller.FileUploadController.java

 /*
      Multi file upload
   */
    @RequestMapping("/filesupload")
    public String filesUpload(String username, MultipartFile[] filePic) throws IOException {

        //Obtain the submission parameters of the form and complete the file upload
        System.out.println(username);

        // Get the original file upload name a.txt ABC
        for (MultipartFile multipartFile : filePic) {
            String originalFilename = multipartFile.getOriginalFilename();
            multipartFile.transferTo(new File("D:/upload/"+originalFilename));
        }
        return "success";
    }

IV. exception handling

4.1 ideas for exception handling

In Java, there are generally two ways to handle exceptions:

  • One is the current method capture processing (try catch), which will cause the coupling of business code and exception handling code.
  • The other is not to deal with it, but to throw it to the caller. The caller then throws it to its caller, that is, to throw it up all the time.
    Based on this method, the exception handling mechanism of spring MVC is derived.

The dao, service and controller of the system are thrown upward through the throws Exception. Finally, the spring MVC front-end controller is handed over to the exception handler for exception handling, as shown in the following figure:

4.2 custom exception handler

Step analysis

  1. Create an exception handler class to implement HandlerExceptionResolver
  2. Configure exception handler
  3. Write exception page
  4. Test abnormal jump

1) Create an exception handler class to implement HandlerExceptionResolver
exception/GlobalExceptionResolver.java

public class GlobalExceptionResolver implements HandlerExceptionResolver {
    /*
        Exception e:Exception object actually thrown
     */

    @Override
    public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object handler, Exception e) {
        //After the specific exception handling generates an exception, jump to a final exception page
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.addObject("error",e.getMessage());
        modelAndView.setViewName("error");

        return modelAndView;
    }
}

2) Configure exception handler
Method 1:

Method of annotation:
@Component 
public class GlobalExecptionResovler implements HandlerExceptionResolver {}

Method 2:

XML Configuration method:
<bean id="globalExecptionResovler" class="com.lagou.exception.GlobalExecptionResovler">
</bean>

3) Write exception page
WEB-INF/pages/error.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>error</title>
</head>
<body>
<h3>This is a final exception display page</h3> 
<p>${error}</p>
</body>
</html>

4) Test abnormal jump
com.lagou.controller.ExceptionController

@Controller
public class ExceptionController {

    @RequestMapping("/testException")
    public String testException(){
        int i=1/0;
        return "success";
    }
}

4.3 exception handling mechanism of Web

newly build:
404.jsp and 500 jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    The resource you requested has been deleted
</body>
</html>

web.xml

 <!--Handling 404 exceptions-->
    <error-page>
        <error-code>404</error-code>
        <location>/404.jsp</location>
    </error-page>

    <!--Handling 500 exceptions-->
    <error-page>
        <error-code>500</error-code>
        <location>/500.jsp</location>
    </error-page>

Five interceptors

5.1 function of interceptor

The interceptor of Spring MVC is similar to the Filter in Servlet development, which is used to preprocess and post process the processor.
The interceptors are connected into a chain in a certain order, which is called interceptor chain. When accessing the intercepted method or field, the interceptors in the interceptor chain will be called in the order they were previously defined. Interceptor is also the concrete implementation of AOP idea.

5.2 difference between interceptor and filter

The difference between interceptor and filter is shown in the figure:

5.3 quick start

Step analysis

  1. Create an interceptor class to implement the HandlerInterceptor interface
  2. Configuring Interceptors
  3. Test the interception effect of the interceptor

1) Create an interceptor class to implement the HandlerInterceptor interface
com.lagou.interceptor.MyInterceptor1

public class MyInterceptor1 implements HandlerInterceptor {


    /*
        preHandle: Intercept before the target method is executed return false: do not release
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("preHandle....1");

        return true;
    }


    /*
        postHandle: The method executed after the target method is executed and before the view object returns
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("postHandle....1");
    }

    /*
        afterCompletion: The method to be executed after all processes are executed
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

        System.out.println("afterCompletion....1");

    }
}

2) Configure interceptor
spring-mvc.xml

 <!--Configuring Interceptors -->
    <mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/**"/><!--For all controller All methods in the class are intercepted-->
            <bean class="com.lagou.interceptor.MyInterceptor1"></bean>
        </mvc:interceptor>
    </mvc:interceptors>

3) Test the interception effect of the interceptor
Write the controller, send the request to the controller and jump to the page
com.lagou.controller.TargetController

@Controller
public class TargetController {

    @RequestMapping("/target")
    public String targetMethod(){
        System.out.println("The target method is executed...");
        return "success";
    }
}

Writing jsp pages

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <h3>success... </h3>

    <% System.out.println("View executed....");%>
</body>
</html>

Output printing effect:

preHandle
 The target method is executed...
postHandle...
View executed....
afterCompletion...

5.4 interceptor chain

In development, interceptors can be used alone or multiple interceptors can be used at the same time to form an interceptor chain. The development steps are the same as that of a single interceptor, except that multiple interceptors are registered during registration. Note that the registration order here represents the execution order of the interceptor.
As above, write another MyHandlerInterceptor2 operation to test the execution sequence:

<!--Configuring Interceptors -->
    <mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/**"/> <!--For all controller All methods in the class are intercepted-->
            <bean class="com.lagou.interceptor.MyInterceptor1"></bean>
        </mvc:interceptor>
        <mvc:interceptor>
            <mvc:mapping path="/**"/> <!--For all controller All methods in the class are intercepted-->
            <bean class="com.lagou.interceptor.MyInterceptor2"></bean>
        </mvc:interceptor>
    </mvc:interceptors>

Execution effect:

preHandle...1
preHandle...2
 The target method is executed...
postHandle....2
postHandle...1
 View executed....
afterCompletion....2
afterCompletion...1

##Bold style # 5.5 knowledge summary
The method in the interceptor is described as follows:

Topics: Ajax RESTful