记录SpringBoot学习之旅

文章目录

SpringBoot

感谢秦老师 指路: 秦老师

image-20200518143037005

什么是Spring

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

Spring是如何简化Java开发的

为了降低Java开发的复杂性,Spring采用了以下4种关键策略:

  • 基于POJO的轻量级和最小侵入性编程;
  • 通过IOC,依赖注入(DI)和面向接口实现松耦合;
  • 基于切面(AOP) 和惯例进行声明式编程;
  • 通过切面和模版减少样式代码;

什么 SpringBoot

学过javaweb的同学 就知道,开发-个web应用,从最初开始接触Servlet结合Tomcat,跑出一个Hello Wolrld程序,是要经历特别多的步骤;后来就用了框架Struts,再后来是SpringMVC,到了现在的SpringBoot,过一两年又会有其他web框架出现;不知道你们有没经历过框架不断的演进,然后自己开发项目所有的技术也再不断的变化、改造,反正我是都经历过了,哈哈。言归正传,什么是SpringBoot呢,就是一个javaweb的开发框架,和SpringMVC类似,对比其他javaweb框 架的好处,官方说是简化开发,约定大于配置,you can “just run”,能迅速的开发web应用,几行代码开发一个http接口.

所有的技术框架的发展似乎都遵循了-条主线规律:从一个复杂应用场景衍生-种规范框架,人们只需要进行各种配置而不需要自己去实现它,这时候强大的配置功能成了优点;发展到一定程度之后,人们根据实际生产应用情况,选取其中实用功能和设计精华,重构出一些轻量级的框架;之后为了提高开发效率,嫌弃原先的各类配置过于麻烦,于是开始提倡”约定大于配置”,进而衍生出一些一站式的解决方案。

是的这就是Java企业级应用-> J2EE-> spring-> springboot的过程。
随着Spring不断的发展,涉及的领域越来越多,项目整合开发需要配合各种各样的文件,慢慢变得不那么易用简单,违背了最初的理念,甚至人称配置地狱。Spring Boot正是在这样的一个背景下被抽象出来的开发框架,目的为了让大家更容易的使用Spring、更容易的集成各种常用的中间件、开源软件;

Spring Boot基于Spring开发, Spirng Boot本身并不提供Spring框架的核心特性以及扩展功能,只是用于快速、敏捷地开发新一代基于Spring框架的应用程序。也就是说,它并不是用来替代Spring的解决方案,而是和Spring框架紧密结合用于提升Spring开发者体验的工具。SpringBoot以约定大于配置的核心思想,默认帮我们进行了很多设置,多数Spring Boot应用只需要很少的Spring配置。同时它集成了大量常用的第三方库配置(例如Redis、MongoDB、Jpa、RabbitMQ、Quartz 等等),Spring Boot应用中这些第三方库几乎可以零配置的开箱即用,

简单来说就是SpringBoot其实不是什么新的框架,它默认配置了很多框架的使用方式,就像maven整合了所有的jar包,spring boot整合了所有的框架
Spring Boot 出生名门,从一开始就站在-个比较高的起点,又经过这几年的发展,生态足够完善,Spring Boot 已经当之无愧成为Java 领域最热门的技术。

SpringBoot的主要优点:

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

Springboot starter官方文档 https://docs.spring.io/spring-boot/docs/2.2.7.RELEASE/reference/html/using-spring-boot.html#using-boot-starter

微服务

什么是微服务?

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

单体应用架构

所谓单体应用架构(all in one)是指,我们将一个应用的中的所有应用服务都封装在一个应用中。
无论是ERP、CRM或是其他什么系统,你都把数据库访问,web访问,等等各个功能放到一个war包内。

  • 这样做的好处是,易于开发和测试;也十分方便部署;当需要扩展时,只需要将war复制多份,然后放到多个服务器上,再做个负载均衡就可以了。
  • 单体应用架构的缺点是,哪怕我要修改一个非常小的地方,我都需要停掉整个服务,重新打包、部署这个应用war包。特别是对于一个大型应用,我们不可能吧所有内容都放在一个应用里面,我们如何维护、如何分I合作都是问题。

微服务架构

image

all in one的架构方式,我们把所有的功能单元放在一个应用里面。然后我们把整个应用部署到服务器上。如果负载能力不行,我们将整个应用进行水平复制,进行扩展,然后在负载均衡。
所谓微服务架构,就是打破之前all in one的架构方式,把每个功能元索独立出来。把独立出来的功能元索的动态组合,需要的功能元索才去拿来组合,需要多一些时 可以整合多个功能元素。所以微服务架构是对功能元索进行复制,而没有对整个应用进行复制。

这样做的好处是:

  1. 节省了调用资源
  2. 每个功能元素的服务都是一个可替换的,可独立升级的软件代码.

如何构建微服务

一个大型系统的微服务架构,就像一个复杂交织的神经网络,每-个神经元就是- -个功能元素,它们各自完成自己的功能,然后通过http相互请求调用。比如一个电商系统,查缓存、连数据库、浏览页面、结账、支付等服务都是一个个独立的功能服务,都被微化了,它们作为一个个微服务共同构建了一个庞大的系统。如果修改其中的一个功能,只需要更新升级其中-个功能服务单元即可。
但是这种庞大的系统架构给部署和运维带来很大的难度。于是,spring为我们带来了构建大型分布式微服务的全套、全程产品:

  • 构建-个个功能独立的微服务应用单元,可以使用springboot, 可以帮我们快速构建一个 应用;
  • 大型分布式网络服务的调用,这部分由spring cloud来完成,实现分布式;
  • 在分布式中间,进行流式数据计算、批处理,我们有spring cloud data flow。
  • spring为我们想清楚了整个从开始构建应用到大型分布式应用全流程方案。

image-20200518145905217

第一个SpringBoot程序

  1. IDEA整合了Springboot,创建项目时选择Spring Initializer创建项目
  2. 在启动类同级目录下建包

image-20200518160335795

  1. 编写controller,加上@RestController注解,就可以不用写@Responsebody了image-20200518160712836
  2. 启动类本身就是spring的一个组件,@SpringbootApplication整合@Springbootconfiguration,再进去是@Configuration,最底层是一个@Componentimage-20200518160904227
  3. pom依赖[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8ijOENbH-1590996141553)(upload\image-20200518160954380.png)]
  4. springboot帮我们自动导入的web依赖[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HNmUlrlx-1590996141554)(upload\image-20200518161047662.png)]

主要有四个部分:

  • 项目元数据信息:创建时候输入的Project Metadata部分, 也就是Maven项目的基本元素,包括: groupld、 artifactld、 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来直接运行。

自动装配原理初探

pom.xml

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

启动器:

  • <dependency>
    	<groupId>org.springframework.boot</groupId>
    	<artifactId>spri ng-boot-starter</artifactId>
    </dependency>
    
  • 启动器:说白了就是springboot的启动场景

  • 比如spring-boot-starter-web,他就会帮我们自动导入web环境所有的依赖

  • springboot会将所有的功能场景,都变成一个个的启动器

  • 如果我们要使用什么功能,就只需要找到对应的启动器就可以了 Starter

主程序

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class HelloworldApplication {
   

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

}

注解

  • @SpringBootConfiguration	:	springboot的配置
    	@Configuration	:	spring配置类
    	@Component	:	说明这也是一个spring的组件
            
    @EnableAutoConfiguration	:	自动配置
        @AutoConfigurationPackage   	:	自动配置包
            @Import({
         Registrar.class})	:	自动配置'包注册'
        @Import({
         AutoConfigurationImportSelector.class})	:	自动配置导入选择   
            
    @ComponentScan	:	扫描当前主启动类同级的包
        
    //获取所有的配置
    List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
    

    获取候选的配置

    protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
         
            List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader());
            Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you are using a custom packaging, make sure that file is correct.");
            return configurations;
    }
    

    META-INF/spring.factories:自动配置的核心文件

    image-20200518164312472

image-20200518164537691

每一个自动装配的类(bean)最终会对应一个properties或者yml配置文件,通过导入的方式进行参数绑定,以达到自动配置的效果.

@Conditional扩展注解

image-20200519143606147

结论:

虽然是有这么多自动配置,但为什么不是每一个都会生效呢?原因是因为在对应的自动配置类中会进行条件判断’@ConditionOnxxx’,条件成立了之后配置才会生效.例如我们导入了web的starter,web相关的配置就会生效,而我们没有开启AOP,那AOP的相关配置就不会生效

  1. springboot在启动的时候,从类路径下META-INF/spring.factories获取指定的值
  2. 将这些自动配置的类导入容器,自动配置就会生效,帮我门进行自动配置
  3. 以前我们需要自动配置的东西,现在springboot帮我门做了
  4. 整个javaEE,解决方案和自动配置的东西都在spring-boot-autoconfigure包下
  5. 他会把所有需要导入的组件,以类名的方式返回,这些组件就会被添加到容器
  6. 容器中也会存在非常多的xxxxAutoConfiguration的文件(@Bean),就是这些类给容器导入了这个场景需要的所有组件

SpringApplication

这个类主要做了以下四个事情

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

查看构造器

public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
   
        this.sources = new LinkedHashSet();
        this.bannerMode = Mode.CONSOLE;
        this.logStartupInfo = true;
        this.addCommandLineProperties = true;
        this.addConversionService = true;
        this.headless = true;
        this.registerShutdownHook = true;
        this.additionalProfiles = new HashSet();
        this.isCustomEnvironment = false;
        this.lazyInitialization = false;
        this.resourceLoader = resourceLoader;
        Assert.notNull(primarySources, "PrimarySources must not be null");
        this.primarySources = new LinkedHashSet(Arrays.asList(primarySources));
        this.webApplicationType = WebApplicationType.deduceFromClasspath();
        this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));
        this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));
        this.mainApplicationClass = this.deduceMainApplicationClass();
    }

springboot启动流程

关于springboot,谈谈你的理解

  • 自动装配
  • run()

SpringBoot配置

配置文件

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

  • application.properties
    • 语法结构: key=value
  • application.yaml
    • 语法结构: key: 空格 value

配置文件的作用: 修改springboot自动配置的默认值,因为springboot在底层都给我们自动配置好了

YAML

YAML是"YAML Ain’t a Markup Language" (YAML不是一 种置标语言)的递归缩写。
在开发的这种语言时,YAML的意思其实是: “Yet Another Markup Language” (仍是一种置标语言)
YAML A Markup Language :是一个标记语言
YAML isnot Markup Language :不是一个标记语言

标记语言

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

yaml配置:

server:
	port: 8080

xml配置:

<server>
    	<port>8081<port>
</server>

YAML语法

基本语法

k:(空格) v

以此来表示一对键值对(空格不能省略) ;以空格的缩进来控制层级关系,只要是左边对齐的一-列数据都是同一个层级的。
注意:属性和值的大小写都是十分敏感的。例子:

server:
	port: 8081
	path: /hello

值的写法

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

k: v

字面量直接写在后面就可以,字符串默认不用加上双引号或者单引号;

“” 双引号,不会转义字符串里面的特殊字符,特殊字符会作为本身想表示的意思;

比如: name: “kang \n yuan” 输出: kang 换行 yuan

# k=v
# 对空格的要求十分严格
# 普通的key-value

# 可以注入到配置类中
name: deemo

# 对象
student:
  name: deemo
  age: 21

#行内写法
student1: {
   name: deemo, age: 21}

# 数组
pets:
  - cat
  - dog
  - pig

pets1: [cat,dog,pig]

@ConfigurationProperties(prefix = “yaml配置中的对象”)

把这个注解加在类上,prefix中写yaml中对应的key,就可以为POJO赋值,注意,k-v和POJO中的字段要一一对应

举一反三

我们可以写一个Mybatis的配置类,然后把配置信息写在yaml配置文件中,加上@ConfigurationProperties注解为Mybatis配置类注入值

如果非要用properties呢?

注意:此时必须是UTF-8

用@PropertiesSource(value=“classpath:xxx.properties”)注解,然后在字段上用@Value注解,写SPEL表达式去除配置文件的值就可以

一点骚操作

image-20200518203737813

松散绑定

image-20200518204539986

结论

  • 配置yml和配置properties都可以获取到值,强烈推荐 yml

  • 如果我们在某个业务中,只需要获取配置文件中的某个值,可以使用一下@value

  • 如果说,我们专门编写了-个JavaBean来和配置文件进行映射,

    就直接使用@configurationProperties,不要犹豫!

JSR303校验

在类上加上@Validated注解开启数据校验

image-20200518205100431

配置文件位置优先级

image-20200518211729626

强制:必须以前缀为application为开头

在生产环境中,我们可以在不同位置进行配置,然后达到覆盖的效果

第一种方式.指定properties配置文件:

image-20200518212503203

image-20200518212616081

第二种方式:yaml配置文件:

image-20200518212925477

为什么可以完成自动配置

在我们这配置文件中能配置的东西,都存在一个固有的规律

xxxAutoConfiguration:默认值 <—注入----- xxxProperties -----绑定— 配置文件

精髓

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

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

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

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

    xxxxAutoConfigurartion: 自动配置类; 给容器中添加组件
    xxxxProperties: 封装配置文件中相关属性;

查看哪些配置类生效

debug: true

如果配置了log4j之类的,设置log的level为debug,也可以看到

自动配置了并且生效的

image-20200519151115420

大量的没有生效的

image-20200519151158381

没有条件所以没生效的

image-20200519151244998

SpringBoot Web开发

要解决的问题:

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

静态资源

public void addResourceHandlers(ResourceHandlerRegistry registry) {
   
    //第一种方式,webjars
    if (!this.resourceProperties.isAddMappings()) {
   
        logger.debug("Default resource handling disabled");
    } else {
   
        Duration cachePeriod = this.resourceProperties.getCache().getPeriod();
        CacheControl cacheControl = this.resourceProperties.getCache()
            .getCachecontrol().toHttpCacheControl();
        if (!registry.hasMappingForPattern("/webjars/**")) {
   
            this.customizeResourceHandlerRegistration(registry.addResourceHandler(new String[]{
   "/webjars/**"}).addResourceLocations(new String[]{
   "classpath:/META-INF/resources/webjars/"}).setCachePeriod(this.getSeconds(cachePeriod)).setCacheControl(cacheControl));
        }
		
        //第二种方式,某路径下的静态资源
        String staticPathPattern = this.mvcProperties.getStaticPathPattern();
        if (!registry.hasMappingForPattern(staticPathPattern)) {
   
            this.customizeResourceHandlerRegistration(
                registry.addResourceHandler(new String[]{
   staticPathPattern})
.addResourceLocations(
    WebMvcAutoConfiguration.getResourceLocations(
        this.resourceProperties.getStaticLocations()))
                .setCachePeriod(this.getSeconds(cachePeriod))
                .setCacheControl(cacheControl));
        }
    }
}

什么是webjars?

给静态资源的一层封装,比如jquery,以maven的方式引入的话,会给他包上一层webjars封装

image-20200519161822815

如上述代码 “/webjars/**” 对应的是 “classpath:/META-INF/resources/webjars/” 直接输入/webjars/jquery/3.5.1/jquery.js就可以访问到js文件了

静态资源目录

优先级即为,他们的位置关系 /META-INF/resources/ 优先级最高,最低的是classpath:/public/

private static final String[] CLASSPATH_RESOURCE_LOCATIONS = new String[]{
   "classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/"};

总结

  1. 在springboot中,我们可以使用以下方式处理静态资源

    • webjars localhost:8080/webjars/
    • public, static, /**, resources localhost:8080/
  2. 优先级: resources > static(默认) > public

首页如何定制

    @Bean
    public WelcomePageHandlerMapping welcomePageHandlerMapping(ApplicationContext applicationContext, FormattingConversionService mvcConversionService, ResourceUrlProvider mvcResourceUrlProvider) {
   
        WelcomePageHandlerMapping welcomePageHandlerMapping = new WelcomePageHandlerMapping(new TemplateAvailabilityProviders(applicationContext), applicationContext, this.getWelcomePage(), this.mvcProperties.getStaticPathPattern());
        welcomePageHandlerMapping.setInterceptors(this.getInterceptors(mvcConversionService, mvcResourceUrlProvider));
        welcomePageHandlerMapping.setCorsConfigurations(this.getCorsConfigurations());
        return welcomePageHandlerMapping;
    }

    private Optional<Resource> getWelcomePage() {
   
        String[] locations = WebMvcAutoConfiguration.getResourceLocations(this.resourceProperties.
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值