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 ",并单击"登录 "按钮后,浏览器跳转到系统主页面如下图所示

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

相关推荐
工业3D_大熊4 分钟前
【虚拟仿真】CEETRON SDK在船舶流体与结构仿真中的应用解读
java·python·科技·信息可视化·c#·制造·虚拟现实
lzb_kkk12 分钟前
【JavaEE】JUC的常见类
java·开发语言·java-ee
爬山算法36 分钟前
Maven(28)如何使用Maven进行依赖解析?
java·maven
小春学渗透1 小时前
Day107:代码审计-PHP模型开发篇&MVC层&RCE执行&文件对比法&1day分析&0day验证
开发语言·安全·web安全·php·mvc
陈大爷(有低保)1 小时前
三层架构和MVC以及它们的融合
后端·mvc
河西石头1 小时前
一步一步从asp.net core mvc中访问asp.net core WebApi
后端·asp.net·mvc·.net core访问api·httpclient的使用
2401_857439691 小时前
SpringBoot框架在资产管理中的应用
java·spring boot·后端
怀旧6661 小时前
spring boot 项目配置https服务
java·spring boot·后端·学习·个人开发·1024程序员节
李老头探索1 小时前
Java面试之Java中实现多线程有几种方法
java·开发语言·面试
芒果披萨1 小时前
Filter和Listener
java·filter