第四章 1SpringMVC拦截器

zhanglei 2022年06月17日 313次浏览

4.0 准备工作

建一个web 工程,在src/main/java下创建包com/zhanglei/controller,interceptor,在web 目录下创建 jsp 目录:

image-20220617212100324

编写 index.jsp:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
  <title>$Title$</title>
</head>
<body>
  <form action="zhanglei" method="post">
    姓名:<input type="text" name="name"/></br>
    年龄:<input type="text" name="age"/></br>
    <input type="submit" value="提交">
  </form>
</body>
</html>

在 controller下创建一个控制器类:

package com.zhanglei.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Controller //要在springmvc配置文件中 配置注解扫描器
public class HelloController{
    @RequestMapping("/zhanglei")
    public String doController(HttpServletRequest h,String name,String age){
        System.out.println("====控制器的doController方法执行====");
        h.setAttribute("myname",name);
        h.setAttribute("myage",age);
        return "Hello";//要在springmvc配置文件中配 置视图解析器
    }
}

目的跳转页面 Hello.jsp:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>跳转页面</title>
</head>
<body>
        接收的参数为:</br>
        name:${myname} </br>
        age:${myage}

</body>
</html>

maven依赖pom.xml、web.xml、springmvc.xml 的配置

springmvc 常用配置 - ZhangLeiのWorld (zhangleistudy.com)

4.1 拦截器概述

​ 拦截器时 springmvc 中的一种,需要实现 HandlerInterceptor 接口。

​ 拦截器和过滤器类似,功能方向侧重点不同。过滤器是用来过滤请求参数,设置编码字符集等工作。拦截器时拦截用户的请求,对请求做判断处理的。

​ 拦截器是全局的,可以对多个Controller 做拦截。一个项目可以有0个或者多个拦截器,他们在一起拦截用户的请求。

​ 拦截器常用在:用户登录处理,权限检查

4.2 拦截器使用步骤

4.2.1 定义类实现 HandlerInterceptor 接口

​ 定义一个类实现 HandlerInterceptor 接口,并重写接口的三个方法:

package com.zhanglei.interceptor;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class MyInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("MyInterceptor 的 preHandle 方法");

        //设置为tue 说明使他验证通过,请求交给处理器方法可以执行
        return true;
    }

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

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

preHander 方法特点:(重点使用这个方法)

​ 实在控制器方法(MyController 的doSome)之前先执行的。用户的请求首先到达此方法。preHander 方法有一个boolean 类型的返回值,true:请求通过了拦截器的验证,交给控制器处理,false:请求被拦截器拦截。

​ 可以验证用户是否登录,验证用户是否有权限访问某个地址(url)。

​ 如果验证失败,可以截断请求,请求不能被控制器处理;

​ 如果验证成果,可以放行请求,此时控制器才能处理。

postHandler 方法特点:

​ postHandler 方法在控制器方法(MyController 的doSome)之后执行的

afterCompletion方法特点:

​ afterCompletion 方法在请求处理完之后执行的,就是在执行完forward 转发之后,就认为请求处理完成。

4.2.2 在 springmvc 配置文件中声明拦截器(如上)

​ 在springmvc 配置文件中声明 注解扫描器,声明 拦截器并指定所拦截请求的 uri 地址。

4.3 拦截器演示

​ 由于springmvc.xml 中拦截器的声明如下:

image-20220617213854081

​ 可以理解为,拦截器的 preHandler 方法就是门卫,controller 方法就是小区内,/**意思是只要人请求通过小区门,均会被 MyInterceptor 拦截器拦下检查健康码,这一步骤就是验证,如果验证通过了(即 preHandler 方法返回值是 true),那么放行该请求,请求交给 controller 处理;反之,拒绝该请求,请求就不会交给 controller 处理器处理(人进不了小区内)

​ 未测试方便,在我自定义的拦截器 MyInterceptor 内,preHander 方法返回值 设为 true,意思是拦截下来的请求均通过拦截器验证,移交给 controller 控制器处理,实际可以写一些逻辑,如 if…return true; else…return false 。

image-20220617214806832

4.3.1 验证拦截器(preHandler 方法返回值设为true)

​ 集成 tomcat,启动tomcat,访问项目地址:

image-20220617215205483

​ 点击提交

image-20220617215336073

​ 此时看控制台!!!:

image-20220617215452899

4.3.2 再验证拦截器(preHandler 方法返回值设为false)

​ preHandler 方法返回值设为false: 意思是先拦截所有请求( 因为mapping path="/"),然后拒绝所有请求,请求不会被移交给 controller 控制器处理。**

image-20220617215945420

​ 重新启动 tomcat,输入项目地址,到首页后输入值(跟上面一样):

image-20220617220125555

​ 点击提交:

image-20220617220220879

由于在 Hello.jsp显示数据的代码实在 controller 控制器内实现的,如下:

image-20220617220400758

但是拦截器 “门卫方法” preHandler 返回值为 false,因此,请求不会被controller 处理,因此这时Hello.jsp 数据为空;同时,控制台只有门卫方法执行了!!:

image-20220617220643153

4.4 拦截器原理图示总结

image-20220618102325939

补充拦截器和过滤器的区别:

​ 1.过滤器是Servlet 中的对象 ,拦截器是框架中的对象

​ 2.过滤器是实现 Filter 接口的对象,拦截器是实现 HandlerInterceptor

​ 3.过滤器是用来设置 request,response的参数,属性的,侧重于对数据的过滤。而拦截器是用来验证请求的,能截断请求,也能放行请求。

​ 4.过滤器在拦截器之前执行

​ 5.过滤器只有一个执行时间点,而拦截器有三个执行时间点

​ 6.过滤器可以处理jsp,js,html等等,而拦截器侧重拦截请求:使用拦截器的前提是,你的请求必须要被中央调度器 DispatcherServlet 接收,如果不被中央调度器接收,请求无意义,只会出现404错误。