SpringBoot

196 阅读14分钟

一、快速入门

  • pom.xml
<parent>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-parent</artifactId>
          <version>3.0.1</version>
      </parent>
   <dependencies>
       <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web -->
       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-web</artifactId>
<!--            <version>3.0.1</version>-->
       </dependency>
   </dependencies>
   <build>
       <plugins>
           <plugin>
               <groupId>org.springframework.boot</groupId>
               <artifactId>spring-boot-maven-plugin</artifactId>
           </plugin>
       </plugins>
   </build>
  • com.xie.controller.HelloController.java
@RestController
public class HelloController {
    @RequestMapping("/hello")
    public String hello(){
        return "hello Spring Boot!";
    }
}
  • com.xie.HlloAplication.java
/**
 * 引导类:SpringBoot项目的入口
 * */
@SpringBootApplication
public class HelloApplication {
    public static void main(String[] args) {
        SpringApplication.run(HelloApplication.class,args);
    }
}
  • 运行

  • 浏览器http://localhost:8080/hello

  • 小结

    • SpringBoot在创建项目时,使用jar的打包方式
    • SpringBoot的引导类,是项目入口,运行main方法就可以启动项目.
    • 使用SpringBooti和Spring构建的项目,业务代码编写方式完全一样.

使用idea快速构建SpringBoot工程

图片.png

图片.png

  • 新建com.xie.HelloController.java
@RestController
public class HelloController {
    @RequestMapping("/hello")
    public String hello(){
        return "SpringBoot快速构建";
    }
}
  • 测试:浏览器http://localhost:8080/hello

二、SpringBoot起步依赖原理分析

  • 在spring-boot-starter-parent中定义了各种技术的版本信息,组合了一套最优搭配的技术版本。
  • 在各种starter中,定义了完成该功能需要的坐标合集,其中大部分版本信息来自于父工程。
  • 我们的工程继承parent,引l入starter)后,通过依赖传递,就可以简单方便获得需要的jar包,并且不会存在版本冲突等问题。

三、SpringBoot配置

3.1 配置文件分类

Spring Boot是基于约定的,所以很多配置都有默认值,但如果想使用自己的配置替换默认配置的话,就可以使用application.properties或者application.yml(application.yml)进行配置。

  • properties:
server.port=8080
  • yaml
server:
    port: 8080

注意:如果三个都配置了,那么properties生效

小结

  1. SpringBoot提供了2种配置文件类型:properteisi和yml/yaml
  2. 默认配置文件名称:application
  3. 在同一级目录下优先级为:properties>yml>yaml

3.2 yaml

YAML全称是YAML Ain't Markup Language。YAML是一种直观的能够被电脑识别的的数据数据序列化格式,并且容易被人类阅读,容易和脚本语言饺互的,可以被支持YAML库的不同的编程语言程序导入,比如:C/C++,Ruby,Python,Java,Perl,C#,PHP等。YML文件是以数据为核心的,比传统的xml方式更加简洁。

YAML文件的扩展名可以使用.yml或者.yaml。

图片.png

3.2.1 基本语法

  • 大小写敏感
  • 数据值前边必须有空格,作为分隔符
  • 使用缩进表示层级关系
  • 缩进时不允许使用Tab键,只允许使用空格(各个系统Tb对应的空格数目可能不同,导致层次混乱)。
  • 缩进的空格数目不重要,只要相同层级的元素左侧吹对齐即可
  • #表示注释,从这个字符一直到行尾,都会被解析器忽略。
server:
    port: 8080
    address: 127.0.0
    
name:abc

3.2.2 数据格式

  • 对象(map):键值对的集合
person:
    name: zhangsan
# 行内写法
person: {name: zhangsan}
  • 数组:一组按次序排列的值
address:
    - beijing
    - shanghai
# 行内写法
address: [beijing,shanghai]
  • 纯量:单个的、不可再分的值
msg1: 'hello \n world'  # 单引忽略转义字符
msg2: "hello \n world"  # 双引识别转义字符
  • 参数引用
name: list

person:
    name: ${name} #引用上边定义的name值

图片.png

3.3 读取配置文件内容

  1. @Value
  2. Environment
  3. @ConfigurationProperties

3.3.1 @value

@RestController
public class HelloController {
    @Value("${name}")
    private String name;
    @Value("${person.name}")
    private String name2;
    @Value("${person.age}")
    private int age;
    @Value("${address[0]}")
    private String address;
    @Value("${msg1}")
    private String msg1;
    @Value("${msg2}")
    private String smg2;

    @RequestMapping("/hello")
    public String hello(){
        return "SpringBoot快速构建";
    }

    @RequestMapping("/hello2")
    public String hello2(){
        System.out.println(name);
        System.out.println("person.name的值:"+name2);
        System.out.println("person底下age的值:"+age);
        System.out.println("获取数组里的值:"+address);
        System.out.println("获取msg1的值:  "+msg1);
        System.out.println("打印msg2:  "+smg2);
        return "获取数据";
    }
}

图片.png

3.3.2 Environment

@RestController
public class HelloController {
    @Autowired
    private Environment env;
    @RequestMapping("/hello2")
    public String hello2(){
        System.out.println(env.getProperty("person.name"));
        System.out.println(env.getProperty("msg1"));
        System.out.println(env.getProperty("address[0]"));
        return "获取数据";
    }
}

3.3.3 @ConfigurationProperties

  • 新建Person.java
@Component
@ConfigurationProperties
public class Person {
    private String name;
    private int age;

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "person{" +
                "name='" + name + ''' +
                ", age=" + age +
                '}';
    }
}
@RestController
public class HelloController {  
    @Autowired
    private Person person;

    @RequestMapping("/hello2")
    public String hello2(){      
        System.out.println(person);
        String[] address= person.getAddress();
        for(String s:address){
            System.out.println(s);
        }
        return "获取数据";
    }
}

这里获取的是这个值 图片.png 要想获取person.name和person.age的值,要添加前缀

@Component
@ConfigurationProperties(prefix = "person")

3.3.4 添加依赖

<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-configuration-processor -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-configuration-processor</artifactId>
    <optional>true</optional>
</dependency>

3.4 profile

我们在开发Spring Boot应用时,通常同一套程序会被安装到不同环境,比如:开发、测试、生产等。其中数据库地址、服务器端口等等配置都不同,如果每次打包时,都要修改配置文件,那么非常麻烦。profile功能就是来进行动态配置切换的。

  1. profile配置方式
    • 多profile文件方式
    spring.profiles.active=dev
    

图片.png * yml多文档方式 2. profile激活方式 * 配置文件 * 虚拟机参数 * 命令行参数

  1. profile是用来完成不同环境下,配置动态切换功能的。
  2. profile配置方式
  • 多profile.文件方式:提供多个配置文件,每个代表一种环境
    • application-dev.properties/,yml开发环境
    • application-test.properties/yml测试环境
    • application-pro.properties./yml生产环境
  • yml多文档方式:
    • 在yml中使用--分隔不同配置
  1. profile激活方式
    • 配置文件:在配置文件中配置:spring.profiles.active:=dev
    • 虚拟机参数:在VM options指定:-Dspring.profiles.active:=dev
    • 命令行参数:java-jarxxx.jar-spring.profiles..active=dev

3.5 内部配置加载顺序

内部配置加载顺序

Springbooti程序启动时,会从以下位置加载配置文件:

  1. file:./config/:当前项目下的/config目录下
  2. file:./ : 当前项目的根目录
  3. classpath:/config/:classpath的/config目录
  4. classpath:/:classpath的根目录

加载顺序为上文的排列顺序,高优先级配置的属性会生效

图片.png

# 修改项目的访问路径 默认为/
server.servlet.context-path=/hello

3.6 外部配置加载顺序

spring.io/spring-boot…

四、SprinBoot整合其他框架

4.1 SpringBoot整合junit

  1. 搭建SpringBoot工程
  2. 引入starter-test起步依赖
  3. 编写测试类
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <scope>test</scope>
</dependency>
  1. 添加测试相关注解
  • @RunWith(SpringRunner.class)
  • @SpringBootTest(classes=启动类.class))
  1. 编写测试方法

图片.png

@Service
public class UserService {
    public void add(){
        System.out.println("add....");
    }
}
/**
 * UserService的测试类
 * */
@RunWith(SpringRunner.class)
@SpringBootTest()
public class UserServiceTest {
    @Autowired
    private UserService userService;
    @Test
    public void testAdd(){
        userService.add();
    }

}

4.2 整合Redis

  1. 搭建SpringBoot框架
  2. 搭建SpringBoot工程
  3. 引入redis起步依赖
  4. 配置redis相关属性
  5. 注入RedisTemplate模板
  6. 编写测试方法,测试

图片.png

4.3 整合mybatis

  1. 搭建SpringBoot工程
  2. 引入mybatisi起步依赖,添加mysq驱动
  3. 编写DataSource和MyBatis相关配置
  4. 定义表和实体类
  5. 编写dao和mapper文件/纯注解开发
  6. 测试

图片.png 图片.png

图片.png

  • domain.User.java
package com.xie.mybatis.domain;

public class User {
    private int id;
    private String username;
    private String password;

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + ''' +
                ", password='" + password + ''' +
                '}';
    }

    public int getId() {
        return id;
    }

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

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}
  • application.yml
# datasource
spring:
  datasource:
    url: jdbc:mysql:///springboot?serverTimezone=UTC
    username: root
    password: root
    driver-class-name: com.mysql.cj.jdbc.Driver
  • mapper.UserMapper.java
@Mapper
public interface UserMapper {
    @Select("select * from t_user")
    public List<User> findAll();
}
  • 测试
@SpringBootTest
class SpringbootMybatisApplicationTests {
    @Autowired
    private UserMapper userMapper;

    @Test
    public void testFindAll() {
        List<User> list = userMapper.findAll();
        System.out.println(list);
    }

}

4.3.1 方法一

@Mapper
public interface UserMapper {
    @Select("select * from t_user")
    public List<User> findAll();
}

测试

@SpringBootTest
class SpringbootMybatisApplicationTests {
    @Autowired
    private UserMapper userMapper;
  
    @Test
    public void testFindAll() {
        List<User> list = userMapper.findAll();
        System.out.println(list);
    }
   }

4.3.2 方法二

  • application.yml
# mybatis
mybatis:
  mapper-locations: classpath:mapper/*Mapper.xml # mapper映射文件路径
  type-aliases-package: com.xie.mybatis.domain

  # config-location:  # 指定mybatis的核心配置文件
  • UserMapper.xml
<?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.xie.mybatis.mapper.UserXmlMapper">
<select id="findAll" resultType="User">
        select * from t_user
    </select>
</mapper>
  • UserXmlMapper.java
@Mapper
public interface UserXmlMapper {
    public List<User> findAll();
}
  • 测试
@SpringBootTest
class SpringbootMybatisApplicationTests {
  
    @Autowired
    private UserXmlMapper userXmlMapper;
    @Test
    public void testFindAll2() {
        List<User> list = userXmlMapper.findAll();
        System.out.println(list);
    }

}

五、SpringBoot原理分析

5.1 Condition

Condition是在Spring 4.0增加的条件判断功能,通过这个可以功能可以实现选择性的创建Bean操作。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

在Spring的IOC容器中有一个User的Bean,现要求:

  1. 导入jedis坐标后,加载该Bean,没导入,则不加载
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
</dependency>
public class User {

}
public class ClassCondition implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
//        1.需求:导入jedis坐标后创建bean
//        思路:判断redis.clients.jedis.Jedis。class文件是否存在
        boolean flag=true;
        try {
            Class<?> aClass = Class.forName("redis.clients.jedis.Jedis");
        } catch (ClassNotFoundException e) {
            flag=false;
        }
        return flag;
    }
}
@Configuration
public class UserConfig {
    @Bean
    @Conditional(ClassCondition.class)
    public User user(){
        return new User();
    }
}
    public static void main(String[] args) {
        ConfigurableApplicationContext context=SpringApplication.run(SpringbootConditionApplication.class, args);
//        Object redis=context.getBean("redisTemplate");
//        System.out.println(redis);
        Object user = context.getBean("user");
        System.out.println(user);
    }
  1. 将类的判断定义为动态的,判断哪个字节码文件存在可以动态指定。
  • pom.xml
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
</dependency>
  • domain.User.java
public class User {

}
  • condition.ConditionOnClass.java(自定义注解)
@Conditional(ClassCondition.class)
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ConditionOnClass {
    String[] value();
}
  • config.UserConfig.java
@Configuration
public class UserConfig {
    @Bean
    @ConditionOnClass("redis.clients.jedis.Jedis")
    public User user(){
        return new User();
    }
}
  • condition.ClassCondition.java
public class ClassCondition implements Condition {
    /**
     * context  上下文对戏,用于获取环境,IOC容器,ClassLoader对象
     * metadata 注解的元对象,可以用于获取注解定义的属性值
     * */
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        //        2.需求:导入通过注解属性value指定坐标后创建bean
//        获取注解属性值:value
        Map<String, Object> map = metadata.getAnnotationAttributes(ConditionOnClass.class.getName());
//        System.out.println(map);
        String[] value =(String[]) map.get("value");
        boolean flag=true;
        try {
            for(String className:value){
                Class<?> aClass = Class.forName(className);
            }

        } catch (ClassNotFoundException e) {
            flag=false;
        }
        return flag;
    }
}
  • 测试
@SpringBootApplication
public class SpringbootConditionApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext context=SpringApplication.run(SpringbootConditionApplication.class, args);
//        Object redis=context.getBean("redisTemplate");
//        System.out.println(redis);
        Object user = context.getBean("user");
        System.out.println(user);
    }
}

也可以:

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>2.0.23</version>
</dependency>
@Configuration
public class UserConfig {
    @Bean
//    @ConditionOnClass("redis.clients.jedis.Jedis")
    @ConditionOnClass("com.alibaba.fastjson.JSON")
    public User user(){
        return new User();
    }
}
  • 方法二
  • UserConfig.java
@Configuration
public class UserConfig {
    @Bean
    @ConditionOnClass("redis.clients.jedis.Jedis")
//    @ConditionOnClass("com.alibaba.fastjson.JSON")
    public User user(){
        return new User();
    }
    @Bean
    @ConditionalOnProperty(name="itcast" ,havingValue = "xie")
    public User user2(){
        return new User();
    }
}
  • application.yml
itcast=xie
  • 测试
@SpringBootApplication
public class SpringbootConditionApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext context=SpringApplication.run(SpringbootConditionApplication.class, args);
//        Object redis=context.getBean("redisTemplate");
//        System.out.println(redis);
        Object user = context.getBean("user2");
        System.out.println(user);
    }

}

小结

  1. 自定义条件:
  • 定义条件类:自定义类实现Condition接口,重写matches方法,在matches方法中进行逻辑判断,返回boolean值。matches方法两个参数:
    • context:上下文对象,可以获取属性值,获取类加载器,获取BeanFactory等。

    • metadata:元数据对象,用于获取注解属性。

  • 判断条件:在初始化Bean时,使用@Conditional(条件类.class)注解
  1. SpringBoot提供的常用条件注解:
  • ConditionalonProperty:判断配置文件中是否有对应属性和值才初始化Bean
  • Conditionalonclass:判断环境中是否有对应字节码文件才初始化Bean
  • ConditionalonMissingBean:判断环境中设有对应Bean才初始化Bean

5.2 切换内置服务器

SpringBoot的web环境中默认使用tomcatf作为内置服务器,其实SpringBoot提供了4中内置服务器供我们选择,我们可以很方便的进行切换。

5.2.1 Tomcat

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

5.2.2 jetty

 <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
<!--            排除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>

5.3 @Enable*注解

SpringBoot中提供了很多Enable开头的注解,这些注解都是用于动态启用某些功能的。而其底层原理是使用@Import注解导入一些配置类,实现Bean的动态加载。

5.3.1 不同模块获取bean

图片.png

图片.png

<dependency>
    <groupId>com.xie</groupId>
    <artifactId>enable-other</artifactId>
    <version>0.0.1-SNAPSHOT</version>
</dependency>
  • User.java
public class User {
}
  • UserConfig.java
@Configuration
public class UserConfig {
    @Bean
    public User user(){
        return new User();
    }
}
  • 测试(main)
/**
 * @ComponentScan 扫描范围,当前引导类所在包及其子包
 * com.xie.config;
 *  com.xie.domain;
 * 解决方法:
 *  1. 使用@ComponentScan扫描com.xie.config包
 *  2.可以使用@import注解,加载类。这些类都会被Spring创建,并放入IOC容器
 *  3.可以对Import注解进行封装
 *
 * */
@SpringBootApplication
//@ComponentScan("com.xie.config")
//@Import(UserConfig.class)
public class SpringbootEnableApplication {

    public static void main(String[] args) {

        ConfigurableApplicationContext context = SpringApplication.run(SpringbootEnableApplication.class, args);
        Object user = context.getBean("user");
        System.out.println(user);
    }
}
  • 方法三:对Import注解进行封装
    • 新建EnableUser.java 图片.png
    @Import(UserConfig.class)
    @Target({ElementType.TYPE, ElementType.METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface EnableUser {
    }
    
    • 测试(main)
    @SpringBootApplication
    //@ComponentScan("com.xie.config")
    //@Import(UserConfig.class)
    @EnableUser
    public class SpringbootEnableApplication {
    
        public static void main(String[] args) {
    
            ConfigurableApplicationContext context = SpringApplication.run(SpringbootEnableApplication.class, args);
            Object user = context.getBean("user");
            System.out.println(user);
        }
    }
    

5.4 @Import注解

@Enable*底层依赖于@Importi注解导入一些类,使用@Import导入的类会被Spring加载到1OC容器中。而@Import提供4种用法:

  1. 导入Bean
  2. 导入配置类
  3. 导入ImportSelector实现类,一般用于加载配置文件中的类
  4. 导入ImportBeanDefinitionRegistrar实现类

5.4.1 用法一:导入bean

@SpringBootApplication
//@ComponentScan("com.xie.config")
//@Import(UserConfig.class)
//@EnableUser
@Import(User.class)
public class SpringbootEnableApplication {

    public static void main(String[] args) {

        ConfigurableApplicationContext context = SpringApplication.run(SpringbootEnableApplication.class, args);
        User bean = context.getBean(User.class);
        Map<String, User> map = context.getBeansOfType(User.class);
        System.out.println(map);//所有User对应的类以及键的名称,也就是bean的名称以及bean的值
        System.out.println(bean);//bean的值
    }
}

5.4.2 用法二:导入配置类

  • UserConfig.java
@Configuration
public class UserConfig {
    @Bean
    public User user(){
        return new User();
    }
    @Bean
    public Role role(){
        return new Role();
    }
}
  • main
@SpringBootApplication
@Import(UserConfig.class)//如果用了这个注解,则UserConfig里的@Configuration注解可以不加
public class SpringbootEnableApplication {

    public static void main(String[] args) {

        ConfigurableApplicationContext context = SpringApplication.run(SpringbootEnableApplication.class, args);
        User bean = context.getBean(User.class);
        Role role = context.getBean(Role.class);
        System.out.println(role);
        System.out.println(bean);//bean的值
    }
}

5.4.3 用法三:导入ImportSelect的实现类

  • com.xie.config.MyImportSelect.java
public class MyImportSelect implements ImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        return new String[]{"com.xie.domain.User","com.xie.domain.Role"};
    }
}
  • main
@SpringBootApplication
@Import(MyImportSelect.class)
public class SpringbootEnableApplication {

    public static void main(String[] args) {

        ConfigurableApplicationContext context = SpringApplication.run(SpringbootEnableApplication.class, args);
        User bean = context.getBean(User.class);
        Role role = context.getBean(Role.class);
        System.out.println(role);
        System.out.println(bean);//bean的值
    }
}

5.4.4 用法四:导入实现类

  • com.xie.config.MyImportBeanDefinitionRegistrar.java
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
    public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry){
        AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(User.class).getBeanDefinition();
        registry.registerBeanDefinition("user",beanDefinition);
    }
}
  • main
@SpringBootApplication
@Import(MyImportBeanDefinitionRegistrar.class)

public class SpringbootEnableApplication {

    public static void main(String[] args) {

        ConfigurableApplicationContext context = SpringApplication.run(SpringbootEnableApplication.class, args);
        User bean = context.getBean(User.class);
        Object user=context.getBean("user");
        System.out.println(user);
        System.out.println(bean);//bean的值
    }
}

5.5 @EnableAutoConfiguration注解

  • @EnableAutoConfiguration注解内部使用@Import(AutoConfigurationImportSelector.class)来加载配置类。
  • 配置文件位置:META-lNF/spring.factories,该配置文件中定义了大量的配置类,当SpringBoot应用启动时,会自动加载 这些配置类,初始化Bean
  • 并不是所有的Bean都会被初始化,在配置类中使用Condition来加载满足条件的Bean

5.5.1 案例

自定义redis-starter。要求当导入redis坐标时,SpringBoot自动创建Jedis的Bean。

<!--        mybatis起步依赖-->
        <!-- https://mvnrepository.com/artifact/org.mybatis.spring.boot/mybatis-spring-boot-starter -->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.2.2</version>
        </dependency>

实现步骤

  1. 创建redis-spring-boot-autoconfigure模块
  2. 创建redis-spring-boot-starter模块,依赖redis-spring- boot-autoconfigurel的模块
  3. 在redis-spring-boot-autoconfigure模块中初始化Jedis的 Bean。并定义META-lNF/spring.factories文件
  4. 在测试模块中引入自定义的redis--starter依赖,测试获取 Jedis的Bean,操作redis。.
  • redis-spring-boot-starter模块的pom.xml把测试依赖和插件给删了
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
<!--        引入configure-->
        <dependency>
            <groupId>com.xie</groupId>
            <artifactId>autoconfigure</artifactId>
        </dependency>
    </dependencies>
  • redis-spring-boot-autoconfigure模块
<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
<!--        引入jedis依赖-->
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
        </dependency>
    </dependencies>
  • redis-spring-boot-autoconfigure模块新建config.RedisAutoConfiguration.java
@Configuration//表示是配置文件
@EnableConfigurationProperties(RedisProperties.class)//把RedisProperties这个类加载进来
public class RedisAutoConfiguration {
//    提供Jedis的bean
    @Bean
    public Jedis jedis(RedisProperties redisProperties){
        return new Jedis(redisProperties.getHost(),redisProperties.getPort());
    }
}
  • redis-spring-boot-autoconfigure模块新建RedisProperties.java
@Component
@ConfigurationProperties(prefix = "redis")
public class RedisProperties {
    private String host="localhost";
    private int port=6379;

    public String getHost() {
        return host;
    }

    public void setHost(String host) {
        this.host = host;
    }

    public int getPort() {
        return port;
    }

    public void setPort(int port) {
        this.port = port;
    }
}

5.6 SpringBoot监听机制

SpringBoot的监听机制,其实是对Java提供的事件监听机制的封装。

  • Java监听机制

Java中的事件监听机制定义了以下几个角色:

  1. 事件:Event,.继承java.util.EventObject类的对象
  2. 事件源:Source,任意对象Object
  3. 监听器:Listener,实现java.util.EventListener接口的对象
  • SpringBoot监听机制

SpringBoot在项目启动时,会对几个监听器进行回调,我们可以实现这些监听器接口,在项目启动时完成一些操作。
ApplicationContextlnitializer SpringApplicationRunListener CommandLineRunner,ApplicationRunner

  • MyApplicationContextInitializer.java
/**
 * 当做是监听器
 * */
@Component//注册到Spring容器里
public class MyApplicationContextInitializer implements ApplicationContextInitializer {
    @Override
    public void initialize(ConfigurableApplicationContext applicationContext) {
        System.out.println("ApplicationContextInitializer.......initialize");
    }
}
  • MyApplicationRunner.java
/**
 * 当我们的项目启动后执行run方法(自动调用)
 *
 * */
@Component
public class MyApplicationRunner implements ApplicationRunner {
    @Override
    public void run(ApplicationArguments args) throws Exception {
        System.out.println("ApplicationRunner......run");
        System.out.println(Arrays.asList(args.getSourceArgs()));
    }
}
  • MyCommandLineRunner.java
@Component
public class MyCommandLineRunner implements CommandLineRunner {
    @Override
    public void run(String... args) throws Exception {
        System.out.println("CommandLineRunner.....run");
        System.out.println(Arrays.asList(args));
    }
}
  • MySpringApplicationRunListener.java
@Component
public class MySpringApplicationRunListener implements SpringApplicationRunListener {

    @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("contextPrepared。。。。。。上下文对象开始准备");
    }

    @Override
    public void contextLoaded(ConfigurableApplicationContext context) {
        System.out.println("contextLoaded。。。。。上下文对象开始加载");
    }

    @Override
    public void started(ConfigurableApplicationContext context, Duration timeTaken) {
        System.out.println("started.......上下文对象加载完成");
    }

    @Override
    public void failed(ConfigurableApplicationContext context, Throwable exception) {
        System.out.println("failed......项目启动失败");
    }
}

注意:当项目启动时,只有run方法执行(即只有两个类),另外两个类需要配置才能执行

图片.png

org.springframework.context.ApplicationContextInitializer=com.xie.listener.listener.MyApplicationContextInitializer

5.7 SpringBoot启动流程分析

六、SpringBoot监控

6.1 actuator

Spring Bootl自带监控功能Actuator,可以帮助实现对程序内部运行情况监控,比如监控状况、Bean加载情况、配置属性、日志信息等。

使用步骤

  1. 导入依赖 图片.png 图片.png

  2. 运行后访问http://localhost:8080/actuator

# 开启健康检查的完整信息
management.endpoint.health.show-details=always
# 将所有的监控endpoint暴露出来
management.endpoints.web.exposure.include=*

6.2 Spring Boot Admin(图形化界面使用)

  • Spring Boot Admin是一个开源社区项目,用于管理和监控SpringBoot)应用程序。
  • Spring Boot Admin有两个角色,客户端Client)和服务端Server)。
  • 应用程序作为Spring Boot Admin Clientl向为Spring Boot Admin Serveri注册
  • Spring Boot Admin Server的Ul界面将Spring Boot Admin Client的Actuator Endpoint上的一些监控信息,

使用步骤

  1. 创建两个模块(admin-server,admin-client)
    • admin-server
      • 创建admin-server模块
      • 导入依赖坐标admin-starter-server
      • 在引导类上启用监控功能@EnableAdminServer 图片.png
      • 加入 @EnableAdminServer注解
        @EnableAdminServer
        @SpringBootApplication
        public class AdminServerApplication {
        
            public static void main(String[] args) {
                SpringApplication.run(AdminServerApplication.class, args);
            }
        
        }
        
      • 配置
        server.port=9000
        
    • admin-client
      • 创建admin-client模块
      • 导入依赖坐标admin-starter-client
      • 配置相关信息:server地址等
      • 启动server和client服务,访问server
        图片.png
      • 配置
        # 执行admin.server地址
        spring.boot.admin.client.url=http://localhost:9000
        
        # 开启所有信息
        management.endpoint.health.show-details=always
        # 开启所有配置
        management.endpoints.web.exposure.include=*
        

先运行admin-server,后运行admin-client,再浏览器http://localhost:9000 ,则可以跳转

图片.png

七、SpringBoot项目部署

SpringBoot项目开发完毕后,支持两种方式部署到服务器:

  1. jar包(官方推荐)
  2. war包

7.1 jar包

图片.png

  • UserController.java
@RequestMapping("/user")
@RestController
public class UserController {
    @RequestMapping("/findAll")
    public String findAll(){
        return "success";
    }
}
  • 打包

图片.png

图片.png

图片.png

图片.png 回车运行,然后访问http://localhost:8080/user/findAll

7.2 war包

这是使用内置的Tomcat运行的,也可以用其他的

图片.png

  • 启动类
@SpringBootApplication
public class SpringbootDeployApplication extends SpringBootServletInitializer {
    public static void main(String[] args) {
        SpringApplication.run(SpringbootDeployApplication.class, args);
    }
    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
        return builder.sources(SpringbootDeployApplication.class);
    }
}

ctrl+o:重写方法

然后再打包,然后找到位置

图片.png

图片.png

图片.png

图片.png 然后浏览器访问