SpringBoot,简化Spring开发。
介绍
SpringBoot
Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置。通过这种方式,Spring Boot致力于在蓬勃发展的快速应用开发领域(rapid application development)成为领导者。摘自百度百科。
springIOC
Ioc—Inversion of Control,即“控制反转”,不是什么技术,而是一种设计思想。在Java开发中,Ioc意味着将你设计好的对象交给容器控制,而不是传统的在你的对象内部直接控制。如何理解好Ioc呢?理解好Ioc的关键是要明确“谁控制谁,控制什么,为何是反转(有反转就应该有正转了),哪些方面反转了”,那我们来深入分析一下:
- 谁控制谁,控制什么:传统Java SE程序设计,我们直接在对象内部通过new进行创建对象,是程序主动去创建依赖对象;而IoC是有专门一个容器来创建这些对象,即由Ioc容器来控制对 象的创建;谁控制谁?当然是IoC 容器控制了对象;控制什么?那就是主要控制了外部资源获取(不只是对象包括比如文件等)。
- 为何是反转,哪些方面反转了:有反转就有正转,传统应用程序是由我们自己在对象中主动控制去直接获取依赖对象,也就是正转;而反转则是由容器来帮忙创建及注入依赖对象;为何是反转?因为由容器帮我们查找及注入依赖对象,对象只是被动的接受依赖对象,所以是反转;哪些方面反转了?依赖对象的获取被反转了。
- 更详细介绍,见这篇博客。
使用注解@Autowired,实现自动装配,不需要手动创建实例;但是也需要在IOC中有相应的对象,否则会报错。
使用注解@Mapper、@Service、@RestController(底层还是注解@Component)的类,spring会自动创建相应的实例(在IOC容器中)
创建项目
在IDEA中创建SpringBoot+mybatis项目。更多案例,见后边“整合mybatis”部分。
准备
可以对Maven、JDK进行默认配置。不用每次创建项目时都需要再配置一次。
- JDK版本配置,在Project Structure(项目结构)中。
- 左上角“文件” - 设置 - 项目设置 - 项目 - 项目SDK
- maven配置。在settings(设置)中。
- 左上角“文件” - 项目结构 - “构建、执行、部署” - 构建工具 - Maven
- 相关文件可在这里下载。
创建项目
使用开发工具IDEA创建SpringBoot项目,有两种方式:
- 从一个普通maven项目,搭建SpringBoot项目。参考这篇博客。
- 创建一个普通maven项目
- 编写SpringBoot配置文件
- 编写SpringBoot启动类
- 一开始就搭建一个SpringBoot项目。见下边的案例。
若已有项目(project)则在项目中新建模块(module)即可,否则创建一个新的项目。新建的项目中会默认创建一个模块。项目中可以包含多个模块。
左上角“文件 ”- 新建项目 - Spring Initializer - 选择jdk版本,使用默认配置。
一些基本信息:
- 填写公司域名,作为Java程序包名。
- 填写项目名(Artifact)。
- 选择开发使用的jdk版本。
类型选择Spring Web。
Project name设置与前边的Artifact中设置的相同。project location,建议创建一个文件夹专门保存项目文件。
选择自动导入。
新建项目成功的状态:
项目结构
文件application.properties为springBoo的配置文件,详细配置参考这篇博客。
代码编写
依赖
在pom.xml 中导入对应的Maven依赖:
1 |
<!--spring-boot--> |
配置
在springBoot的配置文件application.properties中配置服务器地址和账户等信息。配置如下:
1 |
#服务端口 |
关于mybatis的参数配置,见后边“整合mybatis”部分。
DAO模块
定义Mapper模块(叫DAO模块也行,一个名称而已),对数据库进行增删改查等操作。
- 接口使用注解
@Mapper
。 - 扩展:在SpringBoot启动类中使用注解
@MapperScan
,可自动扫描接口不用每一个mapper接口都添加注解@Mapper
。 - 编写接口DepartmentMapper
- 定义方法queryAll,查询所有的部门信息,
SELECT * FROM department
,查询表department
- 方法使用注解
@Select
(根据SQL语句选择相应注解,@Insert、@Delete、@Update、@Select等) - tips:sql语句验证通过后再添加到注解中。
- 定义方法queryAll,查询所有的部门信息,
1 |
|
扩展
可编写一个类,专门用于拼接复杂的sql语句。
1 |
public class DepartmentMapperProvider { |
注解@Select改为@SelectProvider。指定类和类中的具体哪个方法用于拼接SQL。
1 |
.class,method = "querySql") (value = DepartmentMapperProvider |
service模块
业务层。编写业务逻辑,调用DAO模块中实现的功能。
service接口:
- 编写接口IDepartmentService,定义方法queryAll。
public List<Department> queryAll();
- 接口可以不写,视具体的开发规范而定
实现类:
编写实现类 DepartmentServiceImpl,实现方法queryAll。
调用DAO模块中DepartmentMapper接口的相应方法,实现对数据库的增、删、改、查操作。
实现类,使用注解@Service
变量departmentMapper,使用注解@Autowired,实现自动装配(不需要手动创建实例;但是也需要在IOC中有相应的对象,否则会报错。原因看这里)
1
2
3
4//Mapper接口通过@Autowired注入。在代码编辑时,由于没有对应的实现类,IDEA会标红报错,无视即可。
//项目是能正常运行的。(由于动态代理机制,会自动创建并实例化一个实现类)
//自动装配。不需要手动创建接口departmentMapper的实例
private DepartmentMapper departmentMapper;
web模块
编写web层实现(Controller层),根据前端页面的请求调用(使用)业务层实现的功能。
编写类DepartmentController,作为web层组件
使用注解@RestController,将类声明为web层组件
(调用)使用Service层实现的功能,使用注解Autowired实现自动装配:
1
2
3
4
5
6
7
8//调用Service模块中的 实现类
//自动装配。不new DepartmentServiceImpl()也可以
private DepartmentServiceImpl departmentService;
//或 调用Service模块中的 接口
// @Autowired//自动装配
// @Qualifier("departmentServiceImpl")//指定实现类(只有一个实现类时可以省略)
// private IDepartmentService departmentService;使用注解@RequestMapping,配置请求路径
- 例如:
@RequestMapping("department/query") 或 @RequestMapping(value="/login",method=RequestMethod.POST)
- 可在Controller上使用,将作为路径前缀
- 可细分为@GetMapping、@PostMapping、@DeleteMapping、@PatchMapping、@PutMapping等
- 例如:
如果形参为一个对象,(前端页面)只需要传递创建对象需要的成员变量即可,springBoot会自动实例化对象
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20//新增 或 修改:
//参数是一个自定义的Department部门对象,传递数据的时候,只需要传递对应的Department部门对象的属性即可
//比如说:name --> department.setName(name)
//sn --> department.setSn(sn)
"/department/saveOrUpdate") (
public Boolean saveOrUpdate(Department department){
if (department.getName() =="" && department.getSn() == ""){
return false;//没有name、sn这两个参数,则直接退出
}
//判断id是否为空,如果为空,就是新增操作,否则就是修改操作
if (department.getId() == null){
//新增
departmentService.insert(department);
}else {
System.out.println("修改数据:id="+department.getId());
//修改
departmentService.update(department);
}
return true;
}
跨域配置
两种配置方式:
- 配置类
- Controller层中允许跨域请求的类上使用注解“@CrossOrigin”
- 详细配置,见这篇博客
高级查询
模糊查询
模糊查询: https://www.processon.com/view/link/5fcc400be401fd1e15ca02c1
1 |
模糊查询,% |
分页显示数据
MySQL分页语句
1 |
SELECT * FROM department LIMIT 20,10; |
使用插件实现
老师笔记:分页功能的实现。
导入依赖
mybatis分页插件:传送门。Maven依赖:
1 |
<dependency> |
帮助文档:传送门。
1 |
例三,使用PageInfo的用法: |
代码修改
DAO层不需要修改(查询所有数据select * from 表名
)。修改service层和web层。
PageHelper插件的分页是基于mybatis框架实现的。使用了mybatis的拦截器。在执行查询sql前根据分页信息,把分页参数拼接到sql后面再去查询。
参数:
添加插件需要的用到的参数:
在查询条件DepartmentQueryObject类中定义一个分页处理插件的两个参数。pageSize、currentPage。(将前端页面发送请求的参数封装在类中。springboot会使用接收到的参数自动创建对象)
1 |
package com.qsdbl.demo.qo; |
service模块
使用到插件的PageInfo类,对数据进行封装。
修改IDepartmentService(接口)的查询方法的返回值:
1 |
public PageInfo<Department> queryAll(DepartmentQueryObject qo); |
修改DepartmentServiceImpl类(实现类)的查询方法:PageHelper查询指定的分页数据。PageInfo将DAO模块中查询出来的List数据进行封装,返回PageInfo类型数据。
1 |
|
方法queryAll的改变:
- 修改前
- 可以查询所有数据和模糊查询所有匹配的数据。根据是否有参数KeyWord来区分(不为null且长度大于0)
- 见拼接SQL语句的类DepartmentMapperProvider
- 修改后
- 也是可以查询所有数据和模糊查询所有匹配的数据
- 但是显示的数据为分页插件pagehelper处理后的数据,所以显示数据的数量由参数pageSize确定,本案例中默认为10
- 其他分页设置参数见将参数封装的类DepartmentQueryObject
web模块
修改DepartmentController查询方法的返回值
1 |
//查询: |
前端页面
运行结果
结果集映射
单元测试
测试,需要注意两个地方:
- 测试类上,使用
注解@SpringBootTest
- 测试方法上,使用
注解@Test
- 回顾:junit单元测试
案例:
1 |
package com.qsdbl.nazox_demo; |
数据源
笔记来自狂神说博客
Spring Boot 2.0 以上默认使用 Hikari 数据源,Hikari 与 Druid 都是当前 Java Web 上最优秀的数据源。Druid 是阿里巴巴开源平台上一个数据库连接池实现,结合了 C3P0、DBCP 等 DB 池的优点,同时加入了日志监控。
集成Druid
1、添加maven依赖
1 |
<!--druid数据源--> |
2、SpringBoot配置文件(application.properties)中,设置数据源为druid
1 |
#数据源使用 阿里巴巴的druid |
3、验证已切换数据源。参考上边“测试”中的案例,进行验证。
配置
注意:下边配置的参数都是druid的私有属性,后边还需要添加配置类绑定配置文件中配置的参数才能生效
同样是在SpringBoot配置文件(application.properties)中进行配置。druid配置说明:
配置示例:
1 |
#Spring Boot 默认是不注入这些属性值的,需要自己绑定 |
绑定配置
为 DruidDataSource 绑定全局配置文件中的参数,添加到容器中(不使用 Spring Boot 自动生成的)。创建Druid配置类如下:
1 |
package com.qsdbl.nazox_demo.configuration; |
测试
1 |
package com.qsdbl.nazox_demo; |
结果:可以看到,与我们的配置是一致的
1 |
class com.alibaba.druid.pool.DruidDataSource |
开启监控
Druid 数据源具有监控的功能,并提供了一个 web 界面方便用户查看,类似安装 路由器 时,人家提供一个默认的 web 页面。整合log4j后,也可以使用log4j的其他功能。
1、添加maven依赖
前边的配置中开启了log4j日志监控,需要在pom.xml文件中添加maven依赖:
1 |
<!--日志监控:log4j--> |
2021-12-20日,Apache Log4j连续曝光了三个漏洞。官方已发布 2.17.0 版本修复漏洞,注意不要使用比2.17.0低的版本。(受影响版本为2.0~2.14,此处使用的是1.2不受影响)
2、在Druid配置类中,配置 Druid 的后台管理页面,比如 登录账号、密码 等;DruidConfig中添加如下配置:
1 |
import com.alibaba.druid.support.http.StatViewServlet; |
3、添加log4j配置文件
完成上边两步配置后,Druid 监控管理后台就可以正常访问了。但是log4j的日志功能还需要进行相关配置(在resources文件夹下创建log4j.properties文件),简单配置如下:
1 |
DEBUG, stdout = |
log4j的使用和properties文件的配置,见这篇博客。建议整合上边druid中的配置一起使用。
测试
启动SpringBoot项目后,访问路径/druid
,输入上边配置的用户名密码后进入Druid
监控管理后台。进行一些数据库crud操作后即可看到Druid的监控数据:
过滤器
配置 Druid web 监控 filter 过滤器,过滤我们不需要Druid进行监控的资源。(了解即可)
示例:
在Druid配置类DruidConfig中添加如下配置:
1 |
import com.alibaba.druid.support.http.WebStatFilter; |
事务管理
笔记摘自CSDN
在SpringBoot中开启事务管理,只需要在方法上添加注解@Transactional
即可。(复习:在spring中开启声明式事务管理)
介绍
事务管理是应用系统开发中必不可少的一部分。Spring 为事务管理提供了丰富的功能支持。Spring 事务管理分为编程式和声明式的两种方式。编程式事务指的是通过编码方式实现事务;声明式事务基于 AOP,将具体业务逻辑与事务处理解耦。声明式事务管理使业务代码逻辑不受污染, 因此在实际使用中声明式事务用的比较多。声明式事务有两种方式,一种是在配置文件(xml)中做相关的事务规则声明,另一种是基于 @Transactional 注解的方式。
注意:
- 默认配置下 Spring 只会回滚运行时、未检查异常(继承自 RuntimeException 的异常)或者 Error。参考这里
- @Transactional 注解只能应用到 public 方法才有效。参考这里 Method visibility and @Transactional
mybatis + springboot,springboot 会自动配置一个 DataSourceTransactionManager
,我们只需在方法(或者类)加上
@Transactional
注解,就自动纳入 Spring 的事务管理了。
实现机制
在应用系统调用声明了 @Transactional 的目标方法时,Spring Framework 默认使用 AOP 代理,在代码运行时生成一个代理对象,根据 @Transactional 的属性配置信息,这个代理对象决定该声明 @Transactional 的目标方法是否由拦截器 TransactionInterceptor 来使用拦截,在 TransactionInterceptor 拦截时,会在目标方法开始执行之前创建并加入事务,并执行目标方法的逻辑, 最后根据执行情况是否出现异常,利用抽象事务管理器 AbstractPlatformTransactionManager 操作数据源 DataSource 提交或回滚事务。
Spring AOP 代理有 CglibAopProxy 和 JdkDynamicAopProxy 两种,以 CglibAopProxy 为例,对于 CglibAopProxy,需要调用其内部类的 DynamicAdvisedInterceptor 的 intercept 方法。对于 JdkDynamicAopProxy,需要调用其 invoke 方法。
正如上文提到的,事务管理的框架是由抽象事务管理器 AbstractPlatformTransactionManager 来提供的,而具体的底层事务处理实现,由 PlatformTransactionManager 的具体实现类来实现,如事务管理器 DataSourceTransactionManager。不同的事务管理器管理不同的数据资源 DataSource,比如 DataSourceTransactionManager 管理 JDBC 的 Connection。
多线程
访问这篇博客。
注解总结
记录使用过的注解:
1 |
|
个性化配置
启动banner
配置SpringBoot项目启动动画(控制台打印的字符)。
在resources文件夹下,新建一个banner.txt文件。在其中添加自定义的字符即可。
例如:
1 |
_ __ |
配置文件
一些常见配置:
1 |
#服务端口 |
自定义配置
将配置保存在springBoot配置文件中,在class中通过@Value注解获取。
在springBoot配置文件application.properties中,添加配置参数:
1 |
#JWT配置 |
在class中,通过@Value注解获取:
1 |
//私钥 |
- 使用static或final修饰了变量
- 类没有加上@Component(或者其他将类注册到spring容器的注解)
- 类被new新建了实例,而不是使用@Autowired
在实体类中,自动注入配置文件中配置的属性值
1 |
//使用注解ConfigurationProperties |
多个配置文件
笔记摘自:传送门
项目在开发环境和生产环境下的配置是不一样的。我们可以使用多个配置文件,在不同的环境下使用不同的配置文件即可。
起名
springboot中,可以根据如下格式给配置文件起名:application-{profile}.properties
,其中profile可以看作是该配置文件的标识。比如:
1 |
开发环境: |
激活
在application.properyies中通过spring.profiles.active来具体激活一个或者多个配置文件(逗号隔开)。比如:
1 |
#application.properyies中进行配置 |
扩展:还可以使用spring.profiles.include
来启用多个配置文件(逗号隔开)
命令行方式:可在使用命令行启动程序时,指定激活哪个配置文件。
1 |
java -jar xxx.jar --spring.profiles.active=dev |
连续的两个减号就是对application.properties中的属性值进行赋值的标识。若要屏蔽通过命令行修改配置,需要在启动类中添加配置:SpringApplication.setAddCommandLineProperties(false)
高级应用
在类上添加注解Profile,只有当激活的配置文件与注解Profile中的相同时,才会实例化该类。
1 |
//在类上添加注解Profile |
总结
application.properties中配置通用内容,并设置spring.profiles.active默认激活开发环境。在运行项目时可以根据需要,通过命令行方式去激活不同的环境配置。
配置类
springboot整合其他框架,一般需要编写配置类。例如上边整合Druid的例子。
1 |
#配置类上需要添加此注解 |
整合
MyBatis
SpringBoot项目中,整合mybatis框架。上边的“创建项目”部分,就记录了使用SpringBoot+mybatis来创建一个web项目的过程。
步骤:
- 添加Maven依赖
- 在SpringBoot配置文件application.properties中配置mybatis、数据库
1 |
#-----------mybatis----------- |
注意:仔细检查一下xml文件实际所在的路径与配置文件中的是否一致。
若xml文件与mapper接口在同一个包下,则不需要在配置中指定路径。resource文件夹下的文件(包括文件夹)在编译后会保存到”classpath:“下,所以根据上边的mybatis.mapperLocations的配置信息,xml文件应当保存在resource文件夹下的mapper文件夹内。
案例2
springBoot+MyBatis+pagehelper,案例见这篇博客。
案例1
使用结果集映射,实现多表查询。(属于“案例2”中的“结果嵌套查询”)
有用户表、角色表、用户-角色表三张表。用户可能有多个角色,所以需要使用结果集映射,将用户角色映射到用户实体类中的一个集合中进行保存。
用户实体类
1 |
package com.qsdbl.cashier_system.entity; |
mapper接口
1 |
package com.qsdbl.cashier_system.mapper; |
xml文件
在resources文件夹下,新建包mappers,添加mapper接口对应的xml配置文件,配置如下:
1 |
|
扩展:若不想每一个mapper接口都添加一个@Mapper
注解注册Bean到SpringBoot框架,可以在SpringBoot启动类中使用注解@MapperScan
,扫描mapper包下的接口自动注册Bean。
1 |
package com.qsdbl.cashier_system; |
SpringBoot配置文件application.properties。
1 |
#指定实体类所在路径 |
结果
查询所有数据,queryAll:
1 |
[ |
实体类Account中的变量roleList,可以正常保存数据([role_admin, role_common]
)
部署前端项目
将打包好的前端项目,放在static目录下即可。springBoot程序(.jar文件)运行后,访问所设置的端口即可访问前端项目(index.html文件要在static下)。
打包
打开maven面板,双击执行package命令即可。打包后的jar包在target文件夹内,使用命令java
-jar xxx.jar
启动项目。
1 |
... |
启动项目时可以修改SpringBoot的配置,例如:
java -jar xxx.jar --server.port=8090 --spring.datasource.username=root --spring.datasource.password=123456
设置端口为8090,数据库账号为root,数据库root账号的密码为123456