简化spring应用的框架
整个Spring技术栈的大整合
j2ee开发的一站式解决方案
2014 马丁·福勒(martin fowler)
微服务: 架构风格
一个应用应该是一组小型微服务,可以通过HTTP的方式去进行访问
单体应用: ALL IN ONE
微服务:每一个功能元素最终都是一个独立运行或者升级的软件单元
环境:
- 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
一个需求:
浏览器发送hello 请求,服务器接收并处理,响应Hello World字符串
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.3.0.RELEASEversion>
parent>
他的父项目是
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-dependenciesartifactId>
<version>2.3.0.RELEASEversion>
parent>
他是真正用来管理Spring boot 应用的所有依赖版本
SpringBoot的版本仲裁中心
我们以后导入依赖的时候都不需要写版本(没有写在dependencies中的需要单独声明版本号)
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
spring-boot-starter == web ==
spring-boot-starter :springboot 的场景启动器,帮我们导入web模块正常运行所需要的组件
SpringBoot把所有的功能场景都提取出来,做成一个个starter(启动器),我们只需要在项目里导入相关的starter相关的场景就会把所有相关的依赖都会导入进来。要用什么功能就达到入什么场景的启动器
/**
* @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制定的值,把这些值作为自动配置加入到容器。然后自动配置类就会生效。
- idea都有一个快速构建springboot项目的向导器Spring Initializr,可以使用它来创建项目,只需要勾选你想要的场景模块,就会自动下载所需要的依赖, 注: 创建过程中必须要联网 。
- 出程序以及生产好了,只需要根据我们的逻辑需求去编写
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>8081port>
server>
.yml
server:
port: 8081
K: (空格)V 类似于键值对的写法,注意: 冒号后面要跟空格才能写V(值)
用空格来控制层级关系,只要根据左对齐的方式,同一列的数据都同一层级
server:
port: 8081
servlet:
context-path: /hello
K: (空格)V 类似于键值对的写法,注意: 冒号后面要跟空格才能写V(值)
K: V : 直接键值对写值
注: - 如果说值是字符串也不需要去给引号
在什么情况下可以加引号?
双引号 " " : 如果说包含特殊字符,那么引不会转义特殊字符的含义,会直接根据特殊字符的本身含义展示出来
user:
name: "laowang \n gebi" ----- name: laowang 换行 gebi**
单引号 ’ ':如果说包含特殊字符,那么单引号会转义特殊字符的含义,会直接把特殊字符作为一个字符串进行输出
user:
name: ‘laowang \n gebi’ ----- name: laowang \n gebi**
K: V : 在下一行去根据键值对的方式写属性个值
user:
username: xiaoming
age: 18
gender: 男
如果说想把对象或者Map在一行内写出来
user: {
username: xiaoming,age: 18,gender: 男}
在下一行使用 - (空格)值,来表示一个元素
sub:
- JAVA
- Python
- HTML
如果说想把组或者list、set在一行内写出来
sub: java,python,html
配置文件:
.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.bootgroupId>
<artifactId>spring-boot-configuration-processorartifactId>
<optional>trueoptional>
dependency>
.properties中的的参数取值乱码怎么办?
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ED1rug3C-1591951707038)(C:\Users\JiangXinWei\Desktop\第二十九天\springBoot笔记\images\1.png)]
@ConfigurationProperties | @Value | |
---|---|---|
取值 | 可以一次取出全部参数进行绑定 | 一个一个取 |
SpEL | 不支持 | 支持 |
松散绑定 | 支持 | 不支持 |
JSR303数据校验 | 支持 | 不支持 |
复杂类型绑定 | 支持 | 不支持 |
提问:
这两个直接的应用场景分别是什么?
如果说你只是在处理业务时,需要用到配置问价中某一个参数的值,就用@Value
如果说你专门做实体绑定配置文件的实例,这是用@ConfigurationProperties
数据校验
/**
* @ConfigurationProperties 标注在一个类上,告诉Springboot讲本类中所有的属性和指定的配置文件中的参数进行绑定
* 注: ConfigurationProperties 属于容器中的注解,
* prefix = "user" 指定获取的是配置文件中哪一个下面所有参数
*/
@Component
@ConfigurationProperties(prefix = "user")
@Validated
public class User {
/**
*
*
*/
// @Value("${user.user-name}")
private String userName;
// @Value("#{2*5*8}")
private int age;
private String gender;
// @Value("false")
private boolean isgirl;
// @Value("${maps}")
@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 必须要标注在一个配置类上
<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的配置类
*
*
**/
@Configuration
public class BootConfig {
// 把返回值加载到容器中
@Bean
public UserService userService(){
System.out.println("正在给spring容器注入组件");
return new UserService();
}
}
${
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
我们在主配置文件编写的时候,文件名可以是 :
application.properties/.yml
application-{profiles}.properties/.yml
当项目中同时存在默认配置文件喝profiles文件时,
默认使用 application.properties/.yml
server:
port: 8084
spring:
profiles:
active: prov
---
server:
port: 8085
spring:
profiles: devs
---
server:
port: 8086
spring:
profiles: prov
1. 在配置文件中激活 spring.profiles.active: prov
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(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
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
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指定的默认属性
配置文件中到底能写什么?怎么写?自动配置的原理;
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类都是容器中的一个组件,都加到容器中,同时就是用他们来自做自动配置。
@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中获取的,同时,这些类里面的每一个属性有和配置文件进行绑定
总结:
1, springboot启动时会加载大量的配置类;
2,我们在写之前,看一下我们需要的东西有没有是springboot默认写好的自动配置类
3,如果有,只需要看一下自动配置类中到底 配置了哪些组件;
4, 给容器中自动配置类添加组件的时候。会从从对应的properties中获取的,就可在配置文件中制定这些属性的值
@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)
使用Springboot:
自动配置原理?
Springboot到底给我们配置了什么? 能不能修改? 能不能修改默认配置?。。。。
xxxAutoConfiguration 帮我们给容器中自动配置组件
xxxproperties 配置类来封装配置文件的内容
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
<dependency>
<groupId>org.webjarsgroupId>
<artifactId>jqueryartifactId>
<version>3.3.1version>
dependency>
"classpath:/META-INF/resources/",
"classpath:/resources/",
"classpath:/static/",
"classpath:/public/"
"/" 当前项目的根路径
http://localhost:8080/style.js 会从静态资源路径去找style.js
http://localhost:8080/
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)]
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-thymeleafartifactId>
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就可以自动进行渲染。
使用:
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Titletitle>
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>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(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: *{...} : 选择表达式,和${}在功能上是一样的
补充:
Name: Sebastian.
Surname: Pepper.
Nationality: Saturn.
Message Expressions: #{...} : 获取国际化内容
Link URL Expressions: @{...} : 定义URL
view
view
view
Fragment Expressions: ~{...} : 片段引用表达式
...
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: _
https://docs.spring.io/spring-boot/docs/2.3.0.RELEASE/reference/htmlsingle/#boot-features-developing-web-applications
Spring Boot 自动配置好了SprinMVC
以下是SpringBoot对SpringMVC的默认配置:WebMvcAutoConfiguration :
org\springframework\boot\autoconfigure\web\servlet\WebMvcAutoConfiguration.java
Inclusion of ContentNegotiatingViewResolver
and BeanNameViewResolver
beans.
ContentNegotiatingViewResolver
: 组合所有的视图解析器Support for serving static resources, including support for WebJars (covered later in this document)). :
自动注册了 of Converter
, GenericConverter
, and Formatter
beans.
Converter
:转换器;public String Hello(User user){}; 类型转换器Converter
Formatter
: 格式化器: 2020.05.30 === DateSupport for HttpMessageConverters
(covered later in this document).
HttpMessageConverters
: SpringMVC用来转换Http请求的请求和相应的;User—JSONAutomatic 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
.
<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. 我们的配置类也会生效
@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中最基本的功能
模式:
1. SpringBoot在自动配置很多组件的时候,先看容器中有没有用户自己配置的(@Bean,@Component),如果有就用用户自己配置的,如果没有才会进行自动配置。如果说有一些组件可以配置多个(ViewResolver)会将用户配置和自己默认的配置组合起来。
2. SpringBoot中会有很多的XXXXConfigurer帮我们去自定义扩展配置
3. SpringBoot中会有很多的XXXXCustomizer帮我们去定制配置
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;
}
}
需要编写国际化相关的配置文件
2. 使用ResourceBundleMessageSource管理国际化资源文件(Springboot中已经自动配置了)
3. jsp的时候使用fmt:message取出国际化内容(Springboot中使用#{})
步骤:
1. 编写国际化配置文件,抽取页面需要显示的国际化(汉化)内容
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8lbkvdH0-1591951707049)(C:\Users\JiangXinWei\Desktop\springBoot笔记\springBoot笔记\images\10.png)]
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
<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 Bootstraptitle>
<link href="asserts/css/bootstrap.min.css" th:href="@{/webjars/bootstrap/3.3.5/css/bootstrap.css}" rel="stylesheet">
<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 inh1>
<label class="sr-only">Usernamelabel>
<input type="text" class="form-control" placeholder="Username" th:placeholder="#{login.username}" required="" autofocus="">
<label class="sr-only">Passwordlabel>
<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 inbutton>
<p class="mt-5 mb-3 text-muted">© 2019-2020p>
<a class="btn btn-sm">中文a>
<a class="btn btn-sm">Englisha>
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();
}
模拟登录
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";
}
}
}
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/**");
}
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>idth>
<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
// 点击添加来到添加页面
@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";
}
<form action="/emp" th:action="@{/emp}" method="post">
<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>LastNamelabel>
<input type="text" name="lastName" class="form-control" placeholder="zhangsan" th:value="${emp!=null}?${emp.lastName}">
div>
<div class="form-group">
<label>Emaillabel>
<input type="email" name="email" class="form-control" placeholder="[email protected]" th:value="${emp!=null}?${emp.email}">
div>
<div class="form-group">
<label>Genderlabel><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>departmentlabel>
<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>Birthlabel>
<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";
}
方法、
<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>
@GetMapping("/user/logout")
public String logOut(HttpSession session){
// session.invalidate();
session.removeAttribute("user");
return "login";
}
Springboot 默认使用Tomcat作为嵌入式的servlet容器
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rmQTxXJk-1591951707050)(C:\Users\Administrator\Desktop\springBoot笔记\springBoot笔记\images\12.png)]
问题?
1. 修改个server有关的配置(serverProperties)
server.port=8081
server.servlet.context-path=/crud
server.tomcat.uri-encoding=utf-8
// serverProperties 在底层最终会实现WebServerFactoryCustomizer
@Bean
public WebServerFactoryCustomizer<ConfigurableServletWebServerFactory> myServer(){
return new WebServerFactoryCustomizer<ConfigurableServletWebServerFactory>() {
@Override
public void customize(ConfigurableServletWebServerFactory factory) {
factory.setPort(8083);
}
};
}
自定义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;
}