SpringBoot学习笔记

目录

一、什么是springboot?

二、为什么要学SpringBoot?

1、SpringBoot的依赖管理

2、SpringBoot实现自动配置

自动配置SpringMVC、tomcat

3、开发导入starter场景启动器

三、怎么用springboot?

JavaConfig(@Configuration)

@ImportResource

@PropertyResource

创建Spring Boot项目

1、使用国外的Spring提供的初始化器, 就是向导创建SpringBoot应用

2、使用国内的Spring提供的初始化器, 就是向导创建SpringBoot应用

3、第三种方式 使用 maven 向导创建项目

@SpringBootApplication注解

启动springboot的主程序后发生了什么

SpringBoot项目创建的一般步骤

1)想要开发什么就引入对应的starter场景依赖

2)看引入的starter自动配置了哪些组件(可以选做,因为这是底层原理,我们只要开发即可)

3)看哪些组件的默认配置需要改

4)自定义组件

配置自定义的组件

SpringBoot的核心配置文件

SpringBoot应用的多环境配置

@Value 注解

@ConfigurationProperties

在SpringBoot中使用jsp

使用SpringBoot中的容器

ComnandLineRunner 接口 , ApplcationRunner接口

SpringBoot中的拦截器

SpringBoot中使用Servlet

SpringBoot中使用Filter过滤器

在SpringBoot中使用CharacterEncodingFilter(字符集过滤器)

SpringBoot中操作数据库

@Mapper注解

@MapperScan

mapper接口和映射文件分开

开启MyBatis日志功能

 ⭐SpringBoot事务处理

接口架构风格 —RESTful

SpringBoot中的一些重要注解

在页面中或Ajax中实现put、delete请求

SpringBoot中操作Redis

 1)添加web和redis的起步依赖​编辑

2)在springboot核心配置文件中指定redis的配置信息

3)编写程序和Redis进行交互

4)RedisTemplate和StringRedisTemplate的区别

5)RedisTemplate自定义序列化方式

 6)设置IDEA可自动在类中生成序列化版本号

7)JSON序列化数据存储到Redis中

SpringBoot中集成Dubbo

1)创建公共接口工程项目

2)创建服务提供者

3)创建服务消费者


一、什么是springboot?

  • SpringBoot 就相当于不需要配置文件的Spring+SpringMVC。 常用的框架和第三方库都已经配置好了。拿来就可以使用了。
  • SpringBoot是Spring中的一个成员, 可以简化Spring,SpringMVC的使用。 他的核心还是IOC容器。
  • SpringBoot的特点:
    • Create stand-alone Spring applications

      创建spring应用

    • Embed Tomcat, Jetty or Undertow directly (no need to deploy WAR files)

      内嵌的tomcat, jetty , Undertow服务器

    • Provide opinionated 'starter' dependencies to simplify your build configuration

      提供了starter起步依赖,简化应用的配置。

      比如使用MyBatis框架 , 需要在Spring项目中,配置MyBatis的对象 SqlSessionFactory , Dao的代理对象

      在SpringBoot项目中,在pom.xml里面, 加入一个 mybatis-spring-boot-starter依赖

    • Automatically configure Spring and 3rd party libraries whenever possible

      尽可能去配置spring和第三方库。叫做自动配置(就是把spring中的,第三方库中的对象都创建好,放到容器中, 开发人员可以直接使用)

    • Provide production-ready features such as metrics, health checks, and externalized configuration

      提供了健康检查, 统计,外部化配置

    • Absolutely no code generation and no requirement for XML configuration

      不用生成代码, 不用使用xml,做配置

二、为什么要学SpringBoot?

  • 因为Spring, SpringMVC 需要使用的大量的配置文件 (xml文件)比较麻烦,还需要配置各种对象,把使用的对象放入到spring容器中才能使用对象。
  • 需要了解其他框架配置规则,比如在整合mybatis框架就需要配置spring整合mybatis的配置文件applicationContext_mapper.xml。
  • SpringBoot开发效率高,使用方便多了.

1、SpringBoot的依赖管理

我们使用初始化器创建springboot项目的pom文件中都会有这个依赖:

    
        org.springframework.boot
        spring-boot-starter-parent
        2.7.1
         
    

上面依赖的父依赖是:
  
    org.springframework.boot
    spring-boot-dependencies
    2.7.1
  

这个依赖包含了我们很多开发方面所需的常用依赖以及对应的版本,帮我们管理依赖版本。
假如我们要导入的依赖,在这个里面,就不用写版本号了,如果没有就需要自己写。
spring-boot-starter-*

比如springboot项目中开发web方面的依赖spring-boot-starter-web,
引入此依赖无需定义版本。因为父依赖中已经定义好了。
        
            org.springframework.boot
            spring-boot-starter-web
        

2、SpringBoot实现自动配置

自动配置SpringMVC、tomcat

SpringBoot学习笔记_第1张图片

我们使用springmvc配置的中文过滤器、中央调度器、视图解析器等组件,springboot都帮我们导入了。

3、开发导入starter场景启动器

1)我们在使用springboot开发的时候,会导入spring-boot-starter-* 包。*表示不同的场景。springboot帮我们将所有的功能场景都抽取出来,做成一个个启动器。

spring-boot-starter-web             开发web

spring-boot-starter-tomcat        tomcat相关

比如我们要开发web,导入一个spring-boot-starter-web启动器,里面包含了做web模块所需的所有模块,比如: spring、springmvc、tomcat等

SpringBoot学习笔记_第2张图片

2)*-spring-boot-starter: 第三方为我们提供的简化开发的场景启动器

        
            org.mybatis.spring.boot
            mybatis-spring-boot-starter
        
mybatis提供的,整合mybatis用的

3)所有场景启动器最底层的依赖


  org.springframework.boot
  spring-boot-starter
  2.3.4.RELEASE
  compile

三、怎么用springboot?

JavaConfig(@Configuration)

使用java类作为xml配置文件的替代, 是配置spring容器的纯java的方式。 在这个java类这可以创建java对象,把对象放入spring容器中(注入到容器).

使用两个注解:

1)@Configuration : 放在一个类的上面,指明表示这个类是作为一个配置文件使用的。

2)@Bean:声明对象,把对象注入到容器中。

// 表示以下这个类是一个配置文件,
// 相当于applicationContext.xml
@Configuration
public class SpringConfig {

    /**
     * @Bean: 把对象注入到spring容器中。 作用相当于
     *     写在方法上,方法的返回值对象就会被Spring容器管理。
     *     注意:若不指定对象的id,则默认用方法名当对象的id
     */
    @Bean
    public Student getStudent(){

        return new Student("李四",25);
    }

    // 也可以指定对象的id属性
    @Bean(name = "lisiStu")
    public Student getStudent2(){

        return new Student("王五",52);
    }
}
public class MyTest1 {

    @Test
    public void test1(){
        // 创建并启动spring容器
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        Student myStudent = (Student) ac.getBean("myStudent");
        System.out.println("使用xml配置文件的形式取出容器中的对象:" + myStudent);
    }

    @Test
    public void test2(){
        // 使用JavaConfig作为对象创建并启动Spring容器
        // SpringConfig.class 就等于 applicationContext.xml
        ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfig.class);
        Student stu = (Student) ac.getBean("getStudent");
        System.out.println("使用javaconfig对象创建的bean:" + stu);
    }

    @Test
    public void test3(){
        // 使用JavaConfig作为对象创建并启动Spring容器
        // SpringConfig.class 就等于 applicationContext.xml
        ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfig.class);
        Student stu = (Student) ac.getBean("lisiStu");
        System.out.println("使用javaconfig对象创建的bean:" + stu);
    }
}

@ImportResource

@ImportResource

使用在类上

作用导入其他的xml配置文件, 等于在xml配置文件中使用:

要导入的spring配置文件: 




    
        
        
    

// 表示以下这个类是一个配置文件,
// 相当于applicationContext.xml
@Configuration
// 导入其他配置文件
@ImportResource({"classpath:applicationContext.xml"})
public class SpringConfig {

    /**
     * @Bean: 把对象注入到spring容器中。 作用相当于
     *     写在方法上,方法的返回值对象就会被Spring容器管理。
     *     注意:若不指定对象的id,则默认用方法名当对象的id
     */
    @Bean
    public Student getStudent(){

        return new Student("李四",25);
    }

    // 也可以指定对象的id属性
    @Bean(name = "lisiStu")
    public Student getStudent2(){

        return new Student("王五",52);
    }
}
    @Test
    public void test4(){
        // 使用JavaConfig作为对象创建并启动Spring容器
        // SpringConfig.class 就等于 applicationContext.xml
        ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfig.class);
        Student stu = (Student) ac.getBean("myStudent");
        System.out.println("取出导入的配置文件中的bean:" + stu);// 取出导入的配置文件中的bean:Student{name='张三', age=23}

    }

@PropertyResource

@PropertyResource: 用于读取properties属性配置文件,引入属性文件,就可以使用${key}的方式访问里面的值了。 使用属性配置文件可以实现外部化配置 ,在程序代码之外提供数据。

等同于之前的:

cat.properties 

cat.name=tomcat
cat.age=23

@Component("myCat") // 使用spring注解创建对象,交给spring容器管理

// 引入properties属性文件
@PropertySource("classpath:cat.properties")
public class Cat {

    // ${cat.name}使用属性文件的值
    @Value("${cat.name}")
    private String name;

    @Value("${cat.age}")
    private int age;

    @Override
    public String toString() {
        return "Cat{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
// 表示以下这个类是一个配置文件,
// 相当于applicationContext.xml
@Configuration
// 导入其他配置文件
@ImportResource({"classpath:applicationContext.xml"})

// 告诉spring要去扫描这个包下的类,看是否需要创建对象
@ComponentScan(basePackages = "com.lin.spirngboot.bean")
public class SpringConfig {

    /**
     * @Bean: 把对象注入到spring容器中。 作用相当于
     *     写在方法上,方法的返回值对象就会被Spring容器管理。
     *     注意:若不指定对象的id,则默认用方法名当对象的id
     */
    @Bean
    public Student getStudent(){

        return new Student("李四",25);
    }

    // 也可以指定对象的id属性
    @Bean(name = "lisiStu")
    public Student getStudent2(){

        return new Student("王五",52);
    }
}

创建Spring Boot项目

1、使用国外的Spring提供的初始化器, 就是向导创建SpringBoot应用

地址:

https://start.spring.io

SpringBoot学习笔记_第3张图片

在这一步,可以自己手动选择maven需要的依赖,就不用像之前那样一个一个的在pom文件中配置了。 

SpringBoot学习笔记_第4张图片

目录介绍

SpringBoot学习笔记_第5张图片

2、使用国内的Spring提供的初始化器, 就是向导创建SpringBoot应用

国外的速度比较慢,可以使用国内的地址:

https://start.springboot.io

3、第三种方式 使用 maven 向导创建项目

@SpringBootApplication注解

@SpringBootApplication注解是一个复合注解,由以下三个注解组成
        @SpringBootConfiguration
        @EnableAutoConfiguration
        @ComponentScan
  • 1、@SpringBootConfiguration使用了这个注解的类,可以作为一个配置文件来使用,可以使用@Bean声明对象注入到Spring容器中,相当于说明SpringBoot的启动类是一个配置文件。
  • 2、@EnableAutoConfiguration注解表示开启自动配置功能,该注解是Spring Boot框架最重要的注解,也是实现自动化配置的注解。 把java对象配置好,注入到spring容器中。例如可以把mybatis的对象创建好,放入到容器中直接使用。
  • 3、@ComponentScan 包扫描,有了这个注解后,就可以默认扫描@ComponentScan所在的类所在的包和子包。扫描到有创建对象的注解就创建对象,有依赖注入的注解就进行依赖注入等。也就是会扫描SpringBoot的主程序所在的包以及它的子包。

启动springboot的主程序后发生了什么

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

}

1、@SpringBootApplication注解表示这是一个spirngboot应用的主程序

这个注解是个复合注解,包含了三个注解的作用:@SpringBootConfiguration @EnableAutoConfiguration @ComponentScan

        1、@SpringBootConfiguration表示这个主程序可以作为一个配置文件来使用,告诉SpringBoot这是一个配置类 == 配置文件。

        2、@EnableAutoConfiguration也是一个复合注解,启动自动的配置,@EnableAutoConfiguration注解的意思就是Springboot根据你添加的jar包来配置你项目的默认配置,比如根据spring-boot-starter-web ,来判断你的项目是否需要添加了webmvc和tomcat,就会自动的帮你配置web项目中所需要的默认配置。                                                                             包含了:@AutoConfigurationPackage                 @Import

                  1、 @AutoConfigurationPackage,指定了默认的包规则。以下就是这个注解,@Import往spring容器中导入bean组件Registrar.class,会利用Registrar往容器中导入一系列组件, Register会将注解所修饰的类所在的包下的组件注册进来,即主程序所在包下的所有组件都会被导入到容器中。

@Import(AutoConfigurationPackages.Registrar.class)
public @interface AutoConfigurationPackage {}

Registrar组件:
static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {

		@Override
		public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
			register(registry, new PackageImports(metadata).getPackageNames().toArray(new String[0]));
		}

		@Override
		public Set determineImports(AnnotationMetadata metadata) {
			return Collections.singleton(new PackageImports(metadata));
		}

	}

                2、@Import 默认先把127个场景的自动配置类xxxAutoConfiguration先都加载,然后再根据@Condition注解加载满足条件的自动配置类。这些条件是根据我们自己导入的starter进行判断。自动配置类加载到容器中后,这些配置类可以提供很多组件,这些组件有了,我们就不用配了,直接用。

比如:HttpEncodingAutoConfiguration编码自动配置类,就给我们提供了中文编码过滤器bean放到容器中,组件一般会有默认的属性值,比如字符集值,这些属性值是从xxxProperties中取,而这个xxxProperties又和spring boot的核心配置文件.yml绑定,所以我们如果想要修改组件的默认值,就可以直接在.yml文件中配置实现定制化配置,server.servlet.encoding设置编码过滤器组件的默认配置,比如:server.servlet.encoding.charset=GBK设置字符集。

还有DispatcherServletAutoConfiguration自动配置类提供DispatcherServlet给我们。

@EnableConfigurationProperties(ServerProperties.class)
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
@ConditionalOnClass(CharacterEncodingFilter.class)
@ConditionalOnProperty(prefix = "server.servlet.encoding", value = "enabled", matchIfMissing = true)

HttpEncodingAutoConfiguration 自动配置类需要满足以下三个条件才会生效:
1、当前web项目是传统的servlet项目时
2、当存在指定的类CharacterEncodingFilter时(导入webmvc包就有了)
3、当springboot核心配置文件application.yml(properties)中
server.servlet.encoding属性值为enabled时,就算没有的话也生效,因为matchIfMissing = true


public class HttpEncodingAutoConfiguration {

	@Bean
	@ConditionalOnMissingBean
	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;
	}

}

          3、@ComponentScan 指定扫描哪些包,扫描了发现有注解的则创建组件放进容器,Spring注解

@ComponentScan
(excludeFilters = 
{ @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) }
)

总结:springboot启动类运行后,主程序会先被当作一个配置文件加载,然后扫描主程序所在包以及子包,根据注解(@Component、@Respository、@Service、@Controller)创建bean放进IOC容器中,最后根据引入的starter启用相应的自动配置类(用于提供组件)。

自动配置:按需加载xxxAutoConfiguration自动配置类==》提供组件==》组件的属性来自xxxProperties==》xxxProperties又和.yml文件绑定

SpringBoot项目创建的一般步骤

1)想要开发什么就引入对应的starter场景依赖

springboot官方提供的:spring-boot-starter-*

其他人提供的:*-spring-boot-starter

spring-boot-starter 这是Spring Boot的核心启动器,提供了日志和YAML和banner图等组件。

spring-boot-starter-web web开发,提供了中文过滤器以及DispatcherServlet转发器等组件。

2)看引入的starter自动配置了哪些组件(可以选做,因为这是底层原理,我们只要开发即可)

在springboot的核心配置文件.yml中加入:debug=true,然后启动项目,就可以在控制台看到哪些组件生效了,Negative(不生效)\Positive(生效)。

3)看哪些组件的默认配置需要改

自动配置类提供的组件有时需要改它的默认配置,比如中文过滤器的字符集、数据库的账号密码等

a.参考文档修改组件的配置:

      • Common Application Properties

b.自己分析自动配置类绑定的配置文件前缀

比如:HttpEncodingAutoConfiguration这个自动配置类是提供中文过滤器的,这个自动配置类的前缀就是server.servlet.encoding,就可以在springboot的核心配置文件.yml文件中配置这个自动配置类提供的组件的相关配置了。

SpringBoot学习笔记_第6张图片

@AutoConfiguration
@EnableConfigurationProperties(ServerProperties.class)
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
@ConditionalOnClass(CharacterEncodingFilter.class)
@ConditionalOnProperty(prefix = "server.servlet.encoding", value = "enabled", matchIfMissing = true)
public class HttpEncodingAutoConfiguration {


	@Bean
	@ConditionalOnMissingBean
	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;
	}

4)自定义组件

对他们提供的组件不满意,可以自己在配置类中加入组件或者替换组件,使用注解@Bean,用户自己提供了组件,springboot原来的组件就不会生效了。

还有自定义器xxxCustomizer

.....

配置自定义的组件

我们可以自己提供一些组件到容器中供自己使用。

@Data
@Component// 自定义组件

// 组定义的组件的相关配置可以绑定到springboot核心配置文件中,然后在核心配置文件中配置组件
@ConfigurationProperties(prefix = "person")
public class Person {

    private String userName;
    private Boolean boss;
    private Date birth;
    private Integer age;
    private Pet pet;
    private String[] interests;
    private List animal;
    private Map score;
    private Set salarys;
    private Map> allPets;
}

组件的相关配置可以和application.yml文件绑定,就可以在这个文件中定义组件的配置,但是要想配置的时候可以提示配置项,需要引入一个依赖

!--配置处理器,组件绑定配置文件提示功能-->
        
            org.springframework.boot
            spring-boot-configuration-processor
            true
        


        
            
                org.springframework.boot
                spring-boot-maven-plugin

                
                
                    
                        
                        
                            org.springframework.boot
                            spring-boot-configuration-processor
                        
                    
                
            
        
    

这样在配置文件yml中配置我们自己的组件就有提示了:

SpringBoot学习笔记_第7张图片

配置我们的组件person

# yaml表示以上对象
person:
  userName: zhangsan
  boss: false
  birth: 2019/12/12 20:12:33
  age: 18
  pet: 
    name: tomcat
    weight: 23.4
  interests: [篮球,游泳]
  animal: 
    - jerry
    - mario
  score:
    english: 
      first: 30
      second: 40
      third: 50
    math: [131,140,148]
    chinese: {first: 128,second: 136}
  salarys: [3999,4999.98,5999.99]
  allPets:
    sick:
      - {name: tom}
      - {name: jerry,weight: 47}
    health: [{name: mario,weight: 47}]



------------------------------------
person:
  user-name: 人组件
  boss: true
  birth: 2021/2/12
  age: 23
  pet:
    name: tom猫
    weight: 23.3
  interests: [打游戏,看电影]
  animal: [阿猫,阿狗]
  score: {"math":99,"eng":23}
  salarys: [23.2,23.5]
  all-pets: {
    dogs:[{name: 狗1,weight: 3},{name: 狗2,weight: 2}],
    cats:[{name: 猫1,weight: 3},{name: 猫2,weight: 2}]
  }

SpringBoot的核心配置文件

  •  Spring Boot 的核心配置文件用于配置 Spring Boot 程序,文件名字必须以 application 开始。
  • application.properties(.yml)是spring-boot的核心配置文件,这个配置文件基本可以取代我们ssm或者ssh里面的所有的xml配置文件。
  • 当我们的SpringBoot项目启动的第一时间就是加载我们的配置文件。
  • 在此配置文件中,可以配置Springboot应用的端口号,上下文访问路径等。

配置文件扩展名有两种:

        .properties

        .yml

如果两种扩展名的配置文件一样,默认使用.properties的配置文件

推荐使用 yml 格式配置文件

application.yml

#设置Springboot应用的端口号和上下文访问路径contextPath
server:
  port: 8082
  servlet:
    context-path: /myboot

 application.properties

#设置端口号
server.port=8082
#设置访问应用上下文路径, contextpath
server.servlet.context-path=/myboot

SpringBoot应用的多环境配置

在实际开发的过程中,我们的项目会经历很多的阶段(开发->测试->上线),每个阶段的配置也会不同,例如:端口、上下文路劲、数据库等,那么这个时候为了方便在不同的环境 
之间切换对应的配置,SpringBoot 提供了多环境配置。

本地程序员开发的时候所用的配置文件:application-dev.yml
#本地程序员开发的时候所用的配置
server:
  port: 8081
  servlet:
    context-path: /mydev
项目测试的时候所用的配置文件:application-test.yml
#项目测试的时候所用的配置
server:
  port: 8082
  servlet:
    context-path: /mytest
项目上线的时候所用的配置文件:application-online.yml
#项目上线的时候所用的配置
server:
  port: 8083
  servlet:
    context-path: /myonline

最后在springboot项目的主配置文件application.yml中根据环境,指定要使用的配置文件

#在主配置文件中,指定要使用的配置文件

#激活开发的时候的配置文件
#spring:
#  profiles:
#    active: dev

#激活测试的时候的配置文件
spring:
  profiles:
    active: test

@Value 注解

@Value("${key}") , key 来自 application.properties(yml),根据key直接取来自Spring Boot的核心配置文件中的value。

application.properties: 

server.port=9090 
server.servlet.context-path=/myboot 

#自定义的key=value 
school.name=动力节点 
school.address=北京大兴区 
school.website=www.bjpowernode.com 
 
site=www.bjpowernode.com 

 读取配置文件中的数据:

@Controller 
public class HelloController { 
 @Value("${server.port}") 
 private String port; 
 @Value("${school.name}") 
 private String name; 
 
 @Value("${site}") 
 private String site;

 @RequestMapping("/hello") 
 @ResponseBody 
 public String doHello(){ 
 return "hello, port:" + port + "学校:"+name+",网站:"+site; 
 } 
}

@ConfigurationProperties

在 SpringBoot 中,当想需要获取到配置文件数据时,除了可以用 Spring 自带的 @Value 注解外,SpringBoot 还提供了一种更加方便的方式:@ConfigurationProperties。

只要在 Bean 上添加上了这个注解,指定好配置文件的前缀,那么对应的配置文件中的数据就会自动填充到 Bean 中。填充规则就是找到相同名字的key和属性名进行数据注入。

#项目端口号
server:
  port: 8082
  servlet:
    context-path: /myboot

#自定义数据key-value
school:
  name: 莆田学院
  website: www.ptu.com
  address: 福建莆田
package com.lin.bean;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

/**
 * @author shkstart
 * @create 2022-07-03 19:19
 */
@Component// 交给Spring创建对象

// 除了@Value注解, @ConfigurationProperties注解也可以从配置文件中获取数据
// 这样这个bean中的属性就会在application.properties中找前缀为school,
// 然后找到和属性名一样的key将对应的value赋给属性
@ConfigurationProperties(prefix = "school")
public class School {
    private String name;

    private String website;

    private String address;

    @Override
    public String toString() {
        return "School{" +
                "name='" + name + '\'' +
                ", website='" + website + '\'' +
                ", address='" + address + '\'' +
                '}';
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getWebsite() {
        return website;
    }

    public void setWebsite(String website) {
        this.website = website;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public School(String name, String website, String address) {
        this.name = name;
        this.website = website;
        this.address = address;
    }

    public School() {
    }
}
package com.lin.controller;

import com.lin.bean.School;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.Resource;

/**
 * @author shkstart
 * @create 2022-07-03 19:14
 */
@Controller
public class GetDataController {

    // @Value注解可以获取application.properties(yml)中的数据
    @Value("${server.servlet.context-path}")
    private String contextPath;

    @Value("${school.name}")
    private String school;

    // @Resource注解和@Autowired注解类似,都用来声明需要自动装配的bean,
    // 区别在于@Autowired是类型驱动的注入,而@Resource是名称驱动的注入,所以前者存在多bean问题,
    // 而后者,只要保证bean命名唯一就不会出现多bean的问题。
    @Resource
    private School ptu;

    @RequestMapping("/data")
    @ResponseBody
    public String getDate(){

        return "我在"+school+"学" + contextPath + "school对象:" + ptu;
    }
}

在SpringBoot中使用jsp

使用SpringBoot中的容器

如果想要使用容器,然后获取容器中管理的对象的话,得需要先获取容器对象。

// SpringBoot项目启动的方法run()的返回值就是容器
public static ConfigurableApplicationContext run(Class primarySource, String... args) {
        return run(new Class[]{primarySource}, args);
    }
// ApplicationContext就是Spring容器
public interface ConfigurableApplicationContext extends ApplicationContext

例子: 

@Service("userService")// 交给spring创建对象,将对象放进容器中管理
public class UserServiceImpl implements UserService {
    @Override
    public void sayHello(String name) {
        System.out.println("say hello to" + name);
    }
}
@SpringBootApplication
public class Springboot007SpringcontainerApplication {

    public static void main(String[] args) {
        // 获取容器对象
        ConfigurableApplicationContext applicationContext = SpringApplication.run(Springboot007SpringcontainerApplication.class, args);

        // 从容器中取出对象
        UserService userService = (UserService) applicationContext.getBean("userService");
        userService.sayHello("张三");
    }

}

ComnandLineRunner 接口 , ApplcationRunner接口

开发中可能会有这样的情景。需要在容器启动后执行一些内容。比如读取配置文件,数 
据库连接之类的。SpringBoot 给我们提供了两个接口来帮助我们实现这种需求。这两个接口 
分别为 CommandLineRunner 和 ApplicationRunner。他们的执行时机为容器启动完成的时候。 
这两个接口中有一个 run 方法,我们只需要实现这个方法即可,这个方法会在容器启动完之后被调用。这两个接口的不同之处 
在于: ApplicationRunner 中 run 方 法 的 参 数 为 ApplicationArguments , 而 
CommandLineRunner 接口中 run 方法的参数为 String 数组

@SpringBootApplication
public class Springboot008ApplicationRunnerApplication implements ApplicationRunner {

    public static void main(String[] args) {
        System.out.println("创建启动容器之前....");

        // 创建并启动容器
        SpringApplication.run(Springboot008ApplicationRunnerApplication.class, args);

        System.out.println("创建启动容器之后");
    }

    @Override
    public void run(ApplicationArguments args) throws Exception {
        System.out.println("读取配置文件");
    }
}

SpringBoot学习笔记_第8张图片

只要实现CommandLineRunner接口 或 ApplicationRunner接口,然后实现里面的run()方法,就可以在创建启动之后执行。

SpringBoot中的拦截器

以前我们在SpringMVC中使用拦截器,需要在配置文件中配置注册拦截器等,比较麻烦,接下来介绍SpringBoot中优化的拦截器。

而且拦截器拦截的请求是要经过springmvc的DispatcherServlet转发的请求才会被拦截下来,如果是请求原生servlet的不会拦截。

实现步骤:

  1. 创建一个类实现SpringMVC框架的HandlerInterceptor接口
  2. 注册拦截器
  3. 创建controller测试拦截器功能
  4. 在主启动类中启动应用
  5. 在浏览器上访问测试是否被拦截

1

public class LoginInterceptor implements HandlerInterceptor {

    /**
     * 拦截器,这个方法会在请求到达控制层之前拦截起来做预先处理工作.
     *
     * @param request
     * @param response
     * @param handler 请求对应的控制层对象?
     * @return
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        System.out.println("拦截登录相关的请求,验证是否登录过。。。。");

        // 返回true说明登录过,放行请求
        return true;

        // 返回false说明没登录过,不放行请求
//        return false;
    }
}

 2

/**
 * WebMvcConfigurer接口提供了很多方法, 是原本SpringMVC中的xml文件配置
 *
 * @author shkstart
 * @create 2022-07-04 16:26
 */
// 指明这是一个配置文件,相当于springmvc.xml
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {

    // 注册拦截器s,相当于之前在xml配置文件中配置拦截器
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 要拦截的请求uri
        String[] paths = {"/user/**"};

        // 不拦截的请求uri
        String[] excludePaths = {"/user/login",""};

        // 注册具体的拦截器
        registry.addInterceptor(new LoginInterceptor()).addPathPatterns(paths).excludePathPatterns(excludePaths);
    }

}

3

@Controller
public class InterceptorController {

    // 这个请求会被拦截
    @RequestMapping("/user/login")
    @ResponseBody
    public String doLogin(){

        return "我要去登录...";
    }

    // 这个请求不会被拦截
    @RequestMapping("/user/page")
    @ResponseBody
    public String getPageUser(){

        return "获取分页用户数据...";
    }
}

SpringBoot学习笔记_第9张图片

SpringBoot学习笔记_第10张图片

SpringBoot中使用Servlet

在SpringBoot中使用Servlet

ServletRegistrationBean 用来做在 servlet 3.0+容器中注册 servlet 的功能,但更具有
SpringBean 友好性。 

使用步骤:

  1. 创建类实现HttpServlet(使之成为一个servlet)
  2. 注册servlet类,让框架能找到servlet
public class HelloServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=utf-8");
        PrintWriter out = resp.getWriter();
        out.println("hello servlet");
        out.flush();
        out.close();
    }
}

@Configuration
public class ServletConfig {

    /**
     * 注册servlet
     * 将servlet对象和对应的请求路径绑定在一个ServletRegistrationBean对象中,
     * 然后将这个对象放进spring容器中,告诉框架,好让请求的时候框架能够找到servlet然后创建servlet对象.
     *
     * @return
     */
    @Bean
    public ServletRegistrationBean servletRegistrationBean(){
        // public ServletRegistrationBean(T servlet, String... urlMappings)
        // servlet是要注册的servlet对象,urlMappings是servlet对应的请求路径
        ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(new HelloServlet(), "/hello");

        return servletRegistrationBean;
    }
}

SpringBoot中使用Filter过滤器

我们在现实业务中,多个请求对应的不同controller,对于这多个controller来说,可能都会有一些共同的操作要做,比如:设置字符集编码等公共的代码,这时就可以在过滤器中添加过滤规则,请求先经过过滤器的处理后,才能到达下面的controller。

实现步骤:

  1. 创建过滤器类,实现servlet.Filter接口
  2. 注册过滤器,让框架知道
import javax.servlet.*;

public class UserFilter implements Filter {

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("对请求进行处理,进行字符集的设置.......");

        // 若下面没有过滤器了,则执行请求对应的controller
        filterChain.doFilter(servletRequest,servletResponse);
    }
}
@Configuration
public class FilterConfig {

    // 注册过滤器
    @Bean
    public FilterRegistrationBean userFilterBean(){
        FilterRegistrationBean filterBean = new FilterRegistrationBean();

        // 设置过滤器类对象
        filterBean.setFilter(new UserFilter());
        
        // 添加要被过滤的请求路径,请求都被过滤一下再执行对应的controller
        filterBean.addUrlPatterns("/user/*");

        return filterBean;
    }
}

在SpringBoot中使用CharacterEncodingFilter(字符集过滤器)

CharacterEncodingFilter是spring内置的字符集过滤器,用来指定请求或者响应使用的字符集,用来解决请求和响应的乱码问题。

第一种:自定义字符集过滤器 

@Configuration
public class FilterConfig {

    // 注册Spring自带的字符集编码过滤器
    @Bean
    public FilterRegistrationBean characterFilterBean(){
        FilterRegistrationBean filterBean = new FilterRegistrationBean();

        // 创建Spring内置的字符集过滤器对象并设置相关的属性
        CharacterEncodingFilter encodingFilter = new CharacterEncodingFilter();
        encodingFilter.setEncoding("UTF-8");// 设置字符集
        encodingFilter.setForceRequestEncoding(true);// 设置请求是否强制使用设置的字符集
        encodingFilter.setForceResponseEncoding(true);

        // 设置过滤器类对象
        filterBean.setFilter(encodingFilter);

        // 所有路径都过滤一下,处理一下字符集再放行
        filterBean.addUrlPatterns("/*");

        return filterBean;
    }
}

server.servlet.context-path=/filter

#SpringBoot中默认已经配置了CharacterEncodingFilter。 编码默认ISO-8859-1
#设置enabled=false 作用是取消使用SpringBoot配置好的过滤器, 使用自定义的CharacterEncodingFilter
server.servlet.encoding.enabled=false

第二种:使用SpringBoot中默认配置好的CharacterEncodingFilter

#使用SpringBoot默认配置好的CharacterEncodingFilter
server.servlet.encoding.enabled=true

#指定CharacterEncodingFilter的字符集为UTF-8
server.servlet.encoding.charset=UTF-8

#设置请求和响应都强制使用设置的字符集
server.servlet.encoding.force=true

SpringBoot中操作数据库

MyBatis 框架操作数据库,读写 MySQL 数据。通过 SpringBoot +MyBatis 实现对数据库学生表的查询操作。 

使用MyBatis框架操作数据库,在SpringBoot中集成MyBatis框架。

 1.创建模块,添加web、mysql驱动、mybatis依赖等

SpringBoot学习笔记_第11张图片

2、创建mapper接口以及对应的映射文件

@Mapper注解

/**
 * @Mapper注解
 * 告诉MyBatis框架这是你的mapper接口,到时候就会使用动态代理创建Mapper接口的实现类对象
 *
 * 之前ssm的做法:
 *     
 *     
 *         
 *         
 *     
 */
@Mapper
public interface StudentMapper {

    /**
     * 根据学生id获取学生信息
     *
     * @param id
     * @return
     */
    Student getStudentById(@Param("stuId") Integer id);
}


    
    

@MapperScan

在Mapper接口上面加入@Mapper,来由mybatis框架创建动态代理对象,需要在每个接口都加入注解。 当 Mapper 接口多的时候不方便。

可以使用如下的方式解决:
在主启动类上添加注解包扫描:@MapperScan("com.jay.mapper") 

这样就会去扫描com.jay.mapper下的所有mapper接口以及对应的映射文件,并动态代理创建对应的实现类对象。

3、创建service层,新建StudentService以及实现类StudentServiceImpl

public interface StudentService {

    Student getStudentById(Integer stuId);
}
@Service // 创建对象放进Spring容器中,这个对象到时候要在controller中用
public class StudentServiceImpl implements StudentService {

    @Autowired
    private StudentMapper studentMapper;

    @Override
    public Student getStudentById(Integer stuId) {
        Student studentById = studentMapper.getStudentById(stuId);

        return studentById;
    }
}

4.创建StudentController类

@Controller
public class StudentController {

    @Resource
    private StudentService studentService;

    @RequestMapping("/queryStu")
    @ResponseBody
    public String queryForStudent(Integer stuId){

        Student student = studentService.getStudentById(stuId);
        return student.toString();
    }
}

5、在application.properties文件中配置连接数据库的四个基本信息

server.port=8088
server.servlet.context-path=/bootdb

#配置连接数据库的四个基本信息
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/springboot?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8
spring.datasource.username=root
spring.datasource.password=001219

6、测试SpringBoot集成mybatis访问数据库

启动项目访问: 

SpringBoot学习笔记_第12张图片

mapper接口和映射文件分开

这种方式比较推荐,mapper 文件放在 resources 目录下, java 代码放在 src/main/java。 

1、在 resources 创建自定义目录和mapper接口所在的包名一样(这样SpringBoot扫描mapper接口的时候就能一块找到对应的映射文件了,因为他们的包名一样),存放 xml 文件。

SpringBoot学习笔记_第13张图片

 2、如果映射文件的包名和mapper接口的包名不一样的话,需要在 application.properties 配置文件中指定映射文件的位置。 

开启MyBatis日志功能

#指定mapper文件的位置,直接告诉框架映射文件的位置
mybatis.mapper-locations=classpath:mapper/*.xml
#指定mybatis的日志,开启日志功能
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

 ⭐SpringBoot事务处理

Spring Boot 使用事务非常简单,底层依然采用的是 Spring 本身提供的事务管理。

回顾Spring的事务处理:

1) 管理事务的对象: 事务管理器(接口, 根据不同的情况接口有很多的实现类)

例如:使用Jdbc或mybatis访问数据库,使用的事务管理器:DataSourceTransactionManager

2 ) 声明式事务: 在xml配置文件或者使用注解说明事务控制的内容

控制事务: 隔离级别,传播行为, 超时时间

3)事务处理方式:

        1) Spring框架中的@Transactional

        2) aspectj框架可以在xml配置文件中,声明事务控制的内容

SpringBoot中使用事务:

第一种:基于注解的方式

  1. 在service层,在需要事务功能的方法上添加@Transactional 注解
  2. 在SpringBoot的主启动类上加上@EnableTransactionManager 注解

@EnableTransactionManagement表示开启事务支持,开启事务注解驱动支持,在springboot项目中一般配置在启动类上,效果等同于xml配置的.开启事务支持后,然后在访问数据库的Service方法上添加注解 @Transactional 便可配合达成事务的使用。

 service层使用事务:

@Service // 创建对象放进Spring容器中,这个对象到时候要在controller中用
public class StudentServiceImpl implements StudentService {

    @Resource
    private StudentMapper studentMapper;

    /**
     * @Transactional: 表示方法的有事务支持
     *       不设置参数的话,默认:使用数据库库的隔离级别, REQUIRED 传播行为; 超时时间  -1
     *
     *       抛出运行时异常,需要回滚事务,撤销sql语句
     */
    @Transactional
    @Override
    public int addStudent(Student stu) {
        System.out.println("添加学生的业务方法开始执行。。。");
        int i = studentMapper.addStudent(stu);
        System.out.println("添加学生的sql语句已经执行完毕。。。。。");

        // 手动抛出异常,模拟网络异常,需要回滚事务
        int m = 1/0;

        return i;
    }
}

启动类:

@SpringBootApplication
// 会去扫描然后创建对应的实现类
@MapperScan(basePackages = "com.example.mapper")

@EnableTransactionManagement
public class Application {

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

测试事务:

    @RequestMapping("/addstu")
    @ResponseBody
    public String addStudent(Student stu){

        int i = studentService.addStudent(stu);
        return "增加学生成功:" + i;
    }

SpringBoot学习笔记_第14张图片

 取消抛出异常后:

SpringBoot学习笔记_第15张图片

 SpringBoot学习笔记_第16张图片

SpringBoot学习笔记_第17张图片

接口架构风格 —RESTful

这里说的接口,不是Java中的接口interface。

接口: API(Application Programming Interface,应用程序接口)是一些预先定义的接口(如函数、HTTP接口、url等),或指软件系统不同组成部分衔接的约定。 用来提供应用程序与开发人员基于某软件或硬件得以访问的一组例程,而又无需访问源码,或理解内部工作机制的细节。

通俗的解释:我们平时说的开发一个接口,就是一个API,比如:访问servlet或controller的url:http://localhost:8088/boottrans/addstu?name=张三&age=23  就是一个接口,用户无需知道底层如何实现这个添加学生功能是如何实现的,这个添加学生功能只需要对外提供一个接口url拱别人访问使用即可。开发一个接口就是从mapper层到service层再到controller层,而对外只提供一个url接口。

架构风格: 就是api组织方式(样子)

一个传统的架构风格: http://localhost:9002/mytrans/addStudent?name=lisi&age=26

在地址上提供了 访问的资源名称addStudent, 在其后使用了get方式传递参数。

RESTful架构风格

1)REST : (英文: Representational State Transfer , 中文: 表现层状态转移)。

REST:是一种接口的架构风格和设计的理念,不是标准。

优点: 相比传统的架构风格,更简洁,更有层次

2) 一句话说明REST:

使用url表示资源 ,使用http动作(增POST、删DELETE、改PUT、查GET)操作资源。

增POST:通过post请求提交表单,从而插入数据资源

姓名: 年龄:

删DELETE:通过超链接发送删除资源的请求到后端对应controller来处理删除资源

删除id为2的学生

PUT更新资源:由于浏览器只支持GET和POST请求,所以需要通过post请求实现PUT

姓名:
年龄:

GET查询资源:通过发送GET请求,获取想要的资源


查询id为1的学生
// 根据学生id查询学生信息
@RequestMapping("/queryStu/{stuId}")
public String queryStudentById(@PathVariable(value = "stuId") Integer stuId){
    Student studentById = studentService.getStudentById(stuId);
    return studentById.toString();
}

SpringBoot中的一些重要注解

@PathVariable : 从url中获取数据

http://localhost:8080/queryStu/1

http://localhost:8080/queryStu/2

http://localhost:8080/queryStu/3

给路径起个变量{stuId},这样就可以使用@PathVariable注解获取这个路径变量的值。

比如发来请求,@PathVariable注解就会获取url中的stuId

    // 根据学生id查询学生信息
    @RequestMapping("/queryStu/{stuId}")
    public String queryStudentById(@PathVariable(value = "stuId") Integer stuId){
        Student studentById = studentService.getStudentById(stuId);
        return studentById.toString();
    }

@GetMapping: 支持的get请求方式, 等同于 @RequestMapping( method=RequestMethod.GET)

@PostMapping: 支持post请求方式 ,等同于 @RequestMapping( method=RequestMethod.POST)

@PutMapping: 支持put请求方式, 等同于 @RequestMapping( method=RequestMethod.PUT)

@DeleteMapping: 支持delete请求方式, 等同于 @RequestMapping( method=RequestMethod.DELETE)

@RestController: 复合注解, 是@Controller 和@ResponseBody组合。

在类的上面使用@RestController , 表示当前类中的所有方法上都加上了 @ResponseBody,同时表示当前类为controller,会创建对象到Spring容器中。

在页面中或Ajax中实现put、delete请求

由于浏览器html页面等只支持get和post请求,所以想实现put和delet请求就需要通过post请求实现:

  1. 在SpringBoot核心配置文件中,application.properties(yml) : 开启使用 HiddenHttpMethodFilter 过滤器
    spring.mvc.hiddenmethod.filter.enabled=true
  2. 在请求页面中,包含 _method参数, 他的值是 put, delete ,但是发起这个请求使用的post方式,到了后端过滤器查看_method的值处理对应的请求。

    姓名:
    年龄:

SpringBoot中操作Redis

要操作Redis数据库,就要有客户端连接上进行交互,Java中比较著名的客户端类库有:Jedis , lettuce , Redisson

Spring,SpringBoot中添加完Redis的起步依赖后,有 一个RedisTemplate(StringRedisTemplate) ,这两个的对象由框架自动创建好放入容器中就可以用来和redis交互。

 1)添加web和redis的起步依赖SpringBoot学习笔记_第18张图片

Redis的起步依赖:

        
        
            org.springframework.boot
            spring-boot-starter-data-redis
        

2)在springboot核心配置文件中指定redis的配置信息

#设置redis的主机ip,端口号,密码(没有可以不设)。用于连接redis的时候用。
spring.redis.host=localhost
spring.redis.port=6379
#spring.redis.password=....

3)编写程序和Redis进行交互

package com.lin.com.lin.springboot.redis.controller;

import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;

/**
 * @author shkstart
 * @create 2022-07-24 16:30
 */
@RestController
@RequestMapping("/redis")
public class RedisController {

    /*
    * 使用springboot提供的操作redis的类RedisTemplate来和Redis进行交互
    *
    * @Resource默认按名称进行bean注入
    * 这个对象的名称只能为:redisTemplate,因为底层帮我们创建的RedisTemplate对象的名称默认是redisTemplate
    *
    * RedisTemplate的泛型三种情况:
    * RedisTemplate
    * RedisTemplate
    * RedisTemplate 无泛型
    * */
    @Resource
    private RedisTemplate redisTemplate;

    @Resource
    private StringRedisTemplate stringRedisTemplate1;

    // 使用RedisTemplate添加数据到redis中
    @PostMapping("/add/redis")
    public String addToRedisByRedisTemplate(String key,String value){
        // 获取操作String类型value的对象
        ValueOperations valueOperations = redisTemplate.opsForValue();

        // 添加数据到redis中: set key value
        valueOperations.set(key,value);

        return "使用RedisTemplate添加数据到redis中";
    }

    // 使用RedisTemplate从redis中取出数据
    @GetMapping("/get/redis")
    public String getFromRedisByRedisTemplate(String key){
        ValueOperations valueOperations = redisTemplate.opsForValue();
        // 根据key获取对应的value
        Object value = valueOperations.get(key);

        return key + "对应的值为:" + value.toString();
    }

    // ------------------------------


    // 使用StringRedisTemplate添加数据到redis中
    @PostMapping("/add/stringredis/{key}/{value}")
    public String addToRedisByStringRedisTemplate(@PathVariable String key,
                                                  @PathVariable String value){
        // 获取操作String类型value的对象
        ValueOperations valueOperations = stringRedisTemplate1.opsForValue();

        // 添加数据到redis中: set key value
        valueOperations.set(key,value);

        return "使用StringRedisTemplate添加数据到redis中";
    }

    // 使用StringRedisTemplate从redis中取出数据
    @GetMapping("/get/stringredis/{key}")
    public String getFromRedisByStringRedisTemplate(@PathVariable String key){
        ValueOperations valueOperations = redisTemplate.opsForValue();
        // 根据key获取对应的value
        Object value = valueOperations.get(key);

        return key + "对应的值为:" + value.toString();
    }
}

SpringBoot学习笔记_第19张图片

SpringBoot学习笔记_第20张图片  

4)RedisTemplate和StringRedisTemplate的区别

相同点就是:

都是Spring、SpringBoot提供的操作Redis的类,都会创建好对应的对象bean放入容器中待使用。

不同点:

因为要和redis交互,比如插入数据的时候,需要将数据进行序列化后再在网络中进行传输。

StringRedisTemplate :

1.把k,v 都是作为String处理, 使用的是String的序列化 , 可读性好。

2.StringRedisTemplate extends RedisTemplate,key和value只能是字符串的。

RedisTemplate :

1.把k,v 经JDK序列化经过网络传输到Redis服务器上然后存到redis。JDK序列化的可读性差。默认使用的jdk序列化, 可以修改为指定的序列化。

2.key和value可以是任何类型的,范围比StringRedisTemplate大,如果只是想存储String类型的key-value,可以直接用StringRedisTemplate比较方便,因为它默认key和value设置了字符串序列化方式。

补充:

序列化:把 对象 转化为可在网络中传输的 字节序列 过程称为序列化。

反序列化:把 字节序列 还原为 对象 的过程称为反序列化。
 

序列化只是一种拆装组装对象的规则,那么这种规则肯定也可能有多种多样,比如现在常见的序列化方式有:

JDK(不支持跨语言)、JSON、XML、Hessian、Kryo(不支持跨语言)、Thrift、Protofbuff、

JSON序列化:

Student( name=zs, age=20) ---- { "name":"zs", "age":20 }

java的序列化: 把java对象转为byte[], 二进制数据

5)RedisTemplate自定义序列化方式

    /** RedisTemplate默认的序列化方式是采用JDK
     *  我们也可以单独设置 key 的序列化方式,也可以单独设置value的序列化方式.
     */
    @GetMapping("/addStr")
    public String addString(String key,String value){
        // 设置value的序列化方式为String序列化
        redisTemplate.setValueSerializer(new StringRedisSerializer());

        // 存
        redisTemplate.opsForValue().set(key,value);

        // 取
        Object myValue = redisTemplate.opsForValue().get(key);

        return "添加数据到redis" + key + "=" + myValue;
    }

 6)设置IDEA可自动在类中生成序列化版本号

SpringBoot学习笔记_第21张图片

7)JSON序列化数据存储到Redis中

        由于StringRedisTemplate只能添加String类型的数据,因此如果想要存一个java对象,就必须使用RedisTemplate,而且设置为json序列化方式。

package com.lin.springboot.redis.controller;

import com.lin.springboot.redis.bean.Student;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;

/**
 * @author shkstart
 * @create 2022-07-24 16:30
 */
@RestController
@RequestMapping("/redis")
public class RedisController {

    /*
    * 使用springboot提供的操作redis的类RedisTemplate来和Redis进行交互
    *
    * @Resource默认按名称进行bean注入
    * 这个对象的名称只能为:redisTemplate,因为底层帮我们创建的RedisTemplate对象的名称默认是redisTemplate
    *
    * RedisTemplate的泛型三种情况:
    * RedisTemplate
    * RedisTemplate
    * RedisTemplate 无泛型
    * */
    @Resource
    private RedisTemplate redisTemplate;

    @Resource
    private StringRedisTemplate stringRedisTemplate1;

    // 使用RedisTemplate添加数据到redis中
    @PostMapping("/add/redis")
    public String addToRedisByRedisTemplate(String key,String value){
        // 获取操作String类型value的对象
        ValueOperations valueOperations = redisTemplate.opsForValue();

        // 添加数据到redis中: set key value
        valueOperations.set(key,value);

        return "使用RedisTemplate添加数据到redis中";
    }

    // 使用RedisTemplate从redis中取出数据
    @GetMapping("/get/redis")
    public String getFromRedisByRedisTemplate(String key){
        ValueOperations valueOperations = redisTemplate.opsForValue();
        // 根据key获取对应的value
        Object value = valueOperations.get(key);

        return key + "对应的值为:" + value.toString();
    }

    // ------------------------------


    // 使用StringRedisTemplate添加数据到redis中
    @PostMapping("/add/stringredis/{key}/{value}")
    public String addToRedisByStringRedisTemplate(@PathVariable String key,
                                                  @PathVariable String value){
        // 获取操作String类型value的对象
        ValueOperations valueOperations = stringRedisTemplate1.opsForValue();

        // 添加数据到redis中: set key value
        valueOperations.set(key,value);

        return "使用StringRedisTemplate添加数据到redis中";
    }

    // 使用StringRedisTemplate从redis中取出数据
    @GetMapping("/get/stringredis/{key}")
    public String getFromRedisByStringRedisTemplate(@PathVariable String key){
        ValueOperations valueOperations = redisTemplate.opsForValue();
        // 根据key获取对应的value
        Object value = valueOperations.get(key);

        return key + "对应的值为:" + value.toString();
    }

    // ------------------

    /** RedisTemplate默认的序列化方式是采用JDK
     *  我们也可以单独设置 key 的序列化方式,也可以单独设置value的序列化方式.
     */
    @GetMapping("/addStr")
    public String addString(String key,String value){
        // 设置value的序列化方式为String序列化,到时候传输value的时候就是采用String序列化
        redisTemplate.setValueSerializer(new StringRedisSerializer());

        // 设置key的序列化方式为String序列化,到时候传输key的时候就是采用String序列化
        redisTemplate.setKeySerializer(new StringRedisSerializer());

        // 存
        redisTemplate.opsForValue().set(key,value);

        // 取
        Object myValue = redisTemplate.opsForValue().get(key);

        return "添加数据到redis" + key + "=" + myValue;
    }

    // ------------------------
    @GetMapping("/add/json")
    public String addJsonToRedis(String key,Student stuValue){

        // 设置redis的value序列化方式为json,参数Student.class是要序列化的类型
        redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer<>(Student.class));

        // 获取操作值key-value的对象
        ValueOperations valueOperations = redisTemplate.opsForValue();

        stuValue = new Student(12,"张三abc1");

        // 将key-value(hash)存到redis中
        valueOperations.set(key,stuValue);

        return stuValue + "成功存到redis中";
    }

    @GetMapping("/get/json")
    public String getJson(String key){

        ValueOperations valueOperations = redisTemplate.opsForValue();

        // 指明value的序列化方式,这样序列化和反序列化就会自动按照指定的序列化方式执行.
        redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer<>(Student.class));

        Object value = valueOperations.get(key);

        return "获取json" + value.toString();
    }
}

SpringBoot中集成Dubbo

1)创建公共接口工程项目

按照dubbo官方提供的最佳方案,要将服务接口、数据实体bean、公共异常放在公共接口项目中供服务提供者使用。这个公共接口工程是普通的maven项目即可,可以打包,然后提供坐标信息给别人引用依赖。

SpringBoot学习笔记_第22张图片

public class Student implements Serializable {
    // 数据实体类需要序列化,到时候消费者调用提供者处理完要将数据通过网络传输给消费者
    private static final long serialVersionUID = 9090382456117315755L;

    private Integer id;

    private String name;

    private Integer gae;
}
public interface StudentService {

    /**
     * 根据id,name,age获取学生信息
     * @param id
     * @param name
     * @param age
     * @return
     */
    Student getStudent(Integer id,String name,Integer age);
}

2)创建服务提供者

 这个服务提供者工程,需要引入公共接口工程的依赖,然后编写服务接口的实现类,对外暴露服务接口,这是一个SpringBoot项目,但是不需要web依赖等,springboot内置了tomcat服务器。

SpringBoot学习笔记_第23张图片

 pom.xml:



    4.0.0

    
    
        org.springframework.boot
        spring-boot-starter-parent
        2.7.2
        
    

    com.lin
    springboot_017_dubbo_service_provider
    0.0.1-SNAPSHOT



    
        1.8
    

    
        
        
            org.springframework.boot
            spring-boot-starter
        

        
        
            org.springframework.boot
            spring-boot-starter-test
            test
        

        
        
            com.lin
            springboot_016_dubbo_interface
            1.0-SNAPSHOT
        

        
        
            org.apache.dubbo
            dubbo-spring-boot-starter
            2.7.8
        

        
        
            org.apache.dubbo
            dubbo-dependencies-zookeeper
            2.7.8
            pom
        


    

    
        
            
                org.springframework.boot
                spring-boot-maven-plugin
            
        
    


服务接口的实现类:

package com.lin.service.impl;

import com.lin.inter.bean.Student;
import com.lin.inter.service.StudentService;
import org.apache.dubbo.config.annotation.DubboService;

/**
 * @author shkstart
 * @create 2022-07-27 11:24
 */

// 使用dubbo中的注解暴露服务,干活的实现类就是当前类。
// interfaceClass指明要暴露的接口。
@DubboService(interfaceClass = StudentService.class,version = "1.0")
public class StudentImpl implements StudentService {
    @Override
    public Student getStudent(Integer id, String name, Integer age) {
        Student stu = new Student();
        stu.setId(id);
        stu.setName(name);
        stu.setGae(age);

        return stu;
    }
}

服务提供者工程的核心配置文件application.properties:

#配置服务提供者的名称
spring.application.name=student-service-provider

#配置zookeeper注册中心的地址
dubbo.registry.address=zookeeper://localhost:2181

#配置要扫描的包
dubbo.scan.base-packages=com.lin.service.impl

#也可以配置dubbo的协议以及端口号
#dubbo.protocol.name=dubbo
#dubbo.protocol.port=32345

服务提供者的启动类:

@SpringBootApplication
/**
 *  @EnableDubbo 开启Dubbo功能,这个注解包含了以下两个注解:
 *      @EnableDubboConfig
 *      @DubboComponentScan dubbo组件扫描,如:服务提供者
 *
 */
@EnableDubbo
public class ProviderApplication {

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

}

3)创建服务消费者

pom.xml


        
            org.springframework.boot
            spring-boot-starter-web
        

        
        
            org.springframework.boot
            spring-boot-starter-test
            test
        

        
        
            com.lin
            springboot_016_dubbo_interface
            1.0-SNAPSHOT
        

        
        
            org.apache.dubbo
            dubbo-spring-boot-starter
            2.7.8
        

        
        
            org.apache.dubbo
            dubbo-dependencies-zookeeper
            2.7.8
        
    

controller:

@RestController
public class DubboController {

    /*
    * 引用远程服务
    * interfaceClass指明引用的服务接口
    * */
    @DubboReference(interfaceClass = StudentService.class,version = "1.0")
    private StudentService studentService;

    @PostMapping("/stu")
    public String getStudent(Integer id,String name,Integer age){
        Student student = studentService.getStudent(id, name, age);
        return "学生信息:" + student;
    }
}

消费者核心配置文件:

#指明服务消费者的名称
spring.application.name=service-consumer

#设置zookeeper注册中心的地址
dubbo.registry.address=zookeeper://localhost:2181

最终测试:启动服务提供者和服务消费者 

SpringBoot学习笔记_第24张图片

使用Spring boot进行web开发

我们都知道springboot是整合其他框架的框架,所以我们开发web,也是基于springmvc,只不过是spring boot整合了springmvc,底层的配置大多都配置好了,我们借用boot来应用springmvc开发web应用。

静态资源访问

只要静态资源放在类路径下: /static (or /public or /resources or /META-INF/resources 

resource目录编译后会被编译成classes目录下:

访问地址:http://localhost:8080/当前项目根路径/ + 静态资源名就可以直接访问到静态资源。

SpringBoot学习笔记_第25张图片

SpringBoot学习笔记_第26张图片

原理

静态映射:项目根路径/**,默认所有请求进来先看有没对应的控制器映射,如果没有对应的控制器,则j将请求交给静态资源处理器,静态资源处理器会去类路径resources下的/static (or /public or /resources or /META-INF/resources 四个目录下找有没有对应的资源,没有报404。

修改静态资源的请求路径

以后我们要配置拦截器,一般拦截所有的请求/**,但是一般静态资源不拦截,为了方便放行静态资源,一般修改静态资源的请求路径。以后/res/**都直接放行。

spring:
  mvc:
    #默认是 /** 项目根路径下的所有请求会去四个静态资源目录下找静态资源

    static-path-pattern: /res/** 
    #项目根路径/res/下的所有请求才会去四个静态资源目录下找静态资源

SpringBoot学习笔记_第27张图片

SpringBoot学习笔记_第28张图片

修改静态资源处理器默认去找静态资源的路径

spring:
  mvc:
    #默认是 /** 项目根路径下的所有请求会去四个静态资源目录下找静态资源
    static-path-pattern: /res/** #项目根路径/res/下的所有请求会去四个静态资源目录下找静态资源
  web:
    resources:
      #默认去找的静态资源位置:"classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/"
      static-locations: classpath:/res/

现在请求过来,只会去类路径下的res/目录下找有没有对应的静态资源。

欢迎页

只要将欢迎页放在四个静态资源目录下,访问项目的根路径即可访问到欢迎页。

spring:
#  mvc:
#    static-path-pattern: /res/**   这个会导致welcome page功能失效

或者可以处理/index请求的controller,然后跳到欢迎页。

自定义 Favicon

图片名favicon.ico 放在静态资源目录下即可。

spring:
#  mvc:
#    static-path-pattern: /res/**   这个会导致 Favicon 功能失效

rest使用与原理

请求参数处理,前端发送请求必定带参数过来后端处理。

以前对于资源的增删改查操作,是通过以下不同的请求路径区分:

/getUser   获取用户  /deleteUser 删除用户   /editUser  修改用户   /saveUser 保存用户

但是这样一旦项目大起来,请求路径就会很多,可能重复的很多,不好区分。

现在使用Rest方式处理,就都是/user请求路径,但是通过请求方式的不同来区分不同的操作:

姓名:
年龄:
姓名:
年龄:
姓名:
年龄:
姓名:
年龄:
    请求路径都是/user,但是通过前端请求方式来区分不同的动作。

    @RequestMapping(value = "/user",method = RequestMethod.GET)
    等同:@GetMappping("/user")
    public String getUser(){
        return "GET-获取用户";
    }

    @RequestMapping(value = "/user",method = RequestMethod.POST)
    public String saveUser(){
        return "POST-保存用户";
    }


    @RequestMapping(value = "/user",method = RequestMethod.PUT)
    public String putUser(){
        return "PUT-修改用户信息";
    }

    @RequestMapping(value = "/user",method = RequestMethod.DELETE)
    public String deleteUser(){
        return "DELETE-删除用户";
    }


	@Bean
	@ConditionalOnMissingBean(HiddenHttpMethodFilter.class)
	@ConditionalOnProperty(prefix = "spring.mvc.hiddenmethod.filter", name = "enabled", matchIfMissing = false)
	public OrderedHiddenHttpMethodFilter hiddenHttpMethodFilter() {
		return new OrderedHiddenHttpMethodFilter();
	}


//自定义filter
    @Bean
    public HiddenHttpMethodFilter hiddenHttpMethodFilter(){
        HiddenHttpMethodFilter methodFilter = new HiddenHttpMethodFilter();
        methodFilter.setMethodParam("_m");
        return methodFilter;
    }

原理:

要想实现上面Rest的方式,要有HiddenHttpMethodFilter核心过滤器,表单的请求方式method=post,隐藏域 _method=put,因为表单只能写get和post请求,所以通过这种方式实现put和delete请求。

而我们springboot的mvc自动配置类WebMvcAutoConfiguration中也提供了HiddenHttpMethodFilter组件,但是需要在yml配置文件中开启这个组件,spring.mvc.hiddenmethod.filter.enabled=true

public class WebMvcAutoConfiguration {


	@Bean
	@ConditionalOnMissingBean(HiddenHttpMethodFilter.class)
	@ConditionalOnProperty(prefix = "spring.mvc.hiddenmethod.filter", 
    name = "enabled",matchIfMissing = false)
	public OrderedHiddenHttpMethodFilter hiddenHttpMethodFilter() {
		return new OrderedHiddenHttpMethodFilter();
	}

Rest原理(表单提交要使用REST的时候)

  • 表单提交会带上_method=PUT
  • 请求过来被HiddenHttpMethodFilter过滤器拦截
    • 请求是否正常,并且是POST
      • 获取到_method的值,根据_method的值区分不同的请求方式。
      • 兼容以下请求;PUT.DELETE.PATCH
      • 原生request(post),包装模式requesWrapper重写了getMethod方法,返回的是传入的值。
      • 过滤器链放行的时候用wrapper。以后的方法调用getMethod是调用requesWrapper的。

Rest使用客户端工具,

  • 如PostMan直接发送Put、delete等方式请求,无需Filter。就可以不开HiddenHttpMethodFilter组件 【spring.mvc.hiddenmethod.filter.enabled=true】

web处理请求参数的几种方式

1)注解

@PathVariable、@RequestHeader、@ModelAttribute、@RequestParam、@MatrixVariable、@CookieValue、@RequestBody

@RequestAttribute(value = "key")获取请求域中的数据

@RestController
public class ParameterTestController {


    //  car/2/owner/zhangsan
    @GetMapping("/car/{id}/owner/{username}")
    public Map getCar(@PathVariable("id") Integer id,
                                     @PathVariable("username") String name,
                                     @PathVariable Map pv,

                                     获取请求头中的某个值
                                     @RequestHeader("User-Agent") String userAgent,
                                     获取请求头的所有信息
                                     @RequestHeader Map header,

                                     根据参数名获取请求中的参数值
                                     @RequestParam("age") Integer age,
                                     获取请求中是数组形式的参数
                                     @RequestParam("inters") List inters,
                                     获取所有的请求参数,封装成一个map
                                     @RequestParam Map params,

                                     根据cookie的参数名获取cookie中的某个值
                                     @CookieValue("_ga") String _ga,
                                     根据参数名获取某个cookie对象(key-value)
                                     @CookieValue("_ga") Cookie cookie){


        Map map = new HashMap<>();

//        map.put("id",id);
//        map.put("name",name);
//        map.put("pv",pv);
//        map.put("userAgent",userAgent);
//        map.put("headers",header);
        map.put("age",age);
        map.put("inters",inters);
        map.put("params",params);
        map.put("_ga",_ga);
        System.out.println(cookie.getName()+"===>"+cookie.getValue());
        return map;
    }


    @PostMapping("/save")
    public Map postMethod(@RequestBody String content){
        Map map = new HashMap<>();
        map.put("content",content);
        return map;
    }


    //1、语法: 请求路径:/cars/sell;low=34;brand=byd,audi,yd
    //2、SpringBoot默认是禁用了矩阵变量的功能
    //      手动开启:原理。对于路径的处理。UrlPathHelper进行解析。
    //              removeSemicolonContent(移除分号内容)支持矩阵变量的
    //3、矩阵变量必须有url路径变量才能被解析
    @GetMapping("/cars/{path}")
    public Map carsSell(@MatrixVariable("low") Integer low,
                        @MatrixVariable("brand") List brand,
                        @PathVariable("path") String path){
        Map map = new HashMap<>();

        map.put("low",low);
        map.put("brand",brand);
        map.put("path",path);
        return map;
    }

    // /boss/1;age=20/2;age=10

    @GetMapping("/boss/{bossId}/{empId}")
    public Map boss(@MatrixVariable(value = "age",pathVar = "bossId") Integer bossAge,
                    @MatrixVariable(value = "age",pathVar = "empId") Integer empAge){
        Map map = new HashMap<>();

        map.put("bossAge",bossAge);
        map.put("empAge",empAge);
        return map;

    }

}

2)Servlet API

WebRequest、ServletRequest、MultipartRequest、 HttpSession、javax.servlet.http.PushBuilder、Principal、InputStream、Reader、HttpMethod、Locale、TimeZone、ZoneId

控制器方法参数定义一些servlet对象,来接收参数,比如:HttpServletRequest就可以代表一个请求。

    @RequestMapping("/test")
    public String test(HttpServletRequest request){
        String value = request.getParameter("key");

        return "";
    }

3)复杂参数对象

MapModel(map、model里面的数据会被放在request的请求域 request.setAttribute)、Errors/BindingResult、RedirectAttributes( 重定向携带数据)ServletResponse(response)、SessionStatus、UriComponentsBuilder、ServletUriComponentsBuilder

4)自定义的bean参数对象

/**
        
       post请求提交数据:

 *     姓名:  
* 年龄:
* 生日:
* 宠物姓名:
* 宠物年龄: */ @Data public class Person { private String userName; private Integer age; private Date birth; private Pet pet; } @Data public class Pet { private String name; private String age; } result
    @RequestMapping("/test2")
    public String test2(@RequestBody Person person){
        String name = person.getUserName;

        return "";
    }

@RequestBody 将post请求体中的参数和自定义的Person实体对应,自动调用Person的set方法

Themeleaf视图解析器

springboot默认不支持jsp页面,所以控制器处理完逻辑,想要展示页面,有三种方法:

请求转发到页面、重定向到页面、使用视图解析器。

SpringBoot学习笔记_第29张图片

@Controller
public class ViewController {

    @RequestMapping("/forward")
    public String forwardToPage(){

        // 返回的字符串中带forward,默认会进行转发:项目根路径/+后面的路径
        return "forward:/forward.html";
    }

    @RequestMapping("/redirect")
    public String redirectToPage(){

        // 返回的字符串中带redirect,默认会进行重定向:项目根路径/+后面的路径
        // 访问项目的根路径/ + 资源名,就会去默认的静态资源目录下找资源
        return "redirect:/redirect.html";
    }

    // 当时以上展示视图的两种方法:转发和重定向,每次都需要把路径写全,太麻烦了
    // 所以可以引入视图解析器Thymeleaf,来简化操作.
}

1) 引入Thymeleaf的场景启动器依赖

 springboot提供了使用Thyme leaf的场景启动器

        
            org.springframework.boot
            spring-boot-starter-thymeleaf
        

引入启动器后,ThymeleafAutoConfiguration自动配置类就生效了,它往容器总提供了两个组件

public class ThymeleafAutoConfiguration {
        
        Thymeleaf默认的视图解析器
        @Bean
		SpringResourceTemplateResolver defaultTemplateResolver() {}

        @Bean
		@ConditionalOnEnabledResourceChain
		@ConditionalOnMissingFilterBean(ResourceUrlEncodingFilter.class)
		FilterRegistrationBean resourceUrlEncodingFilter() {}
}

2)Themeleaf视图解析器默认的前缀后缀

@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";
}

意思是我们只需要把要展示的页面放在类路径的templates/页面中,然后页面是.html,控制器返回字符串就会自动加上前缀后缀变成: /templates/字符串.html

@Controller
public class ViewController {

    @RequestMapping("/forward")
    public String forwardToPage(){

        // 返回的字符串中带forward,会屏蔽视图解析器,默认会进行转发:项目根路径/+后面的路径
        return "forward:/forward.html";
    }

    @RequestMapping("/redirect")
    public String redirectToPage(){

        // 返回的字符串中带redirect,会屏蔽视图解析器,默认会进行重定向:项目根路径/+后面的路径
        // 访问项目的根路径/ + 资源名,就会去默认的静态资源目录下找资源
        return "redirect:/redirect.html";
    }

    // 当时以上展示视图的两种方法:转发和重定向,每次都需要把路径写全,太麻烦了
    // 所以可以引入视图解析器,来简化操作.
    @RequestMapping("/thy")
    public String thymeleafToPage(){

        return "thymeleaf";
    }
    
    // http://localhost:8080/thy  ==> 转发 http://localhost:8080/templates/thymeleaf.html
}

SpringBoot学习笔记_第30张图片

3)在html页面中使用thymeleaf(类比jsp)

a.现在html标签中加入thymeleaf的命名空间




b.基本表达式

表达式名字

语法

用途

变量取值

${...}

获取请求域、session域、对象等值

选择变量

*{...}

获取上下文对象值

消息

#{...}

获取国际化等值

链接

@{...}

生成链接

片段表达式

~{...}

jsp:include 作用,引入公共页面片段

spring boot默认的错误处理方式

Spring Boot 提供了一套默认的异常处理机制,一旦程序中出现了异常,Spring Boot 会自动识别客户端的类型(浏览器客户端或机器客户端),并根据客户端的不同,以不同的形式展示异常信息。

1、浏览器客户端响应一个“ whitelabel”错误视图,以HTML格式呈现相同的数据

SpringBoot学习笔记_第31张图片

2、机器客户端,如postman,它将生成JSON响应,这个json响应数据应该是保存在某个域中,然后在页面取。其中包含错误,HTTP状态和异常消息的详细信息。

SpringBoot学习笔记_第32张图片

自定义异常处理方式

在下面目录中创建error目录,必须名为error,因为程序出错了会发送/error请求。

error/404.html error/5xx.html;程序出错后,根据状态码去匹配页面,匹配到了就返回给用户。

有精确的错误状态码页面就匹配精确,没有就找 4xx.html;如果都没有就触发白页。

一句话,4xx开头的错误都响应4xx.html,5xx开头的错都响应5xx.html

SpringBoot学习笔记_第33张图片 

你可能感兴趣的:(SSM,spring,boot,spring,java)