黑马新出的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 

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

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

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

相关文章

Nginx - location中的匹配规则和动态Proxy

文章目录 官网location 规则详解动态Proxy使用多个 if 指令指定不同的 proxy_pass根据参数选择不同的 proxy_pass 官网 https://nginx.org/en/docs/http/ngx_http_core_module.html#location location 规则详解 Nginx的location指令工作原理如下&#xff1a; 位置匹配&#…

Spring WebFlux 初探-响应式编程-020

&#x1f917; ApiHug {Postman|Swagger|Api...} 快↑ 准√ 省↓ GitHub - apihug/apihug.com: All abou the Apihug apihug.com: 有爱&#xff0c;有温度&#xff0c;有质量&#xff0c;有信任ApiHug - API design Copilot - IntelliJ IDEs Plugin | Marketplace The Nex…

4.2 试编写一程序,要求比较两个字符串STRING1和STRING2所含字符是否相同,若相同则显示“MATCH”,若不相同则显示“NO MATCH”

方法一&#xff1a;在程序内部设置两个字符串内容&#xff0c;终端返回是否匹配 运行效果&#xff1a; 思路&#xff1a; 1、先比较两个字符串的长度&#xff0c;如果长度不一样&#xff0c;则两组字符串肯定不匹配&#xff1b;如果长度一样&#xff0c;再进行内容的匹配 2、如…

读万卷书|《从负债2000万到心想事成每一天》相信相信的力量

‍ ‍‍今天是2024年第20周 这是「输出倒逼输入」计划的第8篇文章 全年进度&#xff1a;8/52 PART 1 书籍简要介绍 阅读动力 这本书是读书群的好朋友小鹅推荐的&#xff0c;当时看完她的推荐就记住了这本书&#xff0c;感觉会是一本轻松愉悦且积极向上的书。而且冲着这个活力满…

【管理咨询宝藏101】普华永道并购尽调内部培训

【管理咨询宝藏101】普华永道并购尽调内部培训 【格式】PDF版本 【关键词】普华永道、兼并收购、尽职调查 【核心观点】 - 尽职调查的目的&#xff0c;发现潜在的致命缺陷&#xff0c;判断是否继续交易进程&#xff1b;发现潜在的问题&#xff0c;制定交易前后相应的应对措施。…

activiti——流程变量

文章目录 前言定义说明定义流程变量的作用域(范围) 绘制流程图文件部署数据库设置流程变量并执行流程Global 作用域 流程变量设置启动流程时设定变量查询已经创建的流程信息完成提交申请节点任务&#xff0c;推进工作流任务执行完成部门经理审批 推进节点 Local 流程变量 删除已…

齐护K210系列教程(十二)_拍照存SD卡

在AIstart中我们经常会用到在某些情况成立时&#xff0c;要把当前摄像头中的图像进行保存&#xff0c;这时我们就要用到拍照保存到SD卡的功能。 1&#xff0c;按键拍照保存 下面以【AIstart_掌机】为例&#xff0c;按下“口”键拍照1次存1.jpg到SD卡&#xff0c;再按拍照2.jpg…

在云计算与人工智能中,7ECloud扮演着什么样的角色

数据驱动的时代&#xff0c;云计算和人工智能已成为推动现代科技进步的两大引擎。作为一家专注于云计算的公司&#xff0c;7ECloud正是在这个领域发挥自己的力量&#xff0c;力图为企业提供一站式解决方案&#xff0c;并拥有来自厂家的源头支持&#xff0c;用极其低的价格助力企…

初始Linux(一)基础命令

前言&#xff1a; 我们不能总沉浸在编程语言中&#xff0c;虽然代码能力提升了&#xff0c;但是也只是开胃小菜。我们要朝着更高的方向发展。 最近小编一直在刷力扣&#xff0c;以至于博客更新的比较少。今天就带各位开始学习全新的知识——Linux.至于为啥要学&#xff1f; Lin…

【简单探索微软Edge】

&#x1f3a5;博主&#xff1a;程序员不想YY啊 &#x1f4ab;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f917;点赞&#x1f388;收藏⭐再看&#x1f4ab;养成习惯 ✨希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出…

内存屏障 - LINUX KERNEL MEMORY BARRIERS 上 与 下

内存屏障&#xff08;Memory Barrier&#xff09;是在计算机体系结构中使用的一种同步机制&#xff0c;用于确保在多线程或多核处理器环境中&#xff0c;对共享内存的操作按照预期顺序进行。它们通过强制在特定点执行一些指令来规定内存访问的顺序&#xff0c;并防止内存乱序执…

【antd + vue】Failed to resolve component: a-select-option

一、问题说明 1、出现情况&#xff1a; <a-select>嵌套<a-select-option>&#xff0c;其中<a-select-option>循环&#xff0c;能正常使用&#xff0c;但是控制台警告。 2、控制台警告&#xff1a; [Vue warn]: Failed to resolve component: a-select-op…