当前位置: 首页 > news >正文

HttpServletRequest 和 HttpServletResponse 不同JDK版本的引入

java中,可能会用到JWT令牌校验,
这时,大概率会用到 HttpServletRequest,和 HttpServletResponse

若为 JDK8SpringBoot 2.7.3 的版本则引入:

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

若是 JDK17, SpringBoot 3.4.0 或更高的版本,则为:

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

我出现这个问题的时候,是从哔哩哔哩上找了个项目,打算学习一下,但视频中用的是JDK8,而我用的JDK17,所以在这里记录一下。

拦截器

import cn.hutool.core.util.ObjectUtil;
import com.Jwt工具类.JwtUtil;
import com.ThreadLocal工具类.ThreadLocalUtil;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.common.exception.ServiceException;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import java.util.Map;

/**
 * 拦截器
 */
@RequiredArgsConstructor
@Component //注入到IOC容器里
public class LoginInterceptor implements HandlerInterceptor {

    private final StringRedisTemplate stringRedisTemplate;

    //preHandle : 在……之前处理
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        //令牌验证
        String token = request.getHeader("Authorization");

        //验证 token
        try {
            //从redis中获取相同的token
            ValueOperations<String, String> operations = stringRedisTemplate.opsForValue();

            //根据redis键值对的键,获取对应的值
            String redisToken = operations.get(token);

            if (ObjectUtil.isNull(redisToken)){
                //token失效了
                throw new RuntimeException();
            }

            Map<String, Object> map = JwtUtil.paresToken(token);
            //把业务数据存储到ThreadLocal中
            ThreadLocalUtil.set(map);

            //放行
            return true;
        } catch (Exception e) {
            //http响应状态码401
            response.setStatus(401);

            //不放行
            throw new ServiceException("登录状态已失效,请重新登录");

        }
    }

    //afterCompletion 在……之后处理
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        //清空ThreadLocalUtil中的数据,防止内存泄露
        ThreadLocalUtil.remove();
    }
}

JWT工具类:

import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;

import java.util.Date;
import java.util.Map;

public class JwtUtil {
    private static final String KEY = "event";

    //接受业务数据,生成token并返回
    public static String genToken(Map<String, Object> claims) {
        // 创建 JWT 构建器
        return JWT.create()
                // 将传入的 claims 放入 token 中,键名为 "claims"
                .withClaim("claims", claims)
                // 设置过期时间为 当前时间加 3 小时
                .withExpiresAt(new Date(System.currentTimeMillis() + 1000 * 60 * 60 * 3))
                // 使用 HMAC256 算法,并用 "event" 作为密钥进行签名
                .sign(Algorithm.HMAC256(KEY));

    }

    //接受token, 验证token, 并返回业务数据
    public static Map<String, Object> paresToken(String token) {
        return JWT.require(Algorithm.HMAC256(KEY))
                .build()
                .verify(token)
                .getClaim("claims")
                .asMap();
    }
}

ThreadLocal工具类:

ThreadLocal 用来为每个线程提供独立的变量副本,从而实现线程隔离。使每个线程独立地操作自己的变量副本,而不会影响其他线程的副本。
ThreadLocal 的主要作用是解决多线程环境下共享变量的线程安全问题。它通过为每个线程维护一个独立的变量副本,避免了线程之间的竞争和同步问题。

注意事项

  • 避免滥用:ThreadLocal 适用于线程隔离的场景,但不适合存储大量数据,否则可能会导致内存泄漏。

  • 清理资源:在使用线程池时,务必在任务执行完毕后调用 ThreadLocal.remove(),以防止内存泄漏。

  • 线程池中的问题:如果线程池中的线程被复用,且 ThreadLocal 变量没有被清理,可能会导致数据错乱。

public class ThreadLocalUtil {
    private static final ThreadLocal THREAD_LOCAL = new ThreadLocal();

    //根据键获取值
    public static <T> T get(){
        return (T) THREAD_LOCAL.get();
    }

    //存储键值对
    public static void set(Object value){
        THREAD_LOCAL.set(value);
    }

    //清除ThreadLocal 防止内存泄露
    public static void remove(){
        THREAD_LOCAL.remove();
    }
}
http://www.dtcms.com/a/48539.html

相关文章:

  • 23种设计模式之单例模式(Singleton Pattern)【设计模式】
  • 【三.大模型实战应用篇】【4.智能学员辅导系统:docx转PDF的自动化流程】
  • 基于springboot的丢失儿童的基因比对系统(源码+lw+部署文档+讲解),源码可白嫖!
  • SFP28(25 Gigabit Small Form-factor Pluggable)详解
  • STM32-FOC-SDK包含以下关键知识点
  • 算法基础 -- 字符串哈希的基本概念和数学原理分析
  • Linux常用指令学习笔记
  • 以1.7K深圳小区房价为例,浙大GIS实验室使用注意力机制挖掘地理情景特征,提升空间非平稳回归精度
  • 蓝桥与力扣刷题(蓝桥 k倍区间)
  • JavaScript 系列之:事件
  • 使用Docker搭建Oracle Database 23ai Free并扩展MAX_STRING_SIZE的完整指南
  • C++基础算法:模拟
  • Redis 哨兵模式
  • 本地部署大数据集群前置准备
  • Java中常见的设计模式
  • Qt信号与槽机制
  • 调用的子组件中使用v-model绑定数据以及使用@调用方法
  • 硅基流动前端如何设置tool工具
  • Collab-Overcooked:专注于多智能体协作的语言模型基准测试平台
  • go语言逆向-符号恢复
  • VUE集成Live2d
  • python3使用selenium打开火狐并全屏
  • DeepSeek掘金——DeepSeek-R1图形界面Agent指南
  • LeetCode(必刷75题)151. 反转字符串中的单词——字符串处理
  • 双碳战略下的智慧能源实践:安科瑞储能管理系统助力企业绿色转型
  • Microk8s Ingress实现七层负载均衡
  • 【零基础到精通Java合集】第三集:流程控制与数组
  • Nerf流程
  • Google C++ 开源风格指南
  • 【零基础到精通Java合集】第二集:数据类型与运算符