IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> Spring MVC (三) -> 正文阅读

[Java知识库]Spring MVC (三)

  • 拦截器的定义
  • 拦截器的配置
  • 拦截器的执行流程

一、拦截器的概述

Spring MVC的拦截器(Intercept)与Java Servlet的过滤器(Filter)类型,主要用于拦截用户的请求并做相应的处理,通常在权限验证、记录请求信息的日志、判断用户是否登录等功能上。

1.1 拦截器的定义

在Spring MVC框架中定义一个拦截器需要对拦截器进行定义和配置,定义一个拦截器可以通过两种方式:

  1. 通过实现HandlerInterceptor接口或者继承HandlerInterceptor接口的实现类来定义
  2. 通过实现WebRequestInterceptor或者继承WebRequestInterceptor接口的实现类来定义

比如实现HandlerInterceptor接口:

public class UserInterceptor 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 {

    }
}

实现HandlerInterceptor接口,实现了接口中的3种方法:

  • preHandle 方法:该方法在控制器的处理请求方法前执行,其返回值表示是否中断后续操作,返回true表示继续向下执行,返回false表示中断后续操作。
  • postHandle 方法:该方法在控制器的处理请求调用之后、解析视图之前执行,可以通过此方法对请求域中的模型和视图做进一步的修改。
  • afterCompletion 方法:该方法在控制器的处理请求方法执行完成后执行,即视图渲染结束后执行,可以通过此方法实现一些资源清理、记录日志信息等工作。

1.2 拦截器的配置

自定义拦截器生效需要在Spring MVC的配置文件中进行配置。

 <!--配置拦截器-->
    <mvc:interceptors>
        <!--配置一个全局拦截器,拦截所有请求-->
        <bean class="main.java.springmvc.utils.UserInterceptor"/>
        <mvc:interceptor>
            <!--配置拦截器作用的路径-->
            <mvc:mapping path="/**"/>
            <!--配置不需要拦截器作用的路径-->
            <mvc:exclude-mapping path=""/>
            <!--定义在 <mvc:interceptor>元素中,表示匹配指定路径的请求才进行拦截-->
            <bean class=""
        </mvc:interceptor>
    </mvc:interceptors>
  • <mvc:interceptors> 用于配置一组拦截器
  • <bean >定义的是全局拦截器,拦截所有请求
  • <mvc:interceptor>指定路径的拦截器,顺序不能变!

二、拦截器的执行流程

2.1 单个拦截器的执行流程

1. 准备拦截器类


/**
 * @author xry
 */
public class UserInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("preHandle方法控制器的处理请求方法前执行");
        return false;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("postHandle方法在控制器的处理请求调用之后、解析视图之前执行");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("afterCompletion方法在控制器的处理请求方法执行完成后执行");
    }
}

2. 在springmvc配置文件中配置单个拦截器

<!--配置拦截器-->
    <mvc:interceptors>
        <!--配置一个全局拦截器,拦截所有请求-->
        <bean class="main.java.springmvc.utils.interceptor.UserInterceptor"/>
    </mvc:interceptors>

3. 编写测试界面

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>测试拦截器执行流程</title>
</head>
<body>
视图
<% System.out.println("视图渲染结束。");%>
</body>
</html>

4. 编写控制器,请求跳转至测试界面


/**
 * @author xry
 */

@Controller
public class TestInterceptor {

    @RequestMapping("/toTestInterceptor")
    public String test() {
        System.out.println("正在测试拦截器,执行控制器的处理请求方法中");
        return "testinterceptor";
    }
}

5. 结果

  • 如果拦截器实现类实现的preHandle方法返回false
    *
    可以看出结果只执行了拦截器实现类中的preHandle,后续操作已经被中断。

  • 如果如果拦截器实现类实现的preHandle方法返回true

在这里插入图片描述

从结果可以看出执行流程,单个拦截器中首先执行拦截器中的preHandle方法,方法返回true,程序继续执行控制器中处理请求的方法,然后在返回视图前执行postHandle方法,返回视图后才执行afterCompletion方法。

2.2 多个拦截器的执行了流程

1. 在创建两个两个拦截器Interceptor1 和Interceptor2


/**
 * @author xry
 */
public class Interceptor1 implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("Interceptor1 preHandle方法执行中");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("Interceptor1 postHandle方法执行中");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("Interceptor1 afterCompletion方法执行中");
    }
}

2. springmvc配置文件中配置多个拦截器

 <!--配置拦截器-->
    <mvc:interceptors>
        <!--配置一个全局拦截器,拦截所有请求-->
       <!-- <bean class="main.java.springmvc.utils.interceptor.UserInterceptor"/>-->
        <mvc:interceptor>
            <!--配置拦截器作用的路径-->
            <mvc:mapping path="/**"/>
            <!--配置不需要拦截器作用的路径-->
            <!--<mvc:exclude-mapping path=""/>-->
            <!--定义在 <mvc:interceptor>元素中,表示匹配指定路径的请求才进行拦截-->
            <bean class="main.java.springmvc.utils.interceptor.Interceptor1"/>
        </mvc:interceptor>
        <mvc:interceptor>
            <!--拦截所有以/toTestInterceptor结尾的路径-->
            <mvc:mapping path="/toTestInterceptor"/>
            <bean class="main.java.springmvc.utils.interceptor.Interceptor2"/>
        </mvc:interceptor>
    </mvc:interceptors>

3. 访问请求进行测试

在这里插入图片描述

由结果可知,在程序中有多个拦截器同时工作时,他们的preHandle方法按照配置文件中拦截器的配置顺序执行,而postHandle方法、afterCompletion方法按照反序执行。

三、简单实例–用户登陆权限验证

1. 创建实体类User

/**
 * @author xry
 */
public class User {
    private String name;
    private String password;
    //省略getter和setter
}

2. 创建服务层UserService接口和实现类

/**
 * @author xry
 */
public interface UserService {
    public Boolean isLogin(User user);
}

@Service
public class UserServiceImpl implements UserService {
    @Override
    public Boolean isLogin(User user) {
        if ("zhangsan".equals(user.getName()) && "123456".equals(user.getPassword())){
            return true;
        }else {
            return false;
        }
    }
}

3. 编写控制器类

@Controller
//类级别注解
@RequestMapping(value = "/index")
public class UserContrloller /*extends BaseController*/{

    @Autowired
    private UserService userService;

    private static final Log logger = LogFactory.getLog(UserContrloller.class);


   @RequestMapping("/isLogin")
    public String isLogin(User user, Model model, HttpSession session) {
        if (userService.isLogin(user)){
            session.setAttribute("user",user);
            logger.info("登陆成功");
            return "redirect:/index/toSuccess";
        }else {
            logger.info("登陆失败");
            model.addAttribute("loginfail", "用户名或密码错误,请重新登陆");
            return "login";
        }
    }

    //注销
    @RequestMapping(value = "/toLogout")
    public String logout(HttpSession session) {
        session.invalidate();
        return "login";
    }

    // 方法级别注解,登录界面
    @RequestMapping(value = "/toLogin")
    public String toLogin() {
        return "login";
    }

    //调到成功界面
    @RequestMapping(value = "/toSuccess")
    public String toSuccess() {
        return "loginsuccess";
    }
}

4. 前端登陆界面和登陆成功界面

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>登陆界面</title>
</head>
<body>
<form action="${pageContext.request.contextPath}/index/isLogin" method="post">
    <table>
        <tr>
            <td colspan="2"> 登陆界面 </td>
        </tr>
        <tr>
            <td>用户名: <input type="text" name="name" placeholder="请输入用户名"/> </td>
            <td> 密码:<input type="password" name="password"  placeholder="请输入密码"/> </td>
        </tr>

        <tr>
           <td colspan="2"> <input type="submit" value="登陆"> </td>
        </tr>
    </table>

    ${msg}
    ${loginfail}
</form>
</body>
</html>

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>login success</title>
</head>
<body>
hello ${user.name}  欢迎回来<br>
<a href="${pageContext.request.contextPath}/index/toLogout">退出</a>

</body>
</html>

5. 登录拦截器

public class LoginInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //获取请求的url
        StringBuffer url = request.getRequestURL();

        //登录请求或者login.jsp放行,不拦截
        if(url.indexOf("/toLogin")>=0 || url.indexOf("/isLogin")>=0){
            return true ;
        }

        //获取session
        HttpSession session = request.getSession();
        Object obj = session.getAttribute("user");
        if (obj != null) {
            return true;
        }

        //没有登录且不是登录界面,转发到登录界面,并给出错误提示
        request.setAttribute("msg", "没有登录,请先登录");
        request.getRequestDispatcher("/WEB-INF/pages/login.jsp").forward(request, response);
        return false;
    }
}

6. springmvc配置文件中配置拦截器

<!--配置拦截器-->
    <mvc:interceptors>
        <mvc:interceptor>
            <!--配置拦截器的路径-->
            <mvc:mapping path="/**"/>
            <bean class="main.java.springmvc.utils.interceptor.LoginInterceptor"/>
        </mvc:interceptor>
    </mvc:interceptors>

7. 结果查看

登录界面,放行进行登陆

在这里插入图片描述

登陆请求isLogin放行,转到登录成功界面:

在这里插入图片描述

退出到登陆界面,退出前session值还有存在:

在这里插入图片描述

退出后session值注销掉,直接访问成功界面效果:

在这里插入图片描述

至此,简单的登录权限验证拦截器完成

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-02-27 10:57:09  更:2022-02-27 10:57:56 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 11:26:04-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码