Spring MVC learning summary (9): interceptors and exception handling

1. Interceptor

1. Introduction to interceptors

The Interceptor of Spring MVC is similar to the Filter of Java Servlet. It is mainly used to intercept user requests and do corresponding processing. It is usually used for permission verification, logging of request information, and judging whether the user is logged in, etc. Functionally. Defining an interceptor in the Spring MVC framework requires the definition and configuration of the interceptor. There are two ways to define an interceptor: one is defined by implementing the HandlerInterceptor interface or the implementation class that inherits the HandlerInterceptor interface; the other is through Define by implementing the WebRequestInterceptor interface or inheriting the implementation class of the WebRequestInterceptor interface. This article demonstrates in the second way.

There are three methods in HandlerInterceptor, which are described as follows:

  • preHandle method: This method is executed before the controller's processing request method, and its return value indicates whether to interrupt subsequent operations, return true to continue downward execution, and false to interrupt subsequent operations.
  • postHandle method: This method is executed after the controller's request processing method is called and before the view is resolved. This method can be used to further modify the model and view in the request domain.
  • afterCompletion method: This method is executed after the controller's processing request method is executed, that is, it is executed after the view rendering is finished. This method can be used to clean up some resources and record log information.

The difference between interceptor and filter is as follows:

  Filter Interceptor
Different scope of use According to the Servlet specification, it can only be used in Web programs Can be used in Web programs, but also in Applicaiont and Swing programs
Different specifications A supplement to the Servlet specification, which can be used by any Web project Spring framework's own, only projects that use Spring MVC framework can be used
Different resources used Filter doesn't work

The interceptor is a component of Spring, managed by Spring, configured in the Spring file, and can use any resource and object in Spring, such as Service object, data source, transaction management, etc.

Different depth The filter only works before and after the servlet. Interceptors can go deep into before and after methods, before and after exceptions are thrown, and have greater flexibility.
Different intercepted resources After configuring /* in url-pattern, the filter will block all resources to be accessed The interceptor only intercepts access to the controller method, if the access is jsp, html, css, image, js, etc., it will not be intercepted

 

2. The execution process of a single interceptor

If only one interceptor is defined in the configuration file, the program will first execute the preHandle method in the interceptor class. If the method returns true, the program will continue to execute the method of processing the request in the controller, otherwise the execution will be interrupted. If the preHandle method returns true, and the method of processing the request in the controller is executed, the postHandle method will be executed before the view is returned, and the afterCompletion method will be executed after the view is returned.

(1) Configure web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
  <display-name>Archetype Created Web Application</display-name>
  <servlet>
    <servlet-name>dispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <!--  指定Spring MVC配置文件的位置    -->
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:springmvc.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>dispatcherServlet</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>
  <!--   字符编码过滤器  -->
  <filter>
    <filter-name>CharacterEncodingFilter</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <!--  encoding:指定一个具体的字符集  -->
    <init-param>
      <param-name>encoding</param-name>
      <param-value>UTF-8</param-value>
    </init-param>
    <!-- forceEncoding:处理 response中的字符编码  -->
    <init-param>
      <param-name>forceEncoding</param-name>
      <param-value>true</param-value>
    </init-param>

  </filter>
  <filter-mapping>
    <filter-name>CharacterEncodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>


</web-app>

(2) Create a controller class

@Controller
public class InterceptorController {
    @RequestMapping("/testInterceptor")
    public String testInterceptor(){
        System.out.println("我是testInterceptor方法");
        return "interceptorPage";
    }
}

(3) Create an interceptor class

public class MyInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
        System.out.println("我是preHandle方法---在控制器的处理请求方法调用之后,解析视图之前执行");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
        System.out.println("我是postHandle方法---在控制器的处理请求方法调用之后,解析视图之前执行");
    }

    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
        System.out.println("我是afterCompletion方法---在控制器的处理请求方法执行完成后执行,即视图渲染结束之后执行");
    }
}

(4) Configure the interceptor class in springmvc.xml 

    <!-- 配置拦截器 -->
    <mvc:interceptors>
        <!-- 配置一个全局拦截器,拦截所有请求 -->
        <mvc:interceptor>
            <!-- 配置拦截器作用的路径 -->
            <mvc:mapping path="/**" />
            <!-- 配置不需要拦截作用的路径 -->
<!--            <mvc:exclude-mapping path="" />-->
            <!-- 定义<mvc:interceptor>元素中,表示匹配指定路径的请求才进行拦截 -->
            <bean class="com.yht.example1.interceptor.MyInterceptor" />
        </mvc:interceptor>
    </mvc:interceptors>

In the above sample code, the <mvc:interceptors> element is used to configure a set of interceptors, and its child element <bean> defines a global interceptor, that is, intercepts all requests.

The <mvc:interceptor> element defines the interceptor of the specified path, and its child element <mvc:mapping> is used to configure the path of the interceptor, which is defined in its attribute path.

As in the above example code, the attribute value of path "/**" means to block all paths, and "/**" means to block all paths. If the request path contains content that does not need to be intercepted, it can be configured through the <mvc: exclude-mapping> sub-element.

It should be noted that the child elements of the <mvc:interceptor> element must be configured in the order of <mvc:mapping.../>, <mvc:exclude-mapping.../>, <bean.../>. 

(5) Create interceptorPage.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
视图
<%System.out.println("视图渲染结束。"); %>
</body>
</html>

(6) Start the Tomcat server, and then test the interceptor through the address " http://localhost:8080/SpringMVCStudy02_war/testInterceptor ". The output is as follows:

3. The execution process of multiple interceptors

In Web applications, multiple interceptors are usually required to work at the same time. At this time, their preHandle methods will be executed in the order of configuration of the interceptors in the configuration file, and their postHandle methods and afterCompletion methods will be executed in the reverse order of the configuration order. As shown below:

(1) Create the interceptor class TestInterceptor.

public class TestInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
        System.out.println("我是preHandle方法---TestInterceptor类");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
        System.out.println("我是postHandle方法---TestInterceptor类");
    }

    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
        System.out.println("我是afterCompletion方法---TestInterceptor类");
    }
}

(2) Configure TestInterceptor in springmvc.xml.

<!-- 配置拦截器 -->
    <mvc:interceptors>
        <mvc:interceptor>
            <!-- 配置拦截器作用的路径 -->
            <mvc:mapping path="/**" />
            <bean class="com.yht.example1.interceptor.MyInterceptor" />
        </mvc:interceptor>
        <mvc:interceptor>
            <!-- 配置拦截器作用的路径 -->
            <mvc:mapping path="/**" />
            <bean class="com.yht.example1.interceptor.TestInterceptor" />
        </mvc:interceptor>
    </mvc:interceptors>

(3) Start the Tomcat server, and then test the interceptor through the address " http://localhost:8080/SpringMVCStudy02_war/testInterceptor ". The output is as follows:

note:

If false is returned in preHandle, it means not letting go, then we can use request.getRequestDispatcher("/WEB-INF/pages/page name").forward(request,response); to jump to a page. 

Two, exception handling

In the development of Spring MVC applications, no matter it is the operation of the underlying database, or the operation of the business layer or the control layer, it will inevitably encounter various predictable and unpredictable exceptions that need to be dealt with. The HandlerExceptionResolver interface is used to resolve exceptions generated during request processing.

(1) The custom exception class SystemException.

public class SystemException extends Exception{
    private String message;

    public SystemException(String message) {
        this.message = message;
    }

    @Override
    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}

(2) Create error.jsp under pages.

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<h4>这是错误页面</h4>
${msg}
</body>
</html>

(3) Create a SystemExceptionHandler that implements the HandlerExceptionResolver interface

public class SystemExceptionHandler implements HandlerExceptionResolver {

    @Override
    public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
        SystemException systemException = null;
        if(e instanceof  SystemException){
            systemException = (SystemException) e;
        }else{
            e = new SystemException("系统异常");
        }
        ModelAndView mv = new ModelAndView();
        mv.setViewName("error");
        mv.addObject("msg", e.getMessage());
        return mv;
    }
}

(4) Create a controller

@Controller
public class ExceptionController {
    @RequestMapping("/testException")
    public String testException() throws Exception{
        System.out.println("我是testException方法");
        int num = Integer.parseInt("a123");
        return "success";
    }
}

(5) Configure SystemExceptionHandler in springmvc.xml

    <bean class="com.yht.example1.handler.SystemExceptionHandler"></bean>

(6) Start the Tomcat server, and then test the interceptor through the address " http://localhost:8080/SpringMVCStudy02_war/testException ". The interface results are as follows:

Guess you like

Origin blog.csdn.net/weixin_47382783/article/details/113615558