Springboot复习1

Springboot复习1

新建一个空的maven工程

pom.xml里:

  <?xml version="1.0" encoding="UTF-8"?>
  <project xmlns="http://maven.apache.org/POM/4.0.0"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
      <modelVersion>4.0.0</modelVersion>
      <!--导入父工程-->
      <parent>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-parent</artifactId>
          <version>2.1.3.RELEASE</version>
      </parent>
      <groupId>com.wsk.springboot</groupId>
      <artifactId>springboot_helloworld</artifactId>
      <version>1.0-SNAPSHOT</version>
      <!--springboot打包方式啥都没写就是jar-->
      <!--<packaging>jar</packaging>-->
      <!--加入web场景启动器-->
      <dependencies>
          <dependency>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-starter-web</artifactId>
          </dependency>
      </dependencies>
  </project>

新建一个helloworld

  package com.wsk.springboot;
 
  import org.springframework.boot.SpringApplication;
  import org.springframework.boot.autoconfigure.SpringBootApplication;
 
  //springboot程序的入口
  //表明次类是入口
  @SpringBootApplication
  public class HelloWorld {
      public static void main(String[] args) {
          SpringApplication.run(HelloWorld.class,args);
      }
  }

这就可以正常运行了,访问8080页面会报404,这时我们新建可以控制层,让他访问hello

  package com.wsk.springboot;
 
 
  import org.springframework.web.bind.annotation.GetMapping;
  import org.springframework.web.bind.annotation.RestController;
 
  @RestController
  public class HelloWorldController {
      @GetMapping("hello")
      public String hello(){
          return "ok";
      }
  }

这里面有两个组合注解RestController,GetMapping

这时访问http://localhost:8080/hello,会给你返回一个ok

注意:控制层要与定义的boot入口是同级或者是入口的子集,不然会报404

 

简化依赖和配置

不引入依赖的情况加package它只是一个普通的jar包

引入springboot插件

  <!-- 引入springboot插件;打包插件 -->
      <build>
          <plugins>
              <plugin>
                  <groupId>org.springframework.boot</groupId>
                  <artifactId>spring-boot-maven-plugin</artifactId>
              </plugin>
          </plugins>
      </build>

再package他就多了很多东西

也可以把项目停了,在打包目录shift右击,在此处打开PowerShell窗口

  java -jar .\springboot_helloworld-1.0-SNAPSHOT.jar

运行完继续访问http://localhost:8080/hello,还是返回ok(不行的话就clean一下,继续package)

 

快速创建springboot应用

创建Spring Starter Project; 必须联网创建(记得看一看java11新特性)

这里只需要勾选springWEB,新建项目即可

系统默认的:

  @SpringBootApplication
  public class SpringbootHello2Application {
 
      public static void main(String[] args) {
          SpringApplication.run(SpringbootHello2Application.class, args);
      }
 
  }

自己写的

  package com.wsk.springboot.controller;
 
  import org.springframework.web.bind.annotation.GetMapping;
  import org.springframework.web.bind.annotation.RestController;
 
  @RestController
  public class UserController {
      @GetMapping("list")
      public String list(){
          return "好好找工作,运气加身";
      }
  }

application.properties可以修改系统默认配置

  server.port=8081
  server.servlet.context-path=/hi
  #spring.mvc.view.prefix=/WEB-INF/jsp/
  #spring.mvc.view.suffix=.jsp

运行测试

https://docs.spring.io/spring-boot/docs/2.0.7.RELEASE/reference/htmlsingle/#common-application-properties

server.session.timeout=60

server.tomcat.max-threads=800(线程默认500)

server.tomcat.uri-encoding=UTF-8

修改banner

https://www.bootschool.net/ascii-art/search

resources下新建一个banner.txt,里面换成你想要的banner

如:

                  _________________________________________
                .' _____________________________________ '.
                "| .'                                     '. |
                "| |                                       | |
                "| | {                                   | |
                "| |   cout << "Vopec_" << endl;         | |
                "| |   return 0;                         | |
                "| | }                                   | |
                "| |                                       | |
                "| '._____________________________________.' |`*.
                "'._________________________________________.'   `.
                """"""""""""""""""|.   .|""""""""""""""""""     '
            ----------------------__|   |__------------------------`--------------
          /                     /_________\.......-----------.     `.           \
 

 

SpringBoot-yml配置文件

  • SpringBoot使用一个全局的配置文件,配置文件名是固定的;

  • application.properties

  • application.yml

    • 配置文件的作用:修改SpringBoot自动配置的默认值;SpringBoot在底层都给我们自动配置好;

    • YAML(YAML Ain't Markup Language)

    • YAML A Markup Language:是一个标记语言

    • YAML isn't Markup Language:不是一个标记语言;

  • 标记语言:

    • 以前的配置文件;大多都使用的是 xxxx.xml文件;

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

    • YAML:配置例子

resources下新建file,application.yml(在里面写配置清晰,有层级感yml更有优势)

  server:
    port: 8080
    servlet:
      context-path: /hi
  • xml的例子

  <server>
  <port>8081</port>
  </server>

 

1.1yaml语法:

  • 使用缩进表示层级关系

  • 缩进时不允许使用Tab键,只允许使用空格。

  • 缩进的空格数目不重要,只要相同层级的元素左侧对齐即可

  • 大小写敏感

 

1.2yaml支持的三种数据结构

  • 对象:键值对的集合

  • 数组:一组按次序排列的值

  • 字面量:单个的、不可再分的值

 

值的写法

2.1 字面量:普通的值(数字,字符串,布尔)

  • k: v:字面直接来写;

  • 字符串默认不用加上单引号或者双引号;

  • "":双引号;不会转义字符串里面的特殊字符;特殊字符会作为本身想表示的意思

  • name: "zhangsan \n lisi":输出;zhangsan 换行 lisi

  • '':单引号;会转义特殊字符,特殊字符最终只是一个普通的字符串数据

  • name: 'zhangsan \n lisi':输出;zhangsan \n lisi

 

2.2 对象、Map(属性和值)(键值对):

  • k: v:在下一行来写对象的属性和值的关系;注意缩进

  • 对象还是k: v的方式

     friends:
     lastName: zhangsan
     age: 20
  • 行内写法:

  • friends: {lastName: zhangsan,age: 18}

 

2.3 数组(List、Set)

用- 值表示数组中的一个元素

 pets:
 cat
 dog
 pig

行内写法

 pets: [cat,dog,pig]

 

练习来了:

新建bean,里面封装两个实体类Person,Dog

Person:注意用到注解

@Component指的是实现bean的注入 @ConfigurationProperties(prefix = "person")

@Value可以取配置文件中配置的值,也可以自定义注入值

(prefix = "person")指的是扫application.yml里的person配置,进行配置绑定

 @Value(${person.lastName})或者@Value("张三")

 

 package com.wsk.springboot.bean;
 
 
 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 Person {
     @Value(${person.lastName})
     private String lastName;
     private int age; private boolean boss;
     private Date birth;
     private Map<String,Object> maps;
     private List lists;
 
     @Override
     public String toString() {
         return "Person{" +
                 "lastName='" + lastName + '\'' +
                 ", age=" + age +
                 ", boss=" + boss +
                 ", birth=" + birth +
                 ", maps=" + maps +
                 ", lists=" + lists +
                 ", dog=" + dog +
                 '}';
    }
 
     public String getLastName() {
         return lastName;
    }
 
     public void setLastName(String lastName) {
         this.lastName = lastName;
    }
 
     public int getAge() {
         return age;
    }
 
     public void setAge(int age) {
         this.age = age;
    }
 
     public boolean isBoss() {
         return boss;
    }
 
     public void setBoss(boolean boss) {
         this.boss = boss;
    }
 
     public Date getBirth() {
         return birth;
    }
 
     public void setBirth(Date birth) {
         this.birth = birth;
    }
 
     public Map<String, Object> getMaps() {
         return maps;
    }
 
     public void setMaps(Map<String, Object> maps) {
         this.maps = maps;
    }
 
     public List getLists() {
         return lists;
    }
 
     public void setLists(List lists) {
         this.lists = lists;
    }
 
     public Dog getDog() {
         return dog;
    }
 
     public void setDog(Dog dog) {
         this.dog = dog;
    }
 
 
 
     private Dog dog;
 
     public Person() {
    }
 }

Dog:

 package com.wsk.springboot.bean;
 
 public class Dog {
     private String name;
     private int age;
 
     @Override
     public String toString() {
         return "Dog{" +
                 "name='" + name + '\'' +
                 ", age=" + age +
                 '}';
    }
 
     public String getName() {
         return name;
    }
 
     public void setName(String name) {
         this.name = name;
    }
 
     public int getAge() {
         return age;
    }
 
     public void setAge(int age) {
         this.age = age;
    }
 }

接着配置application.yml

 person:
  lastName: hello
  age: 18
  boss: false
  birth: 2017/12/12
  maps: {k1: v1,k2: 12}
  lists:
    ‐ lisi
    ‐ zhaoliu
  dog:
    name: 小狗
    age: 12

控制层,让他返回一个Person对象

 @RestController
 public class TestController {
     @Autowired
     private Person person;
     @GetMapping("test")
     public Person test(){
         return person;
    }
 }

这边写完程序能正常运行,但是person还是会报红线,这时pom里加个

 <dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-configuration-processor</artifactId>
     <optional>true</optional>
 </dependency>

即可

效验之前看

 @ConfifigurationProperties@Value
功能 批量注入配置文件中的属性 一个个指定
松散绑定(松散语法) 支持 不支持
SpEL 不支持 支持
JSR303数据校验 支持 不支持
复杂类型封装 支持 不支持
  1. 配置文件yml还是properties他们都能获取到值;

  2. 如果说,我们只是在某个业务逻辑中需要获取一下配置文件中的某项值,使用@Value;

  3. 如果说,我们专门编写了一个javaBean来和配置文件进行映射,我们就直接使用@ConfifigurationProperties;

 

效验:

@Validated

 <!--效验的场景启动器-->
 <dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-validation</artifactId>
 </dependency>
 @Component
 @ConfigurationProperties(prefix = "person")
 //@Validated//效验 也可以后台效验
 public class Person {
     //@Value("${person.lastName}")
     @Email //会对属性值lastName 进行效验 @email就是效验email
     @NotNull
     private String lastName;
     private int age;
     private boolean boss;
     private Date birth;
     private Map<String, Object> maps;
     private List lists;
     private Dog dog;

后台效验

 @RestController
 public class TestController {
 //   @Autowired
 //   private Person person;
     @GetMapping("test")
     public Person test(@Validated Person person){
         return person;
    }
 }

由于lastName效验完不是@email格式,所以会报错

 

自定义properties配置

新建person.properties

 person.lastName=张三

Person中

 @Component
 @PropertySource(value={"person.properties"})//添加自定义properties文件使用
 @ConfigurationProperties(prefix = "person")//读取配置文件中person前缀的内容给属性赋值
 //@Validated//效验 也可以后台效验
 public class Person {
     //@Value("${person.lastName}")
 //   @Email //会对属性值lastName 进行效验 @email就是效验email
 //   @NotNull
     private String lastName;
     private int age;
     private boolean boss;
     private Date birth;
     private Map<String, Object> maps;
     private List lists;
     private Dog dog;

控制层

 @RestController
 public class TestController {
     @Autowired
     private Person person;
     @GetMapping("test")
     public Person test(){
         return person;
    }
 }

 

使用自定义xml文件

 @ImportResource(locations = {"classpath:bean.xml"})

新建一个bean.xml

 <?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 class="com.wsk.springboot.service.PersonService"></bean>
 </beans>

建一个空的service

package com.wsk.springboot.service;

public class PersonService {
}

控制层注入service

 @RestController
 public class TestController {
     @Autowired
     private Person person;
     @Autowired
     private PersonService personService;
     @GetMapping("test")
     public Person test(){
         System.out.println(personService);
         return person;
    }
 }

程序入口新增注解

 @SpringBootApplication
 @ImportResource(locations = {"classpath:bean.xml"})//这就是自定义xml方式注入
 public class SpringbootYmlApplication {
 
     public static void main(String[] args) {
         SpringApplication.run(SpringbootYmlApplication.class, args);
    }
 
 }

另外自定义properties注解写到入口也行,只要保证被读取了就可以

 @PropertySource(value={"person.properties"})//添加自定义properties文件使用

 

新建Config配置类

config包下,config与controller同级

 /**
 * @Configuration:指明当前类是一个配置类;就是来替代之前的Spring配置文件
 *
 * 在配置文件中用<bean><bean/>标签添加组件
 *
 */
 
 @SpringBootConfiguration
 public class SpringConfig {
     //将方法的返回值添加到容器中;容器中这个组件默认的id就是方法名
     @Bean
     public PersonService getPersonService(){
         System.out.println("配置类@Bean给容器中添加组件了...");
         return new PersonService();
    }
 }

等价于resource下的bean.xml:

 <?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 class="com.wsk.springboot.service.PersonService"></bean>
 </beans>

controller也可以手动装配,也可以直接Autowired不动

 @RestController
 public class TestController {
     @Autowired
     private Person person;
     @Resource(name = "getPersonService")
     private PersonService personService;
     @GetMapping("test")
     public Person test(){
         System.out.println(personService);
         return person;
    }
 }

config里的方法名就是controller中的@Resouce的name对应的id

 

注意:

1、配置类@Confifiguration------>Spring配置文件

2、使用@Bean给容器中添加组件

 

 

 

springboot-自动配置原理

@SpringBootApplication点进去

自动配置分析

元注解:这四个是声明注解的注解

  @Target({ElementType.TYPE}) //标注此注解的注解能写在什么地方
  @Retention(RetentionPolicy.RUNTIME) //保持的策略 RUNTIME是在源码期,字节码期间,运行时都生效
  @Documented //自动生成JavaDoc文档
  @Inherited //能被继承
  @SpringBootConfiguration //作用等价于@Configuration 被标注的类作为一个配置文件
  @ComponentScan //扫包的 默认扫当前包及当前包的子包
  @EnableAutoConfiguration //允许自动配置
  @AutoConfigurationPackage 自动配置包 相当于<context:component-scan   package=”当前包路径”>
  • SpringBoot所有的东西都自动配置好了;

    1. spring-boot-autoconfigure-2.0.7.RELEASE.jar(自动配置包)

    2. 好多的场景全部自动配置好

  • 自动配置原理:

    1. 主程序类标注了@SpringBootApplication注解相当于标注了@EnableAutoConfiguration

    2. @EnableAutoConfiguration 开启SpringBoot的自动配置功能

  • 就会自动的将所有的自动配置类导进来

如:HttpEncodingAutoConfiguration(http编码的自动配置)

  1. @ConditionalOnXX根据当前系统环境判断我这个类的所有配置是否需要生效

  2. 会发现这些配置类中使用@Bean给容器中放了好多组件,这些组件就生效;

  3. 这些组件会从一个类中(配置文件属性值的封装类)获取到它应该使用的值是什么。比如HttpEncodingProperties获取charset

  4. 这写配置文件值的封装类都是和配置文件一一绑定

    @ConfigurationProperties(prefix = "spring.http.encoding")

    HttpEncodingProperties

  • 使用心得

    1. SpringBoot帮我们配好了所有的场景

    2. SpringBoot中会有很多的 xxxxAutoConfigurarion(帮我们给容器中自动配好组件)

    3. xxxxAutoConfigurarion给容器中配组件的时候,组件默认的属性一般都是从 xxxProperties中获取这些属性的值

    4. xxxProperties 是和配置文件绑定的(属性一一对应)

    5. 我们改掉这些默认配置即可;

    6. 如果默认的组件我们不用;

      1. @Bean

        @ConditionalOnMissingBean:容器中没这个组件

        public InternalResourceViewResolver defaultViewResolver()

        SpringBoot的一个最大策略:自定义组件用自己的,否则,使用默认的。

源码分析:

步骤1:查看类导入选择器源码

img

步骤2:查看选择导入的方法

img

步骤3:查看getAutoConfigurationEntry源码

img

步骤4:查看getCandidateConfigurations源码

img

步骤4-1:查看getSpringFactoriesFactoryClass()源码

img

img

 

综上:会到spring.boot.enableautoconfiguration类所在的jar包----->META-INF/spring.factories进行加载

img

加载此配置:加载此处指定的所有类

img

 

Debug调试:

img

 

posted @ 2022-07-25 15:00  为了她  阅读(37)  评论(0编辑  收藏  举报