SpringBoot 入门04

SpringBoot笔记

一、SpringBoot入门

1、SpringBoot简介

简化spring应用的框架

整个Spring技术栈的大整合

j2ee开发的一站式解决方案

2、微服务

2014 马丁·福勒(martin fowler)

微服务: 架构风格

一个应用应该是一组小型微服务,可以通过HTTP的方式去进行访问

单体应用: ALL IN ONE

微服务:每一个功能元素最终都是一个独立运行或者升级的软件单元

3、 环境的准备

环境:

- jdk1.8  : SpringBoot官方推荐的1.7以上  java version "1.8.0_171"
- maven: Apache Maven 3.6.0
- idea: IntelliJ IDEA 2020.1 x64
- SpringBoot: 2.3.0

4、SpringBoot HelloWorld

一个需求:

​ 浏览器发送hello 请求,服务器接收并处理,响应Hello World字符串

  1. 创建Maven工程
  2. 导入Springboot相关依赖
  3. 编写主程序:启动SpringBoot应用
  4. 编写相关的controller、service
  5. 运行主程序进行测试
  6. 简化部署
    1. Jar包 打包过后直接使用 java -jar 在cmd里运行

5、Hello World 探究

5.1、POM文件

<parent>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-parentartifactId>
        <version>2.3.0.RELEASEversion>
parent>

他的父项目是
<parent>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-dependenciesartifactId>
    <version>2.3.0.RELEASEversion>
  parent>

他是真正用来管理Spring boot 应用的所有依赖版本

SpringBoot的版本仲裁中心

​ 我们以后导入依赖的时候都不需要写版本(没有写在dependencies中的需要单独声明版本号)

5.2、 启动器

<dependency>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-starter-webartifactId>
 dependency>

spring-boot-starter == web ==

​ spring-boot-starter :springboot 的场景启动器,帮我们导入web模块正常运行所需要的组件

SpringBoot把所有的功能场景都提取出来,做成一个个starter(启动器),我们只需要在项目里导入相关的starter相关的场景就会把所有相关的依赖都会导入进来。要用什么功能就达到入什么场景的启动器

5.3、主程序类和入口类

/**
 *   @SpringBootApplication 来标准一个主程序类,说明当前是一个SpringBoot应用
 */
@SpringBootApplication
public class HelloWorldMainApplication {
     

    public static void main(String[] args) {
     
        //  让 Spring应用程序跑起来
        SpringApplication.run(HelloWorldMainApplication.class,args);
    }

}

@SpringBootApplication: 这个注解标注到哪个类上面,就代表了这个类是SpringBoot的主配置类,

SpringBoot是运行这个main方法来启动当前的SpringBoot项目:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
      @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
		@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
     

@SpringBootConfiguration: SpringBoot的配置类:

​ 标注在哪个类,表示当前是一个SpringBoot的一个配置类

@Configuration:标注在配置类上的

​ 配置类 ------ 配置文件: 配置类也是容器中的一个组键,@Component

@EnableAutoConfiguration: 开启自动配置功能

以前需要配置东西的时候,SpringBoot会帮我们配置,@EnableAutoConfiguration 是告诉SpringBoot开启自动配置,这样我们的配置才会生效

@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
     

@AutoConfigurationPackage : 自动配置包

@Import(AutoConfigurationImportSelector.class)

@Import是spring的底层注解,给容器导入一个组件;导入的组件由AutoConfigurationImportSelector.class

这个注解会将主配置类(@SpringBootApplication所标注的类)下面所有的子包里面的组价扫描到spring容器

@Import(AutoConfigurationImportSelector.class)

给容器中导入组件

AutoConfigurationImportSelector: 导入哪些主键的选择器

将所有需要导入的组件以全类目的方式返回: 这些组件就会加载到spring容器中

会给容器导入很多的配置类(xx.AutoConfiguration):其实就是导入你当前的场景所需要的依赖包

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vNcBPkYW-1591951707033)(C:\Users\JiangXinWei\Desktop\第二十八天\springBoot笔记\images\1589772241592_0B427267-7E72-4ba3-B3AE-034D934FE971.png)]

有了这个配置类,我们就不用手动去编写配置类去加载到项目中;

SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader());

springboot会在启动的时候在类路径下的META-INF/spring.factories,会获取道@EnableAutoConfiguration制定的值,把这些值作为自动配置加入到容器。然后自动配置类就会生效。

5.4 、使用spring中的项目创建的向导器Spring Initializr去创建SpringBoot项目

- idea都有一个快速构建springboot项目的向导器Spring Initializr,可以使用它来创建项目,只需要勾选你想要的场景模块,就会自动下载所需要的依赖, 注: 创建过程中必须要联网 。
- 出程序以及生产好了,只需要根据我们的逻辑需求去编写
  • resources 文件夹下的目录结构
    • static: 存放当前项目下的所有静态资源 CSS、JS、Images …
    • templates: 存放所有的模板页面;
      • 注: 因为SpringBoot是内嵌Tomcat,所以说默认不支持JSP页面,可以使用插件去使用JSP页面
      • 注:SpringBoot推荐使用模板引擎 - Thymeleaf、Freemarker
        - application.properties : SpringBoot默认加载的配置文件,可以去修改一些默认配置

二、配置文件

6、配置文件

6.1、配置文件

​ SpringBoot使用了一个全局的配置文件,配置文件的名字是固定的。

​ application.properties

​ application.yml

​ 作用: 修改SpringBoot中的一些默认配置,这个文件会被springboot进行自动配置

yml = YAML:

  • 格式: 序列化

  • 写法: 递归的写法

  • 以数据为中心,比json、xml等更适合做配置文件

  • “YAML Ain’t a Markup Language”(YAML不是一种标记语言)

    “Yet Another Markup Language”(仍是一种标记语言)

标记语言:

​ 以前 使用xxx.xml

​ 现在: YAML更好一些

.xml

<server>
	<port>8081port>
server>

.yml

server: 
	port: 8081

6.2 YAML语法

6.2.1 基本语法

K: (空格)V 类似于键值对的写法,注意: 冒号后面要跟空格才能写V(值)

用空格来控制层级关系,只要根据左对齐的方式,同一列的数据都同一层级

server:
  port: 8081
  servlet:
    context-path: /hello

6.2.2 值的写法

1、基本语法

​ K: (空格)V 类似于键值对的写法,注意: 冒号后面要跟空格才能写V(值)

2、 字面量: 普通的值(字符串、数字、布尔值)

​ K: V : 直接键值对写值

​ 注: - 如果说值是字符串也不需要去给引号

​ 在什么情况下可以加引号?

​ 双引号 " " : 如果说包含特殊字符,那么引不会转义特殊字符的含义,会直接根据特殊字符的本身含义展示出来

user:
	name: "laowang \n gebi"  -----     name: laowang 换行  gebi**

​ 单引号 ’ ':如果说包含特殊字符,那么单引号会转义特殊字符的含义,会直接把特殊字符作为一个字符串进行输出

user:
	name: ‘laowang \n gebi’  -----     name: laowang \n  gebi**

3、对象、Map

​ K: V : 在下一行去根据键值对的方式写属性个值

user:
	username: xiaoming
	age: 18
	gender:

如果说想把对象或者Map在一行内写出来

user: {
     username: xiaoming,age: 18,gender:}
4、数组、list、set

​ 在下一行使用 - (空格)值,来表示一个元素

sub:
	- JAVA
	- Python
	- HTML

如果说想把组或者list、set在一行内写出来

sub: java,python,html

6.3 获取YAML中的值

​ 配置文件:

​ .yml

user:
  userName: xiaoming
  age: 18
  gender:isgirl: true
  maps: {
     k1: v1,k2: v2}
  sub:
    - java
    - python
    - html
  girl:
    name: 小芳
    age: 16

JavaBean

/**
 * @ConfigurationProperties 标注在一个类上,告诉Springboot讲本类中所有的属性和指定的配置文件中的参数进行绑定
 *      注: ConfigurationProperties 属于容器中的注解,
 * prefix = "" 指定获取的是配置文件中哪一个下面所有参数
 */
@Component
@ConfigurationProperties(prefix = "user")
public class User {
     

    private String userName;
    private int age;
    private String gender;
    private boolean isgirl;
    private Map<String,Object> maps;
    private List<Object> sub;
    private Girl girl;

配置文件处理器,到入这个包之后,我们进行属性和参数的绑定时会有人性化提示

 <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-configuration-processorartifactId>
            <optional>trueoptional>
        dependency>

.properties中的的参数取值乱码怎么办?

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ED1rug3C-1591951707038)(C:\Users\JiangXinWei\Desktop\第二十九天\springBoot笔记\images\1.png)]

6.4 @Value 和 @ConfigurationProperties 应用场景

@ConfigurationProperties @Value
取值 可以一次取出全部参数进行绑定 一个一个取
SpEL 不支持 支持
松散绑定 支持 不支持
JSR303数据校验 支持 不支持
复杂类型绑定 支持 不支持

提问:

​ 这两个直接的应用场景分别是什么?

​ 如果说你只是在处理业务时,需要用到配置问价中某一个参数的值,就用@Value

​ 如果说你专门做实体绑定配置文件的实例,这是用@ConfigurationProperties

数据校验

/**
 * @ConfigurationProperties 标注在一个类上,告诉Springboot讲本类中所有的属性和指定的配置文件中的参数进行绑定
 *      注: ConfigurationProperties 属于容器中的注解,
 * prefix = "user" 指定获取的是配置文件中哪一个下面所有参数
 */
@Component
@ConfigurationProperties(prefix = "user")
@Validated
public class User {
     
    /**
     *  
     *       
     */

//    @Value("${user.user-name}")
    private String userName;
//    @Value("#{2*5*8}")
    private int age;
    private String gender;
//    @Value("false")
    private boolean isgirl;
//    @Value("${maps}")

6.5 @PorpertySource & @ImportSource & @Bean

@PorpertySource: 加载指定的配置文件


/**
 * @Author Administrator
 * @Date 2020/5/20 15:31
 * @ConfigurationProperties 会告诉springboot将本类中的属性和配置文件相关的参数进行绑定
 * 注: ConfigurationProperties 是容器中的方法,所以当前类必须要容器中
 *
 * prefix = "user" ;去指定配置文件中的哪一个下面的属性
 **/
@PropertySource(value = {
     "classpath:User.properties"}) //加载指定的配置文件
@Component
@ConfigurationProperties(prefix = "user")
//@Validated
public class User {
     

@ImportSource: 导入spring的配置文件,使其生效;

Springbooot中是 没有Spring配置文件的,我们自己编写的配置文件,也不会自动识别。

可以使用@ImportSource,让spring的配置类生效

注:@ImportSource 必须要标注在一个配置类上


<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="userService" class="com.gm.service.UserService">bean>
beans>

如果说,我们项目中不允许出现.xml文件怎么办呢?

SpringBoot 推荐给容器中添加组件的方式;推荐使用全注解

@Configuration ------ spring配置文件

@Bean —

/**
 * @Author Administrator
 * @Date 2020/5/22 14:51
 * @Configuration 标注在哪个类上,就代表当前是springboot的配置类
 *
 *
 **/
@Configuration
public class BootConfig {
     


    // 把返回值加载到容器中
    @Bean
    public UserService userService(){
     
        System.out.println("正在给spring容器注入组件");
        return new UserService();
    }
}

6.6 占位符

6.6 .1随机数

${
     random.value}、${
     random.int}、${
     random.long}
${
     random.int(10)}、${
     random.int[1024,65536]}

赋值 、 取值 、 自定义

user.user-name= 夏明翰${random.UUID}
user.age=${random.int}
user.gender=男
user.isgirl=true
user.maps.k1=v1
user.maps.k2=v2
user.sub=java,python,html
user.girl.name=${user.user-name}${user.password:的第二个}老Boby
user.girl.age=16

7、Profiles

7.1多Profiles文件

我们在主配置文件编写的时候,文件名可以是 :

application.properties/.yml

application-{profiles}.properties/.yml

当项目中同时存在默认配置文件喝profiles文件时,

默认使用 application.properties/.yml

7.2 YAML支持多文档块

server:
  port: 8084
spring:
  profiles:
    active: prov
---

server:
  port: 8085
spring:
  profiles: devs
---

server:
  port: 8086
spring:
  profiles: prov

7.3 激活制定的profiles的方法

​ 1. 在配置文件中激活 spring.profiles.active: prov

  1. 在spring环境里去激活 --spring.profiles.active=devs
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JBc3anwb-1591951707041)(C:\Users\JiangXinWei\Desktop\springBoot笔记\springBoot笔记\images\2.PNG)]
  1. 命令行:

    ​ java -jar springboot-03-config2-0.0.1-SNAPSHOT.jar --spring.profiles.active=devs

  2. 虚拟机参数:

    -Dspring.profiles.active=devs

8. 配置文件的加载位置

SpringBoot启动的时候会扫描以下位置application.properties和application.yml的默认配置文件

file:./config/

file: ./

classpath: /config/

classpath: /

优先级由高到低,

如果项目中存在相同配置不同位置的properties文件,那么高优先级是不是会覆盖低优先级;

如果项目中存在不同配置不同位置的properties文件,那么会发生 互补配置;

还可以通过 命令行: spring.config.location来改变默认加载的配置文件位置,同时,会同样遵守互补配置;

java -jar springboot-03-config-0.0.1-SNAPSHOT.jar --spring.config.location=C:/Users/JiangXinWei/Desktop/application.properties

9、配置文件的外部加载顺序

Springboot也可以从以下位置加载配置文件,优先级从高到低、遵循高覆盖低而且配置互补。

1.命令行参数

所有的配置都可以在命令行行进行执行

java -jar springboot-03-config-0.0.1-SNAPSHOT.jar --server.port=8088 --server.servlet.context-path=/ufo

书写规范: –配置项=值

2.来自java:comp/env的JNDI属性

3.Java系统属性(System.getProperties())

4.操作系统环境变量

5.RandomValuePropertySource配置的random.*属性值

== 由jar包外向jar包内进行寻找==:

**-- 优先加载带profile的文件-- **

6.jar包外部的application-{profile}.properties或application.yml(带spring.profile)配置文件

7.jar包内部的application-{profile}.properties或application.yml(带spring.profile)配置文件

– 再加载不带profile的文件–

8.jar包外部的application.properties或application.yml(不带spring.profile)配置文件

9.jar包内部的application.properties或application.yml(不带spring.profile)配置文件

10.@Configuration注解类上的@PropertySource

11.通过SpringApplication.setDefaultProperties指定的默认属性

10 自动配置的原理

配置文件中到底能写什么?怎么写?自动配置的原理;

10.1 自动配置原理

  1. springboot启动的时候回加载主配置类,开启自动配置:@EnableAutoConfiguration
  2. @EnableAutoConfiguration:
    • 利用AutoConfigurationImportSelector给容器导入了一些组件
    • selectImports()方法的内容
    • List configurations = getCandidateConfigurations(annotationMetadata, attributes); 获取候选的配置
	SpringFactoriesLoader.loadFactoryNames()
    扫描所以jar类路径下的 : META-INF/spring.factories
    把扫描的这些文件的内容包装成properties对象
    从properties中获取EnableAutoConfiguration.class类名对应的值,然后把他们添加到容器中
# Initializers
org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer,\
org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener

# Application Listeners
org.springframework.context.ApplicationListener=\
org.springframework.boot.autoconfigure.BackgroundPreinitializer

# Auto Configuration Import Listeners
org.springframework.boot.autoconfigure.AutoConfigurationImportListener=\
org.springframework.boot.autoconfigure.condition.ConditionEvaluationReportAutoConfigurationImportListener

# Auto Configuration Import Filters
org.springframework.boot.autoconfigure.AutoConfigurationImportFilter=\
org.springframework.boot.autoconfigure.condition.OnBeanCondition,\
org.springframework.boot.autoconfigure.condition.OnClassCondition,\
org.springframework.boot.autoconfigure.condition.OnWebApplicationCondition

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\
org.springframework.boot.autoconfigure.context.LifecycleAutoConfiguration,\
org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,\
org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration,\
org.springframework.boot.autoconfigure.dao.PersistenceExceptionTranslationAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ReactiveElasticsearchRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ReactiveElasticsearchRestClientAutoConfiguration,\
org.springframework.boot.autoconfigure.data.jdbc.JdbcRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.ldap.LdapRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.solr.SolrRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.r2dbc.R2dbcDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.r2dbc.R2dbcRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.r2dbc.R2dbcTransactionManagerAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisReactiveAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.rest.RepositoryRestMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.data.web.SpringDataWebAutoConfiguration,\
org.springframework.boot.autoconfigure.elasticsearch.ElasticsearchRestClientAutoConfiguration,\
org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration,\
org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration,\
org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration,\
org.springframework.boot.autoconfigure.h2.H2ConsoleAutoConfiguration,\
org.springframework.boot.autoconfigure.hateoas.HypermediaAutoConfiguration,\
org.springframework.boot.autoconfigure.hazelcast.HazelcastAutoConfiguration,\
org.springframework.boot.autoconfigure.hazelcast.HazelcastJpaDependencyAutoConfiguration,\
org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration,\
org.springframework.boot.autoconfigure.http.codec.CodecsAutoConfiguration,\
org.springframework.boot.autoconfigure.influx.InfluxDbAutoConfiguration,\
org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration,\
org.springframework.boot.autoconfigure.integration.IntegrationAutoConfiguration,\
org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.JndiDataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.XADataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration,\
org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.JndiConnectionFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.activemq.ActiveMQAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.artemis.ArtemisAutoConfiguration,\
org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration,\
org.springframework.boot.autoconfigure.jooq.JooqAutoConfiguration,\
org.springframework.boot.autoconfigure.jsonb.JsonbAutoConfiguration,\
org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration,\
org.springframework.boot.autoconfigure.availability.ApplicationAvailabilityAutoConfiguration,\
org.springframework.boot.autoconfigure.ldap.embedded.EmbeddedLdapAutoConfiguration,\
org.springframework.boot.autoconfigure.ldap.LdapAutoConfiguration,\
org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration,\
org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration,\
org.springframework.boot.autoconfigure.mail.MailSenderValidatorAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.MongoReactiveAutoConfiguration,\
org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration,\
org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\
org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration,\
org.springframework.boot.autoconfigure.r2dbc.R2dbcAutoConfiguration,\
org.springframework.boot.autoconfigure.rsocket.RSocketMessagingAutoConfiguration,\
org.springframework.boot.autoconfigure.rsocket.RSocketRequesterAutoConfiguration,\
org.springframework.boot.autoconfigure.rsocket.RSocketServerAutoConfiguration,\
org.springframework.boot.autoconfigure.rsocket.RSocketStrategiesAutoConfiguration,\
org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration,\
org.springframework.boot.autoconfigure.security.servlet.SecurityFilterAutoConfiguration,\
org.springframework.boot.autoconfigure.security.reactive.ReactiveSecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.reactive.ReactiveUserDetailsServiceAutoConfiguration,\
org.springframework.boot.autoconfigure.security.rsocket.RSocketSecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.saml2.Saml2RelyingPartyAutoConfiguration,\
org.springframework.boot.autoconfigure.sendgrid.SendGridAutoConfiguration,\
org.springframework.boot.autoconfigure.session.SessionAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.client.servlet.OAuth2ClientAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.client.reactive.ReactiveOAuth2ClientAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.resource.servlet.OAuth2ResourceServerAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.resource.reactive.ReactiveOAuth2ResourceServerAutoConfiguration,\
org.springframework.boot.autoconfigure.solr.SolrAutoConfiguration,\
org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration,\
org.springframework.boot.autoconfigure.task.TaskSchedulingAutoConfiguration,\
org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration,\
org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration,\
org.springframework.boot.autoconfigure.transaction.jta.JtaAutoConfiguration,\
org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration,\
org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.web.embedded.EmbeddedWebServerFactoryCustomizerAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.HttpHandlerAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.ReactiveWebServerFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.error.ErrorWebFluxAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.function.client.ClientHttpConnectorAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.MultipartAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.reactive.WebSocketReactiveAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.servlet.WebSocketServletAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.servlet.WebSocketMessagingAutoConfiguration,\
org.springframework.boot.autoconfigure.webservices.WebServicesAutoConfiguration,\
org.springframework.boot.autoconfigure.webservices.client.WebServiceTemplateAutoConfiguration

# Failure analyzers
org.springframework.boot.diagnostics.FailureAnalyzer=\
org.springframework.boot.autoconfigure.diagnostics.analyzer.NoSuchBeanDefinitionFailureAnalyzer,\
org.springframework.boot.autoconfigure.flyway.FlywayMigrationScriptMissingFailureAnalyzer,\
org.springframework.boot.autoconfigure.jdbc.DataSourceBeanCreationFailureAnalyzer,\
org.springframework.boot.autoconfigure.jdbc.HikariDriverConfigurationFailureAnalyzer,\
org.springframework.boot.autoconfigure.r2dbc.ConnectionFactoryBeanCreationFailureAnalyzer,\
org.springframework.boot.autoconfigure.session.NonUniqueSessionRepositoryFailureAnalyzer

# Template availability providers
org.springframework.boot.autoconfigure.template.TemplateAvailabilityProvider=\
org.springframework.boot.autoconfigure.freemarker.FreeMarkerTemplateAvailabilityProvider,\
org.springframework.boot.autoconfigure.mustache.MustacheTemplateAvailabilityProvider,\
org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAvailabilityProvider,\
org.springframework.boot.autoconfigure.thymeleaf.ThymeleafTemplateAvailabilityProvider,\
org.springframework.boot.autoconfigure.web.servlet.JspTemplateAvailabilityProvider

每一个xxxxxxAutoConfiguration类都是容器中的一个组件,都加到容器中,同时就是用他们来自做自动配置。

  1. 接下来用 HttpEncodingAutoConfiguration (Http编码自动配置) 来解释一下自动原理
@Configuration(proxyBeanMethods = false) // 表示是一个配置类,相当于以前的xml配置文件

@EnableConfigurationProperties(ServerProperties.class) // 启动指定类的ConfigurationProperties,将配置文件中对应的值和ServerProperties进行绑定,并且绑定完之后会把ServerProperties加载道IOC容器中

@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)// Conditiona 是spring中的底层注解,用来判断的,根据不同的条件,如果满足指定的条件,整个配置类中的配置才会生效。        判断当前是不是WEB项目,如果是,当前配置类生效

@ConditionalOnClass(CharacterEncodingFilter.class) //  判断当前项目中有没有这个类,CharacterEncodingFilter.class: SpringMVC中解决乱码问题的过滤器


@ConditionalOnProperty(prefix = "server.servlet.encoding", value = "enabled", matchIfMissing = true)// 判断配置文件中有没有某个配置,server.servlet.encoding.enabled,如果不存在,判断也是成立的,即使我们的配置文件中不存在server.servlet.encoding.enabled=true,也是默认生效的




public class HttpEncodingAutoConfiguration {
     
	
    // 已经和springboot的配置文件进行绑定了
	private final Encoding properties;

    // 有参构造、当只有一个有参构造的时候,参数的值会从容器中得到
	public HttpEncodingAutoConfiguration(ServerProperties properties) {
     
		this.properties = properties.getServlet().getEncoding();
	}

	@Bean // 给容器中添加一个组价,组件中有些值需要从properties去获取
	@ConditionalOnMissingBean // 判断当前容器中有没有这个组件,CharacterEncodingFilter
	public CharacterEncodingFilter characterEncodingFilter() {
     
		CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();
		filter.setEncoding(this.properties.getCharset().name());
		filter.setForceRequestEncoding(this.properties.shouldForce(Encoding.Type.REQUEST));
		filter.setForceResponseEncoding(this.properties.shouldForce(Encoding.Type.RESPONSE));
		return filter;
	}

Conditiona 根据不同的条件判断得到不同的结果;

一旦这个配置文件生效,这个配置类就会给容器中添加各种组件;这些组件中的属性都是从对应的properties中获取的,同时,这些类里面的每一个属性有和配置文件进行绑定

  1. 每一个XXXAutoConfiguration都应该有一个相对于的xxxxproperties文件。

总结:

​ 1, springboot启动时会加载大量的配置类;

​ 2,我们在写之前,看一下我们需要的东西有没有是springboot默认写好的自动配置类

​ 3,如果有,只需要看一下自动配置类中到底 配置了哪些组件;

​ 4, 给容器中自动配置类添加组件的时候。会从从对应的properties中获取的,就可在配置文件中制定这些属性的值

11 拓展 @Conditional扩展

@Conditional****扩展注解 作用(判断是否满足当前指定条件)
@ConditionalOnJava 系统的java版本是否符合要求
@ConditionalOnBean 容器中存在指定Bean;
@ConditionalOnMissingBean 容器中不存在指定Bean;
@ConditionalOnExpression 满足SpEL表达式指定
@ConditionalOnClass 系统中有指定的类
@ConditionalOnMissingClass 系统中没有指定的类
@ConditionalOnSingleCandidate 容器中只有一个指定的Bean,或者这个Bean是首选Bean
@ConditionalOnProperty 系统中指定的属性是否有指定的值
@ConditionalOnResource 类路径下是否存在指定资源文件
@ConditionalOnWebApplication 当前是web环境
@ConditionalOnNotWebApplication 当前不是web环境
@ConditionalOnJndi JNDI存在指定项

注: 自动配置类必须在一定条件下才会生效,

可以通过 debug = true 来查看哪些配置生效

Positive matches: (自动配置类生效)
-----------------

   AopAutoConfiguration matched:
      - @ConditionalOnProperty (spring.aop.auto=true) matched (OnPropertyCondition)

   AopAutoConfiguration.ClassProxyingConfiguration matched:
      - @ConditionalOnMissingClass did not find unwanted class 'org.aspectj.weaver.Advice' (OnClassCondition)
      - @ConditionalOnProperty (spring.aop.proxy-target-class=true) matched (OnPropertyCondition)

   DispatcherServletAutoConfiguration matched:
      - @ConditionalOnClass found required class 'org.springframework.web.servlet.DispatcherServlet' (OnClassCondition)
      - found 'session' scope (OnWebApplicationCondition)

   DispatcherServletAutoConfiguration.DispatcherServletConfiguration matched:
      - @ConditionalOnClass found required class 'javax.servlet.ServletRegistration' (OnClassCondition)
      - Default DispatcherServlet did not find dispatcher servlet beans (DispatcherServletAutoConfiguration.DefaultDispatcherServletCondition)
          
          
          
Negative matches:(没有启动,么有匹配成功的配置类)
-----------------

   ActiveMQAutoConfiguration:
      Did not match:
         - @ConditionalOnClass did not find required class 'javax.jms.ConnectionFactory' (OnClassCondition)

   AopAutoConfiguration.AspectJAutoProxyingConfiguration:
      Did not match:
         - @ConditionalOnClass did not find required class 'org.aspectj.weaver.Advice' (OnClassCondition)

三、Web开发

1、简介

使用Springboot:

  1. 创建springboot应用,选中我们需要的模块;
  2. springboot已经默认的把这些场景都配置好了,只需要去更改配置文件中的少量配置就可以运行起来
  3. 自己编写业务代码;

自动配置原理?

Springboot到底给我们配置了什么? 能不能修改? 能不能修改默认配置?。。。。

xxxAutoConfiguration  帮我们给容器中自动配置组件
xxxproperties 配置类来封装配置文件的内容

2、SpringBoot对静态资源路径映射的规则

WebMvcAutoConfiguration
		@Override
		public void addResourceHandlers(ResourceHandlerRegistry registry) {
     
			if (!this.resourceProperties.isAddMappings()) {
     
				logger.debug("Default resource handling disabled");
				return;
			}
			Duration cachePeriod = this.resourceProperties.getCache().getPeriod();
			CacheControl cacheControl = this.resourceProperties.getCache().getCachecontrol().toHttpCacheControl();
			if (!registry.hasMappingForPattern("/webjars/**")) {
     
				customizeResourceHandlerRegistration(registry.addResourceHandler("/webjars/**")
						.addResourceLocations("classpath:/META-INF/resources/webjars/")
						.setCachePeriod(getSeconds(cachePeriod)).setCacheControl(cacheControl));
			}
			
			String staticPathPattern = this.mvcProperties.getStaticPathPattern();
			// 静态资源文件夹映射
			if (!registry.hasMappingForPattern(staticPathPattern)) {
     
				customizeResourceHandlerRegistration(registry.addResourceHandler(staticPathPattern)
						.addResourceLocations(getResourceLocations(this.resourceProperties.getStaticLocations()))
						.setCachePeriod(getSeconds(cachePeriod)).setCacheControl(cacheControl));
			}
		}
	
 // 首页的映射
@Bean
		public WelcomePageHandlerMapping welcomePageHandlerMapping(ApplicationContext applicationContext,
				FormattingConversionService mvcConversionService, ResourceUrlProvider mvcResourceUrlProvider) {
     
			WelcomePageHandlerMapping welcomePageHandlerMapping = new WelcomePageHandlerMapping(
					new TemplateAvailabilityProviders(applicationContext), applicationContext, getWelcomePage(),
					this.mvcProperties.getStaticPathPattern());
			welcomePageHandlerMapping.setInterceptors(getInterceptors(mvcConversionService, mvcResourceUrlProvider));
			welcomePageHandlerMapping.setCorsConfigurations(getCorsConfigurations());
			return welcomePageHandlerMapping;
		}
  1. 所有的 /webjars/都会去 classpath:/META-INF/resources/webjars/ 去资源**

    webjars: 把前段的资源以jar包的方式引用

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Yxa7FBKb-1591951707044)(C:\Users\JiangXinWei\Desktop\springBoot笔记\springBoot笔记\images\5.png)]

​ localhost:8080/webjars/jquery/3.3.1/jquery.js


<dependency>
    <groupId>org.webjarsgroupId>
    <artifactId>jqueryartifactId>
    <version>3.3.1version>
dependency>
  1. “/” 访问当前项目的任何资源,都会去静态资源的文件夹去找映射
"classpath:/META-INF/resources/",  
"classpath:/resources/",
"classpath:/static/", 
"classpath:/public/"
"/" 当前项目的根路径

http://localhost:8080/style.js 会从静态资源路径去找style.js

  1. 欢迎页/首页,静态资源文件夹下的所有的index.html页面,都会背部“/”映射

http://localhost:8080/

  1. 所有的**/favicon.ico 都在静态资源目录中去找

3、模板引擎

jSP、Velocity、Freemarker、Thymeleaf

Thymeleaf:

1、Thymeleaf 是 Web 和独立环境的现代服务器端 Java 模板引擎,能够处理HTML,XML,JavaScript,CSS 甚至纯文本。

2、Thymeleaf 的主要目标是提供一种优雅和高度可维护的创建模板的方式。为了实现这一点,它建立在自然模板的概念上,将其逻辑注入到模板文件中,不会影响模板被用作设计原型。这改善了设计的沟通,弥补了设计和开发团队之间的差距。

3、Thymeleaf 也从一开始就设计了Web标准 - 特别是 HTML5 - 允许您创建完全验证的模板,Spring Boot 官方推荐使用 thymeleaf 而不是 JSP。

4、Thymeleaf 官网:https://www.thymeleaf.org/

5、Thymeleaf 在 Github 的主页:https://github.com/thymeleaf/thymeleaf

6、Spring Boot 中使用 Thymeleaf 模板引擎时非常简单,因为 Spring Boot 已经提供了默认的配置,比如解析的文件前缀,文件后缀,文件编码,缓存等等,程序员需要的只是写 html 中的内容即可,可以参考《Spring Boot 引入 Thymeleaf 及入门》

特点 : 语法更简单、功能更强大

原 理:

模板引擎原理图如下,模板引擎的作用都是将模板(页面)和数据进行整合然后输出显示,区别在于不同的模板使用不同的语法,如 JSP 的 JSTL 表达式,以及 JSP 自己的表达式和语法,同理 Thymeleaf 也有自己的语法

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VcYoEPHg-1591951707047)(C:\Users\JiangXinWei\Desktop\springBoot笔记\springBoot笔记\images\6.png)]

3.1 引入Thymeleaf:


        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-thymeleafartifactId>
        dependency>

使用Thymeleaf:

@ConfigurationProperties(prefix = "spring.thymeleaf")
public class ThymeleafProperties {
     

	private static final Charset DEFAULT_ENCODING = StandardCharsets.UTF_8;

	public static final String DEFAULT_PREFIX = "classpath:/templates/";

	public static final String DEFAULT_SUFFIX = ".html";

所以说,只要把页面放到classpath:/templates/,thymeleaf就可以自动进行渲染。

使用:

  1. 需要导入Thymeleaf的名称空间
<html lang="en" xmlns:th="http://www.thymeleaf.org">
  1. 使用thymeleaf语法:

<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Titletitle>
head>
<body>
    <p>这里是测试页面p><hr>

    <p  id="p" >[[ ${hello} ]]p><hr>
    <input th:value="${hello}"  value="我是取值的Input标签"/><hr>

    <p th:each="user:${list}" th:text="${user}">我是取list的地方p>



body>
html>
  1. 语法规则:
  2. th:text ; 改变当前元素里面的文本内容
  3. th: 任意html属性,来替换原生属性的值

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9Ty6GWKW-1591951707048)(C:\Users\JiangXinWei\Desktop\springBoot笔记\springBoot笔记\images\9.png)]

取值:

Simple expressions: (表达式语法)
	Variable Expressions: ${...}: 获取变量的值,OGNL 
		1. 获取对象的属性、调用方法
		2. 使用内置的基本对象
		#ctx : the context object. 
		#vars: the context variables. 
		#locale : the context 	locale.
        #request : (only in Web Contexts) the HttpServletRequest object.
        #response : (only in Web Contexts) the HttpServletResponse object. 
        #session : (only in Web Contexts) the HttpSession object.
        #servletContext : (only in Web Contexts) the ServletContext object.
		${session.foo}
		3. 内置的一些工具对象:
		#execInfo : information about the template being processed.
        #messages : methods for obtaining externalized messages inside variables expressions, in the same way as they would be obtained using #{…} syntax. 
        #uris : methods for escaping parts of URLs/URIs
		#conversions : methods for executing the configured conversion service (if any). 
		#dates : methods for java.util.Date objects: formatting, component extraction, etc. 
		#calendars : analogous to #dates , but for java.util.Calendar objects. 
		#numbers : methods for formatting numeric objects. 
		#strings : methods for String objects: contains, startsWith, prepending/appending, etc. 
		#objects : methods for objects in general.
        #bools : methods for boolean evaluation. 
        #arrays : methods for arrays. 
        #lists : methods for lists.
        #sets : methods for sets. 
        #maps : methods for maps. 
        #aggregates : methods for creating aggregates on arrays or collections. 
        #ids : methods for dealing with id attributes that might be repeated (for example, as a result of an iteration).

		
		
	
    Selection Variable Expressions: *{...} : 选择表达式,和${}在功能上是一样的
    	补充: 

Name: Sebastian.

Surname: Pepper.

Nationality: Saturn.

Message Expressions: #{...} : 获取国际化内容 Link URL Expressions: @{...} : 定义URL view view view Fragment Expressions: ~{...} : 片段引用表达式
...
Literals (字面量) Text literals: 'one text' , 'Another one!' ,… Number literals: 0 , 34 , 3.0 , 12.3 ,… Boolean literals: true , false Null literal: null Literal tokens: one , sometext , main ,… Text operations: (文本操作) String concatenation: + Literal substitutions: |The name is ${name}| Arithmetic operations: (数学运算) Binary operators: + , - , * , / , % Minus sign (unary operator): - Boolean operations: (布尔值运算) Binary operators: and , or Boolean negation (unary operator): ! , not Comparisons and equality: (比较运算) Comparators: > , < , >= , <= ( gt , lt , ge , le ) Equality operators: == , != ( eq , ne ) Conditional operators: 条件运算(三元运算符) If-then: (if) ? (then) If-then-else: (if) ? (then) : (else) Default: (value) ?: (defaultvalue) Special tokens: No-Operation: _

3.2 SpringMVC自动配置:

https://docs.spring.io/spring-boot/docs/2.3.0.RELEASE/reference/htmlsingle/#boot-features-developing-web-applications

1. Spring MVC Auto-configuration

Spring Boot 自动配置好了SprinMVC

以下是SpringBoot对SpringMVC的默认配置:WebMvcAutoConfiguration

org\springframework\boot\autoconfigure\web\servlet\WebMvcAutoConfiguration.java

  • Inclusion of ContentNegotiatingViewResolver and BeanNameViewResolver beans.

    • 自动配置了ViewResolver(视图解析器: 根据当前的方法返回值,得到视图对象(View),视图的对象绝对了如何进行渲染(转发,重定向))
    • ContentNegotiatingViewResolver : 组合所有的视图解析器
    • 如何自己去写: 我们可以给容器中添加一个视图解析器;自动帮我们将自己写的组合进去
  • Support for serving static resources, including support for WebJars (covered later in this document)). :

    • WebJars ,静态资源文件夹路径的webjars
    • localhost:8080/webjars/xxxxxxx
  • 自动注册了 of Converter, GenericConverter, and Formatter beans.

    • Converter:转换器;public String Hello(User user){}; 类型转换器Converter
    • Formatter : 格式化器: 2020.05.30 === Date
  • Support for HttpMessageConverters (covered later in this document).

    • HttpMessageConverters : SpringMVC用来转换Http请求的请求和相应的;User—JSON
    • HttpMessageConverters: 从容器中确定: 获取所有的HttpMessageConverters,
    • 如果自己去添加,只需要将自己的组件去注册到容器中(@Bean,@Component)
  • Automatic registration of MessageCodesResolver (covered later in this document).

    • 定义错误代码生成规则
  • Static index.html support.: 静态资源的首页访问

  • Custom Favicon support (covered later in this document). : Favicon.ico

  • Automatic use of a ConfigurableWebBindingInitializer bean (covered later in this document).

    • 可以去定义一个属于自己的ConfigurableWebBindingInitializer 来替换默认的,只需要将自己写的祖册到容器中

If you want to keep those Spring Boot MVC customizations and make more MVC customizations (interceptors, formatters, view controllers, and other features), you can add your own @Configuration class of type WebMvcConfigurer but without@EnableWebMvc.

If you want to provide custom instances of RequestMappingHandlerMapping, RequestMappingHandlerAdapter, or ExceptionHandlerExceptionResolver, and still keep the Spring Boot MVC customizations, you can declare a bean of type WebMvcRegistrations and use it to provide custom instances of those components.

If you want to take complete control of Spring MVC, you can add your own @Configuration annotated with @EnableWebMvc, or alternatively add your own @Configuration-annotated DelegatingWebMvcConfiguration as described in the Javadoc of @EnableWebMvc.

2. 扩展SpringMVC
<mvc:view-controller path="/JJ" view-name="test2"/>
    <mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/JJ"/>
            <bean>bean>
        mvc:interceptor>
    mvc:interceptors>

步骤: 编写一个配置类(@Configuration),属于WebMvcConfigurer类型(2.3.0),之前的版本叫做WebMvcConfigurerApapter;不能是@EnableWebMvc


@Configuration
//@EnableWebMvc
public class MyMvcConfig implements WebMvcConfigurer{
     
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
     
            registry.addViewController("/JJ").setViewName("test2");
            registry.addViewController("/").setViewName("test2");
    }
}

原理:

1. WebMvcConfigurer 是SpringMVC的自动配置类
2. 当我们配置好的时候启动项目,容器中所有的WebMvcConfigurer  都会一起起作用
	3. 我们的配置类也会生效

3.3 全面接管SpringMVC

@EnableWebMvc:SpringBoot对SpringMVC的自动配置已经不需要了。所有的都需要我们自已配置;所以SprigMVC的自动配置失效了;

实现: 只需要在配置类中加入@EnableWebMvc注解

// WebMvcConfigurer 可以扩展SpringMVC中的功能
@Configuration
@EnableWebMvc
public class MyMvcConfig implements WebMvcConfigurer{
     
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
     
            registry.addViewController("/JJ").setViewName("test2");
            registry.addViewController("/").setViewName("test2");
    }
}

原理:

​ 为什么加入@EnableWebMvc之后自动配置就失效了?

1、@EnableWebMvc的核心

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(DelegatingWebMvcConfiguration.class) 
public @interface EnableWebMvc {
     
}
@Configuration(proxyBeanMethods = false)
public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {
     

3、

@ConditionalOnMissingBean(WebMvcConfigurationSupport.class) // 容器中没有WebMvcConfigurationSupport 配置类才生效
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
@AutoConfigureAfter({
      DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class,
		ValidationAutoConfiguration.class })
public class WebMvcAutoConfiguration {
     

4、@EnableWebMvc将所有的WebMvcConfigurationSupport组件导入进来

5、导入的WebMvcConfigurationSupport只是SpringMVC中最基本的功能

3.4 如何去修改SpringBoot的默认配置

模式:

​ 1. SpringBoot在自动配置很多组件的时候,先看容器中有没有用户自己配置的(@Bean,@Component),如果有就用用户自己配置的,如果没有才会进行自动配置。如果说有一些组件可以配置多个(ViewResolver)会将用户配置和自己默认的配置组合起来。

​ 2. SpringBoot中会有很多的XXXXConfigurer帮我们去自定义扩展配置

​ 3. SpringBoot中会有很多的XXXXCustomizer帮我们去定制配置

4. RestFul CRUD

4.1 首页

1. 默认访问首页
 1. 写一个转发的方法
@Controller
public class LoginController {
     

    @RequestMapping({
     "/","login.html"})
    public String dpPage(){
     
        return "login";
    }
}

  1. 自定义配置文件
@Configuration
public class MyConfig {
     

    @Bean
    public WebMvcConfigurer webMvcConfigurer(){
     
        WebMvcConfigurer webMvcConfigurer = new WebMvcConfigurer() {
     
            @Override
            public void addViewControllers(ViewControllerRegistry registry) {
     
                registry.addViewController("/").setViewName("login");
                registry.addViewController("/login.html").setViewName("login");
            }
        };
        return webMvcConfigurer;
    }

}
  1. 自行修改页面中的静态资源路径

4.2 国际化

  1. 需要编写国际化相关的配置文件

     2.  使用ResourceBundleMessageSource管理国际化资源文件(Springboot中已经自动配置了)
     3.  jsp的时候使用fmt:message取出国际化内容(Springboot中使用#{})
    

步骤:

​ 1. 编写国际化配置文件,抽取页面需要显示的国际化(汉化)内容

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8lbkvdH0-1591951707049)(C:\Users\JiangXinWei\Desktop\springBoot笔记\springBoot笔记\images\10.png)]

  1. SpringBoot自动配置好了管理国际化文件的组件
public class MessageSourceProperties {
     

	/**
	 * Comma-separated list of basenames (essentially a fully-qualified classpath
	 * location), each following the ResourceBundle convention with relaxed support for
	 * slash based locations. If it doesn't contain a package qualifier (such as
	 * "org.mypackage"), it will be resolved from the classpath root.
	 */
	private String basename = "messages";
// 我们的配置文件可以直接放在类路径下叫messages.properties
    
    
    
    @Bean
	public MessageSource messageSource(MessageSourceProperties properties) {
     
		ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
		if (StringUtils.hasText(properties.getBasename())) {
     
            // login   login_zh_CN   login_en_US
            // 设置国际化资源文件的基础名(去掉语言和国家代码)
			messageSource.setBasenames(StringUtils
					.commaDelimitedListToStringArray(StringUtils.trimAllWhitespace(properties.getBasename())));
		}
		if (properties.getEncoding() != null) {
     
			messageSource.setDefaultEncoding(properties.getEncoding().name());
		}
		messageSource.setFallbackToSystemLocale(properties.isFallbackToSystemLocale());
		Duration cacheDuration = properties.getCacheDuration();
		if (cacheDuration != null) {
     
			messageSource.setCacheMillis(cacheDuration.toMillis());
		}
		messageSource.setAlwaysUseMessageFormat(properties.isAlwaysUseMessageFormat());
		messageSource.setUseCodeAsDefaultMessage(properties.isUseCodeAsDefaultMessage());
		return messageSource;
	}
# 指定国际化资源文件
spring.messages.basename=i18n.login
  1. 去页面取出国际化的值:

<html lang="en" xmlns:th="http://www.thymeleaf.org">
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
		<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
		<meta name="description" content="">
		<meta name="author" content="">
		<title>Signin Template for Bootstraptitle>
		
		<link href="asserts/css/bootstrap.min.css" th:href="@{/webjars/bootstrap/3.3.5/css/bootstrap.css}"  rel="stylesheet">
		
		<link href="asserts/css/signin.css" th:href="@{/asserts/css/signin.css}" rel="stylesheet">
	head>

	<body class="text-center">
		<form class="form-signin" action="dashboard.html">
			<img class="mb-4" src="asserts/img/bootstrap-solid.svg" th:src="@{/asserts/img/bootstrap-solid.svg}" alt="" width="72" height="72">
			<h1 class="h3 mb-3 font-weight-normal" th:text="#{login.tip}">Please sign inh1>
			<label class="sr-only">Usernamelabel>
			<input type="text" class="form-control" placeholder="Username" th:placeholder="#{login.username}" required="" autofocus="">
			<label class="sr-only">Passwordlabel>
			<input type="password" class="form-control" placeholder="Password" th:placeholder="#{login.password}" required="">
			<div class="checkbox mb-3">
				<label>
          <input type="checkbox" value="remember-me" /> [[ #{login.remember} ]]
        label>
			div>
			<button class="btn btn-lg btn-primary btn-block" type="submit" th:text="#{login.sign}">Sign inbutton>
			<p class="mt-5 mb-3 text-muted">© 2019-2020p>
			<a class="btn btn-sm">中文a>
			<a class="btn btn-sm">Englisha>
		form>

	body>

html>

效果:

​ 当前只能根据浏览器的语言选项来切换国际化

我们想要的是点击链接进行切换

​ 首先要了解Springboot到底是怎么处理国际化资源的

​ 原理:

​ Locale (区域信息对象); LocaleResolver(获取区域信息对象的)

		@Bean
		@ConditionalOnMissingBean
		@ConditionalOnProperty(prefix = "spring.mvc", name = "locale")
		public LocaleResolver localeResolver() {
     
			if (this.mvcProperties.getLocaleResolver() == WebMvcProperties.LocaleResolver.FIXED) {
     
				return new FixedLocaleResolver(this.mvcProperties.getLocale());
			}
			AcceptHeaderLocaleResolver localeResolver = new AcceptHeaderLocaleResolver();
			localeResolver.setDefaultLocale(this.mvcProperties.getLocale());
			return localeResolver;
		}
// 默认的就是根据请求头带来的区域信息获取Locale进行国际化
  1. 点击链接切换国际化
package com.gm.common;

import org.apache.logging.log4j.util.Strings;
import org.springframework.web.servlet.LocaleResolver;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Locale;

public class MyLocaleResolver implements LocaleResolver {
     
    @Override
    public Locale resolveLocale(HttpServletRequest request) {
     
        String i = request.getParameter("i");
        Locale locale = Locale.getDefault();
        if (!Strings.isEmpty(i)) {
     
            // i = en_US
            String[] s = i.split("_");
            locale = new Locale(s[0],s[1]);
        }
        return locale;
    }

    @Override
    public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) {
     

    }
}
  @Bean
    public LocaleResolver localeResolver(){
     
        return new MyLocaleResolver();
    }

4.3 登录

模拟登录

package com.gm.controller;

import org.apache.logging.log4j.util.Strings;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

@Controller
public class LoginController {
     
//    @PutMapping
//    @DeleteMapping
//    @GetMapping
//    @RequestMapping(value = "/user/login",method = RequestMethod.POST)
    @PostMapping("/user/login")
    public String doLogin(@RequestParam("username") String username,
                          @RequestParam("password") String password,
                          Model model){
     
        if (!Strings.isEmpty(username) && "000000".equals(password)){
     
            // 登录成功
            return "dashboard";
        } else {
     
            // 登录失败
            model.addAttribute("msg","用户名密码错误!");
            return "login";
        }

    }
}

4.4 添加拦截器

package com.gm.common;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class MyInterceptor implements HandlerInterceptor {
     
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
     
        Object user = request.getSession().getAttribute("user");
        if (user == null) {
     
            // 未登录,返回登录页面
            request.setAttribute("msg","没有操作权限,请先登录!");
            request.getRequestDispatcher("/login.html").forward(request,response);
            return false;
        }else {
     
            // 成功登录,进行放行
            return true;
        }
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
     

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
     

    }
}




 @Override
            public void addInterceptors(InterceptorRegistry registry) {
     
                registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**")
                        .excludePathPatterns("/login.html","/","/user/login")
                        .excludePathPatterns("/asserts/**")
                        .excludePathPatterns("/webjars/**");
            }

4.5 CRUD - 员工列表实现

RestFul web service

Restful风格:

RUI : /资源名称/资源标识 HTTP请求方式区分对资源的CRUD操作

普通CRUD RestFul CRUD
添加 addEmp Emp - POST
删除 delEmp?id=xxx Emp/{id} - DELETE
查询 findEmps?id=xxx Emp/{id} - GET
修改 updEmp?id=xxx Emp/{id} - PUT

当前的项目需求: 满足RestFul 风格

功能需求 请求的URI 请求方式
查询所有员工 Emps GET
点击到增加页面 Emp GET
添加 Emp POST
单查询 Emp/{id} GET
修改前的查询 Emp/{id} GET
修改 Emp PUT
删除 Emp/{id} DELETE
  1. 公共页面的提取
<div th:fragment="copy">  
     © 2011 The Good Thymes Virtual Grocery   
div> 

<div th:insert="~{footer :: copy}">div> 
footer : 公共片段存在的页面

~{templatename::selector}: 模板名:: 选择器

 ~{templatename::fragmentname} :模板名:: 片段名


th:insert 效果:把公共页面插入到了获取时包裹的标签中

引入公共页面的方式

th:insert : 将整个公共片段插入到声明引入的元素中

th:replace:将声明的元素替换为公共片段

th:includ:将被引入的片段的内容包含进这个标签中

<footer th:fragment="copy">  
    © 2011 The Good Thymes Virtual Grocery 
footer>


 <div th:insert="footer :: copy">div>
 <div th:replace="footer :: copy">div>
 <div th:include="footer :: copy">div> 



 <div> 
     <footer>     
         © 2011 The Good Thymes Virtual Grocery    
     footer>  
div>

 <footer>   
      © 2011 The Good Thymes Virtual Grocery  
footer>

 <div>   
      © 2011 The Good Thymes Virtual Grocery 
div> 

引入片段的时候传入参数


	<div th:replace="common/header :: header">div>

		<div class="container-fluid">
			<div class="row">
				
				<div th:replace="common/header :: #sidebar(active='Emps')">div>

查询:

@Controller
public class EmployeeController {
     
    @Autowired
    private EmployeeDao employeeDao;

//    @DeleteMapping
//    @PutMapping
//    @PostMapping
//    @RequestMapping(value = "/Emps",method = RequestMethod.POST)
    @GetMapping("/Emps")
    public String findAllEmps(Model model){
     
        Collection<Employee> all = employeeDao.getAll();

        model.addAttribute("emps",all);

        return "emp/list";
    }
}

list.html

<table class="table table-striped table-sm">
							<thead>
								<tr>
									<th>idth>
									<th>姓名th>
									<th>邮箱th>
									<th>性别th>
									<th>部门th>
									<th>生日th>
									<th>操作th>
								tr>
							thead>
							<tbody>
								<tr th:each="emp:${emps}">
									<td th:text="${emp.id}">td>
									<td th:text="${emp.lastName}">td>
									<td th:text="${emp.email}">td>
									<td th:text="${emp.gender==0}?'':''">td>
									<td th:text="${emp.department.getDepartmentName()}">td>
									<td th:text="${#dates.format(emp.birth, 'yyyy-MM-dd HH:mm')}">td>
									<td>
										<button class="btn btn-sm btn-info">编辑button>
										<button class="btn btn-sm btn-danger">删除button>

									td>
								tr>
							tbody>
						table>s

4.6 员工添加

LastName
Email
Gender
department 1 2 3 4 5
Birth
添加
// 点击添加来到添加页面
    @GetMapping("/emp")
    public String toAddPage(Model model){
     
        // 点击查询按钮,应当查出来所有的部门信息,以供选择
        Collection<Department> departments = this.departmentDao.getDepartments();
        model.addAttribute("depms",departments);

        return "emp/add";
    }

    // 添加操作,Springboot web阶段使用的还是SpringMVC,会帮我们自动进行封装
    @PostMapping("/emp")
    public String addEmp(Employee employee){
     
//        System.out.println("得到的员工信息为:" + employee );

        this.employeeDao.save(employee);

        return "redirect:/Emps";
    }

4.7 员工修改

<form action="/emp" th:action="@{/emp}" method="post">
					
						<input type="hidden" name="_method" value="put" th:if="${emp!=null}">
						<input type="hidden" name="id" th:if="${emp!=null}" th:value="${emp.id}">

						<div class="form-group">
							<label>LastNamelabel>
							<input type="text" name="lastName" class="form-control" placeholder="zhangsan" th:value="${emp!=null}?${emp.lastName}">
						div>
						<div class="form-group">
							<label>Emaillabel>
							<input type="email" name="email" class="form-control" placeholder="[email protected]" th:value="${emp!=null}?${emp.email}">
						div>
						<div class="form-group">
							<label>Genderlabel><br/>
							<div class="form-check form-check-inline">
								<input class="form-check-input" type="radio" name="gender" th:checked="${emp!=null}?${emp.gender==1}"  value="1">
								<label class="form-check-label">label>
							div>
							<div class="form-check form-check-inline">
								<input class="form-check-input" type="radio" name="gender" th:checked="${emp!=null}?${emp.gender==0}" value="0">
								<label class="form-check-label">label>
							div>
						div>
						<div class="form-group">
							<label>departmentlabel>
							<select class="form-control" name="department.id">
								<option th:each="depm:${depms}" th:value="${depm.id}" th:selected="${emp!=null}?${depm.id == emp.department.id}" th:text="${depm.departmentName}">部门option>
							select>
						div>
						<div class="form-group">
							<label>Birthlabel>
							<input type="text" name="birth" class="form-control" placeholder="zhangsan" th:value="${emp!=null}?${#dates.format(emp.birth, 'yyyy-MM-dd')}">
						div>
						<button type="submit" class="btn btn-primary" th:text="${emp!=null}?'修改':'添加'">添加button>
					form>

    // 点击编辑到页面,显示员工信息
    @GetMapping("/emp/{id}")
    public String toUpdPage(@PathVariable("id") Integer id,Model model){
     
        Employee employee = this.employeeDao.get(id);
        model.addAttribute("emp",employee);
        // 点击查询按钮,应当查出来所有的部门信息,以供选择
        Collection<Department> departments = this.departmentDao.getDepartments();
        model.addAttribute("depms",departments);
        return "emp/add";
    }


    // 修改
    @PutMapping("/emp")
    public String updEmp(Employee employee){
     
        this.employeeDao.save(employee);

        return "redirect:/Emps";
    }

4.8 员工删除

方法、

<button th:attr="action_uri=@{/emp/}+${emp.id}"  class="btn btn-sm btn-danger delete" >删除button>

<form  id="deleteEmpForm" method="post">
	<input type="hidden" name="_method" value="delete">
form>


<script>
	$(".delete").click(function () {
      
		$("#deleteEmpForm").attr("action",$(this).attr("action_uri")).submit();
		return false;
	});
script>

4.9 退出登录

    @GetMapping("/user/logout")
    public String logOut(HttpSession session){
     
//        session.invalidate();
        session.removeAttribute("user");
        return "login";
    }

5. 配置嵌入式Servlet容器

Springboot 默认使用Tomcat作为嵌入式的servlet容器

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rmQTxXJk-1591951707050)(C:\Users\Administrator\Desktop\springBoot笔记\springBoot笔记\images\12.png)]

问题?

5.1.如何去修改servlet容器相关的配置:

​ 1. 修改个server有关的配置(serverProperties)

server.port=8081
server.servlet.context-path=/crud

server.tomcat.uri-encoding=utf-8
  1. 自定义WebServerFactoryCustomizer
// serverProperties 在底层最终会实现WebServerFactoryCustomizer
    @Bean
    public WebServerFactoryCustomizer<ConfigurableServletWebServerFactory> myServer(){
     

        return new WebServerFactoryCustomizer<ConfigurableServletWebServerFactory>() {
     
            @Override
            public void customize(ConfigurableServletWebServerFactory factory) {
     
                factory.setPort(8083);
            }
        };
    }

5.2 注册servlet中的三大组件: Servlet、Filter、Listener

自定义Servlet: **ServletRegistrationBean**
@Bean
    public ServletRegistrationBean<MyServlet> myServlet(){
     
        ServletRegistrationBean<MyServlet> myServlet = new ServletRegistrationBean<>(new MyServlet(),"/MyServlet");

        return myServlet;

    }

​ 自定义Filter: FilterRegistrationBean

 @Bean
    public FilterRegistrationBean<MyFilter> myFilter(){
     
        FilterRegistrationBean<MyFilter> myFilter = new FilterRegistrationBean<>();
        myFilter.setFilter(new MyFilter());
        myFilter.setUrlPatterns(Arrays.asList("/hello","/MyFilter"));
        return myFilter;
    }

​ 自定义 Listener: ServletListenerRegistrationBean

@Bean
    public ServletListenerRegistrationBean<MyListener> myListener(){
     

        ServletListenerRegistrationBean<MyListener> myListener = new ServletListenerRegistrationBean<>();
        myListener.setListener(new MyListener());
        return myListener;
    }

SpringBoot 在自动配置SpringMVC时,自动注册了SpringMVC中的前端控制器:DispatcherServlet

@Bean(name = DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME)
		@ConditionalOnBean(value = DispatcherServlet.class, name = DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)
		public DispatcherServletRegistrationBean dispatcherServletRegistration(DispatcherServlet dispatcherServlet,
				WebMvcProperties webMvcProperties, ObjectProvider<MultipartConfigElement> multipartConfig) {
     
			DispatcherServletRegistrationBean registration = new DispatcherServletRegistrationBean(dispatcherServlet,
					webMvcProperties.getServlet().getPath());
            /*
            	默认拦截: / 所有请求,包括静态资源,但是会放行.jsp请求
            			/*  所有请求,包括静态资源,同时拦截JSp请求
            			
            			*.do
            			
            			可以通过spring.mvc.servlet.path来修改SpringMVC前端控制器默认拦截的路径
            */
            
			registration.setName(DEFAULT_DISPATCHER_SERVLET_BEAN_NAME);
			registration.setLoadOnStartup(webMvcProperties.getServlet().getLoadOnStartup());
			multipartConfig.ifAvailable(registration::setMultipartConfig);
			return registration;
		}

你可能感兴趣的:(java)