15. 拦截器

1. 拦截器概述

Spring MVC中的拦截器(Interceptor)类似于Servlet中的过滤器(Filter),它主要用于拦截用户请求并做相应的处理。例如通过拦截器可以进行权限验证、记录请求信息的日志、判断用户是否登录等

要使用Spring MVC中的拦截器,就需要对拦截器类进行定义和配置。通常拦截器类可以通过两种方式来定义
一种是通过实现HandlerInterceptor接口,或继承HandlerInterceptor接口的实现类(如HandlerInterceptorAdapter)来定义;
另一种是通过实现WebRequestInterceptor接口,或继承WebRequestInterceptor接口的实现类来定义

package com.clarence.controller;

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

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

public class CustomInterceptor implements HandlerInterceptor{

    @Override
    public void afterCompletion(HttpServletRequest arg0,
            HttpServletResponse arg1, Object arg2, Exception arg3)
            throws Exception {
        // TODO Auto-generated method stub
        
    }

    @Override
    public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1,
            Object arg2, ModelAndView arg3) throws Exception {
        // TODO Auto-generated method stub
        
    }

    @Override
    public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1,
            Object arg2) throws Exception {
        // TODO Auto-generated method stub
        return false;
    }
}

自定义的拦截器类实现了HandlerInterceptor接口,并实现了接口中的三个方法。关于这三个方法的具体描述如下

  1. preHandler()方法:该方法会在控制器方法前执行,其返回值表示是否中断后续操作。当其返回值为true时,表示继续向下执行;当其返回值为false时,会中断后续的所有操作(包括调用下一个拦截器和控制器类中的方法执行等)
  2. postHandle()方法:该方法会在控制器方法调用之后,且解析视图之前执行。可以通过此方法对请求域中的模型和视图做出进一步的修改
  3. afterCompletion()方法:该方法会在整个请求完成,即视图渲染结束之后执行。可以通过此方法实现一些资源清理、记录日志信息等工作
1.springmvc配置
<!-- 配置拦截器 -->
    <mvc:interceptors>
        <!-- 其子元素<bean>中定义的是全局拦截器,它会拦截所有的请求 -->
        <bean class="com.clarence.interceptor.CustomerInterceptor"></bean>
        <mvc:interceptor>
            <!-- 配置拦截路径 “/ **” 表示拦截所有路径-->
            <mvc:mapping path="/**"/>
            <!-- 不需要拦截的路径 -->
            <mvc:exclude-mapping path=""/>
            <!-- 只对路径下的请求拦截 -->
            <bean class="com.clarence.interceptor.Interceptor1"/>
        </mvc:interceptor>
        <mvc:interceptor>
            <!--/hello”表示拦截所有以“/hello”结尾的路径 -->
            <mvc:mapping path="/hello"/>
            <bean class="com.clarence.interceptor.Interceptor2"/>
        </mvc:interceptor>
    </mvc:interceptors>

需要注意的是,< mvc:interceptor>中的子元素必须按照上述代码的配置顺序进行编写,即<mvc:mapping … />→<mvc:exclude-mapping …/>→<bean … />的顺序,否则文件会报错。

2. 拦截器的执行流程

2.1 单个拦截器的执行流程

在运行程序时,拦截器的执行是有一定顺序的,该顺序与配置文件中所定义的拦截器的顺序相关。如果在项目中只定义了一个拦截器,那么该拦截器在程序中的执行流程如图所示
在这里插入图片描述
程序首先会执行拦截器类中的preHandle()方法,如果该方法的返回值为true,则程序会继续向下执行处理器中的方法,否则将不再向下执行;
在业务处理器(即控制器Controller类)处理完请求后,会执行postHandle()方法,然后会通过DispatcherServlet向客户端返回响应;
在DispatcherServlet处理完请求后,才会执行afterCompletion()方法

1.拦截器
package com.clarence.interceptor;

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

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

public class CustomInterceptor implements HandlerInterceptor{

    @Override
    public void afterCompletion(HttpServletRequest arg0,
            HttpServletResponse arg1, Object arg2, Exception arg3)
            throws Exception {
        System.out.println("Cunstomer.....Intercepter1....afterHandle");
        
    }

    @Override
    public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1,
            Object arg2, ModelAndView arg3) throws Exception {
        // handler (or HandlerMethod) that started asynchronousexecution, for type and/or instance examination
        System.out.println("Cunstomer.....Intercepter1....postHandle");
        
    }

    @Override
    public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1,
            Object arg2) throws Exception {
        //  arg2:chosen handler to execute, for type and/or instance evaluation
        System.out.println("Cunstomer.....Intercepter1....preHandle");
        return true;
    }

}
2.springmvc-config.xml配置
    <mvc:interceptors>
        <!-- 其子元素<bean>中定义的是全局拦截器,它会拦截所有的请求 -->
        <bean class="com.clarence.interceptor.CustomInterceptor"></bean>
    </mvc:interceptors>

3.controller类
@Controller
public class HelloController {
   /**
    * 页面跳转
    */
    @RequestMapping("/hello")
    public String toHello() {
        System.out.println("hello!");
        return "success";
    }
}

运行结果
在这里插入图片描述

多个拦截器的执行流程

在这里插入图片描述

显然,这里的调用方式为栈式调用
假设Interceptorn的preHandle为An,postHandle为Bn,afterCompletion为Cn
出栈顺序(执行顺序)为:
A1,A2,A3,…,An,handleAdapter,Bn,Bn-1,Bn-2,…,B1,DispatcherServlet,Cn,Cn-1,Cn-2,…,C1
其中,排序是按照配置文件中拦截器配置的先后顺序

拦截用户登录的简单案例

流程图
在这里插入图片描述
1.拦截器

package com.clarence.interceptor;

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

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

import com.clarence.po.User;

public class LoginInterceptor implements HandlerInterceptor{

    @Override
    public boolean preHandle(HttpServletRequest request,
            HttpServletResponse response, Object handler) throws Exception {
        String url = request.getRequestURI();
        if(url.indexOf("/login")>0) {
            return true;
        }        
        HttpSession httpSession = request.getSession();
        User user = (User)httpSession.getAttribute("USER_SESSION");
        if(user!=null) {
            return true;
        }        
        request.setAttribute("msg", "您还没有登录!");
        request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request, response);;
        return false;
    }

    @Override
    public void postHandle(HttpServletRequest request,
            HttpServletResponse response, Object handler,
            ModelAndView modelAndView) throws Exception {
        // TODO Auto-generated method stub        
    }

    @Override
    public void afterCompletion(HttpServletRequest request,
            HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
        // TODO Auto-generated method stub        
    }
}

2.控制类

package com.clarence.controller;

import javax.servlet.http.HttpSession;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.clarence.po.User;

@Controller
public class UserController {
    @RequestMapping(value="/login",method = RequestMethod.GET )
    public String toLogin() {
        return "login";
    }
    
    @RequestMapping(value="/login",method = RequestMethod.POST)
    public String login(User user,Model model,HttpSession httpSession) {
        String username = user.getUsername();
        String password = user.getPassword();
        if(username!=null&&username.equals("Caris")){
            if(password!=null&&password.equals("123456")) {
               httpSession.setAttribute("USER_SESSION", user);
               return "redirect:main";
            }            
        }
        model.addAttribute("msg", "用户名或密码错误");
        return "login";
    }
    
    @RequestMapping("/main")
    public String toMain() {
        return "main";
    }
    
    @RequestMapping("/logout")
    public String logout(HttpSession httpSession) {
        httpSession.invalidate();
        return "redirect:login";
    }
    
}

3.jsp页面

1.login.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
${msg}
<form action="${pageContext.request.contextPath}/login" method="post">
    用户名:<input type="text" name="username"/>
    密码:<input type="password" name="password"/>
    <input type="submit" value="登录"/>
</form>
</body>
</html>
2.main.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
当前用户:${USER_SESSION.username };
<a href="${pageContext.request.contextPath}/logout">退出</a>
</body>
</html>

配置文件

1.Springmvc-config.xml
    <mvc:interceptors>
        <mvc:interceptor>
            <!-- 配置拦截路径 “/ **” 表示拦截所有路径 -->
            <mvc:mapping path="/**"/>
            <!-- 不需要拦截的路径 -->
            <mvc:exclude-mapping path=""/>
           <!--  只对路径下的请求拦截 -->
            <bean class="com.clarence.interceptor.LoginInterceptor"/>
        </mvc:interceptor>
    </mvc:interceptors>
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值