SpringMVC拦截器详解:原理、使用与配置

发布于:2025-02-10 ⋅ 阅读:(40) ⋅ 点赞:(0)

目录

         1. 什么是拦截器?

2. 拦截器与过滤器的区别

3. 拦截器方法详解

4. 单个拦截器执行流程

5. 使用拦截器实现用户登录权限验证

6. 多个拦截器的执行流程


1. 什么是拦截器?

在SpringMVC框架中,拦截器(Interceptor)是一种用于拦截用户请求并进行处理的机制,类似于Servlet中的过滤器(Filter)。拦截器主要用于:

  • 用户权限验证
  • 用户是否登录验证
  • 日志记录
  • 请求的预处理和后处理等

SpringMVC的拦截器机制是可插拔的,可以在配置文件中进行灵活配置,启用或禁用某个功能的拦截器。例如,如果需要权限验证,只需在配置文件中添加拦截器;如果不需要,只需将其移除。


2. 拦截器与过滤器的区别

        拦截器与过滤器在功能上相似,都是用于拦截请求并作相应处理,但它们的实现和执行流程有所不同。以下是它们的主要区别:

区别 过滤器 (Filter) 拦截器 (Interceptor)
依赖关系 依赖于Servlet,工作在Servlet容器层 属于SpringMVC,工作在SpringMVC层
作用范围 对所有请求都有效 仅对Controller层的请求有效
执行顺序 过滤器先执行,拦截器后执行 拦截器在Controller方法执行前和后都可执行

执行顺序:

  • 过滤器在请求进入Tomcat容器后、Servlet前执行。
  • 拦截器则是在请求到达Controller方法前执行,在请求返回视图前以及请求处理完后执行。

 


3. 拦截器方法详解

自定义拦截器需要实现SpringMVC的HandlerInterceptor接口,该接口定义了以下三个方法:

  • preHandle:在Controller方法执行之前执行。如果该方法返回false,请求会被拦截,不再执行后续的操作;如果返回true,则继续执行后续操作,包括Controller方法。

  • postHandle:在Controller方法执行之后、视图渲染之前执行。可以在此方法中修改返回的Model和View,例如添加一些数据或修改视图。

  • afterCompletion:在整个请求处理完毕之后执行,用于清理资源、记录日志等。

示例代码:

public class MyInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("preHandle: 在Controller方法执行前");
        return true; // 继续执行后续操作
    }

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

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("afterCompletion: 请求处理完成,视图渲染后");
    }
}

4. 单个拦截器执行流程

当请求到达SpringMVC时,拦截器的执行顺序如下:

  1. preHandle():首先执行preHandle()方法。如果返回false,请求会被拦截,后续操作不会执行;如果返回true,继续执行Controller方法。
  2. Controller方法:处理请求,进行相应的业务逻辑处理。
  3. postHandle():Controller方法执行后,执行postHandle()方法,此时可以操作Model和View。
  4. 视图渲染:DispatcherServlet将视图返回给客户端。
  5. afterCompletion():请求处理完毕后,执行afterCompletion()方法,进行资源清理、日志记录等操作。


5. 使用拦截器实现用户登录权限验证

        以下是一个实现用户登录验证的例子。在SpringMVC应用中,我们可以通过自定义拦截器来检查用户是否已登录,若未登录,则拦截请求并重定向到登录页面。

1. Controller层设计

@Controller
public class LoginController {

    /**
     * 跳转登录页
     * @return
     */
    @RequestMapping(value = "/login",method = RequestMethod.GET)
    public String loginPage(){
        System.out.println("跳转到login.html页面当中");
        return "login";
    }

    /**
     * 用户登录,成功到主页,失败回到登录页
     * @param user
     * @param model
     * @param session
     * @return
     */
    @RequestMapping(value = "/login",method = RequestMethod.POST)
    public String login(User user, Model model, HttpSession session){
        if(user.getUsername() !=null && user.getUsername().equals("admin")
                && user.getPassword() !=null && user.getPassword().equals("123456")){
            System.out.println("用户登录功能实现");
            //将用户添加到session保存
            session.setAttribute("user",user);
            return "/suc";
        }
        model.addAttribute("msg","账户或密码错误,请重新登录");
        return "login";
    }

    /**
     * 跳转到主页
     * @return
     */
    @RequestMapping("/index")
    public String indexPage(){
        System.out.println("跳转到主页");
        return "suc";
    }

    /**
     * 用户退出登录
     * @param session
     * @return
     */
    @RequestMapping("/logout")
    public String logout(HttpSession session){
        session.invalidate();//清除session
        System.out.println("用户退出登录");
        return "login";
    }

}

2. 登录拦截器设计


public class LoginInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String url = request.getRequestURI();
        
        // 如果是非登录请求,且用户未登录,跳转到登录页面
        if (!url.contains("login")) {
            if (request.getSession().getAttribute("user") != null) {
                return true; // 已登录,放行
            } else {
                request.setAttribute("msg", "您还未登录,请先登录");
                request.getRequestDispatcher("/login").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 {
        // 可用于清理资源、记录日志等
    }
}

3. 拦截器配置

springmvc.xml配置文件中配置拦截器:

<!--配置拦截器-->
<mvc:interceptors>
    <mvc:interceptor>
        <mvc:mapping path="/**"/> <!--/**表示所有url-->
        <bean class="com.qcby.Interceptor.LoginInterceptor"/>
    </mvc:interceptor>
</mvc:interceptors>

4. 登录页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登录页面</title>
</head>
<body>
<h1> <font color="red"> <b th:text="${msg}"></b></font></h1>
<form action="/SSMDemo/login" method="post">
    账户:<input type="text" name="username"/>
    密码:<input type="password" name="password"/>
    <input type="submit" value="登录"/>
</form>
</body>
</html>

5.主页

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>Hello <b th:text="${msg}"></b></h1>
<a href="/SSMDemo/logout" >入门程序</a>
</body>
</html>

6. 多个拦截器的执行流程

当有多个拦截器同时工作时,它们的执行流程如下:

  • preHandle()方法按照配置的顺序执行。
  • postHandle()方法和afterCompletion()方法则是按照配置的逆序执行;
    即后配置的拦截器的postHandle()afterCompletion()方法先执行。

 

示例:

假设有两个拦截器Interceptor1Interceptor2,并且Interceptor1先配置在springmvc.xml中。它们的执行顺序如下:

  • Interceptor1preHandle()执行
  • Interceptor2preHandle()执行
  • Controller方法执行
  • Interceptor2postHandle()执行
  • Interceptor1postHandle()执行
  • Interceptor2afterCompletion()执行
  • Interceptor1afterCompletion()执行

总结

        SpringMVC的拦截器为我们提供了灵活的请求处理机制,能够在请求的生命周期中进行多方面的控制,如权限验证、日志记录、性能监控等。通过实现HandlerInterceptor接口并配置拦截器,可以轻松地在请求的不同阶段插入自定义逻辑,从而增强应用的功能和可维护性。


网站公告

今日签到

点亮在社区的每一天
去签到