做一个springboot用户信息模块

目录

用户信息部分

1、获取用户详细信息

前言

代码分析

代码实现 

测试

 2、更新用户信息

前言

代码实现

测试

3、更新用户头像

前言

代码实现

测试

4、更新用户密码

前言

代码实现

测试


用户信息部分

1、获取用户详细信息

前言

承接上一篇博客登录注册功能实现

        由于我们的数据库字段是下划线命名的creat_time,而实体类中对应的是creatTime,字段不一致无法直接获取。

因此需要在yml配置文件中开启驼峰命名

mybatis:
  configuration:
    mapUnderscoreToCamelCase: true

        既然要获取用户的详细信息,所以会自然的想到在controller中写一个/info接口,然后在service中调用mapper,mapper再调数据库,这样也没有错。但是我们再学习token的时候就说过了,token本身就是由用户的各种信息组成的,所以其实我们直接从token获取用户信息就行了,这样效率更高代码更少。

代码分析

        首先由于token中包含了用户的各种信息,所以默认也会包含密码在内,但是我们不希望在响应的时候把密码也解析出来,这是很不安全的,因此我们需要使用一个注解@JsonIgnore

@JsonIgnore:让springmvc把当前对象转换为json字符串的时候,忽略掉该注解作用的字段,最终的json中就没有这个字段了

        其次我们在创建拦截器的时候就对令牌进行了一次解析响应,虽然我们在使用的时候也可以重新写一遍解析jwt,但是既然已经被解析过了,我们还是直接去拦截器中取比较好,这样显得比较专业和逼格。为此我们需要使用到ThreadLocal

ThreadLocal:提供线程变量

  • 用来存储数据:get()和set()
  • 使用ThreadLocal存储的数据,线程安全

        线程安全就是说假如我们直接使用一个全局静态变量才存储变量,那么两个不同的线程同时会对这一个变量进行操作,数据就会错乱。但是使用ThreadLocal就可以保证不同的线程中只使用到自己的变量,不会互相串数据        

代码实现 

ThreadLocalUtil工具类,这个类是为了让我们更方便的使用ThreadLocal。其中我们声明了一个全局的静态变量THREAD_LOCAL,可以对其进行set值和get值,还有一个remove方法是因为它的生命周期很长,为了防止内存泄漏要在一次线程完成时把这个变量的值删掉

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

优化拦截器 ,相比上次写的多了一个afterCompletion方法,这个方法也是顾名思义在目标方法执行后它再执行

@Component
public class LoginInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //获取令牌
        String token = request.getHeader("Authorization");
        //验证token
        try {
            Map<String,Object> claims = JwtUtil.parseToken(token);

            //将解析的token信息放入ThreadLocal
            ThreadLocalUtil.set(claims);

            //没有异常就放行
            return true;
        } catch (Exception e) {
            //未登录,不放行
            response.setStatus(401);
            return false;
        }

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        
        //清空ThreadLocal的数据
        ThreadLocalUtil.remove();
    }
}

 Controller

        可以直接这里面获取ThreadLocal的值,之前往里存放的是什么类型的值就用什么类型接收就行了。

@RestController
@RequestMapping("/article")
public class ArticleController {

    @Autowired
    private UserService userService;

    @GetMapping("/list")
    public Result<User> list(){

        Map<String,Object> map = ThreadLocalUtil.get();
        String username = (String) map.get("username");
        User user = userService.findByUserName(username);

        return Result.success(user);
    }
}

测试

发起请求

 2、更新用户信息

前言

        使用者在前端修改用户的个人信息,发送到后端。我们接收过来的就是一个User对象,但是spring无法直接识别一个对象类,所以我们需要使用注解@RequestBody。

        其次就是参数校验,实际上这个功能是要在前端完成的,不过我们在后端也写一下吧。我们之前在注册模块对密码进行过检验,让他限定在5~16位。使用Spring Validation,在需要被校验的参数前加上@Pattern(regexp = "^正则表达式$"),在需要生效的地方加上@Validated就完成了。

代码实现

user实体类,直接在类上加上注解即可参数校验

测试

数据校验

3、更新用户头像

前言

因为头像只是更新用户信息中的一部分,所以使用PATCH请求方式

avaterUrl是头像的地址,一般都存放在阿里云中

代码实现

controller

@URL是数据校验是否是一个url格式的字符串,防止胡乱上传

    @PatchMapping("/updateAvatar")
    public Result updateAvatar(@RequestParam @URL String avatarUrl){
        userService.updateAvatar(avatarUrl);

        return Result.success(avatarUrl);
    }

service

直接从mapper中获取当前登录人token中的id

    @Override
    public void updateAvatar(String avatarUrl) {
        Map<String,Object> map = ThreadLocalUtil.get();

        Integer id = (Integer) map.get("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);

测试

4、更新用户密码

前言

        同样地,更新密码也是用户信息整体的一部分,所以用PATCH请求方式

        在之前我们更新用户基本信息的时候,传递的参数是一个user实体类参数,且json字段名和user属性名一摸一样。但是在更新密码中,有一个new_pwd和old_pwd来表示新密码和旧密码,user类中就没有这个属性了,添加进去在逻辑上也不太合适。所以我们可以通过传递一个map集合来表示这个参数。

        由于我们的密码在数据库中已经经过了MD5加密,所以直接拿传递过来的参数与数据库中的密码比对是不行的,可以先对参数进行MD5加密,然后在与数据库数据进行比对检验是否正确。

代码实现

Controller

    @PatchMapping("/updatePwd")
    public Result updatePwd(@RequestBody Map<String,String> params){
        //校验参数
        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("原密码错误");
        }

        //比较新密码和重复新密码是否正确
        if (!rePwd.equals(newPwd)){
            return Result.error("两次填写的新密码不一样");
        }

        //调用service完成密码更新
        userService.updatePwd(newPwd);

        return Result.success();
    }

Service

    @Override
    public void updatePwd(String newPwd) {
        Map<String,Object> map = ThreadLocalUtil.get();

        Integer id = (Integer) map.get("id");

        userMapper.updatePwd(Md5Util.getMD5String(newPwd),id);
    }

Mapper

    @Update("update user set password=#{newPwd},update_time=now() where id = #{id} ")
    void updatePwd(String newPwd,Integer id);

测试

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

找工作去哪个网站比较好

吉鹿力招聘网是一个专注于互联网岗位求职招聘的网站&#xff0c;提供海量的互联网人才储备。它主要覆盖了互联网类招聘&#xff0c;包括技术、产品、设计、运营、市场、销售等。吉鹿力招聘网的特点是用户量大&#xff0c;需求旺盛。如果你希望找工作&#xff0c;吉鹿力招聘网是…

[HCTF 2018]admin 1(四种解法!)

题目环境&#xff1a; 有登录和注册两个按钮 先注册一个admin用户 注册admin用户 显示admin用户已经被注册了 好&#xff0c;这就简单了&#xff0c;admin用户存在&#xff0c;但是不清楚admin用户的密码 尝试以下弱口令 第一种解法&#xff1a;密码爆破-尝试弱口令 进去login登…

基于selenium的pyse自动化测试框架

介绍&#xff1a; pyse基于selenium&#xff08;webdriver&#xff09;进行了简单的二次封装&#xff0c;比selenium所提供的方法操作更简洁。 特点&#xff1a; 默认使用CSS定位&#xff0c;同时支持多种定位方法&#xff08;id\name\class\link_text\xpath\css&#xff09…

Python+unittest+requests接口自动化测试框架搭建 完整的框架搭建过程

首先配置好开发环境&#xff0c;下载安装Python并下载安装pycharm&#xff0c;在pycharm中创建项目功能目录。如果不会的可以百度Google一下&#xff0c;该内容网上的讲解还是比较多比较全的&#xff01; 大家可以先简单了解下该项目的目录结构介绍&#xff0c;后面会针对每个文…

第 19 章 网络编程

网络可以使不同物理位置上的计算机达到资源共享和通信的目的&#xff0c;在Java中也提供了专门的网络开发程序包--java.net&#xff0c;以方便开发者进行网络程序的开发&#xff0c;本章将讲解TCP与UDP程序开发 19.1 网络编程简介 将地理位置不同的、具有独立功能的多台计算机…

uview的u-calendar日历组件,当设置了 minDate配置项后,会导致第一次打开日历弹窗,不会精准的滚动到选中的日期(设置了默认日期都没用)

发现需要给month.vue文件里的getMonth方法加一个延时器&#xff0c;猜测是因为设置最小日期后&#xff0c;日历没渲染完毕的时候就已经开始获取节点信息了

C# Onnx Yolov8 Detect 印章 指纹捺印 检测

应用场景 检测文件中的印章和指纹捺印&#xff0c;用于判断文件是否合规&#xff08;是否盖章&#xff0c;是否按印&#xff09; 效果 项目 代码 using Microsoft.ML.OnnxRuntime; using Microsoft.ML.OnnxRuntime.Tensors; using OpenCvSharp; using System; using System.…

Makefile应用

Makefile实例 在c.c里面&#xff0c;包含一个头文件c.h&#xff0c;在c.h里面定义一个宏&#xff0c;把这个宏打印出来。 c.c&#xff1a; #include <stdio.h> #include <c.h>void func_c() {printf("This is C %d\n", C); }c.h #define C 1然后上传…

跨国企业如何选择安全靠谱的跨国传输文件软件?

随着全球化的不断发展&#xff0c;跨国企业之间的合作变得越来越频繁。而在这种合作中&#xff0c;如何安全、可靠地将文件传输给合作伙伴或客户&#xff0c;成为了跨国企业必须面对的问题。 然而&#xff0c;跨国文件传输并不是一件容易的事情&#xff0c;由于网络物理条件的…

Mysql-库的操作

1.创建数据库 CREATE DATABASE [IF NOT EXISTS] name name后可以加 CHARACTER SET 或者是 charsetname COLLATE collation_name &#xff08;mysql数据库不区分大小写&#xff09; 说明&#xff1a; name表示想创建的库的名字大写的表示关键字 [] 是可选项 CHARACTER SET…

Linux调试器-gdb使用

程序的开发过程 debug和release ​ 程序的发布版本有debug和release版本&#xff0c;debug就是可被调试的&#xff08;debug环境下程序可以进行调试&#xff09;&#xff0c;release是发行版本&#xff0c;测试人员和用户使用的版本。Linux下我们编译代码时默认是release版本&…

苍穹外卖项目学习日记(13)

苍穹外卖项目学习日记(13) day10 Spring task cron表达式 导入spring task坐标&#xff08;spring-context已经存在&#xff09;&#xff0c;添加EnableScheduling注解 订单状态定时处理 新建task包&#xff0c;并且创建OrderTask定时类&#xff0c;添加处理超时订单和处…

网络运维Day12

文章目录 yum概述部署阿里镜像源yum基本使用 NFS网络文件系统NFS共享概述部署NFS服务端部署NFS客户端 Tomcat服务实验拓扑安装Tomcat启动服务客户端&#xff08;真机&#xff09;浏览访问页面测试 Tomcat虚拟主机NGINX服务web服务器对比NGINX简介实验拓扑虚拟机A源码编译安装NG…

ESP32-DHT11温湿度数据上传MQTT服务器

ESP32-DHT11温湿度数据上传MQTT服务器 简介ESP32DHT11 实验实验说明接线MQTT服务器建立连接添加订阅 ESP32驱动DHT11ESP32向MQTT服务器发送数据上传温湿度数据实验结果 简介 ESP32 点击图片购买 ESP32 系列模组集成 Wi-Fi、传统蓝牙和低功耗蓝牙功能&#xff0c;具有广泛的用途…

centos7系统离线安装tcpdump抓包软件、使用教程

tcpdump 是Linux系统下的一个强大的命令&#xff0c;可以将网络中传送的数据包完全截获下来提供分析。它支持针对网络层、协议、主机、网络或端口的过滤&#xff0c;并提供and、or、not等逻辑语句来帮助你去掉无用的信息。 本教程对tcpdump命令使用进行讲解说明&#xff0c;通…

对话金山云高级副总裁刘涛 | 做大模型公司的助力者

“ AIGC的应用化阶段将很快到来&#xff1b;AGI&#xff0c;已步入助手阶段。” 口述 | 刘涛 整理 | 梦婕&云舒 出品&#xff5c;极新 在10月的最后一天&#xff0c;极新有幸采访到了金山云高级副总裁刘涛。我们深入探讨了“云计算逐鹿 AIGC”的话题。作为中国公有云互…

Redhat Linux v8.2 实时内核环境配置及参数调优

BC-Linux V8.2 实时内核环境配置及参数调优 -------物理机 & 虚拟机 一、前言 本文档包含有关Redhat Linux for Real Time的基本安装和调试信息。许多行业和组织需要极高性能的计算&#xff0c;并且可能需要低且可预测的延迟&#xff0c;尤其是在金融和电信行业中。延迟&…

【MySQL】入门基础

文章目录 1 :peach:数据库基础:peach:1.1 :apple:什么是数据库:apple:1.2 :apple:主流数据库:apple:1.3 :apple:服务器/数据库/表关系:apple:1.4 :apple:MySQL架构:apple:1.5 :apple:SQL分类:apple:1.6 :apple:存储引擎:apple: 2 :peach:库的操作:peach:2.1 :apple:创建数据库:…

Xilinx MIPI4.3——bg<x>_pin<y>_nc

摘要&#xff1a;由于使用的需要&#xff0c;我要在一个bank上面使用4个MIPI D-PHY&#xff1b;如果pin的指定&#xff0c;跨了bytegroup就会出现bg<x>_pin<y>_nc信号&#xff0c;而且如果一个bit slice control被多个byte group 使用会发生报错&#xff1b;所以我…

202311.13 windows通过vscode ssh远程连接到Ubuntu 连接失败 waiting for server log

关闭VScode时没有关闭终端的Ubuntu进程&#xff1f; 导致重启后不能正常连接到Ubuntu了 Windows 系统自带的cmd终端通过ssh 可以连接 应该是vscode里对Ubuntu 的服务器端配置出了问题 参考&#xff1a;记录 VSCode ssh 连接远程服务器时出错及解决方法 在Windows 的vscode里面执…