跳至主要內容

SpringBoot

Vingkin...大约 7 分钟

说说你对Spring Boot的理解

从本质上来说,Spring Boot就是Spring。Spring Boot使用“约定大于配置”的理念让你的项目快速的运行起来,使用Spring Boot很容易创建一个能独立运行、准生产级别、基于Spring框架的项目,使用Spring Boot你可以不用或者只需要很少的Spring配置。

简而言之,Spring Boot本身并不提供Spring的核心功能,而是作为Spring的脚手架框架,以达到快速构建项目。Spring Boot有如下优点:

  • 可以快速构建项目
  • 可以对主流开发框架的无配置集成
  • 项目可独立运行,无需外部依赖Servlet容器
  • 提供运行时的应用监控
  • 可以极大地提高开发、部署效率
  • 可以与云计算天然集成

Spring Boot Starter有什么用

Spring Boot提供众多起步依赖(Starter)降低项目依赖的复杂度。起步依赖本质上是一个Maven项目对象模型(Project Object Model,POM),定义了对其他库的传递依赖,这些东西加在一起即支持某项功能。很多起步依赖的命名都暗示了它们提供的某种或某类功能。

举例来说,你打算做个Web应用程序。与其向项目的构建文件里添加一堆单独的库依赖,还不如声明这是一个Web应用程序来的简单。你只要添加Spring Boot的Web起步依赖就好了。

介绍Spring Boot的启动流程

首先,Spring Boot项目创建完成会默认生成一个名为*Application的入口类,我们是通过该类的main方法启动Spring Boot项目的。在main方法中,通过run方法进行*Application类的初始化和启动。

*Application调用run方法的大致流程如下图:

其中,*Application在run方法中重点做了以下操作:

  • 获取监听器的参数配置
  • 打印Banner信息
  • 创建并初始化容器
  • 监听器发送通知

当然,除了上述核心操作,run方法运行过程中还涉及启动时长统计、异常报告、启动日志、异常处理等辅助操作。

Spring Boot项目是如何导入包的

通过Spring Boot Starter导入包。其他详见[0x01](#0x01. Spring Boot Starter有什么用).

Spring Boot自动装配过程

使用Spring Boot时,我们只需引入对应的Starter,Spring Boot启动时便会自动加载相关依赖,配置相应的初始化参数,以最快捷、简单的形式对第三方软件进行集成,这便是Spring Boot的自动配置功能。

整个自动配置的过程是:Spring Boot通过@EnableAutoConfiguration注解开启自动配置,加载spring.factories中的各种AutoConfiguration类,当某个AutoConfiguration类满足其注解@Conditional指定的生效条件(Starters提供的依赖、配置或Spring容器中是否存在某个Bean等)时,实例化该AutoConfiguration类中定义的Bean,并注入Spring容器,就可以完成依赖框架的自动配置。

说说你对Spring Boot的注解的了解

@SpringBootApplication

这个注解时Spring Boot项目的基石,创建Spring Boot项目之后会默认在主类加上。

我们可以把@SpringBootApplication看作是@SpringBootConfiguration@EnableAutoConfiguration@ComponentScan注解的集合。

  • @EnableAutoConfiguration:启用Spring Boot的自动装配机制
  • @ComponentScan:包路径扫描,扫描被@Component注解修饰的Bean
  • @SpringBootConfiguration:就是@Configuration的不同语义的版本,允许在该类中使用@Bean实修方法注册额外的Bean或导入其他配置类

@Import

@EnableAutoConfiguration的关键功能就是通过@Import注解导入的ImportSelector来完成的。从源码得知@Import({AutoConfigurationImportSelector.class})@EnableAutoConfiguration注解的组成部分,也是自动配置功能的核心实现者。

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
    String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";

    Class<?>[] exclude() default {};

    String[] excludeName() default {};
}

@Conditional

@Conditional注解是由Spring 4.0版本引入的新特性,可根据是否满足指定的条件来决定是否进行Bean的实例化及装配,比如,设定当类路径下包含某个jar包才会对注解的类进行实例化操作。总之,就是根据一些特定条件来控制实例化的行为。

@Conditional衍生注解

  • @ConditionalOnBean:在容器中有指定Bean的时候才会加载
  • @ConditiaonOnMissingBean:在容器中没有指定Bean的时候才会加载
  • 等等

@RestController

@RestController@Controller@ResponseBody的合集,表示这是个控制器Bean,并且是将函数的返回值直接填入HTTP响应体中,返回JSON或XML形式数据,是REST风格的控制器。

@Configuration

一般用来声明配置类,可以用@Component注解替代,不过使用@Configuration注解声明配置类更加语义化。

@PathVariable和@RequestParam

  • @PathVariable:用于获取路径参数
  • @RequestParam:用于获取查询参数
@GetMapping("/klasses/{klassId}/teachers")
public List<Teacher> getKlassRelatedTeachers(
         @PathVariable("klassId") Long klassId,
         @RequestParam(value = "type", required = false) String type ) {
...
}

如果我们请求的url是:/klasses/123456/teachers?type=web

那么我们服务获取到的数据就是:klassId=123456,type=web

@RequestBody

用于读取Request请求的body部分,并且Content-Typeapplication/json格式的数据,接收到数据之后会自动将数据绑定到Java对象上去。系统会使用HttpMessageConverter或者自定义的HttpMessageConverter将请求的body中的json字符串转换成java对象。

我们有个注册的接口:

@PostMapping("/sign-up")
public ResponseEntity signUp(@RequestBody @Valid UserRegisterRequest userRegisterRequest) {
  userService.save(userRegisterRequest);
  return ResponseEntity.ok().build();
}

UserRegisterRequest对象

@Data
@AllArgsConstructor
@NoArgsConstructor
public class UserRegisterRequest {
    @NotBlank
    private String userName;
    @NotBlank
    private String password;
    @NotBlank
    private String fullName;
}

我们发送post请求到这个接口,并且body携带JSON数据。这样我们的后端就可以直接把JSON格式的数据映射到我们的UserRegisterRequest类上。

{"userName":"coder","fullName":"shuangkou","password":"123456"}

需要注意的是:一个请求方法只可以有一个@RequestBody,但是可以有多个@RequestParam@PathVariable。 如果你的方法必须要用两个 @RequestBody来接受数据的话,大概率是你的数据库设计或者系统设计出问题了!

@Value和@ConfigurationProperties

wuhan2020: 2020年初武汉爆发了新型冠状病毒,疫情严重,但是,我相信一切都会过去!武汉加油!中国加油!

my-profile:
  name: Guide哥
  email: koushuangbwcx@163.com

library:
  location: 湖北武汉加油中国加油
  books:
    - name: 天才基本法
      description: 二十二岁的林朝夕在父亲确诊阿尔茨海默病这天,得知自己暗恋多年的校园男神裴之即将出国深造的消息——对方考取的学校,恰是父亲当年为她放弃的那所。
    - name: 时间的秩序
      description: 为什么我们记得过去,而非未来?时间“流逝”意味着什么?是我们存在于时间之内,还是时间存在于我们之中?卡洛·罗韦利用诗意的文字,邀请我们思考这一亘古难题——时间的本质。
    - name: 了不起的我
      description: 如何养成一个新习惯?如何让心智变得更成熟?如何拥有高质量的关系? 如何走出人生的艰难时刻?

使用@Value("${property}")读取比较简单的配置信息

@Value("${wuhan2020}")
String wuhan2020;

通过@ConfigurationProperties读取配置信息并于Bean绑定,就可以像使用普通的Bean一样,将其注入到类中使用

@Component
@ConfigurationProperties(prefix = "library")
@Data
@ToString
public class LibraryProperties {

    private String location;
    private List<Book> books;

    @Setter
    @Getter
    @ToString
    static class Book {
        String name;
        String description;
    }
}
@Autowired
private LibraryProperties libraryProperties;

Spring Boot全局异常处理器

@ControllerAdvice开启全局异常处理,使用该注解表示开启了全局异常的捕获,我们只需再自定义一个方法使用@ExceptionHandler注解,然后自定义捕获异常类型即可对这些捕获的异常进行统一处理。

// 全局异常处理器
@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(value = Exception.class)
    @ResponseBody
    public String globalExceptionHandler(Exception e) {
        System.out.println("全局异常捕获>>>:" + e);
        return "全局异常捕获,错误原因>>>" + e.getMessage();
    }

}
// controller中进行测试
@PostMapping("/sign-up")
public ResponseEntity signUp(@RequestBody UserRegisterRequest userRegisterRequest) {
    testService.save(userRegisterRequest);
    int i = 1 / 0;
    return ResponseEntity.ok(userRegisterRequest);
}

结果:

全局异常捕获,错误原因>>>/ by zero
评论
  • 按正序
  • 按倒序
  • 按热度
Powered by Waline v2.15.8