内容概要
SpringBoot入门
SpringBoot配置
SpringBoot与日志
SpringBoot与Web开发
SpringBoot与Docker
SpringBoot与数据访问
SpringBoot启动配置原理
SpringBoot自定义Starters
SpringBoot与缓存
SpringBoot与消息
SpringBoot与检索
SpringBoot与任务
SpringBoot与安全
SpringBoot与分布式
SpringBoot与开发热部署
SpringBoot与监控管理
第一章 SpringBoot入门 1.1 SpringBoot简介 特点:约定大于配置;去繁从简;
背景:
J2EE笨重的开发;
繁多的配置;
低下的效率;
复杂的部署;
第三方技术集成难度大;
解决方案:
SpringBoot:一站式J2EE的解决方案;
SpringCloud:分布式整体解决方案;
优点:
快速创建可独立运行的Spring项目并与主流框架集成;
starters自动依赖管理及版本控制;
使用嵌入的Servlet容器,应用无需打包;
大量的自动配置,简化开发,也可修改默认值;
无需配置XML,无代码生成,开箱即用;
准生产环境的运行时应用监控;
是对Spring技术栈的一个整合。
1.2 微服务 单体应用: 开发,测试,部署简单;
微服务:功能拆分,灵活配置,通信协作。
SpringBoot官网 > 微服务文档
1.3 开发环境配置
JDK版本;
maven版本;
开发工具选择;
框架版本选择;
1.4 第一个应用:HelloWorld
创建一个Maven项目;
导入SpringBoot相关依赖;
编写主程序,启动SpringBoot应用;
1 2 3 4 5 6 @SpringBootApplication public class MainApp { public static void main (String[] args) { SpringApplication.run(MainApp.class, args); } }
编写业务逻辑,服务;
运行主程序测试;
打包jar包:
1 2 3 4 5 6 7 8 <build > <plugins > <plugin > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-maven-plugin</artifactId > </plugin > </plugins > </build >
运行jar包:
1.5 HelloWorld原理探究 POM文件:
父项目:
1 2 3 4 5 6 <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-web</artifactId > </dependency > 父项目:
SpringBoot的版本仲裁中心 ,导入依赖不需要写版本号。
导入的依赖:
1 2 3 4 5 6 <dependencies > <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-web</artifactId > </dependency > </dependencies >
spring-boot-starter-web:
场景启动器:帮我们导入web模块正常运行所需的依赖的组件;
将所有的功能场景抽取出来,做成启动器,只需要在项目中导入相关的starter,所有的依赖都会被导入,版本由spring-boot自动管理。
1.6 主程序类原理探究 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 package com.hello;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication public class MainApp { public static void main (String[] args) { SpringApplication.run(MainApp.class, args); } }
@SpringBootApplication标注在某个类上,指定SpringBoot的主配置类,由这个类来启动SpringBoot应用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 @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} )}
@SpringBootConfiguration:标注在某个类上,表示该类是SpringBoot的配置类。
@Configuration:配置类上标注该类。配置类也是一个组件:@Component;
@EnableAutoConfiguration:开启自动配置,
1 2 @AutoConfigurationPackage @Import({AutoConfigurationImportSelector.class})
1 2 3 @AutoConfigurationPackage:自动配置包,给容器导入一个组件,导入的组件由AutoConfigurationPackage.Registrar; 将主配置类所在的及以下所有的子包里的所有组件添加到Spring容器中。
1 2 3 @Import({Registrar.class}) public @interface AutoConfigurationPackage {}
1 2 3 @Import:给容器中导入一些组件:AutoConfigurationImportSelector:选择哪些组件导入。 给容器中导入自动配置类(xxxAutoConfiguration):给容器中导入场景需要的所有的组件并配置好这些组件。
1 2 3 4 5 protected List<String> getCandidateConfigurations (AnnotationMetadata metadata, AnnotationAttributes attributes) { List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this .getSpringFactoriesLoaderFactoryClass(), this .getBeanClassLoader()); Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you are using a custom packaging, make sure that file is correct." ); return configurations; }
SpringBoot启动的时候从类路径下META-INF/spring.factories中获取EnableAutoConfiguration指定的值,将这些值导入到Spring容器中,自动配置类生效。
需要自己指定的配置,已经由配置类自动配置好。
org/springframework/boot/spring-boot-autoconfigure/2.0.4.RELEASE/spring-boot-autoconfigure-2.0.4.RELEASE.jar!/META-INF/spring.factories
1.7 SpringBoot项目初始化器 SpringBoot项目向导:
IDEA > New Project > Spring Initializer > 项目详情 > 导入相关场景依赖。
@RestController注解:
@ResponseBody和@RequestMapping注解组合。
自动生成主程序;
/resources中目录结构:
static:保存静态资源;
templates:存所有的模板页面(使用嵌入的tomcat,不支持JSP页面,但是可以使用模板引擎);
application.properties:SpringBoot的默认配置文件。
第二章 SpringBoot配置文件 2.1 SpringBoot配置文件 SpringBoot使用全局配置文件,配置文件名是固定的。
application.properties;
application.yml。
配置文件的作用:修改SpringBoot默认配置。
YAML:不仅仅是一个标记语言,以数据为中心,比json和xml更适合做配置文件。
YAML:
2.2 YAML基本语法 key: value 表示键值对,冒号之后的空格必须有的,以空格来控制层级关系。
1 2 3 server: port: 8081 path: /hello
属性和值大小写敏感。
字面量:字符串默认不加单引号和双引号,双引号会转义特殊字符 ,单引号会转义特殊字符 。
对象(属性和值):本质是键值对。
1 2 3 student: name: 张三 age: 14
行内写法:
1 student: {name: 张三 ,age: 15 }
数组(List, Set):
用-表示数组中的一个元素。
1 2 3 4 pets: - cat - dog - pig
行内写法:
2.2.1配置文件注入 application.yml文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 server: port: 8081 person: name: 张三 age: 18 alive: true birth: 2018 /09/11 classes: - v1 - v2 map: k1: v1 k2: v2 dog: name: dog age: 4
JavaBean:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 package com.demo.po;import org.springframework.boot.context.properties.ConfigurationProperties;import org.springframework.stereotype.Component;import java.util.Date;import java.util.List;import java.util.Map;@Component @ConfigurationProperties(prefix = "person") public class Student { private String name; private Integer age; private boolean alive; private Date birth; private List<String> classes; private Map<String, Object> map; private Dog dog; @Override public String toString () { return "Student{" + "name='" + name + '\'' + ", age=" + age + ", alive=" + alive + ", birth=" + birth + ", classes=" + classes + ", map=" + map + ", dog=" + dog + '}' ; } }
可以导入配置文件处理器之后,编写配置文件有IDE智能提示。
1 2 3 4 5 <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-configuration-processor</artifactId > <optional > true</optional > </dependency >
@ConfigurationProperties(prefix = “person”)获取配置文件的值。
application.properties乱码问题:file encoding勾选将properties配置文件转换成ascii码。
配置文件的旧写法:
1 2 3 <bean class ="person" > <property name ="lastName" value ="zhagsa" /> </bean >
2.2.2 @Value注入值 1 2 3 4 5 6 7 8 9 10 11 12 public class Student { @Value("${person.name}") private String name; @Value("#{11*2}") private Integer age; @Value("true") private boolean alive; private Date birth; private List<String> classes; private Map<String, Object> map; private Dog dog; }
2.2.3 @Value和@ConfigurationProperties获取值比较:
@ConfigurationProperties
@Value
功能
批量注入配置文件中的属性
单个指定变量的值
松散绑定
支持
不支持
SpEL
不支持
支持
JSR303数据校验
支持
不支持
复杂类型封装
支持
不支持
2.2.4 @Value和@ConfigurationProperties的比较 如果只是在某个业务逻辑中需要获取一下配置文件中的值,那就用@Value;如果专门编写了Java bean和配置文件进行映射,就直接使用@ConfigurationProperties。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 package com.demo.controller;import org.springframework.beans.factory.annotation.Value;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;@RestController public class DemoController { @Value("${person.name}") private String name; @RequestMapping("/demo.do") public String sayHello () { return "Hello, " + name; } }
2.3 @PropertySource和@ImportSource @ConfigurationProperties默认从全局配置文件中获取值。
2.3.1 @PropertySource获取配置文件的值
1 2 @ConfigurationProperties(prefix = "person") @PropertySource(value = {"classpath:person.properties"})
2.3.2 @ImportSource:导入Spring配置文件,是配置文件中的配置生效
SpringBoot默认没有加载Spring配置文件,手动编写的配置文件也无法识别,想让配置文件生效,将@ImportSource标注在主配置类上。
1 2 3 4 5 6 7 <?xml version="1.0" encoding="UTF-8" ?> <beans xmlns ="http://www.springframework.org/schema/beans" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation ="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd" > <bean id ="demoService" class ="com.demo.service.DemoService" /> </beans >
1 2 3 4 5 6 7 8 @Autowired private ApplicationContext applicationContext;@Test public void demoServiceTest () { boolean hasDemoService = applicationContext.containsBean("demoService" ); System.out.println(hasDemoService); }
2.3.3 SpringBoot推荐的添加组件方式
SpringBoot推荐给容器中添加组件的方式:使用全注解,@Configuration标注配置类。
@Bean:将方法的返回值添加到容器中,组件的默认id就是方法名。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 package com.demo.config;import com.demo.service.DemoService;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;@Configuration public class AppConfig { @Bean public DemoService demoService () { System.out.println("给容器中添加组件" ); return new DemoService (); } }
2.4 配置文件占位符 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 server: port: 8081 person: name: 张三${random.value} age: ${random.int} birth: 2018 /09/11 map: k1: ${random.value} k2: v2 dog: name: ${person.hello:defau} age: 4 alive: true classes: - v1 - v2
随机数:
${random.value},${random.int},${random.long},${random.int(10)},${random.int[1,10]}
占位符获取配置之前的值,${app.name:默认值}
2.5 Profile多环境支持
profile为不同环境提供不同配置的功能。
多profile文件的方式:
在主配置文件编写的时候,文件名可以是application-{profile}.properties/application-{profile}.yml;
SpringBoot默认使用全局环境配置
激活指定profile:
1 2 3 spring: profiles: active: dev
命令行方式:
–spring.profiles.active=dev/prod
虚拟机参数:
-Dspring.profiles.active=dev/prod
yaml支持文档块的方式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 server: port: 8080 spring: profiles: active: dev --- server: port: 8083 spring: profiles: dev --- server: port: 8084 spring: profiles: prod
见下图:
2.6 配置文件加载位置 SpringBoot启动会扫描以下位置的application.properties或者application.yml文件作为SpringBoot的默认配置文件:
file:./config/
file:./
classpath:/config/
classpath:/
以上位置优先级从高到低。所有位置的配置文件都会被加载,高优先级的配置会覆盖低优先级的配置,高优先级和低优先级配置文件形成互补配置。
server.context-path=/config02 -> http://localhost:8080/config02/hello.do
还可以通过spring.config.location来改变默认的配置文件位置(项目打包后可以使用命令行参数的形式启动项目时候来指定配置文件的位置,指定的配置文件和默认加载的配置文件会形成互补配置)。
见下图:
2.7 外部配置文件加载顺序 SpringBoot也可以从以下位置加载配置文件,优先级从高到低,高优先级的配置会覆盖低优先级的配置,高低优先级的配置会形成互补配置 。
Devtools global settings properties on your home directory (~/.spring-boot-devtools.properties when devtools is active).
@TestPropertySource annotations on your tests.
@SpringBootTest#properties annotation attribute on your tests.
Command line arguments.
Properties from SPRING_APPLICATION_JSON (inline JSON embedded in an environment variable or system property).
ServletConfig init parameters.
ServletContext init parameters.
JNDI attributes from java:comp/env.
Java System properties (System.getProperties()).
OS environment variables.
A RandomValuePropertySource that has properties only in random.*.
Profile-specific application properties outside of your packaged jar (application-{profile}.properties and YAML variants).
Profile-specific application properties packaged inside your jar (application-{profile}.properties and YAML variants).
Application properties outside of your packaged jar (application.properties and YAML variants).
Application properties packaged inside your jar (application.properties and YAML variants).
@PropertySource annotations on your @Configuration classes.
Default properties (specified by setting SpringApplication.setDefaultProperties).
由jar包外向jar包内进行查找。
命令行参数(多个参数用空格分开);
java -jar xxx.jar –server.port=8081 server.context.path=/ab
优先加载带profile的配置文件。
jar包外的application-{profile}或application-{yml}或不带spring.profile的配置文件;
jar包内的application-{profile}或application-{yml}或不带spring.profile的配置文件;
再加载带不profile的配置文件。
jar包外的application-{profile}或application-{yml}或不带spring.profile的配置文件;
jar包内的application-{profile}或application-{yml}或不带spring.profile的配置文件;
@Configuration注解类上的@PropertySource;
通过SpringApplication.setDefaultProperties指定的默认属性。
详细参见SpringBoot官网:SpringBoot外部配置文件加载顺序
2.8 自动配置原理 配置文件能写什么,怎么写?
自动配置原理:
SpringBoot在启动的时候加载主配置类,开启了自动配置功能:@EnableAutoConfiguration;
@EnableAutoConfiguration的作用:
利用@EnableAutoConfigurationImportSelector给容器导入一些组件;
可以查看selectImports中的内容;
List configurations = getCandidateConfigurations(annotationMetadata, attributes) 方法;
SpringFactoriesLoader.loadFactoryNames();
扫描所有jar包类路径下:META-INF/spring.factories;
将扫描到的文件内容加载包装成properties对象。
每一个自动配置类进行功能的自动配置;
所有在配置文件中能配置的属性都在xxxProperties类中配置着,配置文件能配置什么都参照配置文件中的值;
SpringBoot的特点:
SpringBoot启动时会加载大量的自动配置类;
看SpringBoot有没有自动配置类;
如果有,不用自己再写自动配置类。
给容器中自动配置类添加组件的时候,会从properties类中读取某些属性,我们就可以在配置文件中指定这些属性的值。
2.9 @Conditional自动配置
自动配置类需要在一定条件下才能生效。
注解的作用:必须是@Conditional指定的条件成立,才能给容器中添加组件,配置里面的所有内容才生效。
@Conditional扩展
作用(判断是否满足当前条件)
@ConditionalOnJava
系统的Java版本是否符合要求
@ConditionalOnBean
容器中存在指定的bean
@ConditionalOnMissingBean
容器中不存在指定的bean
@ConditionalOnExpression
满足SpEL表达式
@ConditionalOnClass
容器中有指定的类
@ConditionalOnMissingClass
容器中没有指定的类
@ConditionalOnProperty
系统中指定属性是有指定的值
@ConditionalOnResource
类路径下是否存在指定资源文件
@ConditionalOnWebApplication
当前是web环境
@ConditionalOnNotWebApplication
当前不是web环境
@ConditionalOnJndi
JNDI存在指定项
@ConditionalOnSingleCandidate
容器中只有一个指定的bean,或者这个bean是首选的bean
自动配置文件:org/springframework/boot/spring-boot-autoconfigure/2.0.5.RELEASE/spring-boot-autoconfigure-2.0.5.RELEASE.jar!/META-INF/spring.factories
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 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.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.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.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.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.jest.JestAutoConfiguration,\ org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration,\ 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.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.groovy.template.GroovyTemplateAutoConfiguration,\ 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.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.reactor.core.ReactorCoreAutoConfiguration,\ org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration,\ org.springframework.boot.autoconfigure.security.servlet.SecurityRequestMatcherProviderAutoConfiguration,\ 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.sendgrid.SendGridAutoConfiguration,\ org.springframework.boot.autoconfigure.session.SessionAutoConfiguration,\ org.springframework.boot.autoconfigure.security.oauth2.client.OAuth2ClientAutoConfiguration,\ 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.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.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
开启SpringBoot的debug,可以通过debug=true让控制台打印自动配置报告,便可以方便的知道哪些自动配置类生效了。
1 2 3 4 5 6 7 8 9 10 11 12 13 ============================ CONDITIONS EVALUATION REPORT ============================ Positive matches: ----------------- CodecsAutoConfiguration matched: - @ConditionalOnClass found required class 'org.springframework.http.codec.CodecConfigurer'; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition) CodecsAutoConfiguration.JacksonCodecConfiguration matched: - @ConditionalOnClass found required class 'com.fasterxml.jackson.databind.ObjectMapper'; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)
1 2 3 4 5 6 7 8 9 10 11 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', 'org.aspectj.weaver.AnnotatedElement' (OnClassCondition)
第三章 SpringBoot与日志 3.1 日志框架
System.out.println(“welcome!”); 不利于代码维护;
使用日志框架;
加入异步,自动归档等功能;
与程序耦合控制;
统一的接口层:日志门面。
常见的日志框架:
JUL(java.util.logging);
JCL;
jboss-logging;
logback;
log4j;
log4j2;
slf4j;
日志门面:SLF4J;
日志实现:Logback。
SpringBoot:底层是Spring框架,SpringBoot框架默认是JCL
SpringBoot选用SLF4J,Logback。
3.2 SLF4J的使用 3.2.1 如何在系统中使用SLF4J
开发的时候,日志记录的方法调用,应该直接调用日志抽象层里的方法,而不是日志的实现类。
给系统导入slf4j的jar和logback的实现jar:
1 2 3 4 5 6 7 8 9 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以后,配置文件还是作为日志实现框架本身的配置文件。
3.2.2 遗留问题
a(slf4j + logback):Spring(commons-logging),Hibernate(jboss-logging)
统一日志记录,即便是别的框架也使用同一日志框架。
如何让系统中所有的日志都统一到slf4j:
将系统中其他日志框架排除在外;
用中间适配层包替换原有日志框架;
导入slf4j其他的实现。
3.3 SpringBoot日志关系 1 2 3 4 <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-web</artifactId > </dependency >
SpringBoot的日志功能:
1 2 3 4 5 6 <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-logging</artifactId > <version > 2.0.5.RELEASE</version > <scope > compile</scope > </dependency >
SpringBoot底层依赖关系(pom.xml文件,show diagram查看maven项目依赖关系):
SpringBoot底层也是用slf4j + logback的方式进行日志记录;
SpringBoot也把其他的日志都替换成了slf4j;
中间替换包;
如果要引入其他框架,一定要把这个框架的默认日志依赖移除。
SpringBoot自动适应所有的日志框架,而且底层使用了slf4j + logback的方式记录日志,引入其他框架的时候,只需要把这个框架依赖移除掉。
3.4 SpringBoot默认日志配置 日志的级别,由低到高,可以调整日志输出的级别:
1 2 3 4 5 6 7 Logger logger = LoggerFactory.getLogger(getClass());logger.trace("这是日志..." ); logger.debug("这是debug日志..." ); logger.info("这是Info信息..." ); logger.warn("这是警告..." ); logger.error("这是错误信息..." );
SpringBoot默认日志输出级别为info。
可以在application.yml中自定义日志输出级别: logging.level.com.hape.nmsl=trace
在当前项目下生成日志文件:logging.file=springboot.log
不指定路径在项目路径下生成日志文件。
logfile优先级高于logpath。
logpath:指定日志文件的路径,默认文件名spring.log。
logging.pattern.console:控制台输出日志的格式。
logging.pattern.file:日志文件输出格式。
日志输出格式:
1 2 3 4 5 6 7 8 9 10 11 %d:表示日期时间; %thread:表示线程号; %-5level:级别从左显示5个字符宽度; %logger{50}:表示logger名字最长50个字符,否则按照句点分割; %msg:日志信息; %n:换行符。
日志格式配置实例:
1 %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n
3.5 指定日志文件和日志profile功能 给类路径下放上每个日志框架自己配置文件即可,
Because the standard logback.xml configuration file is loaded too early, you cannot use extensions in it. You need to either use logback-spring.xml or define a logging.config property.
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。
1 2 3 4 5 6 7 8 9 10 11 12 可以指定某一段配置只在某个环境下生效 <springProfile name ="staging" > </springProfile > <springProfile name ="dev, staging" > </springProfile > <springProfile name ="!production" > </springProfile >
3.6 切换日志框架 可以按照slf4j适配图进行相关的切换。
排除不使用的包;
导入相关的适配包;
不推荐更换SpringBoot默认使用的日志记录框架。
第四章 SpringBoot与Web开发 使用SpringBoot:
创建SpringBoot应用,选中需要的模块;
SpringBoot自动配置好场景,需要在配置文件中指定少量配置,即可运行程序;
编写相关的业务逻辑。
依赖于SpringBoot的自动配置。
4.1 webjar与静态资源映射规则 SpringBoot对静态资源的映射规则:(WebMvcAutoConfiguration.java)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 @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)); } }
在访问的时候只需要写webjars下的资源名称即可。(http://localhost:8080/webjars/jquery/3.3.1-1/jquery.js)
1 2 3 4 5 <dependency > <groupId > org.webjars</groupId > <artifactId > jquery</artifactId > <version > 3.3.1-1</version > </dependency >
4.2 引入Thymeleaf模板引擎
thymeleaf, jsp, freemaker, velocity
SpringBoot推荐的thymeleaf:
引入thymeleaf;
自定义thymeleaf版本。
1 2 3 <thymeleaf.version > 3.0.2.RELEASE</thymeleaf.version > <thymeleaf.layout.dialect.version > 2.1.1</thymeleaf.layout.dialect.version >
4.3 Thymeleaf语法 默认请求路径:classpath:templates/xxx.html
文档地址:Thymeleaf参考文档
使用方法:
导入Thymeleaf名称空间;
1 <html lang ="en" xmlns:th ="http:y//www.thymeleaf.org" >
使用Thymeleaf语法;
1 <div th:text ="${hello}" > 显示欢迎信息</div >
thymeleaf语法规则:
th:text:改变text文本值;
th:任意属性都可以替换;
文档第十章/Attributes/优先级;
thymeleaf表达式;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 Simple expressions: Variable Expressions: ${...} Selection Variable Expressions: *{...} Message Expressions: #{...} Link URL Expressions: @{...} 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: Page 17 of 106No-Operation: _
内置对象:
4.4 SpringMVC自动配置功能 SpringBoot文档地址:官方文档地址
4.4.1 SpringMVC自动配置项
SpringMVC自动配置:
Inclusion of ContentNegotiatingViewResolver and BeanNameViewResolver beans.
Support for serving static resources, including support for WebJars (covered later in this document )).
Automatic registration of Converter, GenericConverter, and Formatter beans.
Support for HttpMessageConverters (covered later in this document ).
Automatic registration of MessageCodesResolver (covered later in this document ).
Static index.html support.
Custom Favicon support (covered later in this document ).
Automatic use of a ConfigurableWebBindingInitializer bean (covered later in this document ).
1 2 3 4 5 6 7 8 9 10 11 12 @Bean @ConditionalOnBean(ViewResolver.class) @ConditionalOnMissingBean(name = "viewResolver", value = ContentNegotiatingViewResolver.class) public ContentNegotiatingViewResolver viewResolver (BeanFactory beanFactory) { ContentNegotiatingViewResolver resolver = new ContentNegotiatingViewResolver (); resolver.setContentNegotiationManager( beanFactory.getBean(ContentNegotiationManager.class)); resolver.setOrder(Ordered.HIGHEST_PRECEDENCE); return resolver; }
1 2 3 4 5 6 7 8 9 10 11 12 @Override public void addFormatters (FormatterRegistry registry) { for (Converter<?, ?> converter : getBeansOfType(Converter.class)) { registry.addConverter(converter); } for (GenericConverter converter : getBeansOfType(GenericConverter.class)) { registry.addConverter(converter); } for (Formatter<?> formatter : getBeansOfType(Formatter.class)) { registry.addFormatter(formatter); } }
1 2 3 4 5 @Override public void configureMessageConverters (List<HttpMessageConverter<?>> converters) { this .messageConvertersProvider.ifAvailable((customConverters) -> converters .addAll(customConverters.getConverters())); }
如果用户有配置(@Bean,@Component),则使用组合配置;
4.4.2 扩展SpringMVC配置
添加一个配置类并且继承自WebMvcConfigurerAdapter。
将hello.do请求映射到hello.html视图:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 package com.web.config;import org.springframework.context.annotation.Configuration;import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;@Configuration public class MvcConfig extends WebMvcConfigurerAdapter { @Override public void addViewControllers (ViewControllerRegistry registry) { registry.addViewController("/hello.do" ).setViewName("/hello.html" ); } }
WebMvcAutoConfiguration是SpringMVC的自动配置类;
在做其他自动配置时会导入:@Import(EnableWebMvcConfiguration.class)。
1 2 3 4 5 6 @Autowired(required = false) public void setConfigurers (List<WebMvcConfigurer> configurers) { if (!CollectionUtils.isEmpty(configurers)) { this .configurers.addWebMvcConfigurers(configurers); } }
容器中所有的WebMvcConfiguration都会被调用。所有的配置都会共同起作用。
4.4.3 全面接管SpringMVC
在配置类中添加@EnableWebMvc:丢弃所有的自动配置,手动配置所有的配置。
原理:
WebMvc:
1 2 3 4 5 6 @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE}) @Documented @Import({DelegatingWebMvcConfiguration.class}) public @interface EnableWebMvc {}
DelegatingWebMvcConfiguration:
1 2 3 4 @Configuration public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport { private final WebMvcConfigurerComposite configurers = new WebMvcConfigurerComposite (); }
WebMvcAutoConfiguration:
1 2 3 4 5 6 7 8 @Configuration @ConditionalOnWebApplication(type = Type.SERVLET) @ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class }) @ConditionalOnMissingBean(WebMvcConfigurationSupport.class) @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10) @AutoConfigureAfter({ DispatcherServletAutoConfiguration.class, ValidationAutoConfiguration.class })
4.5 引入资源 SpringBoot中使用webjars 引入jquery和bootstrap之类的资源:
1 2 3 4 5 6 7 8 9 10 11 <!DOCTYPE html > <html lang ="en" xmlns:th ="http://www.thymeleaf.org" > <head > <meta charset ="UTF-8" > <title > index</title > <link rel ="stylesheet" th:href ="@{webjars/bootstrap/4.1.3/css/bootstrap.css}" th:type ="text/css" /> </head > <body > </body > </html >
即使更换项目访问名也可以正常加载静态资源。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 package com.web.config;import org.springframework.context.annotation.Configuration;import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;@Configuration public class MvcConfig extends WebMvcConfigurerAdapter { @Override public void addViewControllers (ViewControllerRegistry registry) { registry.addViewController("/hello.do" ).setViewName("/hello.html" ); registry.addViewController("/" ).setViewName("/hello.html" ); } public WebMvcConfigurerAdapter webMvcConfigurerAdapter () { return new WebMvcConfigurerAdapter () { @Override public void addViewControllers (ViewControllerRegistry registry) { registry.addViewController("/" ).setViewName("/hello.html" ); } }; } }
4.6 国际化
编写国际化配置文件;
使用ResourceBundleMessageSource管理国际化资源文件;
在页面使用fmt:message取出国际化内容。
配置如下图:
SpringBoot自动配置(MessageSourceAutoConfiguration.java):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 @Bean @ConfigurationProperties(prefix = "spring.messages") public MessageSourceProperties messageSourceProperties () { return new MessageSourceProperties (); } @Bean public MessageSource messageSource () { MessageSourceProperties properties = messageSourceProperties(); ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource (); if (StringUtils.hasText(properties.getBasename())) { 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; }
设置配置文件地址:
页面中获取国际化资源:
1 2 3 4 <lable class ="sr-only" th:message ="#{login.tip}" > Tips</lable > <lable class ="sr-only" th:message ="#{login.username}" > Username</lable > <lable class ="sr-only" th:message ="#{login.password}" > Password</lable > <lable class ="sr-only" th:message ="#{login.remember}" > remember</lable >
浏览器根据浏览器语言设置的信息自动切换国际化。
SpringMVC区域信息组件:
1 2 3 4 5 6 7 8 9 10 11 12 13 @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; }
可以在请求参数上携带区域信息实现国际化:
1 2 https://localhost:8080/hello.do?language=zh_CN https://localhost:8080/hello.do?language=en_US
手动配置区域信息解析器:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 package com.web.config;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.web.servlet.LocaleResolver;import org.thymeleaf.util.StringUtils;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.util.Locale;@Configuration public class MyLocaleResolver implements LocaleResolver { @Override public Locale resolveLocale (HttpServletRequest httpServletRequest) { String language = httpServletRequest.getParameter("language" ); Locale locale = Locale.getDefault(); if (!StringUtils.isEmpty(language)) { String[] regionInfo = language.split("_" ); locale = new Locale (regionInfo[0 ], regionInfo[1 ]); } return locale; } @Override public void setLocale (HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Locale locale) { } }
4.7 拦截器
PostMapping():RestfulAPI注解;
开发期间禁用Thymeleaf的缓存:spring.thymeleaf.cache=false;
错误消息的显示;
防止表单重复提交,添加视图视图映射后,使用重定向。
使用拦截器进行身份校验;
编写拦截器,在配置类中注册拦截器。
页面中使用Thymeleaf获取值。
4.8 CRUD实验 4.8.1 实验要求
实验要求:
RestfulAPI风格:
URI:/资源名称/资源标识;
HTTP请求方式区分对资源的CRUD操作;
操作
普通CRUD
RestfulCRUD
查询
getEmp
emp—GET
添加
addEmp?xxx
emp—POST
修改
updateEmp?id=xxx&xxx=xxx
emp/{id}—PUT
删除
deleteEmp?id=1
emp/{id}—DELETE
实验的请求架构:
请求URI
请求方式
查询所有的员工
emps
GET
查询某个员工
emp/{id}
GET
来到添加界面
emp
GET
添加员工
emp
POST
来到修改界面
emp/{id}
PUT
修改员工
emp
PUT
删除员工
emp/{id}
DELETE
4.8.2 公共页面抽取—列表页
利用Thymeleaf抽取公共页面;
1 2 3 4 5 6 7 8 <!DOCTYPE html > <html xmlns:th ="http://www.thymeleaf.org" > <body > <div th:fragment ="copy" > © 2011 The Good Thymes Virtual Grocery</div > </body > </html >
“~{templatename::selector}”:模板名选择器;
~{templatename::fragmentname}:模板名:片断名。
默认效果:
insert片段都在div标签中
1 2 3 4 <body > ... <div th:insert ="footer :: copy" > </div > </body >
三种引入功能片段的th属性:
th:insert:将公共片段整个插入到声明引入的元素中;
th:replace:将声明引入的元素替换为公共片段;
th:include:将被引入的片段的内容包含进这个标签中。
4.8.3 链接高亮&列表完成
实现方法:引入公共片段时传入相关参数,公共片段根据参数高亮相关部分。
Thymeleaf日期工具对象(文档附录 > dates):
1 # dates : methods for java.util.Date objects: formatting, component extraction, etc.
1 2 3 4 ${#dates.format(date, 'dd/MMM/yyyy HH:mm')} ${#dates.arrayFormat(datesArray, 'dd/MMM/yyyy HH:mm')} ${#dates.listFormat(datesList, 'dd/MMM/yyyy HH:mm')} ${#dates.setFormat(datesSet, 'dd/MMM/yyyy HH:mm')}
4.8.4 添加员工 > 来到添加页面
添加表单:Bootstrap官网模板直接复制;
通过 **添加 **按钮跳转到添加页面;
使用th:each完成部门的遍历;
4.8.5 添加员工 > 完成添加
完成添加后 重定向 至列表页面(forward或者redirect);
提交的数据格式问题:日期格式:
日期格式化:SpringMVC将页面提交的值需要转换成指定的类型;
在配置文件中自定义表单提交的日期格式。
4.8.6 修改员工信息
配置HiddenHttpMethodFilter;
4.8.7 删除员工
4.9 定制错误页面
默认出错处理:返回一个默认的错误处理页面:在页面共享信息;
如果是其他客户端,默认响应一个json数据;
可以参照ErrorAutoConfiguration,错误处理的自动配置,在容器中添加如下组件:
DefaultErrorAttributes;
BasicErrorController:处理默认的error错误请求;
1 2 3 4 5 6 7 8 9 10 @RequestMapping(produces = "text/html") public ModelAndView errorHtml (HttpServletRequest request, HttpServletResponse response) { HttpStatus status = getStatus(request); Map<String, Object> model = Collections.unmodifiableMap(getErrorAttributes( request, isIncludeStackTrace(request, MediaType.TEXT_HTML))); response.setStatus(status.value()); ModelAndView modelAndView = resolveErrorView(request, response, status, model); return (modelAndView != null ) ? modelAndView : new ModelAndView ("error" , model); }
ErrorPageCustomizer:系统出现错误,来到/error请求进行处理:web.xml;
DefaultErrorViewResolver;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 static { Map<Series, String> views = new EnumMap <>(Series.class); views.put(Series.CLIENT_ERROR, "4xx" ); views.put(Series.SERVER_ERROR, "5xx" ); SERIES_VIEWS = Collections.unmodifiableMap(views); } @Override public ModelAndView resolveErrorView (HttpServletRequest request, HttpStatus status, Map<String, Object> model) { ModelAndView modelAndView = resolve(String.valueOf(status), model); if (modelAndView == null && SERIES_VIEWS.containsKey(status.series())) { modelAndView = resolve(SERIES_VIEWS.get(status.series()), model); } return modelAndView; } private ModelAndView resolve (String viewName, Map<String, Object> model) { String errorViewName = "error/" + viewName; TemplateAvailabilityProvider provider = this .templateAvailabilityProviders .getProvider(errorViewName, this .applicationContext); if (provider != null ) { return new ModelAndView (errorViewName, model); } return resolveResource(errorViewName, model); }
定制自定义错误页面:
有模板引擎的情况下:error/状态码,将错误命名为status_code.html放在classpath:error/下,发生此错误会来到该页面;
可以使用4xx和5xx作为错误页面的文件名来匹配该类型的所有错误,精确匹配优先;
页面能获取的信息:
timestamp;
message;
status code;
exception;
errors。
没有模板引擎:静态资源文件夹下寻找。
定制自定义json数据:
没有自适应效果,浏览器和客户端返回的都是json数据:
1 2 3 @ControllerAdvice @ExceptionHandler @Response
自适应效果:转发给/error进行自适应效果处理,给request中传入自己的参数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 @RequestMapping(produces = "text/html") public ModelAndView errorHtml (HttpServletRequest request, HttpServletResponse response) { HttpStatus status = getStatus(request); Map<String, Object> model = Collections.unmodifiableMap(getErrorAttributes( request, isIncludeStackTrace(request, MediaType.TEXT_HTML))); response.setStatus(status.value()); ModelAndView modelAndView = resolveErrorView(request, response, status, model); return (modelAndView != null ) ? modelAndView : new ModelAndView ("error" , model); } @RequestMapping @ResponseBody public ResponseEntity<Map<String, Object>> error (HttpServletRequest request) { Map<String, Object> body = getErrorAttributes(request, isIncludeStackTrace(request, MediaType.ALL)); HttpStatus status = getStatus(request); return new ResponseEntity <>(body, status); }
将自定义错误信息携带:
响应数据由getErrorAttributes()获取:
编写一个ErrorController的实现类或者AbstractErrorController的子类,放在容器中;
页面上能用的数据或者json返回的数据都是errorAttributes.getErrorAttributes得到;DefaultErrorAttributes.getErrorAttributes()进行错误处理。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 package com.web.config;import org.springframework.boot.web.servlet.error.DefaultErrorAttributes;import org.springframework.stereotype.Component;import java.util.Map;@Component public class MyErrorHandler extends DefaultErrorAttributes { @Override public Map<String, Object> getErrorAttributes ( org.springframework.web.reactive.function.server.ServerRequest request, boolean includeStackTrace) { return super .getErrorAttributes(request, includeStackTrace); } }
第五章 配置嵌入式Servlet容器 5.1 定制嵌入式Servlet容器 默认使用嵌入式tomcat8.5.4作为嵌入式的Servlet容器;
如何定制嵌入式的Servlet容器?
SpringBoot能否支持其他的Servlet容器?
修改和Server有关的配置(server.properties):
1 2 server.port =8080 servet.context-path =/path
编写一个EmbeddedServletContainerCustomizer来修改嵌入式Servlet容器:
1 2 3 4 5 6 @Bean public EmbeddedServletContainerCustomizer embeddedServletContainerCustomizer () { public void customize (ConfigurableEmbeddedServletContainer container) { container.setPort(8083 ); } }
与容器相关的类:ServerProperties.class
SpringBoot2.0:
1 2 3 4 5 6 7 8 @Component public class EmbeddedTomcatConfig implements WebServerFactoryCustomizer <ConfigurableServletWebServerFactory> { @Override public void customize (ConfigurableServletWebServerFactory factory) { factory.setContextPath("/test" ); } }
5.2 注册Servlet容器三大组件 Servlet:ServletRegistrationBean
1 2 3 4 @Bean public ServletRegistrationBean<MyServlet> myServlet () { return new ServletRegistrationBean <>(new MyServlet (), "/servlet.do" ); }
Filter:FilterRegistrationBean
1 2 3 4 5 6 7 @Bean public FilterRegistrationBean<MyFilter> myFilter () { FilterRegistrationBean<MyFilter> registrationBean = new FilterRegistrationBean <>(); registrationBean.setFilter(new MyFilter ()); registrationBean.setUrlPatterns(Arrays.asList("/hello.do" , "/nihao.do" )); return registrationBean; }
Listener:ServletListenerRegistrationBean
1 2 3 4 5 6 @Bean public ServletListenerRegistrationBean<MyListener> myListener () { ServletListenerRegistrationBean<MyListener> registrationBean = new ServletListenerRegistrationBean <MyListener>(); registrationBean.setListener(new MyListener ()); return registrationBean; }
5.3 嵌入式Servlet容器自动配置原理 EmbeddedWebServerFactoryCustomizerAutoConfiguration.class
Tomcat:
1 2 3 4 5 6 7 8 9 10 @Configuration @ConditionalOnClass({ Tomcat.class, UpgradeProtocol.class }) public static class TomcatWebServerFactoryCustomizerConfiguration { @Bean public TomcatWebServerFactoryCustomizer tomcatWebServerFactoryCustomizer ( Environment environment, ServerProperties serverProperties) { return new TomcatWebServerFactoryCustomizer (environment, serverProperties); } }
Jetty:
1 2 3 4 5 6 7 8 9 10 11 @Configuration @ConditionalOnClass({ Server.class, Loader.class, WebAppContext.class }) public static class JettyWebServerFactoryCustomizerConfiguration { @Bean public JettyWebServerFactoryCustomizer jettyWebServerFactoryCustomizer ( Environment environment, ServerProperties serverProperties) { return new JettyWebServerFactoryCustomizer (environment, serverProperties); } }
Undertow:
1 2 3 4 5 6 7 8 9 10 11 @Configuration @ConditionalOnClass({ Undertow.class, SslClientAuthMode.class }) public static class UndertowWebServerFactoryCustomizerConfiguration { @Bean public UndertowWebServerFactoryCustomizer undertowWebServerFactoryCustomizer ( Environment environment, ServerProperties serverProperties) { return new UndertowWebServerFactoryCustomizer (environment, serverProperties); } }
配置文件:Server.properties:
1 2 @ConfigurationProperties(prefix = "server", ignoreUnknownFields = true) public class ServerProperties {
ConfigurableTomcatWebServerFactory.class:
5.4 使用外置的Servlet容器 内置的servlet容器不支持jsp;
向项目中导入tomcat服务器,创建web.xml文件,添加application.properties配置;打包方式为war包;
必须编写一个ServletInitializer文件;
1 2 3 4 5 6 public class ServletInitializer extends SpringBootServletInitializer { @override protected SpringApplicationBuilder configure (SpringApplicationBuilder application) { return application.sources(${MainClass}.class); } }
将嵌入式spring-boot-start-web内嵌的tomcat的scope指定为provided;
第六章 Docker技术 6.1 docker简介 概念:Docker是一个开源的引擎,可以轻松的为任何应用创建一个轻量级的、可移植的、自给自足的容器。开发者在笔记本上编译测试通过的容器可以批量地在生产环境中部署,包括VMs(虚拟机)、bare metal 、OpenStack 集群和其他的基础应用平台。
Docker入门
6.2 Docker核心概念
docker主机(Host):安装了Docker程序的机器(Docker直接安装在操作系统之上);
docker客户端(Client):连接Docker主机进行操作;
docker仓库(Registry):用来保存各种打包好的软件镜像;
docker镜像(Images):软件打包好的镜像,放在docker仓库中;
docker容器(Container):镜像启动后的实例称为一个容器,容器是独立运行的一个或一组应用;
使用docker容器的步骤:
安装docker;
去docker仓库找到这个软件对应的镜像;
使用docker运行这个镜像,就会生成一个Docker镜像容器;
对容器的启动和停止就是对软件的启动和停止。
6.3 Docker常用操作 镜像官方网站:Docker Hub
1 2 3 4 docker search mysql //搜索镜像 docker pull mysql:5.5 //拉取镜像 docker images //查看本地所有镜像 docker rmi images-id //删除本地镜像
各个独立的容器互不干扰,独立运行。
6.4 环境搭建 6.4.1 安装MySQL
启动一个MySQL实例(需要指定密码和端口映射 ):
1 $ docker run -p port --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag
官方文档:MySQL文档
几个高级操作:
1 2 3 4 5 使用配置文件: $ docker run --name some-mysql -v /my/custom:/etc/mysql/conf.d -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag 不适用配置文件: $ docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
6.4.2 安装Redis
6.4.3 安装RabbitMQ
6.4.4 安装ElasticSearch
第七章 SpringBoot与数据库访问 SpringBoot与数据访问相关的场景启动器:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 spring-boot-starter-data-cassandra Starter for using Cassandra distributed database and Spring Data Cassandra Pom spring-boot-starter-data-cassandra-reactive Starter for using Cassandra distributed database and Spring Data Cassandra Reactive Pom spring-boot-starter-data-couchbase Starter for using Couchbase document-oriented database and Spring Data Couchbase Pom spring-boot-starter-data-couchbase-reactive Starter for using Couchbase document-oriented database and Spring Data Couchbase Reactive Pom spring-boot-starter-data-elasticsearch Starter for using Elasticsearch search and analytics engine and Spring Data Elasticsearch Pom spring-boot-starter-data-jpa Starter for using Spring Data JPA with Hibernate Pom spring-boot-starter-data-ldap Starter for using Spring Data LDAP Pom spring-boot-starter-data-mongodb Starter for using MongoDB document-oriented database and Spring Data MongoDB Pom spring-boot-starter-data-mongodb-reactive Starter for using MongoDB document-oriented database and Spring Data MongoDB Reactive Pom spring-boot-starter-data-neo4j Starter for using Neo4j graph database and Spring Data Neo4j Pom spring-boot-starter-data-redis Starter for using Redis key-value data store with Spring Data Redis and the Lettuce client Pom spring-boot-starter-data-redis-reactive Starter for using Redis key-value data store with Spring Data Redis reactive and the Lettuce client Pom spring-boot-starter-data-rest Starter for exposing Spring Data repositories over REST using Spring Data REST Pom spring-boot-starter-data-solr Starter for using the Apache Solr search platform with Spring Data Solr Pom
7.1 整合JDBC与数据源 建表语句执行:classpath:schema-*.sql
数据操作语句:classpath:data-*.sql
也可以使用schema在application.yml中自定义数据文件地址。
7.2 Druid数据源配置
引入依赖;
配置属性。
添加一个配置类,将Druid配置映射到数据源。
结合过滤器和Servlet设置Druid监控。
7.3 整合MyBatis 启动器:
1 mybatis-spring-boot-starter
获取插入数据库的记录的ID:
@Options(userGeneratedKeys=, keyProperty=)
开启MyBatis驼峰命名:
写一个配置类,实现ConfigurationCustomizer接口中的customize()方法:
1 configuration.setMapUnderscopeToCamelCase(true );
批量扫描所有的@Mapper注解:
@MapperScan(value=””)
相关配置文件见官网文档。
全局配置文件配置:
1 2 mybatis-config-location :classpath:mybatis/config.xml mybatis-config-mapper :class:mybatis/mapper.xml
7.4 SpringData数据访问JPA