0%

SpringBoot

SpringBoot概述

SpringBoot引言

Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化Spring应用的 初始搭建以及开发过程。该框架使用了特定的方式来进行配置,从而使开发人员不 再需要定义样板化的配置。通过这种方式,Spring Boot致力于在蓬勃发展的快速应 用开发领域(rapid application development)成为领导者。

Spring Boot 全新框架 作用: 简化spring应用初始搭建和开发过程

如何简化: 开发人员使用springboot只要基于特定方式进行配置 简化spring使用

SpringBoot 微框架: 5分钟 完成之前ssm中环境

springboot(微框架) = springmvc(控制器) + spring core(项目管理)

SpringBoot的优势

  1. 创建完整的独立的Spring应用程序 spring springmvc 只有一个容器
  2. 嵌入的Tomcat,无需部署WAR文件 springboot 内嵌tomcat 应用跑在内嵌服务器
  3. 简化Maven配置,自动配置Spring Springmvc,没有XML配置 几个依赖
    1. 用来springboot spring应用再无xml

SpringBoot的约定

  • springboot 项目中必须在src/main/resources中放入application.yml(.properties)核心配置文件

    名字必须为:application

  • springboot 项目中必须在src/main/java中所有子包之外构建全局入口类型,xxApplication,入口类一个springboot项目只能有一个

环境搭建

环境要求

1
2
3
4
5
6
7
8
9
10
# 1.System Requirements
JDK1.8+
MAVEN3.2+
Spring Framework 5.x+

# 2.ServletContainers:
Tomcat 9.0+

# 3.开发工具
IDEA 2021版本

新建项目引入依赖

再pom.xml中加入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!--继承springboot的父项目-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.0</version>
</parent>

<dependencies>
<!--引入springboot的web支持-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>

引入配置文件

项目中 src/main/resources/application.yml

编写入口类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**总结:
* 1.pom文件引入依赖
* 2.resources生成application.yml
* 3.创建入口类加入@SpringBootApplication注解,在main中启动应用
*/
//这个注解:修饰范围:用在类上,只能用在入口类上,且只能出现一次
//作用:标识这个类是springboot的入口类,启动整个springboot的总入口
@SpringBootApplication
public class SpringBootDay1Application {
public static void main(String[] args) {
//启动springboot应用,参数1:指定入口类的类对象 .class
// 参数2: main函数的参数
SpringApplication.run(SpringBootDay1Application.class, args);

}
}

运行main启动项目

启动成功✌

注意:到这里项目环境已经搭建成功了😄😁😁

建包并创建控制器

1
2
3
4
5
6
7
8
9
@RestController
public class HelloController {
//测试控制器
@RequestMapping("hello")
public String hello() {
System.out.println("hello springboot....");
return "hello springboot";
}
}

访问项目

springboot 默认启动默认项目名

http://localhots:8080/

修改服务器端口和应用名称

1
2
3
4
server:
port: 8081 # 修改内嵌服务器端口号
servlet:
context-path: /springboot_day1 #修改项目名 注意:项目名必须以 "/" 开头

相关注解说明

@SpringBootApplication:

  • 组合注解,由多个注解组合而成
    • 元注解:用来修饰注解的注解 @Target:指定注解的作用范围 @Retention:指定注解什么时候有效
  • 等价于以下三个注解
    • @SpringBootConfiguration:这个注解用来自动配置spring, springmvc(初始化servlet ..)相关环境
    • @EnableAutoConfiguration:开启自动配置 自动配置核心注解 自动配置spring相关环境,自动与项目中引入第三方环境自动配置
      • mybatis-springboot, redis-springboot, es-springboot, rabbitmq-springboot等第三方技术
    • @ComponentScan: 组件扫描,根据注解发挥注解作用,默认扫描当前包及其子包

配置文件

配置文件的拆分

说明: 在实际开发过程中生产环境和测试环境有可能是不一样的 因此将生产中的配置和测试中的配置拆分开,是非常必要的在springboot中也提供了配置文件拆分的方式. 这里以生产中项名名称不一致为例:

  • 生产中项目名为: springboot

  • 测试中项目名为: springboot_day1

  • 端口同时为: 8080

主配置文件

1
2
3
4
5
6
7
8
9
10
# 公共配置
server:
port: 8081 # 修改内嵌服务器端口号
#servlet:
# context-path: /springboot_day1 #修改项目名 注意:项目名必须以 "/" 开头

# 激活哪个环境
spring:
profiles:
active: prod #让dev环境生效

生产配置文件 application-prod.xml

1
2
3
server:
servlet:
context-path: /springboot #生产项目名

测试配置文件 application-dev.xml

1
2
3
server:
servlet:
context-path: /springboot_day1 #测试项目名

启动指定配置文件

说明: 往往在企业级开发过程中为SpringBoot应用启动时指定一个完整外部配置也是经常用到的,在SpringBoot中也提供这个方式来启动项目

  1. 创建一个完整的配置文件

    1
    2
    3
    4
    server:
    port: 8080
    servlet:
    context-path: /spring
  2. 启动时指定配置文件的位置

工厂创建对象

创建单个对象

在springboot中可以管理单个对象可以直接使用spring框架中注解形式创建。

  • @Component 通用的对象创建注解
    • @Controller 用来创建控制器对象
    • @Service 用来创建业务层对象
    • @Repository 用来创建DAO层对象
      • 以上注解都有value属性,value属性用来指定工厂中对象名称
1
2
3
4
5
6
7
@Service
public class DemoServiceImpl implements DemoService {
@Override
public void demo() {
System.out.println("demo service ok !");
}
}
1
2
3
4
5
6
7
8
9
10
11
12
@RestController
public class DemoController {
@Autowired
@Qualifier(value = "demoServiceImpl")//用来修改autowired默认不在根据类型注入,修改为根据名称注入
private DemoService demoService;
@RequestMapping("demo")
public String demo() {
System.out.println("demo ok");
demoService.demo();
return "demo ok";
}
}

创建多个对象

如何在springboot中像spring框架一样通过xml创建多个对象,在SpringBoot中也提供了相同注解如**@Configuration + @Bean**注解进行创建

  • @Configuration 代表这是一个spring的配置类相当于Spring.xml配置文件
  • @Bean 用来在工厂中创建这个@Bean注解标识的对象
    • 默认使用@Bean创建对象在工厂中唯一标识为方法名称
    • 修改在工厂中对象标识可以在使用**@Bean(“工厂中名字”)指定一个名字**

管理复杂对象的创建

1
2
3
4
5
6
7
8
@Configuration //修饰范围:只能用在类上 作用:代表这个类是一个配置类 ===> spring.xml
public class BeanConfig {
@Bean //修饰范围:用在方法上或注解上 作用:将方法的返回值交给工厂管理 bean id class
//方法名:推荐返回值首字母小写,代表当前创建对象在工厂中的名称
public Calendar calendar() {
return Calendar.getInstance();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@RestController
public class DemoController {
@Autowired
@Qualifier(value = "demoService")//用来修改autowired默认不在根据类型注入,修改为根据名称注入
private DemoService demoService;
@Autowired
@Qualifier(value = "calendar")
private Calendar calendar;

@RequestMapping("demo")
public String demo() {
System.out.println("demo ok");
demoService.demo();
System.out.println("工厂中获取的日历对象,当前日期:" + calendar.getTime());
return "demo ok";
}
}

属性注入

基本属性注入

1
# 1.@Value 属性注入 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
package com.sineagle.controller;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Date;
import java.util.List;
import java.util.Map;

/**
* 用来测试属性的注入
*/
@RestController
public class InjectionController {
@Value("${name}")
private String name;
@Value("${age}")
private Integer age;
@Value("${price}")
private Double price;
@Value("${birthday}")
private Date birthday;
@Value("${sex}")
private Boolean sex;
@Value("${qqs}")
private String[] qqs;
@Value("${lists}")
private List<String> lists;
@Value("#{${maps}}") //注入map集合时,配置文件中要使用json格式赋值,在注入时必须使用 "#{${xx}}" 进行获取
private Map<String, String> maps;

@RequestMapping("inject")
public String inject() {
System.out.println("inject ok");
System.out.println("name = " + name);
System.out.println("age = " + age);
System.out.println("price = " + price);
System.out.println("birthday = " + birthday);
System.out.println("sex = " + sex);
System.out.println("遍历数组");
for (String qq: qqs) {
System.out.println("qq = " + qq);
}
System.out.println("=======================");
System.out.println("遍历list");
lists.forEach(li -> System.out.println("li = " + li));
System.out.println("=======================");
System.out.println("遍历Map");
maps.forEach((key, value) -> System.out.println("key = " + key + ", value = " + value));
System.out.println("=======================");

return "inject ok";
}
}

1
# 2.在配置文件中定义注入值
1
2
3
4
5
6
7
8
9
#声明基本注入值
name: 小陈
age: 30
price: 23.23
birthday: 2012/12/12 12:12:12 #日期格式 yyyy/mm/dd HH:MM:ss
sex: true
qqs: 123, 456, 789 #注入多个元素,用","隔开
lists: xiaoming, xiaochen, xiaosun, xiaohong #和数组一致
maps: "{'aa':'小虎', 'bb':'小张'}" #注入map集合可以使用json形式,注意:使用@Value注入时必须加入#{${属性}}
  • 注意: 这里面map集合注入比较特殊

对象方式注入

注意: 这种方式必须提供SET方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
@RestController
@ConfigurationProperties(prefix="orders") //修饰范围:用在类上
//用来将指定前缀的属性,注入到当前对象属性名一致的属性中
//注意:使用这个注解为属性一次赋值,必须为属性提供set方法
public class InjectionObjectController {

private String name;
private Integer id;
private Double price;

public void setName(String name) {
this.name = name;
}

public void setId(Integer id) {
this.id = id;
}

public void setPrice(Double price) {
this.price = price;
}

@RequestMapping("injectObject")
public String injectObject() {
System.out.println("injectObject ok ! ");
System.out.println("name = " + name);
System.out.println("id = " + id);
System.out.println("price = " + price);
return "injectObject OK ! ";
}
}

编写配置文件

1
2
3
4
5
#声明对象方式注入
orders:
id: 21
name: xiaoming
price: 23.33

引入依赖构建自定义注入元数据

1
2
3
4
5
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>

JSP模板集成

引入jsp集成的jar包

1
2
3
4
5
6
7
8
9
10
11
12
<!--c标签库-->
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>

<!--让内嵌tomcat具有解析jsp功能-->
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
</dependency>

引入 jsp 的运行插件

1
2
3
4
5
6
7
8
9
10
<build>
<finalName>springboot_day1</finalName>
<!--引入springboot插件 可以正确打包 显示jsp-->
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

配置视图解析器

1
2
3
4
5
6
#在配置文件中引入视图解析器
spring:
mvc:
view:
prefix: / # /代表访问项目中webapp中页面
suffix: .jsp

第一种方式使用插件方式启动访问jsp页面

第二种方式使用idea中指定工作目录启动 访问JSP

修改jsp无须重启应用

1
2
3
4
5
server:
servlet:
jsp:
init-parameters:
development: true

整合Mybatis框架

回顾spring框架如何整合mybatis ?

  1. 引入依赖

    • spring相关
    • mysql相关 驱动 数据源
    • mybatis相关: mybatis核心jar mybatis和spring框架的整合
  2. spring.xml

    • 开启注解扫描

    • 创建数据源对象

      • 注入 指定使用哪种数据源 类型 注入driverClassName 注入url, 注入username, password
    • 创建sqlSessionFactory数据源

    • 注入数据源,注入mapper配置文件的位置 注入实体别名的包

    • 创建dao对象

    • 注入sqlSessionFactory 以及 Dao接口所在的包

    • 创建事务管理器

      • 注入 数据源对象
    • 在业务层组件上加入事务注解 @Transactional

      1
      <tx:annotation-driven transaction-manager="transactionManager"/>
  3. 测试

    • 建表
    • 开发实体类
    • 开发Dao接口
    • 开发Mapper配置文件
    • 开发Service接口
    • 开发ServiceImpl实现类
    • 测试ServiceImpl

SpringBoot框架中如何整合mybatis框架

1. 引入依赖

  • springboot-web

  • mysql相关 mysql驱动 druid数据源

  • mybatis相关的(mybatis-spring-boot-starter)依赖(包含之前的mybatis, mybatis-spring)

2. 书写配置

  1. 开启注解扫描 (@SpringBoolApplication @ComponentScan) 故可省略

  2. 创建数据源

    1. 指定数据源类型
    2. 指定数据库驱动
    3. 指定url
    4. 指定username
    5. 指定password
  3. 创建sqlSessionFactory

    1. 指定mapper配置文件的位置
    2. 指定实体所在包的位置 起别名
  4. 创建Dao

    1. 指定dao接口所在的包
  5. 创建事务管理器 开启注解式事务生效 省略

3. 测试

  • 建表
  • 开发实体类
  • 开发Dao接口
  • 开发Mapper配置文件
  • 开发Service接口
  • 开发ServiceImpl实现类
  • 测试ServiceImpl

例子

引入依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.4</version>
</dependency>

<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.38</version>
</dependency>

<!--整合mybatis-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.4</version>
</dependency>

<!--
说明:由于springboot整合mybatis版本中默认依赖mybatis 因此不需要额外引入mybati版本,否则会出现冲突`-->

配置配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
server:
port: 8989
servlet:
context-path: /springboot_day3

# 整合mybatis相关配置
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.jdbc.Driver #mysql5.x驱动版本
url: jdbc:mysql://localhost:3306/bootssm?characterEncoding=UTF-8
username: root
password: kkk
mybatis:
mapper-locations: classpath:com/sineagle/mapper/*.xml #指定mapper配置文件的位置
type-aliases-package: com.sineagle.entity #指定实体类的包名 默认别名:类名 类名首字母小写



在入口类加入如下配置

1
2
3
4
5
6
7
@SpringBootApplication
@MapperScan("com.sineagle.dao") //修饰范围: 用在类上 作用:用来扫描dao接口所在的包,同时将所有dao接口在工厂中创建对象
public class SpringbootDay3Application {
public static void main(String[] args) {
SpringApplication.run(SpringbootDay3Application.class, args);
}
}

建表

开发实体类

1
2
3
4
5
6
public class Clazz {
private String id;
private String name;
private String no;
//get set 方法省略....
}

开发Dao接口及其Mapper

1
2
3
4
5
6
public interface UserDao  {
//查询所有
List<User> findAll();
void save(User user);
}

1
2
3
4
5
6
7
8
9
10
11
12
13
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.sineagle.dao.UserDao">
<!-- 查询所有-->
<select id="findAll" resultType="User">
select id, name, birthday, salary from `user`
</select>
<insert id="save" parameterType="User" useGeneratedKeys="true" keyProperty="id">
insert into `user` values(#{id}, #{name}, #{birthday}, #{salary})
</insert>
</mapper>

开发Service及其实现

1
2
3
4
5
6
public interface UserService {
//查询所有
List<User> findAll();
void save(User user);
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@Service
@Transactional
public class UserServiceImpl implements UserService {
private UserDao userDao;
@Autowired
public UserServiceImpl(UserDao userDao) {
this.userDao = userDao;
}

@Override
public List<User> findAll() {
return userDao.findAll();
}

@Override
public void save(User user) {
userDao.save(user);
}
}

开发Controller

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package com.sineagle.controller;

import com.sineagle.entity.User;
import com.sineagle.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
public class UserController {
private UserService userService;

@Autowired
public UserController(UserService userService) {
this.userService = userService;
}
//查询所有
@RequestMapping("findAll")
public List<User> findAll() {
return userService.findAll();
}
//保存方法
@RequestMapping("save")
public void save(User user) {
userService.save(user);
}

}

本地测试

spring中本地测试

  1. 启动工厂

    1
    ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
  2. 从工厂中获取指定对象

    1
    UserDao userDao = context.getBean("userDao");
  3. 调用方法

    1
    userDao.xxx(xxx);

springboot框架中完成本地测试

  1. 引入junit和springboot依赖

    1
    2
    3
    4
    5
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
    </dependency>
  2. 启动springboot应用, 才能spring工厂启动, 注入测试对象

    @SpringBootTest

    ​ 修饰范围: 用在类上

    ​ 作用:在这个类实例化过程中启动springboot应用

往往在开发过程中业务代码课程非常复杂频繁启动服务器测试,非常麻烦!这个时候使用本地测试就是一个很好的解决方案,springboot也提供了本地测试解决方案!

引入测试依赖

1
2
3
4
5
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>

编写测试类

  • @SpringBootTest
    • 修饰范围: 用在类上
    • 作用: 用来启动本地Spring环境
1
2
3
4
5
6
7
8
9
10
11
@SpringBootTest
public class TestEmpService {

@Autowired
private EmpService empService;

@Test
public void test(){
empService.findAll().forEach(emp-> System.out.println(emp));
}
}

热部署工具

开启热部署

在项目中引入依赖(每次搭建项目都需要引入)

1
2
3
4
5
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>

设置idea中支持自动编译(只需要设置一次)

1
2
3
4
5
6
# 1.开启自动编译

Preferences | Build, Execution, Deployment | Compiler -> 勾选上 Build project automatically 这个选项

# 2.开启允许在运行过程中修改文件
ctrl + alt + shift + / ---->选择1.Registry ---> 勾选 compiler.automake.allow.when.app.running 这个选项

启动项目检测热部署是否生效

日志处理

## 引言

​ springboot框架 集成日志 logback 日志

​ Logback是由log4j创始人设计的又一个开源日志组件。目前,logback分为三个模块:logback-core,logback-classic和logback-access。是对log4j日志展示进一步改进!

​ 总结: logback 也是一个开源日志组件 和 log4j作用一致 都是用来生成日志 logback更加轻量

日志的级别

1
2
3
4
5
6
7
8
9
10
11
12
> All < Trace < `DEBUG < INFO < WARN < ERROR` < Fatal < OFF

- OFF | 关闭:最高级别,不打印日志。
- FATAL | 致命:指明非常严重的可能会导致应用终止执行错误事件。
- ERROR | 错误:指明错误事件,但应用可能还能继续运行。
- WARN | 警告:指明可能潜在的危险状况。
- INFO | 信息:指明描述信息,从粗粒度上描述了应用运行过程。
- DEBUG | 调试:指明细致的事件信息,对调试应用最有用。
- TRACE | 跟踪:指明程序运行轨迹,比DEBUG级别的粒度更细。
- ALL | 所有:所有日志级别,包括定制级别。

> 日志级别由低到高: `日志级别越高输出的日志信息越多`

项目中日志的分类

  • 一种是rootLogger: 用来监听日志中所有的运行日志,包括引入jar中的日志
  • 一种是logger: 用来监听指定包中的日志信息

事务

Spring框架中的事务

1) 管理事务的对象:事务管理器(接口,有很多的实现类)

  • 例如:使用jdbc或mybatis访问数据库,使用的事务管理器:DataSourceTransactionManager

2)声明式事务:在xml配置文件或使用注解说明事务控制的内容

  • 控制事务:隔离级别,传播行为,超时时间

3)事务处理方式:

  • Spring框架中的Transactional
  • aspectj框架可以在xml配置文件中,声明事务控制的内容

SpringBoot中使用事务

有两种方式都可以

  1. 在业务方法上加入@Transactional,加入注解后,方法就有事务功能了

  2. 明确在主启动类的上面,加入@EnableTransactionManager

求大佬赏个饭