与用户有关的接口

1.获取用户详细信息

跟着黑马程序员继续学习SpringBoot3+Vue3

用户登录成功之后跳转到首页,需要获取用户的详细信息

打开接口文档

使用Token令牌解析得到用户名

我们需要根据用户名查询用户,获取详细信息 

但是请求参数是无,由于都需要携带Token令牌, 可以解析Token令牌得到用户名。

打开UserController.java

在下面声明方法userInfo,返回类型Result<User>,添加注解,映射路径。想得到用户名就要声明一个String类型的Token,并且从请求头获取的。

发送请求

401?为什么?因为没有携带请求头,打开postman,携带请求头,再次发送就成功了

很多接口都需要添加请求头,为了测试方便,在postman中,可以给集合里所有的请求头统一添加请求头

回到响应数据里发现把password也给响应回来了

在user类里面,passward上面添加@JsonIgnore

作用:让springmvc把当前对象转换成Json字符串的时候,忽略password,最终json字符串中就没有password这个属性了

But! 我遇到了问题(未解决)

我加上了后,password还是在这里????!!!!为什么?!

先不理!!

我们发现后面两个时间为null?为什么?因为数据库里的命名和实体类里的不一样

配置yml文件中添加://开启驼峰命名和下划线命令的自动转换
mybatis:configuration:map-underscore-to-camel-case: true

发现已经有数据了

 2.优化获取用户详细信息的代码

 因为我们在拦截器里已经解析了Token,所以在用户获取详细信息时,不用再次解析Token了。

我们需要复用拦截器中的代码,那如何能做到呢 

使用ThreadLocal对象优化

作用:提供线程的局部变量

ThreadLocal

  • 使用set()/get()存取数据
  • 使用TreadLocal存储的数据,线程安全(与局部变量一样,每个线程自己玩自己的)
  • 用完记得清除数据(自定义remove方法)

 在Test里创建一个测试类ThreadLocalTest .java

package org.exampletest;import org.junit.jupiter.api.Test;public class ThreadLocalTest {@Testpublic void testThreadLocalSetAndGet() {//提供一个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());System.out.println(Thread.currentThread().getName()+":"+tl.get());},"蓝色").start();new Thread(()->{tl.set("药尘");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();}
}

与当前的需求有什么关系呢?

假如程序中有这几个

都有add的方法且都需要userId信息,我们就需要在每个里面都声明一个userId

使用ThreadLocal优化,可以维护一个全局的ThreadLocal tl对象存储用户名这类数据,有了这个对象,请求到达拦截器之后,就可以调用ThreadLocal对象的set()方法存储用户id.

所以当请求到达Controller,Service,Dao之后就可以使用tl.get()方法获取到这个用户id进行使用。

每个Controller,Controller,Service,Dao在容器当中都是单例的,我们怎么知道用户id是哪个呢?

 借助ThreadLocal完成两个事情:

  • 减少参数的传递
  • 在同一个线程间进行共享数据

UserController.java类

使用ThreadLocal对象获取用户id(为了使用方便,封装到工具类里),不用再次解析Token

    @GetMapping("/userInfo")public Result<User> userInfo(/*@RequestHeader(name="Authorization") String token*/){//根据用户名查询用户// Map<String,Object>map=JwtUtil.parseToken(token);Map<String,Object>map = ThreadLocalUtil.get();String username=(String)map.get("username");//map.get("username")是Object类型,我们知道存username是String,强转User user=userService.findByUserName(username);return Result.success(user);//把user响应给浏览器}

工具类

ThreadLocalUtil.java
package org.exampletest.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();}
}

在拦截器里把业务数据存储到ThreadLocal中,并且需要在请求完成之后清除数据,防止内存泄漏
  //把业务数据存储到ThreadLocal中ThreadLocalUtil.set(claims);

完整代码:

package org.exampletest.interceptors;import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.exampletest.pojo.Result;
import org.exampletest.utils.JwtUtil;
import org.exampletest.utils.ThreadLocalUtil;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;import java.util.Map;@Component
public class LoginInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler){//令牌验证String 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;}}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception{//移除ThreadLocal中的数据ThreadLocalUtil.remove();}
}

 3.更新用户基本信息

 查看接口文档

得到请求路径,请求方式,请求参数,响应数据等

实现思路

在UserController中添加一个方法,方法上添加注解@PutMapping("/update"),因为这个方法是put请求方式。

浏览器将来会给我们提供id,nickname,email这样的数据并且是在请求体中以json格式给我们携带过来的,所以就把这些数据封装到一个实体类对象User里面进行接收。为了让我们的框架能够自动的把请求体里面的json数据转换成一个实体类对象,需要在参数前面添加一个注解@RequestBoby

 @PutMapping("/update")public Result update(@RequestBody User user){userService.update(user);return Result.success();}

接下来在方法体内,只需要调用service层的方法完成更新就可以了,所以service层也要提供对应的更新的相关方法,在mapper层也要执行对应的sql(username,用户不能进行修改;updatetime更新时间也要进行修改)

service层:

void update(User user);

实现接口:UserServiceImpl.java

   @Overridepublic void update(User user) {user.setUpdateTime(now());userMapper.update(user);}

mapper层

 @Update("update user set nickname=#{nickname},email=#{email},update_time=#{updateTimme} where id=#{id}")void update(User user);

在Body里面添加 

 

遇到的问题?(为解决版)

数据库中user表: 

参数校验 

 

我们把请求的参数封装到一个实体类对象user里面

对实体参数完成校验

1.在实体类成员变量上添加 Validation提供的注解,对指定的属性值完成校验

 2.添加完指定注解之后,在实体类参数前添加注解@Validated(使得实体类中属性上的注解生效)

    @PutMapping("/update")public Result update(@RequestBody @Validated User user){userService.update(user);return Result.success();}

 此时校验已经生效了(虽然我遇到了问题,但是请求是成功的)

 

4.更新用户头像

 接口文档

实现

 需要从RequestParam里面获取到这个数据

 

@URL校验是不是一个url地址

参数里没有id,而sql语句中需要根据用户名进行查询,使用拦截器解析得的,ThreadLocal中的数据

    @PatchMapping("/updateAvatar")public Result updateAvatar(@RequestParam  @URL String avatarUrl){Map<String,Object> map = ThreadLocalUtil.get();Integer id = (Integer) map.get("id");userService.updateAvatar(avatarUrl,id);return Result.success();}

 service层

//更新头像void updateAvatar(String avatarUrl,Integer id);

 实现接口.Impl

  @Overridepublic void updateAvatar(String avatarUrl, Integer id) {userMapper.updateAvatar(avatarUrl,id);}

mapper层

  @Update("update user set user_pic=#{avatarUrl},update_time=now() where id= #{id}")void updateAvatar(String avatarUrl, Integer id) ;

5.更新用户密码

 接口文档

实现

 在UserController里添加一个方法,方法上添加@PatchMapping("/updatePwd")指定访问的路径

 方法上需要声明一个Map类型的参数params,用来接收前端提交的json参数。

在前面更新用户信息时,也接收json参数,当时是声明一个user实体对象来接收。当时传递的json数据中的键名和实体类属性名一样。

现在请求参数中键名是old_pwd,new_pwd,re_pwd等,没有和实体类属性名一致,所以需要声明一个map集合来接收参数,到时候MVC框架会自动帮我们把json数据转换成map集合对象

添加@RequestBodyMVC框架才会自动读取请求体里面的数据,然后转换成map集合对象

 @PatchMapping("/updatePwd")public Result updatePwd(@RequestBody Map<String,String> params){//1.校验参数,没有提供相应的注解能满足,需要手动校验参数String oldPwd=params.get("old_pwd");String newPwd=params.get("new_pwd");String rePwd =params.get("re_pwd");if(!StringUtils.hasLength(oldPwd) || !StringUtils.hasLength(newPwd) || !StringUtils.hasLength(rePwd)){return Result.error("缺少必要的参数");}//原密码是否正确//根据用户名查询用户拿到密码Map<String,Object> map = ThreadLocalUtil.get();String username = (String) map.get("username");User loginUser = userService.findByUserName(username);if(! loginUser.getPassword().equals(Md5Util.getMD5String(oldPwd))){return Result.error("原密码不正确");}//校验newPwd与rePwd是否一致if(!newPwd.equals(rePwd)){return Result.error("两次输入的新密码不一致");}//2.调用service完成密码更新Integer id = (Integer) map.get("id");userService.updatePwd(newPwd,id);return Result.success();}
//更新密码void updatePwd(String newPwd,Integer id);
   @Overridepublic void updatePwd(String newPwd, Integer id) {usermapper.updatePwd(Md5Util.getMD5String(newPwd),id);}
@Update("update user set password=#{md5String},update_time=now() where id=#{id}")void updatePwd(String md5String, Integer id);

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/394654.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于微信小程序的小学生口算练习系统

摘 要 随着当今网络的发展&#xff0c;时代的进步&#xff0c;各行各业也在发生着变化&#xff0c;小程序也逐步进入人们的生活&#xff0c;给我们生活或者工作提供了新的方向新的可能。 本毕业设计的内容是设计实现一个小学生口算练习的小程序。微信开发者是以java语言进行…

2023 江苏省第一届数据安全技术应用职业技能竞赛 决赛 部分wp

文章目录 一、前言比赛平台全貌题目附件及工具下载&#xff08;123网盘&#xff09; 二、参考文章三、题目&#xff08;解析&#xff09;一、内存取证-MemoryLife1、请给出内存镜像中黑客使用工具对外连接的IP地址及端口号是___________。&#xff08;格式为IP_PORT&#xff09…

app抓包 burp配置

证书导出 模拟器安装证书 点击安装证书 将证书直接拖进来就行 配置代理 打开浏览器抓包

用python创建极坐标平面

极坐标的介绍 http://t.csdnimg.cn/ucau3http://t.csdnimg.cn/ucau3这个文章里可以知道极坐标的基本知识&#xff0c;接下来实现极坐标的绘制 PolarPlane 是 Manim&#xff08;一个用于数学动画的Python库&#xff09;中的一个类&#xff0c;用于创建极坐标平面。与笛卡尔…

开发android app用于移远模块读写IMEI 模组EC200DEULA-D08-SNNDA 支持socket连接读写IMEI

开放权限 adb kill-serveradb rootadb shell setenforce 0adb install -t app-debug.apkadb shell am start -n com.azhon.spplus/.MainActivity::F310A_WriteIMEI -DWadb.exe forward tcp:5902 tcp:5902pause写读IMEI ADB socket协议 TCP 127.0.0.1:5902 PC与终端APP之间 j…

大放异彩!东软医疗DSA闪耀欧洲

欧洲&#xff0c;作为影像技术的发源地&#xff0c;当下正面临经济发展和人口老龄化的双重考验&#xff0c;对医疗技术的革新与升级需求也愈发迫切。中国高端医疗装备品牌东软医疗&#xff0c;凭借深厚的创新底蕴与对临床需求的精准把握&#xff0c;深耕欧洲市场二十余年&#…

数据结构——排序(2):选择排序+交换排序

目录 一、选择排序 &#xff08;1&#xff09;直接选择排序 ①思路 ②过程图示 ③代码实现 ④代码解释 ⑤优化 1.代码实现 2.过程图示 3.代码解释 4.注意 ⑥直接选择排序的复杂度 &#xff08;2&#xff09;堆排序 ①注意 ②代码实现 二、交换排序 &#xff08…

Vue前端服务加密后端服务解密--AES算法实现

在实际项目中考虑到用户数据的安全性&#xff0c;在用户登录时&#xff0c;前端需要对用户密码加密&#xff08;防止用户密码泄露&#xff09;&#xff0c;服务端收到登录请求时先对密码进行解密&#xff0c;然后再进行用户验证登操作。本文 AES ECB 模式来实现前端机密后端解密…

GPT-5:未来已来,你准备好了吗?

GPT-5 一年半后发布&#xff1f;对此你有何期待&#xff1f; IT之家6月22日消息&#xff0c;在美国达特茅斯工程学院周四公布的采访中&#xff0c;OpenAI首席技术官米拉穆拉蒂被问及GPT-5是否会在明年发布&#xff0c;给出了肯定答案并表示将在一年半后发布。此外&#xff0c;穆…

数据库基础知识

数据库基础知识 主流的数据库连接MySQL理解mysql和mysqld和数据库简单对数据库操作MySQL构架SQL分类存储引擎总结 主流的数据库 SQL Sever&#xff1a; 微软的产品&#xff0c;.Net程序员的最爱&#xff0c;中大型项目。Oracle&#xff1a; 甲骨文产品&#xff0c;适合大型项目…

【Linux网络】网络层协议:IP

本篇博客整理了 TCP/IP 分层模型中网络层的 IP 协议&#xff0c;旨在让读者更加深入理解网络协议栈的设计和网络编程。 目录 一、网络层 二、IP 报头 1&#xff09;报头与有效载荷的分离 2&#xff09;有效载荷的上交 3&#xff09;源 IP 与目的 IP 4&#xff09;生存时间…

学习笔记 韩顺平 零基础30天学会Java(2024.8.7)

P481 Math方法 利用random返回一个[2,7]之间的随机数&#xff1a; 因为random只能返回[0,1)之间的随机数&#xff0c;因此做一下处理&#xff1a;[(int)(a), (int) (aMath.random()*(b-a1))]&#xff0c;对于Math.random()*(b-a1)&#xff0c;其中b-a1&#xff0c;它乘上[0,1)相…

第R3周:天气预测

本文为365天深度学习训练营 中的学习记录博客原作者&#xff1a;K同学啊 任务说明&#xff1a;该数据集提供了来自澳大利亚许多地点的大约 10 年的每日天气观测数据。需要做的是根据这些数据对RainTomorrow进行一个预测&#xff0c;这次任务任务与以往的不同&#xff0c;增加了…

目录函数以及链接文件

一、对stat里面的用户名时间做处理的函数 1.1.getpwuid&#xff08;&#xff09; struct passwd *getpwuid(uid_t uid); 功能: 根据用户id到/etc/passwd文件下解析获得 结构体信息 参数: uid:用户id 返回值: 成功返回id对应用户的信息 失败返回NULL 1. 2.getgrgid&#xf…

数据复盘“黑色星期一”:加密市场震荡,代币表现如何?

8月5日的“黑色星期一”成为了全球金融市场的动荡日&#xff0c;这一波及到加密市场的剧烈震荡导致了大量清算事件和代币的暴跌。本文将通过数据复盘&#xff0c;分析这一事件中加密货币的表现&#xff0c;并探讨未来市场的可能走向。 一、暴跌中的惨痛数据 在“黑色星期一”事…

Jenkins构建异常,Dockerfile中ADD或COPY及相对路径

Jenkins构建异常&#xff0c;Dockerfile中ADD或COPY及相对路径 制品构建前后端异常 #前端 09:45:53 docker build -t hubtest.......com.cn/duty_record/......-web-01:origin-master-20 -f vue/script/Dockerfile vue/script 09:45:54 Sending build context to Docker da…

zabbix7.0TLS-05-快速入门-触发器

文章目录 1 概述2 查看触发器3 添加触发器4 验证触发器5 查看问题6 问题恢复 1 概述 监控项用于收集数据&#xff0c;但是我们并不能时刻观测每个监控项的数据&#xff0c;看看哪个监控项的数据超过了正常可接受的数值或状态&#xff0c;比如 CPU 负载高于 90%、磁盘使用率低于…

TypeScript位运算

参考文献&#xff1a; https://blog.csdn.net/xuaner8786/article/details/138858747 https://www.runoob.com/typescript/ts-operators.html 位运算符 TypeScript 中的位运算符用于在二进制位级别上操作数字。这些运算符在处理整数和底层系统编程时特别有用。以下是一些使用…

互联网医院系统源码与医保购药APP开发:探索医疗的数字化转型

互联网医院系统的开发是一个复杂的工程&#xff0c;需要多个模块的有机结合才能实现高效、安全的在线医疗服务。以下是互联网医院系统的几个关键组成部分&#xff1a; 1.在线问诊模块 2.电子病历管理 3.在线预约与支付系统 4.远程医疗设备对接 一、医保购药APP的开发要点 …

三大浏览器Google Chrome、Edge、Firefox内存占用对比

问题 Chrome、Edg、Firefox三家究竟谁的占用少 结论 打开一个页面内存占用 Firefox>Edge>Chrome 打开打量页面内存占用 Firefox>Chrome>Edge 从监视器可以看到Edge增加一个页面增加一个页面不到100M而其它浏览器需要150M左右;Firefox浏览器主线程内存占用800M比…