SpringBoot

介绍

  1. SpringBoot 相当于是一个Spring 和 SpringMVC的集成 又在其上增加了其他功能 对其他主流框架的支持也是非常好, 所以SpringBoot更新的非常频繁,需要时常关注它更新的内容
  2. 微服务架构
     Spring Boot 是由 Pivotal 团队提供的全新框架,其设计目的是用来简化新 Spring 应用的初始搭建以及开发过程。
     该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置。  
     通过这种方式,Spring Boot 致力于在蓬勃发展的快速应用开发领域(rapidapplication development)成为领导者。

SpringBoot优点

  • Create stand-alone Spring applications
    • 创建独立Spring应用
  • Embed Tomcat, Jetty or Undertow directly (no need to deploy WAR files)

    • 内嵌web服务器
  • Provide opinionated ‘starter’ dependencies to simplify your build configuration

    • 自动starter依赖,简化构建配置
  • Automatically configure Spring and 3rd party libraries whenever possible

    • 自动配置Spring以及第三方功能
  • Provide production-ready features such as metrics, health checks, and externalized configuration

    • 提供生产级别的监控、健康检查及外部化配置
  • Absolutely no code generation and no requirement for XML configuration

    • 无代码生成、无需编写XML

SpringBoot是整合Spring技术栈的一站式框架

SpringBoot是简化Spring技术栈的快速开发脚手架

SpringBoot最大的特点就是 无需编写大量的配置文件 需要什么功能模块 只需要导入相应的starter即可 < parent>中也几乎包含所有需要用到的功能依赖的版本号

SpringBoot缺点

  • 人称版本帝,迭代快,需要时刻关注变化
  • 封装太深,内部原理复杂,不容易精通

微服务

  • 微服务是一种架构风格

  • 一个应用拆分为一组小型服务

  • 每个服务运行在自己的进程内,也就是可独立部署和升级

  • 服务之间使用轻量级HTTP交互

  • 服务围绕业务功能拆分

  • 可以由全自动部署机制独立部署

  • 去中心化,服务自治。服务可以使用不同的语言、不同的存储技术

分布式

就是把一个一个的服务细分为不同功能的微服务 再将这些服务部署到不同的服务器上 以达到性能能效最大化 同时也避免了一台服务器出现问题 整个系统业务完全瘫痪

分布式的困难

  • 远程调用

  • 服务发现

  • 负载均衡

  • 服务容错

  • 配置管理

  • 服务监控

  • 链路追踪

  • 日志管理

  • 任务调度

  • ……

分布式的解决: SpringBoot+SpringCloud

img

云原生

原生应用如何上云。 Cloud Native

上云的困难

  • 服务自愈

  • 弹性伸缩

  • 服务隔离

  • 自动化部署

  • 灰度发布

  • 流量治理

  • ……

上云的解决

img

学习SpringBoot

  1. 查看官方文档:Spring官方 所有Spring的框架 包括分布式的解决方案

  2. 查看SpringBoot官方文档 Spring Boot官方文档

  3. 查看版本新特性: SpringBoot迭代更新文档

SpringBoot2入门

一: 基础要求

系统要求

  • Java 8 & 兼容java14 .

  • Maven 3.3+

  • idea 2019.1.2

二: 开始步骤

方式一:直接使用Maven创建SpringBoot项目
  1. 需要导入< parent></ parent> 依赖 里面包含了几乎开发要用到的所用依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.2</version>
</parent>
  1. 开始一个web项目,就加入spring-boot-starter-web依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
  1. 加入插件 该插件可以简化部署
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

该插件可以将 Spring Boot应用打包为可执行的jar或war文件,然后以通常的方式运行Spring Boot应用。

  1. 如果想更改SpringBoot内置服务器的端口号 就创建一个application.properties
server.port=8888

这样SpringBoot就能识别出了并修改了

  1. 创建主程序类 (也是SpringBoot的核心)
/**
* 主程序类
* @SpringBootApplication: 这是一个SpringBoot应用
*/
@SpringBootApplication
public class MainApplication {
public static void main(String[] args) {
SpringApplication.run(MainApplication.class,args);
}
}

  1. 编写一个控制器 和 处理器方法
/**
* @auther Devil
* @create 2022-01-11-20:37
*/

@RestController
public class HelloController {
@RequestMapping("/")
public String handler01(){
return "Hello,Spring Boot2";
}
}

  1. 运行主程序类 并测试

image-20220120140741819

方式二: 使用idea自带的模板创建(spring initializr)

选择spring initalizr 填入相应的信息 然后点击next

image-20220120141041583

因为我们是做web应用 所以这里选择springweb 如果是其他项目 选择相应的模块即可

image-20220120141138907

然后等待创建 最后创建相应的Controller等 运行即可(剩下于方式一相同)

方式三:spring官网创建(同样使用的是spring initializr)

image-20220120141750951

官网找到 project 点击SpringBoot 拉到最后

image-20220120141836152

点击Spring initializr

界面如图

image-20220120141947001

方式于idea创建相同 只是创建后的形式不同 创建后是以压缩包的形式下载 下载后要导入idea 这种方式是用来应付idea无法联网的情况

注意:

  1. SpringBoot的配置文件一定要写到 resources目录下 且尽量以application为文件名 这样才能识别
  2. 所有的Controller类 等业务类都要写道SpringBootApplication(主程序类)的同级或是子级目录下 否则会报404
  3. 常用的方式是 一 和 二

自动配置原理

一:yin_yang:依赖管理

  • SpringBoot使用了父项目做为项目管理
依赖管理    
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.4.RELEASE</version>
</parent>

他的父项目
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.3.4.RELEASE</version>
</parent>

几乎声明了所有开发中常用的依赖的版本号,自动版本仲裁机制

  • 开发只需要导入starter场景启动器(Starter就是一个包含了若干个坐标定义的pom管理文件, 即包含了若干个依赖的信息)
1、见到很多 spring-boot-starter-* : *就某种场景
2、只要引入starter,这个场景的所有常规需要的依赖我们都自动引入
3、SpringBoot所有支持的场景
https://docs.spring.io/spring-boot/docs/current/reference/html/using-spring-boot.html#using-boot-starter
4、见到的 *-spring-boot-starter: 第三方为我们提供的简化开发的场景启动器。
5、所有场景启动器最底层的依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.3.4.RELEASE</version>
<scope>compile</scope>
</dependency>
  • 无需关注版本号,自动版本仲裁

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

修改默认版本号 是使用依赖覆盖

1、查看spring-boot-dependencies里面规定当前依赖的版本 用的 key。
2、在当前项目里面重写配置
<properties>
<mysql.version>5.1.43</mysql.version>
</properties>
也可以直接在pom.xml中重写依赖来覆盖
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.27</version>
</dependency>

之所以在配置了< parent>之后不需要填写版本号 是因为 < parent>中使用了< dependencyManagement>管理

注意:
  1. 当导入一个Starter时又想导入一些其他技术 又不想直接导入其他的Starter 可以直接导入该技术的依赖 而且只需要写GAV中的GA而不需要写V 但是如果< Parent>中没有该依赖时 就需要完整写上GAV

二:first_quarter_moon:自动配置:

  • 自动配好Tomcat

    • 引入Tomcat依赖。
    • 配置Tomcat
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<version>2.3.4.RELEASE</version>
<scope>compile</scope>
</dependency>
  • 自动配好SpringMVC

    • 引入SpringMVC全套组件
    • 自动配好SpringMVC常用组件(功能)
  • 自动配好Web常见功能,如:字符编码问题

    • SpringBoot帮我们配置好了所有web开发的常见场景
  • 默认的包结构

    • 主程序所在包及其下面的所有子包里面的组件都会被默认扫描进来(所以一般将组件都写在主程序的同级或是子级目录)
    • 无需以前的包扫描配置
    • 想要改变扫描路径,
    • @SpringBootApplication(scanBasePackages=“com.atguigu”)
    • 或者@ComponentScan 指定扫描路径(更改方式)
@SpringBootApplication
等同于
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan("com.atguigu.boot")
  • 各种配置拥有默认值

    • 默认配置最终都是映射到某个类上,如:MultipartProperties
    • 配置文件的值最终会绑定每个类上,这个类会在容器中创建对象
  • 按需加载所有自动配置项

    • 非常多的starter
    • 引入了哪些场景这个场景的自动配置才会开启
    • SpringBoot所有的自动配置功能都在 spring-boot-autoconfigure 包里面
  • ….


容器中的注解的功能

一:question:@Configuration(配置类):

使用:

  1. 用在类的上方 表示该类为配置类 可以与@Bean标签一起使用 作用类似于Spring.xml文件中< bean>创建对象

告诉springboot这个是一个配置类 == 配置文件

  • 配置类里面使用@Bean标注在方法的上面给容器注册组件,默认也是单实例的

  • 配置类本身也是组件

  • proxyBeanMethods()方法:代理bean的方法

  • 当@Configuration中的参数proxyBeanMethods 的值为true时为代理模式 Cglib代理 会在原来的方法上增加功能 判断容器中是否已有对象 单例模式

  • 当@Configuration中的参数proxyBeanMethods 的值为false时为非代理模式 就是非单例模式

  • Full模式(proxyBeanMethods = true)(保证每个@Bean方法被调用多少次返回的组件都是单实例的)

  • Lite模式(proxyBeanMethods = false)(每个@Bean方法被调用多少次返回的组件都是新创建的)

    • 配置 类组件之间无依赖关系用Lite模式加速容器启动过程,减少判断
    • 配置类组件之间有依赖关系,方法会被调用得到之前单实例组件,用Full模式
@Configuration
public class MyConfig {


/**
* 外部无论对配置类中的这个组件注解方法调用多少次,获取的都是之前注册容器中的单实例对象
*
*
*
* //给容器中添加组件.以方法名作为组件的id,返回类型的,就是组件在容器中的实例
* @return Cat
*/
@Bean 方法名就是实例的名称
public Cat cat(){
return new Cat("彭芳姐");
}

}

测试发现 Full模式(proxyBea+nMethods = true) 使用的是Cglib代理模式

com.dyw.application.config.MyConfig$$EnhancerBySpringCGLIB$$c5874a7@120d3fd

Lite(proxyBeanMethods = true)则是没有被代理

com.dyw.application.config.MyConfig@29fa6b65
1. 1 @Import

@Import({Cat.class}) 给容器中自动创建出这个类型的组件 默认组件的名字为全类名

@Import({User.class})
@Configuration(proxyBeanMethods = false)
public class Config {

}
boolean bean = context.containsBean("com.dyw.springboot.entity.User");
true
1.2 @Conditional
  • 条件装配: 满足Conditional指定的条件,则进行组件注入
  • @ConditionalOnBean
  • @ConditionalOnMissingBean
  • @ConditionalOnMissingClass
  • @ConditionalOnResource
  • @ConditionalOnJava
  • @ConditionalOnWebApplication
  • @ConditionalOnNotWebApplication
  • @ConditionalOnClass

使用在@Configuration注解类中的@Bean标签下 根据注解条件判断是否注入

@Bean
@ConditionalOnBean(Cat.class)
public User user(){
User user = new User();
user.setCat(cat());
return user;
}

二: @SpringBootApplication(主程序类或引导类)
  1. 类上加上@SpringBootApplication 表示该类为主程序类
  2. 在类中写上主方法(main) 调用 SpringApplication.run(主程序类.class, args);即可开始SpringBoot程序
  3. 注意 组件都要写到主程序类的同级或是子级目录
  4. SpringApplication.run()方法会返回SpringBoot的容器 可以根据容器的getBean(“组件名”,类名.class)获取组件
  5. SpringApplication.run(主程序类.class, args)方法会返回一个Context上下文对象(容器), 里面包含了DispatcherServlet等对象, 这也是问什么运行此方法就可以达到实现web应用的功能. 通过内嵌的TomCat服务器核心就可以读取这个容器的组件.
  6. SpringBoot内嵌的服务器核心同样也是通过组件的方式存在SpringBoot的Context上下文对象中.(因为TomCat是java写的 运行原理就是执行java对象 所以把Tomcat的对象的创建和管理交给了SpringBoot);

三: @Bean
  1. 用于配置类的方法上 用来注册组件 使得组件管理的主权在容器

    @Bean
    public Cat cat(){
    return new Cat("彭芳姐");
    }

    方法名就是组件的名称 也可以在@Bean中设置组件的名称 @Bean(“组件名”)

  2. 创建组件的方法有两种

    1. 一种是利用有参构造创建组件 可以利用有参构造注入

      @Bean
      public Cat cat(){
      return new Cat("彭芳姐");
      }
    2. 另一种是利用无参构造 需要后续使用set方法注入 或是利用spring中的注解注入

      @Bean
      public Cat cat(){
      return new Cat();
      }

四: @RestController
  • @RestController = @Controller + @ResponseBody

即**@RestController@Controller的基础上 集成了@ResponseBody**的特性 即将java对象转换为json数据或是其他数据

  • @ResponseBody 注解的作用是将controller的方法返回的对象通过适当的转换器转换为指定的格式之后,写入到response对象的body区,通常用来返回JSON数据或者是XML 数据。

注意:在使用此注解之后不会再走视图处理器,而是直接将数据写入到输入流中,他的效果等同于通过response对象输出指定格式的数据。

  • @ResponseBody是作用在方法上(可使用在类上表示整个类中的方法都受@ResponseBody的影响)的,@ResponseBody 表示该方法的返回结果直接写入 HTTP response body 中,一般在异步获取数据时使用【也就是AJAX】。
  • 注意:在使用 @RequestMapping后返回值通常解析为跳转路径,但是加上 @ResponseBody 后返回结果不会被解析为跳转路径,而是直接写入 HTTP response body 中。 比如异步获取 json 数据,加上 @ResponseBody 后,会直接返回 json 数据。@RequestBody 将 HTTP 请求正文插入方法中,使用适合的 HttpMessageConverter 将请求体写入某个对象。

五:eagle:@RequstMapping

在SpringMVC的学习中我们知道 被它标注的方法称为处理器方法 , 它可以标注一个处理器方法的请求路径, 被他修饰的处理器方法, 默认返回值通常解析为跳转路径

在SpringBoot中 它的功能被细分了

原本的**@RequestMapping**在不指定请求方法时,会接收任意请求方法的请求

但是SpringBoot中推荐不直接在方法而是使用功能更细的**@请求方法名Mapping** 例如**@GetMapping或是@PostMapping**

而把@RequstMapping用在类上 用来当访问路径的前缀

http://localhost:8088/dyw/cat

@RestController
@RequestMapping("/dyw")
public class Controller {

@GetMapping("/cat")
public String doCat(){
return null;
}
}

六:@PathVariable(常用于REST风格)
  • 绑定路径参数于处理器方法形参间的关系,要求路径参数名于形参名一一对应
  • 使用: 用在SpringMVC控制器方法形参定义前面
  • @PathVariable常用于RESTful中且 请求路径参数只有较少数量时 如一个

注意参数是在路径上的使用{参数名称}描述路径参数

@DeleteMapping("/{id}")
public String delete(@PathVariable Integer id){
System.out.println("user delete..."+id);
return "{'module':user delete}";
}

image-20220120201849092

@RequestBody
  • 用来接收Josn请求

json请求传参方式

{
"id":12
}

使用键值对的方式传参 **键名+”:”+值 ** 键值放在{}中

@RequestParam
  • 用于接收url地址传来的参数 或是表单提交的参数 但路径传参的格式相对于RESTful的**@PathVariable**麻烦一点
@RequestParam
http://localhost:0000/users?id=1
=====================================================
@PathVariable
http://localhost:0000/users/1
@RequestBody、@RequestParam和@PathVariable总结
  • 应用
    • 后期开发中,发送请求参数超过一个时 ,以json格式为主,@RequestBody应用较广
    • 如果发送非json格式数据,选用@RequestParam接收参数
    • 采用RESTful进行开发,当参数数量较少时,例如一个可以采用@PathVariable接收请求路径变量,通常用于传递id值

七:@ImportResource
  • 该注解可以导入原生的配置文件 例如Spring中的Bean.xml配置文件 让其生效

  • 使用在任意配置类上

    @Import({Cat.class})
    @ImportResource("classpath:Bean.xml")
    @Configuration(proxyBeanMethods = false)
    public class Config {


    }

    ​ Bean.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="user" class="com.dyw.springboot.entity.User">
    <property name="cat" ref="cat"/>
    </bean>
    <bean id="cat" class="com.dyw.springboot.entity.Cat"/>
    </beans>

八: @ConfigurationProperties
  • 配置绑定 使用该注解 可以使用java读取到的配置文件(xml properties yml)中的内容,并且把它封装到JavaBean中,以供随时使用

    mycar.name=BYD
    mycar.price=10
  • 方式一: 在JavaBean上加上@Component(将其注册到springboot容器)和@ConfigurationPropertes注解

    @Data
    @Component
    @ConfigurationProperties(prefix = "mycar")
    public class Car {
    private String name;
    private Integer price;
    }
  • 方式二:在JavaBean上只用加上@ConfigurationPropertes注解 并且在配置类(@Configuration)上加上@EnableConfigurationPropertes(Class<?>[])

    @EnableConfigurationProperties(Car.class)
    //1. 开启Car配置绑定功能
    //2. 把这个Car这个组件自动注册到容器中
    @Configuration(proxyBeanMethods = false)
    public class Config {

    }

    @Data
    @ConfigurationProperties(prefix = "mycar")
    public class Car {
    private String name;
    private Integer price;
    }

REST风格

简介:

优点:

  • 隐藏资源的访问行为,无法通过地址得知资源是何种操作
  • 书写简化

注意:

  • 上述行为是约定方式,约定方式不是规范,可以打破,所以称为REST风格,而不是REST规范 但是由于使用REST风格的公司越来越多,也就慢慢都认为它是一种规范(都去遵守它了)。
  • 描述模块名称通常使用复数,也就是加s的格式描述,表示此类资源,而非单个资源,例如users、books….。

实例步骤:

  1. 设定http请求动作(动词)
  2. 设定请求参数(路径变量)
@RestController
@RequestMapping("/users")
public class MyController {
//保存用户
@PostMapping
public String save(){
System.out.println("user save...");
return "{'module':user save}";
}
//删除用户
@DeleteMapping("/{id}")
public String delete(@PathVariable Integer id){
System.out.println("user delete..."+id);
return "{'module':user delete}";
}
//修改用户
@PutMapping
public String update(@RequestBody User user){
System.out.println("user update..."+user);
return "{'module':user update}";
}
//获取指定用户
@GetMapping("/{id}")
public String getById(Integer id){
System.out.println("user getById..."+id);
return "{'module':user getById}";
}
//获取全部用户
@GetMapping
public String getAll(){
System.out.println("user getAll...");
return "{'module':user getAll}";
}
}

配置文件

配置文件(application.properties)前面提到可以修改Springboot内置的端口号

server.port=8080

还可以修改banner、log等配置信息

更多的、详细的配置信息都在https://docs.spring.io/spring-boot/docs/current/reference/html/application-properties.html#application-properties中

image-20220120211025873

注意:

  • 配置文件中的内容要与你导入的依赖相关,如果你没有导入相关的依赖那么配置的内容是不会生效的,例如没有导入tomcat的依赖,那么配置文件中修改server.port是不会有高亮提示的也不生效。

配置文件的格式

  • .properties(传统格式/默认格式)
  • .yaml
  • .yml(主流)

上述三种配置文件同时存在的执行的优先级(会加载覆盖)

是properties >> yml >> yaml

但上述情况一般不会出现


yaml
  • YAML(YAML Ain’t Markup Language),一种数据序列化格式

  • 优点:

    • 容易阅读
    • 容易与脚本语言交互
    • 以数据为核心,重数据格式
  • YAML文件扩展名

    • .yaml
    • .yml(主流)
  • 语法规则

    • 大小写敏感
    • 属性层级关系使用多行描述,每行结尾使用冒号结束
    • 使用缩进表示层级关系,同层级左侧对齐,只允许使用空格(不允许使用Tab键)
    • 属性值前面添加空格(属性名与属性之间使用冒号+空格作为分隔)
    country: china

    Java程序读取

    • 使用Spring的IOC机制使用@Value注入

      @Value("${country}")//读取键值对中的值
      private String Country;
      • 使用java类读取 (YAML类)
    static {
    Yaml yaml = new Yaml();
    try (InputStream in = YamlReader.class.getClassLoader().getResourceAsStream("application.yml");) {
    properties = yaml.loadAs(in, HashMap.class);
    } catch (Exception e) {
    log.error("Init yaml failed !", e);
    }
    }

    • 使用环境变量对象来存储yaml配置文件中的键值对(使用@Autowire注入赋值)用来应对当yaml配置文件中对象过多的情况
    @Autowired
    private Environment env;

    System.out.println(env.getProperty("server.port"));
    System.out.println(env.getProperty("Country"));
    • 使用自定义类封装yaml配置文件中的数据

      ​ application.yaml

      User:
      name: 丁杨维
      age: 20

      自定义User类


      @Component//将对象的生命周期交给容器管理 也为了容器将配置文件中的信息赋值给该对象
      @ConfigurationProperties(prefix = "user")
      public class User {
      private String name;
      private Integer age;

      public String getName() {
      return name;
      }

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

      public Integer getAge() {
      return age;
      }

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

      @Override
      public String toString() {
      return "User{" +
      "name='" + name + '\'' +
      ", age=" + age +
      '}';
      }
      }

      Controller.java

      @RestController
      @RequestMapping("/books")
      public class BookController {
      @Autowired
      private User user;
      @GetMapping
      public String getById(){
      System.out.println(user);
      return null;
      }
      }

      结果

      image-20220120224222972

    • yaml文件中值的相互引用 直接使用${键名}即可

BaseDir: c\windows
TempDir: ${BaseDir}\temp
#如果有转义字符想要显示出来 就加上双引号 如这里\t就是一个转义字符
TempDir: "${BaseDir}\temp"

注意:

  • 虽然配置文件格式多 单文件名可不是乱取的 名字一定是application.xxx才行

  • 如果idea没有识别你的yaml文件或是yml文件为springboot配置文件(前提是文件名是applicaiton.xxx) 可以在Project Struct中设置

image-20220120213544643

选择Facts 选择Configuration Files 在点击那个绿叶标志

image-20220120213633139

点击+号找到你的文件

image-20220120213807493

SpringBoot整合第三方技术

注意:如果使用的第三方技术无法在Spring Initializr中勾选到 则需要手动添加(maven中央仓库中查找)

SpringBoot整合Junit

使用Spring Initializr创建一个普通的SpringBoot程序(啥都不选) 会自动导入test依赖

这是因为maven创建的项目,生命周期中离不开test的原因,所以不用我们导入它会自动引入。

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

BookDao.java接口

public interface BookDao {
void save();
}

BookImpl.java实现类

@Repository
public class BookImpl implements BookDao {

@Override
public void save() {
System.out.println("book save");
}
}

Springboot05ApplicationTests.java

@SpringBootTest
class Springboot05ApplicationTests {
@Autowired
private BookImpl book;
@Test
void contextLoads() {
book.save();
}
}

运行测试类获得结果

image-20220120230704919

注意:

使用测试类时要将测试类放在与classes目录下引导类的路径呈同级或子级关系 否则测试类会找不到**@SpringBootConfiguration**而出现异常,而引导类的注解中包含@SpringBootConfiguration 所以引导类也是一个SpringBootConfiguration。

解决方案
  1. 将测试类放在classes目录下与引导类的路径呈同级或是子级关系的包下。
  2. 使用@ContextConfiguration(classes=…)注解指定引导类
  3. 使用@SpringBootTest(classes=…)注解指定引导类

SpringBoot整合Mybatis

创建
  1. 使用Spring Initializr创建,需要勾选SQL中的MySQL Driver和MyBatis Framework,根据需要勾选WEB。

image-20220120232906258

Mybatis与SpringBoot整合的依赖以及JDBC的依赖

      <dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
  1. 配置数据库连接信息

application.yml

spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/my_db
username: root
password: devil
  1. 写实体类

Student.java

package com.dyw.springboot06mybatis.Domain;

/**
* Devil
*
* @create 2022-01-20-23:36
*/
public class Student {
private int id;
private String name;
private int age;

@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
'}';
}

public int getId() {
return id;
}

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

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;
}
}

  1. 写StudentDao接口 写入相关操作

StudentDao.java

@Mapper
public interface StudentDao {
@Select("select id,name,age from student order by id")
List<Student> selectStudents();
}

如果不适用配置文件那么则加入**@Mapper**注解 就类似于配置文件 自动代理 在里面使用@Select注解(查找)配置操作 @Update(修改/更新)….

执行测试类

image-20220120234846000

注意:

如果出现了serverTimezone异常 需要在配置文件URL后加入?serverTimezone=UTC(时区任意)

SpringBoot整合Mybatis-Plus

直接导入相应的依赖mybatis-plus-boot-starter即可

并且在配置文件中写上数据库相关配置即可


SpringBoot整合Mybatis+Druid

需要导入druid的依赖

<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.8</version>
</dependency>

application.yml配置数据源类型

方式一: 在spring.datasource中配置type为DruidDataSource

spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/my_db?serverTimezone=UTC
username: root
password: devil
type: com.alibaba.druid.pool.DruidDataSource

方式二: 直接在spring.datasource.druid中配置数据源信息

spring:
datasource:
druid:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/my_db?serverTimezone=UTC
username: root
password: devil

推荐第二种

SSMP(SpringBoot+Mybatis-Plus)综合案例

  1. pom.xml 配置起步依赖
  2. application.yml 设置数据源 端口 框架技术相关配置等
  3. dao 继承BaseMapper, 设置@Mapper
  4. dao 测试类
  5. service 调用数据层接口或Mybatis-Plus提供的接口(ServiceImpl<BookMapper,Book>)快速开发
  6. service测试类
  7. controller 基于Restful开发, 使用Postman测试跑通功能
  8. 页面 放置在resources目录下的static目录中

使用Spring Initializr创建项目 勾选Spring webMysql Driver 额外加入依赖Druid Mybatis-Plus

<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.8</version>
</dependency>

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

创建数据库表 创建实体类

image-20220123202528206

@Data
@AllArgsConstructor
@NoArgsConstructor
//@TableName("tbl_book")(这里可以选择在application.yml文件中配置mybaits-plus中的table_prefix=tbl_)
public class Book {
@TableId(value = "id",type = IdType.AUTO)
private Integer id;
private String type;
private String name;
private String description;
}
server:
port: 80

spring:
datasource:
druid:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/my_db?serverTimezone=UTC
username: root
password: devil

mybatis-plus:
global-config:
db-config:
table-prefix: tbl_
id-type: auto
# mybatis-plus 日志配置
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

表现层消息一致性处理

  • 设计表现层返回结果的模型类,用于后端与前端进行数据格式的同意, 也称为前后端数据协议
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Result {
private Boolean flag;
private Object data;
private String msg;
public Result(Boolean flag){
this.flag = flag;
}

public Result(Boolean flag, Object data) {
this.flag = flag;
this.data = data;
}

public Result(Boolean flag,String msg){
this.flag = flag;
this.msg = msg;
}

public Result(String msg){
this.flag = false;
this.msg = msg;
}
}

  1. 设计同一个返回值结果类型便于前端开发读取数据
  2. 返回值结果类型可以根据需求自行设定,没有固定格式
  3. 返回值结果模型类用于后端与前端进行数据格式同意, 也称为前后端数据协议

异常消息处理

根据前文我们定义的前后端数据协议 如果遇到程序出现异常 会给前端返回一个异常数据 这并不在前后端数据协议定义范围 如果要进行消息处理 就必须进行异常消息处理

  1. 这里就要使用注解**@RestControllerAdvice**(控制器增强)定义SpringMVC异常处理器来处理异常的

  2. @ExceptionHandler(异常处理器)必须被扫描加载,否则无法生效

  3. 表现层返回结果中模型类中添加消息属性用来传递消息到页面

    //作为springmvc异常处理
    @RestControllerAdvice
    public class ProjectExceptionAdvice {
    //拦截所有的异常信息
    @ExceptionHandler
    public Result doException(Exception ex){
    //记录日志
    //通知运维
    //通知开发
    return new Result("服务器故障,请稍后再试");
    }
    }

运维部分

image-20220124205028879

image-20220124205017270

临时属性

  1. 使用命令行dos命令运行springboot工程是可以使用临时属性替换配置文件中的属性
  2. 临时属性添加方式: java -jar 工程名.jar –属性名=值
  3. 多个临时属性之间使用空格分隔
  4. 临时属性必须是当前boot工程支持的属性,否则设置无效

配置文件的四级分类

  • SpringBoot中4级配置文件(级别越高 优先级越高)

1级: file :config/application.yml 【最高】

2级: file :application.yml

3级:classpath:config/application.yml

4级:classpath:application.yml 【最低】

  • 作用:

1级与2级留做系统打包后设置通用属性,1级常用于运维经理进行线上整体项目部署方案调控

3级与4级用于系统开发阶段设置通用属性,3级常用于项目经理进行整体项目属性调控

自定义配置文件

  • 通过启动参数加载配置文件(无需书写配置文件扩展名)
  • image-20220125222425964
  • 通过启动参数加载指定文件路径下的配置文件

image-20220125222635339

  • 通过启动参数加载指定文件路径下的配置文件时可以加载多个配置

image-20220125222709306

重要说明

  • 单服务器项目:使用自定义配置文件需求较低

  • 多服务器项目:使用自定义配置文件需求较高,将所有配置放置在一个目录中,统一管理

  • 基于SpringCloud技术,所有的服务器将不再设置配置文件,而是通过配置中心进行设定,动态加载配置信息

多环境开发(YAML版)

单配置文件版本

  • 多环境开发需要设置若干种常用环境,例如开发 生产 测试环境

  • yaml格式中设置多环境使用"---"区分环境设置边界

  • 每种环境的区别在于加载的配置属性不同

  • 启用某种环境时需要指定启动时使用该环境

  • #生成环境
    spring:
      config:
        activate:
          on-profile: pro
    
  • ```yml
    #指定环境
    spring:
    profiles:
    active: test


    实例

    ```yml
    #应用环境
    #公共配置
    spring:
    profiles:
    active: test
    ---
    #设置环境
    #生成环境
    spring:
    config:
    activate:
    on-profile: pro
    server:
    port: 81
    ---
    #开发环境
    spring:
    profiles:
    active: dev
    server:
    port: 82
    ---
    #测试环境
    spring:
    config:
    activate:
    on-profile: test
    server:
    port: 83

多配置文件版本

  1. 主启动配置文件 application.yml
spring:
profiles:
active: test
  1. 环境分类配置文件application-pro.yml
server:
port: 82
  1. 环境分类配置文件application-dev.yml
server:
port: 81
  1. 环境分类配置文件application-dev.yml
server:
port: 83

环境的分类多配置文件其实就是在application后加上-环境名称即可

  • 可以独立配置文件定义环境属性
  • 独立配置文件便于线上系统维护更新并保障系统安全性

多环境开发(Properties)

步骤与yml版一致 只是由于与yml文件的格式不同导致两者的格式不同

  • 但properties版本支支持多文件模式 不支持单一配置文件多环境模式

多环境分组管理

  • 根据功能对配置文件中的信息进行拆分,并制作成独立的配置文件,命名规则如下(实际开发中)

    • applicaiton-devDB.yml
    • applicaiton-devRedis.yml
    • applicaiton-devMVC.yml
  • 使用include属性在激活指定环境的情况下,同时对多个环境进行加载使其生效,多个环境间使用逗号分隔(引入一个环境配置文件组)

    spring:
    profiles:
    active: dev
    include: devDB,devRedis,devMVC

    注意: 当主环境有相同属性时,当主环境生效;其他环境中有相同属性时,最后加载的环境属性生效


  • 从SpringBoot2.4版本开始使用group替代了include属性,降低了配置书写量
  • 使用group属性定义多种主环境与子环境的包含关系
spring:
profiles:
active: dev
group:
"dev": devDB,devRedis,devMVC
"pro": proDB,proRedis,proMVC

实际开发中 常使用"group"

多环境开发中使用group属性设置配置文件分组,便于线上维护管理

多环境开发控制

SpringBoot在工作时是基于maven坐标运行的

  • 当Maven与SpringBoot同时对多环境进行控制时,以Maven为主,SpringBoot使用@..@占位符读取Maven对应的配置属性值
  • 基于SpringBoot读取Maven配置属性的前提下,如果在Idea下测试工程时p吗.xml每次更新需要手动compile或是刷新Maven方可生效
  1. 需要在Maven的pom.xml中配置多环境属性值
<!--设置多环境-->
<profiles>
<profile>
<id>env_dev</id>
<properties><!--设置获得profile-->
<profile.active>dev</profile.active>
</properties>
<activation><!--是否默认生效-->
<activeByDefault>true</activeByDefault>
</activation>
</profile>
<profile>
<id>env_pro</id>
<properties>
<profile.active>pro</profile.active>
</properties>
</profile>
</profiles>
  1. 在SpringBoot配置文件中指定获取Maven中活动的profile
spring:
profiles:
active: @profile.active@

日志

日志基础操作

  • 日志(log)作用
    • 编程期调试diamagnetic
    • 运营期记录信息
      • 记录日常运营重要信息(峰值流量 平均响应时长…..)
      • 记录应用报错信息(错误堆栈)
      • 记录运维过程数据(扩容 宕机 报警….)
@SuppressWarnings("all")
@RestController
@RequestMapping("/log")
public class Controller3 {
//创建记录日志的对象
private static final Logger log = LoggerFactory.getLogger(Controller3.class);
@GetMapping
public String doLog(){
log.debug("debug...");
log.error("error...");
log.info("infor...");
log.warn("warn...");
return "SpringBoot2 正在运行....";
}
}

日志级别(从上往下依次升高)

  • TRACE:运行堆栈信息,使用率低

  • DEBUG:程序员调试代码使用

  • INFO:记录运维过程数据

  • WARN:记录运维过程报警数据

  • ERROR:记录错误堆栈信息

  • FATAL:灾难信息,合并计入ERROR

设置日志输出级别 可以在springboot配置文件中设置

# 开启debug模式,输出调试信息,常用于检查系统运行状况
debug: true
# 设置日志级别,root表示根节点,即整体应用日志级别
logging:
level:
root: debug

设置日志组,控制指定包对应的日志输出级别,也可以直接空值指定包对应的日志输出级别

logging:
# 设置日志组
group:
# 自定义组名,设置当前组中所包含的包
ebank: com.itheima.controller
level:
root: warn
# 为对应组设置日志级别
ebank: debug
# 为对包设置日志级别
com.itheima.controller: debug

优化日志对象创建代码

  • 使用lombok提供的注解**@Slf4j**简化开发,减少日志对象的声明操作
@Slf4j
@SuppressWarnings("all")
@RestController
@RequestMapping("/log")
public class Controller3 {
@GetMapping
public String doLog(){
log.debug("debug...");
log.error("error...");
log.info("infor...");
log.warn("warn...");
return "SpringBoot2 正在运行....";
}
}
日志输出格式
2022-01-26 14:07:21.604  INFO 1416 --- [           main] c.a.d.s.b.a.DruidDataSourceAutoConfigure : Init DruidDataSource
2022-01-26 14:07:21.700 INFO 1416 --- [ main] com.alibaba.druid.pool.DruidDataSource : {dataSource-1} inited

上述即为日志的默认结构 分为 时间 日志级别 PID 所属线程 所属类/接口名 日志信息

  • PID:进程ID,用于表明当前操作所处的进程,当多服务同时记录日志时,该值可用于协助程序员调试程序
  • 所属类/接口名:当前显示信息为SpringBoot重写后的信息,名称过长时,简化包名书写为首字母,甚至直接删除