Java

SpringBoot入门

勤劳的小蜜蜂 · 8月1日 · 2019年 ·

如果你了解 Spring,那么学习 SpringBoot,是一件很简单的事,因为它只是简化了对 Spring 的使用与配置。

SpringBoot是什么

  • SpringBoot 是 Spring开源组织的一个子项目
  • SpringBoot 是在 Spring 的基础之上,将 Spring 的配置封装起来
  • Spring Boot提供了各种组件的启动器(starter),开发者只需要简单的配置好对应组件参数,Spring Boot 就会自动配置

为什么要使用 SpringBoot

  • 极大的简化 Spring 的开发
  • 避免大量 Maven 导入和版本的冲突
  • 零 XML 配置
  • 内置 Tomcat 服务器

SpringBoot 的特性

应用启动入口

启动类需使用 @SpringBootApplication 注解

SpringBoot 三种启动方式

配置文件优先级

内容较多,另写一篇文章 SpringBoot配置文件的优先级 讲解

  • properties 和 yml 格式文件的区别
  • application 和 bootstrap 的优先级
  • 不同位置配置文件的优先级

配置注入的两种方式

  • 使用注解 @Vaule(“${全路径}”)
  • 使用注解 @ConfigurationProperties(prefix = “前缀”)

使用 @ConfigurationProperties 需引入依赖

<dependency>
    <groupId> org.springframework.boot </groupId>
    <artifactId> spring-boot-configuration-processor </artifactId>
    <optional>true</optional>
</dependency>
application.yml中的配置

Jackson 的使用

SpringBoot 内置了 Jackson,可以非常方便的完成序列化和反序列化操作

通过一个例子来解释各个注解的含义

@Data
@NoArgsConstructor
@AllArgsConstructor
@JsonIgnoreProperties({ "address" })
public class Student {

    private int id;

    private String name;

    private int age;

    @JsonIgnore
    private String address;

    @JsonProperty("ct")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date createTime;

    public static class Builder {
        private int id;
        private String name;
        private int age;
        private String address;
        private Date createTime;

        public Builder id(int i) {
            id = i;
            return this;
        }

        public Builder name(String n) {
            name = n;
            return this;
        }

        public Builder age(int a) {
            age = a;
            return this;
        }

        public Builder address(String add) {
            address = add;
            return this;
        }

        public Builder createTime(Date c) {
            createTime = c;
            return this;
        }

        public Student build() {
            return new Student(this);
        }
    }

    private Student(Builder builder) {
        id = builder.id;
        name = builder.name;
        age = builder.age;
        address = builder.address;
        createTime = builder.createTime;
    }
}
  • @Data:lombok 插件提供的注解,用来给每个字段提供set和get属性
  • @NoArgsConstructor: lombok 插件提供的注解, 无参构造函数
  • @AllArgsConstructor: lombok 插件提供的注解, 全参构造函数
  • @JsonIgnoreProperties({ “address” }):设置字段不参与序列化,它的参数的列表类型
  • @JsonIgnore:作用同上,不过只能单个字段的设置
  • @JsonProperty(“ct”):为字段设置别名,该字段序列化之后显示别名
  • @JsonFormat(pattern = “yyyy-MM-dd HH:mm:ss”):将时间戳格式化为 “yyyy-MM-dd HH:mm:ss” 时间格式
  • 为什么方便序列化,使用了构造器模式
public static void main(String[] args) throws IOException {

    Student student = new Student.Builder()
            .id(1)
            .name("beeij")
            .age(24)
            .address("上海市")
            .createTime(new Date())
            .build();

    ObjectMapper mapper = new ObjectMapper();

    // 序列化
    String jsonStudent = mapper.writeValueAsString(student);

    System.out.println(jsonStudent);

    // 反序列化
    System.out.println(mapper.readValue(jsonStudent, Student.class));
}

输出结果:

输出结果

定时任务

SpringBoot 中开启定时任务只需要两个步骤

  • 在启动类上加 @EnableScheduling 注解
  • 在定时方法上加 @Scheduled(定时规则)
@Slf4j
@Component
public class BootSchedule {

    private final DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    /**
     * @Description 上一次开始执行时间点之后3秒再执行
     */
    @Scheduled(fixedRate = 3000)
    public void schedule01() {
        log.info("schedule01 -> {}", LocalDateTime.now().format(fmt));
    }

    /**
     * @Description 上次执行完毕时间点之后3秒再执行
     */
    @Scheduled(fixedDelay = 3000)
    public void schedule02() {
        log.info("schedule02 -> {}", LocalDateTime.now().format(fmt));
    }

    /**
     * @Description 第一次延迟2秒后执行,之后按 fixedRate 的规则每3秒执行一次
     */
    @Scheduled(initialDelay = 2000, fixedRate = 3000)
    public void schedule03() {
        log.info("schedule03 -> {}", LocalDateTime.now().format(fmt));
    }

    /**
     * @Description 通过cron表达式定义规则
     * 每三秒执行一次
     */
    @Scheduled(cron = "*/3 * * * * ?")
    public void schedule04() {
        log.info("schedule04 -> {}", LocalDateTime.now().format(fmt));
    }

}

异步任务

SpringBoot 中编写异步方法只需要三步走:

  1. 在 pom 文件中引入 spring-boot-starter-web 依赖
  2. 在启动类上加上 @EnableAsync 注解
  3. 在方法上加上 @Async 的注解,该方法就是异步方法
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

springboot默认异步线程池的配置,使得当前线程不能重用,所以每次调用异步方法都会新建线程,因此我们可以自己定义线程池配置,对服务进行优化。

单元测试

单元测试需要引入 spring-boot-starter-test 依赖(一般 ide 会帮我们自动引入)

一个标准的 SpringBoot 测试用例应该包含两个注解:

  1. @SpringBootTest:意思是带有 SpringBoot 支持的引导程序,其中提供了可以制定 Web 环境的参数
  2. @RunWith(SpringRunner.class):告诉 JUnit 运行使用 Spring 的测试支持。SpringRunner 是 SpringJUnit4ClassRunner 的别名,只是为了让名字看起来简单些
@Slf4j
@RunWith(SpringRunner.class)
@SpringBootTest
public class AsyncServiceTest {

    @Autowired
    private AsyncService asyncService;

    @Test
    public void testAsyncProcess() throws InterruptedException {
        asyncService.asyncProcess();
        log.info("coming in testAsyncProcess...");
    }

    @Test
    public void testAsyncProcessHasReturn() throws Exception {

        long start = System.currentTimeMillis();

        Future<Integer> result = asyncService.asyncProcessHasReturn();
        
        log.info("get async task value: {}", result.get());

        log.info("time elapse for async task: {} ms", System.currentTimeMillis() - start);
    }
}

0 条回应