SpringBoot 详解

一、进入微服务阶段

javase :OOP

mysql : 持久化

html+css+js+jquery+框架 :视图,框架不熟练,css不好

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

ssm:框架:简化了我们的开发流程,配置也开始较为复杂

war包:Tomcat运行

微服务阶段:

spring再简化:SpringBoot ,jar‘包:内嵌tomcat; 微服务架构

服务越来越多:springcloud

二、什么是SpringBoot

  1. 什么是Spring

Spring是一个开源框架,Spirng是为了解决企业级应用开发的复杂性而创建的,简化开发。

  1. Spring是如何简化Java开发的

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

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

SpringBoot ,就是一个javaweb的开发框架,简化开发,约定大于配置,能迅速的开发web应用。

随着Spring不断的发展,涉及的领域越来越多,项目整合开发需要配合各种各样的文件,慢慢变得不那么易用简单,人称配置地域。Spring Boot 正是在这样的一个背景下被抽象出来的开发框架,目的为了让大家更容易的使用Spring、更容易集成各种常用的中间件、开源软件;

Spring Boot 基于Spring开发,SpringBoot 本身并不提供Spring框架的核心特性以及扩展功能,只是用于快速、敏捷的开发新一代基于Spring框架的应用程序,也就是说,它并不是用来替代Spring的解决方案,而是和Spring框架紧密结合用于提升Spring开发体验的工具。

Spring Boot的主要优点:

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

三、什么是微服务架构

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

是指,我们将一个应用中的所有应用服务都封装在一个应用中

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

所谓微服务架构,就是打破之前all in one的架构方式,把每个功能元素独立出来,把独立出来的功能元素动态组合,需要的功能元素才去拿来组合,需要多一些时可以整合多个功能元素。所以微服务架构是对功能元素进行复制,而没有对整个应用进行复制。

这样做的好处是:

  • 节省了调用资源
  • 每个功能元素的服务都是一个可替换的、可独立升级的软件代码
  1. 如何搭建微服务

这种庞大的系统架构给部署和运维带来很大的难度,于是Spring为我们带来了构建大型分布式微服务的全套、全程产品:

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

四、学习SpringBoot

1)第一个SpringBoot程序

  1. 环境:
  • jdk1.8
  • maven3.6.1
  • springboot :最新版
  • IDEA
  1. 创建
  • 可以在官网直接下载后,导入idea开发
  • 直接使用idea创建一个springboot项目(一般开发直接在idea中创建)
  1. 核心文件
  • application
package com.example.springboot01;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
//本身就是spring的一个组件
//程序的主入口
@SpringBootApplication
public class Springboot01Application {public static void main(String[] args) {SpringApplication.run(Springboot01Application.class, args);}}
  • properties

是springboot的核心配置文件

  • ApplicationTest
package com.example.springboot01;import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;//单元测试
@SpringBootTest
class Springboot01ApplicationTests {@Testvoid contextLoads() {}}
  • pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.7.2</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.example</groupId><artifactId>springboot-01</artifactId><version>0.0.1-SNAPSHOT</version><name>springboot-01</name><description>springboot-01</description><properties><java.version>1.8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies><build>
<!--        打包插件--><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

parent:继承spring-boot-starter-parent的依赖管理,控制版本与打包等内容

dependencies:项目具体依赖 spring-boot-starter-web 用于实现HTTP接口,该依赖中包含了springMVC,即“使用SpringMVC构建WEB应用程序,使用Tomcat作为默认嵌入式容器”

  1. 编写Http接口
  • 在于Application同级目录下创建controller层、dao层、pojo层、service层
  • 写HelloController.java
package com.example.springboot01.controller;import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;//自动装配
@RestController
public class HelloController {//接口:http://localhost:8080/hello@RequestMapping("/hello")public String hello(){//调用业务,接收前端的参数!return "hello,World";}
}
  • 启动测试
  1. 修改端口号

在配置文件中application.properties

server.port=8081

即可修改当前程序端口号

  1. 修改banner ,就是运行程序下面弹出来的图片
  • 网上搜修改springboot banner的网站
  • 拿到自己想要的图片对应的ascii码
  • 在resource文件夹下创建banner.txt,将其复制进去,重启,即可看到banner变成了自己喜欢的

2)原理初探

自动配置

  1. pom.xml
  • 继承spring-boot-starter-parent,而spring-boot-starter-parent又继承spring-boot-dependencies,spring-boot-dependencies是核心依赖
  • 我们在写或者引入一些springbboot依赖的时候不需要指定版本号,因为有这些版本仓库
  • 启动器
 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency>
  • 启动器:说白了就是springboot的启动场景
  • 比如spring-boot-starter-web,它会自动导入web环境所有的依赖
  • springboot会将所有的功能场景,都变成一个个的启动器
  • 我们要使用说明功能,就只需要找到对应的启动器就行 starter
  1. 主程序
  • @SpringBootApplication:标注这个类是一个springboot的应用:启动类下的所有资源被导入

  • 点进去@SpringBootApplication:

    • @SpringBootConfiguration:springboot的配置:

      • @configuration:是spring的一个配置---->@component :说明这也是spring的一个组件
    • @EnableAutoConfiguration:自动导入包

      • @AutoConfigurationPackage:自动配置包,>@Import({AutoConfigurationPackages.Registrar.class}):导入选择器:自动配置‘包注册’

      • @Import({AutoConfigurationImportSelector.class}):导入选择器:自动配置选择器

      • protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {List<String> configurations = new ArrayList(SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader()));ImportCandidates.load(AutoConfiguration.class, this.getBeanClassLoader()).forEach(configurations::add);Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories nor in META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports. If you are using a custom packaging, make sure that file is correct.");return configurations;}
        //获取候选的配置
        
    • @ComponentScan :扫描当前主启动类同级的包

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

  1. 过程:
  • springboot在启动的时候,从类路径下\META-INF\spring.factories获取指定的值
  • 将这些自动配置的类导入容器,自动配置就会生效,帮我们进行自动配置
  • 以前我们需要自动配置的东西,现在springboot帮我们做了
  • 整合javaee,解决方案和自动配置的东西都在\spring-boot-autoconfigure\2.7.2\spring-boot-autoconfigure-2.7.2.jar这个包下
  • 它会把所有需要导入的组件,以类名的方式返回,这些组件就会被添加到容器
  • 容器中也会存在非常多的xxxAutoConfiguration的文件(@Bean),就是这些类个容器中导入了这个场景需要的所有组件;并自动配置,@Configuration -----JavaConfig
  • 有了自动配置;类,免去了我们手动编写配置文件的工作!

3)了解主启动类怎么运行

 public static void main(String[] args) {SpringApplication.run(Springboot01Application.class, args);}}
  • 该方法返回一个ConfigurableApplicationContext对象
  1. SpringApplication.run
  • SpringApplication的实例化

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

1)推断应用的类型是普通的项目还是Web项目

2)查找并加载所有可用初始化器,设置到initializers属性中

3)找出所有的应用程序监听器,设置到listeners属性中

4)推断并设置main方法的定义类,找到运行的主类

  • run()方法

4)yaml语法讲解

ps:创建springboot项目时,url报错,解决方案:

  • 改成阿里云镜像:https://start.aliyun.com/ (推荐好用)
  • 降springboot版本
  1. 配置文件

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

  • application.properties

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

    • 语法结构: key:空格 value
  • 配置文件的作用:修改SpringBoot自动配置的默认值,因为SpringBoot在底层都给我们自动配置好了

  1. YAML
  • 标记语言

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

xml:

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

yaml:

server:port: 8080
  1. YAML语法
  • key:空格 value (一定要有空格)
  • 对象

基础语法

server:port: 8081
#对空格的要求很严格# 对象student:name: xqhage: 3# 行内写法person: {name:xqh,age:3}#数组pets:- cat- dog- pigpets1: [cat,dog,pig]

5)给属性赋值的几种方法

  • 通过@Value

实体类Dog.java

package com.example.pojo;import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;//成为spring的组件
@Component
public class Dog {@Value("旺财")private String name;@Value("3")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;}@Overridepublic String toString() {return "Dog{" +"name='" + name + '\'' +", age=" + age +'}';}
}

测试类

package com.example;import com.example.pojo.Dog;
import com.example.pojo.Person;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;@SpringBootTest
class Springboot02ApplicationTests {@Autowiredprivate Dog dog;@Testvoid contextLoads() {System.out.println(dog);}}

//输出结果:Dog{name=‘旺财’, age=3}

  • 通过配置文件.yml

实体类Person.java

package com.example.pojo;import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;import java.util.Date;
import java.util.List;
import java.util.Map;@Component  //注册bean
@ConfigurationProperties(prefix = "person")
//@ConfigurationProperties作用:
//将配置文件中的每一个属性的值,映射到这个组件中;告诉springboot将本类中的所有属性和配置文件中相关的配置进行绑定;
//参数prefix=“person” :将配置文件中的person下面的的所有属性一一对应
//只有这个组件是容器中的组件,才能使用@ConfigurationProperties,所以要先@Component,让它成为spring的组件
public class Person {private String name;private Integer age;private Boolean happy;private Date birth;private Map<String,Object>maps;private List<Object>lists;private Dog dog;public Person() {}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;}public Boolean getHappy() {return happy;}public void setHappy(Boolean happy) {this.happy = happy;}public Date getBirth() {return birth;}public void setBirth(Date birth) {this.birth = birth;}public Map<String, Object> getMaps() {return maps;}public void setMaps(Map<String, Object> maps) {this.maps = maps;}public List<Object> getLists() {return lists;}public void setLists(List<Object> lists) {this.lists = lists;}public Dog getDog() {return dog;}public void setDog(Dog dog) {this.dog = dog;}@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", age=" + age +", happy=" + happy +", birth=" + birth +", maps=" + maps +", lists=" + lists +", dog=" + dog +'}';}
}

配置文件 application.yml

person:name: qinjiangage: 3happy: falsebirth: 2019/11/2maps: {k1: v1,k2: v2}lists:- code- music- girldog:name: 旺财age: 3

测试:

package com.example;import com.example.pojo.Dog;
import com.example.pojo.Person;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;@SpringBootTest
class Springboot02ApplicationTests {@Autowiredprivate Person person;@Testvoid contextLoads() {System.out.println(person);}}

//结果:Person{name=‘qinjiang’, age=3, happy=false, birth=Sat Nov 02 00:00:00 CST 2019, maps={k1=v1, k2=v2}, lists=[code, music, girl], dog=Dog{name=‘旺财’, age=3}}

  • 通过配置文件.properties

实体类Person.java

package com.example.pojo;import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;import java.util.Date;
import java.util.List;
import java.util.Map;@Component  //注册bean
//加载指定的配置文件
@PropertySource(value = "classpath:person.properties")
public class Person {@Value("${name}")private String name;private Integer age;private Boolean happy;private Date birth;private Map<String,Object>maps;private List<Object>lists;private Dog dog;public Person() {}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;}public Boolean getHappy() {return happy;}public void setHappy(Boolean happy) {this.happy = happy;}public Date getBirth() {return birth;}public void setBirth(Date birth) {this.birth = birth;}public Map<String, Object> getMaps() {return maps;}public void setMaps(Map<String, Object> maps) {this.maps = maps;}public List<Object> getLists() {return lists;}public void setLists(List<Object> lists) {this.lists = lists;}public Dog getDog() {return dog;}public void setDog(Dog dog) {this.dog = dog;}@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", age=" + age +", happy=" + happy +", birth=" + birth +", maps=" + maps +", lists=" + lists +", dog=" + dog +'}';}
}

配置文件.properties

name=xqh

测试

package com.example;import com.example.pojo.Dog;
import com.example.pojo.Person;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;@SpringBootTest
class Springboot02ApplicationTests {@Autowiredprivate Person person;@Testvoid contextLoads() {System.out.println(person);}}
  • 推荐使用yaml配置文件来给属性赋值,更方便。
  1. @ConfigurationProperties 和 @Value 对比
  • 前者支持批量注入配置文件的属性,而后者只能一个一个指定
  • 前者支持松散绑定,后者不支持

松散绑定:即便是实体类中属性名为firstName,而配置文件中写的first-name,一样可以进行绑定

  • 前者支持JSR303数据校验,后者不支持

  • 前者支持复杂类型封装,后者不支持。如yaml中可以封装对象,而@value就不行

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

6)JSR303数据校验

JSR303数据校验:我们可以在字段增加一层过滤器验证,可以保证数据的合法性

@Validated //数据校验
public class Person {@Email(message="邮箱格式错误")  //这样后,如果配置文件中对应的属性赋值不是email的话,就会报错private String name;

常用校验注解:

1、空检查

Constraint 详细信息
@Null 验证对象是否为null
@NotNull 验证对象是否不为null,无法检查长度为0的字符串
@NotBlank 检查约束字符串是不是NULL还有被Trim的长度是否大于0,只对字符串,且会去掉前后空格。
@NotEmpty 检查约束元素是否为NULL或者EMPTY.

2、Boolean检查

Constraint 详细信息
@AssertTrue 验证 Boolean 对象是否为 true
@AssertFalse 验证 Boolean 对象是否为 false

3、长度检查

Constraint 详细信息
@Size(min=,max=) 验证对象(Array,Collection,Map,String) 长度是否在给定方位之内
@Length(min=,max=) Validates that the annotated string is between min and max included.

4、日期检查

Constraint 详细信息
@Past 验证 Date 和 Calendar 对象是否在当前时间之前
@Future 验证 Date 和 Calendar 对象是否在当前时间之后
@Pattern 验证 String 对象是否符号正则表达式的规则 : 正则表达式

7)多环境配置及配置文件位置

  1. 配置文件位置:
  • 项目根目录下建config文件夹(与src同级),在config文件夹内写配置文件
  • 在项目根目录下直接写配置文件
  • 在resource文件夹下建config文件夹,再在config文件夹下写配置文件
  • 直接在resource文件夹里写配置文件(一创建好springboot项目的默认配置文件位置)
  1. 不同配置文件位置的优先级:

项目下config文件夹内的配置文件 > 项目下的配置文件 > resource文件夹下的config文件夹内的配置文件 >resource文件夹下的配置文件

  1. 多环境配置
  • 可以选择激活哪一个配置文件

第一种方法分开文件写

真实开发环境中,比如有application.yml , application-dev.yml , application-test.yml三个不同环境下的配置文件

application.yml

spring.profiles.active: dev

即可切换到使用application-dev.yml配置文件

第二种方法,在一个文件中写(因为yaml可以模块化配置)

application.yml

server:port: 8080
spring:profiles:active: dev---
server:port: 8082
spring:profiles: dev---
server:port: 8081
spring:profiles: test

用—分隔开不同环境下

8)自动配置原理再理解

配置文件到底能写什么-----联系------spring.factories(在spring-boot-autoconfigure\2.3.7.RELEASE\spring-boot-autoconfigure-2.3.7.RELEASE.jar!\META-INF\spring.factories)

  1. 点开spring.factories,比如在spring.factories中的一条配置代码,org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration,点开HttpEncodingAutoConfiguration
  2. HttpEncodingAutoConfiguration
//表示这是一个配置类
@Configuration(proxyBeanMethods = false
)
//自动装配属性:ServerProperties
@EnableConfigurationProperties({ServerProperties.class})//spring的底层注解:根据不同的条件,来判断当前配置或者类是否生效
@ConditionalOnWebApplication(type = Type.SERVLET
)//是不是这个类型
@ConditionalOnClass({CharacterEncodingFilter.class}) //是否存在这个字符编码过滤器
@ConditionalOnProperty(prefix = "server.servlet.encoding",value = {"enabled"},matchIfMissing = true
)//是否存在这些配置
  1. 点进ServerProperties
@ConfigurationProperties(
//配置前缀是serverprefix = "server",ignoreUnknownFields = true)public class ServerProperties {//这些属性就是配置文件中能配置的属性private Integer port;private InetAddress address;@NestedConfigurationPropertyprivate final ErrorProperties error = new ErrorProperties();private ForwardHeadersStrategy forwardHeadersStrategy;private String serverHeader;private DataSize maxHttpHeaderSize = DataSize.ofKilobytes(8L);private Shutdown shutdown;@NestedConfigurationPropertyprivate Ssl ssl;@NestedConfigurationPropertyprivate final Compression compression;@NestedConfigurationPropertyprivate final Http2 http2;private final Servlet servlet;private final Tomcat tomcat;private final Jetty jetty;private final Netty netty;private final Undertow undertow;
...
  1. 对应着application.yml中能够配置的东西,对应着server前缀下的能配置的所有属性
server:port:server-header:address:forward-headers-strategy: ...
  1. @Conditional扩展注解

作用:判断是否满足当前指定条件,后缀不同对应着不同条件

  1. 在我们这配置文件中能配置的东西,都存在一个固有规律,对应着 xxxAutoConfiguration中的xxxProperties中的属性,配置文件绑定。

  2. 自动装配原理再总结

  • SpringBoot启动会加载大量的自动装配类
  • 我们看我们需要的功能有没有在SpringBoot默认写好的自动配置类当中(spring.factories)
  • 我们再来看springboot写好的这个自动配置类到底配置了哪些组件(xxxAutoConfiguration中)(只要我们要用的组件存在其中,我们就不需要再手动配置了)
  • 给容器中自动配置类添加组件的时候,会从properties类中获取某些属性,我们只需要在配置文件中指定这些属性的值即可

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

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

  1. 查看哪些配置属性生效,通过debug: true
debug: true

五、SpringBoot Web开发

1)web开发探究

jar:webapp

自动装配

要解决的问题:

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

2)静态资源导入

  1. 分析源码 WebMvcAutoConfiguration.class 里面
public void addResourceHandlers(ResourceHandlerRegistry registry) {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,通过maven导入,在classpath:/META-INF/resources/webjars/可以找到
  • staticPathPattern

在resources下建文件夹public、static、resource,springboot会自动扫描这些文件内的静态资源,且优先级是:

resources>static>public

  • if (!this.resourceProperties.isAddMappings()) {

​ logger.debug(“Default resource handling disabled”);意思是如果自己在配置文件中配置了静态资源路径,那么前面的默认的配置就不生效

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

    • webjars localhost:8080/webjars/
    • public , static , resources , /** localhost:8080/
  • 优先级:

resources>static(默认)>public

3)首页如何定制

  1. 相关源码
@Beanpublic 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.getStaticLocations());return Arrays.stream(locations).map(this::getIndexHtml).filter(this::isReadable).findFirst();}private Resource getIndexHtml(String location) {return this.resourceLoader.getResource(location + "index.html");}

springboot会自动识别resource下的index.html,并把它设置为首页

4)thymeleaf模板引擎

  1. springboot这个项目以jar的方式,默认是不支持jsp的,不支持jsp,如果我们直接用静态页面的方式,那给我们开发会带来非常大的麻烦,所以SpringBoot推荐使用模板引擎

  2. jsp其实就是一个模板引擎,还有用的比较多的freemarker,包括springboot给我们推荐的Thymeleaf

  3. 导入依赖

    <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId><version>2.2.1.RELEASE</version></dependency>
  1. 将html页面放在我们的templates文件夹下,就可以实现直接跳转。
package com.example.controller;import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;//在templates目录下的所有页面,只能通过controller来跳转
@Controller
public class IndexController {@RequestMapping("/test")public String test(){return "test";}
}

test.html在templates下

<!doctype html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport"content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title>
</head>
<body>
<h1>test</h1>
</body>
</html>

测试,可以跳转到test页面

  1. 编写thymeleaf页面
  • 加入标签 xmlns:th="http://www.w3.org/1999/xhtml“

  • <!doctype html>
    <html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
    <head><meta charset="UTF-8"><meta name="viewport"content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title>
    </head>
    <body>
    <!--所有的html元素都可以被thymeleaf替换接管: th:元素名-->
    <div th:text="${msg}"></div>
    </body>
    </html>
    
  • 取文本内容

package com.example.controller;import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;//在templates目录下的所有页面,只能通过controller来跳转
@Controller
public class IndexController {@RequestMapping("/test")public String test(Model model){model.addAttribute("msg","hello,springboot");return "test";}
}

这样就可以取到了!

  1. thymeleaf 常用语法

常用标签

标签 作用 示例
th:text 替换文本 th:text="${title}"
th:value 替换值 th:value="${user.name}"
th:each 迭代 th:each="stu:${user}"
th:href 替换链接 th:href="@{/index.html}"
th:src 替换资源 th:src="@{/img/Wechat.jpg}"
th:if 条件判断 th:if="${isVip}"
th:switch th:case 条件判断 th:switch="${sex}" th:case="'man'"
th:insert 插入 th:insert="footer :: copy"
th:replace 替换 th:replace="footer :: copy"
th:fragment 定义片段 th:fragment="frag (onevar,twovar)"
  • th:test 和th:utext
<body>
<!--所有的html元素都可以被thymeleaf替换接管: th:元素名-->
<!--字符串的形式取到-->
<div th:text="${msg}"></div>
<!--把<h1>转义出来,即标题内容-->
<div th:utext="${msg}"></div>
</body>
  • 遍历 th:each

后端输入数据

  model.addAttribute("users", Arrays.asList("java","python"));

页面中获取数据

<!--<h3 th:each="user:${users}" th:text="${user}"></h3>-->
<!--行内来写,类似vue-->
<h3 th:each="user:${users}" >[[${user}]]</h3>

推荐使用第一种

5)SpringMVC自动配置原理 和 扩展

  1. MVC自动配置原理(举例扩展视图解析器)
package com.example.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.View;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;import java.util.Locale;
//如果你想diy一些定制化的功能,只要写这个组件,然后将它交给springboot,springboot就会帮我们自动装配
//写组件(@Configuration),自定义(继承这个功能的接口类)---->注入到springboot(@Bean) ---->springboot会帮我们自动装配
//扩展mvc
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {// public interface ViewResolver 实现了视图解析器接口的类,我们就可以把它看做视图解析器(现在默认是springboot自动装配的)@Beanpublic ViewResolver myViewResolver(){return new MyViewResolver();}//自定义一个自己的视图解析器MyViewResolverpublic static class MyViewResolver implements ViewResolver{@Overridepublic View resolveViewName(String s, Locale locale) throws Exception {return null;}}
}
  • SpringBoot在自动配置很多组件的时候,先看容器中有没有用户自己配置的(用户自己配置@Bean),如果有就用用户配置的,如果没有就用自动配置的;如果有些组件可以存在多个,比如我们的视图解析器,就将用户配置的和自己默认的组合起来!
  1. 扩展SpringMvc
package com.example.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;//如果我们要扩展springmvc,官方建议我们这样去做,@Configuration成为组件,然后继承类,然后重写方法
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {//视图跳转//实现重命名,从/view也可以跳转到test@Overridepublic void addViewControllers(ViewControllerRegistry registry) {registry.addViewController("/view").setViewName("test");}
}
  • 在SpringBoot中,有非常多的xxx Configuration帮助我们进行扩展配置,只要看见了这个东西,我们就要注意了!

SpringBoot详解(一)相关推荐

  1. 十二、springboot 详解RestControllerAdvice(ControllerAdvice)

    springboot 详解RestControllerAdvice(ControllerAdvice)拦截异常并统一处理 简介 @Target({ElementType.TYPE}) @Retenti ...

  2. springboot 详解 (四)redis filter

    ---------------------------------------------------------------------------------------------------- ...

  3. SpringBoot详解(一)-快速入门

    SpringBoot详解系列文章: SpringBoot详解(一)-快速入门 SpringBoot详解(二)-Spring Boot的核心 SpringBoot详解(三)-Spring Boot的we ...

  4. SpringBoot详解(四)-优雅地处理日志

    SpringBoot详解系列文章: SpringBoot详解(一)-快速入门 SpringBoot详解(二)-Spring Boot的核心 SpringBoot详解(三)-Spring Boot的we ...

  5. SpringBoot详解

    1.回顾Spring 1.优点 开源,轻量级,非侵入式的一站式框架,简化企业级应用开发. 控制反转(IOC),依赖注入(DI)降低了组件之间的耦合性,实现了软件各层之间的解耦. 面向切面(AOP),利 ...

  6. Springboot是什么?Springboot详解!入门介绍

    Spring Boot概述 Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化Spring应用的创建.运行.调试.部署等.使用Spring Boot可以做到专注于Spri ...

  7. boot入门思想 spring_微服务架构之SpringBoot详解,夯实底层知识,带你轻松入门开发...

    对于Spring,相信大家都非常熟悉,从出现开始,一直是企业级开发的主流.但是随着软件的发展和应用开发的不断演化,它的一些缺点也逐渐暴露了出来.下面看一下Spring的发展历程并且认识一下Spring ...

  8. SpringBoot 详解

    Spring Boot 0. 概述 简介 Spring Boot 基于 Spring 开发,本身并不提供 Spring 框架的核心特性以及扩展功能,只是用于快速.敏捷地开发新一代基于 Spring 框 ...

  9. SpringBoot第十篇:thymeleaf详解

    作者:追梦1819 原文:https://www.cnblogs.com/yanfei1819/p/10931435.html 版权声明:本文为博主原创文章,转载请附上博文链接! 引言   Sprin ...

最新文章

  1. 运维工程师必备之负载 均衡集群及LVS详解
  2. ORACLE 错误:oralce record is locked by another user
  3. PDF密码去除常用工具
  4. 问题 L: 超超的中等意思
  5. 【英语学习】【Level 08】U01 Let's Read L4 Hot off the press
  6. 用ASP.Net写一个发送ICQ信息的程序
  7. 第 20 次 CSP认证 202009-4 星际旅行
  8. mysql安装方法及使用
  9. AP注册不上线(现网中存在其它厂商的控制器)
  10. IntelliJ IDEA 字体配置常用快捷键
  11. seo模拟点击软件_百度搜索SEO优化算法揭秘
  12. 基于Zynq的光流法软硬件协同实现
  13. 职称计算机 2007 还是2003,职称计算机考试, PPT2003和2007 区别大吗?哪个版本更容易。...
  14. 关于SQLServer关键词“union all”与“order by”的矛盾
  15. idea怎样创建jsp文件
  16. 上交计算机考研分数线2018,2018上交考研经验贴
  17. 自定义UI 简易图文混排
  18. SE14造成表丢失后找回数据
  19. 阿里云ECS服务器安装docker教程(超详细图文教程)
  20. 树莓派4B安装历程(小白)

热门文章

  1. HDFS物理块存储大小
  2. 三菱DPLSR无故不执行问题
  3. android 图片字体涂鸦,android 涂鸦功能
  4. Android入门第9天-Android读本地JSON文件并显示
  5. UR机器人数据包解析(python与C++实现)
  6. PDF修改目录和跳转
  7. 12 聚类模型 -- 机器学习基础理论入门
  8. CCF201712-4 行车路线(最短路)
  9. 我的世界java无法连接服务器_java - 无法连接到Minecraft服务器 - SO中文参考 - www.soinside.com...
  10. U盘和存储卡实际上可以轻松的创建隐藏分区制作PE启动盘