谈谈SpringBoot(三)

1. SpringBoot依赖管理

1.1 父依赖

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.8</version>
        <relativePath/>
    </parent>

点击进去,看父依赖的父依赖

  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-dependencies</artifactId>
    <version>2.7.8</version>
  </parent>

再点击进去,会看到全局的版本管理,声明了开发中几乎所有常用jar包的版本

spring-boot-dependencies里面规定当前依赖的版本 用的 key

  <properties>
    <activemq.version>5.16.5</activemq.version>
    <antlr2.version>2.7.7</antlr2.version>
    <appengine-sdk.version>1.9.98</appengine-sdk.version>
    <artemis.version>2.19.1</artemis.version>
    <aspectj.version>1.9.7</aspectj.version>
    <assertj.version>3.22.0</assertj.version>
    <atomikos.version>4.0.6</atomikos.version>
........
    <mysql.version>8.0.32</mysql.version>
........
  </properties>

1.2 修改jar的版本

   比如,如何修改mysql版本呢?当前版本是8.0.32,那么改成8.0.31?

        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <scope>runtime</scope>
        </dependency>

根据全局的版本管理中的mysql的key进行设置

    <properties>
        <mysql.version>8.0.31</mysql.version>
    </properties>

注意:

1、引入依赖默认都可以不写版本
2、引入非版本仲裁的jar,要写版本号

2. 容器功能

2.1 组件添加 

2.1.1 @Configuration

@Configuration //告诉Springboot这是一个配置类,它本身也是一个组件
public class MyTestConfig {
    //给容器中添加组件。以方法名作为组件的id。返回类型就是组件类型。
    //返回的值,就是组件在容器中的实例
    @Bean 
    public Employee emp(){
        Employee zhangsan = new Employee(1,"zhangsan", 18,"zs@126.com",1);
        //emp组件依赖了dept组件
        zhangsan.setDepartment(dept());
        return zhangsan;
    }

    @Bean("dept")
    public Department dept(){
        return new Department(1,"dept001");
    }
}
@MapperScan("com.zmj.springboot.mapper")
@SpringBootApplication
public class SpringbootApplication {
    public static void main(String[] args) {
        //1、返回我们IOC容器
        ConfigurableApplicationContext run = SpringApplication.run(SpringbootApplication.class, args);
        //2、查看容器里面的组件
        String[] beanDefinitionNames = run.getBeanDefinitionNames();
        for (String beanDefinitionName : beanDefinitionNames) {
            System.out.println(beanDefinitionName);
        }
        //3、从容器中获取组件
        Employee emp = run.getBean("emp", Employee.class);
        System.out.println("emp:"+emp);

        MyTestConfig bean = run.getBean(MyTestConfig.class);
        Employee emp1 = bean.emp();
        Employee emp2 = bean.emp();
        System.out.println("是否是单例:"+(emp1 == emp2));
    }
}

服务启动后,会在日志里面打印出来,刚才在配置类的两个Bean

组件默认是单例的

 原因是@Configuration的proxyBeanMethods属性默认是true,也就是Full 模式,保证每个@Bean方法被调用多少次返回的组件都是单实例的。

配置类组件之间有依赖关系,方法会被调用得到之前单实例组件,用Full模式。

配置类组件之间无依赖关系用Lite模式,加速容器启动过程,减少判断。

@Configuration(proxyBeanMethods=false) //告诉Springboot这是一个配置类,它本身也是一个组件
public class MyTestConfig {
    @Bean //给容器中添加组件。以方法名作为组件的id。返回类型就是组件类型。返回的值,就是组件在容器中的实例
    public Employee emp(){
        Employee zhangsan = new Employee(1,"zhangsan", 18,"zs@126.com",1);
        return zhangsan;
    }

    @Bean("dept")
    public Department dept(){
        return new Department(1,"dept001");
    }
}

重启后,再次查看结果,就不再是单例了

2.1.2 @Import 自动导入组件

@Import({DOMObjectHelper.class})
@Configuration
public class MyTestConfig {
}
@MapperScan("com.zmj.springboot.mapper")
@SpringBootApplication
public class SpringbootApplication {
    public static void main(String[] args) {
        //1、返回我们IOC容器
        ConfigurableApplicationContext run = SpringApplication.run(SpringbootApplication.class, args);
        DOMObjectHelper bean2 = run.getBean(DOMObjectHelper.class);
        System.out.println(bean2);
    }
}

启动后,查看结果发现可以获取到

2.1.3 @Conditional

条件装配:满足Conditional指定的条件,则进行组件注入

@ConditionalOnBean(Department.class)   存在这个Bean才生效;@ConditionalOnMissingBean(name = "dept")  不存在这个Bean才生效
@Configuration
//只有存在Bean为Department,这个配置类才生效
@ConditionalOnBean(Department.class)
public class MyTestConfig {
    @Bean
    public Employee emp(){
        Employee zhangsan = new Employee(1,"zhangsan", 18,"zs@126.com",1);
        return zhangsan;
    }
}

启动后,查看结果为 是否包含EmployeeBean:false

2.1.4 @ImportResource

@ImportResource("classpath:beans.xml")  导入Spring的配置文件 

2.2 配置绑定

2.2.1 方式一

@Component  + @ConfigurationProperties(prefix = "mycar")

@Component //只有在容器中的组件,才会拥有SpringBoot提供的强大功能
@ConfigurationProperties(prefix = "mycar")
public class Car {
    private String brand;
    private Integer price;
//省去setter/getter方法
}

application.yml中内容追加

mycar:
  brand: 宝马
  price: 320000
@RestController
public class HelloController {
    @Autowired
    private Car car;

    @GetMapping("/getCar")
    public Car getCar(){
        return car;
    }
}

 

2.2.2 方式二

@EnableConfigurationProperties(Car.class)  + @ConfigurationProperties(prefix = "car")

@ConfigurationProperties(prefix = "car")
public class Car {
    private String brand;
    private Integer price;
    //省略setter/getter方法
}
@Configuration
@EnableConfigurationProperties(Car.class)
public class MyTestConfig {
}

application.yml内容里面追加

car:
  brand: 奔驰
  price: 990000
@RestController
public class HelloController {
    @Autowired
    private Car car;

    @GetMapping("/getCar")
    public Car getCar(){
        return car;
    }
}

3. SpringBoot自动配置原理

3.1 @SpringBootApplication

@SpringBootApplication
public class SpringbootDataJdbcApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringbootDataJdbcApplication.class, args);
    }
}

点击 @SpringBootApplication注解进去发现,实际上它是三个注解的组合

@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
    excludeFilters = {@Filter(
    type = FilterType.CUSTOM,
    classes = {TypeExcludeFilter.class}
), @Filter(
    type = FilterType.CUSTOM,
    classes = {AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication {...}

3.2 @SpringBootConfiguration

点击 @SpringBootConfiguration注解进去发现,它其实就是一个配置类

@Configuration
public @interface SpringBootConfiguration {...}

3.3 @ComponentScan

指定扫描哪些包,默认是扫描启动类所在包及其子包

3.4 @EnableAutoConfiguration

这个注解由另外两个注解组成

@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {...}

3.5 @AutoConfigurationPackage

@Import({Registrar.class})
public @interface AutoConfigurationPackage {...}

Registrar类会给容器导入非常多的组件启动类下的所有

3.6 @Import({AutoConfigurationImportSelector.class})

获取所有自动配置的集合

1、利用getAutoConfigurationEntry(annotationMetadata);给容器中批量导入一些组件
2、调用List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes)获取到所有需要导入到容器中的配置类
3、利用工厂加载 Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader);得到所有的组件
4、从META-INF/spring.factories位置来加载一个文件。
    默认扫描我们当前系统里面所有META-INF/spring.factories位置的文件
    spring-boot-autoconfigure-2.7.7.jar包里面也有META-INF/spring.factories

5、按需加载

protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
        List<String> configurations = new ArrayList(SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader()));
        ImportCandidates.load(AutoConfiguration.class, this.getBeanClassLoader()).forEach(configurations::add);
        Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories nor in META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports. If you are using a custom packaging, make sure that file is correct.");
        return configurations;
    }

 3.7 总结

总结:

1.  SpringBoot先加载所有的自动配置类 xxxxxAutoConfiguration

2. 每个自动配置类按照条件进行生效,默认都会绑定配置文件指定的值。xxxxProperties里面拿。xxxProperties和配置文件进行了绑定

3. 生效的配置类就会给容器中装配很多组件

4. 只要容器中有这些组件,相当于这些功能就有了

5. 定制化配置

  • 用户直接自己@Bean替换底层的组件
  • 用户去看这个组件是获取的配置文件什么值就去修改。

xxAutoConfiguration ---> 组件 ---> xxProperties里面拿值 ---> application.properties

4. 开发技巧

4.1 参照文档

比如:我们想修改下面的启动图标

文档:Common Application Properties 

  

application.yml追加内容

spring:
  banner:
    image:
      location: classpath:qiudashang.png

4.2 Lombok

  简化JavaBean开发

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
注解位置释义
@Data
注解在类上提供类所有属性的 getting 和 setting 方法,此外还提供了equals、canEqual、hashCode、toString 方法
@NoArgsConstructor注解在类上为类提供一个无参的构造方法
@AllArgsConstructor注解在类上为类提供一个全参的构造方法
@Slf4j
注解在类上为类提供一个 属性名为log 的 Slf4j 日志对象
@Setter注解在属性上为属性提供 setting 方法
@Getter注解在属性上为属性提供 getting 方法

4.3 IDEA配置JRebel热部署

IDEA配置JRebel热部署

5.SpringBoot2.x整合Druid

Druid配置介绍

5.1 导入Maven依赖

		<dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.23</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>

5.2 application.yml

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/mytest
    username: root
    password: 123456
    driver-class-name: com.mysql.cj.jdbc.Driver
    druid:
      aop-patterns: com.zmj.admin.*  #监控SpringBean
      filters: stat,wall,slf4j    # 底层开启功能,stat(sql监控),wall(防火墙)
      stat-view-servlet:   # 配置监控页功能
        enabled: true
        login-username: admin
        login-password: admin
        reset-enable: false
      web-stat-filter:    # 监控web 用于采集web-jdbc关联监控的数据
        enabled: true
        url-pattern: /*
        exclusions: '*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*'
      filter:
        stat:     # 对上面filters里面的stat的详细配置
          slow-sql-millis: 1000   # 设置只要超过1000毫秒的,都为慢查询
          logSlowSql: true
          enabled: true
        wall:
          enabled: true
          config:
            drop-table-allow: false

5.3 Controller层

@RestController
public class HelloController {
    @Autowired
    private JdbcTemplate jdbcTemplate;

    @GetMapping("/queryDB")
    public String queryDB(){
        Long ret = jdbcTemplate.queryForObject("select count(*) from employee",Long.class);
        return ret.toString();
    }
}

5.5 测试

登录druid监控页面  

http://localhost:8080/druid/sql.html

 

 

 页面访问下数据库

http://localhost:8080/queryDB

6.SpringBoot2.x整合MyBatis

mybatis – MyBatis 3 | 入门

6.1 导入Maven依赖

        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.3.0</version>
        </dependency>

6.2 Mapper和Mapper.xml

public interface EmployeeMapper {
    Employee getEmp(Integer id);
}

 mybatis/mapper/EmployeeMapper.xml 

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zmj.springboot.mapper.EmployeeMapper">
    <select id="getEmp" resultType="com.zmj.springboot.entity.Employee">
        select * from employee where id = #{id}
    </select>
</mapper>

6.3 Service和Controller

@Service
public class EmployeeService {
    @Autowired
    private EmployeeMapper employeeMapper;

    public Employee getEmpById(Integer id){
        Employee emp = employeeMapper.getEmp(id);
        return emp;
    }
}
@RestController
public class EmployeeController {
    @Autowired
    private EmployeeService employeeService;

    @GetMapping("/getEmp/{id}")
    public Employee getEmpById(@PathVariable("id") Integer id){
        Employee emp = employeeService.getEmpById(id);
        return emp;
    }
}

6.4 application.yml

mybatis: # 配置mybatis规则
  mapper-locations: classpath:mybatis/mapper/*.xml  # 指定sql映射文件的位置
  configuration:  # 指定mybatis的全局配置
    map-underscore-to-camel-case: true   # 驼峰命名

6.5 启动类

@MapperScan("com.zmj.springboot.mapper")
@SpringBootApplication
public class SpringbootApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringbootApplication.class, args);
    }
}

6.6 页面访问

http://localhost:8080/getEmp/1

{"id":1,"lastName":"张三","email":"sas@email.com","gender":1,"did":1}

7.SpringBoot2.x整合MyBatisPlus

简介 | MyBatis-Plus

7.1 导入依赖

        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.4.1</version>
        </dependency>

7.2 xxxMapper

public interface UserMapper  extends BaseMapper<User> {
//只要继承了BaseMapper,就可以拥有简单的增删改查,不用写mapper.xml
}

7.3 测试

@Slf4j
@SpringBootTest
class SpringbootWebJspApplicationTests {
    @Autowired
    private UserMapper userMapper;

    @Test
    void testUserMapper() {
        User user = userMapper.selectById(1);
        log.info("用户信息:{}",user);
        //用户信息:User(id=1, name=Jone, age=18, email=test1@baomidou.com)
    }

}

8.SpringBoot2.x整合Redis

8.1 Maven依赖

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

8.2  application.yml

spring:
  redis:
    port: 6379
    host: 127.0.0.1

8.3 测试

@Slf4j
@SpringBootTest
class SpringbootWebJspApplicationTests {
    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Test
    void testRedis() {
        ValueOperations operations = redisTemplate.opsForValue();
        operations.set("key1","hello world");
        String key1 = (String) operations.get("key1");
        System.out.println(key1);//hello world
        ValueOperations<String, String> operations2 = stringRedisTemplate.opsForValue();
        operations2.set("key2","你好");
        String key2 = operations2.get("key2");
        System.out.println(key2);//你好
    }
}

8.4 如果使用Jedis

<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
</dependency>

 application.yml

spring:
  redis:
    port: 6379
    host: 127.0.0.1
    client-type: jedis

9. Springboot2.4以上的单元测试

9.1 导入Maven依赖

使用的Junit5

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

9.2 JUnit5常用注解

JUnit 5 User Guide

@Test :表示方法是测试方法。但是与JUnit4的@Test不同,
    它的职责非常单一不能声明任何属性,拓展的测试将会由Jupiter提供额外测试
@ParameterizedTest :表示方法是参数化测试,下方会有详细介绍
@RepeatedTest :表示方法可重复执行,下方会有详细介绍
@DisplayName :为测试类或者测试方法设置展示名称
@BeforeEach :表示在每个单元测试之前执行
@AfterEach :表示在每个单元测试之后执行
@BeforeAll :表示在所有单元测试之前执行
@AfterAll :表示在所有单元测试之后执行
@Tag :表示单元测试类别,类似于JUnit4中的@Categories
@Disabled :表示测试类或测试方法不执行,类似于JUnit4中的@Ignore
@Timeout :表示测试方法运行如果超过了指定时间将会返回错误
@ExtendWith :为测试类或测试方法提供扩展类引用

10. 断言机制

10.1 简单断言

@Slf4j
@SpringBootTest
class SpringbootWebJspApplicationTests {
    @DisplayName("测试简单断言")
    @Test
    void testSimpleAssertions() {
        int cal = 2+3;
        Assertions.assertEquals(6,cal,"业务逻辑计算失败");//期望是6,实际是5,报错
        /*org.opentest4j.AssertionFailedError: 业务逻辑计算失败 ==>
        Expected :6
        Actual   :5*/
    }
}
方法说明
assertEquals判断两个对象或两个原始类型是否相等
assertNotEquals判断两个对象或两个原始类型是否不相等
assertSame判断两个对象引用是否指向同一个对象
assertNotSame判断两个对象引用是否指向不同的对象
assertTrue判断给定的布尔值是否为 true
assertFalse判断给定的布尔值是否为 false
assertNull判断给定的对象引用是否为 null
assertNotNull判断给定的对象引用是否不为 null

10.2 组合断言

@Slf4j
@SpringBootTest
class SpringbootWebJspApplicationTests {
    @DisplayName("测试组合断言")
    @Test
    void testAllAssertions() {
        Assertions.assertAll("test",()->Assertions.assertTrue(true && true,"结果不为true"),
                () -> Assertions.assertEquals(1,2,"结果不是1"));
        /*结果不是1 ==> expected: <1> but was: <2>
                Comparison Failure:
        Expected :1
        Actual   :2*/
    }
}

10.3 异常断言

@Slf4j
@SpringBootTest
class SpringbootWebJspApplicationTests {
    @Test
    @DisplayName("异常测试")
    public void exceptionTest() {
        ArithmeticException exception = Assertions.assertThrows(
                ArithmeticException.class, () -> System.out.println(1 % 0));//断定有异常
    }
}

11.Profile环境切换

11.1 默认情况下

@RestController
public class HelloController {

    @Value("${employee.lastName:无名}")
    private String lastName;
    @Value("${MAVEN_HOME}")
    private String mavenHome;
    @Value("${os.name}")
    private String osName;

    @GetMapping("/msg")
    public String msg(){
        return "Hello " + lastName + ",mavenHome="+mavenHome+",osName="+osName;
    }
}

http://127.0.0.1:8080/msg

11.2 增加一个生产配置文件一个测试配置文件 

#application-prod.yml
employee:
  lastName: prod-zhangsan
#application-test.yml
employee:
  lastName: test-zhangsan
#application.yml
spring:
  profiles:
    active: test  #指定激活的环境,test是测试;prod是生产

如果是test,则显示 Hello test-zhangsan;如果是prod,则显示 Hello prod-zhangsan

#可以命令中设置取哪个配置文件
java -jar springboot-web-jsp-0.0.1-SNAPSHOT.jar --spring.profiles.active=prod

#可以命令中设置取哪个配置文件,还可以再设置某个具体的属性值
java -jar springboot-web-jsp-0.0.1-SNAPSHOT.jar --spring.profiles.active=prod --employee.lastName=cmd

11.3 外部化配置

可以在jar包所在目录下,或者/config目录下放入一个yml文件

持续更新中.................

相关内容:谈谈SpringBoot(一)               谈谈SpringBoot(二)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

朱梦君

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值