获取用户信息功能

总说

过程参考黑马程序员SpringBoot3+Vue3全套视频教程,springboot+vue企业级全栈开发从基础、实战到面试一套通关_哔哩哔哩_bilibili

目录

总说

一、基本功能实现

1.1 controller层

1.2 测试接口

1.3 调整apifox

1.4 不返回密码

1.5 mabits命名映射

二、代码优化

2.1 代码优化


一、基本功能实现

1.1 controller层

进入我们的UserController,我们再写一个方法

代码如下:

//获取用户信息
    //@RequestHeader(name = "Authorization") 是从请求头中获取Authorization的值
    @GetMapping("/userInfo")
    public Result<User> userInfo(@RequestHeader(name = "Authorization") String token) {
        //根据用户名查询用户
        Map<String, Object> map = JwtUtil.parseToken(token);//传入token 解析token
        String username = (String) map.get("username");//获取用户名
        User user = userService.findByUserName(username);//返回一个查找到的User对象
        return Result.success(user);
    }

service、impl、mapper层的方法我们之前登录的时候写过了。

1.2 测试接口

直接进行测试

先不传任何参数,会得到401,因为我们没有请求头,它获取不到参数

所以,我们先通过登录接口,登录一下,账号还是admin 123456(数据库中已有的)

得到token

然后复制到这个获取用户信息的请求头中,

点击测试,可以得到用户的信息,成功。

1.3 调整apifox

我们发现每次测试一个接口,都要去登录一下获得token,再手动添加Authorization,非常麻烦,可以添加相同的请求头。

点击设置

点击全局参数,将Authorization写入到里面,值就是刚刚测试用的token

如下图:

这时候回到原来的接口测试

就会发现下面多了参数,我们以后就不用再手动添加Authorization

1.4 不返回密码

由于我们之前测试的时候,将用户的所有信息都返回了包括密码,这是不安全的,所有我们要设置一下不返回密码

来到pojo层目录下的User

在password上添加一个注解@JsonIgnore

重启项目,测试一下

不再包含密码

1.5 mabits命名映射

我们发现返回的数据中,createTime 和 updateTime也是空

这是因为我们pojo中是驼峰命名,而数据库中是下划线隔开的

我们添加一下配置转化一下即可

打开application.yml,添加代码:

mybatis:
  configuration:
    map-underscore-to-camel-case: true # 开启 驼峰命名 和 下划线命名 自动转换

重启项目,测试一下

时间不再为空,成功。

二、代码优化

我们在写userInfo接口时,又解析了一遍token,但是在拦截器中,我们已经解析过了

我们可以用ThreadLocal来进行优化

写一个test测试验证一下

代码如下:

public class ThreadLocalTest {

    @Test
    public void testThreadLocalDetAndGet(){
        //提供一个ThreadLocal对象
        ThreadLocal tl = new ThreadLocal();

        //开启两个线程
        new Thread(()->{
            tl.set("萧炎");//设置值
            System.out.println(Thread.currentThread().getName() + ": " + tl.get());//获取值
            System.out.println(Thread.currentThread().getName() + ": " + tl.get());//获取值
        }, "线程1").start();//开启线程1

        new Thread(()->{
            tl.set("药尘");//设置值
            System.out.println(Thread.currentThread().getName() + ": " + tl.get());//获取值
            System.out.println(Thread.currentThread().getName() + ": " + tl.get());//获取值
        }, "线程2").start();//开启线程2
    }
}

运行一下测试结果

可以看到,虽然用的同一个ThreadLocal中存取数据,但是做到了线程隔离的效果

如何运用在项目中呢?我们每次调用controller、service等的方法时,都需要传入参数,很麻烦。

如果在拦截器中直接用线程声明线程局部变量,其他层用到时可以直接用.get()方法得到参数。

而且因为线程安全,每个线程的变量是独立的

根据以上,我们可以对我们的代码进行优化

2.1 代码优化

先在utils目录下添加一个工具类ThreadLocalUtil

代码如下:

@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();
    }
}

然后来到拦截器LoginInterceptor

只用添加一行代码

//可以把业务数据存储到ThreadLocal中
ThreadLocalUtil.set(claims);

然后去UserController找到刚刚写的userInfo方法,修改代码如下:

//获取用户信息
    //@RequestHeader(name = "Authorization") 是从请求头中获取Authorization的值
    @GetMapping("/userInfo")
    public Result<User> userInfo(/* @RequestHeader(name = "Authorization") String token */) {
        /*
        //根据用户名查询用户
        Map<String, Object> map = JwtUtil.parseToken(token);//传入token 解析token
        String username = (String) map.get("username");//获取用户名
        User user = userService.findByUserName(username);//返回一个查找到的User对象
        return Result.success(user);
        */

        Map<String, Object> map = ThreadLocalUtil.get();//获取ThreadLocal中的数据
        String username = (String) map.get("username");
        User user = userService.findByUserName(username);//返回一个查找到的User对象
        return Result.success(user);
    }

启动项目,再去用apifox测试

如果显示401,可能是token过期了,因为我们之前设置的是12小时,解决办法是

1、每12小时,去登录一下得到新token更换全局变量的值

2、把token有效时间设置的长一点,但是到期仍然需要更换

那我们什么时候清空ThreadLocal呢?

再处理完请求之后清空

我们要在LoginInterceptor类中再写一个方法

@Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        //在请求处理完成之后被调用,可以在这里进行一些后置处理,比如清理ThreadLocal中的数据
        ThreadLocalUtil.remove();
    }

完成后上传git

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值