SpringBoot详解(一)
SpringBoot 详解
一、进入微服务阶段
javase :OOP
mysql : 持久化
html+css+js+jquery+框架 :视图,框架不熟练,css不好
javaweb:独立开发MVC三层架构的网站:原始
ssm:框架:简化了我们的开发流程,配置也开始较为复杂
war包:Tomcat运行
微服务阶段:
spring再简化:SpringBoot ,jar‘包:内嵌tomcat; 微服务架构
服务越来越多:springcloud
二、什么是SpringBoot
- 什么是Spring
Spring是一个开源框架,Spirng是为了解决企业级应用开发的复杂性而创建的,简化开发。
- Spring是如何简化Java开发的
为了降低Java开发的复杂性,Spring采用了以下4种关键策略:
- 基于POJO的轻量级和最小侵入性编程
- 通过IOC,依赖注入(DI)和面向接口实现松耦合
- 基于切面(AOP)和惯例进行声明式编程
- 通过切面和模板减少样式代码
- 什么是SpringBoot
SpringBoot ,就是一个javaweb的开发框架,简化开发,约定大于配置,能迅速的开发web应用。
随着Spring不断的发展,涉及的领域越来越多,项目整合开发需要配合各种各样的文件,慢慢变得不那么易用简单,人称配置地域。Spring Boot 正是在这样的一个背景下被抽象出来的开发框架,目的为了让大家更容易的使用Spring、更容易集成各种常用的中间件、开源软件;
Spring Boot 基于Spring开发,SpringBoot 本身并不提供Spring框架的核心特性以及扩展功能,只是用于快速、敏捷的开发新一代基于Spring框架的应用程序,也就是说,它并不是用来替代Spring的解决方案,而是和Spring框架紧密结合用于提升Spring开发体验的工具。
Spring Boot的主要优点:
- 为所有Spring开发者更快的入门
- 开箱即用 ,提供各种默认配置来简化项目配置
- 内嵌式容器简化Web项目
- 没有冗余代码生成和XML配置的要求
三、什么是微服务架构
- 微服务是一种架构风格 ,它要求我们在开发一个应用的时候,这个应用必须构建成一系列小服务的组合,可以通过http的方式进行互通。
- 单体应用架构
是指,我们将一个应用中的所有应用服务都封装在一个应用中
- 这样做的好处是,易于测试和开发;也十分方便部署;当需要扩展时,只需要将war复制多份,然后放到多个服务器上,再做个负载均衡就可以了
- 单体应用架构的缺点是,哪怕我要修改一个非常小的地方,我都需要停掉整个服务,重新打包、部署这个应用war包。特别是对于一个大型应用,我们不可能把所有内容都放在一个应用里面,我们如何维护、如何分工合作都是问题
- 微服务架构
所谓微服务架构,就是打破之前all in one的架构方式,把每个功能元素独立出来,把独立出来的功能元素动态组合,需要的功能元素才去拿来组合,需要多一些时可以整合多个功能元素。所以微服务架构是对功能元素进行复制,而没有对整个应用进行复制。
这样做的好处是:
- 节省了调用资源
- 每个功能元素的服务都是一个可替换的、可独立升级的软件代码
- 如何搭建微服务
这种庞大的系统架构给部署和运维带来很大的难度,于是Spring为我们带来了构建大型分布式微服务的全套、全程产品:
- 构建一个个独立的微服务应用单元,可以使用springboot,可以帮我们快速构建一个应用
- 大型分布式网络服务的调用,这部分由spring cloud 来完成,实现分布式
- 在分布式中间,进行流式数据计算、批处理 ,我们有spring cloud data flow
- spring 为我们想清楚了整个从开始构建应用到大型分布式应用全流程方案
四、学习SpringBoot
1)第一个SpringBoot程序
- 环境:
- jdk1.8
- maven3.6.1
- springboot :最新版
- IDEA
- 创建
- 可以在官网直接下载后,导入idea开发
- 直接使用idea创建一个springboot项目(一般开发直接在idea中创建)
- 核心文件
- 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作为默认嵌入式容器”
- 编写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";}
}
- 启动测试
- 修改端口号
在配置文件中application.properties
server.port=8081
即可修改当前程序端口号
- 修改banner ,就是运行程序下面弹出来的图片
- 网上搜修改springboot banner的网站
- 拿到自己想要的图片对应的ascii码
- 在resource文件夹下创建banner.txt,将其复制进去,重启,即可看到banner变成了自己喜欢的
2)原理初探
自动配置
- 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
- 主程序
@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,有对应的启动器,我们的自动装配才会生效,然后才配置成功。
- 过程:
- 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对象
- SpringApplication.run
- SpringApplication的实例化
这个类主要做了以下四件事
1)推断应用的类型是普通的项目还是Web项目
2)查找并加载所有可用初始化器,设置到initializers属性中
3)找出所有的应用程序监听器,设置到listeners属性中
4)推断并设置main方法的定义类,找到运行的主类
- run()方法
4)yaml语法讲解
ps:创建springboot项目时,url报错,解决方案:
- 改成阿里云镜像:https://start.aliyun.com/ (推荐好用)
- 降springboot版本
- 配置文件
Springboot使用一个全局的配置文件,配置文件名称是固定的
application.properties
- 语法结构: key=value
application.yml
- 语法结构: key:空格 value
配置文件的作用:修改SpringBoot自动配置的默认值,因为SpringBoot在底层都给我们自动配置好了
- YAML
- 标记语言
以前的配置文件,大多数都是使用xml来配置,比如一个简单的端口配置,对比xml和yaml
xml:
<server><port>8081</port>
</server>
yaml:
server:port: 8080
- 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配置文件来给属性赋值,更方便。
- @ConfigurationProperties 和 @Value 对比
- 前者支持批量注入配置文件的属性,而后者只能一个一个指定
- 前者支持松散绑定,后者不支持
松散绑定:即便是实体类中属性名为firstName,而配置文件中写的first-name,一样可以进行绑定
前者支持JSR303数据校验,后者不支持
前者支持复杂类型封装,后者不支持。如yaml中可以封装对象,而@value就不行
- 结论:
- 配置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)多环境配置及配置文件位置
- 配置文件位置:
- 项目根目录下建config文件夹(与src同级),在config文件夹内写配置文件
- 在项目根目录下直接写配置文件
- 在resource文件夹下建config文件夹,再在config文件夹下写配置文件
- 直接在resource文件夹里写配置文件(一创建好springboot项目的默认配置文件位置)
- 不同配置文件位置的优先级:
项目下config文件夹内的配置文件 > 项目下的配置文件 > resource文件夹下的config文件夹内的配置文件 >resource文件夹下的配置文件
- 多环境配置
- 可以选择激活哪一个配置文件
第一种方法分开文件写
真实开发环境中,比如有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)
- 点开spring.factories,比如在spring.factories中的一条配置代码,org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration,点开HttpEncodingAutoConfiguration
- 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
)//是否存在这些配置
- 点进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;
...
- 对应着application.yml中能够配置的东西,对应着server前缀下的能配置的所有属性
server:port:server-header:address:forward-headers-strategy: ...
- @Conditional扩展注解
作用:判断是否满足当前指定条件,后缀不同对应着不同条件
在我们这配置文件中能配置的东西,都存在一个固有规律,对应着 xxxAutoConfiguration中的xxxProperties中的属性,配置文件绑定。
自动装配原理再总结
- SpringBoot启动会加载大量的自动装配类
- 我们看我们需要的功能有没有在SpringBoot默认写好的自动配置类当中(spring.factories)
- 我们再来看springboot写好的这个自动配置类到底配置了哪些组件(xxxAutoConfiguration中)(只要我们要用的组件存在其中,我们就不需要再手动配置了)
- 给容器中自动配置类添加组件的时候,会从properties类中获取某些属性,我们只需要在配置文件中指定这些属性的值即可
xxxAutoConfiguration:自动配置类;给容器中添加组件
xxxProperties:封装配置文件中相关属性
- 查看哪些配置属性生效,通过debug: true
debug: true
五、SpringBoot Web开发
1)web开发探究
jar:webapp
自动装配
要解决的问题:
- 导入静态资源
- 首页
- jsp,模板引擎 Thymeleaf
- 装配扩展SpringMVC
- 数据库增删改查
- 拦截器
- 国际化
2)静态资源导入
- 分析源码 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”);意思是如果自己在配置文件中配置了静态资源路径,那么前面的默认的配置就不生效
- 总结
在springboot,我们可以使用一下方式处理静态资源
- webjars localhost:8080/webjars/
- public , static , resources , /** localhost:8080/
优先级:
resources>static(默认)>public
3)首页如何定制
- 相关源码
@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模板引擎
springboot这个项目以jar的方式,默认是不支持jsp的,不支持jsp,如果我们直接用静态页面的方式,那给我们开发会带来非常大的麻烦,所以SpringBoot推荐使用模板引擎
jsp其实就是一个模板引擎,还有用的比较多的freemarker,包括springboot给我们推荐的Thymeleaf
导入依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId><version>2.2.1.RELEASE</version></dependency>
- 将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页面
- 编写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";}
}
这样就可以取到了!
- 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自动配置原理 和 扩展
- 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),如果有就用用户配置的,如果没有就用自动配置的;如果有些组件可以存在多个,比如我们的视图解析器,就将用户配置的和自己默认的组合起来!
- 扩展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详解(一)相关推荐
- 十二、springboot 详解RestControllerAdvice(ControllerAdvice)
springboot 详解RestControllerAdvice(ControllerAdvice)拦截异常并统一处理 简介 @Target({ElementType.TYPE}) @Retenti ...
- springboot 详解 (四)redis filter
---------------------------------------------------------------------------------------------------- ...
- SpringBoot详解(一)-快速入门
SpringBoot详解系列文章: SpringBoot详解(一)-快速入门 SpringBoot详解(二)-Spring Boot的核心 SpringBoot详解(三)-Spring Boot的we ...
- SpringBoot详解(四)-优雅地处理日志
SpringBoot详解系列文章: SpringBoot详解(一)-快速入门 SpringBoot详解(二)-Spring Boot的核心 SpringBoot详解(三)-Spring Boot的we ...
- SpringBoot详解
1.回顾Spring 1.优点 开源,轻量级,非侵入式的一站式框架,简化企业级应用开发. 控制反转(IOC),依赖注入(DI)降低了组件之间的耦合性,实现了软件各层之间的解耦. 面向切面(AOP),利 ...
- Springboot是什么?Springboot详解!入门介绍
Spring Boot概述 Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化Spring应用的创建.运行.调试.部署等.使用Spring Boot可以做到专注于Spri ...
- boot入门思想 spring_微服务架构之SpringBoot详解,夯实底层知识,带你轻松入门开发...
对于Spring,相信大家都非常熟悉,从出现开始,一直是企业级开发的主流.但是随着软件的发展和应用开发的不断演化,它的一些缺点也逐渐暴露了出来.下面看一下Spring的发展历程并且认识一下Spring ...
- SpringBoot 详解
Spring Boot 0. 概述 简介 Spring Boot 基于 Spring 开发,本身并不提供 Spring 框架的核心特性以及扩展功能,只是用于快速.敏捷地开发新一代基于 Spring 框 ...
- SpringBoot第十篇:thymeleaf详解
作者:追梦1819 原文:https://www.cnblogs.com/yanfei1819/p/10931435.html 版权声明:本文为博主原创文章,转载请附上博文链接! 引言 Sprin ...
最新文章
- 运维工程师必备之负载 均衡集群及LVS详解
- ORACLE 错误:oralce record is locked by another user
- PDF密码去除常用工具
- 问题 L: 超超的中等意思
- 【英语学习】【Level 08】U01 Let's Read L4 Hot off the press
- 用ASP.Net写一个发送ICQ信息的程序
- 第 20 次 CSP认证 202009-4 星际旅行
- mysql安装方法及使用
- AP注册不上线(现网中存在其它厂商的控制器)
- IntelliJ IDEA 字体配置常用快捷键
- seo模拟点击软件_百度搜索SEO优化算法揭秘
- 基于Zynq的光流法软硬件协同实现
- 职称计算机 2007 还是2003,职称计算机考试, PPT2003和2007 区别大吗?哪个版本更容易。...
- 关于SQLServer关键词“union all”与“order by”的矛盾
- idea怎样创建jsp文件
- 上交计算机考研分数线2018,2018上交考研经验贴
- 自定义UI 简易图文混排
- SE14造成表丢失后找回数据
- 阿里云ECS服务器安装docker教程(超详细图文教程)
- 树莓派4B安装历程(小白)
热门文章
- HDFS物理块存储大小
- 三菱DPLSR无故不执行问题
- android 图片字体涂鸦,android 涂鸦功能
- Android入门第9天-Android读本地JSON文件并显示
- UR机器人数据包解析(python与C++实现)
- PDF修改目录和跳转
- 12 聚类模型 -- 机器学习基础理论入门
- CCF201712-4 行车路线(最短路)
- 我的世界java无法连接服务器_java - 无法连接到Minecraft服务器 - SO中文参考 - www.soinside.com...
- U盘和存储卡实际上可以轻松的创建隐藏分区制作PE启动盘