Spring Boot
Spring Boot 注解
Spring Boot 注解
目前刚入手,也不会ssm的bean那套,听说spring boot只需要会用类的注解就可以,不需要在xml里面配置bean,所以就记录一下常用的注解。资料来自于JavaGuide
注解原理
Spring Boot 利用 AOP 和 依赖注入(DI) 机制来实现注解驱动的功能,具体地,它是通过以下步骤进行处理的:
- 扫描注解: Spring Boot 在启动时会扫描所有 Bean 定义,找到被注解标记的类和方法。
- 创建动态代理对象: 对于标记了 @Transactional 这样的注解的方法,Spring 会使用动态代理技术生成一个代理对象,对该方法进行拦截。
一般注解会由在JVM中nio-x线程的ThreadLocal中的管理器给管理 - 拦截执行: 当该方法被调用时,动态代理对象会拦截方法调用,并在方法执行前执行事务开启操作,并在方法执行后进行事务提交或回滚操作。
Spring Boot 常用注解
-
@SpringBootApplication 这个注解是SpringBoot的核心注解,可以标注在启动类上(会默认加在主类上),SpringBoot会自动扫描该类所在的包及其子包下所有的类。并且这玩意由三个注解组合而成:
- @EnableAutoConfiguration:启用 SpringBoot 的自动配置机制。触发Spring Boot的自动配置特性,即根据classpath(类路径)下的jar包,自动配置程序所需的bean。
- @ComponentScan:扫描被@Component (@Repository,@Service, @Controller)注解的 bean,注解默认会扫描该类所在的包下所有的类。
- @Configuration:允许在 Spring 上下文中注册额外的 bean 或导入其他配置类
-
@Bean
放在启动类的方法的上面, 把方法的返回值对象,注入到spring容器中。 -
@Autowired
加在类的method上,通过容器自动注入bean。当然如果某个类基本都被加@Autowired,那么可以直接加在类上。 -
@Component,@Mapper,@Service, @Controller
@Component:通用的注解,标记某个代码段使得容器可以扫描到它,从而成为 Spring 组件。如果一个 Bean 不知道属于哪个层,可以使用@Component
注解标注。而下面这三个其实都是它的衍生注解。放在类的上面,创建此类的对象,放入到容器中。
@Mapper: 让MyBatis找到接口, 创建它的代理对象。
@Service : 对应服务层,主要涉及一些复杂的逻辑,需要用到 Dao 层。一般标注在Service层。
@Controller : 对应 Spring MVC 控制层,主要用于接受用户请求并调用 Service 层返回数据给前端页面。一般标注在Controller层。 -
@RestController (@Controller + @ResponseBody)
@RestController 注解相当于@Controller
和@ResponseBody
注解的组合,可以将返回值直接写入 HTTP 响应体中。现在很少裸用@Controller,一般都是用@RestController。 -
Scope
@Scope
注解用于指定 Spring Bean 的作用域(生命周期),共有以下几种:- singleton:单例模式,Spring 容器中只会存在一个 Bean 实例。
- prototype:原型模式,每次调用getBean()方法时,都会返回一个新的 Bean 实例。
- request:请求作用域,每个 HTTP 请求都会产生一个新的 Bean 实例,仅适用于 Web 应用。
- session:会话作用域,每个 HTTP 会话都会产生一个新的 Bean 实例,仅适用于 Web 应用。
- global-session:全局会话作用域,一般用于 Portlet 应用。
- websocket:WebSocket 作用域,每个 WebSocket 会话都会产生一个新的 Bean 实例,仅适用于 WebSocket 应用。
-
@Configuration
@Configuration
注解用于将类声明为 Spring 配置类,可以用来注册 Bean。也可以用@Component
代替。表示这是个配置类,相当于xml配置文件。 -
HTTP 请求
- 总结来说 Get获取特定数据,Post创建新数据,Put更新数据,Delete删除特定数据。
@GetMapping
,@PostMapping
,@PutMapping
,@DeleteMapping
这几个注解用于映射 HTTP 请求方法和 URL。- @PathVariable
用于绑定 URL 路径参数到方法参数。 - @RequestParam
用于绑定请求参数到方法参数。 - @RequestBody
用于绑定请求体中的 JSON 数据到方法参数。(Json -> Java) - @RequestHeader
用于绑定请求头信息到方法参数。 - @ResponseBody
用于将方法的返回值直接写入 HTTP 响应体中。表示方法的返回值是数据,而不是视图。
-
读取配置信息
- @Value
用于读取简单的配置信息 - @ConfigurationProperties
用于读取复杂的配置信息,将配置文件中的属性映射到 bean 的属性上。
- @Value
-
校验
1. `@NotNull` 被注释元素不能为null
2. `@NotEmpty` 被注释的字符串不能为空
3. `@NotBlank` 被注释的字符串不能为空并且必须包含一个非空白字符
4. `@Email` 被注释的字符串必须是有效的电子邮件地址
5. `@Pattern` 被注释的字符串必须匹配指定的正则表达式,
6. `@Positive` 被注释的元素必须是一个正数
7. `@Max(value)` 被注释的元素必须小于等于value
8. `@Min(value)` 被注释的元素必须大于等于value
9. `@DecimalMax` `@DecimalMin` 类似同上
10. `@Size(max=, min=)` 被注释的元素的大小必须在min和max之间
11. `@Past` 被注释的元素必须是一个过去的日期
12. `@Future` 被注释的元素必须是一个将来的日期
13. `@PastOrPresent` `@FutureOrPresent` 同上
14. `@Range` 被注释的元素必须在指定的范围内
15. `@Valid` 被注释的元素必须是一个合法的对象
16. `@Validated` 被注释的元素必须是一个合法的对象,并且应用 Bean Validation 验证规则
- JPA (Java Persistence API) 即数据库相关
1. `@Entity`声明一个类对应一个数据库实体。
2. `@Table` 设置表名
3. `@Id` 设置主键
4. `@GeneratedValue` 设置主键生成策略,如AUTO(数据库默认), IDENTITY(数据库自增长), SEQUENCE(序列), TABLE(通过特定的表)
5. `@Column` 设置列名和类型
6. `@Transient` 声明属性不映射到数据库表
7. `@Lob` 声明一个大字段,比如图片、视频等
8. `@enumerated` 设置枚举类型
9. `@Transacional` 声明事务,具体用来配置事务传播属性。
1. 对于Transactional这个事务注解,常用的就是**ROLLBACK\_FOR(默认)**、REQUIRED、REQUIRES\_NEW、NEVER、MANDATORY这几个属性。ROLLBACK\_FOR表示遇到运行时异常,事务回滚,里面**一般填写Exception.class**;REQUIRED表示遇到运行时异常,事务不回滚,继续运行;REQUIRES\_NEW表示遇到运行时异常,开启一个新的事务,继续运行;NEVER表示不管遇到什么异常,都不开启事务;MANDATORY表示必须开启事务,如果没有事务,就抛出异常。
-
@Slf4j
日志注解,可以自动生成日志对象。打印日志时,可以直接使用log.info()等方法。 -
@ActiveProfiles
作用于测试类种,用于指定激活的配置文件,默认使用 application.properties。 -
@Test 作用于测试方法,对一个method进行测试声明,用于声明测试用例。
-
@Transactional 作用于方法上,声明一个事务,用于测试事务相关的操作。
-
Mock相关:Mock是一种测试技术,可以模拟一个对象,使其在测试中可以替代真实的对象。Spring Boot中提供了Mock相关的注解,包括:
* @Mock 用于创建Mock对象
* @Spy 用于创建Spy对象
* @InjectMocks 用于注入Spy对象到被测试对象中
* @MockBean 用于创建Mock对象并注入到Spring容器中
Spring Boot 3 项目创建
这个真的踩了好多坑,跟着网上教程好久一步步来都能报错
- maven源设置
这个可搞可不搞,不能科学上网的话,搞一个下载速度提示还是比较显著的。
这个在maven安装目录下的setting.xml文件中设置,在标签下添加如下代码:
|
|
- 项目创建
这个start.spring.io
源不建议换,project name随你,jdk版本也随便,按照它的来
- 依赖选择
这里就算你要改spring boot的版本,你别急待会可以改的。基本常用的依赖就这几个,mybatis-plus
的依赖进去了再加。
- 导入MySQL数据库
- 修改spring boot版本
pom.xml
文件中修改版本号
比如我创建的时候是3.3多,现在随便改
这个需要注意,springboot应该是更新的快,然后mybatis-plus是来不及更新,所以遇到类似这样的报错,你可以尝试把spring boot的版本降低。
|
|
|
|
附上修改maven依赖的下载位置,如何改变防止C盘爆红
- 添加
mybatis-plus
依赖
添加到pom.xml
文件中,改完记得刷新maven
注意这个版本号千万不能错,mybaits-plus
的3.5.7版本对应spring-boot
的3.2.6版本,如果你用的版本不一样,记得改。这个你可以去GitHub上查查。
|
|
- 修改
application.properties
文件
这里我不确定跟步骤4
是否重复,但是我只做4
好像会报错。
首先,修改为yml文件,因为这个可读性什么的都比properties好。然后添加数据库源的设置。
- 测试运行
到这里就成功啦,去浏览器访问http://localhost:8080/
试试吧。
这里还有一个Warning是因为还没有具体设置。
Mybatis
官方文档: Mybatis-Plus, Mybatis-Plus-Join
个人觉得看官方文档大于看那些杂七杂八的视频,真的文档半个小时学会所有语法,看那些什么黑马啊,几个小时你还用不明白。就算忘记了,也可以去文档,就跟小时候查字典一样,哪里不会查哪里,越用越熟的。
先来概述一波,搞java后端说白了就是玩数据库的(并把操控的接口暴露给前端使用)。而为了要能在Spring Boot框架下的Java项目操控DB,就需要JDBC,它使得我们可以在Java代码中直接操作数据库。但是,问题在于JDBC还是很复杂,我们进行了简化就有了基于ORM框架的Mybatis。
你先别急,还有但是,Mybatis其实还是不够简单,为了照顾”低能”的Java程序员,我们连SQL语句都不想打怎么办,就出现了Mybatis Plus,有了它我们甚至只需要用它的封装库,就可以对数据库单表进行CRUD操作。
但是,事情还没完,Java程序员发现,对于多表查询(Join)和分页处理(一个表可能放不下输出),MP还是需要SQL语句的编写,所以引入了Mybatis Plus Join和Mybatis Plus Extension。它们前者可以进行join操作,后者可以进行分页处理。
但是,这是最后一个但是了。Java程序员一想,SQL语句可以不用写了,我连代码都不想写了,反正Entity和Mapper都是固定的,为什么不能一键生成代码呢?于是MybatisX就出现了,它能根据你数据库的形式,自动生成代码,包括Entity,Mapper,XML。
导入依赖
我本地用的是Spring Boot 3.1.6, Java 17。在pom.xml中引入依赖:
Mybatis-Plus
|
|
Mybatis-Plus-Extension
|
|
Mybatis-Plus-Join
|
|
安装插件
配置文件
-
配置application.yml以连接到数据库
1 2 3 4 5 6 7 8 9 10 11
datasource: url: spring.application.name=bank-simulation driver-class-name: com.mysql.cj.jdbc.Driver name: root password: 123456
-
在根包下创建包config,然后创建MybatisPlusConfig.java。这个很无脑的,只要你用的MySQL基本这样能应对99%的情况,如果不是的话,你换成你用的其他DB也可以的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
@Configuration // @MapperScan("org.tsu.banksimulation.mapper") public class MybatisPlusConfig { @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); return interceptor; } }
-
右侧栏的Datasource导入就不赘述,之前讲过而且很简单。
生成代码
MyBatisX大显身手
效果很惊艳的,我就不放图了
MPJ微调
这些都放心调就行了,因为这些MPJ开头的类都是扩展自Base开头的MP类,所以后者有的,前者不会拉下。
- 将所有mapper文件做调整,获取MPJ的接口实现(必须),而且记得加这个注解,不加的话,任何test测试都会报错
|
|
- 将所有service文件做调整,获取MPJ的接口实现(可选)
|
|
- 将所有serviceImpl文件做调整,获取MPJ的接口实现(可选)
|
|
总结
再提一点我的个人体验,MP和MybatisX是我平时一直用的,但是这俩仅限于单表CRUD操作,对于多表查询和分页处理,还是需要SQL语句的编写。
而MPJ我感觉其实并不好用,不如你直接去Mapper
里面直接用SQL语句实现,其实写个SQL并没有很难。而且最主要的一点是,如果你select
的字段同时在两个表的话,就需要多出一个entity类去装结果字段,而且这个result实体类得跟select的字段一一对应,少一个就不显示,多一个就永远为null
。况且Join类的多表操作其实并不多,它的效率问题就注定了频率不可能很高。
但是MPJ你装了肯定无伤大雅的,它是对MP的扩展,MP有的它都有的,万一用到了对吧,而且它的封装更好听更规范。
Wrapper
这个概念在MP里面也算是重点了,我的经验是抛弃所有普通Wrapper,只用LambdaWrapper
,不论你是单纯查询还是更新。二者区别就是,前者来做判断是用字段名称的String形式区分,后者调用实体类的方法来区分,前者你可能记错,后者不可能对错。
而在MPJ里面,只有MPJLambdaWrapper
和MPJQueryWrapper
。这里老样子我还是建议使用前者,不同点在于后者是要写SQL语句的,前者可以用Class::GetMethod
的办法,因为你都用这些插件了,还用SQL不是脱裤子放屁吗。
Spring Boot整合knife4j
最近在开发新项目,在整合Swagger的时候出现了很多问题,踩了很多坑,特此记录一下。
首先最需要提的springfox这个其实已经过时了,从Maven Repository上次更新就可以看出,swagger已经停止更新了四年之久。
而网上比如去搜swagger的使用,比如国内经常鼓吹的StackOverFlow网站,上面就说了让我们去用springfox-boot-starter这个依赖,但是它仍然不是一个较好的解决方案。而且比如我使用的是阿里云的仓库,出于国内直连网速的限制,阿里云的maven仓库甚至没有新的(3.0.0)版本的swagger2。
所以我开始探索,现在的主流方案是怎么样的。先叠个甲,还是有很多公司在用swagger的老版本,那当然是可以用的,还有些公司可能直接用apifox,我也觉得蛮好用的。
官方文档
其实Knife4j的官方文档写的挺详细的,挺不错的。quick-start
引入依赖
|
|
配置application.yml
|
|
编写Controller
大概规则就是在Controller类上加注解@Tag(name = "xxx")
用来注释类,在类内方法上加注解@Operation(summary = "xxx")
用来注释方法,然后在类内方法上加注解@Parameter(name = "xxx", description = "xxx", in = ParameterIn.QUERY/path, required = true)
用来注释参数。
启动项目
- 先启动我们的Spring Boot项目,默认端口是8080。
- 访问http://localhost:8080/swagger-ui.html,可以看到Swagger的页面。这个是我们在application.yml中配置的路径。
- 点击接口,可以看到接口的详细信息。
踩坑记录
- 如果出现依赖问题,则
mvn clean install
清一下nexus缓存。还不行,则清一下IDEA的缓存,运行File -> Invalidate Caches / Restart...
来清理缓存、重启项目。如果还不行,就直接把maven本地的依赖全部整个删除,重装整个项目的依赖。 - swagger3.0.0已不再维护,别用。至于网上说的,什么wagger-ui和swagger二合一的解决方案,别试。
- swagger2.10.x版本的
@EnableSwagger2
注解被废弃了,改成@EnableSwagger2WebMvc
注解。