简化Spring应用开发的一个框架;
整个Spring技术栈的一个大整合;
J2EE开发的一站式解决方案;
2014 , martin fowler
微服务:是一种架构风格
一个用用应该是一组小型服务; 可以通过HTTP的方式进行互通;
每一个功能元素最终都是一个可独立替换和独立升级的软件单元;
在maven的setting.xml中添加
1.8
true
1.8
1.8
1.8
1.8
设置maven环境
实现一个功能:
浏览器发送hello请求,服务器接收请求并处理,响应Hello World字符串;
org.springframework.boot
spring-boot-starter-parent
1.5.9.RELEASE
org.springframework.boot
spring-boot-starter-web
/**
* @SpringBootApplication来标注一个主程序类
*/
@SpringBootApplication
public class HelloWorldMainApplication {
public static void main(String[] args) {
//Spring应用启动起来
SpringApplication.run(HelloWorldMainApplication.class,args);
}
}
@Controller
public class HelloController {
@ResponseBody
@RequestMapping("/hello")
public String hello(){
return "Hello World!";
}
}
org.springframework.boot
spring-boot-maven-plugin
将这个应用打成jar包,直接使用java -jar的命令进行执行。
1、父项目
org.springframework.boot
spring-boot-starter-parent
1.5.9.RELEASE
他的父项目是:
org.springframework.boot
spring-boot-dependencies
1.5.9.RELEASE
../../spring-boot-dependencies
他来真正管理Spring Boot应用里面的所有依赖版本;
Spring Boot的版本仲裁中心;
以后我们导入依赖默认是不需要写版本; ( 没有在dependencies里面管理依赖自然需要声明版本号 )
2、导入的依赖
org.springframework.boot
spring-boot-starter-web
spring-boot-starter-web:
spring-boot-starter : spring-boot的场景启动器 ; 帮我们导入了web模块正常运行所依赖的组件;
Spring Boot将所有的功能场景都抽取出来,做成一个个的starters( 启动器 ),只需要在项目里面引入,这些starter相关场景的所有依赖都会导入进来。要用什么功能就导入什么场景的启动器。
@SpringBootApplication: Spring Boot 应用标注在某个类上说明这个类是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:Spring Boot的配置类;
标注在某个类上,表示这是一个Spring Boot的配置类;
@Configuration:配置类上来标注这个注解:
配置类 ------- 配置文件;配置类也是容器中的一个组件;@Component
@EnableAutoConfiguration:开启自动配置功能;
以前我们需要配置的东西,Spring Boot帮我们自动配置;@EnableAutoConfiguration告诉SpringBoot开启自动配置功能;这样自动配置才能生效;
@AutoConfigurationPackage
@Import({EnableAutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
@AutoConfigurationPackage:自动配置包
@Import(AutoConfigurationPackages.Registrar.class):
Spring的底层注解@Import,给容器中导入一个组件;导入的组件由AutoConfigurationPackages.Registrar.class
将主配置类(@SpringBootApplication标注的类)的所在包及下面所有子包里面的所有组件扫描到Spring容器;
@Import(EnableAutoConfigurationImportSelector.class);
给容器中导入组件?
EnableAutoConfigurationImportSelector:导入哪些组件的选择器;
会给容器中导入非常多的自动配置类(xxxAutoConfiguration);就是给容器中导入这个场景需要的所有组件,并配置好这些组件;
有了自动配置类,免去了我们手动编写配置注入功能组件等的工作;
SpringFactoricesLoader.loadFactoryNames(EnableAutoConfiguration.class,classLoader);
Spring Boot在启动的时候从类路径的META-INF/spring.factories中获取EnableAutoConfiguration指定的值,将这些值作为自动配置类导入到容器中,自动配置类就生效,帮我们进行自动配置工作;以前我们需要自己配置的东西,自动配置类都帮我们配置;
J2EE的整体整合解决方案和自动配置都在 spring-boot-autoconfigure-1.5.9.RELEASE.jar;
IDE都支持使用Spring的项目创建向导快速创建一个Spring Boot项目;
选择我们需要的模块;向导会联网创建Spring Boot项目;
默认生成的Spring Boot项目;
主程序已经生成好了,我们只需要我们自己编写逻辑
resources文件夹中目录结构
static:保存所有的静态资源;js css images;
templates:保存所有的模版页面;(Spring Boot默认jar包使用嵌入式的Tomcat,默认不支持JSP页面);可以使用模版引擎(freemarker、thymeleaf)
application.properties:Spring Boot应用的配置文件;
Spring Boot使用一个全局的配置文件,配置文件名是固定的;
application.properties
application.yml
配置文件的使用:修改Spring Boot自动配置的默认值;Spring Boot在底层都给我们自动配置好;
YAML( YAML Ain't Markup Language)
YAML A Markup Language:是一个标记语言
YAML isn't Markup Language:不是一个标记语言
标记语言:
以前的配置文件;大多都使用的是 xxx.xml 文件;
YAML:以数据为中心,比json、xml等更适合做配置文件;
YAML:配置实例
server:
port:8081
XML:配置实例
8081
k:(空格)v:表示一对键值对(空格必须有);
以空格的缩进来控制层级关系;只要是左对齐的一列数据,都是一个层级的。
server:
port: 8081
path: /hello
属性和值也是大小写敏感的;
k: v:字面直接来写;
字符串默认不用加上单引号或者双引号;
"":双引号;不会转义字符串里面的特殊字符;特殊字符会作为本身想表示的意思
name:"zhangsan \n lisi":输出;zhangsan 换行 lisi
'':单引号;会转义特殊字符,特殊字符最终只是一个普通的字符串数据
name:'zhangsan \n lisi':输出;zhangsan \n lisi
k: v:在下一行来写对象的属性和值的关系;注意缩进
对象还是k: v的方式
friends:
lastName: zhangsan
age: 20
行内写法:
friends: {lastName: zhangsan,age: 18}
用- 值表示数组中的一个元素
pets
- cat
- dog
- pig
行内写法:
pets: [cat,dog,pig]
配置文件:
person:
lastName: zhangsan
age: 21
boss: false
birth: 2017/12/12
maps:
k1: v1
k2: v2
lists:
- lisi
- zhaoliu
- wangwu
dog:
name: xiaogou
age: 2
javabean:
/**
* 将配置文件中配置的每一个属性的值,映射到这个组件中
* @ConfigurationProperties : 告诉SpringBoot 将本类中的所有属性和配置文件中相关的配置进行绑定;
* prefix = "person" : 配置文件中哪个下面的所有属性进行一一映射
*
* 只有这个组件是容器中的组件,才能使用容器提供的@ConfigurationProperties功能;
*/
@Component
@ConfigurationProperties(prefix = "person")
public class Person {
private String lastName;
private Integer age;
private Boolean boss;
private Date birth;
private Map maps;
private List
我们可以导入配置文件处理器,以后编写配置文件就会有提示了:
org.springframework.boot
spring-boot-configuration-processor
true
@ConfigurationProperties | @Value | |
---|---|---|
功能 | 批量注入配置文件中的属性 | 一个个的指定 |
松散绑定(松散语法) | 支持 | 不支持 |
SqEL | 不支持 | 支持 |
JSR303数据校验 | 支持 | 不支持 |
复杂类型封装 | 支持 | 不支持 |
配置文件不管是yml还是properties都能获取到值;
如果说,我们只是在某个业务逻辑中获取一下配置文件中的某项值,使用@Value
@RestController
public class HelloController {
@Value("#{11 * 2}")
private String name;
@RequestMapping("sayHello")
public String sayHello(){
return "hello" + name;
}
如果说,我们专门编写了一个javaBean来和配置文件进行映射;使用@ConfigurationProperties
@Component
@ConfigurationProperties(prefix = "person")
@Validated
public class Person {
/**
*
*
*
*/
//lastName必须是邮箱格式的。
@Email
private String lastName;
@Value("#{11*2}")
private Integer age;
@Value("true")
private Boolean boss;
private Date birth;
private Map maps;
private List
4、@PropertySource&@ImportResource
@PropertySource(value = {"classpath:xxx.properties"}):加载指定的配置文件
/**
* 将配置文件中配置的每一个属性的值,映射到这个组件中
* @ConfigurationProperties : 告诉SpringBoot 将本类中的所有属性和配置文件中相关的配置进行绑定;
* prefix = "person" : 配置文件中哪个下面的所有属性进行一一映射
*
* 只有这个组件是容器中的组件,才能使用容器提供的@ConfigurationProperties功能;
* @ConfigurationProperties(prefix = "person")默认从全局配置文件中获取值
*/
@PropertySource(value = {"classpath:person.properties"})
@Component
@ConfigurationProperties(prefix = "person")
@Validated
public class Person {
/**
*
*
*
*/
private String lastName;
@Value("#{11*2}")
private Integer age;
@Value("true")
private Boolean boss;
private Date birth;
private Map maps;
private List
@ImportResource:导入Spring的配置文件,让配置文件里面的内容生效;
Spring Boot里面没有Spring的配置文件,我们自己编写的设置文件,也不能自动识别;
想让Spring的配置文件生效,加载进来;@ImportResource标注在一个配置类上
@ImportResource(locations = {"classpath:beans.xml"})
导入Spring的配置文件让其生效
不来编写Spring的配置文件
SpringBoot推荐给容器中添加组件的方式;推荐使用全注解的方式;
1、配置类====Spring配置文件
2、使用@Bean给容器中添加组件
/**
* @Configuration指明当前类是一个配置类;就是来代替之前的Spring配置文件
*/
@Configuration
public class MyAppConfig {
/**
* @Bean将方法的返回值添加到容器中;容器中这个组件默认的id就是方法的方法名
*
*/
@Bean
public HelloService helloService(){
return new HelloService();
}
}
${random.value}、${random.int}、${random.long}
${random.int(10)}、${random.int[1024,65536]}
person.age=${random.int}
person.birth=2017/12/12
person.boss=false
person.dog.name=dog_${person.hello:hello}
person.dog.age=15
person.last-name=张三${random.uuid}
person.lists=a,b,c
person.maps.k1=v1
person.maps.k2=v2
我们在主配置文件编写的时候,文件名可以是 application-{profile}.properties/yml
morning使用application.properties
server:
port: 80
person1:
lastName: zhangsan
age: 21
boss: false
birth: 2017/12/12
maps:
k1: v1
k2: v2
lists:
- lisi
- zhaoliu
- wangwu
dog:
name: xiaogou
age: 2
#激活配置环境 dev
spring:
profiles:
active: dev
#下面的 --- 是文档块
---
#文档块2
server:
port: 8081
spring:
profiles: dev
---
#文档块3
server:
port: 8082
spring:
profiles: product #指定这个文档块属于哪个环境
1、在配置文件中指定 spring.profiles.active=dev
2、命令行:
--spring.profiles.active=dev
在启动jar包的时候使用命令来指定启动软件所使用的的配置环境。
java -jar spring-boot-02-config-0.0.1-SNAPSHOT.jar --spring.profiles.active=dev
SpringBoot启动会扫描以下位置的application.properties或者application.yml文件作为SpringBoot的默认配置文件
-file:./config/
-file:./
-classpath:/config/
-classpath:/
优先级由高到低,高优先级的配置会覆盖低优先级的配置;
SpringBoot会从这四个位置全部加载主配置文件;互补配置;
我们还可以通过spring.config.location来改变默认的配置文件位置
项目打包以后,我们可以使用命令行参数的形式,启动项目的时候来指定配置文件的新位置;指定配置文件和默认加载的这些配置文件共同起作用形成互补配置;
SpringBoot也可以从以下位置加载配置;优先级从高到低;高优先级的配置覆盖低优先级的配置,所有的配置会形成互补配置
1、命令行参数
java -jar spring-boot-02-config-0.0.1-SNAPSHOT.jar --server.port=8085 --server.context-path=/abc
多个配置用空格分开;--配置项=配置值
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指定的默认属性
所有支持的配置加载来源;参考官方文档
配置文件到底能写什么?怎么写?自动配置原理;
配置文件能配置的属性;参照官方文档
1)、SpringBoot启动的时候加载主配置类,开启了自动配置功能@EnableAutoConfiguration
2)、@EnableAutoConfiguration作用:
利用EnableAutoConfigurationImportSelector给容器中导入一些组件?
可以查看selectImports()方法的内容;
List
SpringFactoriesLoader.loadFactoryNames();
扫描所有jar包类路径下的 META-INF/spring.factories
把扫描到的这些文件的内容包装成Properties对象;
从properties中获取到EnableAutoConfiguration.class类(类名)对应的值,然后把他们添加在容器中
将 类路径下 META-INF/spring.factories 里面配置的所有EnableAutoConfiguration的值加入到了容器中;
# 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.cloud.CloudAutoConfiguration,\
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\
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.CassandraRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.ldap.LdapDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.ldap.LdapRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration,\
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.redis.RedisAutoConfiguration,\
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.jest.JestAutoConfiguration,\
org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration,\
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.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.flyway.FlywayAutoConfiguration,\
org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration,\
org.springframework.boot.autoconfigure.jooq.JooqAutoConfiguration,\
org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration,\
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.mobile.DeviceResolverAutoConfiguration,\
org.springframework.boot.autoconfigure.mobile.DeviceDelegatingViewResolverAutoConfiguration,\
org.springframework.boot.autoconfigure.mobile.SitePreferenceAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration,\
org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration,\
org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\
org.springframework.boot.autoconfigure.reactor.ReactorAutoConfiguration,\
org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.SecurityFilterAutoConfiguration,\
org.springframework.boot.autoconfigure.security.FallbackWebSecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.OAuth2AutoConfiguration,\
org.springframework.boot.autoconfigure.sendgrid.SendGridAutoConfiguration,\
org.springframework.boot.autoconfigure.session.SessionAutoConfiguration,\
org.springframework.boot.autoconfigure.social.SocialWebAutoConfiguration,\
org.springframework.boot.autoconfigure.social.FacebookAutoConfiguration,\
org.springframework.boot.autoconfigure.social.LinkedInAutoConfiguration,\
org.springframework.boot.autoconfigure.social.TwitterAutoConfiguration,\
org.springframework.boot.autoconfigure.solr.SolrAutoConfiguration,\
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.DispatcherServletAutoConfiguration,\
org.springframework.boot.autoconfigure.web.EmbeddedServletContainerAutoConfiguration,\
org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.web.HttpEncodingAutoConfiguration,\
org.springframework.boot.autoconfigure.web.HttpMessageConvertersAutoConfiguration,\
org.springframework.boot.autoconfigure.web.MultipartAutoConfiguration,\
org.springframework.boot.autoconfigure.web.ServerPropertiesAutoConfiguration,\
org.springframework.boot.autoconfigure.web.WebClientAutoConfiguration,\
org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.WebSocketAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.WebSocketMessagingAutoConfiguration,\
org.springframework.boot.autoconfigure.webservices.WebServicesAutoConfiguration
每一个这样的xxxAutoConfiguration类都是容器中的一个组件,都加入到容器中;用他们来做自动配置;
3)、每一个自动配置类进行自动配置功能;
4)、以HttpEncodingAutoConfiguration为例来解释自动配置原理;
@Configuration //表示这是一个配置类,和以前写的配置文件文件一样,也可以给容器中添加组件
@EnableConfigurationProperties({HttpEncodingProperties.class})//启动指定类的ConfigurationProperties功能;将配置文件中对应的值和HttpEncodingProperties绑定起来;并把HttpEncodingProperties加入到ioc容器中
@ConditionalOnWebApplication //Spring底层@Conditional注解,根据不同的条件,如果满足指定的条件,整个配置类里面的配置才会生效。 判断当前应用是否是web应用,如果是,当前配置类生效
@ConditionalOnClass({CharacterEncodingFilter.class})//判断当前项目有没有这个类CharacterEncodingFilter;SpringMvc中进行乱码解决的过滤器;
@ConditionalOnProperty(
prefix = "spring.http.encoding",
value = {"enabled"},
matchIfMissing = true
)//判断配置文件中是否存在某个配置 spring.http.encoding.enabled;如果不存在,判断也是成立的
//即使我们配置文件中不配置spring.http.encoding.enabled=true,也是默认生效的;
public class HttpEncodingAutoConfiguration {
//他已经和SpringBoot的配置文件映射了
private final HttpEncodingProperties properties;
//只用一个有残构造器的情况下,HttpEncodingProperties参数的值就会从容器中拿
public HttpEncodingAutoConfiguration(HttpEncodingProperties properties) {
this.properties = properties;
}
@Bean //给容器中添加一个组件,这个组件的某些值需要从properties中获取
@ConditionalOnMissingBean({CharacterEncodingFilter.class})//判断容器中没有这个组件
public CharacterEncodingFilter characterEncodingFilter() {
CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();
filter.setEncoding(this.properties.getCharset().name());
filter.setForceRequestEncoding(this.properties.shouldForce(Type.REQUEST));
filter.setForceResponseEncoding(this.properties.shouldForce(Type.RESPONSE));
return filter;
}
}
根据当前不同的条件判断,决定这个配置类是否生效?
一旦这个配置类乘次奥;这个配置类就会给容器中添加各种组件;这些组件的属性是从对应的properties类中获取的,这些类里面的每一个属性又是和配置文件绑定的;
5)、所有在配置文件中能配置的属性都是在xxxxPropertirs类中封装着;配置文件能配置什么就可以参照某个功能对应的这个属性类
@ConfigurationProperties(
prefix = "spring.http.encoding"
) //从配置文件中获取指定的值和bean的属性进行绑定
public class HttpEncodingProperties {
public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
6)、SpringBoot的精髓:
1、SpringBoot启动会加载大量的自动配置类;
2、我们看我们需要的功能有没有SpringBoot默认写好的自动配置类;
3、我们再来看这个自动配置类中到低配置了哪些组件;(只要我们要用的在组件有,我们就不需要再来配置了)
4、给容器中自动配置类添加组件的时候,会从properties类中获取某些属性。我们就可以在配置文件中指定这些属性的值;
xxxxAutoConfiguration:自动配置类;
给容器中添加组件
xxxxProperties:封装配置文件中相关属性;
1、@Conditional派生注解(Spring注解版原生的@Conditional作用)
作用:必须是@Conditional指定的条件成立,才给容器中添加组件,配置类里面的所有内容才生效;
自动配置类必须在一定条件下才能生效;
怎么才能知道有哪些自动配置类生效了?
我们可以通过穷 debug=true属性;来让控制台答应自动配置报告,这样我们就可以很方便的知道哪些自动配置类生效;
=========================
AUTO-CONFIGURATION REPORT
=========================
Positive matches: //匹配到生效的类
-----------------
DispatcherServletAutoConfiguration matched:
- @ConditionalOnClass found required class 'org.springframework.web.servlet.DispatcherServlet'; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)
- @ConditionalOnWebApplication (required) found 'session' scope (OnWebApplicationCondition)
DispatcherServletAutoConfiguration.DispatcherServletConfiguration matched:
- @ConditionalOnClass found required class 'javax.servlet.ServletRegistration'; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)
- Default DispatcherServlet did not find dispatcher servlet beans (DispatcherServletAutoConfiguration.DefaultDispatcherServletCondition)
Negative matches: //没有匹配生效的类
-----------------
ActiveMQAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required classes 'javax.jms.ConnectionFactory', 'org.apache.activemq.ActiveMQConnectionFactory' (OnClassCondition)
AopAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required classes 'org.aspectj.lang.annotation.Aspect', 'org.aspectj.lang.reflect.Advice' (OnClassCondition)
日志的出现:
小张:开发了一个大型系统;
1、System.out.println("");将关键数据打印在控制台;去掉?卸载一个文件?
2、框架来记录系统的一些运行时信息;日志框架;zhanglogging.jar;
3、高大上的几个功能?异步模式?自动归档?xxxx?zhanglogging-good.jar?
4、将以前框架卸下来?换上新的框架,重新修改之前相关的API;zhanglogging-prefect.jar;
5、模仿JDBC---数据驱动;
写了一个统一的接口层;日志门面(日志的一个抽象层);logging-abstract.jar;
给项目中导入具体的日志实现就行了;我们之前的日志框架都是实现的抽象层;
市面上的日志框架:
JUL、JCL、Jboss-logging、logback、log4j、log4j2、slf4j....
日志门面(日志的抽象层) | 日志实现 |
---|---|
JCL(Jakarta Commons Logging) SLF4j(Simple Logging Facade for Java) jboss-logging |
Log4j JUL(java.util.logging) Log4j2 Logback |
左边选一个门面(抽象层)、右边来选一个实现;
日志门面:SLF4J;
日志实现:Logback
Spring Boot:底层是Spring框架,Spring框架默认是用JCL;
SpringBoot选用SLF4j和logback
以后开发的时候,日志记录方法的调用,不应该来直接调用日志的实现类,而是调用日志抽象层里面的方法;
给系统里面导入slf4j的jar包和logback的实现jar
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class HelloWorld {
public static void main(String[] args) {
Logger logger = LoggerFactory.getLogger(HelloWorld.class);
logger.info("Hello World");
}
}
图示:
每一个日志的实现框架都有自己的配置文件。使用slf4j以后,配置文件还是做成日志实现框架自己的配置文件;
a(slf4j+logback) :Spring(commons-logging)、Hibernate ( jboss-logging )、MyBatis、xxxx
统一日志记录,即使是别的框架也和我们一起统一使用slf4j进行输出?
如何让系统中所有的日志都统一到slf4j;
1、将系统中其他日志框架先排除出去;
2、用中间包来替换原有的日志框架;
3、我们导入slf4j其他的实现;
org.springframework.boot
spring-boot-starter-web
SpringBoot使用它做日志功能;
org.springframework.boot
spring-boot-starter-logging
2.1.4.RELEASE
compile
底层依赖关系
总结:
1)、SpringBoot底层也是使用slf4j+logback的方式进行日志记录
2)、SpringBoot也把其他的日志都替换成了slf4j日志
3)、中间替换包。
4)、如果我们要引入其他框架,一定要把这个框架的默认日志依赖移除掉。
SpringBoot能自动适配所有的日志,而且底层使用slf4j+logback的方式记录日志,引入其他框架的时候,只需要把这个框架依赖的日志框架排除掉;
1、默认配置
SpringBoot默认帮我们配置好了日志;
//记录器
final Logger logger = LoggerFactory.getLogger(getClass());
@Test
public void contextLoads() {
// System.out.println();
//日志的级别
//由低到高 trace
SpringBoot修改日志的默认配置,在application.properties中配置:
#在控制台输出的日志的格式
#日志输出格式:
# %d表示日期时间
# %thread表示线程名
# %-5level:级别从左显示5个字符宽度
# %logger[50] 表示logger名字最长50个字符,否则按照据点分割
# %msg:日志消息
# %n是换行符
logging.pattern.console=%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n
#指定文件中日志输出的格式
logging.pattern.file=%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n
2、指定配置
给类路径下放上每个日志框架自己的配置文件即可;SpringBoot就不使用他默认的配置了
Logging System | Customization |
---|---|
Logback | logback-spring.xml , logback-spring.groovy , logback.xml or logback.groovy |
Log4j2 | log4j2-spring.xml or log4j2.xml |
JDK (Java Util Logging) | logging.properties |
logback.xml:直接就被日志框架识别了
logback-spring.xml:日志框架就不直接加载了,由springboot解析日志配置,可以使用SpringBoot的高级Profile功能
可以指定某段配置只在某个环境下生效
使用SpringBoot;
1)、创建SpringBoot应用,选中我们需要的模块;
2)、SpringBoot已经默认将这些场景配置好了;只需要在配置文件中指定少量配置就可以运行起来;
3)、自己编写业务代码;
自动配置原理?
这个场景SpringBoot帮我们配置了什么?能不能修改?能修改哪些配置?能不能扩展?。。。。
xxxxAutoConfiguration:帮我们给容器中自动配置组件;
xxxxProperties:配置类来封装配置文件的内容;
public void addResourceHandlers(ResourceHandlerRegistry registry) {
if (!this.resourceProperties.isAddMappings()) {
logger.debug("Default resource handling disabled");
} else {
Duration cachePeriod = this.resourceProperties.getCache().getPeriod();
CacheControl cacheControl = this.resourceProperties.getCache().getCachecontrol().toHttpCacheControl();
if (!registry.hasMappingForPattern("/webjars/**")) {
this.customizeResourceHandlerRegistration(registry.addResourceHandler(new String[]{"/webjars/**"}).addResourceLocations(new String[]{"classpath:/META-INF/resources/webjars/"}).setCachePeriod(this.getSeconds(cachePeriod)).setCacheControl(cacheControl));
}
String staticPathPattern = this.mvcProperties.getStaticPathPattern();
if (!registry.hasMappingForPattern(staticPathPattern)) {
this.customizeResourceHandlerRegistration(registry.addResourceHandler(new String[]{staticPathPattern}).addResourceLocations(getResourceLocations(this.resourceProperties.getStaticLocations())).setCachePeriod(this.getSeconds(cachePeriod)).setCacheControl(cacheControl));
}
}
}
1)、所有/webjars/** 的请求,都去 classpath:/META-INF/resources/webjars/下面找资源;
webjars:以jar包的方式引用静态资源
https://www.webjars.org/
以前的静态资源要自己下载好,然后放在项目中,现在可以通过maven引用的方式使用。
在访问的时候只需要写webjars下面资源的名称即可
org.webjars
jquery
3.3.1
localhost:8080/webjars/jquery/3.3.1/jquery.js
2)、"/**"访问当前项目的任何资源;(静态资源的文件夹)
"classpath:/META-INF/resources/"
"classpath:/resources/"
"classpath:/static/"
"classpath:/public/"
"/":当前项目的根路径
静态资源放在这些文件夹下,都能够被访问到。
localhost:8080/abc === 去静态资源文件夹里面找abc
3)、欢迎页;静态资源文件夹下的所有index.html页面,被"/**"映射;
localhost:8080/ ==== 找index页面
4)、所有的**/favicon.ico都是在静态资源文件下找;
JSP、Velocity、Freemarker、Thymeleaf
SpringBoot推荐Thymeleaf;
语法更简单,功能更强大;
org.springframework.boot
spring-boot-starter-thymeleaf
@ConfigurationProperties(
prefix = "spring.thymeleaf"
)
public class ThymeleafProperties {
private static final Charset DEFAULT_ENCODING;
public static final String DEFAULT_PREFIX = "classpath:/templates/";
public static final String DEFAULT_SUFFIX = ".html";
private boolean checkTemplate = true;
private boolean checkTemplateLocation = true;
private String prefix = "classpath:/templates/";
private String suffix = ".html";
private String mode = "HTML";
只要我们把HTML页面放在classpath:/templates/路径下,thymeleaf就能自动渲染;
使用:
1、导入thymeleaf的名称空间
2、使用thymeleaf语法
Title
成功!
1)、th:text:改变当前元素里面的文本内容;
th:任意html属性;来替换原生属性的值
2)、表达式
Simple expressions:(表达式语法)
Variable Expressions: ${...} 获取变量值;
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.
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
Page 20 of 106
#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: *{...} 变量的选择表达式
Message Expressions: #{...} 获取国际化内容
Link URL Expressions: @{...} 定义URL
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)
编写一个配置类(@Configuration),是WebMvcConfigurationSupport(旧版本是WebMvcConfigurerAdapter)类型;不能标注@EnableWebMvc;如果标注了@EnableWebMvc,SpringBoot对SpringMVC的自动配置会全部失效(所有配置需要自己手动来配)
//使用WebMvcConfigurerAdapter可以来扩展SpringMvc的功能
//@EnableWebMvc
@Configuration
public class MyMvcConfig extends WebMvcConfigurerAdapter {
//方法一
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("login");
registry.addViewController("/login.html").setViewName("login");
registry.addViewController("/login").setViewName("login");
}
//方法二
//所有的WebMvcConfigurerAdapter组件都会一起起作用
@Bean
public WebMvcConfigurerAdapter webMvcConfigurerAdapter(){
WebMvcConfigurerAdapter webMvcConfigurerAdapter = new WebMvcConfigurerAdapter(){
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("login");
registry.addViewController("/login.html").setViewName("login");
registry.addViewController("/login").setViewName("login");
}
};
return webMvcConfigurerAdapter;
}
}
1、静态资源都放在resources/static/路径下 引用的时候模版引擎会自动去找
2、html页面中引入的方式(引入webjars)
3、html页面中引入自定义的静态文件
static下的静态资源由模版引擎去解析 所以这里的路径前面不用写static
以前的SpringMVC的做法:
1)、编写国际化配置文件;
2)、使用ResourceBundleMessageSource管理国际化资源文件
3)、在页面使用fmt:message取出国际化内容
现在的SpringBoot的做法:
1)、编写国际化配置文件,抽取页面需要显示的国际化消息
2)、SpringBoot自动配置好了管理国际化资源文件的组件
@ConfigurationProperties(
prefix = "spring.messages"
)
public class MessageSourceAutoConfiguration {
//我们的配置文件可以直接放在类路径下叫messages.properties;
private String basename = "messages";
@Bean
public MessageSource messageSource() {
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
if (StringUtils.hasText(this.basename)) {
//设置国际化资源文件的基础名(去掉语言国家代码)
messageSource.setBasenames(StringUtils.commaDelimitedListToStringArray(StringUtils.trimAllWhitespace(this.basename)));
}
if (this.encoding != null) {
messageSource.setDefaultEncoding(this.encoding.name());
}
messageSource.setFallbackToSystemLocale(this.fallbackToSystemLocale);
messageSource.setCacheSeconds(this.cacheSeconds);
messageSource.setAlwaysUseMessageFormat(this.alwaysUseMessageFormat);
return messageSource;
}
//我们的配置文件可以直接放在类路径下叫messages.properties;然后不需要再做任何配置;
如果不是上面的情况,就需要指定基础名:
在配置文件中添加:
3)、去页面获取国际化的值:
访问页面 可能会出现乱码
乱码原因前面提到过,是因为properties中的内容最终都要转换成ASCII码,需要自己设置
File --> Settings --> 搜索 file encodings 改变设置(修改当前项目的)
如果想要修改全局的配置,应用到所有项目,File --> Other settings --> settings for new projects..
国际化原理:
国际化Locale(区域信息对象);LocaleResolver(获取区域信息对象)
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(
prefix = "spring.mvc",
name = {"locale"}
)
public LocaleResolver localeResolver() {
if (this.mvcProperties.getLocaleResolver() == org.springframework.boot.autoconfigure.web.servlet.WebMvcProperties.LocaleResolver.FIXED) {
return new FixedLocaleResolver(this.mvcProperties.getLocale());
} else {
AcceptHeaderLocaleResolver localeResolver = new AcceptHeaderLocaleResolver();
localeResolver.setDefaultLocale(this.mvcProperties.getLocale());
return localeResolver;
}
}
默认的区域信息就是根据请求头带来的区域信息获取Locale进行国际化
4)、点击链接切换国际化
自己编写LocaleResolver
/**
* 可以在连接上携带区域信息
*/
public class MyLocaleResolver implements LocaleResolver {
@Override
public Locale resolveLocale(HttpServletRequest httpServletRequest) {
String lang = httpServletRequest.getParameter("lang");
Locale locale = Locale.getDefault();
if(!StringUtils.isEmpty(lang)){
String[] split = lang.split("_");
locale = new Locale(split[0],split[1]);
}
return locale;
}
@Override
public void setLocale(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Locale locale) {
}
}
在springMVC配置类中注入自己定义的LocaleResolver
/**
* 注入自定义的MyLocaleResolver
* @return MyLocaleResolver
*/
@Bean
public LocaleResolver localeResolver(){
return new MyLocaleResolver();
}
开发期间模版引擎页面修改以后,要实时生效
1)、禁用模版引擎的缓存
#禁用缓存
spring:
thymeleaf:
cache: false
2)、页面修改完成以后按ctrl+F9:重新编译;
登录错误信息的显示
1)、自定义一个拦截器
public class LoginHandlerInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
final Object loginedUser = httpServletRequest.getSession().getAttribute("loginedUser");
if(loginedUser == null){
//未登录,返回到登录页面
httpServletRequest.setAttribute("msg","您还未登录,请先登录");
httpServletRequest.getRequestDispatcher("/login.html").forward(httpServletRequest,httpServletResponse);
return false;
}else {
//已登录,放行请求
return true;
}
}
@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {}
@Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {}
}
2)、将自定义的拦截器添加到WebMvcConfigurerAdapter组件中
/**
* 添加过滤器
* @param registry
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
//静态资源:*.css *.js
//SpringBoot已经做好了静态资源映射,不需要考虑静态资源
registry.addInterceptor(new LoginHandlerInterceptor())
.addPathPatterns("/**")
.excludePathPatterns("/","/login","/login.html","/user/login");
}
实验要求:
1)、RestfulCRUD:CRUD满足Rest风格;
URI:/资源名称/资源标识 HTTP请求方式区分对资源CRUD操作
普通CRUD(uri来区分操作) | RestfulCRUD | |
---|---|---|
查询 | getEmp | emp----GET |
添加 | addEmp?xxx | emp----POST |
修改 | updateEmp?xxx&xxx | emp/{id}----PUT |
删除 | deleteEmp?id=1 | emp/{id}----DELETE |
2)、试验的请求架构;
试验功能 | 请求URI | 请求方式 |
---|---|---|
查询所有员工 | emps | GET |
查询某个员工(来到修改页面) | emp/1 | GET |
来到添加页面 | emp | GET |
添加员工 | emp | POST |
来到修改页面(查出员工进行信息回显) | emp/1 | GET |
修改员工 | emp | PUT |
删除员工 | emp/1 | DELETE |
3)、员工列表:
1.抽取公共片段
© 2011 The Good Thymes Virtual Grocery
2.引入公共片段
...
或
...
3、默认效果:
insert的功能片段在div标签中
如果使用th:insert等属性进行引入,可以不用写~{};
如果是[[~{}]];[(~{})] 就必须写
三种引入功能片段的th属性:
th:insert:将公共片段整个插入到声明 引入的元素中th:replace:将声明引入的元素替换为公共片段th:include:将被引入的片段的内容包含进这个标签中
引入方式:
引入效果
© 2011 The Good Thymes Virtual Grocery
成功实例:
菜单一
引入模版的时候传参
默认效果:
1)、浏览器,返回一个默认的错误页面
浏览器发送请求的请求头:
2)、如果是其他客户端(安卓手机...)访问、默认响应一个json数据
其他客户端发送请求的请求头:
原理:
可以参照ErrorMvcAutoConfiguration;错误处理的自动配置;
给容器中添加了以下组件
1、DefaultErrorAttributes:
2、BasicErrorController:处理默认/error请求
@Controller
@RequestMapping({"${server.error.path:${error.path:/error}}"})
public class BasicErrorController extends AbstractErrorController {
//产生html类型的数据 浏览器发送的请求来到这个方法处理
@RequestMapping(
produces = {"text/html"}
)
public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) {
HttpStatus status = this.getStatus(request);
Map model = Collections.unmodifiableMap(this.getErrorAttributes(request, this.isIncludeStackTrace(request, MediaType.TEXT_HTML)));
response.setStatus(status.value());
//去哪个页面作为错误页面;包含页面地址和页面内容
ModelAndView modelAndView = this.resolveErrorView(request, response, status, model);
return modelAndView != null ? modelAndView : new ModelAndView("error", model);
}
//生成json数据 其他客户端发送的请求来到这个方法处理
@RequestMapping
@ResponseBody
public ResponseEntity
3、ErrorPageCustomizer:
@Value("${error.path:/error}")
private String path = "/error"; //系统出现错误以后来到error请求进行处理;(类似于web.xml注册的错误页面规则)
4、DefaultErrorViewResolver:
public ModelAndView resolveErrorView(HttpServletRequest request, HttpStatus status, Map model) {
ModelAndView modelAndView = this.resolve(String.valueOf(status), model);
if (modelAndView == null && SERIES_VIEWS.containsKey(status.series())) {
modelAndView = this.resolve((String)SERIES_VIEWS.get(status.series()), model);
}
return modelAndView;
}
private ModelAndView resolve(String viewName, Map model) {
//默认SpringBoot可以去找到一个页面; error/404
String errorViewName = "error/" + viewName;
//模版引擎可以解析这个页面地址 就用模版引擎
TemplateAvailabilityProvider provider = this.templateAvailabilityProviders.getProvider(errorViewName, this.applicationContext);
//模版引擎可用的情况下返回到errorViewName对应的页面
//模版引擎不可用,就在静态资源文件夹下找errorViewName对应的页面 error/404
return provider != null ? new ModelAndView(errorViewName, model) : this.resolveResource(errorViewName, model);
}
步骤:
一旦系统出现4xx或者5xx之类的错误;ErrorPageCustomizer就会生效(定制错误的响应规则);就会来到/error请求;就会被BasicErrorController处理;
1)、响应页面;去哪个页面是由DefaultErrorViewResolver解析得到的;
1)、如何定制错误的页面;
有模版引擎的情况下:error/状态码【将错误页面命名为 错误状态码.html放在模版引擎error文件夹下】
我们可以使用4xx和5xx作为错误页面的文件名来匹配这种类型的所有错误,精确优先(优先寻找精确的状态码.html)
页面能获取到的信息:
timestamp:时间戳
status:状态码
error:错误提示
exception:异常对象
message:异常消息
errors:JSR303数据校验的错误都在这里
如果没有模版引擎:(模版引擎找不到这个错误页面),静态资源文件下找
以上都没有错误页面:就默认来到SpringBoot默认的错误提示页面
2)、如何定制错误的json数据;
1)、自定义异常处理&返回定制json数据;
@ControllerAdvice
public class MyExceptionHandler {
@ResponseBody
@ExceptionHandler(Exception.class)
public Map handleException(Exception e){
Map map = new HashMap();
map.put("code","user.notexist");
map.put("message",e.getMessage());
return map;
}
}
//没有自适应效果。。。
2)、转发到/error进行自适应响应效果处理
@ExceptionHandler(Exception.class)
public String handleException(Exception e, HttpServletRequest request){
Map map = new HashMap();
//传入我们自己的错误状态码 4xx 5xx 否则就不会进入定制错误页面的解析流程
request.setAttribute("javax.servlet.error.status_code",400);
map.put("code","user.notexist");
map.put("message",e.getMessage());
//转发到/error
return "forward:/error";
}
3)、将我们的定制数据携带出去;
出现错误以后,回来到/error请求,会被BasicErrorController处理,响应出去可以获取的数据是由getErrorAttributes()得到的(是AbstractErrorController(ErrorController)规定的方法);
1、完全编写一个ErrorController的实现类【或者是编写AbstractErrorController的子类】,放在容器中;
2、页面上能用的数据,或者是json返回能用的数据,都是通过errorAttributes.getErrorAttributes得到的;
容器中DefaultErrorAttributes默认进行数据处理的;
自定义的ErrorAttributes
//给容器中加入我们自己定义的ErrorAttributes
@Component
public class MyErrorAttributes extends DefaultErrorAttributes {
//返回值的map就是页面和json能获取的所有字段
@Override
public Map getErrorAttributes(RequestAttributes requestAttributes, boolean includeStackTrace) {
Map errorAttributes = super.getErrorAttributes(requestAttributes, includeStackTrace);
errorAttributes.put("错误信息","错误信息的内容");
//我们异常处理器携带的数据
Map ext = (Map) requestAttributes.getAttribute("ext", 0);
errorAttributes.put("ext",ext);
return errorAttributes;
}
}
最终的效果:响应是自适应的,可以通过定制ErrorAttributes改变需要返回的内容;
SpringBoot默认使用Tomcat作为嵌入式的Servlet容器;
问题?
1、修改和server有关的配置(ServerProperties【也是EmbeddedServletContainerCustomizer】)
server:
context-path: /crud
port: 8080
tomcat:
uri-encoding: UTF-8
#通用的Servlet容器的设置 server.xxx
#Tomcat的设置 server.tomcat.xxx
2、编写一个EmbeddedServletContainerCustomizer:嵌入式的Servlet容器的定制器;来修改Servlet其他的一些配置
@Bean
public EmbeddedServletContainerCustomizer embeddedServletContainerCustomizer(){
return new EmbeddedServletContainerCustomizer() {
//定制嵌入式的Servlet容器相关的规则
@Override
public void customize(ConfigurableEmbeddedServletContainer configurableEmbeddedServletContainer) {
configurableEmbeddedServletContainer.setPort(8080);
//...
}
};
}
由于SpringBoot默认是以jar包的方式启动嵌入式的Servlet容器来启东SpringBoot的web应用,没有web.xml文件。
注册三大组件用以下方式:
ServletRegistrationBean:
编写一个Servlet
public class MyServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.getWriter().append("hello my servlet");
}
}
//注册Servlet
@Bean
public ServletRegistrationBean servletRegistrationBean(){
ServletRegistrationBean servletRegistrationBean =
new ServletRegistrationBean(new MyServlet(),"/myServlet");
return servletRegistrationBean;
}
FilterRegistrationBean
public class MyFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException { }
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("my filter process");
filterChain.doFilter(servletRequest,servletResponse);
}
@Override
public void destroy() { }
}
//注册filter
@Bean
public FilterRegistrationBean filterRegistrationBean(){
FilterRegistrationBean filterRegistrationBean =
new FilterRegistrationBean();
filterRegistrationBean.setFilter(new MyFilter());
filterRegistrationBean.setUrlPatterns(Arrays.asList("/myServlet","/hello"));
return filterRegistrationBean;
}
ServletListenerRegistrationBean
public class MyListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
System.out.println("contextInitialized...web 应用启动了...");
}
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
System.out.println("contextDestroyed...web应用销毁了...");
}
}
//注册listener
@Bean
public ServletListenerRegistrationBean servletListenerRegistrationBean(){
ServletListenerRegistrationBean servletListenerRegistrationBean =
new ServletListenerRegistrationBean(new MyListener());
return servletListenerRegistrationBean;
}
2)、SpringBoot能不能支持其他的Servlet容器;
Tomcat(默认使用)
Undertow(不支持JSP,并发性能好)
Jetty(适合长连接,入聊天程序)
切换至jetty
org.springframework.boot
spring-boot-starter-web
spring-boot-starter-tomcat
org.springframework.boot
spring-boot-starter-jetty
org.springframework.boot
切换至Undertow
org.springframework.boot
spring-boot-starter-web
spring-boot-starter-tomcat
org.springframework.boot
spring-boot-starter-undertow
org.springframework.boot
嵌入式Servlet容器:
优点:简单、便携;
缺点:默认不支持JSP、优化定制比较复杂(使用定制器,自己编写嵌入式Servlet容器的创建工厂);
【跳过】
Docker是一个开源的应用引擎;基于Go语言并遵从Apache2.0协议开源。
Docker可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化。
容器是完全使用沙箱机制,相互之间不会有任何接口,更重要的是容器性能开销极低。
Docker支持将软件编译成一个镜像;然后在镜像中各种软件做好配置,将镜像发布出去,其他使用者可以直接使用这个镜像。**运行中的这个镜像称为容器,容器启动时非常快速的。**类似windows里面的ghost操作系统,安装好后很么都有了
Docker主机(HOST):安装了Docker程序的机器(Docker直接安装在操作系统之上)
Docker客户端(Client):连接docker主机进行操作;
Docker仓库(Registry):用来保存各种打包好的软件镜像;
Docker镜像(Images):软件打包好的镜像;放在docker仓库中;
Docket容器(Container):镜像启动后的实例称为一个容器;容器是独立运行的一个或一组应用;
使用Docker的步骤:
1)、安装Docker;
2)、去Docker仓库找到这个软件对应的镜像;
3)、使用Docker运行这个镜像,这个镜像就会生成一个Docker容器;
4)、对容器的启动停止就是对软件的启动停止;
具体笔记博客Docker分类中;博客地址
spring:
datasource:
username: yxh_mysql
password: a
url: jdbc:mysql://47.110.156.54:3306/travelers
driver-class-name: com.mysql.jdbc.Driver
配置效果:
默认使用的是org.apache.tomcat.jdbc.pool.DataSource数据源
数据源的相关配置都在DataSourceProperties里面;
引入数据源:
com.alibaba
druid
1.1.10
application.yml:
spring:
datasource:
username: yxh_mysql
password: a
url: jdbc:mysql://47.110.156.54:3306/travelers
driver-class-name: com.mysql.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
initialSize: 5
minIdle: 5
maxActive: 20
maxWait: 60000
timeBetweenEvictionRunsMillis: 60000
minEvictableIdleTimeMillis: 300000
validationQuery: SELECT 1 FROM DUAL
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
poolPreparedStatements: true
filters: stat,wall,log4j
maxPoolPreparedStatementPerConnectionSize: 20
useGlobalDataSourceStat: true
connectionProperties: druid.stat.mergeSql=true;druid.stat.showSqlMillis=500
配置类:
@Configuration
public class DruidConfig {
@ConfigurationProperties(prefix = "spring.datasource")
@Bean
public DataSource druid(){
return new DruidDataSource();
}
//配置Druid的监控
//1、配置一个管理后台的Servlet
@Bean
public ServletRegistrationBean statViewServlet(){
ServletRegistrationBean bean = new ServletRegistrationBean(new StatViewServlet(), "/druid/*");
Map map = new HashMap();
map.put("loginUsername","admin");
map.put("loginPassword","123456");
map.put("allow",""); //默认就是允许所有访问
map.put("deny","127.0.0.1"); //不让这个IP地址访问
bean.setInitParameters(map);
return bean;
}
//2、配置一个监控的filter
@Bean
public FilterRegistrationBean webStatFilter(){
FilterRegistrationBean bean = new FilterRegistrationBean();
bean.setFilter(new WebStatFilter());
Map map = new HashMap();
map.put("exclusions","*.js,*.css,/druid/*"); //不能拦截的请求
bean.setInitParameters(map);
bean.setUrlPatterns(Arrays.asList("/*"));
return bean;
}
}
访问http://localhost:8080/druid/login.html进入mysql监控网页
引入数据源:
com.alibaba
druid
1.1.10
application.yml:
spring:
datasource:
username: yxh_mysql
password: a
url: jdbc:mysql://47.110.156.54:3306/travelers
driver-class-name: com.mysql.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
initialSize: 5
minIdle: 5
maxActive: 20
maxWait: 60000
timeBetweenEvictionRunsMillis: 60000
minEvictableIdleTimeMillis: 300000
validationQuery: SELECT 1 FROM DUAL
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
poolPreparedStatements: true
filters: stat,wall,log4j
maxPoolPreparedStatementPerConnectionSize: 20
useGlobalDataSourceStat: true
connectionProperties: druid.stat.mergeSql=true;druid.stat.showSqlMillis=500
配置类:
@Configuration
public class DruidConfig {
@ConfigurationProperties(prefix = "spring.datasource")
@Bean
public DataSource druid(){
return new DruidDataSource();
}
//配置Druid的监控
//1、配置一个管理后台的Servlet
@Bean
public ServletRegistrationBean statViewServlet(){
ServletRegistrationBean bean = new ServletRegistrationBean(new StatViewServlet(), "/druid/*");
Map map = new HashMap();
map.put("loginUsername","admin");
map.put("loginPassword","123456");
map.put("allow",""); //默认就是允许所有访问
map.put("deny","127.0.0.1"); //不让这个IP地址访问
bean.setInitParameters(map);
return bean;
}
//2、配置一个监控的filter
@Bean
public FilterRegistrationBean webStatFilter(){
FilterRegistrationBean bean = new FilterRegistrationBean();
bean.setFilter(new WebStatFilter());
Map map = new HashMap();
map.put("exclusions","*.js,*.css,/druid/*"); //不能拦截的请求
bean.setInitParameters(map);
bean.setUrlPatterns(Arrays.asList("/*"));
return bean;
}
}
//指定这是一个操作数据库的mapper
@Mapper
public interface UserMapper{
@Select("select * from user where id=#{id}")
public User getUserById(Integer id);
@Delete("delete from user where id=#{id}")
public int deleteUserById(Integer id);
//返回主键
@Options(useGenerateKeys = true,keyProperty = "id")
@Insert("insert into user(username) values(#{username})")
public int insertUser(User user);
@Update("update user set username=#{username} where id=#{id}")
public int updateUser(User user);
}
问题:
数据库中的下划线命名法和javabean中的驼峰命名法的适配:
解决:
编写配置类,自定义MyBatis的配置:
//javabean与数据库字段对应
@MapperScan("com.yc.springboot.mapper") //扫描所有的mapper
@Configuration
public class MyBatisConfig {
@Bean
public ConfigurationCustomizer configurationCustomizer(){
return new ConfigurationCustomizer() {
@Override
public void customize(org.apache.ibatis.session.Configuration configuration) {
configuration.setMapUnderscoreToCamelCase(true);
}
};
}
}
MyBatis官方文档
1)、mybatis的全局配置文件:文件名:
2)、mapper.xml配置
3)、全局配置文件application.yml文件中添加配置:
mybatis:
config-location: classpath:mybatis/mybatis-config.xml
mapper-locations: classpath:mybatis/mapper/*.xml
JPA:ORM(Object Relational Mapping);
//使用JPA注解配置映射关系
@Entity //告诉JPA这是一个实体类
@Table(name="users") //@Table指定和那个数据表对应 如果省略默认表名就是users
@Data
public class Users {
@Id //标注这是主键
@GeneratedValue(strategy = GenerationType.IDENTITY) //自增主键
private Integer userId;
@Column(name="user_username",length = 50) //这是和数据表对应的一个列
private String userUsername;
@Column(name="user_password") //省略默认列名就是属性名
private String userPassword;
}
//JpaRepository JpaRepository<对象,主键类型>
public interface UsersRepository extends JpaRepository {
}
spring:
datasource:
url: jdbc:mysql://47.110.156.54:3306/travelers
username: yxh_mysql
password: a
driver-class-name: com.mysql.jdbc.Driver
jpa:
hibernate:
#更新或者创建数据表结构
ddl-auto: update
#在控制台可以看到sql
show-sql: true
@Autowired
private UsersRepository usersRepository;
@Test
public void contextLoads() {
List all = usersRepository.findAll();
System.out.println(all);
}