1.代码展示
P9 07:09:如何让Authorization直接保存
UserController:
//获取用户信息@GetMapping("/userInfo")public Result<User> userInfo(@RequestHeader(name="Authorization") String token){//根据token得到usernameMap<String,Object> map=JwtUtil.parseToken(token);String username= (String) map.get("username");//输出完整信息User user=userService.findByUserName(username);return Result.success(user);}
问题:把password也响应了,不安全
修改:
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Data;import java.time.LocalDateTime;
@Data
public class User {private Integer id;//主键IDprivate String username;//用户名@JsonIgnore//当前对象转变为json字符串时,忽略password,最终的json 字符串就无password这个属性private String password;//密码private String nickname;//昵称private String email;//邮箱//驼峰命名,表中是下划线命名private String userPic;//用户头像地址private LocalDateTime createTime;//创建时间private LocalDateTime updateTime;//更新时间
举例:若createTime,updateTime值为空(和nickname,email)一样,原因:类中是驼峰命名,数据库表中是下划线命名
可在application.yml中添加:
mybatis:configuration:map-underscore-to-camel-case: true//开启驼峰命名,下划线命名的自动转换
2.优化
1.ThreaLocal
1.存取数据:set,get()
2.ThreadLocal存储数据,线程安全
3.最后用remove()释放
4.ThreadLocal
是一个工具,它可以让每个线程都有自己的“小盒子”,用来放一些数据。这些数据是每个线程自己用的,不会被其他线程看到或修改。
5.过程:创建(set,get,remove())->拦截器中调用set->Controller中调用get->拦截器中调用remove->运行
6.举例理解:
package com.itheima.springbootconfigfile.controller;import org.junit.jupiter.api.Test;
//获取用户对象->优化
public class ThreadLocalTest {@Testpublic void testThreadLocalSetAndGet(){//两个线程,是一个ThreadLocal对象,但线程隔离ThreadLocal tl=new ThreadLocal();new Thread(()->{tl.set("che");System.out.println(Thread.currentThread().getName()+":"+tl.get());System.out.println(Thread.currentThread().getName()+":"+tl.get());System.out.println(Thread.currentThread().getName()+":"+tl.get());},"红色").start();new Thread(()->{tl.set("xing");System.out.println(Thread.currentThread().getName()+":"+tl.get());System.out.println(Thread.currentThread().getName()+":"+tl.get());System.out.println(Thread.currentThread().getName()+":"+tl.get());},"黄色").start();}
}
两个线程,是一个ThreadLocal对象,但线程隔离
2.代码展示:
package com.itheima.springbootconfigfile.utils;import java.util.HashMap;
import java.util.Map;/*** ThreadLocal 工具类*/
@SuppressWarnings("all")
public class ThreadLocalUtil {//提供ThreadLocal对象,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();}
}
UserController:
//获取用户信息@GetMapping("/userInfo")public Result<User> userInfo(/*@RequestHeader(name="Authorization") String token*/){//根据token得到username
// Map<String,Object> map=JwtUtil.parseToken(token);
// String username= (String) map.get("username");//根据ThreadLocal.get得到全部数据,输出给map,根据key为username,得到对应的valueMap<String,Object> map=ThreadLocalUtil.get();String username= (String) map.get("username");//输出完整信息User user=userService.findByUserName(username);return Result.success(user);}
拦截器相关(注册拦截器,设置拦截器): SpringBoot速成(八)登录实战:未登录不能访问 P5-P8-CSDN博客
拦截器:
package com.itheima.springbootconfigfile.interceptors;import com.itheima.springbootconfigfile.utils.JwtUtil;
import com.itheima.springbootconfigfile.utils.ThreadLocalUtil;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;import java.util.Map;//设置拦截器
@Component
public class LoginInterceptor implements HandlerInterceptor {//token验证@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {//得到tokenString token=request.getHeader("Authorization");//验证tokentry {//获取数据Map<String,Object> claims= JwtUtil.parseToken(token);//把数据存储到ThreadLocal中ThreadLocalUtil.set(claims);return true;}catch (Exception e){response.setStatus(401);return false;}}//用完释放,清空ThreadLocal中的数据@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {ThreadLocalUtil.remove();}
}