2.4.9 Advanced SpringMVC, ajax asynchronous interaction (RequestBody, ResponseBody), RESTful programming style, file upload method, exception handling mechanism, use of interceptor

table of Contents

springmvc advanced

​One ajax asynchronous interaction

1.1 @RequestBody

1.2 @ResponseBody

Two RESTful

2.1 What is RESTful

Three file upload

3.1 Three elements of file upload

3.2 Principle of File Upload

3.3 Single file upload

3.4 Multiple file upload

Four exception handling

4.1 The idea of ​​exception handling

4.2 custom exception handler

4.3 Web's exception handling mechanism

Five interceptors

5.1 The role of interceptor (interceptor)

5.2 The difference between interceptor and filter

5.3 Quick start

5.4 Interceptor chain

5.5 Knowledge summary


 

 

springmvc advanced

main content:


An ajax asynchronous interaction

By default, Springmvc uses MappingJackson2HttpMessageConverter to convert json data, which needs to be added to the jackson package; at the same time use <mvc:annotation-driven />

        <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 method. When submitted using ajax and specifying the contentType as json, it is converted to the corresponding POJO object through the HttpMessageConverter interface.


<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<%--引入js资源, 注意下面的script标签不要自闭合, 否则后面的显示不出来--%>
<script src="${pageContext.request.contextPath}/js/jquery-3.5.1.js"></script>
    <%--ajax异步交互--%>
    <button id="btn1">ajax异步提交</button>

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

            let url = '${pageContext.request.contextPath}/user/ajaxRequest';
            let data = '[{"id":1,"username":"张三"},{"id":2,"username":"李四"}]';

            $.ajax({
                type: 'POST',
                url: url,
                data : data,
                contentType : 'application/json;charset=utf-8',
                success: function (resp) {
                    alert(JSON.stringify(resp));
                }
            })
        })
    </script>
</body>
</html>
    /*
        ajax异步交互  [{"id":1,"username":"张三"},{"id":2,"username":"李四"}]
     */
        @RequestMapping("/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 a specified format through the HttpMessageConverter interface, such as json, xml, etc., and respond to the client through Response.

    /*
        ajax异步交互  [{"id":1,"username":"张三"},{"id":2,"username":"李四"}]
     */
        @RequestMapping("/ajaxRequest")
        @ResponseBody
        public List<User> ajaxRequest(@RequestBody List<User> list){
            System.out.println(list);
            return list;
        }

 


Two RESTful

2.1 What is RESTful

Restful is a software architecture style and design style, not a standard. It only provides a set of design principles and constraints. Mainly used for client-server interaction software, software designed based on this style can be more concise, more layered, and easier to implement caching mechanisms.
Restful style requests use "url+request mode" to indicate the purpose of a request. The four verbs in the HTTP protocol that indicate the operation mode are as follows:

  • GET: Read
  • POST: Create
  • PUT:更新(Update)
  • DELETE: Delete

2.2 Code implementation
@PathVariable

Used to receive the value of the placeholder in the RESTful request address

package com.lagou.controller;

@Controller
@RequestMapping("/restful")
public class RestfulController {

    /*
        根据id进行查询
        localhost:8080/项目名/restful/user/2 + get请求方式  404  findById:2
     */
    // 下面的method表示只能用get方式请求,  {...}是个占位符, 里面写参数名称
    @RequestMapping(value = "/user/{id}",method = RequestMethod.GET)
    public String findById(@PathVariable Integer id){
        // 调用service方法完成对id为2的这条记录的查询
        // 问题:findById方法中怎么才能获取restful编程风格中url里面占位符的值
        // 使用 PathVariable注解 获取占位符的值, 如上 ↑
        return "findById: "+ id ;
    }
}

 

@RestController

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

package com.lagou.controller;

@RestController //这是个组合主键:组合@Controller + @ResponseBody
@RequestMapping("/restful")
public class RestfulController {

    /*
        根据id进行查询
        localhost:8080/项目名/restful/user/2 + get请求方式  404  findById:2
     */
    // 下面的GetMapping表示只能用get方式请求,  {...}是个占位符, 里面写参数名称
    @GetMapping("/user/{id}") // @RequestMapping(value = "/user/{id}",method = RequestMethod.GET)
    //@ResponseBody // 该注解会把return后面的直接以字符串形式返回给浏览器, 而不走视图解析器
    public String findById(@PathVariable Integer id){
        // 调用service方法完成对id为2的这条记录的查询
        // 问题:findById方法中怎么才能获取restful编程风格中url里面占位符的值
        // 使用 PathVariable注解 获取占位符的值, 如上 ↑
        return "findById: "+ id ;
    }

    /*
        新增方法
     */
    // 下面的PostMapping就表示后面的一长串
    @PostMapping("/user") // @RequestMapping(value = "/user",method = RequestMethod.POST)
    public String post(){
        // 新增
        return "post";
    }

    /*
        更新方法
     */
    @PutMapping("/user")
    public String put(){
        // 更新操作
        return "put";
    }

    /*
        删除方法
     */
    @DeleteMapping("/user/{id}")
    public String delete(@PathVariable Integer id){

        return "delete" + id;
    }
}
}

 

Three file upload

3.1 Three elements of file upload

  • Form item type="file"
  • The form submission method method="POST", can there be a request body
  • The enctype attribute of the form is multipart form enctype="multipart/form-data"

 

3.2 Principle of File Upload

When the form form is modified to a multi-part form, request.getParameter() will become invalid.

When the enctype 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 form is mutilpart/form-data , the request body content becomes a multi-part form:

3.3 Single file upload

Step analysis


1) pom.xml import fileupload and io coordinates

        <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>

2) Spring-mvc configuration file upload parser

    <!--配置文件上传解析器-->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <!-- 设定文件上传的最大值为5MB,5*1024*1024 -->
        <property name="maxUploadSize"  value="5242880"></property>
        <!-- 设定文件上传时写入内存的最大值,如果小于这个参数不会生成临时文件,默认为10240 -->
        <property name="maxInMemorySize" value="40960"></property>
    </bean>

3) Write file upload code

<%--
  Created by IntelliJ IDEA.
  User: Szc.0713
  Date: 2020/6/24
  Time: 16:35
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>

    <%--编写一个满足文件上传三要素的表单
        1.表单的提交方式必须是post
        2.表单的enctype属性必须要修改成multipart/form-data
        3.表单中必须要有文件上传项
    --%>
    <form action="${pageContext.request.contextPath}/fileupload" method="post" enctype="multipart/form-data">

        名称:<input type="text" name="username"> <br>
        文件:<input type="file" name="filePic"> <br>
            <input type="submit" value="单文件上传">
    </form>

</body>
</html>
package com.lagou.controller;

@Controller
public class FileUploadController {


    /*
        单文件上传
     */
    // 上传文件类型为下面的multipartfile
    @RequestMapping("/fileupload")
    public String fileUpload(String username, MultipartFile filePic) throws IOException {

        //获取表单的提交参数,完成文件上传
        System.out.println(username);

        // 获取原始的文件上传名 a.txt  abc
        String originalFilename = filePic.getOriginalFilename();
        filePic.transferTo(new File("D:/upload/"+originalFilename));

        return "success";
    }
}

 

3.4 Multiple file upload

<%--
  Created by IntelliJ IDEA.
  User: Szc.0713
  Date: 2020/6/24
  Time: 16:35
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>


    <%--编写一个满足文件上传三要素的表单
        1.表单的提交方式必须是post
        2.表单的enctype属性必须要修改成multipart/form-data
        3.表单中必须要有文件上传项
    --%>
  
    <%--实现多文件上传--%>
    <form action="${pageContext.request.contextPath}/filesupload" method="post" enctype="multipart/form-data">

        名称:<input type="text" name="username"> <br>
        文件1:<input type="file" name="filePic"> <br>
        文件2:<input type="file" name="filePic"> <br>
        <input type="submit" value="多文件上传">
    </form>
</body>
</html>
    /*
      多文件上传
   */
    @RequestMapping("/filesupload")
    public String filesUpload(String username, MultipartFile[] filePic) throws IOException {

        //获取表单的提交参数,完成文件上传
        System.out.println(username);

        // 获取原始的文件上传名 a.txt  abc
        for (MultipartFile multipartFile : filePic) {
            String originalFilename = multipartFile.getOriginalFilename();
            multipartFile.transferTo(new File("D:/upload/"+originalFilename));

        }
        return "success";
    }

 

Four exception handling

4.1 The idea of ​​exception handling

In Java, there are generally two ways to handle exceptions:
one is the current method capture processing (try-catch), this processing method will cause the coupling of business code and exception handling code.
The other is not to process it by itself, but to throw it to the caller for processing (throws), and the caller to throw it to its caller, that is, to throw up.

On the basis of this method, the exception handling mechanism of SpringMVC is derived.

The dao, service, and controller of the system are all thrown upwards through throws Exception, and finally the springmvc front-end controller is handed over to the exception handler for exception handling, as shown below:

 

4.2 custom exception handler

Step analysis


1) Create an exception handler class to implement HandlerExceptionResolver

package com.lagou.exception;

import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

// 全局异常处理类, 实现异常处理器接口
public class GlobalExceptionResolver implements HandlerExceptionResolver {

    /*
        Exception e:实际抛出的异常对象
     */

    @Override
    public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object handler, Exception e) {
        // 进行具体的异常处理 产生异常后,跳转到一个最终的异常页面
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.addObject("error",e.getMessage());
        modelAndView.setViewName("error");

        return modelAndView;
    }
}

2) Configure exception handler

    <!--配置自定义的异常处理器-->
    <bean id="globalExceptionResolver" class="com.lagou.exception.GlobalExceptionResolver"></bean>

3) Write an exception page

<%--
  Created by IntelliJ IDEA.
  User: Szc.0713
  Date: 2020/6/21
  Time: 12:26
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <h3>success... </h3>

    <% System.out.println("视图执行了....");%>
</body>
</html>

4) Test abnormal jump

package com.lagou.controller;

@Controller
public class ExceptionController {
    
    @RequestMapping("/testException")
    public String testException(){

        int i = 1/0;

        return "success";

    }
}

 

4.3 Web's exception handling mechanism

    <!--处理404异常
    产生异常, 跳转到location-->
    <error-page>
        <error-code>404</error-code>
        <location>/404.jsp</location>
    </error-page>

    <!--处理500异常-->
    <error-page>
        <error-code>500</error-code>
        <location>/500.jsp</location>
    </error-page>

 

Five interceptors

5.1 The role of interceptor (interceptor)

The interceptor of Spring MVC is similar to the filter in Servlet development, which is used to pre-process and post-process the processor.
The interceptors are connected in a certain order into a chain, which is called the Interceptor Chain (InterceptorChain). When accessing the intercepted method or field, the interceptors in the interceptor chain will be called in the order defined before. The interceptor is also a concrete realization of the AOP idea.

 

5.2 The 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

package com.lagou.interceptor;

public class MyInterceptor1 implements HandlerInterceptor {


    /*
        preHandle: 在目标方法执行之前 进行拦截   return false:不放行
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("preHandle....");

        return true;
    }


    /*
        postHandle: 在目标方法执行之后,视图对象返回之前,执行的方法
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("postHandle....");
    }

    /*
        afterCompletion:在流程都执行完成后,执行的方法
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

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


    }
}

2) Configure the interceptor

    <!--配置拦截器
        可以配置多个-->
    <mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/**"/> <!--对所有controller类里面的所有方法都进行拦截-->
            <bean class="com.lagou.interceptor.MyInterceptor1"></bean>  <!--采用这个拦截器-->
        </mvc:interceptor>

    </mvc:interceptors>

3) Test the interception effect of the interceptor

Write Controller, send request to controller, jump page

package com.lagou.controller;

@Controller
public class TargetController {

    @RequestMapping("/target")
    public String targetMethod(){
        System.out.println("目标方法执行了....");
        return "success";
    }
}

Write jsp page

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

    <% System.out.println("视图执行了....");%>
</body>
</html>

 

5.4 Interceptor chain

Interceptors can be used alone in development, or multiple interceptors can be used at the same time to form an interceptor chain. The development steps are the same as a single interceptor, except that multiple registrations are registered when registering. Note that the order of registration here represents the order of execution of the interceptor.

Same as above, write a MyHandlerInterceptor2 operation to test the execution order:

    <!--配置拦截器
        可以配置多个, 配置顺序代表执行顺序-->
    <mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/**"/> <!--对所有controller类里面的所有方法都进行拦截-->
            <bean class="com.lagou.interceptor.MyInterceptor1"></bean>  <!--采用这个拦截器-->
        </mvc:interceptor>
        <mvc:interceptor>
            <mvc:mapping path="/**"/> <!--对所有controller类里面的所有方法都进行拦截-->
            <bean class="com.lagou.interceptor.MyInterceptor2"></bean>
        </mvc:interceptor>
    </mvc:interceptors>
package com.lagou.interceptor;

public class MyInterceptor2 implements HandlerInterceptor {
    
    /*
        preHandle: 在目标方法执行之前 进行拦截   return false:不放行
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("preHandle2....");

        return true;
    }
    
    /*
        postHandle: 在目标方法执行之后,视图对象返回之前,执行的方法
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("postHandle2....");
    }

    /*
        afterCompletion:在流程都执行完成后,执行的方法
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

        System.out.println("afterCompletion2....");
    }
}

 

 

5.5 Knowledge summary

The method in the interceptor is described as follows:

 

Guess you like

Origin blog.csdn.net/chengh1993/article/details/110789139