SpringMVC | Spring MVC中的“拦截器”

目录:

作者简介 :一只大皮卡丘,计算机专业学生,正在努力学习、努力敲代码中! 让我们一起继续努力学习!

该文章参考学习教材 为:
《Java EE企业级应用开发教程 (Spring + Spring MVC +MyBatis)》 黑马程序员 / 编著

文章以课本知识点 + 代码为主线,结合自己看书学习过程中的理解和感悟 ,最终成就了该文章

文章用于本人学习使用 , 同时希望能帮助大家。

欢迎大家点赞👍 收藏⭐ 关注💖哦!!!

(侵权可联系我,进行删除,如果雷同,纯属巧合)


实际项目 中,拦截器使用是非常普遍 的,例如在购物网站 中通过 拦截器 可以 拦截未登录的用户禁止其购买商品 ,或者 使用拦截器验证已登录用户是否有相应操作权限 等。在Struts2框架 中,拦截器 是其重要的组成部分 ,而 Spring MVC 中 也提供了拦截器功能,通过配置 即可对请求 进行拦截处理

一、拦截器 :

1. 拦截器的 "概述"

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

2. 拦截器的 "定义" (创建"拦截器"对象)

  • 要使用 SpringMVC 中的拦截器,就需要对拦截器类 进行定义配置 。通常拦截器类可以通过 两种方式来定义

    • 一种 是通过 实现 HandlerInterceptor接口,或 继承 HandlerInterceptor接口实现类HandlerInterceptorAdapter 来定义;
    • 另一种 是通过 实现 WebRequestInterceptor接口,或 继承 WebRequestInterceptor接口实现类 来定义。
  • 例子如 :(实现HandlerInterceptor接口 的方式来实现SpringMVC拦截器) :

    java 复制代码
    //通过实现HandlerInterceptor接口的方式来实现SPringMVC拦截器
    public class CustomerInterceptor implements HandlerInterceptor { 
    
        //该方法在"控制器方法"之前执行,其返回值表示"是否中断后续操作"
        @Override
        public boolean preHandle(javax.servlet.http.HttpServletRequest httpServletRequest, javax.servlet.http.HttpServletResponse httpServletResponse, Object o) throws Exception {
            return false;
        }
    
        //该方法在"控制器方法"之后执行,且"解析视图"之前执行(可通过该方法对"模型和视图"进一步修改)
        @Override
        public void postHandle(javax.servlet.http.HttpServletRequest httpServletRequest, javax.servlet.http.HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
    
        }
    
        //该方法在"整个请求"完成之后执行,即"视图渲染结束"之后执行(通过该方法可进行"资源清理、记录日志信息等")
        @Override
        public void afterCompletion(javax.servlet.http.HttpServletRequest httpServletRequest, javax.servlet.http.HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
    
        }
    }

    上述代码 可以看出,自定义拦截器类实现了HandlerInterceptor接口,并实现了 接口中的三个方法 。 关于这 三个方法具体描述 如下 :

    方法 描述
    preHandler()方法 该方法 会在 控制器方法 之前执行,其 返回值 表示 是否中断后续操作。 当其返回值true 时,表示 继续向下执行; 当其返回值false 时,会 中断后续的所有操作 (包括调用下一个拦截器控制器类 中的方法执行等)。
    postHandle()方法 方法 会在 控制器方法 之后执行,且 解析视图 之前执行。可以通过此方法请求域 中的 模型视图 做出 进一步的修改
    afterCompletion()方法 方法 在 "整个请求完成 " 之后执行,即 视图渲染结束 之后执行。可以通过此方法实现一些资源清理记录日志信息等。

    要想让刚创建好的 "拦截器"生效,就要在 springmvc-config.xml 中进行配置让"拦截器"生效

3. 拦截器的 "配置" (让"拦截器"对象生效)

  • 使自定义拦截器生效,还需要在SpringMVC配置文件 : springmvc-config.xml 中进行配置

  • SpringMVC拦截器"配置元素图" 如下所示

  • SpringMVC拦截器"在==springmvc-config.xml "== 中==配置代码 == 如下所示

    xml 复制代码
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:mvc="http://www.springframework.org/schema/mvc"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="
    	http://www.springframework.org/schema/beans
    	http://www.springframework.org/schema/beans/spring-beans.xsd
    	http://www.springframework.org/schema/mvc
    	http://www.springframework.org/schema/mvc/spring-mvc.xsd
    	http://www.springframework.org/schema/context/spring-context.xsd">
    
        <!-- 配置拦截器 -->
        <mvc:interceptors>
            <!-- 配置"全局拦截器",拦截所有请求 -->
            <bean class="com.myh.interceptor.CustomerInterceptor"/>
    
            <!-- 配置"普通拦截器1",拦截"指定路径"/"指定请求" -->
            <mvc:interceptor>
                <!-- 需要拦截的路径 -->
                <mvc:mapping path="/**"/>
                <bean class="com.myh.interceptor.CustomerInterceptor1"/>
            </mvc:interceptor>
    
            <!-- 配置"普通拦截器2" -->
            <mvc:interceptor>
                <!-- 需要拦截的路径 -->
                <!-- 拦截所有以 /hello 结尾的路径 -->
                <mvc:mapping path="/hello"/>
                <bean class="com.myh.interceptor.CustomerInterceptor2"/>
            </mvc:interceptor>
             .....
        </mvc:interceptors>
    </beans>

    上述配置代码 中,<mvc:interceptors>元素 用于配置一组拦截器 ,其子元素<bean>中定义的
    全局拦截器
    ,它会拦截所有的请求 ;而 <mvc:interceptor>元素 中定义的是指定路径拦截器

    它会对指定路径 下的请求生效<mvc:interceptor> 元素子元素<mvc:mapping>用于配置拦截
    器作用路径 ,该路径在其属性path 中定义。如上述代码中path属性值"/ "** 表示拦截所有路径 ,"hello "表示拦截所有以"hello" 结尾的路径 。如果在请求路径 中包含不需要拦截的内容 ,还可以通过 <mvc:exclude- mapping>元素进行配置

    注意点 :

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

4. 拦截器的 "执行流程"

"单个拦截器"的执行流程
  • 运行程序 时,拦截器的执行 是 有一定顺序 的,该 顺序配置文件中所定义拦截器的顺序 相关。如果在项目只定义了一个拦截器 ,那么该拦截器程序中执行流程如图 如下图所示 :

    上图 可以看出程序首先执行拦截器类 中的 preHandle( )方法,如果该方法的 返回值true ,则程序继续向下执行 处理器类中的方法否则不会向下执行 ,后执行 控制器类中方法
    执行完"控制器类中方法"后,会执行"拦截器类 "中的 postHandle( )方法,然后会通过DispatcherServlet各户端返回响应;在DispatcherServlet处理完请求后 ,才会执行
    afterCompletion( )方法

  • "单个拦截器 "的执行流程 例子如 :

    第一步创建项目,导入依赖
    Spring MVC所需JAR (百度网盘)

    第二步 :配置 SpringMVC拦截器相关文件 :

    web.xml :

    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">
    
    
        <!-- 配置"前端过滤器"-->
        <servlet>
            <servlet-name>dispatcherServlet</servlet-name>
            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
            <!--  配置springmvc-config.xml配置文件的位置 (上下文配置位置) -->
            <init-param>
                <param-name>contextConfigLocation</param-name>
                <param-value>classpath:springmvc-config.xml</param-value>
            </init-param>
            <!--  配置启动服务器时加载此配置文件,加载此servlet -->
            <load-on-startup>1</load-on-startup>
        </servlet>
        
        <!--  配置Servlet的Mapper映射  -->
        <servlet-mapping>
            <servlet-name>dispatcherServlet</servlet-name>
            <url-pattern>/</url-pattern>
        </servlet-mapping>
    
    </web-app>

    springmvc-config.xml :

    xml 复制代码
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:mvc="http://www.springframework.org/schema/mvc"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="
    	http://www.springframework.org/schema/beans
    	http://www.springframework.org/schema/beans/spring-beans.xsd
    	http://www.springframework.org/schema/mvc
    	http://www.springframework.org/schema/mvc/spring-mvc.xsd
    	http://www.springframework.org/schema/context
    	http://www.springframework.org/schema/context/spring-context.xsd">
    
        <!-- 配置组件扫描,进行根包扫描,让注解生效 -->
        <context:component-scan base-package="com.myh.controller"/>
    
        <!-- 配置视图解析器 -->
        <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!-- 前缀 -->
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <!-- 后缀 -->
        <property name="suffix" value=".jsp"/>
        </bean>
    
        <!-- 配置SpringMVC 拦截器 -->
        <mvc:interceptors>
        <!-- 全局拦截器,会拦截所有请求 -->
        <bean class="com.myh.interceptor.CustomerInterceptor"/>
        </mvc:interceptors>
    
    </beans>

    HelloController.java (控制器类) :

    java 复制代码
    package com.myh.controller;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    
    @Controller //标记该类为控制器类
    public class HelloController {
    
        /**
         * 页面跳转
         */
        @RequestMapping("/hello")
        public String Hello() {
            System.out.println("HelloController...Hello()");
            return "success"; //响应一个页面给前端
        }
    }

    CustomerInterceptor.java (拦截器对象) :

    java 复制代码
    package com.myh.interceptor;
    
    import org.springframework.web.servlet.HandlerInterceptor;
    import org.springframework.web.servlet.ModelAndView;
    
    public class CustomerInterceptor implements HandlerInterceptor { //通过实现HandlerInterceptor接口的方式来实现SPringMVC拦截器
    
        //该方法在"控制器方法"之前执行,其返回值表示"是否中断后续操作"
        @Override
        public boolean preHandle(javax.servlet.http.HttpServletRequest httpServletRequest, javax.servlet.http.HttpServletResponse httpServletResponse, Object handler) throws Exception {
            //对拦截的请求放行
            return true;
        }
    
        //该方法在"控制器方法"之后执行,且"解析视图"之前执行(可通过该方法对"模型和视图"进一步修改)
        @Override
        public void postHandle(javax.servlet.http.HttpServletRequest httpServletRequest, javax.servlet.http.HttpServletResponse httpServletResponse, Object handler, ModelAndView modelAndView) throws Exception {
            System.out.println("CustomerInterceptor...postHandle()");
        }
    
        //该方法在"整个请求"完成之后执行,即"视图渲染结束"之后执行(通过该方法可进行"资源清理、记录日志信息等")
        @Override
        public void afterCompletion(javax.servlet.http.HttpServletRequest httpServletRequest, javax.servlet.http.HttpServletResponse httpServletResponse, Object handler, Exception e) throws Exception {
            System.out.println("CustomerInterceptor...afterCompletion()");
        }
    }

    success.jsp :

    html 复制代码
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>success.jsp页面</title>
    </head>
    <body>
    ok
    </body>
    </html>

    启动服务器前端访问 /hello控制台打印内容为

    上图 可以看出 ,程序先执行了拦截器类 中的 preHandle( )方法,然后执行了控制器中Hello( )方法,最后分别执行了拦截器类 中的 postHandle( )方法afterCompletion( )方法。这 与上文所描述单个拦截器的执行顺序一致的

"多个拦截器"的执行流程
  • 大型的企业级项目 中,通常 不会只有一个拦截器开发人员 可能会定义 多个拦截器实现不同的功能
    多个拦截器执行顺序 如下图

    上图 可以看出,当有 "多个拦截器 "同时工作 时,它们的 preHandle( )方法 会按照配置文件中 拦截器 的 "配置顺序 "执行,而它们的 postHandle( )方法afterCompletion( )方法 则会按照 配置顺序 的 "反序执行"。

  • "多个拦截器 "的执行流程 例子如 :

    第一步创建项目,导入依赖
    Spring MVC所需JAR (百度网盘)

    第二步 :配置 SpringMVC拦截器相关文件 :

    web.xml :

    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">
    
    
        <!-- 配置"前端过滤器"-->
        <servlet>
            <servlet-name>dispatcherServlet</servlet-name>
            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
            <!--  配置springmvc-config.xml配置文件的位置 (上下文配置位置) -->
            <init-param>
                <param-name>contextConfigLocation</param-name>
                <param-value>classpath:springmvc-config.xml</param-value>
            </init-param>
            <!--  配置启动服务器时加载此配置文件,加载此servlet -->
            <load-on-startup>1</load-on-startup>
        </servlet>
        
        <!--  配置Servlet的Mapper映射  -->
        <servlet-mapping>
            <servlet-name>dispatcherServlet</servlet-name>
            <url-pattern>/</url-pattern>
        </servlet-mapping>
    
    </web-app>

    springmvc-config.xml :

    xml 复制代码
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:mvc="http://www.springframework.org/schema/mvc"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="
    	http://www.springframework.org/schema/beans
    	http://www.springframework.org/schema/beans/spring-beans.xsd
    	http://www.springframework.org/schema/mvc
    	http://www.springframework.org/schema/mvc/spring-mvc.xsd
    	http://www.springframework.org/schema/context
    	http://www.springframework.org/schema/context/spring-context.xsd">
    
        <!-- 配置组件扫描,进行根包扫描,让注解生效 -->
        <context:component-scan base-package="com.myh.controller"/>
    
        <!-- 配置视图解析器 -->
        <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!-- 前缀 -->
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <!-- 后缀 -->
        <property name="suffix" value=".jsp"/>
        </bean>
    
       <!--  定义两个拦截器  -->
        <mvc:interceptors>
            <!--  拦截器1  -->
            <mvc:interceptor>
                <mvc:mapping path="/**"/>
                <bean class="com.myh.interceptor.Interceptor1"/>
            </mvc:interceptor>
    
            <!--  拦截器2 -->
            <mvc:interceptor>
                <mvc:mapping path="/hello"/>
                <bean class="com.myh.interceptor.Interceptor2"/>
            </mvc:interceptor>
        </mvc:interceptors>
    
    </beans>

    上述拦截器配置代码 中,第一个拦截器 会作用于所有路径下请求,而 第二个拦截器 会作用于以 "hello" 结尾请求

    HelloController.java (控制器类) :

    java 复制代码
    package com.myh.controller;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    
    @Controller //标记该类为控制器类
    public class HelloController {
    
        /**
         * 页面跳转
         */
        @RequestMapping("/hello")
        public String Hello() {
            System.out.println("HelloController...Hello()");
            return "success"; //响应一个页面给前端
        }
    }

    Interceptor1.java (拦截器对象1) :

    java 复制代码
    package com.myh.interceptor;
    
    import org.springframework.web.servlet.HandlerInterceptor;
    import org.springframework.web.servlet.ModelAndView;
    /**
     * 如果有多个拦截器,preHandle()方法按照拦截器的"顺序执行",
     * postHandle()方法 和 afterCompletion()方法按照拦截器的"逆序执行"
     */
    public class Interceptor1 implements HandlerInterceptor {//以实现HandlerInterceptor接口的方式定义拦截器
    
        @Override
        public boolean preHandle(javax.servlet.http.HttpServletRequest httpServletRequest, javax.servlet.http.HttpServletResponse httpServletResponse, Object o) throws Exception {
            System.out.println("Interceptor1...preHandle()");
            return true;   //对拦截的请求放行
        }
    
        @Override
        public void postHandle(javax.servlet.http.HttpServletRequest httpServletRequest, javax.servlet.http.HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
            System.out.println("Interceptor1...postHandle()");
        }
    
        @Override
        public void afterCompletion(javax.servlet.http.HttpServletRequest httpServletRequest, javax.servlet.http.HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
            System.out.println("Interceptor1...afterCompletion()");
        }
    }

    Interceptor2.java (拦截器对象2) :

    java 复制代码
    package com.myh.interceptor;
    
    import org.springframework.web.servlet.HandlerInterceptor;
    import org.springframework.web.servlet.ModelAndView;
    
    /**
     * 如果有多个拦截器,preHandle()方法按照拦截器的"顺序执行",
     * postHandle()方法 和 afterCompletion()方法按照拦截器的"逆序执行"
     */
    public class Interceptor2 implements HandlerInterceptor {//以实现HandlerInterceptor接口的方式定义拦截器
    
        @Override
        public boolean preHandle(javax.servlet.http.HttpServletRequest httpServletRequest, javax.servlet.http.HttpServletResponse httpServletResponse, Object o) throws Exception {
            System.out.println("Interceptor2...preHandle()");
            return true;   //对拦截的请求放行
        }
    
        @Override
        public void postHandle(javax.servlet.http.HttpServletRequest httpServletRequest, javax.servlet.http.HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
            System.out.println("Interceptor2...postHandle()");
        }
    
        @Override
        public void afterCompletion(javax.servlet.http.HttpServletRequest httpServletRequest, javax.servlet.http.HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
            System.out.println("Interceptor2...afterCompletion()");
        }
    }

    success.jsp :

    html 复制代码
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>success.jsp页面</title>
    </head>
    <body>
    ok
    </body>
    </html>

    启动服务器前端访问 /hello控制台打印内容为

    控制体输出信息 可以看出 ,程序 先执行前两个拦截器类 中的 preHandle( )方法,这 两个方法执行顺序配置文件中定义顺序相同;然后执行了控制器类 中的 Hello( )方法; 最后执行了两个拦截器类 中的 postHandle( )方法afterCompletion( )方法 ,且这两个方法的 执行顺序 与配置文件中所 定义 的拦截器 顺序相反

二、应用案例一实现用户登录权限验证

  • 下面 将通过 拦截器 来完成一个 用户登录权限验证案例本案例 中,只有登录后用户 才能访问系统 中的主页面,如果 没有登录系统直接访问主页面,则 拦截器会将请求拦截并转发到登录页面,同时在登录页面 中给出提示信息 。如果 用户名或密码错误,也会在登录页面 给出 相应的提示信息。当 已登录的用户 在系统主页中单击 "退出" 链接 时,系统 同样会 回到登录页面

  • 案例整个执行流程 如下图所示 : ( 用户权限验证的执行流程图 ) :

  • 案例具体代码第一步创建项目,导入依赖
    Spring MVC所需JAR (百度网盘)

    第二步应用案例实现用户登录权限验证相关代码文件 :

    User.java

    java 复制代码
    package com.myh.po;
    public class User {
    private Integer id;
        private String username;
        private String password;
    
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public String getUsername() {
            return username;
        }
    
        public void setUsername(String username) {
            this.username = username;
        }
    
        public String getPassword() {
            return password;
        }
    
        public void setPassword(String password) {
            this.password = password;
        }
    }

    UserController.java : (控制器类

    java 复制代码
    package com.myh.controller;
    
    import com.myh.po.User;
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    
    import javax.servlet.http.HttpSession;
    
    @Controller
    public class UserController {
    
        /**
         * 向用户登录页面跳转
         */
        @RequestMapping(value = "/toLogin",method = RequestMethod.GET)
        public String toLogin() {
            return "login";
        }
    
        /**
         * 用户登录
         */
        @RequestMapping(value = "/login",method = RequestMethod.POST)
        public String login(User user, Model model, HttpSession session) { //Model用于传递属性值
            //获取用户名和密码
            String username = user.getUsername();
            String password = user.getPassword();
            //此处模拟从数据库中获取用户名和密码后进行判断
            if (username != null && username.equals("tom") && password != null && password.equals("123")) {
                //将对象添加到Session中
                session.setAttribute("USER_SESSION",user); //存session
                // redirect:/main : 表示用户应被"重定向"到 "/main"的URL(或视图),此处为重定向到/main这个URL
                return "redirect:main"; //重定向到"主页面"的"跳转方法"
            }
            model.addAttribute("msg", "用户名或密码错误,请重新登录!");
            return "login"; //因为没登录成功,所以重新回到login.jsp页面
        }
    
    
        /**
         * 向主页面跳转
         */
        @RequestMapping(value = "/main")
        public String toMain() {
            return "main";
        }
    
        /**
         * 退出登陆
         */
        @RequestMapping(value = "/logout")
        public String logout(HttpSession session) {
            //清除session
            session.invalidate();
            //重定向到"登录页面"的"跳转方法"
            return "redirect:/toLogin";
        }
    }

    LoginInterceptor.java : (拦截器类

    java 复制代码
    package com.myh.interceptor;
    import com.myh.po.User;
    import org.springframework.web.servlet.HandlerInterceptor;
    import org.springframework.web.servlet.ModelAndView;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.HttpSession;
    
    /**
     * 登录拦截器
     */
    public class LoginInterceptor implements HandlerInterceptor {
    
    
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            //获取请求的URL
            String url = request.getRequestURI();
            //url:除了login.jsp可以公开访问的,其他的url都要进行拦截控制
            if ((url.indexOf("/toLogin") >= 0) |(url.indexOf("/login") >= 0) ) { //整体意思: 判断url中是否包含/login(包含则证明是关于"登录的请求",给予放行)
                return true; //只有/login请求才能被放行,其他都要进行拦截 (如果是/login则返回值true,下面的代码就不用执行了)
            }
    
            /**
             * 没有被前面的if语句拦截,说明url请求不是/login,就判断是否已经登录过了(判断session中是否有登录对象数据)
             */
            //获取Session
            HttpSession session = request.getSession();
            User user = (User)session.getAttribute("USER_SESSION");
            //判断Session中是否有用户数据,如果有返回true,继续向下执行
            if (user != null) {
                return true;
            }
            //没被上面的if语句拦截,说明没有进行登录,Session中查不到登录信息,最后转发到登录页面
            request.setAttribute("msg","您还没有登录,请先登录!");
            /*
               调用getRequestDispatcher对象的 .forward(request,response)来进行请求转发,
               将当前的请求对象和响应对象转发到"指定的资源" : /WEB-INF/jsp/login.jsp
             */
            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 {
    
        }
    
        @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception e) throws Exception {
    
        }
    }

    文件preHandle( ) 方法中,先获取了请求的URL ,然后通过indexOf( )方法判断URL中是否 有 "/login" 字符串"/toLogin" 字符串 。如果 ,则返回true ,即 直接放行;如果没有 ,则继续向下进
    行拦截 处理。接下来获取了Session 中的用户信息 ,如果Session 中包含用户信息 ,即表示用户已登录 ,也直接放行 ;否则会转发到登录页面不再执行后续程序

    main.jsp

    html 复制代码
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>系统主页</title>
    </head>
    <body>
    <%-- 用{ }获得存在session中的数据 --%>
     当前用户: ${USER_SESSION.username}
    <a href="${pageContext.request.contextPath}/logout">退出</a>
    </body>
    </html>

    login.jsp :

    html 复制代码
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>用户登录</title>
    </head>
    <body>
    <span style="color: red"> ${msg}</span>
     <form action="${pageContext.request.contextPath}/login" method="post">
         用户名:<input type="text" name="username"></br>
         密&nbsp;&nbsp;码:<input type="password" name="password"/></br>
         <input type="submit" value="登录">
     </form>
    </body>
    </html>

    项目 发布 Tomcat服务器启动,在浏览器中访问地址"http://localhost:8080/main",其显示效果如下图 所示 :

    从上图可以看出,当 用户未登录直接访问主页面 时,访问请求 会被登录拦截器拦截,从而跳转到登录页面 ,并提示用户未登录信息 。如果在用户名输入框 中输入"jack '" ,密码框中输入"123456 ",当单击 "登录 "按钮后,浏览器的显示结果下图 所示 :

    输入正确的用户名tom密码 "123456 ",并单击"登录 "按钮后,浏览器跳转到系统主页面如下图所示

    单击"退出 "链接后,用户即可退出当前系统 ,系统会从主页面重定向到登录页面

相关推荐
hrrrrb1 小时前
【Spring Security】Spring Security 概念
java·数据库·spring
小信丶1 小时前
Spring 中解决 “Could not autowire. There is more than one bean of type“ 错误
java·spring
周杰伦_Jay2 小时前
【Java虚拟机(JVM)全面解析】从原理到面试实战、JVM故障处理、类加载、内存区域、垃圾回收
java·jvm
程序员小凯5 小时前
Spring Boot测试框架详解
java·spring boot·后端
豐儀麟阁贵5 小时前
基本数据类型
java·算法
_extraordinary_6 小时前
Java SpringMVC(二) --- 响应,综合性练习
java·开发语言
程序员 Harry6 小时前
深度解析:使用ZIP流式读取大型PPTX文件的最佳实践
java
wxweven7 小时前
校招面试官揭秘:我们到底在寻找什么样的技术人才?
java·面试·校招
陈陈爱java7 小时前
新知识点背诵
java
失散137 小时前
分布式专题——39 RocketMQ客户端编程模型
java·分布式·架构·rocketmq