• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录

冬日限定

  • 博客园
  • 联系
  • 订阅
  • 管理

公告

View Post

第15章 拦截器

学习目标
● 了解拦截器定义和配置方式
● 熟悉拦截器的执行流程
● 掌握拦截器的使用
15.1 拦截器概述
Spring MVC中的拦截器(Interceptor)类似于Servlet中的过滤器(Filter),它主要用于拦截用户请求并做相应的处理。
用途:权限验证、记录请求信息的日志、判断用户是否登录等。
15.1.1 拦截器的定义
1.实现HandlerInterceptor接口,或继承HandlerInterceptor接口的实现类(如HandlerInterceptorAdapter)
2.实现WebRequestInterceptor接口,或继承WebRequestInterceptor接口的实现类来定义。
public class CustomInterceptor implements HandlerInterceptor{ 
    @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception { 
        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 ex) throws Exception { 
    } 
}
preHandler()方法:该方法会在控制器方法前执行,其返回值表示是否中断后续操作。
postHandle()方法:该方法会在控制器方法调用之后,且解析视图之前执行。用途:对请求域中的模型和视图做出进一步的修改。
afterCompletion()方法:该方法会在整个请求完成,即视图渲染结束之后执行。用途:资源清理、记录日志信息
15.1.2 拦截器的配置
<! -- 配置拦截器 --> 
<mvc:interceptors> 
    <! --使用bean直接定义在<mvc:interceptors>下面的Interceptor将拦截所有请求--> 
    <bean class="com.itheima.interceptor.CustomInterceptor"/> 
    <! -- 拦截器1--> 
    <mvc:interceptor> 
        <! -- 配置拦截器作用的路径 --> 
        <mvc:mapping path="/**"/> 
        <! -- 配置不需要拦截器作用的路径 --> 
        <mvc:exclude-mapping path=""/> 
        <! -- 定义在<mvc:interceptor>下面的,表示对匹配路径的请求才进行拦截--> 
        <bean class="com.itheima.interceptor.Interceptor1" /> 
    </mvc:interceptor> 
    <! -- 拦截器2--> 
    <mvc:interceptor> 
        <mvc:mapping path="/hello"/> 
        <bean class="com.itheima.interceptor.Interceptor2" /> 
    </mvc:interceptor> 
    ... 
</mvc:interceptors>
<mvc:interceptors>元素用于配置一组拦截器,其子元素<bean>中定义的是全局拦截器,它会拦截所有的请求;而<mvc:interceptor>元素中定义的是指定路径的拦截器,它会对指定路径下的请求生效。
<mvc:interceptor>中的子元素必须按照上述代码的配置顺序进行编写,即<mvc:mapping …/>→<mvc:exclude-mapping … />→<bean … />的顺序
15.2 拦截器的执行流程
15.2.1 单个拦截器的执行流程
1.jar包
2.web.xml配置
3.controller层
4.拦截器类,实现HandlerInterceptor接口并且重写方法
5.springmvc-config.xml
<!--    配置拦截器-->
    <mvc:interceptors>
        <bean class="com.itheima.interceptor.CustomInterceptor"/>
    </mvc:interceptors>
6.success.jsp
7.启动服务器
问题:实现了HandlerInterceptor没有提示重写方法
原因:HandlerInterceptor中的方法是default修饰的
Java 8中引入了一个新的概念,叫做default方法,也可以称为Defender方法,或者虚拟扩展方法(Virtual extension methods)。
Default方法是指,在接口内部包含了一些默认的方法实现(也就是接口中可以包含方法体,这打破了Java之前版本对接口的语法限制),从而使得接口在进行扩展的时候,不会破坏与接口相关的实现类代码。
那怎么重写preHandle()方法呢?
Ctrl+O组合键
本机 alt+shift+T
简单界面出现404,检查requestMapping的value值写对没,检查controller层注解
15.2.2 多个拦截器的执行流程
preHandle()方法:顺序
postHandle()方法和afterCompletion()方法:反序
1.写两个interceptor方法
2.springmvc-config.xml配置
<mvc:interceptor>
    <mvc:mapping path="/**"/>
    <bean class="com.itheima.interceptor.Interceptor1"/>
</mvc:interceptor>
<mvc:interceptor>
    <mvc:mapping path="/hellointercpetor"/>
    <bean class="com.itheima.interceptor.Interceptor2"/>
</mvc:interceptor>
15.3 应用案例——实现用户登录权限验证
执行流程
1.User类
2.UserController
@Controller
public class UserController {
    /*
    向用户登录页面跳转
     */
    @RequestMapping(value = "/login",method = RequestMethod.GET)
    public String toLogin(){
        return "login";
    }
    /*
        用户登录
     */
    @RequestMapping(value = "/login",method = RequestMethod.POST)
    public String login(User user, Model model, HttpSession session){
//        获取用户名和密码
        String username = user.getUsername();
        String password = user.getPassword();
//此处模拟从数据库中获取用户名和密码后进行判断
        if(username != null && password.equals("123456")){
//            将用户对象添加到Session
            session.setAttribute("USER_SESSION",user);
            return "redirect:main";
 
 
 
 
        }
        model.addAttribute("msg","用户名或密码错误,请重新登陆!");
        return "login";
    }
 
 
 
 
    /*
         向用户主页面跳转
     */
    @RequestMapping(value = "/main")
    public String toMain(){
        return "main";
    }
    /*
           退出登录
     */
    @RequestMapping("/logout")
    public String logout(HttpSession session){
//        清除Session
        session.invalidate();
//        重定向到登录页面的跳转方法
        return "redirect:login";
    }
}
跳转到登录页面接收的是GET方式提交的方法,而用户登录接收的是POST方式提交的方法
3.拦截器类LoginInterceptor
public class LoginInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("CustomInterceptor  preHandle");
//        获取请求的URL
        String url = request.getRequestURI();
//        URL:除了login.jsp是可公开访问的,其他的URL都进行拦截控制
        if(url.indexOf("/login")>=0){
            return true;
        }
//        获取Session
        HttpSession session = request.getSession();
        User user = (User) session.getAttribute("USER_SESSION");
//        判断Session中是否有用户数据 如果有则返回true继续向下执行
 
 
        if(user != null){
            return true;
        }
        request.setAttribute("msg","您还没有登录,请先登录");
        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 {
        System.out.println("CustomInterceptor postHandle");
    }
 
 
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("CustomInterceptor  afterCompletion");
 
    }
 
}
4.springmvc-config.xml
<mvc:interceptor>
    <mvc:mapping path="/**"/>
    <bean class="com.itheima.interceptor.LoginInterceptor"/>
</mvc:interceptor>
5.main.jsp
<head>
    <title>系统主页</title>
</head>
<body>
    当前用户:${USER_SESSION.username}
    <a href="${pageContext.request.contextPath }/logout">退出</a>
 
 
</body>
6.login.jsp
<head>
    <title>用户登录</title>
</head>
<body>
    ${msg}
    <form action="${pageContext.request.contextPath }/login" method="post">
        用户名:<input type="text" name="username"><br/>
        密&nbsp;&nbsp;&nbsp;码:<input type="password" name="password"><br/>
        <input type="submit" value="登录">
    </form>
 
 
</body>
7.启动服务器
 
URI是什么?
String、StringBuffer和StringBuilder的区别?
Session相关 getAttribute方法
pageContext.request.contextPath是什么?
什么时候需要用重定向?
 
【思考题】
1.请简述Spring MVC拦截器的定义方式。
在springmvc-config里添加<mvc:interceptors>标签,定义全局拦截器
<mvc:interceptor>标签配置自定义拦截器。
配置顺序必须是mapping exclude bean 标签
<mvc:inteceptors>
    ……
    <mvc:inteceptor>
    ……
    </mvc:intecptor>
</mvc:inteceptors>
2.请简述单个拦截器和多个拦截器的执行流程。
单个拦截器
prehandler
handle
posthandler
dispatcherservlet
afterhander
多个拦截器
按照配置顺序,prehandeler顺序执行,posthandler和afterhandler逆序执行
 
 

posted on 2023-04-25 02:01  冬日限定  阅读(41)  评论(0)    收藏  举报

刷新页面返回顶部
 
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3