;
Controller编写
2:使用Spring Initializr快速搭建
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!--SpringBoot父POM坐标-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.1</version>
<relativePath/>
</parent>
<groupId>cn.xw</groupId>
<artifactId>springboot_test</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springboot_test</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!--WEB开发Starter-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--SpringBoot的开发者工具-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<!--SpringBoot测试Starter-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<!--SpringBoot的Maven插件-->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
自动创建的Maven坐标说明
三:SpringBoot基本分析
1:坐标中starters分析及依赖管理
starter是依赖关系的整理和封装。是一套依赖坐标的整合,可以让导入应用开发的依赖坐标更方便。利用依赖传递的特性帮我们把一些列指定功能的坐标打包成了一个starter,我们只需要导入starter即可,无需导入大量坐标;每个Starter包含了当前功能下的许多必备依赖坐标这些依赖坐标是项目开发,上线和运行必须的。同时这些依赖也支持依赖传递。如下Starter:
<!--导入WEB开发Starter-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.4.1</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-json</artifactId>
<version>2.4.1</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<version>2.4.1</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.3.2</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.2</version>
<scope>compile</scope>
</dependency>
</dependencies>
spring-boot-starter-web内部封装的一些列坐标
封装成各个Starter的好处就是让我们更加专注于业务开发,无需关心依赖导入,依赖冲突,及依赖的版本
问:为什么导入的一些Starter不需要写版本呢?
不指定版本是因为maven有依赖传递的特性,可推测starter在父级定义了并锁定了版本;spring-boot-dependencies.xml 文件可以给大家一个答案;继承关系为 spring-boot-starter-parent.xml ==> spring-boot-dependencies.xml 这里面锁定了我们常用的坐标及Stater
编写SpringBoot项目继承spring-boot-starter-parent的好处和特点
①:默认编译Java 1.8
②:默认编码UTF-8
③:通过spring-boot-denpendencies的pom管理所有公共Starter依赖的版本
④:spring-boot-denpendencies通过Maven的依赖传递和版本锁定特性来实现版本管理
⑤:随用随取,不用继承父类所有的starter依赖。
POM文件中的Maven插件功能
<build>
<plugins>
<!-- 作用:将一个SpringBoot的工程打包成为可执行的jar包 -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
补充:可选择的启动器官网介绍,需要则查询这个手册
2:自动配置(AutoConfiguration)分析
所有我们要配置的项目Pivotal团队的开发人员,帮我们写好了,怎么实现的,主要是通过@Configuration实现 SpringBoot采用约定大于配置设计思想,将所有可能遇到的配置信息提前配置好,写在自动配置的jar包中。每个Starter基本都会有对应的自动配置。SpringBoot帮我们将配置信息写好,存放在一个jar包中:spring-boot-autoconfigure-2.4.1.jar;jar包里,存放的都是配置类,让配置类生效的"规则类"
接下来我来介绍一个我们常见的配置类
一:找到项目的External Libraries
二:查找Maven:org.springframework.boot:spring-autoconfigue:2.4.1
三:内部有个spring-boot-autoconfigue-2.4.1.jar
四:点击org ==> web ==> servlet ==> ServletWebServerFactoryAutoConfiguration类
@Configuration(proxyBeanMethods = false) //代表是个配置类 SpringBoot为我们提供的每个配置类都有此注解
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
@ConditionalOnClass(ServletRequest.class)
@ConditionalOnWebApplication(type = Type.SERVLET)
@EnableConfigurationProperties(ServerProperties.class)
@Import({ ServletWebServerFactoryAutoConfiguration.BeanPostProcessorsRegistrar.class,
ServletWebServerFactoryConfiguration.EmbeddedTomcat.class,
ServletWebServerFactoryConfiguration.EmbeddedJetty.class,
ServletWebServerFactoryConfiguration.EmbeddedUndertow.class })
public class ServletWebServerFactoryAutoConfiguration { ... }
补充:我们回到之前点击META-INF ==> spring.factories 这里面配置的是SpringBoot的全部配置类
补充:我们回到之前点击META-INF ==> spring-configuration-metadata.json 这里面配置着各种配置类的信息参数
问:SpringBoot提供这么多配置类,难道是程序运行后就全部导入吗?
不会全部导入,只会根据当前项目的需求选择性的装配所需的配置类,这也是SpringBoot的自动装配一大特性;我们也可以设想一下,一次性装配全部配置类,那该多慢呀;
问:SpringBoot怎么知道程序运行后就自动装配呢?
我们找到SpringBoot入口函数,点开 @SpringBootApplication 注解会发现里面有个 @EnableAutoConfiguration 这个注解就是开启自动配置的
问:开启自动装配后,它咋知道要加载指定配置呢?那么多配置类呢
我们继续看上面的 ServletWebServerFactoryAutoConfiguration 配置类
@Configuration(proxyBeanMethods = false)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
//配置类能否被自动装配主要看 @ConditionalOnClass注解
//此注解是否可以加载到一个叫 ServletRequest.class文件,一旦存在则自动装配
@ConditionalOnClass(ServletRequest.class)
@ConditionalOnWebApplication(type = Type.SERVLET)
@EnableConfigurationProperties(ServerProperties.class)
@Import({ ServletWebServerFactoryAutoConfiguration.BeanPostProcessorsRegistrar.class,
ServletWebServerFactoryConfiguration.EmbeddedTomcat.class,
ServletWebServerFactoryConfiguration.EmbeddedJetty.class,
ServletWebServerFactoryConfiguration.EmbeddedUndertow.class })
public class ServletWebServerFactoryAutoConfiguration { ... }
有了自动配置后,那么基本全部采用默认配置(这也就是为啥说约定大于配置的思想);那么要修改默认配置也是可以的,我们只需在配置文件配置指定的参数即可 官方全部可配置属性 如下常见配置:
# 端口配置
server.port=8888
# 配置context-path项目访问根路径
server.servlet.context-path=/demo
# 开启debug模式,详细日志输出,用于开发的一种设置 默认是false
debug=true
# 配置日志 logging.level.{指定包下的日志}=debug
logging.level.cn.xw=debug
四:SpringBoot的配置文件
SpringBoot是约定大于配置的,配置都有默认值。如果想修改默认配置,可以使用application.properties或application.yml或application.yaml自定义配置。SpringBoot默认从Resource目录加载自定义配置文件。application.properties是键值对类型;application.yml是SpringBoot中一种新的配置文件方式,在使用自定义配置时名称一定要为application,因为是提前约定好的,而且三个后缀名的文件都写上是有个先后顺序,后面可覆盖前面
<includes>
<include>**/application*.yml</include>
<include>**/application*.yaml</include>
<include>**/application*.properties</include>
</includes>
# properties类型配置文件 application.properties
server.port=8080
server.address=127.0.0.1
<!--xml类型配置文件 application.xml-->
<server>
<port>8080</port>
<address>127.0.0.1</address>
</server>
# yml/yaml类型配置文件 application.yml/ymal
server:
port: 8080
address: 127.0.0.1
三种类型文件的配置方式
1:yml/yaml配置文件语法及使用
YML文件格式是YAML(YAML Aint Markup Language)编写的文件格式。可以直观被电脑识别的格式。容易阅读,容易与脚本语言交互。可以支持各种编程语言(C/C++、Ruby、Python、Java、Perl、C#、PHP)。以数据为核心,比XML更简洁。扩展名为.yml或.yaml 官方网站 在线properties转yml
1:大小写敏感
2:数据值前边必须有空格,作为分隔符
3:使用缩进表示层级关系
4:缩进不允许使用tab,只允许空格
5:缩进的空格数不重要,只要相同层级的元素左对齐即可
6:"#"表示注释,从这个字符一直到行尾,都会被解析器忽略。
7:数组和集合使用 "-" 表示数组每个元素
# 单个值指定
name: 小周
# 单引号忽略转义字符
message1: 'hello \n world'
# 双引号识别转义字符 打印时会换行
message2: "hello \n world"
# 对象方式指定 普通写法
student:
name: 张三
age: 25
address: 安徽六安
# 对象方式指定 行内写法
teacher: { name: 李老师, age: 50, address: 上海 }
# 数组方式 普通写法
hobby:
- baseball
- basketball
- volleyball
# 数组方式 行内写法
likes: [ baseball, basketball, volleyball ]
# 集合方式 map等格式
peoples:
key1: zhangsan
key2: anhui
key3: xiezi
# 集合方式 map等格式 行内写法
peoples1: { key1 : zhangsan, key2 : anhui , key3 : shanghai}
# 这上面的key~ 是具体的key名称
######## 其它方式扩展
# 配置引用
bookName: 零基础学Java
person:
name: xiaowu
likeBookName: ${bookName}
# 配置随机数 其中有int 和 long两种根据情况选择
# 随机字符串
StringA: ${random.value}
# 随机数
numberB: ${random.int}
# 随机产出小于10的数
numberC: ${random.int(10)}
# 随机产出10~100之间的数 大于10小于100
numberD: ${random.int(10,100)}
# 随机产出一个uuid字符串
uuid: ${random.uuid}
yml基本格式写法
2:配置文件与配置类属性映射
(1):java配置获取基本的配置文件信息.properties类型
三:配置类 jdbcConfig.java
//声明此类为配置类
@Configuration
//导入外部配置文件 因为这个配置类是自定义的,不受SpringBoot帮我们管理
@PropertySource(value="classpath:application.properties")
public class JdbcConfig {
@Value(value = "${jdbc.datasource.driver-class-name}")
private String driver;
@Value("${jdbc.datasource.url}")
private String url;
@Value("${jdbc.datasource.username}")
private String username;
@Value("${jdbc.datasource.password}")
private String password;
@Bean(value = "dataSource")
public DataSource getDataSource() {
System.out.println(driver);
//创建连接池 并加入容器
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName(driver);
dataSource.setUrl(url);
dataSource.setUsername(username);
dataSource.setPassword(password);
return dataSource;
四:Controller 通过访问运行程序 这里就先不写测试类
@RestController //结合@ResponseBody 和 @Controller 两注解
@RequestMapping("/index")
public class IndexController {
@Autowired
private DataSource dataSource;
@RequestMapping("/test")
public String testMethod() {
System.out.println("访问到此方法"+dataSource);
return "Hello !!";
//打印
访问到此方法{
CreateTime:"2021-01-09 15:22:49",
ActiveCount:0,
PoolingCount:0,
CreateCount:0,
DestroyCount:0,
CloseCount:0,
ConnectCount:0,
Connections:[
基本数据获取.properties
(2):java配置获取基本的配置文件信息并注入.yml/.yaml类型
1、使用注解@Value映射
@value注解将配置文件的值映射到Spring管理的Bean属性值,只能映射基本数据类型
2、使用注解@ConfigurationProperties映射
通过注解@ConfigurationProperties(prefix=''配置文件中的key的前缀")可以将配置文件中的配置自动与实体进行映射。
使用@ConfigurationProperties方式必须提供Setter方法,使用@Value注解不需要Setter方法
注:使用@ConfigurationProperties要在主函数上开启@EnableConfigurationProperties
* @author: xiaofeng
* @date: Create in $DATE
* @description: 学生对象
* @version: v1.0.0
@Component //一定要保证被映射注入的是个组件
@ConfigurationProperties(prefix = "student") //可以之间映射对象
public class Student {
private Integer id; //id
private String name; //姓名
private String address; //住宅
private List<String> hobbys; //爱好
private Map<String, List<Integer>> score;//各科得分
private Map<String,Teacher> teachers; //各科老师
//...省略get/set 这个一定要写 我为了代码少没复制
* @author: xiaofeng
* @date: Create in $DATE
* @description: 老师对象
* @version: v1.0.0
public class Teacher {
private String name;
private String message;
//注:在添加完@ConfigurationProperties后如果没有spring-boot-configuration-processor编译器会弹出提示
//提示信息:Spring Boot Configuration Annotation Processor.....
//pom.xml添加这个配置注解处理器
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
//然后去主函数类上面添加@EnableConfigurationProperties 开启配置注解处理器
POJO实体类
student:
id: 1001
name: 张三
address: 安徽六安
hobbys:
- baseball
- basketball
- volleyball
score:
yuwen:
shuxue:
#简写 score: { "yuwen" : [58,99], "shuxue" : [88,96] }
# 这里通过外界传入值 注意引号别忘了
teachers:
yuwenTeacher: { name: "${teacherNameA}", message: "${teacherMessageA}" }
shuxueTecher: { name: "${teacherNameB}", message: "${teacherMessageB}" }
teacherNameA: 张老师
teacherMessageA: 教语文
teacherNameB: 李老师
teacherMessageB: 教数学
application.yml配置文件
//通过web的方式加载程序运行
@RestController //结合@ResponseBody 和 @Controller 两注解
@RequestMapping("/index")
public class IndexController {
//注入
@Autowired
private Student student;
@RequestMapping("/test")
public String testMethod() {
System.out.println(student.toString());
//Student{
// id=1001,
// name='张三',
// address='安徽六安',
// hobbys=[baseball, basketball, volleyball],
// score={yuwen=[66, 88], shuxue=[85, 99]},
// teachers={yuwenTeacher=Teacher{name='张老师', message='教语文'},
// shuxueTecher=Teacher{name='李老师', message='教数学'}}}
return "Hello !!";
五:SpringBoot与其它技术集成
1:SpringBoot集成MyBatis 建表语句
集成Mybatis完成查询全部
(1):使用注解方式完成集成
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.1</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>cn.xw</groupId>
<artifactId>demomybatiss</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demomybatiss</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!--web启动器-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--spring-boot启动器-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.4</version>
</dependency>
<!--工具-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<!--mysql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!--测试 这里没用到-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
pom.xml文件
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/demo_school?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
username: root
password: 123
# 加上 ?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC 是为了防止SpringBoot报时区错误
# com.mysql.jdbc.Driver 这种的已经过时了,但是不代表就剔除了 可以用
resources下的application.yml配置文件
///////////POJO
* @author: xiaofeng
* @date: Create in $DATE
* @description: 学生实体类
* @version: v1.0.0
public class Student implements Serializable {
private int id; //id
private String name; //姓名
private String sex; //性别
private int age; //年龄
private double credit; //成绩/学分
private double money; //零花钱
private String address; //住址
private String enrol; //入学时间
//private int fid; //外键 家庭
//private int tid; //外键 老师
//构造器(无参构造器必须有)/set/get/toString 你们补充一下
/////////// Mapper
//此注解org.apache.ibatis.annotations.Mapper 是mybatis提供的加入容器
//Mapper 可以说等于 @Component、@Repository、@Server、@Controller
@Mapper
public interface StudentMapper {
//查询全部
@Select("select * from student")
@Results(id = "studentMapper", value = {
@Result(id = true, column = "sid", property = "id"),
@Result(column = "sname", property = "name"),
@Result(column = "ssex", property = "sex"),
@Result(column = "sage", property = "age"),
@Result(column = "scredit", property = "credit"),
@Result(column = "smoney", property = "money"),
@Result(column = "saddress", property = "address"),
@Result(column = "senrol", property = "enrol")
List<Student> findAll();
///////////Service
* @author: xiaofeng
* @date: Create in $DATE
* @description: 学生业务接口
* @version: v1.0.0
public interface StudentService {
//查询全部
List<Student> findAll();
* @author: xiaofeng
* @date: Create in $DATE
* @description: 学生业务实现
* @version: v1.0.0
@Service //注入到容器
public class StudentServiceImpl implements StudentService {
//注入对象 如果是IDEA编译器这边会有个红线错误,不影响
@Autowired
private StudentMapper studentMapper;
//查询全部
@Override
public List<Student> findAll() {
return studentMapper.findAll();
//////////Controller
@RestController
@RequestMapping("/student")
public class StudentController {
@Autowired
private StudentService studentService;
@RequestMapping("/findAll")
public List<Student> findAll() {
System.out.println("访问成功");
//这里通过json把对象写到浏览器,要序列化对象
return studentService.findAll();
POJO、Mapper、Service、Controller文件
注:使用http://localhost:8080/student/findAll访问,还有就是Mapper文件夹里面的代码一定要写在主函数类当前包及其子包下,如果不在则需要在入口类添加@MapperScan或者@MapperScans注解扫描一下,这个是mybatis提供的
(2):使用Mapper.xml映射完成集成
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/demo_school?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
username: root
password: 123
# spring继承mybatis环境
# type-aliases-package:pojo别名扫描包
# mapper-locations:加载mybatis映射文件
mybatis:
type-aliases-package: cn.xw.pojo
mapper-locations: classpath:mapper/*Mapper.xml
# 加上 ?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC 是为了防止SpringBoot报时区错误
# com.mysql.jdbc.Driver 这种的已经过时了,但是不代表就剔除了 可以用
更改application.yml
<?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="cn.xw.mapper.StudentMapper">
<!--名称字段不一样可以使用这个映射名称对应-->
<resultMap id="studentMapper" type="student">
<id column="sid" property="id"/>
<result column="sname" property="name"/>
<result column="ssex" property="sex"/>
<result column="sage" property="age"/>
<result column="sscore" property="credit"/>
<result column="smoney" property="money"/>
<result column="saddress" property="address"/>
<result column="senrol" property="enrol"/>
</resultMap>
<!--查询全部学生 要使用上面的resultMap才可以-->
<select id="findAll" resultMap="studentMapper">
select * from student;
</select>
</mapper>
在resources下创建mapper/StudentMapper.xml
删除之前在Mapper使用注解的SQL语句删除,只留方法
2:Spring Boot 集成 Redis
springBoot集成Redis后,以上个案例的基础上做个查询学生缓存,如果第一次查询则缓存到redis服务器里,然后从redis读取数据返回到客户端
<!--导入redis启动器-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
@RestController
@RequestMapping("/student")
public class StudentController {
@Autowired
private StudentService studentService;
//注入redis模板对象
@Autowired
private RedisTemplate redisTemplate;
@RequestMapping("/findAll")
public List<Student> findAll() {
System.out.println("访问成功");
//获取类名
String className = studentService.getClass().getName();
//以类名+方法名的方式作为key来查询redis缓存数据
List<Student> studentList = (List<Student>) redisTemplate.boundValueOps(className + "findAll").get();
//redis没有数据 查询数据库放入到redis
if (studentList == null) {
System.out.println("从数据库查询数据放入到redis");
//查询数据库
studentList = studentService.findAll();
//把查询到的数据放入redis中 key为类名加findAll
redisTemplate.boundValueOps(className + "findAll").set(studentList);
} else {
System.out.println("从redis读取数据缓存");
//这里通过json把对象写到浏览器,要序列化对象
return studentList;
更改StudentController
3:Spring Boot 集成定时器
使用SpringBoot完成一个简易的定时器,每5秒输出一下当前的时间到控制台;
首先在入口函数类上面加@EnableScheduling注解,代表开启定时器
@Component
public class TimerUtil {
* @Scheduled 设置方法执行规则 就是定时任务设置
* cron: 设置一个String类型的cron表达式 这个属性和下面6个不要混用
* fixedDelay 以一个固定的延迟时间,上个任务完成后多久执行下一个任务
* fixedDelayString 和上面一样字符串形式传值
* fixedRate 以一个固定的频率运行,不管上一个任务执行时间
* fixedRateString 和上面一样字符串形式传值
* initialDelay 当项目初始化后多久触发事务的执行
* initialDelayString 和上面一样字符串形式传值
//使用cron表达式
@Scheduled(initialDelay=10000,fixedDelay = 5000)
public void myTask(){
System.out.println("当前时间:"+new Date());
//注:写在入口函数类可扫描的范围包下
编写定时器类
4:Spring Boot 集成Test单元测试
<!--测试启动start-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
//@RunWith(SpringRunner.class) 在老版的SpringBoot项目需要这个
//2.2.0.RELEASE以后,springboot测试类不再需要@Runwith的注解
@SpringBootTest //注明为SpringBoot测试类
class DemomybatissApplicationTests {
//注入StudentService对象
@Autowired
private StudentService studentService;
@Test
void contextLoads() {
System.out.println(studentService.findAll());
5:Spring Boot 发送HTTP请求
要在SpringBoot内部发送HTTP请求就得用到RestTemplate模板,它是Rest的HTTP客户端模板工具类;对基于HTTP客户端进行了封装;还实现了对象与JSON的序列化与反序列化;不限定客户端类型,目前常用的3种客户端都支持:HttpClient、OKHttp、JDK原生URLConnection(默认方式)
@SpringBootApplication
@EnableScheduling //开启定时器注解
public class DemomybatissApplication {
public static void main(String[] args) {
SpringApplication.run(DemomybatissApplication.class, args);
//注册RestTemplate对象放入IOC容器
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
入口函数类更改
//@RunWith(SpringRunner.class) 在老版的SpringBoot项目需要这个
@SpringBootTest //注明为SpringBoot测试类
class DemomybatissApplicationTests {
//注入RestTemplate对象
@Autowired
private RestTemplate restTemplate;
@Test
void contextLoads() {
//String.class代表以字符串形式接收结果
String forObject = restTemplate.getForObject("http://baidu.com", String.class);
System.out.println(forObject);
//打印
//<html>
//<meta http-equiv="refresh" content="0;url=http://www.baidu.com/">
//</html>
编写RestTemplate发送Http请求测试类
6:Spring Boot 集成 jsp
其实我们集成JSP技术是官方不推荐的(推荐使用Thymeleaf),也可以发现在项目中导入了web的启动坐标时的项目会在src/main/resources下多出一个templates目录,这就是让我们创建模板文件的,但并没有诸如webapp的目录,那我们该怎么使用呢?导入坐标即可,并简单配置
<dependencies>
<!--springboot集成web启动坐标-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--引入解析jsp页面的依赖-->
<!--Jasper是tomcat中使用的JSP引擎-->
<!--就是把JVM不认识的JSP文件解析成java文件,然后编译成class文件提供使用。
目前有很多的JSP解析引擎,Tomcat中使用的是Jasper。-->
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
</dependency>
<!--JSTL标准库-->
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
</dependencies>
修改application.yml文件:
server:
# 设置端口
port: 8888
servlet:
# 配置 开启jsp页面热部署
init-parameters:
development: true
spring:
mvc:
view:
# 配置mvc的前缀和后缀 类型下面的
prefix: /WEB-INF/pages/
suffix: .jsp
# 下面这种就是我们以前在spring中来集成mvc的xml中配置映射
# <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
# <property name="prefix" value="/WEB-INF/pages/"/>
# <property name="suffix" value=".jsp"/>
# </bean>
<%--webapp/login.jsp--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<title>Title</title>
</head>
<h1>登录模拟页面</h1>
<a href="${pageContext.request.contextPath}/student/login?name=tom">点击登录</a>
</body>
</html>
<%--webapp/WEB-INF/pages/index.jsp--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<title>Title</title>
</head>
<h2>欢迎登录成功</h2>
<c:forEach items="${requestScope.get('students')}" var="stu">
<h5>姓名:${stu.name}</h5>
<h5>年龄:${stu.age}</h5>
<h5>性别:${stu.sex}</h5>
<h5>住址:${stu.address}</h5>
宠物:${stu.dog.name} ## ${stu.dog.color}
</c:forEach>
</body>
</html>
* @Author AnHui_XiaoYang
* @Email [email protected]
* @Date 2021/6/16 8:22
* @Description
@Controller
@RequestMapping("/student")
public class StudentController {
//模拟登录的controller
@GetMapping("/login")
public ModelAndView hello(@RequestParam(value = "name") String name) {
System.out.println("成功访问到 login的控制器 参数获取name:" + name);
//创建数据
ArrayList<Student> list = new ArrayList<>();
list.add(new Student(name + "001", 23, "男", "安徽六安", new Dog("大黄", "#ff0")));
list.add(new Student(name + "002", 24, "女", "安徽合肥", new Dog("大白", "#fff")));
list.add(new Student(name + "003", 22, "男", "安徽蚌埠", new Dog("大蓝", "#00f")));
//创建视图模型对象封装数据和跳转页面(request域和转发)
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("index");
modelAndView.addObject("students", list);
return modelAndView;
controller代码
public class Student {
private String name;
private Integer age;
private String sex;
private String address;
private Dog dog;
public class Dog {
private String name;
private String color;
注:如果运行时出现404问题,先确保是否路径正确,如果正确却404执行以下解决方案
①:插件方式启动jsp
<!--配置后可以使用Springboot插件启动项目,因为将项目打成jar包必须导入此插件-->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<!--设置编码 可以不用设置,但是编码一定要保持一致-->
<jvmArguments>-Dfile.encoding=UTF-8</jvmArguments>
</configuration>
</plugin>
②:修改运行配置
SpringBoot除了上面几个集成外还集成 MongoDB、ElasticSearch、Memcached、邮件服务:普通邮件、模板邮件、验证码、带Html的邮件、RabbitMQ消息中间件、Freemarker或者Thymeleaf等等
六:SpringBoot打包部署
启动方式有两种,一种是打成jar直接执行,另一种是打包成war包放到Tomcat服务下,启动Tomcat
1:打成Jar包部署运行
注:pom文件里的<packaging>jar</packaging>必须为jar,默认就是jar
* 第一步:使用IDEA工具把写的代码通过maven的package打包
* 第二步:找到打包后的target文件夹里面,把xxx.jar包扔给测试
* 第三步:自己测试的话使用cmd执行下面命令,前提得检查自己的pom.xml文件中是否有springboot的maven插件
* java -jar xxxx.jar
* 补充:在运行的时候传递参数 通过main函数的args接收
* java -jar xxxx.jar --server.port=8888
* 补充:在运行的时候配置jvm参数,使占用更少的内存
* java -Xmx80m -Xms20m -jar xxxx.jar
2:打成War包部署运行
注:pom文件里的<packaging>war</packaging>必须为jar,默认就是war
创建一个类如:ServletInitializer.java,继承 SpringBootServletInitializer ,覆盖 configure(),
把启动类 Application 注册进去。外部 Web 应用服务器构建 Web Application Context 的时候,
会把启动类添加进去。
//如下代码创建的类 除了类名和注册的启动类不一样,其它是固定写法
//WEB-INF/web.xml
public class ServletInitializer extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
//DemoApplication是自己当前项目的主函数
return builder.sources(DemoApplication.class);
七:SpringBoot热部署
我们在之前每次写完代码之后都要重新部署运行,这样特别浪费时间,其实SpringBoot是支持热部署的,但是我们得有相对应的参数配置,导入坐标
检查当前的pom.xml必须有此配置才可以,然后正常启动运行即可
<!--工具 用于设置热部署,optional必须为true-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
当我们的代码写文运行后,后期更改了代码无需重写部署,只需要按CTRL+F9(Build Project),这是快速构建项目,或点击有上角的锤子;
如果还觉得麻烦,那就设置,一旦更改代码,IDEA失去焦点就自动构建代码,我们要设置一下IDEA配置
八:SpringBoot配置文件深入
1:多环境配置文件
我们在开发Spring Boot应用时,通常同一套程序会被安装到不同环境,比如:开发dev、测试test、生产pro等。其中数据库地址、服务器端口等等配置都不同,如果每次打包时,都要修改配置文件,那么非常麻烦。profile功能就是来进行动态配置切换的。
(1):单文件的多环境配置
# 在只有application.yml一个文件下配置多个配置环境就需要使用 " --- " 分隔界限
# 为了规范 Dev为开发 Test为测试 Pro为生产
# 配置完以后在这里选择要使用的配置环境
spring:
profiles:
# 开启哪个环境下的配置文件
active: oo
# 引用包含哪个配置文件
include: global
# 开发环境配置 Dev
server.port: 8881
# 设置当前的配置界限为 dev开发环境
spring.profiles: dev
# 测试环境配置 Test
server.port: 8882
spring.profiles: test
# 生产上线环境配置 Pro
server.port: 80
spring.profiles: pro
# 全局的配置供include包含使用
server.servlet.context-path: /littleBird
spring.profiles: global
单个application.yml配置文件完成多环境配置 不推荐
(2):多文件的多环境配置
⭐:application.yml 主配置文件(必须有)
# 为了规范 Dev为开发 Test为测试 Pro为生产
# 配置完以后在这里选择要使用的配置环境
spring:
profiles:
# 开启哪个环境下的配置文件
active: dev
# 引入包含共有配置
include: common
⭐:application-dev.yml/properties 开发环境配置
# 开发环境
server.port: 8881
⭐:application-test.yml/properties 测试环境配置
# 测试环境
server.port: 8882
⭐:application-pro.yml/properties 生产环境配置
# 上线环境
server.port: 80
⭐:application-common.yml/properties 公共环境配置
# 公共配置 供其包含导入
server.servlet.context-path: /littleBird
多文件配置多环境 推荐
(3):profile激活方式
在上面我介绍了使用配置文件来指定配置环境:spring.profiles.active=xx;可是这个是有局限性的,除了这种方式激活还要另外2种
配置文件: 再配置文件中配置:spring.profiles.active=dev
虚拟机参数:在VM options 指定:-Dspring.profiles.active=dev
命令行参数:java –jar xxx.jar --spring.profiles.active=dev
优先级:命令行参数 > 虚拟机参数 > 配置文件
2:松散绑定
不论配置文件中的属性值是短横线、驼峰式还是下换线分隔配置方式,在注入配置时都可以通过短横线方式取出值;使用范围:properties文件、YAML文件、系统属性
⭐命名各种方式的名称 application.yml文件下定义方式
# 短横线分隔
parameter1:
spring-boot:
student-name: zhangsan
# 驼峰式
parameter2:
springBoot:
studentName: lisi
# 下划线分隔
parameter3:
spring_boot:
student_name: wangwu
⭐命名各种方式的名称 application.properties文件下定义方式
# 短横线分隔
parameter1.spring-boot.student-name=zhangsan
# 驼峰式
parameter2.springBoot.studentName=lisi
# 下划线分隔
parameter3.spring_boot.student_name: wangwu
⭐取出方式:使用短横线分隔可以取出上面的任意一直格式
注:在@Value获取上面的3种方式命名的配置只能使用短横线分隔通配
否则配置文件写啥名,获取就写啥名,一一对应
@Value(value="${parameter1.spring-boot.student-name}")
@Value(value="${parameter2.spring-boot.student-name}")
@Value(value="${parameter3.spring-boot.student-name}")
松散绑定配置文件介绍
3:配置路径及其加载顺序
4:外部配置加载顺序 官方文档
外部加载顺序就是说在程序运行时加载外部的配置信息的顺序,如我们常用的命令行下指定额外信息 java -jar xxx.jar --server.port=8888
# 这个是2.1.11版本的springboot之前的信息,中文的看的清楚,以具体版本为准
1:开启 DevTools 时, ~/.spring-boot-devtools.properties
2:测试类上的 @TestPropertySource 注解
3:@SpringBootTest#properties 属性
4:==命令?参数(--server.port=9000 )==
5:SPRING_APPLICATION_JSON 中的属性
6:ServletConfig 初始化参数
7:ServletContext 初始化参数
8:java:comp/env 中的 JNDI 属性
9:System.getProperties()
10:操作系统环境变量
11:random.* 涉及到的 RandomValuePropertySource
12:jar 包外部的 application-{profile}.properties 或 .yml
13:jar 包内部的 application-{profile}.properties 或 .yml
14:jar 包外部的 application.properties 或 .yml
15:jar 包内部的 application.properties 或 .yml
16:@Configuration 类上的 @PropertySource
17:SpringApplication.setDefaultProperties() 设置的默认属性
5:修改配置文件位置及默认名称
我们知道配置文件只能以application.yml/properties来定义,但是名称不一样是可以指定具体文件名,也可以把配置文件放入其它位置并指定都是可以的;指定的方式我以cmd下指定参数 java -jar xxx.jar --xxx -xxx 方式指定,或在IDEA里面指定-xxx参数
# 自定义配置文件名称
--spring.config.name=myApplication
# 指定配置文件存储位置 或 指定配置文件存储位置及配置文件名称
--spring.config.location=classpath:/myconfig/myApplication.yml
注:多个配置参数以空格隔开 --xxx -xxx
九:SpringBoot监听器
我们知道JavaEE包括13门规范,其中Servlet规范包括三个技术点:Servlet、Listener、Filter;而本章介绍的是监听器,监听器就是监听某个对象的状态变化;SpringBoot中的监听器有很多种:如下
①:CommandLineRunner 应用程序启动完成后
②:ApplicationRunner 应用程序启动完成后
③:ApplicationContextInitializer 程序运行初始化前
④:SpringApplicationRunListener 多功能监听器
1:对开发者有益的监听器
@Component //实现CommandLineRunner接口的监听器必须要加入IOC容器
public class MyCommandLineRunner implements CommandLineRunner {
//注 参数args是主函数入口的args传来的
@Override
public void run(String... args) throws Exception {
System.out.println("应用程序启动完成后 打印:CommandLineRunner");
CommandLineRunner 监听器使用
@Component //实现ApplicationRunner接口的监听器必须要加入IOC容器
public class MyApplicationRunner implements ApplicationRunner {
//注 参数args是主函数入口的args传来的
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println("应用程序启动完成后 打印:ApplicationRunner");
ApplicationRunner 监听器使用
2:对框架开发者有意义的监听器 功能多
public class MyApplicationContextInitializer implements ApplicationContextInitializer {
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
System.out.println("程序运行初始化前 打印:ApplicationContextInitializer");
ApplicationContextInitializer 监听器使用
public class MySpringApplicationRunListener implements SpringApplicationRunListener {
//注意:此构造方法必须要写 不写就给你报个错误
public MySpringApplicationRunListener(SpringApplication application, String[] args) {}
@Override
public void starting(ConfigurableBootstrapContext bootstrapContext) {
System.out.println("应用程序开始启动==>starting");
@Override
public void environmentPrepared(ConfigurableBootstrapContext bootstrapContext, ConfigurableEnvironment environment) {
System.out.println("环境准备完成==>environmentPrepared");
@Override
public void contextPrepared(ConfigurableApplicationContext context) {
System.out.println("Spring容器准备完成==>contextPrepared");
@Override
public void contextLoaded(ConfigurableApplicationContext context) {
System.out.println("Spring容器加载完成==>contextLoaded");
@Override
public void started(ConfigurableApplicationContext context) {
System.out.println("应用程序启动完成==>started");
//注:running成功与failed异常只会存在一个
@Override
public void running(ConfigurableApplicationContext context) {
System.out.println("应用程序开始运行==>running");
@Override
public void failed(ConfigurableApplicationContext context, Throwable exception) {
System.out.println("应用程序运行时抛出异常==>failed");
SpringApplicationRunListener 监听器使用
# 说明 在resources目录下创建META-INF文件夹 并在里面创建一个spring.factories
# 主要目的是解耦:将监听器的配置权交给第三方厂商、插件开发者
# 框架提供接口,实现类由你自己来写,释放原生API能力,增加可定制性
# META-INF/spring.factories文件中配置接口的实现类名称
# 配置ApplicationContextInitializer监听器的配置
# 左边监听器的全路径名称=右边实现此监听器的全路径名
org.springframework.context.ApplicationContextInitializer=cn.xw.lintener.MyApplicationContextInitializer
# 配置SpringApplicationRunListener监听器的配置
# 左边监听器的全路径名称=右边实现此监听器的全路径名
org.springframework.boot.SpringApplicationRunListener=cn.xw.lintener.MySpringApplicationRunListener
使用ApplicationContextInitializer/SpringApplicationRunListener监听器必看 配置一些信息才可使用
十:自动配置实现分析
我们在导入spring-boot-starter-web启动器无需其它配置就可以之间用,还有我们导入spring-boot-starter-data-redis启动器后可以直接使用@Autowired直接注入RedisTemplate对象,很奇怪吧,这就是SpringBoot自动配置特性,在下几节我慢慢引入
1:@Import注解进阶
当我们需要导入某个类到spring容器中去,但spring恰好无法扫描到这个类,而我们又无法修改这个类(jar包形式)。我们就可以通过@import(xxx.class)是将这个类导入到spring容器中
(1):直接导入
//配置类 springConfig
@Configuration
@Import(value={DateConfig.class}) //直接导入
public class SpringConfig { }
//普通类,里面有个@Bean注入方法 DateConfig
//被任何一个配置类引用,当前自己类也变为子配置类
public class DateConfig {
//创建时间对象放入容器
@Bean
public Date createDate() { return new Date(); }
(2):通过配置类导入
@Configuration
public class SpringConfig {
//创建时间对象放入容器
@Bean
public Date createDate() { return new Date(); }
@SpringBootApplication
@Import(value={SpringConfig.class}) //导入配置类
public class LintenerDemoApplication {
public static void main(String[] args) {
ConfigurableApplicationContext run = SpringApplication.run(LintenerDemoApplication.class, args);
//打印时间对象
System.out.println(run.getBean(Date.class));
(3):通过ImportSelector接口实现类导入 高级方式
//普通类 里面有个@Bean注入对象
public class DateConfig {
//创建时间对象放入容器
@Bean
public Date createDate() { return new Date(); }
//创建一个类实现ImportSelector
public class MyImportSelector implements ImportSelector {
//这个方法是返回配置类的全类名,导入多少都行,最后通过@Import导入
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
//返回一个数组
return new String[]{"cn.xw.config.DateConfig"};
@SpringBootApplication
@Import(value={MyImportSelector.class}) //导入配置类
public class LintenerDemoApplication {
public static void main(String[] args) {
ConfigurableApplicationContext run = SpringApplication.run(LintenerDemoApplication.class, args);
//打印时间对象
System.out.println(run.getBean(Date.class));
使用ImportSelector接口
2:@Configuration注解进阶
相对这个注解大家肯定不陌生,只要是Spring注解配置类都有这玩意;其实只要添加@Configuration注解的类里面可以衍生出各种条件注解供我们使用,前提只能在注解类下使用,它就是@Conditional条件注解,这个条件注解又衍生出各种详细的条件注解
注:@EnableAutoConfiguration 其本质是 @Import 和 @Configuration的组合
一:class类条件
@ConditionalOnClass == 存在指定类条件
@ConditionalOnMissingClass == 不存在指定类条件
二:属性条件
@ConditionalOnProperty == 属性条件,还可以为属性设置默认值
三:Bean条件
@ConditionalOnBean == 存在Bean条件
@ConditionalOnMissingBean == 不存在Bean条件
@ConditionalOnSingleCondidate == 只有一个Bean条件
四:资源条件
@ConditionalResource == 资源条件
五:Web应用条件
@ConditionalOnWebApplication == web应用程序条件
@ConditionalOnNotWebApplication == 不是web应用程序条件
六:其他条件
@ConditionalOneExpression == EL表达式条件
@ConditionalOnJava == 在特定的Java版本条件
@Configuration还有一些加载顺序的方式
1:@AutoConfigureBefore==在那些自动配置之前执行
2:@AutoConfigureAfter==在那些自动配置之后执行
3:@AutoConfigureOrder==自动配置顺序
(1):@ConditionalOnClass 与 @ConditionalOnProperty 介绍
@ConditionalOnClass注解属性介绍
Class<?>[] value():以类的class形式的数组
String[] name():以类的全路径名的字符串数组
@ConditionalOnProperty注解属性介绍
value 和 name:数组,获取对应property名称的值,它们只能存在其中一个
prefix:配置属性名称的前缀,比如spring.http.encoding
havingValue:可与name组合使用,比较获取到的属性值与havingValue给定的值是否相同,相同才加载配置
matchIfMissing:缺少该配置属性时是否可以加载。如果为true,没有该配置属性时也会正常加载;反之则不会生效
//学生类
public class Student {
private String name;
private String identity;
//省略了get/set,
//老师类
public class Teacher {
private String name;
private String identity;
//省略了get/set,
//需求,当创建Teacher加入容器时得判断当前是否存在Student这个类
@Configuration
@ConditionalOnClass(name = "cn.xw.pojo.Student")
public class SpringConfig {
//可以通过spring.myconfig.enable=true开启 或者false 关闭容器注册
@Bean(value = "teacher")
@ConditionalOnProperty(prefix = "spring.myconfig", name = "enable", havingValue ="true", matchIfMissing = true)
public Teacher createTeacher() {
Teacher teacher = new Teacher();
teacher.setName("张老师");
teacher.setIdentity("老师");
return teacher;
@SpringBootApplication
//导入配置类
@Import(value={SpringConfig.class})
public class LintenerDemoApplication {
public static void main(String[] args) {
ConfigurableApplicationContext run = SpringApplication.run(LintenerDemoApplication.class, args);
//打印时间对象
System.out.println(run.getBean(Teacher.class).getName());
//application.properties
# 关闭容器注册
spring.myconfig.enable=false
案例讲解注解
//注解类
@Configuration(proxyBeanMethods = false)
//条件注解 确保存在RedisOperations类
@ConditionalOnClass(RedisOperations.class)
//@Import 和 @ConfigurationProperties结合 RedisProperties类就是我们配置额外变量的spring.redis
@EnableConfigurationProperties(RedisProperties.class)
//导入配置类
@Import({ LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class })
public class RedisAutoConfiguration {
@Bean
//判断不存在redisTemplate的Bean条件
@ConditionalOnMissingBean(name = "redisTemplate")
//判断只有一个RedisConnectionFactory的Bean条件
@ConditionalOnSingleCandidate(RedisConnectionFactory.class)
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
return template;
//下面差不多
@Bean
@ConditionalOnMissingBean
@ConditionalOnSingleCandidate(RedisConnectionFactory.class)
public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
StringRedisTemplate template = new StringRedisTemplate();
template.setConnectionFactory(redisConnectionFactory);
return template;
RedisTemplate自动注入分析
十一:自定义auto-Configuration及starter
我们平常导入是第三方mybatis-spring-boot-starter启动器都是由第三方提供给,特点就是以mybatis开头,那下面我们自定义starter也得是自定义名称开头,我们要自定义auto-Configuraction并使用必备的四个角色:功能主体框架、自动配置模块、starter模块、开发者引用
1:定制自动配置必要内容
autoconfiguration模块,包含自动配置代码。自定义 *-spring-boot-autoconfigure。
starter模块。自定义 *-spring-boot-starter
2:自动配置命名方式
官方的Starters
spring-boot-starter-* 如:spring-boot-starter-web
非官方的starters
*-spring-boot-starter 如:mybatis-spring-boot-starter
3:SpringBoot起步依赖,Starter Dependencies
接下来我要创建一个第三方模块,功能主体模块是一个图形打印模块,根据配置文件的不同打印出不同的图案,还要就是一个自动配置模块和starter模块咯,最后由我来在普通的springboot应用中调用这个自定义的自动配置
(1):功能主体模块
⭐主体功能模块maven坐标
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>cn.tx</groupId>
<artifactId>graphic-printing</artifactId>
<version>1.0-SNAPSHOT</version>
<!--设置maven使用什么版本的jdk解析编译-->
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
</project>
⭐主体功能模块具体类方法
//图形打印对象
public class GraphicPrintingUtil {
private Integer width = 4;
private Integer height = 3;
//别忘了添加get/set方法,后面会参数注入
//打印图形 方法
public void graphicPrinting() {
System.out.println(">图形开始打印<");
for (int i = 1; i <= height; i++) {
for (int j = 1; j <= width; j++) {
System.out.print(" * ");
System.out.println();
功能主体代码 模块名:graphic-printing
(2):自动配置模块
⭐自动配置模块maven坐标
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!--导入Springboot父坐标-->
<parent>
<artifactId>spring-boot-starter-parent</artifactId>
<groupId>org.springframework.boot</groupId>
<version>2.4.1</version>
</parent>
<!--当前本项目的一些信息-->
<groupId>cn.tx</groupId>
<artifactId>graphic-spring-boot-autoconfigure</artifactId>
<version>1.0-SNAPSHOT</version>
<!--坐标-->
<dependencies>
<!--导入SpringBoot的自动配置坐标 因为代码中要写配置注解-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<!--导入我们之前创建的主体模块graphic-printing-->
<dependency>
<groupId>cn.tx</groupId>
<artifactId>graphic-printing</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
</project>
⭐自动配置模块具体类方法
## GraphicConfiguration类
@Configuration //注解类
@Import(value = {GraphicProperties.class}) //导入配置类
@ConditionalOnClass(GraphicPrintingUtil.class)//判断当前项目是否存在GraphicPrintingUtil类
public class GraphicConfiguration {
@Bean
@ConditionalOnProperty(prefix = "graphic.printing", name = "enable", havingValue = "true", matchIfMissing = true)
//@ConfigurationProperties(prefix = "graphic.config") 可以使用此注解直接注入 注入时值可有可无
public GraphicPrintingUtil createGraphicPrintingUtil(GraphicProperties g) {
//创建图形打印对象,主体模块上的对象
GraphicPrintingUtil printingUtil = new GraphicPrintingUtil();
//设置宽高
printingUtil.setHeight(g.getHeight());
printingUtil.setWidth(g.getWidth());
return printingUtil;
## GraphicProperties 配置类
//这里报红不管他,后面使用者导入<artifactId>spring-boot-configuration-processor</artifactId>
@ConfigurationProperties(prefix = "graphic.config")
public class GraphicProperties {
private Integer width;
private Integer height;
//别忘了写get/set
自动配置代码 模块名:graphic-spring-boot-autoconfigure
# 注册自定义自动配置
# 前面是固定的,后面是自定义配置类
org.springframework.boot.autoconfigure.EnableAutoConfiguration=cn.tx.config.GraphicConfiguration
在resources下创建META-INF文件夹,并在下面创建spring.factories配置
(3):stater模块
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!--自己项目坐标-->
<groupId>cn.tx</groupId>
<artifactId>graphic-spring-boot-starter</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<!--主体功能模块-->
<dependency>
<groupId>cn.tx</groupId>
<artifactId>graphic-printing</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!--自动配置类autoconfigure-->
<dependency>
<groupId>cn.tx</groupId>
<artifactId>graphic-spring-boot-autoconfigure</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
</project>
stater模块 模块名:graphic-spring-boot-starter
注:此模块啥都不用,只要pom.xml文件即可
(3):开发者引用
注:此模块和正常SpringBoot一样,可以使用脚手架构建
⭐使用者maven坐标
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!--springboot父坐标-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.1</version>
<relativePath/>
</parent>
<!--本项目的坐标信息-->
<groupId>cn.xw</groupId>
<artifactId>test001</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>test001</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!--导入我们自定义的stater启动器-->
<dependency>
<groupId>cn.tx</groupId>
<artifactId>graphic-spring-boot-starter</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!--一定要导入,是为了注入配置文件里面的数值-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
<!--maven插件-->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
⭐使用者具体类方法
@SpringBootApplication
public class Test001Application {
public static void main(String[] args) {
ConfigurableApplicationContext run = SpringApplication.run(Test001Application.class, args);
//ConfigurableApplicationContext是ClassPathXmlApplicationContext子类
run.getBean(GraphicPrintingUtil.class).graphicPrinting();
⭐配置文件application.properties
graphic.printing.enable=true
graphic.config.width=10
graphic.config.height=15
开发者模块 模块名:test001
十二:切换内置web应用服务器
SpringBoot的web环境中默认使用tomcat作为内置服务器,其实还提供了另外2种内置服务器供我们选择,我们可以很方便的进行切换。
1:Tomcat:这个是使用最广泛但性能不太好的web应用服务器 默认
2:Jetty:Jetty 是一个开源的servlet容器,它为基于Java的web容器,例如JSP和servlet提供运行环境。
3:Undertow: 是红帽公司开发的一款基于 NIO 的高性能 Web 嵌入式服务器
Tomcat方式:Tomcat started on port(s): 8080 (http) with context path ''
Jetty方式:Jetty started on port(s) 8080 (http/1.1) with context path '/'
Undertow方式:Undertow started on port(s) 8080 (http)
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<!--一定要排除tomcat的starter 因为默认就是tomcat-->
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--导入jetty容器依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
切换为Jetty
<!--导入web的starter启动器-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<!--一定要排除tomcat的starter 因为默认就是tomcat-->
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--导入undertow容器依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
</dependency>
切换Undertow
十三:SpringBoot生产级监控
SpringBoot自带监控功能Actuator,可以帮助实现对程序内部运行情况监控,比如监控状况、Bean加载情况、配置属性、日志信息等
1:项目集成Actuator监控服务
其实导入健康服务特别简单,任何一个SpringBoot只需要加入一个监控启动器则可开启监控服务,然后项目正常运行即可
<!--监控服务Actuator启动器-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
保存SpringBoot导入监控坐标后启动程序,在程序运行的情况下访问 http://localhost:8080/actuator 则可监控程序
补充:默认只可以监控这几项,其实可以监测很多模块
路径 描述 默认开启
/beans 显示容器的全部的Bean,以及它们的关系 N
/env 获取全部环境属性 N
/env/{name} 根据名称获取特定的环境属性值 N
/health 显示健康检查信息 Y
/info 显示设置好的应用信息 Y
/mappings 显示所有的@RequestMapping信息 N
/metrics 显示应用的度量信息 N
/scheduledtasks 显示任务调度信息 N
/httptrace 显示Http Trace信息 N
/caches 显示应用中的缓存 N
/conditions 显示配置条件的匹配情况 N
/configprops 显示@ConfigurationProperties的信息 N
/loggers 显示并更新日志配置 N
/shutdown 关闭应用程序 N
/threaddump 执行ThreadDump N
/headdump 返回HeadDump文件,格式为HPROF N
/prometheus 返回可供Prometheus抓取的信息 N
监控应用endpoint
常用application.properties配置
# 暴露所有的监控点
management.endpoints.web.exposure.include=*
# 定义Actuator访问路径
management.endpoints.web.base-path=/act
# 开启endpoint 关闭服务功能 访问关闭路径只能发送post请求才可关闭
management.endpoint.shutdown.enabled=true
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须在文章页面给出原文链接,否则保留追究法律责任的权利。