SpringBoot笔记
一、SpringBoot入门
1、SpringBoot简介
简化spring应用的框架
整个Spring技术栈的大整合
j2ee开发的一站式解决方案
2、微服务
2014 马丁·福勒(martin fowler)
微服务: 架构风格
一个应用应该是一组小型微服务,可以通过HTTP的方式去进行访问
单体应用: ALL IN ONE
微服务:每一个功能元素最终都是一个独立运行或者升级的软件单元
3、 环境的准备
环境:
- jdk1.8 : SpringBoot官方推荐的1.7以上 java version "1.8.0_171"
- maven: Apache Maven 3.6.0
- idea: IntelliJ IDEA 2020.1 x64
- SpringBoot: 2.3.0
4、SpringBoot HelloWorld
一个需求:
浏览器发送hello 请求,服务器接收并处理,响应Hello World字符串
- 创建Maven工程
- 导入Springboot相关依赖
- 编写主程序:启动SpringBoot应用
- 编写相关的controller、service
- 运行主程序进行测试
- 简化部署
- Jar包 打包过后直接使用 java -jar 在cmd里运行
5、Hello World 探究
5.1、POM文件
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.0.RELEASE</version>
</parent>
他的父项目是
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.3.0.RELEASE</version>
</parent>
他是真正用来管理Spring boot 应用的所有依赖版本
SpringBoot的版本仲裁中心
我们以后导入依赖的时候都不需要写版本(没有写在dependencies中的需要单独声明版本号)
5.2、 启动器
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
spring-boot-starter == web ==
spring-boot-starter :springboot 的场景启动器,帮我们导入web模块正常运行所需要的组件
SpringBoot把所有的功能场景都提取出来,做成一个个starter(启动器),我们只需要在项目里导入相关的starter相关的场景就会把所有相关的依赖都会导入进来。要用什么功能就达到入什么场景的启动器
5.3、主程序类和入口类
/**
* @SpringBootApplication 来标准一个主程序类,说明当前是一个SpringBoot应用
*/
@SpringBootApplication
public class HelloWorldMainApplication {
public static void main(String[] args) {
// 让 Spring应用程序跑起来
SpringApplication.run(HelloWorldMainApplication.class,args);
}
}
@SpringBootApplication: 这个注解标注到哪个类上面,就代表了这个类是SpringBoot的主配置类,
SpringBoot是运行这个main方法来启动当前的SpringBoot项目:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
@SpringBootConfiguration: SpringBoot的配置类:
标注在哪个类,表示当前是一个SpringBoot的一个配置类
@Configuration:标注在配置类上的
配置类 ------ 配置文件: 配置类也是容器中的一个组键,@Component
@EnableAutoConfiguration: 开启自动配置功能
以前需要配置东西的时候,SpringBoot会帮我们配置,@EnableAutoConfiguration 是告诉SpringBoot开启自动配置,这样我们的配置才会生效
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
@AutoConfigurationPackage : 自动配置包
@Import(AutoConfigurationImportSelector.class)
@Import是spring的底层注解,给容器导入一个组件;导入的组件由AutoConfigurationImportSelector.class
这个注解会将主配置类(@SpringBootApplication所标注的类)下面所有的子包里面的组价扫描到spring容器
@Import(AutoConfigurationImportSelector.class)
给容器中导入组件
AutoConfigurationImportSelector: 导入哪些主键的选择器
将所有需要导入的组件以全类目的方式返回: 这些组件就会加载到spring容器中
会给容器导入很多的配置类(xx.AutoConfiguration):其实就是导入你当前的场景所需要的依赖包
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vNcBPkYW-1591951707033)(C:\Users\JiangXinWei\Desktop\第二十八天\springBoot笔记\images\1589772241592_0B427267-7E72-4ba3-B3AE-034D934FE971.png)]
有了这个配置类,我们就不用手动去编写配置类去加载到项目中;
SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader());
springboot会在启动的时候在类路径下的META-INF/spring.factories,会获取道@EnableAutoConfiguration制定的值,把这些值作为自动配置加入到容器。然后自动配置类就会生效。
5.4 、使用spring中的项目创建的向导器Spring Initializr去创建SpringBoot项目
- idea都有一个快速构建springboot项目的向导器Spring Initializr,可以使用它来创建项目,只需要勾选你想要的场景模块,就会自动下载所需要的依赖, 注: 创建过程中必须要联网 。
- 出程序以及生产好了,只需要根据我们的逻辑需求去编写
- resources 文件夹下的目录结构
- static: 存放当前项目下的所有静态资源 CSS、JS、Images …
- templates: 存放所有的模板页面;
- 注: 因为SpringBoot是内嵌Tomcat,所以说默认不支持JSP页面,可以使用插件去使用JSP页面
- 注:SpringBoot推荐使用模板引擎 - Thymeleaf、Freemarker
- application.properties : SpringBoot默认加载的配置文件,可以去修改一些默认配置
二、配置文件
6、配置文件
6.1、配置文件
SpringBoot使用了一个全局的配置文件,配置文件的名字是固定的。
application.properties
application.yml
作用: 修改SpringBoot中的一些默认配置,这个文件会被springboot进行自动配置
yml = YAML:
-
格式: 序列化
-
写法: 递归的写法
-
以数据为中心,比json、xml等更适合做配置文件
-
“YAML Ain’t a Markup Language”(YAML不是一种标记语言)
“Yet Another Markup Language”(仍是一种标记语言)
标记语言:
以前 使用xxx.xml
现在: YAML更好一些
.xml
<server>
<port>8081</port>
</server>
.yml
server:
port: 8081
6.2 YAML语法
6.2.1 基本语法
K: (空格)V 类似于键值对的写法,注意: 冒号后面要跟空格才能写V(值)
用空格来控制层级关系,只要根据左对齐的方式,同一列的数据都同一层级
server:
port: 8081
servlet:
context-path: /hello
6.2.2 值的写法
1、基本语法
K: (空格)V 类似于键值对的写法,注意: 冒号后面要跟空格才能写V(值)
2、 字面量: 普通的值(字符串、数字、布尔值)
K: V : 直接键值对写值
注: - 如果说值是字符串也不需要去给引号
在什么情况下可以加引号?
双引号 " " : 如果说包含特殊字符,那么引不会转义特殊字符的含义,会直接根据特殊字符的本身含义展示出来
user:
name: "laowang \n gebi" ----- name: laowang 换行 gebi**
单引号 ’ ':如果说包含特殊字符,那么单引号会转义特殊字符的含义,会直接把特殊字符作为一个字符串进行输出
user:
name: ‘laowang \n gebi’ ----- name: laowang \n gebi**
3、对象、Map
K: V : 在下一行去根据键值对的方式写属性个值
user:
username: xiaoming
age: 18
gender: 男
如果说想把对象或者Map在一行内写出来
user: {username: xiaoming,age: 18,gender: 男}
4、数组、list、set
在下一行使用 - (空格)值,来表示一个元素
sub:
- JAVA
- Python
- HTML
如果说想把组或者list、set在一行内写出来
sub: java,python,html
6.3 获取YAML中的值
配置文件:
.yml
user:
userName: xiaoming
age: 18
gender: 男
isgirl: true
maps: {k1: v1,k2: v2}
sub:
- java
- python
- html
girl:
name: 小芳
age: 16
JavaBean
/**
* @ConfigurationProperties 标注在一个类上,告诉Springboot讲本类中所有的属性和指定的配置文件中的参数进行绑定
* 注: ConfigurationProperties 属于容器中的注解,
* prefix = "" 指定获取的是配置文件中哪一个下面所有参数
*/
@Component
@ConfigurationProperties(prefix = "user")
public class User {
private String userName;
private int age;
private String gender;
private boolean isgirl;
private Map<String,Object> maps;
private List<Object> sub;
private Girl girl;
配置文件处理器,到入这个包之后,我们进行属性和参数的绑定时会有人性化提示
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
.properties中的的参数取值乱码怎么办?
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ED1rug3C-1591951707038)(C:\Users\JiangXinWei\Desktop\第二十九天\springBoot笔记\images\1.png)]
6.4 @Value 和 @ConfigurationProperties 应用场景
@ConfigurationProperties | @Value | |
---|---|---|
取值 | 可以一次取出全部参数进行绑定 | 一个一个取 |
SpEL | 不支持 | 支持 |
松散绑定 | 支持 | 不支持 |
JSR303数据校验 | 支持 | 不支持 |
复杂类型绑定 | 支持 | 不支持 |
提问:
这两个直接的应用场景分别是什么?
如果说你只是在处理业务时,需要用到配置问价中某一个参数的值,就用@Value
如果说你专门做实体绑定配置文件的实例,这是用@ConfigurationProperties
数据校验
/**
* @ConfigurationProperties 标注在一个类上,告诉Springboot讲本类中所有的属性和指定的配置文件中的参数进行绑定
* 注: ConfigurationProperties 属于容器中的注解,
* prefix = "user" 指定获取的是配置文件中哪一个下面所有参数
*/
@Component
@ConfigurationProperties(prefix = "user")
@Validated
public class User {
/**
* <bean class="user">
* <property name="userName" value="字面量、${},从配置文件中取值、
* SpEL表达式#{},spring表达式,用来做四则运算的"
* </bean>
*/
// @Value("${user.user-name}")
private String userName;
// @Value("#{2*5*8}")
private int age;
private String gender;
// @Value("false")
private boolean isgirl;
// @Value("${maps}")
6.5 @PorpertySource & @ImportSource & @Bean
@PorpertySource: 加载指定的配置文件
/**
* @Author Administrator
* @Date 2020/5/20 15:31
* @ConfigurationProperties 会告诉springboot将本类中的属性和配置文件相关的参数进行绑定
* 注: ConfigurationProperties 是容器中的方法,所以当前类必须要容器中
*
* prefix = "user" ;去指定配置文件中的哪一个下面的属性
**/
@PropertySource(value = {"classpath:User.properties"}) //加载指定的配置文件
@Component
@ConfigurationProperties(prefix = "user")
//@Validated
public class User {
@ImportSource: 导入spring的配置文件,使其生效;
Springbooot中是 没有Spring配置文件的,我们自己编写的配置文件,也不会自动识别。
可以使用@ImportSource,让spring的配置类生效
注:@ImportSource 必须要标注在一个配置类上
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="userService" class="com.gm.service.UserService"></bean>
</beans>
如果说,我们项目中不允许出现.xml文件怎么办呢?
SpringBoot 推荐给容器中添加组件的方式;推荐使用全注解
@Configuration ------ spring配置文件
@Bean —
/**
* @Author Administrator
* @Date 2020/5/22 14:51
* @Configuration 标注在哪个类上,就代表当前是springboot的配置类
*
*<bean id="userService" class="com.gm.service.UserService"></bean>
**/
@Configuration
public class BootConfig {
// 把返回值加载到容器中
@Bean
public UserService userService(){
System.out.println("正在给spring容器注入组件");
return new UserService();
}
}
6.6 占位符
6.6 .1随机数
${random.value}、${random.int}、${random.long}
${random.int(10)}、${random.int[1024,65536]}
赋值 、 取值 、 自定义
user.user-name= 夏明翰${random.UUID}
user.age=${random.int}
user.gender=男
user.isgirl=true
user.maps.k1=v1
user.maps.k2=v2
user.sub=java,python,html
user.girl.name=${user.user-name}${user.password:的第二个}老Boby
user.girl.age=16
7、Profiles
7.1多Profiles文件
我们在主配置文件编写的时候,文件名可以是 :
application.properties/.yml
application-{profiles}.properties/.yml
当项目中同时存在默认配置文件喝profiles文件时,
默认使用 application.properties/.yml
7.2 YAML支持多文档块
server:
port: 8084
spring:
profiles:
active: prov
---
server:
port: 8085
spring:
profiles: devs
---
server:
port: 8086
spring:
profiles: prov
7.3 激活制定的profiles的方法
1. 在配置文件中激活 spring.profiles.active: prov
- 在spring环境里去激活 --spring.profiles.active=devs
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JBc3anwb-1591951707041)(C:\Users\JiangXinWei\Desktop\springBoot笔记\springBoot笔记\images\2.PNG)]
-
命令行:
java -jar springboot-03-config2-0.0.1-SNAPSHOT.jar --spring.profiles.active=devs
-
虚拟机参数:
-Dspring.profiles.active=devs
8. 配置文件的加载位置
SpringBoot启动的时候会扫描以下位置application.properties和application.yml的默认配置文件
file:./config/
file: ./
classpath: /config/
classpath: /
优先级由高到低,
如果项目中存在相同配置不同位置的properties文件,那么高优先级是不是会覆盖低优先级;
如果项目中存在不同配置不同位置的properties文件,那么会发生 互补配置;
还可以通过 命令行: spring.config.location来改变默认加载的配置文件位置,同时,会同样遵守互补配置;
java -jar springboot-03-config-0.0.1-SNAPSHOT.jar --spring.config.location=C:/Users/JiangXinWei/Desktop/application.properties
9、配置文件的外部加载顺序
Springboot也可以从以下位置加载配置文件,优先级从高到低、遵循高覆盖低而且配置互补。
1.命令行参数
所有的配置都可以在命令行行进行执行
java -jar springboot-03-config-0.0.1-SNAPSHOT.jar --server.port=8088 --server.servlet.context-path=/ufo
书写规范: –配置项=值
2.来自java:comp/env的JNDI属性
3.Java系统属性(System.getProperties())
4.操作系统环境变量
5.RandomValuePropertySource配置的random.*属性值
== 由jar包外向jar包内进行寻找==:
**-- 优先加载带profile的文件-- **
6.jar包外部的application-{profile}.properties或application.yml(带spring.profile)配置文件
7.jar包内部的application-{profile}.properties或application.yml(带spring.profile)配置文件
– 再加载不带profile的文件–
8.jar包外部的application.properties或application.yml(不带spring.profile)配置文件
9.jar包内部的application.properties或application.yml(不带spring.profile)配置文件
10.@Configuration注解类上的@PropertySource
11.通过SpringApplication.setDefaultProperties指定的默认属性
10 自动配置的原理
配置文件中到底能写什么?怎么写?自动配置的原理;
10.1 自动配置原理
- springboot启动的时候回加载主配置类,开启自动配置:@EnableAutoConfiguration
- @EnableAutoConfiguration:
- 利用AutoConfigurationImportSelector给容器导入了一些组件
- selectImports()方法的内容
- List configurations = getCandidateConfigurations(annotationMetadata, attributes); 获取候选的配置
SpringFactoriesLoader.loadFactoryNames()
扫描所以jar类路径下的 : META-INF/spring.factories
把扫描的这些文件的内容包装成properties对象
从properties中获取EnableAutoConfiguration.class类名对应的值,然后把他们添加到容器中
# Initializers
org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer,\
org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener
# Application Listeners
org.springframework.context.ApplicationListener=\
org.springframework.boot.autoconfigure.BackgroundPreinitializer
# Auto Configuration Import Listeners
org.springframework.boot.autoconfigure.AutoConfigurationImportListener=\
org.springframework.boot.autoconfigure.condition.ConditionEvaluationReportAutoConfigurationImportListener
# Auto Configuration Import Filters
org.springframework.boot.autoconfigure.AutoConfigurationImportFilter=\
org.springframework.boot.autoconfigure.condition.OnBeanCondition,\
org.springframework.boot.autoconfigure.condition.OnClassCondition,\
org.springframework.boot.autoconfigure.condition.OnWebApplicationCondition
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\
org.springframework.boot.autoconfigure.context.LifecycleAutoConfiguration,\
org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,\
org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration,\
org.springframework.boot.autoconfigure.dao.PersistenceExceptionTranslationAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ReactiveElasticsearchRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ReactiveElasticsearchRestClientAutoConfiguration,\
org.springframework.boot.autoconfigure.data.jdbc.JdbcRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.ldap.LdapRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.solr.SolrRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.r2dbc.R2dbcDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.r2dbc.R2dbcRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.r2dbc.R2dbcTransactionManagerAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisReactiveAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.rest.RepositoryRestMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.data.web.SpringDataWebAutoConfiguration,\
org.springframework.boot.autoconfigure.elasticsearch.ElasticsearchRestClientAutoConfiguration,\
org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration,\
org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration,\
org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration,\
org.springframework.boot.autoconfigure.h2.H2ConsoleAutoConfiguration,\
org.springframework.boot.autoconfigure.hateoas.HypermediaAutoConfiguration,\
org.springframework.boot.autoconfigure.hazelcast.HazelcastAutoConfiguration,\
org.springframework.boot.autoconfigure.hazelcast.HazelcastJpaDependencyAutoConfiguration,\
org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration,\
org.springframework.boot.autoconfigure.http.codec.CodecsAutoConfiguration,\
org.springframework.boot.autoconfigure.influx.InfluxDbAutoConfiguration,\
org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration,\
org.springframework.boot.autoconfigure.integration.IntegrationAutoConfiguration,\
org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.JndiDataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.XADataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration,\
org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.JndiConnectionFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.activemq.ActiveMQAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.artemis.ArtemisAutoConfiguration,\
org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration,\
org.springframework.boot.autoconfigure.jooq.JooqAutoConfiguration,\
org.springframework.boot.autoconfigure.jsonb.JsonbAutoConfiguration,\
org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration,\
org.springframework.boot.autoconfigure.availability.ApplicationAvailabilityAutoConfiguration,\
org.springframework.boot.autoconfigure.ldap.embedded.EmbeddedLdapAutoConfiguration,\
org.springframework.boot.autoconfigure.ldap.LdapAutoConfiguration,\
org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration,\
org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration,\
org.springframework.boot.autoconfigure.mail.MailSenderValidatorAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.MongoReactiveAutoConfiguration,\
org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration,\
org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\
org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration,\
org.springframework.boot.autoconfigure.r2dbc.R2dbcAutoConfiguration,\
org.springframework.boot.autoconfigure.rsocket.RSocketMessagingAutoConfiguration,\
org.springframework.boot.autoconfigure.rsocket.RSocketRequesterAutoConfiguration,\
org.springframework.boot.autoconfigure.rsocket.RSocketServerAutoConfiguration,\
org.springframework.boot.autoconfigure.rsocket.RSocketStrategiesAutoConfiguration,\
org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration,\
org.springframework.boot.autoconfigure.security.servlet.SecurityFilterAutoConfiguration,\
org.springframework.boot.autoconfigure.security.reactive.ReactiveSecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.reactive.ReactiveUserDetailsServiceAutoConfiguration,\
org.springframework.boot.autoconfigure.security.rsocket.RSocketSecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.saml2.Saml2RelyingPartyAutoConfiguration,\
org.springframework.boot.autoconfigure.sendgrid.SendGridAutoConfiguration,\
org.springframework.boot.autoconfigure.session.SessionAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.client.servlet.OAuth2ClientAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.client.reactive.ReactiveOAuth2ClientAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.resource.servlet.OAuth2ResourceServerAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.resource.reactive.ReactiveOAuth2ResourceServerAutoConfiguration,\
org.springframework.boot.autoconfigure.solr.SolrAutoConfiguration,\
org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration,\
org.springframework.boot.autoconfigure.task.TaskSchedulingAutoConfiguration,\
org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration,\
org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration,\
org.springframework.boot.autoconfigure.transaction.jta.JtaAutoConfiguration,\
org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration,\
org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.web.embedded.EmbeddedWebServerFactoryCustomizerAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.HttpHandlerAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.ReactiveWebServerFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.error.ErrorWebFluxAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.function.client.ClientHttpConnectorAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.MultipartAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.reactive.WebSocketReactiveAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.servlet.WebSocketServletAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.servlet.WebSocketMessagingAutoConfiguration,\
org.springframework.boot.autoconfigure.webservices.WebServicesAutoConfiguration,\
org.springframework.boot.autoconfigure.webservices.client.WebServiceTemplateAutoConfiguration
# Failure analyzers
org.springframework.boot.diagnostics.FailureAnalyzer=\
org.springframework.boot.autoconfigure.diagnostics.analyzer.NoSuchBeanDefinitionFailureAnalyzer,\
org.springframework.boot.autoconfigure.flyway.FlywayMigrationScriptMissingFailureAnalyzer,\
org.springframework.boot.autoconfigure.jdbc.DataSourceBeanCreationFailureAnalyzer,\
org.springframework.boot.autoconfigure.jdbc.HikariDriverConfigurationFailureAnalyzer,\
org.springframework.boot.autoconfigure.r2dbc.ConnectionFactoryBeanCreationFailureAnalyzer,\
org.springframework.boot.autoconfigure.session.NonUniqueSessionRepositoryFailureAnalyzer
# Template availability providers
org.springframework.boot.autoconfigure.template.TemplateAvailabilityProvider=\
org.springframework.boot.autoconfigure.freemarker.FreeMarkerTemplateAvailabilityProvider,\
org.springframework.boot.autoconfigure.mustache.MustacheTemplateAvailabilityProvider,\
org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAvailabilityProvider,\
org.springframework.boot.autoconfigure.thymeleaf.ThymeleafTemplateAvailabilityProvider,\
org.springframework.boot.autoconfigure.web.servlet.JspTemplateAvailabilityProvider
每一个xxxxxxAutoConfiguration类都是容器中的一个组件,都加到容器中,同时就是用他们来自做自动配置。
- 接下来用 HttpEncodingAutoConfiguration (Http编码自动配置) 来解释一下自动原理
@Configuration(proxyBeanMethods = false) // 表示是一个配置类,相当于以前的xml配置文件
@EnableConfigurationProperties(ServerProperties.class) // 启动指定类的ConfigurationProperties,将配置文件中对应的值和ServerProperties进行绑定,并且绑定完之后会把ServerProperties加载道IOC容器中
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)// Conditiona 是spring中的底层注解,用来判断的,根据不同的条件,如果满足指定的条件,整个配置类中的配置才会生效。 判断当前是不是WEB项目,如果是,当前配置类生效
@ConditionalOnClass(CharacterEncodingFilter.class) // 判断当前项目中有没有这个类,CharacterEncodingFilter.class: SpringMVC中解决乱码问题的过滤器
@ConditionalOnProperty(prefix = "server.servlet.encoding", value = "enabled", matchIfMissing = true)// 判断配置文件中有没有某个配置,server.servlet.encoding.enabled,如果不存在,判断也是成立的,即使我们的配置文件中不存在server.servlet.encoding.enabled=true,也是默认生效的
public class HttpEncodingAutoConfiguration {
// 已经和springboot的配置文件进行绑定了
private final Encoding properties;
// 有参构造、当只有一个有参构造的时候,参数的值会从容器中得到
public HttpEncodingAutoConfiguration(ServerProperties properties) {
this.properties = properties.getServlet().getEncoding();
}
@Bean // 给容器中添加一个组价,组件中有些值需要从properties去获取
@ConditionalOnMissingBean // 判断当前容器中有没有这个组件,CharacterEncodingFilter
public CharacterEncodingFilter characterEncodingFilter() {
CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();
filter.setEncoding(this.properties.getCharset().name());
filter.setForceRequestEncoding(this.properties.shouldForce(Encoding.Type.REQUEST));
filter.setForceResponseEncoding(this.properties.shouldForce(Encoding.Type.RESPONSE));
return filter;
}
Conditiona 根据不同的条件判断得到不同的结果;
一旦这个配置文件生效,这个配置类就会给容器中添加各种组件;这些组件中的属性都是从对应的properties中获取的,同时,这些类里面的每一个属性有和配置文件进行绑定
- 每一个XXXAutoConfiguration都应该有一个相对于的xxxxproperties文件。
总结:
1, springboot启动时会加载大量的配置类;
2,我们在写之前,看一下我们需要的东西有没有是springboot默认写好的自动配置类
3,如果有,只需要看一下自动配置类中到底 配置了哪些组件;
4, 给容器中自动配置类添加组件的时候。会从从对应的properties中获取的,就可在配置文件中制定这些属性的值
11 拓展 @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 来查看哪些配置生效
Positive matches: (自动配置类生效)
-----------------
AopAutoConfiguration matched:
- @ConditionalOnProperty (spring.aop.auto=true) matched (OnPropertyCondition)
AopAutoConfiguration.ClassProxyingConfiguration matched:
- @ConditionalOnMissingClass did not find unwanted class 'org.aspectj.weaver.Advice' (OnClassCondition)
- @ConditionalOnProperty (spring.aop.proxy-target-class=true) matched (OnPropertyCondition)
DispatcherServletAutoConfiguration matched:
- @ConditionalOnClass found required class 'org.springframework.web.servlet.DispatcherServlet' (OnClassCondition)
- found 'session' scope (OnWebApplicationCondition)
DispatcherServletAutoConfiguration.DispatcherServletConfiguration matched:
- @ConditionalOnClass found required class 'javax.servlet.ServletRegistration' (OnClassCondition)
- Default DispatcherServlet did not find dispatcher servlet beans (DispatcherServletAutoConfiguration.DefaultDispatcherServletCondition)
Negative matches:(没有启动,么有匹配成功的配置类)
-----------------
ActiveMQAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'javax.jms.ConnectionFactory' (OnClassCondition)
AopAutoConfiguration.AspectJAutoProxyingConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'org.aspectj.weaver.Advice' (OnClassCondition)
三、Web开发
1、简介
使用Springboot:
- 创建springboot应用,选中我们需要的模块;
- springboot已经默认的把这些场景都配置好了,只需要去更改配置文件中的少量配置就可以运行起来;
- 自己编写业务代码;
自动配置原理?
Springboot到底给我们配置了什么? 能不能修改? 能不能修改默认配置?。。。。
xxxAutoConfiguration 帮我们给容器中自动配置组件
xxxproperties 配置类来封装配置文件的内容
2、SpringBoot对静态资源路径映射的规则
WebMvcAutoConfiguration
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
if (!this.resourceProperties.isAddMappings()) {
logger.debug("Default resource handling disabled");
return;
}
Duration cachePeriod = this.resourceProperties.getCache().getPeriod();
CacheControl cacheControl = this.resourceProperties.getCache().getCachecontrol().toHttpCacheControl();
if (!registry.hasMappingForPattern("/webjars/**")) {
customizeResourceHandlerRegistration(registry.addResourceHandler("/webjars/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/")
.setCachePeriod(getSeconds(cachePeriod)).setCacheControl(cacheControl));
}
String staticPathPattern = this.mvcProperties.getStaticPathPattern();
// 静态资源文件夹映射
if (!registry.hasMappingForPattern(staticPathPattern)) {
customizeResourceHandlerRegistration(registry.addResourceHandler(staticPathPattern)
.addResourceLocations(getResourceLocations(this.resourceProperties.getStaticLocations()))
.setCachePeriod(getSeconds(cachePeriod)).setCacheControl(cacheControl));
}
}
// 首页的映射
@Bean
public WelcomePageHandlerMapping welcomePageHandlerMapping(ApplicationContext applicationContext,
FormattingConversionService mvcConversionService, ResourceUrlProvider mvcResourceUrlProvider) {
WelcomePageHandlerMapping welcomePageHandlerMapping = new WelcomePageHandlerMapping(
new TemplateAvailabilityProviders(applicationContext), applicationContext, getWelcomePage(),
this.mvcProperties.getStaticPathPattern());
welcomePageHandlerMapping.setInterceptors(getInterceptors(mvcConversionService, mvcResourceUrlProvider));
welcomePageHandlerMapping.setCorsConfigurations(getCorsConfigurations());
return welcomePageHandlerMapping;
}
-
所有的 /webjars/ ,都会去 classpath:/META-INF/resources/webjars/ 去资源**
webjars: 把前段的资源以jar包的方式引用
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Yxa7FBKb-1591951707044)(C:\Users\JiangXinWei\Desktop\springBoot笔记\springBoot笔记\images\5.png)]
localhost:8080/webjars/jquery/3.3.1/jquery.js
<!--Jquery组件(前端)-->
<dependency>
<groupId>org.webjars</groupId>
<artifactId>jquery</artifactId>
<version>3.3.1</version>
</dependency>
- “/” 访问当前项目的任何资源,都会去静态资源的文件夹去找映射
"classpath:/META-INF/resources/",
"classpath:/resources/",
"classpath:/static/",
"classpath:/public/"
"/" 当前项目的根路径
http://localhost:8080/style.js 会从静态资源路径去找style.js
- 欢迎页/首页,静态资源文件夹下的所有的index.html页面,都会背部“/”映射
http://localhost:8080/
- 所有的**/favicon.ico 都在静态资源目录中去找
3、模板引擎
jSP、Velocity、Freemarker、Thymeleaf
Thymeleaf:
1、Thymeleaf 是 Web 和独立环境的现代服务器端 Java 模板引擎,能够处理HTML,XML,JavaScript,CSS 甚至纯文本。
2、Thymeleaf 的主要目标是提供一种优雅和高度可维护的创建模板的方式。为了实现这一点,它建立在自然模板的概念上,将其逻辑注入到模板文件中,不会影响模板被用作设计原型。这改善了设计的沟通,弥补了设计和开发团队之间的差距。
3、Thymeleaf 也从一开始就设计了Web标准 - 特别是 HTML5 - 允许您创建完全验证的模板,Spring Boot 官方推荐使用 thymeleaf 而不是 JSP。
4、Thymeleaf 官网:https://www.thymeleaf.org/
5、Thymeleaf 在 Github 的主页:https://github.com/thymeleaf/thymeleaf
6、Spring Boot 中使用 Thymeleaf 模板引擎时非常简单,因为 Spring Boot 已经提供了默认的配置,比如解析的文件前缀,文件后缀,文件编码,缓存等等,程序员需要的只是写 html 中的内容即可,可以参考《Spring Boot 引入 Thymeleaf 及入门》
特点 : 语法更简单、功能更强大
原 理:
模板引擎原理图如下,模板引擎的作用都是将模板(页面)和数据进行整合然后输出显示,区别在于不同的模板使用不同的语法,如 JSP 的 JSTL 表达式,以及 JSP 自己的表达式和语法,同理 Thymeleaf 也有自己的语法
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VcYoEPHg-1591951707047)(C:\Users\JiangXinWei\Desktop\springBoot笔记\springBoot笔记\images\6.png)]
3.1 引入Thymeleaf:
<!-- 引入thymeleaf -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
使用Thymeleaf:
@ConfigurationProperties(prefix = "spring.thymeleaf")
public class ThymeleafProperties {
private static final Charset DEFAULT_ENCODING = StandardCharsets.UTF_8;
public static final String DEFAULT_PREFIX = "classpath:/templates/";
public static final String DEFAULT_SUFFIX = ".html";
所以说,只要把页面放到classpath:/templates/,thymeleaf就可以自动进行渲染。
使用:
- 需要导入Thymeleaf的名称空间
<html lang="en" xmlns:th="http://www.thymeleaf.org">
- 使用thymeleaf语法:
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<p>这里是测试页面</p><hr>
<p id="p" >[[ ${hello} ]]</p><hr>
<input th:value="${hello}" value="我是取值的Input标签"/><hr>
<p th:each="user:${list}" th:text="${user}">我是取list的地方</p>
</body>
</html>
- 语法规则:
- th:text ; 改变当前元素里面的文本内容
- th: 任意html属性,来替换原生属性的值
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9Ty6GWKW-1591951707048)(C:\Users\JiangXinWei\Desktop\springBoot笔记\springBoot笔记\images\9.png)]
取值:
Simple expressions: (表达式语法)
Variable Expressions: ${...}: 获取变量的值,OGNL
1. 获取对象的属性、调用方法
2. 使用内置的基本对象
#ctx : the context object.
#vars: the context variables.
#locale : the context locale.
#request : (only in Web Contexts) the HttpServletRequest object.
#response : (only in Web Contexts) the HttpServletResponse object.
#session : (only in Web Contexts) the HttpSession object.
#servletContext : (only in Web Contexts) the ServletContext object.
${session.foo}
3. 内置的一些工具对象:
#execInfo : information about the template being processed.
#messages : methods for obtaining externalized messages inside variables expressions, in the same way as they would be obtained using #{…} syntax.
#uris : methods for escaping parts of URLs/URIs
#conversions : methods for executing the configured conversion service (if any).
#dates : methods for java.util.Date objects: formatting, component extraction, etc.
#calendars : analogous to #dates , but for java.util.Calendar objects.
#numbers : methods for formatting numeric objects.
#strings : methods for String objects: contains, startsWith, prepending/appending, etc.
#objects : methods for objects in general.
#bools : methods for boolean evaluation.
#arrays : methods for arrays.
#lists : methods for lists.
#sets : methods for sets.
#maps : methods for maps.
#aggregates : methods for creating aggregates on arrays or collections.
#ids : methods for dealing with id attributes that might be repeated (for example, as a result of an iteration).
Selection Variable Expressions: *{...} : 选择表达式,和${}在功能上是一样的
补充: <div th:object="${session.user}">
<p>Name: <span th:text="*{firstName}">Sebastian</span>.</p>
<p>Surname: <span th:text="*{lastName}">Pepper</span>.</p>
<p>Nationality: <span th:text="*{nationality}">Saturn</span>.</p>
</div>
Message Expressions: #{...} : 获取国际化内容
Link URL Expressions: @{...} : 定义URL
<!-- Will produce 'http://localhost:8080/gtvg/order/details?orderId=3' (plus rewriting) -->
<a href="details.html"th:href="@{http://localhost:8080/gtvg/order/details(orderId=${o.id})}">view</a>
<!-- Will produce '/gtvg/order/details?orderId=3' (plus rewriting) -->
<a href="details.html" th:href="@{/order/details(orderId=${o.id})}">view</a>
<!-- Will produce '/gtvg/order/3/details' (plus rewriting) -->
<a href="details.html" th:href="@{/order/{orderId}/details(orderId=${o.id})}">view</a>
Fragment Expressions: ~{...} : 片段引用表达式
<div th:insert="~{commons :: main}">...</div>
Literals (字面量)
Text literals: 'one text' , 'Another one!' ,…
Number literals: 0 , 34 , 3.0 , 12.3 ,…
Boolean literals: true , false
Null literal: null
Literal tokens: one , sometext , main ,…
Text operations: (文本操作)
String concatenation: +
Literal substitutions: |The name is ${name}|
Arithmetic operations: (数学运算)
Binary operators: + , - , * , / , %
Minus sign (unary operator): -
Boolean operations: (布尔值运算)
Binary operators: and , or
Boolean negation (unary operator): ! , not
Comparisons and equality: (比较运算)
Comparators: > , < , >= , <= ( gt , lt , ge , le )
Equality operators: == , != ( eq , ne )
Conditional operators: 条件运算(三元运算符)
If-then: (if) ? (then)
If-then-else: (if) ? (then) : (else)
Default: (value) ?: (defaultvalue)
Special tokens:
No-Operation: _
3.2 SpringMVC自动配置:
https://docs.spring.io/spring-boot/docs/2.3.0.RELEASE/reference/htmlsingle/#boot-features-developing-web-applications
1. Spring MVC Auto-configuration
Spring Boot 自动配置好了SprinMVC
以下是SpringBoot对SpringMVC的默认配置:WebMvcAutoConfiguration :
org\springframework\boot\autoconfigure\web\servlet\WebMvcAutoConfiguration.java
-
Inclusion of
ContentNegotiatingViewResolver
andBeanNameViewResolver
beans.- 自动配置了ViewResolver(视图解析器: 根据当前的方法返回值,得到视图对象(View),视图的对象绝对了如何进行渲染(转发,重定向))
ContentNegotiatingViewResolver
: 组合所有的视图解析器- 如何自己去写: 我们可以给容器中添加一个视图解析器;自动帮我们将自己写的组合进去
-
Support for serving static resources, including support for WebJars (covered later in this document)). :
- WebJars ,静态资源文件夹路径的webjars
- localhost:8080/webjars/xxxxxxx
-
自动注册了 of
Converter
,GenericConverter
, andFormatter
beans.Converter
:转换器;public String Hello(User user){}; 类型转换器Converter
Formatter
: 格式化器: 2020.05.30 === Date
-
Support for
HttpMessageConverters
(covered later in this document).HttpMessageConverters
: SpringMVC用来转换Http请求的请求和相应的;User—JSON- HttpMessageConverters: 从容器中确定: 获取所有的HttpMessageConverters,
- 如果自己去添加,只需要将自己的组件去注册到容器中(@Bean,@Component)
-
Automatic registration of
MessageCodesResolver
(covered later in this document).- 定义错误代码生成规则
-
Static
index.html
support.: 静态资源的首页访问 -
Custom
Favicon
support (covered later in this document). : Favicon.ico -
Automatic use of a
ConfigurableWebBindingInitializer
bean (covered later in this document).- 可以去定义一个属于自己的
ConfigurableWebBindingInitializer
来替换默认的,只需要将自己写的祖册到容器中
- 可以去定义一个属于自己的
If you want to keep those Spring Boot MVC customizations and make more MVC customizations (interceptors, formatters, view controllers, and other features), you can add your own @Configuration
class of type WebMvcConfigurer
but without@EnableWebMvc
.
If you want to provide custom instances of RequestMappingHandlerMapping
, RequestMappingHandlerAdapter
, or ExceptionHandlerExceptionResolver
, and still keep the Spring Boot MVC customizations, you can declare a bean of type WebMvcRegistrations
and use it to provide custom instances of those components.
If you want to take complete control of Spring MVC, you can add your own @Configuration
annotated with @EnableWebMvc
, or alternatively add your own @Configuration
-annotated DelegatingWebMvcConfiguration
as described in the Javadoc of @EnableWebMvc
.
2. 扩展SpringMVC
<mvc:view-controller path="/JJ" view-name="test2"/>
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/JJ"/>
<bean></bean>
</mvc:interceptor>
</mvc:interceptors>
步骤: 编写一个配置类(@Configuration),属于WebMvcConfigurer类型(2.3.0),之前的版本叫做WebMvcConfigurerApapter;不能是@EnableWebMvc
@Configuration
//@EnableWebMvc
public class MyMvcConfig implements WebMvcConfigurer{
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/JJ").setViewName("test2");
registry.addViewController("/").setViewName("test2");
}
}
原理:
1. WebMvcConfigurer 是SpringMVC的自动配置类
2. 当我们配置好的时候启动项目,容器中所有的WebMvcConfigurer 都会一起起作用
3. 我们的配置类也会生效
3.3 全面接管SpringMVC
@EnableWebMvc
:SpringBoot对SpringMVC的自动配置已经不需要了。所有的都需要我们自已配置;所以SprigMVC的自动配置失效了;
实现: 只需要在配置类中加入@EnableWebMvc
注解
// WebMvcConfigurer 可以扩展SpringMVC中的功能
@Configuration
@EnableWebMvc
public class MyMvcConfig implements WebMvcConfigurer{
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/JJ").setViewName("test2");
registry.addViewController("/").setViewName("test2");
}
}
原理:
为什么加入@EnableWebMvc
之后自动配置就失效了?
1、@EnableWebMvc
的核心
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(DelegatingWebMvcConfiguration.class)
public @interface EnableWebMvc {
}
@Configuration(proxyBeanMethods = false)
public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {
3、
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class) // 容器中没有WebMvcConfigurationSupport 配置类才生效
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
@AutoConfigureAfter({ DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class,
ValidationAutoConfiguration.class })
public class WebMvcAutoConfiguration {
4、@EnableWebMvc
将所有的WebMvcConfigurationSupport组件导入进来
5、导入的WebMvcConfigurationSupport只是SpringMVC中最基本的功能
3.4 如何去修改SpringBoot的默认配置
模式:
1. SpringBoot在自动配置很多组件的时候,先看容器中有没有用户自己配置的(@Bean,@Component),如果有就用用户自己配置的,如果没有才会进行自动配置。如果说有一些组件可以配置多个(ViewResolver)会将用户配置和自己默认的配置组合起来。
2. SpringBoot中会有很多的XXXXConfigurer帮我们去自定义扩展配置
3. SpringBoot中会有很多的XXXXCustomizer帮我们去定制配置
4. RestFul CRUD
4.1 首页
1. 默认访问首页
1. 写一个转发的方法
@Controller
public class LoginController {
@RequestMapping({"/","login.html"})
public String dpPage(){
return "login";
}
}
- 自定义配置文件
@Configuration
public class MyConfig {
@Bean
public WebMvcConfigurer webMvcConfigurer(){
WebMvcConfigurer webMvcConfigurer = new WebMvcConfigurer() {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("login");
registry.addViewController("/login.html").setViewName("login");
}
};
return webMvcConfigurer;
}
}
- 自行修改页面中的静态资源路径
4.2 国际化
-
需要编写国际化相关的配置文件
2. 使用ResourceBundleMessageSource管理国际化资源文件(Springboot中已经自动配置了) 3. jsp的时候使用fmt:message取出国际化内容(Springboot中使用#{})
步骤:
1. 编写国际化配置文件,抽取页面需要显示的国际化(汉化)内容
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8lbkvdH0-1591951707049)(C:\Users\JiangXinWei\Desktop\springBoot笔记\springBoot笔记\images\10.png)]
- SpringBoot自动配置好了管理国际化文件的组件
public class MessageSourceProperties {
/**
* Comma-separated list of basenames (essentially a fully-qualified classpath
* location), each following the ResourceBundle convention with relaxed support for
* slash based locations. If it doesn't contain a package qualifier (such as
* "org.mypackage"), it will be resolved from the classpath root.
*/
private String basename = "messages";
// 我们的配置文件可以直接放在类路径下叫messages.properties
@Bean
public MessageSource messageSource(MessageSourceProperties properties) {
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
if (StringUtils.hasText(properties.getBasename())) {
// login login_zh_CN login_en_US
// 设置国际化资源文件的基础名(去掉语言和国家代码)
messageSource.setBasenames(StringUtils
.commaDelimitedListToStringArray(StringUtils.trimAllWhitespace(properties.getBasename())));
}
if (properties.getEncoding() != null) {
messageSource.setDefaultEncoding(properties.getEncoding().name());
}
messageSource.setFallbackToSystemLocale(properties.isFallbackToSystemLocale());
Duration cacheDuration = properties.getCacheDuration();
if (cacheDuration != null) {
messageSource.setCacheMillis(cacheDuration.toMillis());
}
messageSource.setAlwaysUseMessageFormat(properties.isAlwaysUseMessageFormat());
messageSource.setUseCodeAsDefaultMessage(properties.isUseCodeAsDefaultMessage());
return messageSource;
}
# 指定国际化资源文件
spring.messages.basename=i18n.login
- 去页面取出国际化的值:
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="">
<meta name="author" content="">
<title>Signin Template for Bootstrap</title>
<!-- Bootstrap core CSS -->
<link href="asserts/css/bootstrap.min.css" th:href="@{/webjars/bootstrap/3.3.5/css/bootstrap.css}" rel="stylesheet">
<!-- Custom styles for this template -->
<link href="asserts/css/signin.css" th:href="@{/asserts/css/signin.css}" rel="stylesheet">
</head>
<body class="text-center">
<form class="form-signin" action="dashboard.html">
<img class="mb-4" src="asserts/img/bootstrap-solid.svg" th:src="@{/asserts/img/bootstrap-solid.svg}" alt="" width="72" height="72">
<h1 class="h3 mb-3 font-weight-normal" th:text="#{login.tip}">Please sign in</h1>
<label class="sr-only">Username</label>
<input type="text" class="form-control" placeholder="Username" th:placeholder="#{login.username}" required="" autofocus="">
<label class="sr-only">Password</label>
<input type="password" class="form-control" placeholder="Password" th:placeholder="#{login.password}" required="">
<div class="checkbox mb-3">
<label>
<input type="checkbox" value="remember-me" /> [[ #{login.remember} ]]
</label>
</div>
<button class="btn btn-lg btn-primary btn-block" type="submit" th:text="#{login.sign}">Sign in</button>
<p class="mt-5 mb-3 text-muted">© 2019-2020</p>
<a class="btn btn-sm">中文</a>
<a class="btn btn-sm">English</a>
</form>
</body>
</html>
效果:
当前只能根据浏览器的语言选项来切换国际化
我们想要的是点击链接进行切换
首先要了解Springboot到底是怎么处理国际化资源的
原理:
Locale (区域信息对象); LocaleResolver(获取区域信息对象的)
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(prefix = "spring.mvc", name = "locale")
public LocaleResolver localeResolver() {
if (this.mvcProperties.getLocaleResolver() == WebMvcProperties.LocaleResolver.FIXED) {
return new FixedLocaleResolver(this.mvcProperties.getLocale());
}
AcceptHeaderLocaleResolver localeResolver = new AcceptHeaderLocaleResolver();
localeResolver.setDefaultLocale(this.mvcProperties.getLocale());
return localeResolver;
}
// 默认的就是根据请求头带来的区域信息获取Locale进行国际化
- 点击链接切换国际化
package com.gm.common;
import org.apache.logging.log4j.util.Strings;
import org.springframework.web.servlet.LocaleResolver;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Locale;
public class MyLocaleResolver implements LocaleResolver {
@Override
public Locale resolveLocale(HttpServletRequest request) {
String i = request.getParameter("i");
Locale locale = Locale.getDefault();
if (!Strings.isEmpty(i)) {
// i = en_US
String[] s = i.split("_");
locale = new Locale(s[0],s[1]);
}
return locale;
}
@Override
public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) {
}
}
@Bean
public LocaleResolver localeResolver(){
return new MyLocaleResolver();
}
4.3 登录
模拟登录
package com.gm.controller;
import org.apache.logging.log4j.util.Strings;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
@Controller
public class LoginController {
// @PutMapping
// @DeleteMapping
// @GetMapping
// @RequestMapping(value = "/user/login",method = RequestMethod.POST)
@PostMapping("/user/login")
public String doLogin(@RequestParam("username") String username,
@RequestParam("password") String password,
Model model){
if (!Strings.isEmpty(username) && "000000".equals(password)){
// 登录成功
return "dashboard";
} else {
// 登录失败
model.addAttribute("msg","用户名密码错误!");
return "login";
}
}
}
4.4 添加拦截器
package com.gm.common;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MyInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
Object user = request.getSession().getAttribute("user");
if (user == null) {
// 未登录,返回登录页面
request.setAttribute("msg","没有操作权限,请先登录!");
request.getRequestDispatcher("/login.html").forward(request,response);
return false;
}else {
// 成功登录,进行放行
return true;
}
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**")
.excludePathPatterns("/login.html","/","/user/login")
.excludePathPatterns("/asserts/**")
.excludePathPatterns("/webjars/**");
}
4.5 CRUD - 员工列表实现
RestFul web service
Restful风格:
RUI : /资源名称/资源标识 HTTP请求方式区分对资源的CRUD操作
普通CRUD | RestFul CRUD | |
---|---|---|
添加 | addEmp | Emp - POST |
删除 | delEmp?id=xxx | Emp/{id} - DELETE |
查询 | findEmps?id=xxx | Emp/{id} - GET |
修改 | updEmp?id=xxx | Emp/{id} - PUT |
当前的项目需求: 满足RestFul 风格
功能需求 | 请求的URI | 请求方式 |
---|---|---|
查询所有员工 | Emps | GET |
点击到增加页面 | Emp | GET |
添加 | Emp | POST |
单查询 | Emp/{id} | GET |
修改前的查询 | Emp/{id} | GET |
修改 | Emp | PUT |
删除 | Emp/{id} | DELETE |
- 公共页面的提取
<div th:fragment="copy">
© 2011 The Good Thymes Virtual Grocery
</div>
<div th:insert="~{footer :: copy}"></div>
footer : 公共片段存在的页面
~{templatename::selector}: 模板名:: 选择器
~{templatename::fragmentname} :模板名:: 片段名
th:insert 效果:把公共页面插入到了获取时包裹的标签中
引入公共页面的方式
th:insert : 将整个公共片段插入到声明引入的元素中
th:replace:将声明的元素替换为公共片段
th:includ:将被引入的片段的内容包含进这个标签中
<footer th:fragment="copy">
© 2011 The Good Thymes Virtual Grocery
</footer>
<div th:insert="footer :: copy"></div>
<div th:replace="footer :: copy"></div>
<div th:include="footer :: copy"></div>
<div>
<footer>
© 2011 The Good Thymes Virtual Grocery
</footer>
</div>
<footer>
© 2011 The Good Thymes Virtual Grocery
</footer>
<div>
© 2011 The Good Thymes Virtual Grocery
</div>
引入片段的时候传入参数
<!-- 引入头部公共页面 -->
<div th:replace="common/header :: header"></div>
<div class="container-fluid">
<div class="row">
<!-- 引入左侧 -->
<div th:replace="common/header :: #sidebar(active='Emps')"></div>
查询:
@Controller
public class EmployeeController {
@Autowired
private EmployeeDao employeeDao;
// @DeleteMapping
// @PutMapping
// @PostMapping
// @RequestMapping(value = "/Emps",method = RequestMethod.POST)
@GetMapping("/Emps")
public String findAllEmps(Model model){
Collection<Employee> all = employeeDao.getAll();
model.addAttribute("emps",all);
return "emp/list";
}
}
list.html
<table class="table table-striped table-sm">
<thead>
<tr>
<th>id</th>
<th>姓名</th>
<th>邮箱</th>
<th>性别</th>
<th>部门</th>
<th>生日</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr th:each="emp:${emps}">
<td th:text="${emp.id}"></td>
<td th:text="${emp.lastName}"></td>
<td th:text="${emp.email}"></td>
<td th:text="${emp.gender==0}?'男':'女'"></td>
<td th:text="${emp.department.getDepartmentName()}"></td>
<td th:text="${#dates.format(emp.birth, 'yyyy-MM-dd HH:mm')}"></td>
<td>
<button class="btn btn-sm btn-info">编辑</button>
<button class="btn btn-sm btn-danger">删除</button>
</td>
</tr>
</tbody>
</table>s
4.6 员工添加
// 点击添加来到添加页面
@GetMapping("/emp")
public String toAddPage(Model model){
// 点击查询按钮,应当查出来所有的部门信息,以供选择
Collection<Department> departments = this.departmentDao.getDepartments();
model.addAttribute("depms",departments);
return "emp/add";
}
// 添加操作,Springboot web阶段使用的还是SpringMVC,会帮我们自动进行封装
@PostMapping("/emp")
public String addEmp(Employee employee){
// System.out.println("得到的员工信息为:" + employee );
this.employeeDao.save(employee);
return "redirect:/Emps";
}
4.7 员工修改
<form action="/emp" th:action="@{/emp}" method="post">
<!-- 怎么进行发生PUT请求修改数据
1. SpringMVC中配置 HiddenHttpMethodFilter;
2. 页面中有一个表单
3. 在表单中需要Input,name属性=_method;值就是我们指定的请求方式
-->
<input type="hidden" name="_method" value="put" th:if="${emp!=null}">
<input type="hidden" name="id" th:if="${emp!=null}" th:value="${emp.id}">
<div class="form-group">
<label>LastName</label>
<input type="text" name="lastName" class="form-control" placeholder="zhangsan" th:value="${emp!=null}?${emp.lastName}">
</div>
<div class="form-group">
<label>Email</label>
<input type="email" name="email" class="form-control" placeholder="zhangsan@dd.com" th:value="${emp!=null}?${emp.email}">
</div>
<div class="form-group">
<label>Gender</label><br/>
<div class="form-check form-check-inline">
<input class="form-check-input" type="radio" name="gender" th:checked="${emp!=null}?${emp.gender==1}" value="1">
<label class="form-check-label">男</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="radio" name="gender" th:checked="${emp!=null}?${emp.gender==0}" value="0">
<label class="form-check-label">女</label>
</div>
</div>
<div class="form-group">
<label>department</label>
<select class="form-control" name="department.id">
<option th:each="depm:${depms}" th:value="${depm.id}" th:selected="${emp!=null}?${depm.id == emp.department.id}" th:text="${depm.departmentName}">部门</option>
</select>
</div>
<div class="form-group">
<label>Birth</label>
<input type="text" name="birth" class="form-control" placeholder="zhangsan" th:value="${emp!=null}?${#dates.format(emp.birth, 'yyyy-MM-dd')}">
</div>
<button type="submit" class="btn btn-primary" th:text="${emp!=null}?'修改':'添加'">添加</button>
</form>
// 点击编辑到页面,显示员工信息
@GetMapping("/emp/{id}")
public String toUpdPage(@PathVariable("id") Integer id,Model model){
Employee employee = this.employeeDao.get(id);
model.addAttribute("emp",employee);
// 点击查询按钮,应当查出来所有的部门信息,以供选择
Collection<Department> departments = this.departmentDao.getDepartments();
model.addAttribute("depms",departments);
return "emp/add";
}
// 修改
@PutMapping("/emp")
public String updEmp(Employee employee){
this.employeeDao.save(employee);
return "redirect:/Emps";
}
4.8 员工删除
方法、
<button th:attr="action_uri=@{/emp/}+${emp.id}" class="btn btn-sm btn-danger delete" >删除</button>
<form id="deleteEmpForm" method="post">
<input type="hidden" name="_method" value="delete">
</form>
<script>
$(".delete").click(function () {
$("#deleteEmpForm").attr("action",$(this).attr("action_uri")).submit();
return false;
});
</script>
4.9 退出登录
@GetMapping("/user/logout")
public String logOut(HttpSession session){
// session.invalidate();
session.removeAttribute("user");
return "login";
}
5. 配置嵌入式Servlet容器
Springboot 默认使用Tomcat作为嵌入式的servlet容器
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rmQTxXJk-1591951707050)(C:\Users\Administrator\Desktop\springBoot笔记\springBoot笔记\images\12.png)]
问题?
5.1.如何去修改servlet容器相关的配置:
1. 修改个server有关的配置(serverProperties)
server.port=8081
server.servlet.context-path=/crud
server.tomcat.uri-encoding=utf-8
- 自定义WebServerFactoryCustomizer
// serverProperties 在底层最终会实现WebServerFactoryCustomizer
@Bean
public WebServerFactoryCustomizer<ConfigurableServletWebServerFactory> myServer(){
return new WebServerFactoryCustomizer<ConfigurableServletWebServerFactory>() {
@Override
public void customize(ConfigurableServletWebServerFactory factory) {
factory.setPort(8083);
}
};
}
5.2 注册servlet中的三大组件: Servlet、Filter、Listener
自定义Servlet: **ServletRegistrationBean**
@Bean
public ServletRegistrationBean<MyServlet> myServlet(){
ServletRegistrationBean<MyServlet> myServlet = new ServletRegistrationBean<>(new MyServlet(),"/MyServlet");
return myServlet;
}
自定义Filter: FilterRegistrationBean
@Bean
public FilterRegistrationBean<MyFilter> myFilter(){
FilterRegistrationBean<MyFilter> myFilter = new FilterRegistrationBean<>();
myFilter.setFilter(new MyFilter());
myFilter.setUrlPatterns(Arrays.asList("/hello","/MyFilter"));
return myFilter;
}
自定义 Listener: ServletListenerRegistrationBean
@Bean
public ServletListenerRegistrationBean<MyListener> myListener(){
ServletListenerRegistrationBean<MyListener> myListener = new ServletListenerRegistrationBean<>();
myListener.setListener(new MyListener());
return myListener;
}
SpringBoot 在自动配置SpringMVC时,自动注册了SpringMVC中的前端控制器:DispatcherServlet
@Bean(name = DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME)
@ConditionalOnBean(value = DispatcherServlet.class, name = DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)
public DispatcherServletRegistrationBean dispatcherServletRegistration(DispatcherServlet dispatcherServlet,
WebMvcProperties webMvcProperties, ObjectProvider<MultipartConfigElement> multipartConfig) {
DispatcherServletRegistrationBean registration = new DispatcherServletRegistrationBean(dispatcherServlet,
webMvcProperties.getServlet().getPath());
/*
默认拦截: / 所有请求,包括静态资源,但是会放行.jsp请求
/* 所有请求,包括静态资源,同时拦截JSp请求
*.do
可以通过spring.mvc.servlet.path来修改SpringMVC前端控制器默认拦截的路径
*/
registration.setName(DEFAULT_DISPATCHER_SERVLET_BEAN_NAME);
registration.setLoadOnStartup(webMvcProperties.getServlet().getLoadOnStartup());
multipartConfig.ifAvailable(registration::setMultipartConfig);
return registration;
}