zoukankan      html  css  js  c++  java
  • SprimgMVC学习笔记(十)—— 拦截器

    一、 什么是拦截器?

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

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

    public class HandlerInterceptor1 implements HandlerInterceptor {
        // controller执行后且视图返回后调用此方法
        // 这里可得到执行controller时的异常信息
        // 这里可记录操作日志
        @Override
        public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
                throws Exception {
            System.out.println("HandlerInterceptor1....afterCompletion");
        }
    
        // controller执行后但未返回视图前调用此方法
        // 这里可在返回用户前对模型数据进行加工处理,比如这里加入公用信息以便页面显示
        @Override
        public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
                throws Exception {
            System.out.println("HandlerInterceptor1....postHandle");
        }
    
        // Controller执行前调用此方法
        // 返回true表示继续执行,返回false中止执行
        // 这里可以加入登录校验、权限拦截等
        @Override
        public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception {
            System.out.println("HandlerInterceptor1....preHandle");
            // 设置为true,测试使用
            return true;
        }
    }

     二、拦截器配置

      上面定义的拦截器再复制一份HandlerInterceptor2,注意新的拦截器修改代码:

    System.out.println("HandlerInterceptor2....preHandle");

      在springmvc.xml中配置拦截器:

      <mvc:interceptors>
            <mvc:interceptor>
                <!-- 所有请求都进入拦截器 -->
                <mvc:mapping path="/**"/>
                <!-- 配置具体的拦截器 -->
                <bean class="cn.itcast.ssm.interceptor.HandlerInterceptor1"></bean>
            </mvc:interceptor>
            <mvc:interceptor>
                <!-- 所有请求都进入拦截器 -->
                <mvc:mapping path="/**"/>
                <!-- 配置具体的拦截器 -->
                <bean class="cn.itcast.ssm.interceptor.HandlerInterceptor2"></bean>
            </mvc:interceptor>
        </mvc:interceptors>

     三、测试

    3.1 正常流程测试

      浏览器访问地址:http://127.0.0.1:8080/springmvc-web/itemList.action

      控制台打印:

      

    3.2 中断流程测试

      浏览器访问地址:http://127.0.0.1:8080/springmvc-web/itemList.action

      HandlerInterceptor1的preHandler方法返回false,HandlerInterceptor2返回true:

       

      HandlerInterceptor1的preHandler方法返回true,HandlerInterceptor2返回false:

       

    3.3 结果分析

      从日志看出第一个拦截器的preHandler方法返回false后第一个拦截器只执行了preHandler方法,其它两个方法没有执行,第二个拦截器的所有方法不执行,且Controller也不执行了。

      第二个拦截器的preHandler方法返回false后第一个拦截器的postHandler没有执行,第二个拦截器的postHandler和afterCompletion没有执行,且controller也不执行了。

      总结:

      preHandle按拦截器定义顺序调用

      postHandler按拦截器定义逆序调用

      afterCompletion按拦截器定义逆序调用

      postHandler在拦截器链内所有拦截器返成功调用

      afterCompletion只有preHandle返回true才调用

    四、拦截器应用

    4.1 处理流程

      1、有一个登录页面,需要写一个Controller访问登录页面

      2、登录页面有一提交表单的动作。需要在Controller中处理。

        a) 判断用户名密码是否正确(在控制台打印)

        b) 如果正确,向session中写入用户信息(写入用户名username)

        c) 跳转到商品列表

      3、拦截器

        a) 拦截用户请求,判断用户是否登录(登录请求不能拦截)

        b) 如果用户已经登录。放行

        c) 如果用户未登录,跳转到登录页面。

    4.2 编写登录jsp

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Insert title here</title>
    </head>
    <body>
    
    <form action="${pageContext.request.contextPath }/user/login.action">
    <label>用户名:</label>
    <br>
    <input type="text" name="username">
    <br>
    <label>密码:</label>
    <br>
    <input type="password" name="password">
    <br>
    <input type="submit">
    
    </form>
    
    </body>
    </html>

    4.3 用户登录Controller

    @Controller
    @RequestMapping("user")
    public class UserController {
        
        /**
         * 跳转到登录页面
         * @return
         */
        @RequestMapping("toLogin")
        public String toLogin(){
            return "login";
        }
        
        @RequestMapping("login")
        public String login(String username,String password,HttpSession session){
            // 校验用户登录
            System.out.println(username);
            System.out.println(password);
            
            // 把用户放到session中
            session.setAttribute("username", username);
            
            return "redirect:/item/itemList.action";
        }
    }

    4.4 编写拦截器

    public class LoginHandlerInterceptor implements HandlerInterceptor {
    
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object obj) throws Exception {
            // 从request中获取session
            HttpSession session = request.getSession();
            // 从session中获取username
            Object username = session.getAttribute("username");
            // 判断username是否为null
            if(username != null){
                // 如果不为空,则放行
                return true;
            }else{
                // 如果为空则跳转到登录页面
                response.sendRedirect(request.getContextPath() + "/user/toLogin.action");
            }
            return false;
        }
        
        @Override
        public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
                throws Exception {
        }
    
        @Override
        public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
                throws Exception {
        }
    
    }

    4.5 配置拦截器

      只能拦截商品的url,所以需要修改ItemController,让所有的请求都必须以item开头,如下图:

      

      在springmvc.xml配置拦截器:

    <mvc:interceptor>
        <!-- 配置商品被拦截器拦截 -->
        <mvc:mapping path="/item/**" />
        <!-- 配置具体的拦截器 -->
        <bean class="cn.itcast.ssm.interceptor.LoginHandlerInterceptor" />
    </mvc:interceptor>
  • 相关阅读:
    15. DML, DDL, LOGON 触发器
    5. 跟踪标记 (Trace Flag) 834, 845 对内存页行为的影响
    4. 跟踪标记 (Trace Flag) 610 对索引组织表(IOT)最小化日志
    14. 类似正则表达式的字符处理问题
    01. SELECT显示和PRINT打印超长的字符
    3. 跟踪标记 (Trace Flag) 1204, 1222 抓取死锁信息
    2. 跟踪标记 (Trace Flag) 3604, 3605 输出DBCC命令结果
    1. 跟踪标记 (Trace Flag) 1117, 1118 文件增长及空间分配方式
    0. 跟踪标记 (Trace Flag) 简介
    SpringBoot + Redis + Shiro 实现权限管理(转)
  • 原文地址:https://www.cnblogs.com/yft-javaNotes/p/10216867.html
Copyright © 2011-2022 走看看