当前位置:首页 > 后端开发 > 正文内容

SpringMVC-08-拦截器

邻居的猫1个月前 (12-09)后端开发1631

1、阻拦器概述

SpringMVC的处理器阻拦器 类似于Servlet开发中的过滤器 Filter ,用于对 Handler 进行预处理后处理。开发者能够自己界说一些阻拦器来完结特定的功用。

过滤器与阻拦器的差异:

  • 过滤器
    • servlet标准中的一部分,任何JavaWeb工程都能够运用
    • 在url-pattern中装备了/*之后,能够对一切要拜访的资源进行过滤
  • 阻拦器
    • 阻拦器是SpringMVC结构自己的,只要运用了SpringMVC结构的工程才干运用
    • 阻拦器只会阻拦进入Spring系统中的恳求,即 进入DispatcherServlet中的恳求
    • 像.jsp这种的资源恳求,阻拦器不会履行,由于它并没用进入DispatcherServlet,而是进到Tomcat内置的 JspServlet中

阻拦器是AOP思维的详细运用!


2、阻拦器运用

自界说阻拦器

那怎么完结阻拦器呢?

想要自界说阻拦器,有必要完结 HandlerInterceptor 接口

public interface HandlerInterceptor {

	default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		return true;
	}

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

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

}
  • preHandle
    • 在 Handler履行 之前履行
    • 回来true: 放行,履行下一个阻拦器
    • 回来false: 阻拦,停止此次恳求后边的处理链,接下来需求自己处理request和response来操控网页
  • postHandle
    • 在 Handler履行 之后,ViewResolver解析逻辑视图之前 履行
    • 能够修正ModelAndView 来操控 模型数据 和 接下来即将跳转的视图(仅限于回来逻辑视图名的Handler)
  • afterCompletion
    • 一次恳求 在Spring系统处理工作完结 之后的回调(即,ViewResolver烘托出物理视图之后)
    • 不论Handler是否正常履行(或许抛反常),此办法都会履行
    • 类似于try-catch语法中的finally,常用来做资源整理和依据反常的处理

自界说阻拦器 MyInterceptor

public class MyInterceptor implements HandlerInterceptor {
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object handler) throws Exception {
        System.out.println("------------preHandle------------");

        return !"false".equals(httpServletRequest.getParameter("status"));
    }

    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
        System.out.println("------------postHandle------------");
    }

    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
        System.out.println("------------afterCompletion------------");
        System.out.println(e);
        if (e != null)
            httpServletRequest.getRequestDispatcher("/").forward(httpServletRequest, httpServletResponse);
    }
}

装备阻拦器

在Spring的装备文件中界说

<!--关于阻拦器的装备-->
<mvc:interceptors>
    <mvc:interceptor>
        <!-- /** 包含途径及其子途径 -->
        <!-- /admin/* 阻拦的是/admin/add等等这种 , /admin/add/user不会被阻拦 -->
        <!-- /admin/** 阻拦的是/admin/下的一切途径 -->
        <mvc:mapping path="/**"/>
        <mvc:exclude-mapping path="/login"/>
        <!--bean装备的便是阻拦器-->
        <bean class="com.moondream.interceptor.MyInterceptor"/>
    </mvc:interceptor>
</mvc:interceptors>
  • mvc:mapping
    • 阻拦器映射阻拦的途径
  • mvc:exclude-mapping
    • 在映射阻拦途径中扫除的途径
  • bean
    • 要装备的阻拦器类

测验

增加Controller

@RestController
public class TestController {

    @RequestMapping("test1")
    public String test1() {
        System.out.println("Handler履行");
//        int i = 1 / 0;
        return "hello";
    }

}
  • 阻拦器阻拦:后边的处理链不会履行

    image-20241208170003247

    image-20241208170021613

  • 阻拦器放行:恳求正常处理

    image-20241208170336458

    image-20241208170357884

  • Handler 出现反常:postHandle不会履行,反常被afterCompletion捕获,并由afterCompletion处理恳求

    image-20241208171104846

    image-20241208171127011


3、阻拦器履行次序

增加 MyInterceptor2

public class MyInterceptor2 implements HandlerInterceptor {
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object handler) throws Exception {
        System.out.println("------------preHandle-2------------");
        return true;
    }

    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
        System.out.println("------------postHandle-2------------");
    }

    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
        System.out.println("------------afterCompletion-2------------");
    }
}
<!--关于阻拦器的装备-->
<mvc:interceptors>
    <mvc:interceptor>
        <!-- /** 包含途径及其子途径 -->
        <!-- /admin/* 阻拦的是/admin/add等等这种 , /admin/add/user不会被阻拦 -->
        <!-- /admin/** 阻拦的是/admin/下的一切途径 -->
        <mvc:mapping path="/**"/>
        <mvc:exclude-mapping path="/login"/>
        <!--bean装备的便是阻拦器-->
        <bean class="com.moondream.interceptor.MyInterceptor"/>
    </mvc:interceptor>
    <mvc:interceptor>
        <mvc:mapping path="/**"/>
        <bean class="com.moondream.interceptor.MyInterceptor2"/>
    </mvc:interceptor>
</mvc:interceptors>

履行测验,调查操控台输出

image-20241208181700748

由图可知,

  • 在 preHandle阶段,阻拦器按注册次序履行
  • 在 postHandle阶段 和 afterCompletion阶段,阻拦器逆序履行

这比如进入一个有多重门的宅院,进去 要先开外门,再开内门,出去 要先开内门,再开外门。


4、验证用户是否登录 (项目事例)

完结思路

  1. 有一个登陆页面,需求写一个controller拜访页面。
  2. 登陆页面有一提交表单的动作。需求在controller中处理。
  3. 判别用户名暗码是否正确。假如正确,向session中写入用户信息。回来登陆成功。
  4. 阻拦用户恳求,判别用户是否登陆。
  5. 假如用户现已登陆。放行, 假如用户未登陆,跳转到登陆页面。

编写一个登陆页面 login.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
    
<h1>登录页面</h1>
<hr>
    
<body>
<form action="${pageContext.request.contextPath}/user/login">
    用户名:<input type="text" name="username"> <br>
    暗码: <input type="password" name="pwd"> <br>
    <input type="submit" value="提交">
</form>
</body>
</html>

编写一个Controller处理恳求

@Controller
@RequestMapping("/user")
public class UserController {
    //跳转到登陆页面
    @RequestMapping("/jumplogin")
    public String jumpLogin() throws Exception {
        return "login";
    }
    //跳转到成功页面
    @RequestMapping("/jumpSuccess")
    public String jumpSuccess() throws Exception {
        return "success";
    }
    //登陆提交
    @RequestMapping("/login")
    public String login(HttpSession session, String username, String pwd) throws Exception {
        // 向session记载用户身份信息
        System.out.println("接纳前端==="+username);
        session.setAttribute("user", username);
        return "success";
    }
    //退出登陆
    @RequestMapping("logout")
    public String logout(HttpSession session) throws Exception {
        // session 过期
        session.invalidate();
        return "login";
    }
}

编写一个登陆成功的页面 success.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    
<h1>登录成功页面</h1>
<hr>
    
${user}
<a href="${pageContext.request.contextPath}/user/logout">刊出</a>
</body>
</html>

在 index 页面上测验跳转!发动Tomcat 测验,未登录也能够进入主页!

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>$Title$</title>
  </head>
  <body>
  <h1>主页</h1>
  <hr>
  <%--登录--%>
  <a href="${pageContext.request.contextPath}/user/jumplogin">登录</a>
  <a href="${pageContext.request.contextPath}/user/jumpSuccess">成功页面</a>
  </body>
</html>

编写用户登录阻拦器

public class LoginInterceptor implements HandlerInterceptor {
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws ServletException, IOException {
        // 假如是登陆页面则放行
        System.out.println("uri: " + request.getRequestURI());
        if (request.getRequestURI().contains("login")) {
            return true;
        }
        HttpSession session = request.getSession();
        // 假如用户已登陆也放行
        if(session.getAttribute("user") != null) {
            return true;
        }
        // 用户没有登陆跳转到登陆页面
        request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request, response);
        return false;
    }
    
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
    }
    
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
    }
    
}

在Spring的装备文件中注册阻拦器

<!--关于阻拦器的装备-->
<mvc:interceptors>
    <mvc:interceptor>
        <mvc:mapping path="/**"/>
        <bean id="loginInterceptor" class="com.moondream.interceptor.LoginInterceptor"/>
    </mvc:interceptor>
</mvc:interceptors>

再次重启Tomcat测验!

OK,测验登录阻拦功用无误.

扫描二维码推送至手机访问。

版权声明:本文由51Blog发布,如需转载请注明出处。

本文链接:https://www.51blog.vip/?id=135

标签: JavaSpringMVC
分享给朋友:

“SpringMVC-08-拦截器” 的相关文章

java6,回顾与展望

java6,回顾与展望

Java 6(也称为Java SE 6)是Java编程语言的一个版本,由Sun Microsystems(现为Oracle Corporation)于2006年12月11日发布。Java 6引入了许多新特性和改进,包括但不限于:1. 脚本语言支持:Java 6支持使用脚本语言(如JavaScript...

b rust,性能与安全的完美结合

B树是一种自平衡的树数据结构,它维持数据有序,并且允许搜索、顺序访问、插入和删除操作都在对数时间内完成。Rust是一种系统编程语言,以其内存安全性和高性能著称。在Rust中实现B树是一个很好的练习,可以帮助你理解数据结构和Rust语言的特性。以下是一个简单的B树实现的示例代码:```rustuse...

php如何安装,从入门到环境搭建

php如何安装,从入门到环境搭建

安装PHP是一个多步骤的过程,通常取决于您正在使用的操作系统。以下是在不同操作系统上安装PHP的基本步骤: Windows1. 下载PHP: 访问下载PHP。 选择与您的Windows版本兼容的版本。2. 安装PHP: 双击下载的`.msi`文件启动安装程序。 按照提示完成安...

c语言gets函数,使用、风险与替代方案

`gets` 函数是 C 语言标准库中的一个函数,用于从标准输入读取一行文本,直到遇到换行符或文件结束符。它的原型如下:```cchar gets;```其中,`str` 是一个字符数组,用于存储读取的字符串。`gets` 函数会读取直到换行符或文件结束符,然后将换行符替换为字符串终止符 `0`,并...

delphi7序列号,Delphi7序列号获取与使用指南

1. 序列号: 6AMDPKG68EDB8PP79SFE 3QH9QW2. 获取方法: 通过合法渠道购买:如果您已经购买了Delphi 7的正版授权,序列号通常会在购买时提供,或者在软件安装时输入序列号。如果您丢失了序列号,可以联系Delphi 7官方客服进行查询和恢复。 使用破解...

java重载,什么是Java重载?

java重载,什么是Java重载?

在Java中,方法重载(Overloading)是指在一个类中定义多个名称相同的方法,但它们的参数列表不同。这些方法可以有不同的参数数量、不同的参数类型或不同的参数顺序。Java编译器会根据方法调用时提供的参数类型和数量来决定调用哪个方法。重载的主要目的是为了提高代码的可读性和可维护性,同时也可以为...