1、微服务阶段

Javase:OOP

mysq:持久化

html + css + jquery + 框架:视图

Javaweb:独立开发MVC三层架构的网站:原始

ssm:框架,简化开发流程,配置较为复杂

war:tomcat运行

Spring再简化:SpringBoot-jar:内嵌tomcat;微服务架构

服务越来越多:Spring Cloud;

SpringBoot - 图1

1.1、SpringBoot 是什么

什么是Spring

  1. Spring是一个开源框架,2003年兴起的一个轻量级的Java开发框架,作者:Rod Johnson
  2. **Spring是为了解决企业级应用开发的复杂性而创建的,简化开发。**—— 作用

Spring是如何简化Java开发的

  1. 为了降低Java开发的复杂性,Spring采用了以下4种关键策略:
  2. 1、基于POJO的轻量级和最小侵入性编程;
  3. 2、通过IOC,依赖注入(DI)和面向接口实现松藕合;
  4. 3、基于切面(AOP)和惯例进行声明式编程;
  5. 4、通过切面和模版减少样式代码;

什么是Spring Boot

  1. 开发一个web应用,从最初开始接触Servlet结合Tomcat,跑出一个Hello Wolrld程序,是要经历特别多的步骤;后来就用了框架Struts,再后来是SpringMVC,到了现在的SpringBoot,过一两年又会有其他web框架出现;框架不断的演进,然后开发项目所有的技术也再不断的变化、改造,SpringBoot,就是一个javaweb的开发框架,和SpringMVC类似,对比其他javaweb框架的好处,官方说是简化开发,约定大于配置,you can"just run",能迅速的开发web应用,几行代码开发一个http接口。
  2. 所有的技术框架的发展似乎都遵循了一条主线规律:从一个复杂应用场景衍生一种规范框架,人们只需要进行各种配置而不需要自己去实现它,这时候强大的配置功能成了优点;发展到一定程度之后,人们根据实际生产应用情况,选取其中实用功能和设计精华,重构出一些轻量级的框架;之后为了提高开发效率,嫌弃原先的各类配置过于麻烦,于是开始提倡“**约定大于配置**”,进而衍生出一些一站式的解决方案。
  3. 这就是Java企业级应用 —> J2EE —> Spring —> SpringBoot的过程。
  4. 随着Spring不断的发展,涉及的领域越来越多,项目整合开发需要配合各种各样的文件,慢慢变得不那么易用简单,违背了最初的理念,甚至人称配置地狱。Spring Boot正是在这样的一个背景下被抽象出来的开发框架,目的为了让大家更容易的使用Spring、更容易的集成各种常用的中间件、开源软件;
  5. Spring Boot基于Spring开发,Spirng Boot本身并不提供Spring框架的核心特性以及扩展功能,只是用于快速、敏捷地开发新一代基于Spring框架的应用程序。也就是说,它并不是用来替代Spring的解决方案,而是和Spring框架紧密结合用于提升Spring开发者体验的工具。Spring Boot以**约定大于配置**的核心思想,默认帮我们进行了很多设置,多数 Spring Boot 应用只需要很少的Spring配置。同时它集成了大量常用的第三方库配置(例如RedisMongoDBJpaRabbitMQQuartz等等),Spring Boot应用中这些第三方库几乎可以零配置的开箱即用,
  6. 简单来说就是SpringBoot其实不是什么新的框架,它默认配置了很多框架的使用方式,就像maven整合了所有的jar包,Spring Boot整合了所有的框架。
  7. Spring Boot 出生名门,从一开始就站在一个比较高的起点,又经过这几年的发展,生态足够完善,Spring Boot已经当之无愧成为Java领域最热门的技术。

Spring Boot的主要优点:

  • 为所有Spring开发者更快的入门
  • 开箱即用,提供各种默认配置来简化项目配置
  • 内嵌式容器简化Web项目
  • 没有允余代码生成和XML配置的要求

1.2、微服务

什么是微服务?

  1. 微服务是一种架构风格,它要求我们在开发一个应用的时候,这个应用必须构建成一系列小服务的组合;可以通过http的方式进行互通。要说微服务架构,先得说说过去我们的单体应用架构。

单体应用架构

  1. 所谓单体应用架构(all in one)是指,将一个应用的中的所有应用服务都封装在一个应用中。
  2. 无论是ERPCRM或是其他什么系统,都把数据库访问,web访问,等等各个功能放到一个war包内。
  • 这样做的好处是,易于开发和测试;也十分方便部署;当需要扩展时,只需要将war复制多份,然后放到多个服务器上,再做个负载均衡就可以了。
  • 单体应用架构的缺点是,哪怕要修改一个非常小的地方,都需要停掉整个服务,重新打包、部署这个应用war包。特别是对于一个大型应用,不可能把所有内容都放在一个应用里面,如何维护、如何分工合作都是问题。

微服务架构

  1. all in one的架构方式,把所有的功能单元放在一个应用里面。然后把整个应用部署到服务器上。如果负载能力不行,需要将整个应用进行水平复制,进行扩展,然后在负载均衡。
  2. 所谓微服务架构,就是打破之前all in one的架构方式,把每个功能元素独立出来。把独立出来的功能元素的动态组合,需要的功能元素才去拿来组合,需要多一些时可以整合多个功能元素。所以微服务架构是对功能元素进行复制,而没有对整个应用进行复制。
  3. 这样做的好处是:
  1. 节省了调用资源。
  2. 每个功能元素的服务都是一个可替换的、可独立升级的软件代码。

SpringBoot - 图2

高内聚低耦合

Martin Flower于2014年3月25日写的《Microservices》,详细的阐述了什么是微服务。

如何构建微服务

  1. 一个大型系统的微服务架构,就像一个复杂交织的神经网络,每一个神经元就是一个功能元素,它们各自完成自己的功能,然后通过http相互请求调用。比如一个电商系统,查缓存、连数据库、浏览页面、结账、支付等服务都是一个个独立的功能服务,都被微化了,它们作为一个个微服务共同构建了一个庞大的系统。如果修改其中的一个功能,只需要更新升级其中一个功能服务单元即可。
  2. 但是这种庞大的系统架构给部署和运维带来很大的难度。于是,Spring带来了构建大型分布式微服务的全套、全程产品:
  • 构建一个个功能独立的微服务应用单元,可以使用SpringBoot,可以快速构建一个应用;
  • 大型分布式网络服务的调用,这部分由spring cloud来完成,实现分布式;
  • 在分布式中间,进行流式数据计算、批处理,有spring cloud data flow。
  • Spring整个从开始构建应用到大型分布式应用全流程方案。

SpringBoot - 图3

1.3、SpringBoot程序

程序主入口:

  1. // 本身就是一个组件
  2. // 程序主入口
  3. @SpringBootApplication
  4. public class SpringBootProjectApplication {
  5. public static void main(String[] args) {
  6. SpringApplication.run(SpringBootProjectApplication.class, args);
  7. }
  8. }

核心配置文件:

  1. # SpringBoot 核心配置文件
  2. server:
  3. port: 8081

pom.xml文件

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
  5. https://maven.apache.org/xsd/maven-4.0.0.xsd">
  6. <modelVersion>4.0.0</modelVersion>
  7. <!--有父项目-->
  8. <parent>
  9. <groupId>org.springframework.boot</groupId>
  10. <artifactId>spring-boot-starter-parent</artifactId>
  11. <version>2.2.0.RELEASE</version>
  12. <relativePath/> <!-- lookup parent from repository -->
  13. </parent>
  14. <groupId>cn.dafran</groupId>
  15. <artifactId>spring-boot-project</artifactId>
  16. <version>0.0.1-SNAPSHOT</version>
  17. <name>spring-boot-project</name>
  18. <description>Demo project for Spring Boot</description>
  19. <properties>
  20. <java.version>1.8</java.version>
  21. </properties>
  22. <dependencies>
  23. <!--
  24. SpringBoot依赖都是spring-boot-starter开头
  25. -->
  26. <!--web依赖:tomcat、dispatcherServlet、xml-->
  27. <dependency>
  28. <groupId>org.springframework.boot</groupId>
  29. <artifactId>spring-boot-starter-web</artifactId>
  30. </dependency>
  31. <!--单元测试-->
  32. <dependency>
  33. <groupId>org.springframework.boot</groupId>
  34. <artifactId>spring-boot-starter-test</artifactId>
  35. <scope>test</scope>
  36. </dependency>
  37. </dependencies>
  38. <build>
  39. <!--打jar包插件-->
  40. <plugins>
  41. <plugin>
  42. <groupId>org.springframework.boot</groupId>
  43. <artifactId>spring-boot-maven-plugin</artifactId>
  44. </plugin>
  45. </plugins>
  46. </build>
  47. </project>

主要包含四个部分:

  • 项目元数据信息:创建时候输入的 Project Metadata部分,也就是Maven项目的基本元素,包括:grouped、 artifact、version、name、description等
  • parent:继承 spring-boot-starter-parent的依赖管理,控制版本与打包等内容
  • dependencies:项目具体依赖,这里包含了spring-boot-starter-web用于实现HTTP接口(该依赖中包含了 Spring MVC),官网对它的描述是:使用 Spring MVC构建Web(包括 RESTful)应用程序的入门者,使用 Tomcat作为默认嵌入式容器。spring-boot-starter-test用于编写单元测试的依赖包。
  • build:构建配置部分。默认使用了spring-boot-maven-plugin,配合spring-boot-starter-parent就可以把 Spring Boot应用打包成JAR来直接运行。
  1. java -jar

2、原理初探

2.1、自动配置:

pom.xml

  • spring-boot-dependencies:核心依赖在父工程中
  • 引入一些 SpringBoot依赖的时候,不需要指定版本,就因为有这些版本仓库。

启动器

  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter</artifactId>
  4. </dependency>
  • 启动器:也就是 SpringBoot的启动场景
  • 比如 spring-boot- starter-web,它就会自动导入web环境所有的依赖
  • springboot会将所有的功能场景,都变成一个个starter启动器
  • 要使用什么功能,就只需要找到对应的starter启动器就可以

主程序

  1. // @SpringBootApplication:标注这个类为SpringBoot的应用 启动类下的所有资源被导入
  2. @SpringBootApplication
  3. public class SpringBootProjectApplication {
  4. public static void main(String[] args) {
  5. // 将SpringBoot应用启动 (通过反射)
  6. SpringApplication.run(SpringBootProjectApplication.class, args);
  7. }
  8. }
  • 注解
  1. @SpringBootConfiguration : SpringBoot 配置
  2. @Configuration Spring配置类
  3. @Component :表明其就是一个Spring组件
  4. @EnableAutoConfiguration :自动配置
  5. @AutoConfigurationPackage :自动配置包
  6. @Import(AutoConfigurationPackages.Registrar.class) :导入选择器
  7. @Import(AutoConfigurationImportSelector.class) :自动配置导入选择
  8. // 获取所有的配置
  9. List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
  1. 获取候选的配置
  1. protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
  2. List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
  3. getBeanClassLoader());
  4. Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you "
  5. + "are using a custom packaging, make sure that file is correct.");
  6. return configurations;
  7. }

SpringBoot - 图4

  1. Properties properties = PropertiesLoaderUtils.loadProperties(resource);
  2. // 所有的东西都会加载到配置类中

SpringBoot - 图5

SpringBoot - 图6

静态资源过滤读取的配置

SpringBoot - 图7

SpringBoot - 图8

自动配置原理分析 - 幕布 (mubu.com)

核心注解:@ ConditionalonXXX:如果这里面的条件都满足,配置才会生效

结论:SpringBoot所有自动配置都是在启动的时候扫描并加载:spring.factories所有的自动配置类都在这里面,但是不一定生效,要判断条件是否成立,只要导入了对应的start,就有对应的启动器了,有了启动器,自动装配就会生效,然后就配置成功

  1. springboot在启动的时候,从类路径下 /META-INF/spring.factories获取指定的值;
  2. 将这些自动配置的类导入容器,自动配置就会生效,从而进行自动配置
  3. 以前需要自动配置的东西,现在 springboot做
  4. 整合 javaEE,解决方案和自动配置的东西都在 spring-boot-autoconfigure2.2.0.RELEASE.jar这个包下
  5. 它会把所有需要导入的组件,以类名的方式返回,这些组件就会被添加到容器
  6. .容器中也会存在非常多的 XXXAutoConfiguration的文件(@Bean),就是这些类给容器中导入了这个场景需要的所有组件;并自动配置@ConfigurationJavaConfig
  7. 有了自动配置类,免去了手动编写配置文件

2.2、SpringApplication.run分祈

分析该方法主要分两部分,一部分是 SpringApplication的实例化,二是run方法的执行;

SpringApplication

  1. 这个类主要做了以下四件事情
  1. 推断应用的类型是普通的项目还是Web项目
  2. 查找并加载所有可用初始化器,设置到 initializers属性中
  3. 找出所有的应用程序监听器,设置到 listeners属性中
  4. 推断并设置main方法的定义类,找到运行的主类

构造器:

  1. public SpringApplication(Class<?>... primarySources) {
  2. //调用下面构造方法
  3. this((ResourceLoader)null, primarySources);
  4. }
  5. public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
  6. //设置一些默认参数
  7. this.sources = new LinkedHashSet();
  8. this.bannerMode = Mode.CONSOLE;
  9. this.logStartupInfo = true;
  10. this.addCommandLineProperties = true;
  11. this.addConversionService = true;
  12. this.headless = true;
  13. this.registerShutdownHook = true;
  14. this.additionalProfiles = new HashSet();
  15. this.isCustomEnvironment = false;
  16. this.lazyInitialization = false;
  17. this.resourceLoader = resourceLoader;
  18. Assert.notNull(primarySources, "PrimarySources must not be null");
  19. //保存主配置类到一个Set集合primarySources中
  20. this.primarySources = new LinkedHashSet(Arrays.asList(primarySources));
  21. //获取当前的应用类型,判断是不是web应用
  22. this.webApplicationType = WebApplicationType.deduceFromClasspath();
  23. //找到META‐INF/spring.factories配置的所有ApplicationContextInitializer;然后保存起来
  24. this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));
  25. //找到META‐INF/spring.ApplicationListener;然后保存起来
  26. this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));
  27. //从多个配置类中找到有main方法的主配置类
  28. this.mainApplicationClass = this.deduceMainApplicationClass();
  29. //执行完毕,SpringApplication对象就创建出来了
  30. }

Run方法

并非是一个main方法,而是开启一个服务;

  1. @SpringBootApplication
  2. public class SpringBootProjectApplication {
  3. public static void main(String[] args) {
  4. // 该方法返回一个ConfigurableApplicationContext对象
  5. // 参数一:应用入口的类 参数:命令行参数
  6. SpringApplication.run(SpringBootProjectApplication.class, args);
  7. }
  8. }

SpringBoot - 图9

JavaConfig、@Configuraion、@Bean

Docker:进程

SpringBoot 运行原理

关于SpringBoot 的理解

  • 自动装配
  • run()

2.3、自动装置分析

HttpEncodingAutoConfiguration(Http编码自动配置)为例解释自动配置原理;

SpringBoot - 图10;)

  1. //表示这是一个配置类,和以前编写的配置文件一样,也可以给容器中添加组件;
  2. @Configuration
  3. //启动指定类的ConfigurationProperties功能;
  4. //进入这个HttpProperties查看,将配置文件中对应的值和HttpProperties绑定起来;
  5. //并把HttpProperties加入到ioc容器中
  6. @EnableConfigurationProperties({HttpProperties.class})
  7. //Spring底层@Conditional注解
  8. //根据不同的条件判断,如果满足指定的条件,整个配置类里面的配置就会生效;
  9. //这里的意思就是判断当前应用是否是web应用,如果是,当前配置类生效
  10. @ConditionalOnWebApplication(
  11. type = Type.SERVLET
  12. )
  13. //判断当前项目有没有这个类CharacterEncodingFilter;SpringMVC中进行乱码解决的过滤器;
  14. @ConditionalOnClass({CharacterEncodingFilter.class})
  15. //判断配置文件中是否存在某个配置:spring.http.encoding.enabled;
  16. //如果不存在,判断也是成立的
  17. //即使我们配置文件中不配置pring.http.encoding.enabled=true,也是默认生效的;
  18. @ConditionalOnProperty(
  19. prefix = "spring.http.encoding",
  20. value = {"enabled"},
  21. matchIfMissing = true
  22. )
  23. public class HttpEncodingAutoConfiguration {
  24. //他已经和SpringBoot的配置文件映射了
  25. private final Encoding properties;
  26. //只有一个有参构造器的情况下,参数的值就会从容器中拿
  27. public HttpEncodingAutoConfiguration(HttpProperties properties) {
  28. this.properties = properties.getEncoding();
  29. }
  30. //给容器中添加一个组件,这个组件的某些值需要从properties中获取
  31. @Bean
  32. @ConditionalOnMissingBean //判断容器没有这个组件?
  33. public CharacterEncodingFilter characterEncodingFilter() {
  34. CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();
  35. filter.setEncoding(this.properties.getCharset().name());
  36. filter.setForceRequestEncoding(this.properties.shouldForce(org.springframework.boot.autoconfigure.http.HttpProperties.Encoding.Type.REQUEST));
  37. filter.setForceResponseEncoding(this.properties.shouldForce(org.springframework.boot.autoconfigure.http.HttpProperties.Encoding.Type.RESPONSE));
  38. return filter;
  39. }
  40. //。。。。。。。
  41. }

一句话总结 :根据当前不同的条件判断,决定这个配置类是否生效!

  • 一但这个配置类生效;这个配置类就会给容器中添加各种组件;
  • 这些组件的属性是从对应的properties类中获取的,这些类里面的每一个属性又是和配置文件绑定的;
  • 所有在配置文件中能配置的属性都是在xxxxProperties类中封装着;
  • 配置文件能配置什么就可以参照某个功能对应的这个属性类
  1. //从配置文件中获取指定的值和bean的属性进行绑定
  2. @ConfigurationProperties(prefix = "spring.http")
  3. public class HttpProperties {
  4. // .....
  5. }

SpringBoot - 图11

这就是自动装配的原理!

精髓

1、SpringBoot启动会加载大量的自动配置类

2、看需要的功能有没有在SpringBoot默认写好的自动配置类当中;

3、再看这个自动配置类中到底配置了哪些组件;(只要要用的组件存在在其中,就不需要再手动配置了)

4、给容器中自动配置类添加组件的时候,会从properties类中获取某些属性。只需要在配置文件中指定这些属性的值即可;

xxxxAutoConfigurartion:自动配置类;给容器中添加组件

xxxxProperties:封装配置文件中相关属性;

了解:@Conditional

  1. 了解完自动装配的原理后,发现一个细节问题,自动配置类必须在一定的条件下才能生效;<br />@Conditional派生注解(Spring注解版原生的@Conditional作用)

作用:必须是@Conditional指定的条件成立,才给容器中添加组件,配置配里面的所有内容才生效;

@Conditional扩展注解 作用(判断是否满足当前指定条件)
@ConditionalOnJava
系统的Java版本是否符合要求;
@ConditionalOnBean
容器中存在指定Bean;
@ConditionalOnMissingBean 容器中不存在指定Bean;
@ConditionalOnExpression 满足SpEL表达式指定
@ConditionalOnClass
系统中有指定的类
@ConditionalOnMissingClass 系统中没有指定的类
@ConditionalOnSingleCandidate 容器中只有一个指定的Bean,或者这个Bean是首选Bean
@ConditionalOnProperty 系统中指定的属性是否有指定的值
@ConditionalOnResource 类路径下是否存在指定资源文件
@ConditionalOnWebApplication 当前是web环境
@ConditionalOnNotWebApplication 当前不是web环境
@ConditionalOnJndi
JNDI存在指定项

查看自动配置类是否生效

可以通过启用 debug=true属性;来让控制台打印自动配置报告,这样就可以很方便的知道哪些自动配置类生效;

  1. #开启springboot的调试类
  2. debug=true

Positive matches:(自动配置类启用的:正匹配)

Negative matches:(没有启动,没有匹配成功的自动配置类:负匹配)

Unconditional classes: (没有条件的类)

自动配置原理

3、SpringBoot配置

3.1、配置文件

SpringBoot使用一个全局的配置文件,配置文件名称是固定的

  • application.properties
    • 语法结构:key=value
  • application.yml

    • 语法结构:key:空格 value


    配置文件的作用:修改 Spring Boot自动配置的默认值,因为SpringBoot在底层都自动配置好了;

3.2、yaml

标记语言

以前的配置文件,大多数都是使用xml来配置;比如一个简单的端口配置,

yaml配置:

  1. prot: 8080

xml配置:

  1. <server>
  2. <port>8081</port>
  3. </server>

基础语法

  1. k:(空格)v
  1. 以此来表示一对键值对(空格不能省略);以空格的缩进来控制层级关系,只要是左边对齐的一列数据都是同一个层级的

注意:属性和值的大小写都是十分敏感的。例如:

  1. server:
  2. port: 8081
  3. path: /hello

值的写法:

字面量:普通的值[数字,布尔值,字符串]

  1. # k: v
  2. name: 6b92d6
  3. # 对象
  4. person:
  5. name: 6b92d6
  6. # 行内写法
  7. person: {name: 6b92d6,age: +∞}
  8. # 数组
  9. color:
  10. - red
  11. - blue
  12. - green
  13. color: [red,blue,green]

注入配置文件

  1. 导入配置文件处理器

    1. <!--导入配置文件处理器,配置文件进行绑定就会有提示-->
    2. <dependency>
    3. <groupId>org.springframework.boot</groupId>
    4. <artifactId>spring-boot-configuration-processor</artifactId>
    5. <optional>true</optional>
    6. </dependency>
  2. 编写yml

    1. person:
    2. name: 6b92d6
    3. age: +∞
    4. happy: false
    5. birth: 2020/20/20
    6. maps: {k1: v1,k2: v2}
    7. lists:
    8. - code
    9. - sleep
    10. - eat
    11. dog:
    12. name:
    13. age: 6
  3. 编写person类和dog类
    ```java /* @ConfigurationProperties作用 将配置文件中配置的每一个属性的值,映射到这个组件中; 告诉SpringBoot将本类中的所有属性和配置文件中相关的配置进行绑定 参数 prefix=”person”:将配置文件中的person下面的所有属性一一对应

    只有这个组件是容器中的组件,才能使用容器提供的 @ConfigurationProperties功能 */

@ConfigurationProperties(prefix = “person”) @Component //注册bean @Validated //数据效验

  1. 也可以下面设置条件判断 随机数等
  2. ```yaml
  3. person:
  4. name: 6b92d6${random.uuid}
  5. age: ${random.int}
  6. happy: false
  7. birth: 2020/20/20
  8. maps: {k1: v1,k2: v2}
  9. hello: happy
  10. lists:
  11. - code
  12. - sleep
  13. - eat
  14. dog:
  15. name: ${person.hello:hello}_黑
  16. age: 16

JavaConfig绑定配置文件的值,可以采取这种或者下面的方式

properties文件的指定加载(注意IDEA编码格式要配置UTF-8)

  1. // 加载指定的配置文件
  2. @PropertySource(value = "classpath:dafran.properties")
  3. //SPEL表达式取出配置文件的值
  4. @Value("${name}")

SpringBoot - 图12

(上面的list和lists没有对应,即为null)

解决爆红:导入依赖

  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-configuration-processor</artifactId>
  4. <optional>true</optional>
  5. </dependency>

对比:

@ConfigurationProperties @Value
功能 批量注入配置文件中的属性 一个个指定
松散绑定(松散语法) 支持 不支持
SpEL 不支持 支持
JSR303数据效验 支持 不支持
复杂类型封装 支持 不支持
  • cp只需要写一次即可,value则需要每个字段都添加
  • 松散绑定:比如yml中写的last-name,这个和 lastName是一样的,后面跟着的字母默认是大写的。这就是松散绑定
  • JSR303数据校验,这个就是可以在字段是增加一层过滤器验证,可以保证数据的合法性
  • 复杂类型封装,yml中可以封装对象,使用@value就不支持

结论:

  • 配置yml和配置 properties都可以获取到值,强烈推荐yml
  • 如果在某个业务中,只需要获取配置文件中的某个值,可以使用一下@value
  • 如果说,专门编写了一个 JavaBean来和配置文件进行映射,就直接使用@configurationProperties

3.3、JSR303

  1. @NotNull(message="名字不能为空")
  2. private String userName;
  3. @Max(value=120,message="年龄最大不能超过120")
  4. private int age;
  5. @Email(message="邮箱格式错误")
  6. private String email;
  7. 空检查
  8. @Null 验证对象是否为null
  9. @NotNull 验证对象是否不为null,无法查检长度为0的字符串
  10. @NotBlank 检査约束字符串是不是Null还有被Trim的长度是否大于8,只对字符串,且会去掉前后空格
  11. @NotEmpty 检查约束元素是否为NULL或者是EMPTY
  12. Booelan检查
  13. @AssertTrue 验证Boo1ean对象是否为true
  14. @AssertFalse 验证Boolean对象是否为false
  15. 长度检查
  16. @Size(min=,max=) 验证对象(Array,Collection,Map,String)长度是否在给定的范围之内
  17. @Length(min=, max=) Validates that the annotated string is between min and max included
  18. 日期检查
  19. @Past 验证Date Calendar对象是否在当前时间之前
  20. @Futur 验证Date Calendar对象是否在当前时间之后
  21. @Pattern 验证String对象是否符合正则表达式的规则 :正则表达式
  22. 等等
  23. 除此以外,还可以自定义一些数据校验规则

JSR303校验

SpringBoot - 图13

3.4、多环境下的配置文件

springboot启动会扫描以下位置的 **application.properties** 或者 **application.yml**文件作为 SpringBoot的默认配置文件

优先级1:项目路径下的 config文件夹配置文件
优先级2:项目路径卜配置文件
优先级3:资源路径下的 config文件夹配置文件
优先级4:资源路径下配置文件

优先级由高到底,高优先级的配置会覆盖低优先级的配置;

SpringBoot会从这四个位置全部加载主配置文件;互补配置;

在最低级的配置文件中设置一个项目访问路径的配置来测试互补问题;

  1. # 配置项目的访问路径
  2. server.servlet.context-path=/dafran

【扩展】指定位置加载配置文件

可以通过 spring.config.location来改变默认的配置文件位置

项目打包好以后,可以使用命令行参数的形式,启动项目的时候来指定配置文件的新位置

这种情况,一般是后期运维做的多。相同配置,外部指定的配置文件优先级最高

  1. java -jar spring-boot-config.jar --spring.configlocation=F:/application.properties

优先级:

  1. file:./config/(项目路径下的config)
  2. file:./
  3. classpath:/config/
  4. classpath:/

多环境切换

profile是Spring对不同环境提供不同配置功能的支持,可以通过激活不同的环境版本,实现快速切换环境

方式一:多配置文件

在主配置文件编写的时候。文件名可以是 application-{profile).properties/yml,用来指定多个环境版本

例如:application-test.properties代表测试环境配置 application- dev.properties代表开发环境配置

但是 SpringBoot并不会直接启动这些配置文件,它默认使用application.properties主配置文件

那么需要通过一个配置来选择需要激活的环境

  1. #比如在配置文件中指定使用dev环境,可以通过设置不同的端口号进行测试
  2. #启动 SpringBoot,就可以看到已经切换到dev下的配置了
  3. spring.profiles.active=dev

方式二:yml多文档块

和properties配置文件一样,但是yml可以不用创建多个配置文件

  1. server:
  2. port: 8081
  3. spring:
  4. profiles:
  5. active: dev
  6. ---
  7. server:
  8. port: 8082
  9. spring:
  10. profiles: dev
  11. ---
  12. server:
  13. port: 8083
  14. spring:
  15. profiles: test

springboot多环境配置文件

4、SpringBoot Web开发

springboot到底配置了什么?能不能进行修改?能修改哪些东西?能不能扩展?

  • XXXXAutoConfiguraion:向容器中自动配置组件
  • XXXXProperties:自动配置类,装配配置文件中自定义的一些内容

要解决的问题:

  • 导入静态资源
  • 首页
  • Jsp,模板引擎Thymeleaf,前端模板
  • 装配扩展 SpringMVC
  • 增删改查
  • 拦截器
  • 国际化

4.1、静态资源

  1. public void addResourceHandlers(ResourceHandlerRegistry registry) {
  2. // 有自定义配置则失效
  3. if (!this.resourceProperties.isAddMappings()) {
  4. logger.debug("Default resource handling disabled");
  5. return;
  6. }
  7. // 通过webjars方式
  8. Duration cachePeriod = this.resourceProperties.getCache().getPeriod();
  9. CacheControl cacheControl = this.resourceProperties.getCache().getCachecontrol().toHttpCacheControl();
  10. if (!registry.hasMappingForPattern("/webjars/**")) {
  11. customizeResourceHandlerRegistration(registry.addResourceHandler("/webjars/**")
  12. .addResourceLocations("classpath:/META-INF/resources/webjars/")
  13. .setCachePeriod(getSeconds(cachePeriod)).setCacheControl(cacheControl));
  14. }
  15. // 通过静态路径
  16. String staticPathPattern = this.mvcProperties.getStaticPathPattern();
  17. if (!registry.hasMappingForPattern(staticPathPattern)) {
  18. customizeResourceHandlerRegistration(registry.addResourceHandler(staticPathPattern)
  19. .addResourceLocations(getResourceLocations(this.resourceProperties.getStaticLocations()))
  20. .setCachePeriod(getSeconds(cachePeriod)).setCacheControl(cacheControl));
  21. }
  22. }

webjars?

  1. **WebJars是将web前端资源(jscss等)打成jar包文件**,然后借助Maven工具,以jar包形式对web前端资源进行统一依赖管理,保证这些Web资源版本唯一性。WebJarsjar包部署在Maven中央仓库上。

静态

  1. @ConfigurationProperties(prefix = "spring.resources", ignoreUnknownFields = false)
  2. public class ResourceProperties {
  3. private static final String[] CLASSPATH_RESOURCE_LOCATIONS = { "classpath:/META-INF/resources/",
  4. "classpath:/resources/", "classpath:/static/", "classpath:/public/" };
  5. /**
  6. * Locations of static resources. Defaults to classpath:[/META-INF/resources/,
  7. * /resources/, /static/, /public/].
  8. */
  9. }

优先级:resources > static > public

总结

  1. 在 springboot,可以使用以下方式处理静态资源
    • webjars localhost:8080/webjars/
    • publicstatic/**resourceslocalhost:8080/
  1. 优先级:resources > static(默认) > public

4.2、自定义组件

  1. public class LoginHandlerInterceptor implements HandlerInterceptor {
  2. @Override
  3. public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
  4. //登陆成功以后,应该有用户的session
  5. Object loginUser = request.getSession().getAttribute("loginUser");
  6. if (loginUser==null){
  7. //没有登录
  8. request.setAttribute("msg","无权限,请先登录");
  9. request.getRequestDispatcher("index.html").forward(request,response);
  10. return false;
  11. }else {
  12. return true;
  13. }
  14. }
  15. }
  1. public class MyLocaleResolver implements LocaleResolver {
  2. //解析请求
  3. @Override
  4. public Locale resolveLocale(HttpServletRequest request) {
  5. //获取请求中的参数
  6. String language = request.getParameter("l");
  7. Locale locale = Locale.getDefault();//如果没有就是默认的
  8. //如果请求的链接携带了国际化参数
  9. if (!StringUtils.isEmpty(language)) {
  10. //zj_CN
  11. String[] split = language.split("_");
  12. //国家,地区
  13. locale = new Locale(split[0],split[1]);
  14. }
  15. return locale;
  16. }
  17. @Override
  18. public void setLocale(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Locale locale) {
  19. }
  20. }
  1. @Configuration
  2. public class MyMvcConfig implements WebMvcConfigurer {
  3. @Override
  4. public void addViewControllers(ViewControllerRegistry registry) {
  5. registry.addViewController("/").setViewName("index");
  6. registry.addViewController("/index.html").setViewName("index");
  7. registry.addViewController("/main.html").setViewName("dashboard");
  8. }
  9. //自定义的国际化组件
  10. @Bean
  11. public LocaleResolver localeResolver() {
  12. return new MyLocaleResolver();
  13. }
  14. @Override
  15. public void addInterceptors(InterceptorRegistry registry) {
  16. registry.addInterceptor(new LoginHandlerInterceptor())
  17. .addPathPatterns("/**")
  18. .excludePathPatterns("/index.html","/","/user/login","/static/*");
  19. }
  20. }

i18n:

  1. login.password=密码
  2. login.tip=请登录
  3. login.remember=记住我
  4. login.username=用户名
  5. login.btu=登录
  1. login.password=
  2. login.tip=Please sign in
  3. login.remember=Remember me
  4. login.username=User Name
  5. login.btu=Sign in

4.3、MVC配置原理

SpringBoot对SpringMVC做了哪些配置

官方文档地址

  1. Spring MVC Auto-configuration
  2. // Spring Boot为Spring MVC提供了自动配置,它可以很好地与大多数应用程序一起工作。
  3. Spring Boot provides auto-configuration for Spring MVC that works well with most applications.
  4. // 自动配置在Spring默认设置的基础上添加了以下功能:
  5. The auto-configuration adds the following features on top of Springs defaults:
  6. // 包含视图解析器
  7. Inclusion of ContentNegotiatingViewResolver and BeanNameViewResolver beans.
  8. // 支持静态资源文件夹的路径,以及webjars
  9. Support for serving static resources, including support for WebJars
  10. // 自动注册了Converter:
  11. // 转换器,这就是我们网页提交数据到后台自动封装成为对象的东西,比如把"1"字符串自动转换为int类型
  12. // Formatter:【格式化器,比如页面给我们了一个2019-8-10,它会给我们自动格式化为Date对象】
  13. Automatic registration of Converter, GenericConverter, and Formatter beans.
  14. // HttpMessageConverters
  15. // SpringMVC用来转换Http请求和响应的的,比如我们要把一个User对象转换为JSON字符串,可以去看官网文档解释;
  16. Support for HttpMessageConverters (covered later in this document).
  17. // 定义错误代码生成规则的
  18. Automatic registration of MessageCodesResolver (covered later in this document).
  19. // 首页定制
  20. Static index.html support.
  21. // 图标定制
  22. Custom Favicon support (covered later in this document).
  23. // 初始化数据绑定器:帮我们把请求数据绑定到JavaBean中!
  24. Automatic use of a ConfigurableWebBindingInitializer bean (covered later in this document).
  25. /*
  26. 如果您希望保留Spring Boot MVC功能,并且希望添加其他MVC配置(拦截器、格式化程序、视图控制器和其他功能),则可以添加自己
  27. 的@configuration类,类型为webmvcconfiguer,但不添加@EnableWebMvc。如果希望提供
  28. RequestMappingHandlerMapping、RequestMappingHandlerAdapter或ExceptionHandlerExceptionResolver的自定义
  29. 实例,则可以声明WebMVCregistrationAdapter实例来提供此类组件。
  30. */
  31. If you want to keep Spring Boot MVC features and you want to add additional MVC configuration
  32. (interceptors, formatters, view controllers, and other features), you can add your own
  33. @Configuration class of type WebMvcConfigurer but without @EnableWebMvc. If you wish to provide
  34. custom instances of RequestMappingHandlerMapping, RequestMappingHandlerAdapter, or
  35. ExceptionHandlerExceptionResolver, you can declare a WebMvcRegistrationsAdapter instance to provide such components.
  36. // 如果您想完全控制Spring MVC,可以添加自己的@Configuration,并用@EnableWebMvc进行注释。
  37. If you want to take complete control of Spring MVC, you can add your own @Configuration annotated with @EnableWebMvc.

MVC自动配置原理

4.4、自定义Starter

说明

启动器模块是一个 空 jar 文件,仅提供辅助性依赖管理,这些依赖可能用于自动装配或者其他类库;

命名归约:

官方命名:

  • 前缀:spring-boot-starter-xxx
  • 比如:spring-boot-starter-web….

自定义命名:

  • xxx-spring-boot-starter
  • 比如:mybatis-spring-boot-starter

编写启动器

1、在IDEA中新建一个空项目 spring-boot-starter-diy

2、新建一个普通Maven模块:dafran-spring-boot-starter

SpringBoot - 图14

3、新建一个SpringBoot模块:dafran-spring-boot-starter-autoconfigure

SpringBoot - 图15

4、点击apply即可,基本结构

SpringBoot - 图16

5、在 自定义的 starter 中 导入 autoconfigure 的依赖!

  1. <!-- 启动器 -->
  2. <dependencies>
  3. <!-- 引入自动配置模块 -->
  4. <dependency>
  5. <groupId>cn.dafran</groupId>
  6. <artifactId>dafran-spring-boot-starter-autoconfigure</artifactId>
  7. <version>0.0.1-SNAPSHOT</version>
  8. </dependency>
  9. </dependencies>

6、将 autoconfigure 项目下多余的文件都删掉,Pom中只留下一个 starter,这是所有的启动器基本配置!

SpringBoot - 图17

7、编写 HelloService 服务

  1. public class HelloService {
  2. HelloProperties helloProperties;
  3. public HelloProperties getHelloProperties() {
  4. return helloProperties;
  5. }
  6. public void setHelloProperties(HelloProperties helloProperties) {
  7. this.helloProperties = helloProperties;
  8. }
  9. public String sayHello(String name){
  10. return helloProperties.getPrefix() + name + helloProperties.getSuffix();
  11. }
  12. }

8、编写HelloProperties 配置类

  1. // 前缀 dafran.hello
  2. @ConfigurationProperties(prefix = "dafran.hello")
  3. public class HelloProperties {
  4. private String prefix;
  5. private String suffix;
  6. public String getPrefix() {
  7. return prefix;
  8. }
  9. public void setPrefix(String prefix) {
  10. this.prefix = prefix;
  11. }
  12. public String getSuffix() {
  13. return suffix;
  14. }
  15. public void setSuffix(String suffix) {
  16. this.suffix = suffix;
  17. }
  18. }

9、编写自动配置类并注入bean,测试!

  1. @Configuration
  2. @ConditionalOnWebApplication //web应用生效
  3. @EnableConfigurationProperties(HelloProperties.class)
  4. public class HelloServiceAutoConfiguration {
  5. @Autowired
  6. HelloProperties helloProperties;
  7. @Bean
  8. public HelloService helloService(){
  9. HelloService service = new HelloService();
  10. service.setHelloProperties(helloProperties);
  11. return service;
  12. }
  13. }

10、在resources编写一个 META-INF\spring.factories

  1. # Auto Configure
  2. org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  3. cn.dafran.HelloServiceAutoConfiguration

11、编写完成后,可以安装到maven仓库中!

SpringBoot - 图18

4.5、新建项目测试自定义的启动器

1、新建一个SpringBoot 项目

2、导入自定义的启动器

  1. <dependency>
  2. <groupId>cn.dafran</groupId>
  3. <artifactId>dafran-spring-boot-starter</artifactId>
  4. <version>1.0-SNAPSHOT</version>
  5. </dependency>

4、编写配置文件 application.properties

  1. dafran.hello.prefix="ppp"
  2. dafran.hello.suffix="sss"

5、启动项目进行测试,结果成功 !

SpringBoot - 图19

5、SpringData

简介

  1. 对于数据访问层,无论是 SQL(关系型数据库) 还是 NOSQL(非关系型数据库),Spring Boot 底层都是采用 Spring Data 的方式进行统一处理。
  2. Spring Boot 底层都是采用 Spring Data 的方式进行统一处理各种数据库,Spring Data 也是 Spring 中与 Spring BootSpring Cloud 等齐名的知名项目。
  3. Sping Data 官网:[https://spring.io/projects/spring-data](https://spring.io/projects/spring-data)
  4. 数据库相关的启动器 :可以参考官方文档:

https://docs.spring.io/spring-boot/docs/2.2.5.RELEASE/reference/htmlsingle/#using-boot-starter

5.1、整合JDBC

创建测试项目测试数据源

1、新建一个项目测试:springboot-data-jdbc ; 引入相应的模块!基础模块

SpringBoot - 图20

2、项目建好之后,发现自动导入了如下的启动器:

  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-jdbc</artifactId>
  4. </dependency>
  5. <dependency>
  6. <groupId>mysql</groupId>
  7. <artifactId>mysql-connector-java</artifactId>
  8. <scope>runtime</scope>
  9. </dependency>

3、编写yaml配置文件连接数据库;

  1. spring:
  2. datasource:
  3. username: root
  4. password: 123456
  5. #serverTimezone=UTC解决时区的报错
  6. url: jdbc:mysql://localhost:3306/db?serverTimezone=UTC&useUnicode=trueuseUnicode=true&characterEncoding=utf-8
  7. #根据mysql版本导入相应驱动
  8. driver-class-name: com.mysql.cj.jdbc.Driver
  9. type: com.alibaba.druid.pool.DruidDataSource

4、配置完这些东西后,就可以直接去使用了,因为SpringBoot已经默认进行了自动配置;去测试类测试一下

  1. @SpringBootTest
  2. class SpringbootDataJdbcApplicationTests {
  3. //DI注入数据源
  4. @Autowired
  5. DataSource dataSource;
  6. @Test
  7. public void contextLoads() throws SQLException {
  8. //看一下默认数据源
  9. System.out.println(dataSource.getClass());
  10. //获得连接
  11. Connection connection = dataSource.getConnection();
  12. System.out.println(connection);
  13. //关闭连接
  14. connection.close();
  15. }
  16. }

结果:可以看到默认配置的数据源为 : class com.zaxxer.hikari.HikariDataSource 。

进行全局搜索,找到数据源的所有自动配置都在 :DataSourceAutoConfiguration文件:

  1. 这里导入的类都在 DataSourceConfiguration 配置类下,可以看出 Spring Boot 2.2.5 默认使用HikariDataSource 数据源,而以前版本,如 Spring Boot 1.5 默认使用 org.apache.tomcat.jdbc.pool.DataSource 作为数据源;
  2. **HikariDataSource 号称 Java WEB 当前速度最快的数据源,相比于传统的 C3P0 DBCPTomcat jdbc 等连接池更加优秀;**

可以使用 spring.datasource.type 指定自定义的数据源类型,值为 要使用的连接池实现的完全限定名。

关于数据源并不做介绍,有了数据库连接,显然就可以 CRUD 操作数据库了。但是需要先了解一个对象 JdbcTemplate

5.1.1、JDBCTemplate

1、有了数据源(com.zaxxer.hikari.HikariDataSource),然后可以拿到数据库连接(java.sql.Connection),有了连接,就可以使用原生的 JDBC 语句来操作数据库;

2、即使不使用第三方第数据库操作框架,如 MyBatis等,Spring 本身也对原生的JDBC 做了轻量级的封装,即JdbcTemplate。

3、数据库操作的所有 CRUD 方法都在 JdbcTemplate 中。

4、Spring Boot 不仅提供了默认的数据源,同时默认已经配置好了 JdbcTemplate 放在了容器中,程序员只需自己注入即可使用

5、JdbcTemplate 的自动配置是依赖 org.springframework.boot.autoconfigure.jdbc 包下的 JdbcTemplateConfiguration 类

JdbcTemplate主要提供以下几类方法:

  • execute方法:可以用于执行任何SQL语句,一般用于执行DDL语句;
  • update方法及batchUpdate方法:update方法用于执行新增、修改、删除等语句;batchUpdate方法用于执行批处理相关语句;
  • query方法及queryForXXX方法:用于执行查询相关语句;
  • call方法:用于执行存储过程、函数相关语句。

测试

编写一个Controller,注入 jdbcTemplate,编写测试方法进行访问测试;

  1. @RestController
  2. @RequestMapping("/jdbc")
  3. public class JdbcController {
  4. /**
  5. * Spring Boot 默认提供了数据源,默认提供了 org.springframework.jdbc.core.JdbcTemplate
  6. * JdbcTemplate 中会自己注入数据源,用于简化 JDBC操作
  7. * 还能避免一些常见的错误,使用起来也不用再自己来关闭数据库连接
  8. */
  9. @Autowired
  10. JdbcTemplate jdbcTemplate;
  11. //查询employee表中所有数据
  12. //List 中的1个 Map 对应数据库的 1行数据
  13. //Map 中的 key 对应数据库的字段名,value 对应数据库的字段值
  14. @GetMapping("/list")
  15. public List<Map<String, Object>> userList(){
  16. String sql = "select * from employee";
  17. List<Map<String, Object>> maps = jdbcTemplate.queryForList(sql);
  18. return maps;
  19. }
  20. //新增一个用户
  21. @GetMapping("/add")
  22. public String addUser(){
  23. //插入语句,注意时间问题
  24. String sql = "insert into employee(last_name, email,gender,department,birth)" +
  25. " values ('dafran','1412148742@qq.com',1,101,'"+ new Date().toLocaleString() +"')";
  26. jdbcTemplate.update(sql);
  27. //查询
  28. return "addOk";
  29. }
  30. //修改用户信息
  31. @GetMapping("/update/{id}")
  32. public String updateUser(@PathVariable("id") int id){
  33. //插入语句
  34. String sql = "update employee set last_name=?,email=? where id="+id;
  35. //数据
  36. Object[] objects = new Object[2];
  37. objects[0] = "秦疆";
  38. objects[1] = "24736743@sina.com";
  39. jdbcTemplate.update(sql,objects);
  40. //查询
  41. return "updateOk";
  42. }
  43. //删除用户
  44. @GetMapping("/delete/{id}")
  45. public String delUser(@PathVariable("id") int id){
  46. //插入语句
  47. String sql = "delete from employee where id=?";
  48. jdbcTemplate.update(sql,id);
  49. //查询
  50. return "deleteOk";
  51. }
  52. }

5.2、集成Druid

Druid简介

Java程序很大一部分要操作数据库,为了提高性能操作数据库的时候,又不得不使用数据库连接池。

Druid 是阿里巴巴开源平台上一个数据库连接池实现,结合了 C3P0、DBCP 等 DB 池的优点,同时加入了日志监控。

Druid 可以很好的监控 DB 池连接和 SQL 的执行情况,天生就是针对监控而生的 DB 连接池。

Druid已经在阿里巴巴部署了超过600个应用,经过一年多生产环境大规模部署的严苛考验。

Spring Boot 2.0 以上默认使用 Hikari 数据源,可以说 Hikari 与 Driud 都是当前 Java Web 上最优秀的数据源,Spring Boot 如何集成 Druid 数据源,如何实现数据库监控。

Github地址:https://github.com/alibaba/druid/

com.alibaba.druid.pool.DruidDataSource 基本配置参数如下:

和其它连接池一样DRUID的DataSource类为:com.alibaba.druid.pool.DruidDataSource,基本配置参数如下:

配置 缺省值 说明
name 配置这个属性的意义在于,如果存在多个数据源,监控的时候可以通过名字来区分开来。 如果没有配置,将会生成一个名字,格式是:”DataSource-“ + System.identityHashCode(this)
jdbcUrl 连接数据库的url,不同数据库不一样。例如: mysql : jdbc:mysql://10.20.153.104:3306/druid2 oracle : jdbc:oracle:thin:@10.20.149.85:1521:ocnauto
username 连接数据库的用户名
password 连接数据库的密码。如果你不希望密码直接写在配置文件中,可以使用ConfigFilter。详细看这里:
https://github.com/alibaba/druid/wiki/使用ConfigFilter
driverClassName 根据url自动识别 这一项可配可不配,如果不配置druid会根据url自动识别dbType,然后选择相应的driverClassName(建议配置下)
initialSize 0 初始化时建立物理连接的个数。初始化发生在显示调用init方法,或者第一次getConnection时
maxActive 8 最大连接池数量
maxIdle 8 已经不再使用,配置了也没效果
minIdle 最小连接池数量
maxWait 获取连接时最大等待时间,单位毫秒。配置了maxWait之后,缺省启用公平锁,并发效率会有所下降,如果需要可以通过配置useUnfairLock属性为true使用非公平锁。
poolPreparedStatements false 是否缓存preparedStatement,也就是PSCache。PSCache对支持游标的数据库性能提升巨大,比如说oracle。在mysql下建议关闭。
maxOpenPreparedStatements -1 要启用PSCache,必须配置大于0,当大于0时,poolPreparedStatements自动触发修改为true。在Druid中,不会存在Oracle下PSCache占用内存过多的问题,可以把这个数值配置大一些,比如说100
validationQuery 用来检测连接是否有效的sql,要求是一个查询语句。如果validationQuery为null,testOnBorrow、testOnReturn、testWhileIdle都不会其作用。
testOnBorrow true 申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。
testOnReturn false 归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能
testWhileIdle false 建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。
timeBetweenEvictionRunsMillis 有两个含义: 1) Destroy线程会检测连接的间隔时间2) testWhileIdle的判断依据,详细看testWhileIdle属性的说明
numTestsPerEvictionRun 不再使用,一个DruidDataSource只支持一个EvictionRun
minEvictableIdleTimeMillis
connectionInitSqls 物理连接初始化的时候执行的sql
exceptionSorter 根据dbType自动识别 当数据库抛出一些不可恢复的异常时,抛弃连接
filters 属性类型是字符串,通过别名的方式配置扩展插件,常用的插件有: 监控统计用的filter:stat日志用的filter:log4j防御sql注入的filter:wall
proxyFilters 类型是List,如果同时配置了filters和proxyFilters,是组合关系,并非替换关系

配置数据源

1、导入 Druid 数据源依赖。

  1. <!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
  2. <dependency>
  3. <groupId>com.alibaba</groupId>
  4. <artifactId>druid</artifactId>
  5. <version>1.1.21</version>
  6. </dependency>

2、切换数据源;(Spring Boot 2.0 以上默认使用 com.zaxxer.hikari.HikariDataSource 数据源,但可以通过 spring.datasource.type 指定数据源。)

3、数据源切换之后,在测试类中注入 DataSource,然后获取到它,输出一看便知是否成功切换;

4、切换成功!既然切换成功,就可以设置数据源连接初始化大小、最大连接数、等待时间、最小连接数 等设置项;可以查看源码

  1. spring:
  2. datasource:
  3. username: root
  4. password: 123456
  5. #serverTimezone=UTC解决时区的报错
  6. url: jdbc:mysql://localhost:3306/permission?useUnicode=true&characterEncoding=utf-8
  7. #根据mysql版本导入相应驱动
  8. driver-class-name: com.mysql.cj.jdbc.Driver
  9. type: com.alibaba.druid.pool.DruidDataSource # 自定义数据源
  10. #Spring Boot 默认是不注入这些属性值的,需要自己绑定
  11. #druid 数据源专有配置
  12. initialSize: 5
  13. minIdle: 5
  14. maxActive: 20
  15. maxWait: 60000
  16. timeBetweenEvictionRunsMillis: 60000
  17. minEvictableIdleTimeMillis: 300000
  18. validationQuery: SELECT 1 FROM DUAL
  19. testWhileIdle: true
  20. testOnBorrow: false
  21. testOnReturn: false
  22. poolPreparedStatements: true
  23. #配置监控统计拦截的filters,stat:监控统计、log4j:日志记录、wall:防御sql注入
  24. #如果允许时报错 java.lang.ClassNotFoundException: org.apache.log4j.Priority
  25. #则导入 log4j 依赖即可,Maven 地址:https://mvnrepository.com/artifact/log4j/log4j
  26. filters: stat,wall,log4j
  27. maxPoolPreparedStatementPerConnectionSize: 20
  28. useGlobalDataSourceStat: true
  29. connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500

5、导入Log4j 的依赖

  1. <!-- https://mvnrepository.com/artifact/log4j/log4j -->
  2. <dependency>
  3. <groupId>log4j</groupId>
  4. <artifactId>log4j</artifactId>
  5. <version>1.2.17</version>
  6. </dependency>

6、现在需要程自己为 DruidDataSource 绑定全局配置文件中的参数,再添加到容器中,而不再使用 Spring Boot 的自动生成了;需要自己添加 DruidDataSource 组件到容器中,并绑定属性;

  1. @Configuration
  2. public class DruidConfig {
  3. /*
  4. 将自定义的 Druid数据源添加到容器中,不再让 Spring Boot 自动创建
  5. 绑定全局配置文件中的 druid 数据源属性到 com.alibaba.druid.pool.DruidDataSource从而让它们生效
  6. @ConfigurationProperties(prefix = "spring.datasource"):作用就是将 全局配置文件中
  7. 前缀为 spring.datasource的属性值注入到 com.alibaba.druid.pool.DruidDataSource 的同名参数中
  8. */
  9. @ConfigurationProperties(prefix = "spring.datasource")
  10. @Bean
  11. public DataSource druidDataSource() {
  12. return new DruidDataSource();
  13. }
  14. }

7、去测试类中测试一下;看是否成功!

  1. @SpringBootTest
  2. class SpringbootDataJdbcApplicationTests {
  3. //DI注入数据源
  4. @Autowired
  5. DataSource dataSource;
  6. @Test
  7. public void contextLoads() throws SQLException {
  8. //看一下默认数据源
  9. System.out.println(dataSource.getClass());
  10. //获得连接
  11. Connection connection = dataSource.getConnection();
  12. System.out.println(connection);
  13. DruidDataSource druidDataSource = (DruidDataSource) dataSource;
  14. System.out.println("druidDataSource 数据源最大连接数:" + druidDataSource.getMaxActive());
  15. System.out.println("druidDataSource 数据源初始化连接数:" + druidDataSource.getInitialSize());
  16. //关闭连接
  17. connection.close();
  18. }
  19. }

5.2.1配置Druid数据源监控

Druid 数据源具有监控的功能,并提供了一个 web 界面方便用户查看,类似安装 路由器 时,人家也提供了一个默认的 web 页面。

所以第一步需要设置 Druid 的后台管理页面,比如 登录账号、密码 等;配置后台管理;

  1. //配置 Druid 监控管理后台的Servlet;
  2. //内置 Servlet 容器时没有web.xml文件,所以使用 Spring Boot 的注册 Servlet 方式
  3. @Bean
  4. public ServletRegistrationBean statViewServlet() {
  5. ServletRegistrationBean bean = new ServletRegistrationBean(new StatViewServlet(), "/druid/*");
  6. // 这些参数可以在 com.alibaba.druid.support.http.StatViewServlet
  7. // 的父类 com.alibaba.druid.support.http.ResourceServlet 中找到
  8. Map<String, String> initParams = new HashMap<>();
  9. initParams.put("loginUsername", "admin"); //后台管理界面的登录账号
  10. initParams.put("loginPassword", "123456"); //后台管理界面的登录密码
  11. //后台允许谁可以访问
  12. //initParams.put("allow", "localhost"):表示只有本机可以访问
  13. //initParams.put("allow", ""):为空或者为null时,表示允许所有访问
  14. initParams.put("allow", "");
  15. //deny:Druid 后台拒绝谁访问
  16. //initParams.put("kuangshen", "192.168.1.20");表示禁止此ip访问
  17. //设置初始化参数
  18. bean.setInitParameters(initParams);
  19. return bean;
  20. }

配置完毕后,可以选择访问 :http://localhost:8080/druid/login.html

配置 Druid web 监控 filter 过滤器

  1. //配置 Druid 监控 之 web 监控的 filter
  2. //WebStatFilter:用于配置Web和Druid数据源之间的管理关联监控统计
  3. @Bean
  4. public FilterRegistrationBean webStatFilter() {
  5. FilterRegistrationBean bean = new FilterRegistrationBean();
  6. bean.setFilter(new WebStatFilter());
  7. //exclusions:设置哪些请求进行过滤排除掉,从而不进行统计
  8. Map<String, String> initParams = new HashMap<>();
  9. initParams.put("exclusions", "*.js,*.css,/druid/*,/jdbc/*");
  10. bean.setInitParameters(initParams);
  11. //"/*" 表示过滤所有请求
  12. bean.setUrlPatterns(Arrays.asList("/*"));
  13. return bean;
  14. }

5.3、整合MyBatis

官方文档:http://mybatis.org/spring-boot-starter/mybatis-spring-boot-autoconfigure/

Maven仓库地址:https://mvnrepository.com/artifact/org.mybatis.spring.boot/mybatis-spring-boot-starter/2.1.1

SpringBoot - 图21

5.3.1、整合测试

1、导入 MyBatis 所需要的依赖

  1. <dependency>
  2. <groupId>org.mybatis.spring.boot</groupId>
  3. <artifactId>mybatis-spring-boot-starter</artifactId>
  4. <version>2.1.1</version>
  5. </dependency>

2、配置数据库连接信息(不变)

  1. spring:
  2. datasource:
  3. username: root
  4. password: 123456
  5. #?serverTimezone=UTC解决时区的报错
  6. url: jdbc:mysql://localhost:3306/springboot?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
  7. driver-class-name: com.mysql.cj.jdbc.Driver
  8. type: com.alibaba.druid.pool.DruidDataSource
  9. #Spring Boot 默认是不注入这些属性值的,需要自己绑定
  10. #druid 数据源专有配置
  11. initialSize: 5
  12. minIdle: 5
  13. maxActive: 20
  14. maxWait: 60000
  15. timeBetweenEvictionRunsMillis: 60000
  16. minEvictableIdleTimeMillis: 300000
  17. validationQuery: SELECT 1 FROM DUAL
  18. testWhileIdle: true
  19. testOnBorrow: false
  20. testOnReturn: false
  21. poolPreparedStatements: true
  22. #配置监控统计拦截的filters,stat:监控统计、log4j:日志记录、wall:防御sql注入
  23. #如果允许时报错 java.lang.ClassNotFoundException: org.apache.log4j.Priority
  24. #则导入 log4j 依赖即可,Maven 地址:https://mvnrepository.com/artifact/log4j/log4j
  25. filters: stat,wall,log4j
  26. maxPoolPreparedStatementPerConnectionSize: 20
  27. useGlobalDataSourceStat: true
  28. connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500

3、测试数据库是否连接成功!

4、创建实体类,导入 Lombok!

Department.java

  1. @Data
  2. @NoArgsConstructor
  3. @AllArgsConstructor
  4. public class Department {
  5. private Integer id;
  6. private String departmentName;
  7. }

5、创建mapper目录以及对应的 Mapper 接口

DepartmentMapper.java

  1. //@Mapper : 表示本类是一个 MyBatis 的 Mapper
  2. @Mapper
  3. @Repository
  4. public interface DepartmentMapper {
  5. // 获取所有部门信息
  6. List<Department> getDepartments();
  7. // 通过id获得部门
  8. Department getDepartment(Integer id);
  9. }

6、对应的Mapper映射文件

DepartmentMapper.xml

  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE mapper
  3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  5. <mapper namespace="com.kuang.mapper.DepartmentMapper">
  6. <select id="getDepartments" resultType="Department">
  7. select * from department;
  8. </select>
  9. <select id="getDepartment" resultType="Department" parameterType="int">
  10. select * from department where id = #{id};
  11. </select>
  12. </mapper>

7、maven配置资源过滤问题

  1. <resources>
  2. <resource>
  3. <directory>src/main/java</directory>
  4. <includes>
  5. <include>**/*.xml</include>
  6. </includes>
  7. <filtering>true</filtering>
  8. </resource>
  9. </resources>

8、编写部门的 DepartmentController 测试

  1. @RestController
  2. public class DepartmentController {
  3. @Autowired
  4. DepartmentMapper departmentMapper;
  5. // 查询全部部门
  6. @GetMapping("/getDepartments")
  7. public List<Department> getDepartments(){
  8. return departmentMapper.getDepartments();
  9. }
  10. // 查询全部部门
  11. @GetMapping("/getDepartment/{id}")
  12. public Department getDepartment(@PathVariable("id") Integer id){
  13. return departmentMapper.getDepartment(id);
  14. }
  15. }

6、MVC自动配置原理

在进行项目编写前,需要明白SpringBoot对SpringMVC还做了哪些配置,包括如何扩展,如何定制。

只有把这些都搞清楚了,在之后使用才会更加得心应手。途径一:源码分析,途径二:官方文档!

地址 :https://docs.spring.io/spring-boot/docs/2.2.5.RELEASE/reference/htmlsingle/#boot-features-spring-mvc-auto-configuration

  1. Spring MVC Auto-configuration
  2. // Spring Boot为Spring MVC提供了自动配置,它可以很好地与大多数应用程序一起工作。
  3. Spring Boot provides auto-configuration for Spring MVC that works well with most applications.
  4. // 自动配置在Spring默认设置的基础上添加了以下功能:
  5. The auto-configuration adds the following features on top of Springs defaults:
  6. // 包含视图解析器
  7. Inclusion of ContentNegotiatingViewResolver and BeanNameViewResolver beans.
  8. // 支持静态资源文件夹的路径,以及webjars
  9. Support for serving static resources, including support for WebJars
  10. // 自动注册了Converter:
  11. // 转换器,这就是我们网页提交数据到后台自动封装成为对象的东西,比如把"1"字符串自动转换为int类型
  12. // Formatter:【格式化器,比如页面给我们了一个2019-8-10,它会给我们自动格式化为Date对象】
  13. Automatic registration of Converter, GenericConverter, and Formatter beans.
  14. // HttpMessageConverters
  15. // SpringMVC用来转换Http请求和响应的的,比如我们要把一个User对象转换为JSON字符串,可以去看官网文档解释;
  16. Support for HttpMessageConverters (covered later in this document).
  17. // 定义错误代码生成规则的
  18. Automatic registration of MessageCodesResolver (covered later in this document).
  19. // 首页定制
  20. Static index.html support.
  21. // 图标定制
  22. Custom Favicon support (covered later in this document).
  23. // 初始化数据绑定器:帮我们把请求数据绑定到JavaBean中!
  24. Automatic use of a ConfigurableWebBindingInitializer bean (covered later in this document).
  25. /*
  26. 如果您希望保留Spring Boot MVC功能,并且希望添加其他MVC配置(拦截器、格式化程序、视图控制器和其他功能),则可以添加自己
  27. 的@configuration类,类型为webmvcconfiguer,但不添加@EnableWebMvc。如果希望提供
  28. RequestMappingHandlerMapping、RequestMappingHandlerAdapter或ExceptionHandlerExceptionResolver的自定义
  29. 实例,则可以声明WebMVCregistrationAdapter实例来提供此类组件。
  30. */
  31. If you want to keep Spring Boot MVC features and you want to add additional MVC configuration
  32. (interceptors, formatters, view controllers, and other features), you can add your own
  33. @Configuration class of type WebMvcConfigurer but without @EnableWebMvc. If you wish to provide
  34. custom instances of RequestMappingHandlerMapping, RequestMappingHandlerAdapter, or
  35. ExceptionHandlerExceptionResolver, you can declare a WebMvcRegistrationsAdapter instance to provide such components.
  36. // 如果您想完全控制Spring MVC,可以添加自己的@Configuration,并用@EnableWebMvc进行注释。
  37. If you want to take complete control of Spring MVC, you can add your own @Configuration annotated with @EnableWebMvc.

6.1、内容协商视图解析器

ContentNegotiatingViewResolver 内容协商视图解析器

自动配置了ViewResolver,就是之前SpringMVC的视图解析器;

即根据方法的返回值取得视图对象(View),然后由视图对象决定如何渲染(转发,重定向)。

这里的源码:找到 WebMvcAutoConfiguration , 然后搜索ContentNegotiatingViewResolver。找到如下方法

  1. @Bean
  2. @ConditionalOnBean(ViewResolver.class)
  3. @ConditionalOnMissingBean(name = "viewResolver", value = ContentNegotiatingViewResolver.class)
  4. public ContentNegotiatingViewResolver viewResolver(BeanFactory beanFactory) {
  5. ContentNegotiatingViewResolver resolver = new ContentNegotiatingViewResolver();
  6. resolver.setContentNegotiationManager(beanFactory.getBean(ContentNegotiationManager.class));
  7. // ContentNegotiatingViewResolver使用所有其他视图解析器来定位视图,因此它应该具有较高的优先级
  8. resolver.setOrder(Ordered.HIGHEST_PRECEDENCE);
  9. return resolver;
  10. }

找到对应的解析视图的代码;

  1. @Nullable // 注解说明:@Nullable 即参数可为null
  2. public View resolveViewName(String viewName, Locale locale) throws Exception {
  3. RequestAttributes attrs = RequestContextHolder.getRequestAttributes();
  4. Assert.state(attrs instanceof ServletRequestAttributes, "No current ServletRequestAttributes");
  5. List<MediaType> requestedMediaTypes = this.getMediaTypes(((ServletRequestAttributes)attrs).getRequest());
  6. if (requestedMediaTypes != null) {
  7. // 获取候选的视图对象
  8. List<View> candidateViews = this.getCandidateViews(viewName, locale, requestedMediaTypes);
  9. // 选择一个最适合的视图对象,然后把这个对象返回
  10. View bestView = this.getBestView(candidateViews, requestedMediaTypes, attrs);
  11. if (bestView != null) {
  12. return bestView;
  13. }
  14. }
  15. // .....
  16. }

getCandidateViews中看到把所有的视图解析器拿来,进行while循环,挨个解析。

  1. Iterator var5 = this.viewResolvers.iterator();

所以得出结论:ContentNegotiatingViewResolver 这个视图解析器就是用来组合所有的视图解析器的

再去研究下组合逻辑,看到有个属性viewResolvers,看看是在哪里进行赋值的

  1. protected void initServletContext(ServletContext servletContext) {
  2. // 这里它是从beanFactory工具中获取容器中的所有视图解析器
  3. // ViewRescolver.class 把所有的视图解析器来组合的
  4. Collection<ViewResolver> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(this.obtainApplicationContext(), ViewResolver.class).values();
  5. ViewResolver viewResolver;
  6. if (this.viewResolvers == null) {
  7. this.viewResolvers = new ArrayList(matchingBeans.size());
  8. }
  9. // ...............
  10. }

可以自己给容器中去添加一个视图解析器;这个类就会自动的将它组合进来;

1、在主程序中去写一个视图解析器来试试;

  1. @Bean //放到bean中
  2. public ViewResolver myViewResolver(){
  3. return new MyViewResolver();
  4. }
  5. //写一个静态内部类,视图解析器就需要实现ViewResolver接口
  6. private static class MyViewResolver implements ViewResolver{
  7. @Override
  8. public View resolveViewName(String s, Locale locale) throws Exception {
  9. return null;
  10. }
  11. }

2、怎么看自定义的视图解析器有没有起作用

给 DispatcherServlet 中的 doDispatch方法 加个断点进行调试一下,因为所有的请求都会走到这个方法中

3、启动项目,然后随便访问一个页面,看一下Debug信息;

找到this

找到视图解析器,看到自定义的就在这里了;

6.2、转换器和格式化器

找到格式化转换器:

  1. @Bean
  2. @Override
  3. public FormattingConversionService mvcConversionService() {
  4. // 拿到配置文件中的格式化规则
  5. WebConversionService conversionService =
  6. new WebConversionService(this.mvcProperties.getDateFormat());
  7. addFormatters(conversionService);
  8. return conversionService;
  9. }

点击去:

  1. public String getDateFormat() {
  2. return this.dateFormat;
  3. }
  4. /**
  5. * Date format to use. For instance, `dd/MM/yyyy`. 默认的
  6. */
  7. private String dateFormat;

可以看到在Properties文件中,可以进行自动配置

如果配置了自定义的格式化方式,就会注册到Bean中生效,也可以在配置文件中配置日期格式化的规则:

6.3、修改SpringBoot的默认配置

这么多的自动配置,原理都是一样的,通过这个WebMVC的自动配置原理分析,要学会通过源码探究

SpringBoot的底层,大量用到了这些设计细节思想,所以,没事需要多阅读源码!得出结论;

SpringBoot在自动配置很多组件的时候,先看容器中有没有用户自己配置的(如果用户自己配置@bean),如果有就用用户配置的,如果没有就用自动配置的;

如果有些组件可以存在多个,比如视图解析器,就将用户配置的和默认的组合起来!

扩展使用SpringMVC 官方文档如下:

If you want to keep Spring Boot MVC features and you want to add additional MVC configuration (interceptors, formatters, view controllers, and other features), you can add your own @Configuration class of type WebMvcConfigurer but without @EnableWebMvc. If you wish to provide custom instances of RequestMappingHandlerMapping, RequestMappingHandlerAdapter, or ExceptionHandlerExceptionResolver, you can declare a WebMvcRegistrationsAdapter instance to provide such components.

编写一个@Configuration注解类,并且类型要为WebMvcConfigurer,还不能标注@EnableWebMvc注解;自定义一个;新建一个包叫config,写一个类MyMvcConfig;

  1. //应为类型要求为WebMvcConfigurer,所以我们实现其接口
  2. //可以使用自定义类扩展MVC的功能
  3. @Configuration
  4. public class MyMvcConfig implements WebMvcConfigurer {
  5. @Override
  6. public void addViewControllers(ViewControllerRegistry registry) {
  7. // 浏览器发送/test , 就会跳转到test页面;
  8. registry.addViewController("/test").setViewName("test");
  9. }
  10. }

确实跳转过来了!所以说,要扩展SpringMVC,官方就推荐我们这么去使用,既保SpringBoot留所有的自动配置,也能扩展的配置!

分析一下原理:

1、WebMvcAutoConfiguration 是 SpringMVC的自动配置类,里面有一个类WebMvcAutoConfigurationAdapter

2、这个类上有一个注解,在做其他自动配置时会导入:@Import(EnableWebMvcConfiguration.class)

3、点进EnableWebMvcConfiguration这个类看一下,它继承了一个父类:DelegatingWebMvcConfiguration

这个父类中有这样一段代码

  1. public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {
  2. private final WebMvcConfigurerComposite configurers = new WebMvcConfigurerComposite();
  3. // 从容器中获取所有的webmvcConfigurer
  4. @Autowired(required = false)
  5. public void setConfigurers(List<WebMvcConfigurer> configurers) {
  6. if (!CollectionUtils.isEmpty(configurers)) {
  7. this.configurers.addWebMvcConfigurers(configurers);
  8. }
  9. }
  10. }

4、可以在这个类中去寻找一个自定义设置的viewController当做参考,发现它调用了一个

  1. protected void addViewControllers(ViewControllerRegistry registry) {
  2. this.configurers.addViewControllers(registry);
  3. }

5、点进去看一下

  1. public void addViewControllers(ViewControllerRegistry registry) {
  2. Iterator var2 = this.delegates.iterator();
  3. while(var2.hasNext()) {
  4. // 将所有的WebMvcConfigurer相关配置来一起调用!包括自定义配置的和Spring给配置的
  5. WebMvcConfigurer delegate = (WebMvcConfigurer)var2.next();
  6. delegate.addViewControllers(registry);
  7. }
  8. }

所以得出结论:所有的WebMvcConfiguration都会被作用,不止Spring自己的配置类,自定义的配置类也会被调用;

6.4、全面接管SpringMVC

官方文档:

  1. If you want to take complete control of Spring MVC
  2. you can add your own @Configuration annotated with @EnableWebMvc.

全面接管即:SpringBoot对SpringMVC的自动配置不需要了,所有都是自定义配置

只需在自定义的配置类中要加一个@EnableWebMvc。

如果全面接管了SpringMVC了,之前SpringBoot配置的静态资源映射一定会无效。

在开发中,不推荐使用全面接管SpringMVC

为什么加了一个注解,自动配置就失效了!看下源码:

1、这里发现它是导入了一个类,可以继续进去看

  1. @Import({DelegatingWebMvcConfiguration.class})
  2. public @interface EnableWebMvc {
  3. }

2、它继承了一个父类 WebMvcConfigurationSupport

  1. public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {
  2. // ......
  3. }

3、来回顾一下Webmvc自动配置类

  1. @Configuration(proxyBeanMethods = false)
  2. @ConditionalOnWebApplication(type = Type.SERVLET)
  3. @ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })
  4. // 这个注解的意思就是:容器中没有这个组件的时候,这个自动配置类才生效
  5. @ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
  6. @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
  7. @AutoConfigureAfter({ DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class,
  8. ValidationAutoConfiguration.class })
  9. public class WebMvcAutoConfiguration {
  10. }

总结一句话:@EnableWebMvc将WebMvcConfigurationSupport组件导入进来了;

而导入的WebMvcConfigurationSupport只是SpringMVC最基本的功能!

在SpringBoot中会有非常多的扩展配置,只要看见了这个,就应该多留心注意

7、SpringBoot注解最全详解

使用注解的优势:

1.采用纯java代码,不在需要配置繁杂的xml文件

2.在配置中也可享受面向对象带来的好处

3.类型安全对重构可以提供良好的支持

4.减少复杂配置文件的同时亦能享受到springIoC容器提供的功能

一、注解详解(配备了完善的释义)———(可采用ctrl+F 来进行搜索)

@SpringBootApplication:申明让spring boot自动给程序进行必要的配置,这个配置等同于:

@Configuration ,@EnableAutoConfiguration 和 @ComponentScan 三个配置。

@ResponseBody:表示该方法的返回结果直接写入HTTP response body中,一般在异步获取数据时使用,用于构建RESTful的api。在使用@RequestMapping后,返回值通常解析为跳转路径,加上@esponsebody后返回结果不会被解析为跳转路径,而是直接写入HTTP response body中。比如异步获取json数据,加上@Responsebody后,会直接返回json数据。该注解一般会配合@RequestMapping一起使用。

@Controller:用于定义控制器类,在spring项目中由控制器负责将用户发来的URL请求转发到对应的服务接口(service层),一般这个注解在类中,通常方法需要配合注解@RequestMapping。

@RestController:用于标注控制层组件(如struts中的action),@ResponseBody和@Controller的合集。

@RequestMapping:提供路由信息,负责URL到Controller中的具体函数的映射。

@EnableAutoConfiguration:SpringBoot自动配置(auto-configuration):尝试根据你添加的jar依赖自动配置你的Spring应用。例如,如果你的classpath下存在HSQLDB,并且你没有手动配置任何数据库连接beans,那么我们将自动配置一个内存型(in-memory)数据库”。你可以将@EnableAutoConfiguration或者@SpringBootApplication注解添加到一个@Configuration类上来选择自动配置。如果发现应用了你不想要的特定自动配置类,你可以使用@EnableAutoConfiguration注解的排除属性来禁用它们。

@ComponentScan:表示将该类自动发现扫描组件。个人理解相当于,如果扫描到有@Component、@Controller、@Service等这些注解的类,并注册为Bean,可以自动收集所有的Spring组件,包括@Configuration类。我们经常使用@ComponentScan注解搜索beans,并结合@Autowired注解导入。可以自动收集所有的Spring组件,包括@Configuration类。我们经常使用@ComponentScan注解搜索beans,并结合@Autowired注解导入。如果没有配置的话,Spring Boot会扫描启动类所在包下以及子包下的使用了@Service,@Repository等注解的类。

@Configuration:相当于传统的xml配置文件,如果有些第三方库需要用到xml文件,建议仍然通过@Configuration类作为项目的配置主类——可以使用@ImportResource注解加载xml配置文件。

@Import:用来导入其他配置类。

@ImportResource:用来加载xml配置文件。

@Autowired:自动导入依赖的bean

@Service:一般用于修饰service层的组件

@Repository:使用@Repository注解可以确保DAO或者repositories提供异常转译,这个注解修饰的DAO或者repositories类会被ComponetScan发现并配置,同时也不需要为它们提供XML配置项。

@Bean:用@Bean标注方法等价于XML中配置的bean。

@Value:注入Spring boot application.properties配置的属性的值。示例代码:

@Inject:等价于默认的@Autowired,只是没有required属性;

@Component:泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。

@Bean:相当于XML中的,放在方法的上面,而不是类,意思是产生一个bean,并交给spring管理。

@AutoWired:自动导入依赖的bean。byType方式。把配置好的Bean拿来用,完成属性、方法的组装,它可以对类成员变量、方法及构造函数进行标注,完成自动装配的工作。当加上(required=false)时,就算找不到bean也不报错。

@Qualifier:当有多个同一类型的Bean时,可以用@Qualifier(“name”)来指定。与@Autowired配合使用。@Qualifier限定描述符除了能根据名字进行注入,但能进行更细粒度的控制如何选择候选者,具体使用方式如下:

@Resource(name=”name”,type=”type”):没有括号内内容的话,默认byName。与@Autowired干类似的事。

二、注解列表如下

@SpringBootApplication:包含了@ComponentScan、@Configuration和@EnableAutoConfiguration注解。其中

@ComponentScan:让spring Boot扫描到Configuration类并把它加入到程序上下文。

@Configuration :等同于spring的XML配置文件;使用Java代码可以检查类型安全。

@EnableAutoConfiguration :自动配置。

@ComponentScan :组件扫描,可自动发现和装配一些Bean。

@Component可配合CommandLineRunner使用,在程序启动后执行一些基础任务。

@RestController:注解是@Controller和@ResponseBody的合集,表示这是个控制器bean,并且是将函数的返回值直 接填入HTTP响应体中,是REST风格的控制器。

@Autowired:自动导入。

@PathVariable:获取参数。

@JsonBackReference:解决嵌套外链问题。

@RepositoryRestResourcepublic:配合spring-boot-starter-data-rest使用。

三、JPA注解

@Entity:@Table(name=”“):表明这是一个实体类。一般用于jpa这两个注解一般一块使用,但是如果表名和实体类名相同的话,@Table可以省略

@MappedSuperClass:用在确定是父类的entity上。父类的属性子类可以继承。

@NoRepositoryBean:一般用作父类的repository,有这个注解,spring不会去实例化该repository。

@Column:如果字段名与列名相同,则可以省略。

@Id:表示该属性为主键。

@GeneratedValue(strategy = GenerationType.SEQUENCE,generator = “repair_seq”):表示主键生成策略是sequence(可以为Auto、IDENTITY、native等,Auto表示可在多个数据库间切换),指定sequence的名字是repair_seq。

@SequenceGeneretor(name = “repair_seq”, sequenceName = “seq_repair”, allocationSize = 1):name为sequence的名称,以便使用,sequenceName为数据库的sequence名称,两个名称可以一致。

@Transient:表示该属性并非一个到数据库表的字段的映射,ORM框架将忽略该属性。如果一个属性并非数据库表的字段映射,就务必将其标示为@Transient,否则,ORM框架默认其注解为@Basic。@Basic(fetch=FetchType.LAZY):标记可以指定实体属性的加载方式

@JsonIgnore:作用是json序列化时将Java bean中的一些属性忽略掉,序列化和反序列化都受影响。

@JoinColumn(name=”loginId”):一对一:本表中指向另一个表的外键。一对多:另一个表指向本表的外键。

@OneToOne、@OneToMany、@ManyToOne:对应hibernate配置文件中的一对一,一对多,多对一。

四、springMVC相关注解

@RequestMapping:@RequestMapping(“/path”)表示该控制器处理所有“/path”的UR L请求。RequestMapping是一个用来处理请求地址映射的注解,可用于类或方法上。
用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径。该注解有六个属性:
params:指定request中必须包含某些参数值是,才让该方法处理。
headers:指定request中必须包含某些指定的header值,才能让该方法处理请求。
value:指定请求的实际地址,指定的地址可以是URI Template 模式
method:指定请求的method类型, GET、POST、PUT、DELETE等
consumes:指定处理请求的提交内容类型(Content-Type),如application/json,text/html;
produces:指定返回的内容类型,仅当request请求头中的(Accept)类型中包含该指定类型才返回

@RequestParam:用在方法的参数前面。
@RequestParam
String a =request.getParameter(“a”)。

@PathVariable:路径变量。如

参数与大括号里的名字一样要相同。

五、全局异常处理

@ControllerAdvice:包含@Component。可以被扫描到。统一处理异常。

@ExceptionHandler(Exception.class):用在方法上面表示遇到这个异常就执行以下方法。


六、项目中具体配置解析和使用环境

@MappedSuperclass:

1.@MappedSuperclass 注解使用在父类上面,是用来标识父类的

2.@MappedSuperclass 标识的类表示其不能映射到数据库表,因为其不是一个完整的实体类,但是它所拥有的属性能够映射在其子类对用的数据库表中

3.@MappedSuperclass 标识的类不能再有@Entity或@Table注解

@Column:

1.当实体的属性与其映射的数据库表的列不同名时需要使用@Column标注说明,该属性通常置于实体的属性声明语句之前,还可与 @Id 标注一起使用。

2.@Column 标注的常用属性是name,用于设置映射数据库表的列名。此外,该标注还包含其它多个属性,如:unique、nullable、length、precision等。具体如下:

1 name属性:name属性定义了被标注字段在数据库表中所对应字段的名称

2 unique属性:unique属性表示该字段是否为唯一标识,默认为false,如果表中有一个字段需要唯一标识,则既可以使用该标记,也可以使用@Table注解中的@UniqueConstraint

3 nullable属性:nullable属性表示该字段是否可以为null值,默认为true

4 insertable属性:insertable属性表示在使用”INSERT”语句插入数据时,是否需要插入该字段的值

5 updateable属性:updateable属性表示在使用”UPDATE”语句插入数据时,是否需要更新该字段的值

6 insertable和updateable属性:一般多用于只读的属性,例如主键和外键等,这些字段通常是自动生成的

7 columnDefinition属性:columnDefinition属性表示创建表时,该字段创建的SQL语句,一般用于通过Entity生成表定义时使用,如果数据库中表已经建好,该属性没有必要使用

8 table属性:table属性定义了包含当前字段的表名

9 length属性:length属性表示字段的长度,当字段的类型为varchar时,该属性才有效,默认为255个字符

10 precision属性和scale属性:precision属性和scale属性一起表示精度,当字段类型为double时,precision表示数值的总长度,scale表示小数点所占的位数

具体如下:
1.double类型将在数据库中映射为double类型,precision和scale属性无效
2.double类型若在columnDefinition属性中指定数字类型为decimal并指定精度,则最终以columnDefinition为准
3.BigDecimal类型在数据库中映射为decimal类型,precision和scale属性有效
4.precision和scale属性只在BigDecimal类型中有效

3.@Column 标注的columnDefinition属性: 表示该字段在数据库中的实际类型.通常 ORM 框架可以根据属性类型自动判断数据库中字段的类型,但是对于Date类型仍无法确定数据库中字段类型究竟是DATE,TIME还是TIMESTAMP.此外,String的默认映射类型为VARCHAR,如果要将 String 类型映射到特定数据库的 BLOB 或TEXT字段类型.

4.@Column标注也可置于属性的getter方法之前

@Getter和@Setter(Lombok)

@Setter:注解在属性上;为属性提供 setting 方法 @Getter:注解在属性上;为属性提供 getting 方法

1 @Data:注解在类上;提供类所有属性的 getting 和 setting 方法,此外还提供了equals、canEqual、hashCode、toString 方法
2
3 @Setter:注解在属性上;为属性提供 setting 方法
4
5 @Getter:注解在属性上;为属性提供 getting 方法
6
7 @Log4j2 :注解在类上;为类提供一个 属性名为log 的 log4j 日志对象,和@Log4j注解类似
8
9 @NoArgsConstructor:注解在类上;为类提供一个无参的构造方法
10
11 @AllArgsConstructor:注解在类上;为类提供一个全参的构造方法
12
13 @EqualsAndHashCode:默认情况下,会使用所有非瞬态(non-transient)和非静态(non-static)字段来生成equals和hascode方法,也可以指定具体使用哪些属性。
14
15 @toString:生成toString方法,默认情况下,会输出类名、所有属性,属性会按照顺序输出,以逗号分割。
16
17 @NoArgsConstructor, @RequiredArgsConstructor and @AllArgsConstructor
18 无参构造器、部分参数构造器、全参构造器,当我们需要重载多个构造器的时候,只能自己手写了
19
20 @NonNull:注解在属性上,如果注解了,就必须不能为Null
21
22 @val:注解在属性上,如果注解了,就是设置为final类型,可查看源码的注释知道

当你在执行各种持久化方法的时候,实体的状态会随之改变,状态的改变会引发不同的生命周期事件。这些事件可以使用不同的注释符来指示发生时的回调函数。

@javax.persistence.PostLoad:加载后。

@javax.persistence.PrePersist:持久化前。

@javax.persistence.PostPersist:持久化后。

@javax.persistence.PreUpdate:更新前。

@javax.persistence.PostUpdate:更新后。

@javax.persistence.PreRemove:删除前。

@javax.persistence.PostRemove:删除后。

1)数据库查询

@PostLoad事件在下列情况下触发:

执行EntityManager.find()或getreference()方法载入一个实体后。

执行JPQL查询后。

EntityManager.refresh()方法被调用后。

2)数据库插入

@PrePersist和@PostPersist事件在实体对象插入到数据库的过程中发生:

@PrePersist事件在调用persist()方法后立刻发生,此时的数据还没有真正插入进数据库。

@PostPersist事件在数据已经插入进数据库后发生。

3)数据库更新

@PreUpdate和@PostUpdate事件的触发由更新实体引起:

@PreUpdate事件在实体的状态同步到数据库之前触发,此时的数据还没有真正更新到数据库。

@PostUpdate事件在实体的状态同步到数据库之后触发,同步在事务提交时发生。

4)数据库删除

@PreRemove和@PostRemove事件的触发由删除实体引起:

@PreRemove事件在实体从数据库删除之前触发,即在调用remove()方法删除时发生,此时的数据还没有真正从数据库中删除。

@PostRemove事件在实体从数据库中删除后触发。