黑马新出的SpringBoot3项目后端总结





基础篇-00_SpringBoot3_Vue3导学课程_哔哩哔哩_bilibili  这个是视频链接

这个新课程里面用了一些企业里会用的注解例如Validated这种,业务流程清晰明了简单上手,算是可以了解最基本的Springboot开发流程,方便上手和快速入门

主要是下面这几个部分

目录

引入Validation依赖

全局异常处理器

创建全局异常处理器

指定要处理的类的类型是Result类

拦截器HandlerInterceptor

自定义拦截器

在配置类里面注册拦截器

ThreadLocal的使用

 preHandle

afterCompletion

自定义注解来做参数校验

自定义注解State

自定义校验数据类StateValidation实现ConstraintValidator接口

在需要校验的地方使用自定义注解

(小重点)分组校验的实现

 定义分组

 定义校验项指定归属的分组

检验时指定要检验的分组

使用图床替代OOS上传图片简化实现

Redis实现登录逻辑优化

多环境开发

配置优先级

单文件配置

多文件配置

多环境分组

JWT的使用

引入依赖

jwt令牌的创建

jwt令牌的解析

其他常用注解

JsonIgnore

Data

Validated 


引入Validation依赖

引入springboot的Validation起步依赖,这个依赖的作用是对应参数使用的注解生效

这个依赖提供了许多的注解例如

  • Email
  • Pattern
  • NotNull
  • NotEmpty
  • URL
  • 等等
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-validation -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
    <version>3.2.5</version>
</dependency>

我们看看Controller里面用的Pattern注解,这个就是Validation提供的注解

我们之前要写一大堆的逻辑,来判断username和password是否符合规范

但是我们可以使用Pattern注解直接写正则表达式,这样子就可以简化很多流程了

我们来看看这个项目中Validation其他注解

Validated注解,我们用在Controller上,这个是让我们的实体类User里面的注解生效

看看我们的实体类User

NotNull   不能不传

NotEmpty  必须是字符串,且不能是空字符串

记住NotNull和NotEmpty是有区别的

Pattern   使用正则表达式

Email    判断是否是合理的邮箱

URL 判断是否是URL

这些注解就是Validation提供的注解

但是我们的Validation注解要结合全局异常处理器来使用,不然抛出异常的话我们无法处理


全局异常处理器

例如我们方法上面的注解Pattern匹配失败了,那么它就会报异常

而且它是整个方法都异常了,所以我们不能try catch finally

所以我们要写一个全局异常处理器,定义通用异常抛

创建全局异常处理器

我们自己创建一个全局异常处理器类,GlobalExceptionHandler

注意我们有两个注解

RestControllerAdvice

ExceptionHandler(Exception.class)

RestControllerAdvice,因为我们抛出异常的地方在我们的RestController中

ExceptionHandler(Exception.class)这个注解要写到我们要抛出异常的类上

指定要处理的类的类型是Result类

你看我们Controller里面也就是写了那个Pattern注解的,就是可能抛出异常的,类型是Result类型

所以我们的ExceptionHandler(Exception.class)对应的方法要是Result

e.getMessage是获取我们的错误信息,但是有写异常我们获取不到错误信息,这样子返回给前端不太友好

所以

StringUtils.hasLength我们用这个来判断我们是否e.getmessage是否有信息

记得我们的Validation注解要结合 全局异常处理器来使


拦截器HandlerInterceptor

自定义拦截器

jwt我们就不说了,因为我们不可能在每一个Controller都解析我们的token判断是否登录,所以我们在拦截器里面来解析我们的token,如果我们token解析成功的话,我们就放行

我们的拦截器记得加Component注解来扫描包,然后注入到我们IOC容器

我们自己弄一个类名字叫LoginInterceptor,然后连接HnadlerInterceptor接口,来重写里面的方法

例如我们的preHandler,也就是我们拦截前

我们从请求头里面拿出我们的token,然后解析,如果不报错解析成功的话,我们就return true放行

否则我们就拦截return false

在配置类里面注册拦截器

然后我们把自己写的拦截注册我们的WebConfig配置类里面,也就是我们的WebMvcConfigurer

里面有一个addInterceptors方法,就是添加我们的拦截器

配置类上面要记得加上Configuration注解,使我们的配置生效

我们因为之前把我们自定义拦截器Intercptor弄到IOC容器里面了,所以我们这里可以引入然后AutoWired自动注入

然后我们在addInterceptors()里添加我们的拦截器,但是我们有两个路径是不能拦截的

也就是我们的登录接口和注册接口,所以我们用excludePathPatterns()里面不拦截我们的登录接口和注册接口

然后修改我们的Controller,因为的解析Token的流程已经弄到拦截器里面了,我们不需要在Controller里面来解析Token


ThreadLocal的使用

如果我们想要使用我们存到Token里面的信息的时候,我们就要从请求头获取然后解析

但是我们不可能每次想要用这些信息,然后就每次都从请求头拿出来我们的Token解析吧,这样子太麻烦了,我们直接优化成TreadLocal

ThreadLocal线程池

我们的线程池有线程隔离的效果,我们一般往里面存类似于用户名这种东西,让这个能全局使用

方便取出来弄sql语句或者调用其他函数之类的

我们可以用TreadLocal来存全局变量,这样子就方便了很多

我们要改成从ThreadLocal里面获取我们的数据,但首先我们要往我们的ThreadLocal里面存取我们的数据

一般来说我们要new 一个ThreadLocal线程池 然后用set get remove三个方法

黑马把这些步骤封装成了一个工具类,我们直接使用就行

 preHandle

我们在拦截器的逻辑里面,把我们的业务数据存储到我们的ThreadLocal中

 因为我们token解析的时候是解析成Map的

 我们在拦截器里面,把解析token得到的Map存到我们的ThreadLocal线程池里面

因为我们之前是存了一个map进我们的ThreadLocal

所以我们拿出来的时候,也是一个Map

然后我们用map.get()来取出我们的key对应的

其实我们这个map里面一般放的就是我们的username,id这些,方便我们全局调用的变量

我们还要在线程结束之后把我们的往线程池里存的map移出去,防止占用内存拦截结束后,我们还要记得after之后,清空我们的TreadLocal里面的东西

afterCompletion

所以拦截器里面我们要多重写一个方法,afterCompletion


自定义注解来做参数校验

分为三步

一 自定义注解State

二 自定义校验数据类StateValidation实现ConstraintValidator接口

三 在需要校验的地方使用自定义注解

自定义注解State

我们的类是@interface,我们要写的是注解

@Documented 

这是一个元注解(meta-annotation)用于标记该注解应该包含在生成的文档中

@Target( ElementType.FIELD) 

 元注解,作用在属性上

@Retention(RetentionPolicy.RUNTIME ) 

元注解,注解在我们运行阶段任然要保留,我们这里是Runtime所以是运行阶段要保留

@Constraint(validatedBy = {})

用来指定将来谁给我们自己写的state注解提供校验规则,并指定了 StateValidation.class 作为校验规则的提供者

提供校验失败后的提示信息

String message() default "{jakarta.validation.constraints.NotEmpty.message}";

指定分组

Class<?>[] groups() default {};

负载,获取到State注解的附加信息

Class<? extends Payload>[] payload() default {};

因为我们指定了StateValidation类作为我们的校验规则,所以我们要写一个这个类出来,然后里面实现方法

自定义校验数据类StateValidation实现ConstraintValidator接口

创建规则类,实现 ConstraintValidator接口

我们的ConstraintValidator接口有两个参数

第一个参数,给哪个注解提供校验规则

第二个参数,校验的数据类型

我们是给我们刚刚的State注解提供校验规则,然后我们检验的数据类型为String

重写isValid方法,在isValid这个方法里写我们的校验规则

在需要校验的地方使用自定义注解

然后我们就可以把State注解写到我们的实体类里面


(小重点)分组校验的实现

分组校验

我们添加一下发现添加失败了,失败的原因是我们的id不能为null

因为我们刚刚实体类的ID设置了notnull

但是我们新增和删除,一个不需要传id,一个需要传id

那我们可不可以用校验来进行分组呢?

添加的时候的时候我们需要传ID

新增的时候我们不需要传ID

所以我们来弄一下分组校验

 定义分组

我们用groups来指定我们的注解是哪一个校验组的

 你看我们在这个运行失败的实体类下面弄多了两个自定义接口,名称就好和用途一样

public interface Add extends Default {};
public interface update extends Default{};

一个是Add代表添加,一个是Update代表更新

 定义校验项指定归属的分组

然后我们在Controller里的Validated,指定我们的生效的类型

检验时指定要检验的分组

 如果不指定的话,默认分为为Default,默认组

我们一开始时这样子写,但是我们只定义了Add和Update这两个分组

所以我们就算不些这两个,我们默认分组就包含这两个了

因为我们这样子继承默认分组

就说明我们这两个类其实默认都有了这两个指定对象

所以我们不用大费周章所有都写

(groups = Add.class,update.class),因为如果不写默认就是这两个


使用图床替代OOS上传图片简化实现

我们可以弄图床,然后后端只存我们的url,就可以拿到我们的图片了,我们就不用使用oos

我们随便找一个免费图床,上传图片然后把url存入到我们的数据库就行了,可以不给予OOS简化实现


Redis实现登录逻辑优化

因为jwt令牌无法在某些特定场景做到主动过期,所以我们要结合Redis来做token主动过期

因为我们之前是在jwt里面设置过期时间,拦截器里面解析token,如果解析成功就放行,解析失败就拦截。但是如果我们修改密码之后,我们会得到一个新的token,但是我们旧的token还没有过期,按照之前的逻辑,如果有人能拿到我们的旧的token写入前端请求头,它还是能通过我们的拦截器然后实现登录

所以我们要结合redis优化登录,当更新密码之后,我们往redis里面存新的token,然后主动过期旧的token

所以我们登录的时候,我们要把token存到redis里面

修改密码之后,我们要把原本的token从redis中删除

 然后我们的拦截器的逻辑就是从我们的Redis里面来取出我们的token,然后再来用jwt解析token


多环境开发

配置优先级

我们的属性配置有这四种方式

项目中的application.yml文件

jar包目录下的application.yml文件

操作系统环境变量

命令行参数

然后我们的配置的优先级,从上往下递增,下面的优先级高 


基本使用

分为单文件配置和多文件配置

单文件配置

Profile隔离应用程序配置

首先我们用spring:config来弄三个不同的环境,分别是test,dev和pro

spring:config:activates:on-profile

spring:profiles:active,来指定哪一个环境生效

然后我们在spring:profiles:active的下面配置我们的通用属性

我们的自定义配置属性会覆盖我们的通用属性


多文件配置

我们也可以不在一个配置文件来写,我们可以直接写多个配置文件

例如这样子

我们要在通用配置里面来指定激活的环境,我们的application.yml就是我们的通用配置,其他就是其他配置,我们可以在通用配置里面来指定使用其他配置


多环境分组

如果我们直接这样子写的话,我们的application文件太长了,不利于维护

所以我们使用分组,不同的配置文件写不同的内容,然后弄成同一组统一生效

例如我们的server就写端口配置

我们的DB就写数据库配置

我们的self就写自定义配置

 然后我们把这三个配置文件弄成一组

active来指定我们哪个配置文件生效,这样子就是我们整个组都生效了,简洁还方便维护


JWT的使用

引入依赖

首先我们要引入一个java-jwt依赖

<!-- https://mvnrepository.com/artifact/com.auth0/java-jwt -->
<dependency>
    <groupId>com.auth0</groupId>
    <artifactId>java-jwt</artifactId>
    <version>4.4.0</version>
</dependency>

然后我们使用jwt就行了

jwt令牌的创建

载荷是用来存我们的信息的,我们要把信息存到map里面

然后添加载荷,用“user“当变量存进去,以后取出来也用“user”取

然后withExpiresAt添加过期时间

用sign()里面指定我们的加密算法,

Algorithm是我们的jwt提供的一个加密算法
Algorithm.HMAC256("KIRA")然后我们用“KIRA”来当作这个算法的密钥

jwt令牌的解析

JWTVerifier jwtVerifier = 
JWT.require(Algorithm.HMAC256("KIRA"))
.build();

我们的解析算法和密钥要和我们加密的时候一模一样我们才能成功解析出来

用构造来弄我们的token解析器,类型是JWTVerifier

使用方法vertify(token),来解析我们的token

从解析出来的token拿出Map,这个Map里面存了我们之前存进去的一些数据   

dcoded JWT.getClaims()

这个解析出来的存数据的Map的类型是Map<String,Claim>

之前我们的数据是存到“user”这里的,所以我们取出存的数据的时候用“user”取出

然后我们把这个生成token和解析token弄到一个工具类里面,这样子就简化了代码方便了使用。


驼峰映射

在application文件中开启驼峰映射,这样子我们的sql语句里面的字段才可以自动转换匹配mysql数据库的字段


动态SQL语句

因为我们有些参数不是必须传的,所以我们的后端的SQL语句不能写死,所以我们要写一个xml文件来写一个动态SQL语句,来实现动态传参数

 

 记住,我们的Resource的Mapper的目录,要和上面我们写的Mapper的目录一一对应

看看我们目录的对应 

 Resource其实就是我们的根目录

然后我们安装一个Mybatis插件,如果我们的xml文件和Mapper文件对应上的了话,左边就会有Mapper的标志

 


其他常用注解

JsonIgnore

这个注解的用处是,当我们这个类转化成Json传输的时候,这个参数不参与转换成Json,这样子我们的密码这种隐私信息就不会返回给前端了

Data

lombok的一个自动赋值注解,get,set

Validated 

我们直接在这个Controller类上面用Validated注解,这样子下面使用的Validation注解全都可以生效了

 也可以让POJO实体类里的Validation注解生效

JsonFormat

 用正则表达式来格式化我们的日期

RequestHeader 请求头

RequestParam 参数

RequestBody 请求体

上面三个不必多说

PathVariable 要求路径参数名和形参名一一对应

例如这种


Override 

小提一嘴,这个注解的意思是这个方法是父类的方法,我们可以重写

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

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

相关文章

prompt工程策略(一:使用 CO-STAR 框架来搭建 prompt 的结构)

原文&#xff1a;我是如何赢得GPT-4提示工程大赛冠军的 为了让 LLM 给出最优响应&#xff0c;为 prompt 设置有效的结构至关重要。CO-STAR 框架是一种可以方便用于设计 prompt 结构的模板。该模板考虑了会影响 LLM 响应的有效性和相关性的方方面面&#xff0c;从而有助于得到更…

【送书福利第八期】你好!Python(文末送书)

文章目录 编辑推荐内容简介作者简介目录前言/序言 &#x1f324;️ 粉丝福利 编辑推荐 适读人群 &#xff1a;程序员;相关院校师生 本书以轻松幽默的语言&#xff0c;从零开始介绍Python语言。书名来源于编程语言中最经典的Hello World程序&#xff0c;寓意带读者从入门到精通…

简单的mysql主从复制搭建

文章目录 准备工作用Docker安装MySQL主库配置【192.168.13.32】从库配置【192.168.13.108】小结 准备工作 用虚拟机提前准备两台服务器&#xff0c;并且在服务器中分别安装好MySQL&#xff0c;服务器的信息如下&#xff1a; 数据库IP主节点192.168.13.32从节点192.168.13.108…

使用python开发的闭运算调试器

使用python开发的开运算调试器 简介效果代码 简介 用来调试闭运算效果的小工具&#xff0c;滑动条可以控制滤波核的大小&#xff0c;用来查看不同滤波核下的闭运算效果。 效果 代码 import sys from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QHBoxLayou…

MyBatis缓存的概念

缓存回顾 什么是缓存&#xff1f; 缓存就是内存中的数据&#xff0c;常常来自对数据库查询结果的保存。使用缓存可以避免频繁与数据库交互&#xff0c;进而提高 响应速度 。 MyBatis 对缓存的支持 MyBatis 也提供了对缓存的支持&#xff0c;分为 一级缓存 和 二级缓存。可以…

您的文件和驱动器上的“密码保护”有多安全?

某些行业&#xff08;例如医疗保健、法律和公司&#xff09;的人们在通过电子邮件发送文件时通常依赖密码保护&#xff0c;认为它可以提供足够的安全性来防止窥探。然而&#xff0c;对 PDF 或 Excel 文件进行简单的密码保护并不像看起来那样万无一失。 使用密码保护文件而不加…

稳态大面积光伏组件IV测试太阳光模拟器

稳态大面积光伏组件IV测试太阳光模拟器是太阳能光伏组件质量检测和评价的重要步骤之一。本文将介绍光伏组件IV测试的原理及标准板选择。 I. 光伏组件IV测试原理 光伏组件IV测试即电流电压特性测试&#xff0c;是评估光伏组件性能的重要手段。其测量的主要参数为组件的电流和电…

快速学习SpringAi

Spring AI是AI工程师的一个应用框架&#xff0c;它提供了一个友好的API和开发AI应用的抽象&#xff0c;旨在简化AI应用的开发工序&#xff0c;例如开发一款基于ChatGPT的对话应用程序。通过使用Spring Ai使我们更简单直接使用chatgpt 1.创建项目 jdk17 引入依赖 2.依赖配置 …

LeetCode394字符串解码

题目描述 给定一个经过编码的字符串&#xff0c;返回它解码后的字符串。编码规则为: k[encoded_string]&#xff0c;表示其中方括号内部的 encoded_string 正好重复 k 次。注意 k 保证为正整数。你可以认为输入字符串总是有效的&#xff1b;输入字符串中没有额外的空格&#xf…

优选算法——双指针1

双指针 常⻅的双指针有两种形式&#xff0c;⼀种是对撞指针&#xff0c;⼀种是左右指针。 对撞指针&#xff1a;⼀般⽤于顺序结构中&#xff0c;也称左右指针。 对撞指针从两端向中间移动。⼀个指针从最左端开始&#xff0c;另⼀个从最右端开始&#xff0c;然后逐渐往中间逼 近…

品鉴中的品鉴笔记:如何记录和分享自己的品鉴心得

品鉴云仓酒庄雷盛红酒的过程&#xff0c;不仅是品尝美酒&#xff0c;更是一次与葡萄酒深度对话的旅程。为了更好地记录和分享自己的品鉴心得&#xff0c;养成写品鉴笔记的习惯是十分必要的。 首先&#xff0c;选择一个适合的记录工具。可以是传统的笔记本&#xff0c;也可以是…

linux性能监控之free

free&#xff1a;linux系统自带命令&#xff0c;显示内存状态&#xff0c;命令查询来源于/proc/meminfo 文件 [rootk8s-master ~]# free --helpUsage:free [options]Options:-b, --bytes show output in bytes-k, --kilo show output in kilobytes-m, --mega…

一文掌握gRPC

文章目录 1. gRPC简介2. Http2.0协议3. 序列化-Protobuf4. gRPC开发实战环境搭建5. gRPC的四种通信方式&#xff08;重点&#xff09;6. gRPC的代理方式7. SprintBoot整合gRPC 1. gRPC简介 gRPC是由google开源的高性能的RPC框架。它是由google的Stubby这样一个内部的RPC框架演…

HCIA和HCIP区别大吗?小白请看这

华为认证以其专业性和实用性受到了业界的广泛认可。 HCIA、HCIP、HCIP这三个级别&#xff0c;你会选哪个&#xff1f;IE含金量不用多说&#xff0c;IA还是IP&#xff0c;你会纠结吗。 但面对这两个级别的认证&#xff0c;初学者或者“小白”们可能会感到困惑&#xff1a;两者…

智能体Agent笔记

智能体的定义&#xff1a; 1. 可以感受环境中的动态条件 2. 能采取动作影响环境 3. 能运用推理能力理解信息&#xff0c;解决问题&#xff0c;产生推断&#xff0c;决定动作。 我个人觉得智能体是个饼&#xff0c;最核心的问题是&#xff0c;你如何解决大模型的幻觉问题&…

Kafka官方文档中文版+Kafka面试题详解!

你了解kafka吗&#xff1f;目前它在一线互联网公司以迅雷不及掩耳之势得到了广泛的应用。但究竟是什么呢&#xff1f;Kafka最初于2011年在LinkedIn开发&#xff0c;自那时起经历了很多改进。如今它是一个完整的平台&#xff0c;允许您冗余地存储荒谬的数据量&#xff0c;拥有一…

AD原理图设置:如何在编译工程时,报未连接线或引脚错误

如下图&#xff0c;AD默认在编译原理图时&#xff0c;如果出现未连接的引脚或线时&#xff0c;并不会报相关的错误&#xff0c;这样做其实很危险 所以&#xff0c;我们应该让它提示错误 具体配置方法&#xff1a; 1、找到工程选项 2、切换到第二个选项“Connection Matrix”&a…

RedisTemplate操作Redis详解之连接Redis及自定义序列化

连接到Redis 使用Redis和Spring时的首要任务之一是通过IoC容器连接到Redis。为此&#xff0c;需要java连接器&#xff08;或绑定&#xff09;。无论选择哪种库&#xff0c;你都只需要使用一组Spring Data Redis API&#xff08;在所有连接器中行为一致&#xff09;&#xff1a;…

游戏中的设计模式一

游戏开发是一个快速迭代的过程&#xff0c;代码复杂度也很高&#xff0c;借助于设计模式&#xff0c;可以帮助我们降低复杂度&#xff0c;降低系统间的耦合&#xff0c;从而高效高质的做出交付。 最近读了这本书&#xff1a;《游戏编程模式》[1]&#xff0c;很受启发&#xff…

探索Playwright:Python下的Web自动化测试革命

在如今这个互联网技术迅速发展的时代&#xff0c;web应用的质量直接关系着企业的声誉和用户的体验。因此&#xff0c;自动化测试成为了保障软件质量的重要手段之一。今天&#xff0c;我将带大家详细了解一款在测试领域大放异彩的神器——Playwright&#xff0c;并通过Python语言…