SpringMVC拦截器

拦截器

1. 什么是拦截器

SpringMVC的处理器拦截器类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理

2. maven依赖

<dependencies>
    
    <dependency>
      <groupId>org.springframeworkgroupId>
      <artifactId>spring-coreartifactId>
      <version>4.3.18.RELEASEversion>
    dependency>
    
    <dependency>
      <groupId>org.springframeworkgroupId>
      <artifactId>spring-beansartifactId>
      <version>4.3.18.RELEASEversion>
    dependency>
    
    <dependency>
      <groupId>org.springframeworkgroupId>
      <artifactId>spring-contextartifactId>
      <version>4.3.18.RELEASEversion>
    dependency>
    
    <dependency>
      <groupId>org.springframeworkgroupId>
      <artifactId>spring-expressionartifactId>
      <version>4.3.18.RELEASEversion>
    dependency>
    
    <dependency>
      <groupId>org.springframeworkgroupId>
      <artifactId>spring-aopartifactId>
      <version>4.3.18.RELEASEversion>
    dependency>
    
    <dependency>
      <groupId>org.springframeworkgroupId>
      <artifactId>spring-aspectsartifactId>
      <version>4.3.18.RELEASEversion>
    dependency>
    
    <dependency>
      <groupId>org.springframeworkgroupId>
      <artifactId>spring-webartifactId>
      <version>4.3.18.RELEASEversion>
    dependency>
    
    <dependency>
      <groupId>org.springframeworkgroupId>
      <artifactId>spring-webmvcartifactId>
      <version>4.3.18.RELEASEversion>
    dependency>

    
    
    <dependency>
      <groupId>javax.servletgroupId>
      <artifactId>javax.servlet-apiartifactId>
      <version>3.1.0version>
      <scope>providedscope>
    dependency>
    
    <dependency>
      <groupId>javax.servlet.jspgroupId>
      <artifactId>jsp-apiartifactId>
      <version>2.1version>
      <scope>providedscope>
    dependency>
    
    <dependency>
      <groupId>javax.servletgroupId>
      <artifactId>jstlartifactId>
      <version>1.2version>
    dependency>

    
    <dependency>
      <groupId>com.fasterxml.jackson.coregroupId>
      <artifactId>jackson-coreartifactId>
      <version>2.9.5version>
    dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.coregroupId>
      <artifactId>jackson-databindartifactId>
      <version>2.9.5version>
    dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.coregroupId>
      <artifactId>jackson-annotationsartifactId>
      <version>2.9.5version>
    dependency>
dependencies>

3. SpringMVC配置

web.xml


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

    
    <filter>
        <filter-name>CharacterEncodingFilterfilter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilterfilter-class>
        <init-param>
            <param-name>encodingparam-name>
            <param-value>UTF-8param-value>
        init-param>
    filter>
    <filter-mapping>
        <filter-name>CharacterEncodingFilterfilter-name>
        <url-pattern>/*url-pattern>
    filter-mapping>

    
    <filter>
        <filter-name>HiddenHttpMethodFilterfilter-name>
        <filter-class>org.springframework.web.filter.HiddenHttpMethodFilterfilter-class>
    filter>
    <filter-mapping>
        <filter-name>HiddenHttpMethodFilterfilter-name>
        <url-pattern>/*url-pattern>
    filter-mapping>

    
    <filter>
        <filter-name>HttpPutFormContentFilterfilter-name>
        <filter-class>org.springframework.web.filter.HttpPutFormContentFilterfilter-class>
    filter>
    <filter-mapping>
        <filter-name>HttpPutFormContentFilterfilter-name>
        <url-pattern>/*url-pattern>
    filter-mapping>

    
    <servlet>
        <servlet-name>springmvcservlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
        <init-param>
            <param-name>contextConfigLocationparam-name>
            <param-value>classpath:springmvc.xmlparam-value>
        init-param>
        <load-on-startup>1load-on-startup>
    servlet>
    <servlet-mapping>
        <servlet-name>springmvcservlet-name>
        <url-pattern>/url-pattern>
    servlet-mapping>

    <welcome-file-list>
        <welcome-file>/views/index.jspwelcome-file>
    welcome-file-list>
web-app>

springmvc.xml


<beans
        xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:p="http://www.springframework.org/schema/p"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:aop="http://www.springframework.org/schema/aop"
        xmlns:mvc="http://www.springframework.org/schema/mvc"
        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
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop.xsd
    http://www.springframework.org/schema/mvc
    http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    
    
    <context:component-scan base-package="com.newcapec"/>

    
    <mvc:annotation-driven/>

    
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        
        <property name="prefix" value="/views/"/>
        <property name="suffix" value=".jsp"/>
    bean>

    
    <mvc:default-servlet-handler/>
beans>

4. Controller

DemoController.java

@Controller
@RequestMapping("/demo")
public class DemoController {
     

    @RequestMapping("/find")
    public String find(){
     
        System.out.println("DemoController的find方法...");
        return "success";
    }

    @RequestMapping("/add")
    public String add(){
     
        System.out.println("DemoController的add方法...");
        return "success";
    }

    @RequestMapping("/edit")
    public String edit(){
     
        System.out.println("DemoController的edit方法...");
        return "success";
    }

    @RequestMapping("/remove")
    public String remove(){
     
        System.out.println("DemoController的remove方法...");
        return "success";
    }
}

EmpController.java

@Controller
@RequestMapping("/emp")
public class EmpController {
     

    @RequestMapping("/find")
    public String find(){
     
        System.out.println("EmpController的find方法...");
        return "success";
    }

    @RequestMapping("/add")
    public String add(){
     
        System.out.println("EmpController的add方法...");
        return "success";
    }

    @RequestMapping("/edit")
    public String edit(){
     
        System.out.println("EmpController的edit方法...");
        return "success";
    }

    @RequestMapping("/remove")
    public String remove(){
     
        System.out.println("EmpController的remove方法...");
        return "success";
    }
}

5. 拦截器定义

实现HandlerInterceptor接口,并且实现其中三个抽象方法

/**
 * springmvc中的拦截器对象
 * 1.编写代码:实现拦截器接口 HandlerInterceptor
 * 2.配置拦截器
 */
public class Demo1Interceptor implements HandlerInterceptor {
     

    /**
     * preHandle方法,预处理
     * 作用:在请求进入指定Controller方法之前,执行的方法(对请求进行验证)
     * @param request 请求对象
     * @param response 响应对象
     * @param handler 请求将要执行的Controller对象
     * @return 布尔类型:true表示请求放行,继续向后执行(有可能进入下一个拦截器,也有可能进入Controller)
     *                  false表示拦截请求,请求不能继续向后执行
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
     
        System.out.println("Demo1Interceptor拦截器中的preHandle方法执行了...");
        return true;
    }

    /**
     * postHandle 后处理
     * @param request 请求对象
     * @param response 响应对象
     * @param handler 正在执行的Controller对象
     * @param modelAndView 模型和视图数据,Controller方法执行完成之后的返回值
     *
     * 注意:此方法必须在请求进入Controller之后才会执行,如果没有进入Controller是不会执行的
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
     
        System.out.println("Demo1Interceptor拦截器中的postHandle方法执行了...");
    }

    /**
     * afterCompletion 请求处理完成之后
     * @param request 请求对象
     * @param response 响应对象
     * @param handler 已经执行过的Controller对象
     * @param ex Controller方法抛出的异常对象
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
     
        System.out.println("Demo1Interceptor拦截器中的afterCompletion方法执行了...");
    }
}

方法解析:

  1. preHandle方法
    在请求进入Controller方法之前调用此方法,起到拦截的作用
    如果preHandle方法返回值为true,表示放行(允许进入Controller方法)
    如果preHandle方法返回值为false,表示拦截(不允许进入Controller方法)
  2. postHandle方法
    请求进入Controller方法之后,但未结束之前,调用此方法
    可在返回的模型数据进行处理加工,比如加入公用信息以便页面显示
  3. afterCompletion方法
    请求离开Controller方法之后,调用此方法
    可获取异常信息,记录日志,资源清理等

6. 拦截器配置


<mvc:interceptors>
    
    <mvc:interceptor>
        
        <mvc:mapping path="/**"/>
        
        <bean class="com.newcapec.interceptor.Demo1Interceptor"/>
    mvc:interceptor>
mvc:interceptors>

/* 与 /**的区别:

请求路径 解析
/find 配置/*或/**可进入
/demo/find 配置/**可进入

7. 页面

index.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <base href="${pageContext.request.contextPath}/">
    <title>Titletitle>
head>
<body>
    <div style="text-align: center">
        <h1>拦截器h1>
        <h2>当前登录用户:${sessionScope.loginUser}h2>
        <a href="demo/find">测试查询a><br>
        <a href="demo/add">测试新增a><br>
        <a href="demo/edit">测试编辑a><br>
        <a href="demo/remove">测试删除a><br>
        <a href="emp/find">员工查询a><br>
        <a href="emp/add">员工新增a><br>
        <a href="emp/edit">员工编辑a><br>
        <a href="emp/remove">员工删除a><br>
        <a href="auth/logout">退出系统a><br>
    div>
body>
html>

success.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <base href="${pageContext.request.contextPath}/">
    <title>Titletitle>
head>
<body>
    <div style="text-align: center">
        <h1>操作成功h1>
    div>
body>
html>

8. 拦截器执行流程

定义第二个拦截器Demo2Interceptor.java

public class Demo2Interceptor implements HandlerInterceptor {
     

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
     
        System.out.println("第二个拦截器中的preHandle方法执行了...");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
     
        System.out.println("第二个拦截器中的postHandle方法执行了...");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
     
        System.out.println("第二个拦截器中的afterCompletion方法执行了...");
    }
}

配置:


<mvc:interceptor>
    <mvc:mapping path="/**"/>
    <bean class="com.newcapec.interceptor.Demo2Interceptor"/>
mvc:interceptor>

8.1 正常运行流程

每个拦截器的preHandler方法都返回true

SpringMVC拦截器_第1张图片

8.2 中断流程

Demo1Interceptor的preHandler方法返回true,Demo2Interceptor返回false

在这里插入图片描述

8.3 中断流程

每个拦截器的preHandler方法都返回false

在这里插入图片描述

8.4 总结

  • preHandle方法按拦截器定义顺序调用,postHandler方法按拦截器定义逆序调用,afterCompletion方法按拦截器定义逆序调用
  • postHandler方法在拦截器链内所有拦截器返true时调用
  • afterCompletion方法只要preHandle方法执行过,并且返回true时就会调用

9. 拦截器应用

用户身份认证拦截器的实现

9.1 Controller

@Controller
@RequestMapping("/auth")
public class LoginController {
     

    @RequestMapping("/login")
    public String login(String username, String password, HttpSession session, Model model){
     
        //模拟查询:根据用户名和密码查询数据
        if("admin".equals(username) && "123".equals(password)) {
     
           //比对成功,用户登录
           //将用户信息放入session域对象
           session.setAttribute("loginUser", username);
           return "index";
        }
        model.addAttribute("message", "username or password is invalid");
        return "login";
    }

    @RequestMapping("/logout")
    public String logout(HttpSession session){
     
        session.removeAttribute("loginUser");
        session.invalidate();
        return "login";
    }
}

9.2 拦截器

public class LoginInterceptor implements HandlerInterceptor {
     
    /**
     * 身份认证:
     * 过滤器:
     * 1.从session域中获取用户的登录信息
     * 2.判断用户信息是否为空
     * 3.不为空(表示已登录)放行(doFilter方法)
     * 4.为空(表示未登录)
     * 5.判断当前请求是否为登录请求或无需登录可执行请求(身份认证白名单)
     * 6.如果为白名单请求,放行
     * 7.如果不是,拦截,跳转login,信息提示...
     *
     * 拦截器:
     * 1.从session域中获取用户的登录信息
     * 2.判断用户信息是否为空
     * 3.不为空(表示已登录)放行(返回true)
     * 4.为空(表示未登录),拦截,跳转login,信息提示...
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
     
        System.out.println("身份认证拦截器执行.....");
        HttpSession session = request.getSession();
        Object userInfo = session.getAttribute("loginUser");
        if(userInfo == null){
     
            request.setAttribute("message", "you are not login.");
            request.getRequestDispatcher("/views/login.jsp").forward(request, response);
            return false;
        }
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
     
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
     
    }
}

9.3 配置

<mvc:interceptors>
    <mvc:interceptor>
        <mvc:mapping path="/**"/>
        
        <mvc:exclude-mapping path="/auth/login"/>
        
        <bean class="com.newcapec.interceptor.LoginInterceptor"/>
    mvc:interceptor>
mvc:interceptors>

9.4 页面

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <base href="${pageContext.request.contextPath}/">
    <title>Titletitle>
head>
<body>
    <div style="text-align: center">
        <h1>用户登录h1>
        <div style="color: red;">${message}div>
        <form action="auth/login" method="post">
            <p>用户名:<input type="text" name="username">p>
            <p>码:<input type="text" name="password">p>
            <p><button>登录button>p>
        form>
    div>
body>
html>

你可能感兴趣的:(springmvc,spring,java,过滤器,拦截器)