首页 > 编程语言 >JavaWeb合集17-拦截器(Interceptor)和过滤器(Filter)

JavaWeb合集17-拦截器(Interceptor)和过滤器(Filter)

时间:2024-10-24 16:21:22浏览次数:3  
标签:拦截器 JavaWeb 17 request token 过滤器 response 请求

十七、 拦截器和过滤器

在 Java Web 开发中,拦截器(Interceptor)和过滤器(Filter)都是用于在请求处理前后执行某些操作的机制。虽然它们的功能相似,但在实现方式、使用场景和灵活性方面有一些重要的区别。

1、拦截器和过滤器的区别及选择

1.1 拦截器
  • 定义:拦截器是 Spring 框架提供的一个机制,用于在请求处理前后执行某些操作。它基于 AOP(面向切面编程)的思想。
  • 作用:通常用于处理与业务逻辑相关的操作,如权限校验、日志记录、性能监控等
1.2 过滤器
  • 定义:过滤器是 Servlet 规范中定义的一个接口,用于在请求到达 Servlet 之前或响应离开 Servlet 之后执行某些操作。
  • 作用:通常用于处理与业务逻辑无关的跨切面关注点,如日志记录、认证、编码转换、性能监控等。
1.3 总结

选择使用过滤器还是拦截器,取决于你的具体需求和应用场景。如果你需要处理与业务逻辑无关的通用问题,过滤器是一个不错的选择。

如果你需要处理与业务逻辑相关的操作,特别是当你已经在使用 Spring 框架时,拦截器会更加灵活和强大。

2、拦截器详解

2.1、拦截器三大主要方法

实现了 HandlerInterceptor 接口的类,可以重写三个主要的方法:

  • preHandle:在请求处理之前执行,Controller方法调用之前执行。返回值:返回 boolean 值。如果返回 true,则继续处理请求;如果返回 false,则中断请求处理,不再调用控制器方法和其他拦截器的 postHandle 和 afterCompletion 方法。
  • postHandle:在Controller方法处理之后,但在视图渲染之前执行(返回结果给前端之前执行)。
  • afterCompletion:在整个请求处理完成之后执行(前端已获取到响应结果之后执行)。

执行顺序:preHandle、控制层方法、postHandle、视图渲染、afterCompletion

2.2 三大方法的形参列表

preHandle方法

boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
  1. HttpServletRequest request:当前的 HTTP 请求对象,可以用来获取请求的详细信息,如请求参数、请求头等。
  2. HttpServletResponse response:当前的 HTTP 响应对象,可以用来设置响应头、响应状态码等。
  3. Object handler:处理请求的控制器方法。通常是一个 HandlerMethod 对象,表示具体的控制器方法。可以通过 handler 获取方法上的注解、方法参数等信息。

postHandle方法

void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception;
  1. HttpServletRequest request:当前的 HTTP 请求对象。
  2. HttpServletResponse response:当前的 HTTP 响应对象。
  3. Object handler:处理请求的控制器方法。
  4. ModelAndView modelAndView:控制器方法返回的模型和视图对象。可以用来修改模型数据或视图信息。

afterCompletion 方法

void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception;
  1. HttpServletRequest request:当前的 HTTP 请求对象。
  2. HttpServletResponse response:当前的 HTTP 响应对象。
  3. Object handler:处理请求的控制器方法。
  4. Exception ex:请求处理过程中发生的异常(如果有)。如果没有异常发生,ex 为 null。
2.3、拦截器实现

需要创建一个实现了 HandlerInterceptor 接口的类。可以重写三个主要的方法:preHandle、postHandle、afterCompletion。

1、创建拦截器类,并实现HandlerInterceptor 接口,通过重写三大方法,对请求就行拦截

/**
 * 用户拦截器,用于验证token
 */
@Component    // 交给spring容器管理
@Slf4j       // 日志
public class JwtTokenUserInterceptor implements HandlerInterceptor {


    //重写preHandle, 在请求处理之前进行调用(Controller方法调用之前)
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 获取请求的URL
        String url = request.getRequestURL().toString();
        log.info("请求的URL为:" + url);

        //1、判断当前拦截到的是Controller的方法,还是其他资源或方法,HandlerMethod(控制器类中的方法)
        if (!(handler instanceof HandlerMethod)) {
            // 资源放行(拦截到的不是Controller中的方法,直接放行)
            return true;
        }

        //2、获取token(从请求的请求头中获取到token,token由前端封装到请求头中的,字符串参数"token",与前端传来的要匹配)
        String token = request.getHeader("token");

        //判断请求头是否为空,为空就直接返回提示信息给前端;
        //hasLength方法,验证字符串是否为空或仅为空白字符串(即只包含空格、制表符、换行符等空白字符)
        if (!StringUtils.hasLength(token)) {
            Result result = Result.error("未登录");  //
            //将对象转为json格式字符串
            String jsonStr = JSONObject.toJSONString(result);
            //通过响应体里的输出流来将信息响应给前端
            response.getWriter().write(jsonStr);
            return false;
        }

      //3、判断token是否正确
        try {
            //解析token,只要不报错,就说明token是正确的
            Claims claims=JwtUtil.parseToken(token);
            //将token中的用ID提取出来
            Long userId=Long.parseLong(claims.get("userId").toString());
            //将用户id保存到线程局部变量中,方便后面使用(ThreadLocal)
            BaseContext.setCurrentId(userId);
            return true;
        } catch (Exception e) {

            Result result = Result.error("token无效");
            //将对象转为json格式字符串
            String jsonStr = JSONObject.toJSONString(result);
            //通过响应体里的输出流来将信息响应给前端
            response.getWriter().write(jsonStr);
            return false;
        }
    }
    
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        // 在请求处理之后执行的操作,但在视图渲染之前
        System.out.println("postHandle已执行,在Controller执行之后");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        // 在请求处理完成后执行的操作
        System.out.println("afterCompletion已执行,在响应结果已返回给前端之后");
    }
}

2、注册拦截器:创建配置类,继承WebMvcConfigurationSupport类,注入拦截器,重写addInterceptors方法,添加拦截规则。

/**
 * 配置类,注册web层相关组件,配置拦截器
 */
@Component
public class WebMvcConfiguration extends WebMvcConfigurationSupport {


    @Autowired
    private JwtTokenUserInterceptor jwtTokenUserInterceptor;   // 注入拦截器

    // 注册自定义拦截器,重写addInterceptors方法
    @Override
    protected void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(jwtTokenUserInterceptor)  // 添加拦截器(注入进来的)
                .addPathPatterns("/user/**")          // 拦截路径(请求链接带有user的都拦截)
                .excludePathPatterns("/user/login");  // 放行路径(请求链接是/user/login不拦截)
//        registry.addInterceptor(jwtTokenAdminInterceptor) //如果还有其他拦截器的话,就继续在后面添加即可
//                .addPathPatterns("/admin/**")          // 拦截路径
//                .excludePathPatterns("/admin/login");  // 放行路径

    }
}

3、过滤器详解

3.1 过滤器的三大方法

通过实现 Filter接口,即可实现三大方法

init方法

  • 作用:初始化过滤器,通常用于加载配置信息。
 default void init(FilterConfig filterConfig) throws ServletException { }
  1. FilterConfig filterConfig:提供过滤器的配置信息。

doFilter方法

  • 作用:执行过滤操作。
void doFilter(ServletRequest var1, ServletResponse var2, FilterChain var3) throws IOException, ServletException;
  1. ServletRequest request:当前的 HTTP 请求对象。
  2. ServletResponse response:当前的 HTTP 响应对象。
  3. FilterChain chain:过滤链对象,用于将请求传递给下一个过滤器或目标 Servlet。

destroy 方法

  • 作用:销毁过滤器,通常用于清理资源。
 default void destroy() {}
3.2 过滤器实现

创建一个过滤器工具类,实现Filter 接口,加上注解@WebFilter 配置过滤路径,加上注解@Component将其交给Spring管理,最后重写方法。

@Component
@WebFilter(urlPatterns ="/*")    // 拦截所有请求
public class FilterUtil implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        //先将servletRequest 和 servletResponse对象强制转换为HttpServletRequest和HttpServletResponse对象(要获取链接和token)
        HttpServletRequest request= (HttpServletRequest) servletRequest;
        HttpServletResponse response= (HttpServletResponse) servletResponse;

//        1. 获取请求url。
        String url=request.getRequestURL().toString();
        log.info("请求的URL为:"+url);
//        2. 判断请求url中是否包含login,如果包含,说明是登录操作,放行。
        if(url.contains("/login")){
            filterChain.doFilter(request,response); // 放行
            return;   //放行后就不执行Filter的后面代码了
        }

//        3. 获取请求头中的令牌( token)。
        String token=request.getHeader("token");

//        4. 判断令牌是否存在,如果不存在,返回错误结果(未登录),判断token是否有长度,有true。
        if(!StringUtils.hasLength(token)){
            //没有长度,响应前端错误信息
          Result result=Result.error("Not Login");
            //手动的将对象信息,转换为JSON字符串返回,使用阿里巴巴的fastJSON
            /* <dependency> <groupId>com.alibaba</groupId><artifactId>fastjson</artifactId> <version>1.2.76</version> </dependency>*/
            String errorMsg= JSONObject.toJSONString(result);
            //通过响应体里的输出流来将信息响应给前端
            response.getWriter().write(errorMsg);
            return;
        }

//        5. 解析token,如果解析失败。返回错误结果(未登录)。(校验成功不报错,校验失败会报错)
        try {
            //调用JWT工具类进行jwt校验(解析成功,得到用户数据)
            Claims claims= JwtUtil.parseToken(token);
            //将数据中的ID存储到ThreadLocal中(获取Map对象的属性,转为String,再转为Long)
            BaseContext.setCurrentId(Long.valueOf(claims.get("id").toString()));

        } catch (Exception e) {

            //校验失败,返回错误信息
            Result result=Result.error("Not Login");
            //手动的将对象信息,转换为JSON字符串返回,使用阿里巴巴的fastJSON
            String errorMsg=JSONObject.toJSONString(result);
            //通过响应体里的输出流来将信息响应给前端
            response.getWriter().write(errorMsg);
            return;
        }

//        6. 放行(到这里说明没有报错)。
        filterChain.doFilter(request,response);
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("过滤器初始化");
    }
    
    @Override
    public void destroy() {
        System.out.println("过滤器销毁");
    }
}

标签:拦截器,JavaWeb,17,request,token,过滤器,response,请求
From: https://blog.csdn.net/qq_57340195/article/details/143212364

相关文章

  • JavaWeb合集15-线程局部变量ThreadLocal
    十五、ThreadLocalThreadLocal并不是一个Thread,,而是Thread的局部变量。ThreadLocal为每个线程提供单独一份存储空间,具有线程隔离的效果,只有在线程内才能获取到对应的值,线程外则不能访问。场景:通过过滤器/过滤器获取到JWT,可将JWT值存储到ThreadLocal中,当执行到需要JWT的......
  • Leetcode每日一题:3175. 找到连续赢 K 场比赛的第一位玩家
    题意为给定一个数组,数组头两数比大小,大的放队首,小的放队尾,找到能够连续赢K次的数的编号。思路:如果一轮比较完了,没有赢K次的,那答案就是数组最大值。利用双指针,模拟一轮比较,计算每个数的胜利次数,注意,若起点不是0的话,意味着他和之前的数比较是胜出的,所以初始为1,否则初始为0;1clas......
  • 20222317 2024-2025-1 《网络与系统攻防技术》实验三实验报告
    一、实验内容本次实验目的为通过多次加密、文件格式欺骗、填充、加壳等技术手段实现恶意代码免杀,产生恶意程序,并尝试通过杀毒软件,不被杀毒软件检测出来。具体实验内容如下:1.正确使用msf编码器,使用msfvenom生成如jar之类的其他文件;2.能够使用veil,加壳工具;3.能够使用C+shellcode......
  • GitLab 中文版正式发布最新版本 17.5
    沿袭我们的月度发布传统,极狐GitLab发布了17.5版本,该版本带来了多仓库MR合并时考虑统一主流水线的执行状态(JH-only)、增强的分支规则编辑功能、密钥推送保护已经正式可用等几十个重点功能的改进。下面是部分重点功能的详细解读。关于极狐GitLab的安装升级,可以查看官方指导文......
  • 3175. 找到连续赢 K 场比赛的第一位玩家
    有n位玩家在进行比赛,玩家编号依次为0到n-1。给你一个长度为n的整数数组skills和一个正整数k,其中skills[i]是第i位玩家的技能等级。skills中所有整数互不相同。所有玩家从编号0到n-1排成一列。比赛进行方式如下:队列中最前面两名玩家进行一场比赛,......
  • 【开题报告+论文+源码】基于JavaWeb的中小学心理健康教育平台的设计与实现
    项目背景与意义在当今社会,随着生活节奏的加快和学习压力的增大,中小学生的心理健康问题日益凸显,引起了广泛关注。心理健康不仅关系到学生的个人成长与发展,还对整个社会的和谐稳定具有重要影响。因此,加强中小学生的心理健康教育,提高他们的心理素质,已成为当前教育领域的迫切需求......
  • JavaWeb开发实战详解
    JavaWeb开发在现代应用程序中有广泛的应用场景。以下是一些常见的JavaWeb应用类型及其示例:1.企业级应用特点:通常需要处理大量的数据和用户,具有复杂的业务逻辑,常用于企业内部。示例:客户关系管理(CRM)系统、企业资源计划(ERP)系统。技术栈:SpringFramework、Hibernate、JPA、Th......
  • 极狐GitLab 发布安全补丁版本17.3.3, 17.2.7, 17.1.8, 17.0.8, 16.11.10
    近期,极狐GitLab正式推出安全版本17.3.3,17.2.7,17.1.8,17.0.8,16.11.10,用来减缓安全漏洞CVE-2024-45409带来的安全风险。极狐GitLab正式推出针对GitLabCE老旧版本免费用户的GitLab专业升级服务,可以为老旧版本进行专业升级,避免业务宕机。漏洞详情标题严重等级C......
  • 20222417 2024-2025-1 《网络与系统攻防技术》实验三实验报告
    1.实践内容1.1实验目的(1)正确使用msf编码器,veil-evasion,自己利用shellcode编程等免杀工具或技巧正确使用msf编码器,使用msfvenom生成如jar之类的其他文件veil,加壳工具使用C+shellcode编程(2)通过组合应用各种技术实现恶意代码免杀如果成功实现了免杀的,简单语言描述原理,不......
  • IObit Uninstaller Pro v14.0.0.17 解锁版 (强悍的驱动级软件卸载)
    IObitUninstallerProv14.0.0.17解锁版(强悍的驱动级软件卸载)IObitUninstaller,软件卸载程序。IObitUninstaller是款强悍的驱动级软件卸载工具,有强制卸载、批量卸载、安装监视器、文件粉碎、软件健康检查、卸载Windows更新补丁、移除浏览器工具栏和插件等功能。一、下载地址链......