当前位置: 首页 > news >正文

SpringBoot自动配置核心原理

1. Spring Boot自动配置

1.1 SpringBoot的两大核心

Spring Boot 框架的两大核心特性可以概括为“启动器”(Starter)和“自动配置”(Auto-configuration)。

启动器(Starter)
Spring Boot 提供了一系列的 Starter POMs,它们是一组预定义的依赖关系。当你在项目中引入一个 Starter POM 时,它会自动包含所有必要的 Spring 组件以及合理的默认设置。

自动配置(Auto-Configuration)
当添加了特定的 Starter POM 后,Spring Boot 会根据类路径上存在的 jar 包来自动配置 Bean(自动配置相关组件)(比如:SpringBoot发现类路径上存在mybatis相关的类,例如SqlSessionFactory.class,那么SpringBoot将自动配置mybatis相关的所有Bean。)

1.2 引入web启动器准备的组件

引入了web启动器后,ioc容器中增加了101个bean对象(加入了101个组件)。这101个bean对象都是为web开发而准备的,例如我们常见的:

  • dispatcherServlet:DispatcherServlet 是 Spring MVC 的前端控制器,负责接收所有的 HTTP 请求,并将请求分发给适当的处理器(Controller)

  • viewResolver:ViewResolver 是 Spring MVC 中用于将逻辑视图名称解析为实际视图对象的组件。它的主要作用是根据控制器返回的视图名称,找到对应的视图实现(如 JSP、Thymeleaf、Freemarker 等),并返回给 DispatcherServlet 用于渲染视图。

  • characterEncodingFilter:字符集过滤器组件,解决请求和响应的乱码问题。

  • mappingJackson2HttpMessageConverter:负责处理消息转换的组件。它可以将json字符串转换成java对象,也可以将java对象转换为json字符串。

1.3 默认的包扫描规则

springboot默认情况下只扫描主入口类所在包及子包下的类。

// @ComponentScan("com")
@SpringBootApplication(scanBasePackages = "com")
public class Springboot315AutoConfigurationApplication {public static void main(String[] args) {ConfigurableApplicationContext applicationContext = SpringApplication.run(Springboot315AutoConfigurationApplication.class, args);// 从IoC容器中查看有多少个组件,将组件的id打印出来。String[] allBeanNames = applicationContext.getBeanDefinitionNames();for (String allBeanName : allBeanNames) {//System.out.println(allBeanName);/*if(allBeanName.equals("appBean")){System.out.println(allBeanName);}*/if("test1".equals(allBeanName)){System.out.println(allBeanName);}else if("test2".equals(allBeanName)){System.out.println(allBeanName);}}applicationContext.close();}}

1.4 默认配置

server.port=8081spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.suffix=.html

这些配置最终都会通过 @ConfigurationProperties(prefix="") 注解绑定到对应的bean的属性上。这个Bean一般称为属性类

ServerProperties:服务器属性类,专门负责配置服务器相关信息。

@ConfigurationProperties(prefix = "server", ignoreUnknownFields = true)
public class ServerProperties {}

ThymeleafProperties:Thymeleaf属性类,专门负责配置Thymeleaf模板引擎的。

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

1.5 自动配置按需加载

SpringBoot提供了非常多的自动配置类,有的是web相关的自动配置,有的是mail相关的自动配置。但是这些自动配置并不是全部生效,它是按需加载的。导入了哪个启动器,则该启动器对应的自动配置类才会被加载

任何启动器都会关联引入这样一个启动器:spring-boot-starter,它是springboot框架最核心的启动器。

spring-boot-starter又关联引入了spring-boot-autoconfigure。所有的自动配置类都在这里。

1.6 SpringBoot框架提供的条件注解

@ConditionalOnClass:当指定的类存在时,才创建Bean。

@ConditionalOnMissingClass:当指定的类不存在时,才创建Bean。

@ConditionalOnBean:当容器中存在指定的Bean时,才创建Bean。

@ConditionalOnMissingBean:当容器中不存在指定的Bean时,才创建Bean。

@ConditionalOnProperty:当配置文件中存在指定的属性时,才创建Bean。也可以设置属性值需要匹配的值。

@ConditionalOnResource:当指定的资源存在时,才创建Bean。

@ConditionalOnWebApplication:当应用程序是Web应用时,才创建Bean。

@ConditionalOnNotWebApplication:当应用程序不是Web应用时,才创建Bean。

@Configuration
public class AppConfig {@Beanpublic A a(){return new A();}@ConditionalOnBean(A.class)@Beanpublic B b(){return new B();}
}

2. 自动配置实现原理

为什么导入web启动器,web开发相关的自动配置就会生效?

当导入web启动器之后,底层都一连串的导入了哪些依赖!

1. 导入了spring-boot-starter-web【web启动器】

2. 关联导入了spring-boot-starterspring-boot-starter-jsonspring-boot-starter-tomcatspring-webspring-webmvc

注意:spring-boot-starter是springboot核心启动器,任何启动器在导入时,都会关联导入springboot核心启动器。

3. 核心启动器导入之后,关联导入了一个jar包:spring-boot-autoconfigure。其中存放的是springboot框架官方支持的自动配置类AopAutoConfiguration

4. 官方支持的自动配置类中有152个自动配置类。

2.1 main方法执行分析

1. 程序从main方法进入执行,主入口类上使用@SpringBootApplication进行了标注。

2. @SpringBootApplication注解是复合注解,代表以下三个注解的功能:

  2.1 @SpringBootConfiguration:它被@Configuration标注,说明主入口类就是一个配置类,此时该配置开始加载。

  2.2 @ComponentScan:默认扫描的是主入口所在包以及子包。因此spring-boot-autoconfigure包是扫描不到的,按说XxxAutoConfiguration自动配置类是无法加载的!!!那么这些自动配置类又是如何加载和生效的呢?

通过读取 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 这个固定名单文件来加载自动配置类的。

  2.3 @EnableAutoConfiguration:自动配置类的加载和生效全靠它了。启用自动配置。

3. @EnableAutoConfiguration@Import(AutoConfigurationImportSelector.class)标注

  @Import(AutoConfigurationImportSelector.class)的作用是:将AutoConfigurationImportSelector作为一个Bean加载到IoC容器中。

     这个Bean的作用是:负责收集和选择所有符合条件的自动配置类。

当 Spring Boot 启动时,AutoConfigurationImportSelector 类中的

getAutoConfigurationEntry() 方法会被调用,它的任务是找出所有需要自动配置的类。

在这个方法内部,会进一步调用 getCandidateConfigurations() 方法来获取候选配置类列表。而 getCandidateConfigurations() 不再使用旧版本的 spring.factories 机制,而是通过 ImportCandidates.load() 静态方法来加载。这个方法接收两个参数:一个是 annotation,也就是 @EnableAutoConfiguration 注解的类型;另一个是类加载器。方法首先检查注解不为空,然后决定使用哪个类加载器;接着,根据这个注解的全名(即 annotation.getName(),其值为

org.springframework.boot.autoconfigure.EnableAutoConfiguration),拼接出一个固定的资源路径:

META-INF/spring/org.springframework.boot.autoconfigure.EnableAutoConfiguration.imports;最后,把这些类名全部收集起来,封装成一个 ImportCandidates 对象返回。

Spring 拿到这个名单后,就会将这些类作为配置类进行加载和执行,从而实现“自动配置”。

经过下面的代码处理确定哪些自动配置类生效了。

// 移除配置列表中的重复项,并将结果强制转换为String类型的列表重新赋值给configurations
configurations = this.<String>removeDuplicates(configurations);// 从注解元数据和属性中获取需要排除的配置类集合,存储在exclusions变量中
Set<String> exclusions = this.getExclusions(annotationMetadata, attributes);// 检查配置列表中是否包含被排除的类,可能用于验证或抛出异常提示
this.checkExcludedClasses(configurations, exclusions);// 从配置列表中移除所有在排除集合中的元素
configurations.removeAll(exclusions);// 使用配置类过滤器对配置列表进行过滤,保留符合条件的配置类
configurations = this.getConfigurationClassFilter().filter(configurations);// 触发自动配置导入事件,可能用于通知相关监听器当前的配置和排除情况
this.fireAutoConfigurationImportEvents(configurations, exclusions);

2.2 自动配置类的功能

自动配置类导入了一堆相关的组件(一个组件一个功能),而每个组件获取配置时都是从属性类中获取,而属性类恰好又和配置文件绑定。

DispatcherServletConfiguration组件的配置信息来源于WebMvcProperties属性类。

DispatcherServletConfiguration进行配置的话,

应该在application.properties中使用这样的前缀配置:spring.mvc....


嵌入式Web服务器工厂自定义程序自动配置EmbeddedWebServerFactoryCustomizerAutoConfiguration,通过它可以配置web服务器。

自动配置类中也有很多组件,有tomcat组件,有jetty组件。单独看Tomcat,要配置Tomcat服务器,需要参照ServerProperties属性类。

2.3 自动配置原理

3. SpringBoot的web自动配置

首先引入了web启动器,web启动器传递引入了spring-boot-starter,这个启动器会传递引入一个spring-boot-autoconfigure包,在该包中的.imports文件中包括所有需要导入的自动配置类。

3.1 web自动配置的实现原理

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

从入口程序开始,入口程序被@SpringBootApplication注解标注;

@SpringBootApplication注解被@EnableAutoConfiguration注解标注。表示启用自动配置。

@EnableAutoConfiguration注解被@Import({AutoConfigurationImportSelector.class})注解标注。AutoConfigurationImportSelector决定哪些自动配置类是需要导入的。


3.2 通过web自动配置类逆推web配置的prefix

web自动配置类列表

org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration
org.springframework.boot.autoconfigure.web.embedded.EmbeddedWebServerFactoryCustomizerAutoConfiguration
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

web开发时,在application.properties配置文件中可以配置的前缀是:

# SpringMVC相关配置
spring.mvc.# web开发通用配置
spring.web.# 文件上传配置
spring.servlet.multipart.# 服务器配置
server.

3.3 Web自动配置默认配置内容

# Spring Boot 自动配置的 Spring MVC 特性## 1. 视图解析器
### ContentNegotiatingViewResolver
- 根据 HTTP 请求头中的 Accept 字段选择合适的视图技术渲染响应
### BeanNameViewResolver
- 根据视图名称找到对应的 View 对象## 2. 静态资源支持
### 默认静态资源路径
- `static` 目录下查找静态资源
### WebJars 支持
- 方便地管理前端库(如 jQuery、Bootstrap 等)## 3. 类型转换与格式化
### Converter
- 实现类型转换,例如表单数据到 Java 对象的转换
### GenericConverter
- 更通用的类型转换器
### Formatter
- 数据格式化,例如日期格式化## 4. HttpMessageConverters 支持
### 内置消息转换器
- 如 `MappingJackson2HttpMessageConverter`- 将 JSON 转换为 Java 对象- 将 Java 对象转换为 JSON 字符串## 5. MessageCodesResolver
- 自动生成表单验证错误时的消息代码
- 提供更精确的问题定位和友好的错误提示## 6. 默认主页支持
### index.html 文件
- 自动处理位于静态资源目录下的 `index.html` 文件作为默认主页## 7. ConfigurableWebBindingInitializer
- 指定默认使用的转换器和格式化器## 定制化选项
### 完全控制 Spring MVC
- 使用带有 `@EnableWebMvc` 注解的 `@Configuration` 类
### 保留默认配置并进行定制
- 添加类型为 `WebMvcConfigurer` 的 `@Configuration` 类- 可以添加拦截器、自定义视图控制器等- **注意**:不能同时使用 `@EnableWebMvc`

3.4 WebMvcAutoConfiguration

3.4.1 WebMvc自动配置是否生效的条件

@AutoConfiguration(after = { DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class,ValidationAutoConfiguration.class })
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
@ImportRuntimeHints(WebResourcesRuntimeHints.class)
public class WebMvcAutoConfiguration {}

1. @AutoConfiguration(after = { DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class,ValidationAutoConfiguration.class })

     WebMvcAutoConfiguration自动配置类加载顺序在以上自动配置类加载后加载。

2. @ConditionalOnWebApplication(type = Type.SERVLET)

     WebMvcAutoConfiguration自动配置类只在servlet环境中生效。

3. @ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })

     类路径中必须存在Servlet.classDispatcherServlet.classWebMvcConfigurer.classWebMvcAutoConfiguration自动配置类才会生效。

4. @ConditionalOnMissingBean(WebMvcConfigurationSupport.class)

     类路径中不存在WebMvcConfigurationSupport.classWebMvcAutoConfiguration自动配置类才会生效。

      注意:当使用@EnableWebMvc注解后,类路径中就会注册一个WebMvcConfigurationSupport这样的bean。

5. @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10) 不重要

     指定WebMvcAutoConfiguration自动配置类的加载顺序

6. @ImportRuntimeHints(WebResourcesRuntimeHints.class) 不重要

     运行时引入WebResourcesRuntimeHints这个类,这个类的作用是给JVM或者其他组件提示信息的,提示一下系统应该如何处理类和资源。

3.4.2 WebMvc自动配置生效后引入两个Filter Bean

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

这个过滤器是专门处理Rest请求的。GET POST PUT DELETE请求。

FormContentFilter Bean
@Bean
@ConditionalOnMissingBean(FormContentFilter.class)
@ConditionalOnProperty(prefix = "spring.mvc.formcontent.filter", name = "enabled", matchIfMissing = true)
public OrderedFormContentFilter formContentFilter() {return new OrderedFormContentFilter();
}

OrderedFormContentFilter 是 Spring Boot 中用于处理 HTTP 请求的一个过滤器,特别是针对 PUT 和 DELETE 请求。这个过滤器的主要作用是在处理 PUT 和 DELETE 请求时,确保如果请求体中有表单格式的数据,这些数据会被正确解析并可用。

3.4.3 WebMvc自动配置生效后引入了WebMvcConfigurer接口的实现类

SpringBoot框架的WebMvcAutoConfiguration类中提供了一个内部类:WebMvcAutoConfigurationAdapter

SpringBoot在这个类WebMvcAutoConfigurationAdapter中进行了一系列的Spring MVC相关配置。

开发中要对Spring MVC的相关配置进行修改,可以编写一个类  继承WebMvcAutoConfigurationAdatper,然后重写对应的方法即可。

@Configuration(proxyBeanMethods = false)
@Import({EnableWebMvcConfiguration.class})
@EnableConfigurationProperties({WebMvcProperties.class, WebProperties.class})
@Order(0)
public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer, ServletContextAware{}

该类上有一个注解@EnableConfigurationProperties({ WebMvcProperties.class, WebProperties.class }),该注解负责启用配置属性。会将配置文件application.propertiesapplication.yml中的配置传递到该类中。因此可以通过application.propertiesapplication.yml配置文件来改变Spring Boot对SpringMVC的默认配置。

spring.mvc:主要用于配置 Spring MVC 的相关行为,例如路径匹配、视图解析、静态资源处理等.

spring.web:通常用于配置一些通用的 Web 层设置,如资源处理、安全性配置等.

3.4.4 WebMvcConfigurer接口

这个接口不是SpringBoot框架提供的,是Spring MVC提供的。这个接口的作用主要是允许开发者通过实现这个接口来定制Spring MVC的行为

在这个接口中提供了很多方法,需要改变Spring MVC的哪个行为,则重写对应的方法即可。

public interface WebMvcConfigurer {// 用于定制 Spring MVC 如何匹配请求路径到控制器default void configurePathMatch(PathMatchConfigurer configurer) {}// 用于定制 Spring MVC 的内容协商策略,以确定如何根据请求的内容类型来选择合适的处理方法或返回数据格式default void configureContentNegotiation(ContentNegotiationConfigurer configurer) {}// 用于定制 Spring MVC 处理异步请求的方式default void configureAsyncSupport(AsyncSupportConfigurer configurer) {}// 用于定制是否将某些静态资源请求转发WEB容器默认的Servlet处理default void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {}// 用于定制 Spring MVC 解析视图的方式,以确定如何将控制器返回的视图名称转换为实际的视图资源。default void configureViewResolvers(ViewResolverRegistry registry) {}// 用于定制 Spring MVC 如何处理 HTTP 请求和响应的数据格式,包括 JSON、XML 等内容类型的转换default void configureMessageConverters(List<HttpMessageConverter<?>> converters) {}// 用于定制 Spring MVC 如何处理控制器方法中发生的异常,并提供相应的错误处理逻辑。default void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {}// 用于定制 Spring MVC 如何处理数据的格式化和解析,例如日期、数值等类型的对象的输入和输出格式。default void addFormatters(FormatterRegistry registry) {}// 用于定制 Spring MVC 如何使用拦截器来处理请求和响应,包括在请求进入控制器之前和之后执行特定的操作。default void addInterceptors(InterceptorRegistry registry) {}// 用于定制 Spring MVC 如何处理静态资源(如 CSS、JavaScript、图片等文件)的请求。default void addResourceHandlers(ResourceHandlerRegistry registry) {}// 用于定制 Spring MVC 如何处理跨域请求,确保应用程序可以正确地响应来自不同域名的 AJAX 请求或其他跨域请求。default void addCorsMappings(CorsRegistry registry) {}// 用于快速定义简单的 URL 到视图的映射,而无需编写完整的控制器类和方法。default void addViewControllers(ViewControllerRegistry registry) {}// 用于定制 Spring MVC 如何解析控制器方法中的参数,包括如何从请求中获取并转换参数值。default void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {}// 用于定制 Spring MVC 如何处理控制器方法的返回值,包括如何将返回值转换为实际的 HTTP 响应。default void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> handlers) {}// 用于定制 Spring MVC 如何处理 HTTP 请求和响应的数据格式,允许你添加或调整默认的消息转换器,以支持特定的数据格式。default void extendMessageConverters(List<HttpMessageConverter<?>> converters) {}// 用于定制 Spring MVC 如何处理控制器方法中抛出的异常,允许你添加额外的异常处理逻辑。default void extendHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {}
}

3.5 自动配置中的静态资源处理

静态资源的查找路径:

{ "classpath:/META-INF/resources/","classpath:/resources/", "classpath:/static/", "classpath:/public/" }

重写 WebMvcAutoConfiguration 类的 WebMvcAutoConfigurationAdapter 类中addResourceHandlers方法

@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {// 检查 resourceProperties 中的 addMappings 属性是否为 false。如果为 false,则表示不启用默认的静态资源映射处理。// 在application.properties配置文件中进行`spring.web.resources.add-mappings=false`配置,可以将其设置为false。// 当然,如果没有配置的话,默认值是true。if (!this.resourceProperties.isAddMappings()) {logger.debug("Default resource handling disabled");return;}// 配置 WebJars 的静态资源处理。// this.mvcProperties.getWebjarsPathPattern()的执行结果是:/webjars/**// 也就是说,如果请求路径是 http://localhost:8080/webjars/** ,则自动去类路径下的 /META-INF/resources/webjars/ 目录中找静态资源。// 如果要改变这个默认的配置,需要在application.properties文件中进行这样的配置:`spring.mvc.webjars-path-pattern=...`addResourceHandler(registry, this.mvcProperties.getWebjarsPathPattern(),"classpath:/META-INF/resources/webjars/");// 配置普通静态资源处理// this.mvcProperties.getStaticPathPattern()的执行结果是:/**// this.resourceProperties.getStaticLocations()的执行结果是:{ "classpath:/META-INF/resources/","classpath:/resources/", "classpath:/static/", "classpath:/public/" }// 也就是说,如果请求路径是:http://localhost:8080/**,根据控制器方法优先原则,会先去找合适的控制器方法,如果没有合适的控制器方法,静态资源处理才会生效,则自动去类路径下的/META-INF/resources/、/resources/、/static/、/public/ 4个位置找。// 如果要改变这个默认的配置,需要在application.properties中进行如下的两个配置:// 配置URL:spring.mvc.static-path-pattern=...// 配置物理路径:spring.web.resources.static-locations=...,...,...,...addResourceHandler(registry, this.mvcProperties.getStaticPathPattern(), (registration) -> {registration.addResourceLocations(this.resourceProperties.getStaticLocations());if (this.servletContext != null) {ServletContextResource resource = new ServletContextResource(this.servletContext, SERVLET_LOCATION);registration.addResourceLocations(resource);}});
}

3.5.1 WebJars静态资源处理

默认规则是:当请求路径是/webjars/**,则会去classpath:/META-INF/resources/webjars/找。

WebJars在SpringBoot中的使用

WebJars官网:https://www.webjars.org/

找到某个webjars的maven依赖,将依赖加入到SpringBoot项目中。

在SpringBoot中,对WebJars的默认访问规则是:当请求路径是/webjars/**,则会去classpath:/META-INF/resources/webjars/

要想访问上图的index.js,应该发送请求路径为:http://localhost:8080/webjars/vue/3.5.12/index.js

3.5.2 普通静态资源处理

当请求路径是http://localhost:8080/**,根据控制器方法优先原则,会先去找合适的控制器方法,如果没有合适的控制器方法,静态资源处理才会生效,则自动去类路径下的以下4个位置查找:

  • classpath:/META-INF/resources/
  • classpath:/resources/
  • classpath:/static/
  • classpath:/public/

不管是webjars的静态资源还是普通静态资源,统一都会执行以下这个方法。

这个方法最后几行代码就是关于静态资源的缓存处理方式:

1. 静态资源缓存指的是浏览器的缓存行为,浏览器可以将静态资源(js、css、图片、声音、视频)缓存到浏览器中,只要下一次用户访问同样的静态资源直接从缓存中取,不再从服务器中获取,可以降低服务器的压力,提高用户的体验。而这个缓存策略可以在服务器端程序中进行设置。

2. SpringBoot对静态资源缓存的默认策略就是以下这三行代码:

// 设置缓存的过期时间(单位:秒,若未指定单位则默认使用秒)
// 浏览器会根据此配置决定是否从本地缓存加载资源,减少网络请求,提升加载速度
// 可通过配置文件修改:spring.web.resources.cache.period=3600 或 spring.web.resources.cache.period=1h
registration.setCachePeriod(getSeconds(this.resourceProperties.getCache().getPeriod()));// 设置静态资源的 Cache-Control HTTP 响应头,控制浏览器缓存行为
// 常见指令:max-age(响应在多少秒内有效)、public(可被任何缓存机制缓存)、
// private:表示响应只能被用户的浏览器缓存、no-cache:表示在使用缓存的资源之前必须重新发送一次请求进行验证
// no-store:表示不缓存任何响应的资源
// 可通过配置文件修改:spring.web.resources.cache.cachecontrol.max-age=3600 等
registration.setCacheControl(this.resourceProperties.getCache().getCachecontrol().toHttpCacheControl());// 设置是否在响应头中添加资源最后修改时间(默认启用)
// 浏览器会对比缓存资源与服务器资源的最后修改时间,未变更则使用缓存
// 可通过配置文件修改:spring.web.resources.cache.use-last-modified=false
registration.setUseLastModified(this.resourceProperties.getCache().isUseLastModified());// 是否开启静态资源默认处理方式(默认是:开启)
spring.web.resources.add-mappings=true

3.5.3 欢迎页面index.html

只要请求路径是/**的,会依次去{ "classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/" }这四个位置找index.html页面作为欢迎页。


小疑问

WebMvcAutoConfiguration类中有一个内部类EnableWebMvcConfiguration,EnableWebMvcConfiguration就是一个WebMvcConfigurationSupport这样的Bean。

EnableWebMvcConfigurationWebMvcAutoConfiguration类的内部类。在WebMvcAutoConfiguration进行加载的时候,EnableWebMvcConfiguration这个内部类还没有加载。因此这个时候在容器中还不存在WebMvcConfigurationSupport的Bean,所以WebMvcAutoConfiguration仍然会生效。

WebMvcAutoConfiguration类中的内部类EnableWebMvcConfiguration,是用来启用Web MVC默认配置的。

WebMvcAutoConfiguration的两个内部类:

  • WebMvcAutoConfigurationAdapter作用是用来:修改配置的
  • EnableWebMvcConfiguration作用是用来:启用配置的

favicon.ico

favicon.ico文件放到静态资源路径下

https://www.iconfont.cn/ (阿里巴巴提供的图标库)随便找一个图标,然后将图片名字命名为favicon.ico,然后将其放到SpringBoot项目的静态资源路径下。

4. SpringBoot的web手动配置

4.1 配置文件方式

1. 通过修改application.propertiesapplication.yml

2. 添加spring.mvcspring.web相关的配置。

# Spring MVC的相关配置
# 访问静态资源URL的前缀# 1. 设置webjars静态资源的请求路径的前缀
spring.mvc.webjars-path-pattern=/wjs/**
# http://localhost:8080/wjs/....# 2. 设置普通静态资源的请求路径的前缀
spring.mvc.static-path-pattern=/static/**
# http://localhost:8080/static/....# 修改静态资源的存放位置
spring.web.resources.static-locations=classpath:/static1/,classpath:/static2/

根据上面的配置,可以查看static1,static2文件夹下的静态资源。

存储在classpath:/META-INF/resources/位置的静态资源会被默认加载,不受手动配置的影响。

4.2 编写代码方式

4.2.1 实现WebMvcConfigurer接口

        SpringMVC框架提供了WebMvcConfigurer接口,需要改变默认的行为,可以编写一个类实现WebMvcConfigurer接口,并对应重写接口中的方法即可改变默认的配置行为。

对于web开发来说,配置类一般起名为:WebConfig。配置类一般存放到config包下,因此在SpringBoot主入口程序同级目录下新建config包,在config包下新建WebConfig类:

// 使用该注解标注,表示该类为配置类。
@Configuration
public class WebConfig implements WebMvcConfigurer {@Overridepublic void addResourceHandlers(ResourceHandlerRegistry registry) {registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static1/", "classpath:/static2/");// http://localhost:8080/static/....可以访问static1/static2// http://localhost:8080/.... 可以访问static}
}

Spring Boot对Spring MVC的默认自动配置是生效的。

// 使用该注解标注,不再继续使用SpringBoot提供的默认行为
@EnableWebMvc// 使用该注解标注,表示该类为配置类。
@Configuration
public class WebConfig implements WebMvcConfigurer {@Overridepublic void addResourceHandlers(ResourceHandlerRegistry registry) {registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static1/", "classpath:/static2/");// http://localhost:8080/.... 不可以访问static}
}

4.2.2 采用@Bean注解提供WebMvcConfigurer组件

@Bean 方法向Spring容器注册实例

@Configuration
public class WebConfig2 {@Beanpublic WebMvcConfigurer addResourceHandlers(){return new WebMvcConfigurer() {@Overridepublic void addResourceHandlers(ResourceHandlerRegistry registry) {registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static1/", "classpath:/static2/");}};}
}

4.3 IOC容器中有WebMvcConfigurer 组件,就实现MVC配置

Spring Boot 的 WebMvcAutoConfiguration 是自动配置的核心。

它内部有一个叫 EnableWebMvcConfiguration 的类,这个类继承了DelegatingWebMvcConfiguration(所有自定义的 MVC 配置“收集”起来,统一管理。 

@Autowired
public void setConfigurers(List<WebMvcConfigurer> configurers) {this.configurers.addWebMvcConfigurers(configurers);
}

这个方法用 @Autowired 标记,Spring 会自动把容器中所有实现了 WebMvcConfigurer 接口的组件找出来,放进这个列表里。

this.configurers 实际上是一个 WebMvcConfigurerComposite 对象,它可以把多个WebMvcConfigurer实例“打包”成一个整体,内部维护了一个List<WebMvcConfigurer>,用来存放所有配置组件。

组合模式:

1. 组合多个 WebMvcConfigurer 实例:WebMvcConfigurerComposite 通过 delegates 列表组合了多个 WebMvcConfigurer 实例。

2. 统一接口:WebMvcConfigurerComposite 实现了 WebMvcConfigurer 接口,因此可以像一个单一的 WebMvcConfigurer 一样被使用。

3. 代理调用:在实现 WebMvcConfigurer 接口的方法时,WebMvcConfigurerComposite 会遍历 delegates 列表,调用每个 WebMvcConfigurer 实例的相应方法。

5. Web请求的路径匹配

5.1 AntPathMatcher

首先,在application.properties文件中配置:

spring.mvc.pathmatch.matching-strategy=ant_path_matcher

Ant风格的路径匹配规则:

* 匹配任意长度的任意字符序列(不包括路径分隔符)。示例:/foo/*.html 匹配 /foo/bar.html 和 /foo/baz.html。** 匹配任意数量的目录层级。示例:/foo/** 匹配 /foo/bar、/foo/bar/baz 和 /foo/bar/baz/qux。? 匹配任意单个字符。示例:/foo?bar 匹配 /foobar 和 /fooxbar。[] 匹配指定范围内的单个字符。示例:/foo[a-z]bar 匹配 /fooabar、/foobbar 等。{} 路径变量,用于提取路径的一部分作为参数。示例:/users/{userId} 匹配 /users/123,提取 userId=123。
@RestController
public class PathController {@GetMapping("/{path:[a-z]+}/a?/**/*.do")public String path(HttpServletRequest request, @PathVariable String path){return request.getRequestURI() + "," + path;}
}

5.2 PathPatternParser

首先,在application.properties文件中配置:

<!-- 项目中不做配置,或者按照以下方式配置,都是PathPatternParser-->
spring.mvc.pathmatch.matching-strategy=path_pattern_parser

PathPatternParser风格是兼容Ant风格的。只有一个地方PathPatternParser不支持,Ant支持。在Ant风格中,**可以出现在任意位置。PathPatternParser中只允许**出现在路径的末尾

6. 内容协商

内容协商机制是指服务器根据客户端的请求来决定返回资源的最佳表示形式。

客户端要什么格式的数据,后端就应该返回什么格式的数据。

  • 客户端要JSON,就响应JSON。
  • 客户端要XML,就响应XML。
  • 客户端要YAML,就响应YAML。

6.1 实现内容协商的两种方式

通过HTTP请求头(如 Accept)或请求参数(如 format)来指定客户端偏好接收的内容类型(如JSON、XML等)。服务器会根据这些信息选择最合适的格式进行响应。

6.1.1 HTTP请求头(如 Accept)

SpringBoot框架中,在程序员不做任何配置的情况下,优先考虑的是这种方式。

服务器会根据客户端发送请求时提交的请求头中的"Accept: application/json" 或 "Accept: application/xml" 或 "Accept: text/html"来决定响应什么格式的数据。

@RestController // 相当于@Controller + @ResponseBody ,默认是将数据转换成json字符串进行响应。
public class UserController {@Autowiredprivate UserService userService;@GetMapping("/detail")public User detail(){return userService.findUserById();}
}

使用了@RestController,也就是使用了@ResponseBody。因此默认支持的是返回JSON数据。


支持返回XML格式的数据

1. 引入依赖  (java对象转换成xml格式的字符串)

<dependency><groupId>com.fasterxml.jackson.dataformat</groupId><artifactId>jackson-dataformat-xml</artifactId>
</dependency>

2. 实体类上添加注解

@JacksonXmlRootElement	// 添加这个注解,可以将java对象转换成xml格式的字符串
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {private String name;private Integer age;
}

服务器根据不同的请求头返回了不同格式的数据。

  • Accept: application/xml则返回XML格式的数据
  • Accept: application/json则返回JSON格式的数据

6.1.2 请求参数(format)

<!--内容协商时,优先考虑请求参数format方式-->
spring.mvc.contentnegotiation.favor-parameter=true

<!--内容协商时,设置请求参数的名字,默认为format-->
spring.mvc.contentnegotiation.parameter-name=type

6.2 HttpMessageConverter接口

HttpMessageConverter接口被翻译为:Http消息转换器。它起到转换Http消息的作用。

什么是Http消息?所谓的Http消息本质上就是浏览器向服务器发送请求时提交的数据,或者服务器向浏览器响应的数据。

HttpMessageConverter接口就是负责完成请求/响应时的数据格式转换的。

6.2.1 常见的HttpMessageConverter

内置的常见的HttpMessageConverter的实现类包括:

1. 【请求】提交的表单(form)数据转换成Java对象的主要任务是由 FormHttpMessageConverter 消息转换器完成的。

2. 【请求】提交的JSON数据转换成Java对象的主要任务是由 MappingJackson2HttpMessageConverter 消息转换器完成的。(通常使用的@RequestBody注解)

3. 【响应】将Java对象转换成JSON格式的数据,并将其写入HTTP响应体的任务是由 MappingJackson2HttpMessageConverter 消息转换器完成。(通常使用的@ResponseBody注解)

4. 【响应】将Java对象转换成XML格式的数据,并将其写入HTTP响应体的任务通常由 Jaxb2RootElementHttpMessageConverter 消息转换器完成。

5. 【响应】将 String 直接写入到响应体的任务是由 StringHttpMessageConverter 消息转换器完成。

6.2.2 选择消息转换器条件

请求

请求时通常根据以下条件来确定使用哪个消息转换器:

1. 请求的 Content-Type 字段:

      Spring MVC 会检查请求的 Content-Type 字段,以确定请求体的数据格式(例如 application/json、application/x-www-form-urlencoded(表单) 、application/xml 等)。

2. 方法参数类型:

      控制器方法中接收请求体的参数类型(例如 @RequestBody)。

响应

响应时通常根据以下条件来确定使用哪个消息转换器:

1. 请求提交时,请求头上的Accept字段 :

        Spring MVC 会检查客户端请求的 Accept 字段,以确定客户端期望的响应格式(例如 application/json、application/xml 等)。

2. 方法返回值类型:

        控制器方法的返回值类型(例如 @ResponseBody)。

     例1:@ResponseBody + 控制器方法的返回值是String,则使用StringHttpMessageConverter转换器。(将字符串直接写入响应体)

  例2:@ResponseBody + 控制器方法的返回值是User,则使用MappingJackson2HttpMessageConverter转换器。(将java对象转换成json格式的字符串写入到响应体)

6.2.3 系统默认提供消息转换器

WebMvcAutoConfiguration内部类EnableWebMvcConfiguration

EnableWebMvcConfiguration继承了DelegatingWebMvcConfiguration

DelegatingWebMvcConfiguration继承了WebMvcConfigurationSupport

WebMvcConfigurationSupport类中有这样一个方法:addDefaultHttpMessageConverters() 用来添加默认的HttpMessageConverter对象。

1. ByteArrayHttpMessageConverter:

      用于将字节数组(byte[])与HTTP消息体之间进行转换。这通常用于处理二进制数据,如图片或文件。

2. StringHttpMessageConverter:

      用于将字符串(String)与HTTP消息体之间进行转换。它支持多种字符集编码,能够处理纯文本内容。

3. ResourceHttpMessageConverter:

      用于将Spring的Resource对象与HTTP消息体之间进行转换。Resource是Spring中表示资源的接口,可以读取文件等资源。这个转换器对于下载文件或发送静态资源有用。

4. ResourceRegionHttpMessageConverter:

      用于处理资源的部分内容(即“Range”请求),特别是当客户端请求大文件的一部分时。这对于实现视频流媒体等功能很有用。

5. AllEncompassingFormHttpMessageConverter:

      用于处理表单,是一个比较全面的form消息转换器。处理标准的application/x-www-form-urlencoded格式的数据,以及包含文件上传的multipart/form-data格式的数据。

6. MappingJackson2HttpMessageConverter:

      使用Jackson库来序列化和反序列化JSON数据。可以将Java对象转换为JSON格式的字符串,反之亦然。

6.2.4 定义HttpMessageConverter

6.2.4.1 引入依赖
<!--这个依赖也是jackson家族提供的,可以将java对象转换成yaml格式的字符串。-->
<dependency><groupId>com.fasterxml.jackson.dataformat</groupId><artifactId>jackson-dataformat-yaml</artifactId>
</dependency>
测试依赖库用法
public class TestYAMLApi {public static void main(String[] args) throws JsonProcessingException {// 创建YAMLFactory对象//YAMLFactory yamlFactory = new YAMLFactory();// 🈲写文档头,也就是yaml文件中的   ---YAMLFactory yamlFactory = new YAMLFactory().disable(YAMLGenerator.Feature.WRITE_DOC_START_MARKER);// 创建 对象映射器 对象。ObjectMapper objectMapper = new ObjectMapper(yamlFactory);// 准备一个java对象User user = new User("jackson", 30);// 将java对象转换成字符串String str = objectMapper.writeValueAsString(user);System.out.println(str);}
}

6.2.4.2 新增媒体类型yaml

默认支持xml和json两种媒体类型,要支持yaml格式的,需要新增一个yaml媒体类型,在springboot的配置文件中进行如下配置:

spring.mvc.contentnegotiation.media-types.yaml=text/yaml

以上types后面的yaml是媒体类型的名字,名字随意,如果媒体类型起名为xyz,那么发送请求时的路径应该是这样的:http://localhost:8080/detail?format=xyz

Spring 会识别 format=xyz,并尝试使用 text/yaml 的视图或消息转换器来返回 YAML 格式数据。

6.2.4.3 自定义HttpMessageConverter
// 这是一个消息转换器,专门处理yaml格式数据的。
// 注意,所有的消息转换器必须实现 HttpMessageConverter接口,或者继承AbstractHttpMessageConverter抽象类。并实现/重写方法。
public class YamlHttpMessageConverter extends AbstractHttpMessageConverter {// 对象映射器private ObjectMapper objectMapper = new ObjectMapper(new YAMLFactory().disable(YAMLGenerator.Feature.WRITE_DOC_START_MARKER));// 非常重要的一步:要将媒体类型 text/yaml 和 消息转换器进行绑定。public YamlHttpMessageConverter() {// 新建一个新的媒体类型,并指定字符集super(new MediaType("text", "yaml", Charset.forName("UTF-8")));}// 这个方法用来指定此消息转换器只适合于哪些类型的对象。@Overrideprotected boolean supports(Class clazz) {// 表示只有User类型的对象才能够使用该消息转换器进行转换。return User.class.isAssignableFrom(clazz);}// 将yaml格式的字符串转换成java对象// @RequestBody@Overrideprotected Object readInternal(Class clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {return null;}// 将java对象转换成yaml格式的字符串// @ResponseBody@Overrideprotected void writeInternal(Object o, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {// ObjectMapper对象objectMapper.writeValue(outputMessage.getBody(), o);}
}
6.2.4.4 配置消息转换器

重写WebMvcConfigurer接口的configureMessageConverters方法:

@Configuration
public class WebConfig implements WebMvcConfigurer {@Overridepublic void configureMessageConverters(List<HttpMessageConverter<?>> converters) {converters.add(new YamlHttpMessageConverter());}
}

启动服务器并测试:http://localhost:8080/detail?type=yaml

7. SpringBoot整合Thymeleaf

7.1 在SpringBoot中整合Thymeleaf

7.1.1 引入依赖thymeleaf启动器

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

7.1.2 编写配置文件,指定前缀和后缀

spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.suffix=.html

7.1.3 编写控制器

// 不能使用 @RestController
@Controller
public class HelloController {@GetMapping("/h")public String helloThymeleaf(@RequestParam("name") String name, Model model) {// 将接收到的name数据存储到域对象中model.addAttribute("name", name);// 逻辑视图名return "hello"; // 最终的物理视图名:classpath:/templates/hello.html}
}

7.1.4 thymeleaf模板页面

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>hello, thymeleaf</title>
</head>
<body>
<h1>hello,<span th:text="${name}"></span></h1>
</body>
</html>

7.2 Thymeleaf自动配置

默认情况下,只要放在classpath:/templates/目录下的xxx.html会被自动当做为thymeleaf的模板文件被thymeleaf模板引擎解析。

因此放在classpath:/templates/目录下的html文件不是静态页面,而是动态的thymeleaf模板页面。

7.3 Thymeleaf的核心语法

控制器Controller

@Controller
public class HelloController {// http://localhost:8080/hello?name=jackson@GetMapping("/hello")// Model model 当前指的是请求域对象,用于在控制器(Controller)和 视图(View)之间传递数据的容器public String hello(@RequestParam("name") String name, Model model, @RequestParam("flag") Integer flag) {// 将数据存储到域对象当中model.addAttribute("name", name);// 向域对象当中绑定一段html代码model.addAttribute("htmlCode", "<a href='http://www.bjpowernode.com'>动力节点</a>");// 向域对象当中绑定公司名和公司地址model.addAttribute("company", "动力节点");model.addAttribute("companyUrl", "http://www.bjpowernode.com");// 向域对象中存储一个样式model.addAttribute("style", "color:red");// 根据flag向域对象当中存储数据if(1 == flag){model.addAttribute("display", "true");}else if(0 == flag){model.addAttribute("display", "false");}// 向域对象当中绑定一个URLmodel.addAttribute("imgUrl", "/dog1.jpg");// 向域对象当中存储一个性别model.addAttribute("gender", false);// 返回逻辑视图名称// 最终视图解析器ViewResolver会将逻辑视图名称解析为物理视图名称// 前缀:classpath:/templates/// 后缀:.html// 最终的解析结果:前缀 + 逻辑视图名称 + 后缀 = 物理视图名称// classpath:/templates/hello.thymeleafreturn "hello";}
}
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8"><title>hello thymeleaf</title>
</head><body><h1 th:text="${gender ? '男' : '女'}"></h1><hr><h1 th:text="${name}"></h1><h1 th:text="${'name'}"></h1><hr><h1 th:text="${name}" th:if="${#strings.length(name) > 6}"></h1><h1>hello,<span th:text="${name}">这里是标签体</span></h1><h1>hello,<span th:text="${#strings.toUpperCase(name)}">这里是标签体</span></h1><hr><h1>hello,<span th:text="${#strings.toUpperCase(name)}">这里是标签体</span></h1><h1>hello,<span th:text="${'姓名:' + #strings.toUpperCase(name) + '。'}">这里是标签体</span></h1><h1>hello,<span th:text="|姓名:${#strings.toUpperCase(name)}。|">这里是标签体</span></h1><hr><h1>hello,<span th:utext="${name}">这里是标签体</span></h1><div th:text="${htmlCode}">我是一个DIV</div><div th:utext="${htmlCode}">我是一个DIV</div><a th:href="${companyUrl}" href="http://www.baidu.com" th:text="${company}">百度</a><br><a th:href="${companyUrl}" href="http://www.baidu.com" th:style="${style}" style="color:green" th:text="${company}">百度</a><br><a th:attr="href=${companyUrl},style=${style}" href="http://www.baidu.com"  style="color:green" th:text="${company}">百度</a><br><img src="/myweb/dog1.jpg" th:if="${display}" /><br><img th:src="@{${imgUrl}}" th:if="${display}" /></body>
</html>

其中,${}表达式语法是专门用来获取model中绑定的数据的。

@{}表达式语法是专门用来维护URL请求路径的。它可以动态设置项目的根路径。

SpringBoot中默认的项目根路径是:        /

model.addAttribute("imgUrl", "/dog1.jpg");
<img th:src="${imgUrl}">

如果将web应用的根路径进行了修改,将其配置为:/myweb

server.servlet.context-path=/myweb

此时将模板代码进行如下修改,将${}修改为@{}

<img th:src="@{${imgUrl}}">

7.3.1 Thymeleaf的内置工具

1. 用户提交用户名时,如果名字中含有jack则显示狗狗图片,否则不显示。

<img th:src="@{${imgUrl}}" th:if="${#strings.contains(name,'jack')}">

2. 如果提供的用户名长度大于6,则显示狗狗图片。

<img th:src="@{${imgUrl}}" th:if="${#strings.length(name) > 6}">

3. thymeleaf也支持三目运算符:

<span th:text="${user.gender ? '男' : '女'}"></span>

4. thymeleaf的字符串拼接

<div th:text="${'姓名:' + name + ',年龄:18'}"></div>
<div th:text="|姓名:${name},年龄:18|"></div>

7.3.2 循环遍历

@Service
public class UserServiceImpl implements UserService {@Overridepublic List<User> getAll() {List<User> users = new ArrayList<>();//users.add(new User("jackson", 20, true, "my name is jackson", "BEIJING"));users.add(new User("jackson", 20, true, "", "BEIJING"));users.add(new User("lucy", 21, false, "my name is lucy", "TIANJIN"));users.add(new User("tom", 22, false, "my name is tom", "SHANGHAI"));users.add(new User("smith", 23, true, "my name is smith", "SHENZHEN"));users.add(new User("ford", 24, true, "my name is ford", "WUHAN"));users.add(new User("king", 24, true, "", ""));return users;}
}
<tr th:each="user : ${users}"><td th:text="${user.name}"></td><td th:text="${user.age}"></td><td th:text="${user.gender}"></td><td th:text="${user.desc}"></td><td th:text="${user.location}"></td>
</tr>
  • ${users}:代表集合
  • user:代表集合中的每个元素
  • ${user.name}:元素的name属性值
<div class="container"><h1>动态表格</h1><form id="add-row-form"><input type="text" id="name" placeholder="姓名" required><input type="email" id="email" placeholder="电子邮件" required><button type="submit">添加行</button></form><table><thead><tr><th>序号</th><th>姓名</th><th>年龄</th><th>性别</th><th>简介</th><th>居住地</th><th>状态信息</th></tr></thead><tbody id="table-body"><tr th:object="${user}" th:each="user,state : ${users}"><td>1</td><td th:text="*{name}">张三</td><td th:text="*{age}">30</td><td th:text="${user.gender ? '男' : '女'}">男</td><td th:if="${#strings.isEmpty(user.desc)}" th:text="'你这个人很懒'"></td><td th:if="${not #strings.isEmpty(user.desc)}" th:text="${user.desc}"></td><!--<td>[[${user.location}]]</td>--><td th:switch="${user.location}"><span th:case="BEIJING">北京</span><span th:case="SHANGHAI">上海</span><span th:case="TIANJIN">天津</span><span th:case="WUHAN">武汉</span><span th:case="SHENZHEN">深圳</span><span th:case="*">未知</span></td><td>状态信息:内联表达式<br><!--[[${state.index}]]这种语法属于thymeleaf中的内联表达式写法。也可以写成:[(${state.index})]-->下标:[[${state.index}]]<br>序号:[(${state.count})]<br>当前对象:[(${state.current})]<br>元素总数:[(${state.size})]<br>是否为偶数行:[(${state.even})]<br>是否为奇数行:[(${state.odd})]<br>是否是第一个元素:[(${state.first})]<br>是否是最后一个元素:[(${state.last})]<br></td></tr></tbody></table>
</div>

7.3.3 *{...}表达式

*{...} 主要用于在上下文中访问对象的属性。

语法*{property}:访问当前上下文对象的某个属性。

<form th:object="${user}" method="post" action="/submit"><label for="name">Name:</label><input type="text" id="name" name="name" th:field="*{name}" /> <label for="age">Age:</label><input type="number" id="age" name="age" th:field="*{age}" /><button type="submit">Submit</button>
</form>
  • th:object="${user}"user 对象设置为当前上下文对象。
  • th:field="*{name}"th:field="*{age}" 分别绑定到 user 对象的 nameage 属性。

${...}:标准表达式,用于访问模型中的变量和执行简单的表达式。

*{...}:属性选择表达式,用于在上下文中访问对象的属性,通常与 th:object 一起使用。

7.3.4 thymeleaf属性优先级

“先控制,再遍历,后操作,末内容。”

具体来说:

  1. 先控制th:ifth:unless 用于条件控制,决定是否渲染元素。
  2. 再遍历th:each 用于遍历列表,生成多个元素。
  3. 后操作th:withth:switchth:caseth:removeth:attr 等用于局部变量定义、条件分支、属性操作等。
  4. 末内容th:textth:utextth:html 等用于设置元素的内容。

7.3.5 代码片段共享

公共的header.html

<header th:fragment="h"><nav><ul><li><a th:href="@{/a}">Home</a></li><li><a th:href="@{/b}">About</a></li></ul></nav>
</header>

公共的footer.html

<footer th:fragment="f"><p>&copy; 2025 hnlgnb</p>
</footer>

代码共享a.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head><title>主页</title>
</head>
<body>
<div th:replace="~{header :: h}"></div><main><h1>欢迎来到主页</h1><p>这是主页的主要内容.</p>
</main><div th:replace="~{footer :: f}"></div>
</body>
</html>
  • 在公共代码部分使用th:fragment="片段名称"来声明公共代码片段的名字。
  • 在需要引入的地方使用th:replace="~{文件名去掉后缀 :: 片段名称}"来引入。

7.3.6 无需controller跳转到指定视图

spring.mvc.view.prefix=/templates/
spring.mvc.view.suffix=.html
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {@Overridepublic void addViewControllers(ViewControllerRegistry registry) {registry.addViewController("/a").setViewName("a");registry.addViewController("/b").setViewName("b");}
}

7.3.7 thymeleaf页面修改立即生效

1. 引入依赖

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><scope>runtime</scope><optional>true</optional>
</dependency>

2. 关闭应用重启功能,如果不关闭会导致每一次修改java代码后立即重启应用,不建议。我们现在只希望做到的功能是,修改thymeleaf模板文件后立即生效。

spring.devtools.restart.enabled=false

3. 修改代码后在IDEA中按组合键ctrl+f9

8.异常处理

8.1 自适应的错误处理机制

springboot会根据请求头的Accept字段来决定错误的响应格式。

类型说明
text/html

文档是 HTML 格式的文本内容, 

字符集可指定,如:text/html; charset=UTF-8

application/xhtml+xmlXHTML 文档,结构更严格,用 XML 解析器解析
application/jsonJSON 数据
application/xmlXML 数据
application/pdfPDF 文件
场景推荐 Accept 头
浏览网页text/html(浏览器自动加)
调用 REST API 获取 JSONapplication/json
获取 XML 数据application/xml
下载文件*/* 或具体类型(如 application/pdf
前后端分离项目application/json
内容协商测试application/json;q=0.9, text/html;q=0.8(最想要JSON,其次是HTML)

8.2 SpringMVC的错误处理方案

如果程序员使用了SpringMVC的错误处理方案,SpringBoot的错误处理方案不生效。

    8.2.1 局部控制@ExceptionHandler

    在控制器当中编写一个方法,方法使用@ExceptionHandler注解进行标注,凡是这个控制器当中出现了对应的异常,则走这个方法来进行异常的处理。局部生效。

    @RestController
    /*@Controller
    @ResponseBody*/
    public class UserController {// RESTFul风格@GetMapping("/resource/{id}")public String getResource(@PathVariable("id") Long id){if(id == 1){throw new IllegalArgumentException("无效ID:" + id);}return "ID = " + id;}// springmvc中的异常处理方案:局部方式。// 只有在UserController中发生 IllegalArgumentException 异常时,会走下面这个方法进行异常处理。/*@ExceptionHandler(IllegalArgumentException.class)public String handlerIllegalArgumentException(IllegalArgumentException e){return "错误信息:" + e.getMessage();}*/}

    8.2.2 全局控制@ControllerAdvice + @ExceptionHandler

    @RestController
    public class OtherController {@GetMapping("/other/{id}")public String getResource(@PathVariable("id") Long id){if(id == 1){throw new IllegalArgumentException("无效ID:" + id);}return "ID = " + id;}
    }

    8.3 SpringBoot的错误处理方案

    如果SpringMVC没有对应的处理方案,会开启SpringBoot默认的错误处理方案。

    SpringBoot默认的错误处理方案如下:

    1. 如果客户端要的是json,则直接响应json格式的错误信息。

    2. 如果客户端要的是html页面,则按照下面方案:

    • 第一步(精确错误码文件):去classpath:/templates/error/目录下找404.html500.html精确错误码.html文件。如果找不到,则去静态资源目录下的/error目录下找。如果还是找不到,才会进入下一步。
    • 第二步(模糊错误码文件):去classpath:/templates/error/目录下找4xx.html5xx.html模糊错误码.html文件。如果找不到,则去静态资源目录下的/error目录下找。如果还是找不到,才会进入下一步。
    • 第三步(通用错误页面):去找classpath:/templates/error.html如果找不到则进入下一步。
    • 第四步(默认错误处理):如果上述所有步骤都未能找到合适的错误页面,Spring Boot 会使用内置的默认错误处理机制,即 /error 端点。

    8.4 在错误页获取错误信息

    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www.thymeleaf.org">
    <head><meta charset="UTF-8"><title>error</title>
    </head>
    <body><!--通用错误页面--><h1>error通用错误</h1>异常发生时间:<span th:text="${timestamp}"></span><br>HTTP状态码:<span th:text="${status}"></span><br>错误类型:<span th:text="${error}"></span><br>异常类名:<span th:text="${exception}"></span><br>错误信息:<span th:text="${message}"></span><br>堆栈跟踪:<span th:text="${trace}"></span><br>
    </body>
    </html>

    springboot3.3.5版本默认只向Model对象中绑定了timestampstatuserror。如果要保存exceptionmessagetrace,需要开启以下三个配置:

    server.error.include-exception=trueserver.error.include-message=alwaysserver.error.include-stacktrace=always

    8.5 前后端分离项目的错误解决方案

    统一使用SpringMVC的错误处理方案,定义全局的异常处理机制:@ControllerAdvice + @ExceptionHandler

    返回json格式的错误信息,其它的就不需要管了。

    8.6 服务器端负责页面渲染的项目错误处理方案

    如果发生的异常是HTTP错误状态码:

            建议常见的错误码给定精确错误码.html

            建议不常见的错误码给定模糊错误码.html

    如果发生的异常不是HTTP错误状态码,而是业务相关异常:

            在程序中处理具体的业务异常,自己通过程序来决定跳转到哪个错误页面。

            建议提供classpath:/templates/error.html来处理通用错误。

    9. 实现国际化

    9.1 创建资源文件

    创建包含不同语言版本的消息文件。这些文件通常放在src/main/resources目录下,并且以.properties为扩展名。例如:

    • messages.properties (默认语言,如英语)
    • messages_zh_CN.properties (简体中文)
    • messages_fr.properties (法语)

    每个文件都应包含相同的消息键,但值应对应于相应的语言。例如:messages.properties:

    welcome.message=Welcome to our application!

    messages_zh_CN.properties:

    welcome.message=欢迎来到我们的应用!

    messages_fr.properties:

    welcome.message=Bienvenue dans notre application !

    9.2 模板文件中取出信息

    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www.thymeleaf.org">
    <head><meta charset="UTF-8"><title>welcome</title>
    </head>
    <body><!--获取的是配置文件中的key-value值  welcome.message=Welcome to our application!--><h1 th:text="#{welcome.message}"></h1>
    </body>
    </html>

    9.3 国际化实现原理

    国际化的自动配置类是:MessageSourceAutoConfiguration

    国际化对应的配置前缀是:spring.message

    application.properties文件配置

    # 配置国际化文件命名的基础名称
    spring.messages.basename=messages# 指定国际化信息的字符编码方式
    spring.messages.encoding=UTF-8
    @RestController
    public class MyController {@Autowiredprivate MessageSource messageSource;@GetMapping("/test")public String getSource(HttpServletRequest request) {String message = messageSource.getMessage("welcome.message", null, request.getLocale());return message;}
    }

    10. 定制web容器(服务器)

    10.1 web服务器切换为jetty

    springboot默认嵌入的web服务器是Tomcat,如何切换到jetty服务器?

    实现方式:排除Tomcat,添加Jetty依赖

    修改 pom.xml 文件:在 pom.xml 中,确保使用 spring-boot-starter-web 并排除 Tomcat,然后添加 Jetty 依赖。

    <!-- 排除 Tomcat -->
    <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><exclusions><exclusion><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-tomcat</artifactId></exclusion></exclusions>
    </dependency>
    <!-- 添加 Jetty 依赖 -->
    <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jetty</artifactId>
    </dependency>
    

    10.2 web服务器切换原理

    生效条件是,看类路径当中是否有对应服务器相关的类,如果有则生效。spring-boot-web-starter这个web启动器引入的时候,它间接引入的是tomcat服务器的jar包。因此默认Tomcat服务器被嵌入。如果想要切换web服务器,将tomcat相关jar包排除掉,引入jetty的jar包之后,jetty服务器就会生效,这就是切换web服务器的原理。

    10.3 web服务器优化

    web服务器的相关配置和ServerProperties有关系:

    得知web服务器的配置都是以server开头的。

    如果要对tomcat服务器进行配置,前缀为:server.tomcat

    如果要对jetty服务器进行配置,前缀为:server.jetty

    # 这个参数决定了 Tomcat 在接收请求时,如果在指定的时间内没有收到完整的请求数据,将会关闭连接。这个超时时间是从客户端发送请求开始计算的。
    # 防止长时间占用资源:如果客户端发送请求后,长时间没有发送完所有数据,Tomcat 会在这个超时时间内关闭连接,从而释放资源,避免资源被长时间占用。
    server.tomcat.connection-timeout=20000# 设置 Tomcat 服务器处理请求的最大线程数为 200。
    # 如果超过这个数量的请求同时到达,Tomcat 会将多余的请求放入一个等待队列中。
    # 如果等待队列也满了(由 server.tomcat.accept-count 配置),新的请求将被拒绝,通常会返回一个“503 Service Unavailable”错误。
    server.tomcat.max-threads=200# 用来设置等待队列的最大容量
    server.tomcat.accept-count=100# 设置 Tomcat 服务器在空闲时至少保持 10 个线程处于活动状态,以便快速响应新的请求。
    server.tomcat.min-spare-threads=10# 允许 Tomcat 服务器在关闭后立即重新绑定相同的地址和端口,即使该端口还在 TIME_WAIT 状态
    # 当一个网络连接关闭时,操作系统会将该连接的端口保持在 TIME_WAIT 状态一段时间(通常是 2-4 分钟),以确保所有未完成的数据包都能被正确处理。在这段时间内,该端口不能被其他进程绑定。
    server.tomcat.address-reuse-enabled=true# 设置 Tomcat 服务器绑定到所有可用的网络接口,使其可以从任何网络地址访问。
    server.tomcat.bind-address=0.0.0.0# 设置 Tomcat 服务器使用 HTTP/1.1 协议处理请求。
    server.tomcat.protocol=HTTP/1.1# 设置 Tomcat 服务器的会话(session)超时时间为 30 分钟。具体来说,如果用户在 30 分钟内没有与应用进行任何交互,其会话将被自动注销。
    server.tomcat.session-timeout=30# 设置 Tomcat 服务器的静态资源缓存时间为 3600 秒(即 1 小时),这意味着浏览器会在 1 小时内缓存这些静态资源,减少重复请求。
    server.tomcat.resource-cache-period=3600# 解决get请求乱码。对请求行url进行编码。
    server.tomcat.uri-encoding=UTF-8# 设置 Tomcat 服务器的基础目录为当前工作目录(. 表示当前目录)。这个配置指定了 Tomcat 服务器的工作目录,包括日志文件、临时文件和其他运行时生成的文件的存放位置。 生产环境中可能需要重新配置。
    server.tomcat.basedir=.

    11. logo设置

    11.1 关闭图标

    11.1.1 配置方式

    # 关闭logo的配置
    spring.main.banner-mode=off

    11.1.2 代码方式

    @SpringBootApplication
    public class Springboot322WebServerApplication {public static void main(String[] args) {SpringApplication.run(Springboot322WebServerApplication.class, args);// 关闭logo使用代码方式实现(第一种方式)/*SpringApplication springApplication = new SpringApplication(Springboot322WebServerApplication.class);springApplication.setBannerMode(Banner.Mode.OFF);springApplication.run(args);*/// 流式编程/链式编程/*new SpringApplicationBuilder().sources(Springboot322WebServerApplication.class).bannerMode(Banner.Mode.OFF).run(args);*/}
    }

    11.2 修改图标

    src/main/resources目录下存放一个banner.txt文件。文件名固定。

    利用一些网站生成图标:

    https://www.bootschool.net/ascii (支持中文、英文)

    http://patorjk.com/software/taag/ (只支持英文)

    https://www.degraeve.com/img2txt.php (只支持图片)

    获取图标粘贴到banner.txt文件中运行程序即可。

    12. PageHelper整合

    12.1 引入依赖

    <dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper-spring-boot-starter</artifactId><version>2.1.0</version>
    </dependency>

    12.2 PageHelper实现

    @RestController
    public class VipController {@Autowiredprivate VipService vipService;// RESTFul编程风格@GetMapping("/list/{pageNo}")public PageInfo<Vip> list(@PathVariable int pageNo) {// 1. 设置当前页码和每页显示的记录条数。// 这行代码只要执行,将来执行sql语句的时候会自动添加 limit,比较方便。PageHelper.startPage(pageNo, Constant.PAGE_SIZE);// 2. 查询数据List<Vip> vips = vipService.findAll();// 3. 将数据封装到PageInfo对象当中即可。PageInfo<Vip> vipPageInfo = new PageInfo<>(vips);return vipPageInfo;}}

    13. web层响应结果封装

    13.1 封装R对象

    // 专门维护code+msg的一个枚举类型
    //@Data
    @NoArgsConstructor
    @AllArgsConstructor
    //@Setter
    public enum CodeEnum {//这地方没有写枚举值,那么由于后面有其他代码,这里至少要写一个“;”OK(200, "成功"),FAIL(400, "失败"),BAD_REQUEST(400, "请求错误"),NOT_FOUND(404, "Not Found"),INTERNAL_ERROR(500, "内部服务器错误"),MODIFICATION_FAILED(400, "修改失败"),DELETION_FAILED(400, "删除失败"),CREATION_FAILED(400, "创建失败");// javase当中详细讲过枚举类型// 枚举类型当中可以有属性// 枚举类型当中可以有构造方法// 枚举类型当中可以有setter和getter方法。// 在枚举类型当中有一个语法要求,枚举的大括号一开始的位置必须编写枚举值。// 每一个枚举值就是一个枚举类型的实例。@Setter@Getterprivate int code;@Setter@Getterprivate String msg;
    }
    /*** 统一的WEB层返回数据。统一格式,降低前后端沟通成本。* @param <T>*/
    @Builder // 建造模式
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public class R<T> {// 响应的状态码: 200、500、404private int code;// 响应的消息描述:成功,失败,删除失败,修改失败,添加失败private String msg;// 响应的对象:支持任意类型的对象private T data;// 为了方便返回数据,一般这里的方法都是静态方法。// 方法一般包括两大类:一类是成功,一类是失败。(重载)// 响应成功的消息,但是不携带任何数据// 如果在静态方法中使用泛型,则需要在方法返回值类型前进行泛型的声明public static <T> R<T> OK() {return R.<T>builder().code(CodeEnum.OK.getCode()).msg(CodeEnum.OK.getMsg()).build();}// 响应成功的消息,携带数据datapublic static <T> R<T> OK(T data) {return R.<T>builder().code(CodeEnum.OK.getCode()).msg(CodeEnum.OK.getMsg()).data(data).build();}// 响应失败的消息。默认的code是400,失败的消息:失败// 失败是不可能携带数据。public static <T> R<T> FAIL() {return R.<T>builder().code(CodeEnum.FAIL.getCode()).msg(CodeEnum.FAIL.getMsg()).build();}// 响应失败的消息,controller层的程序员可以通过此方法指定特定的code和特定的消息。/*public static <T> R<T> FAIL(int code, String msg) {return R.<T>builder().code(code).msg(msg).build();}*/public static <T> R<T> FAIL(CodeEnum codeEnum) {return R.<T>builder().code(codeEnum.getCode()).msg(codeEnum.getMsg()).build();}
    }

    14. 事务管理

    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    @Service
    public class AccountServiceImpl implements AccountService {@Autowiredprivate AccountMapper accountMapper;@Overridepublic void transfer(String fromActNo, String toActNo, double money) {Account fromAct = accountMapper.selectByActNo(fromActNo);if(fromAct.getBalance() < money){throw new TransferException("余额不足");}Account toAct = accountMapper.selectByActNo(toActNo);fromAct.setBalance(fromAct.getBalance() - money);toAct.setBalance(toAct.getBalance() + money);int count = accountMapper.update(fromAct);if(1 == 1){throw new TransferException("转账失败");}count += accountMapper.update(toAct);if(count != 2){throw new TransferException("转账失败!");}}
    }

    15. SpringBoot打war包

    第一步:将打包方式设置为war

    <packaging>war</packaging>

    第二步:排除内嵌tomcat

    <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><!--内嵌的tomcat服务器排除掉--><exclusions><exclusion><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-tomcat</artifactId></exclusion></exclusions>
    </dependency>

    第三步:添加servlet api依赖(引入tomcat,但scope设置为provided,这样这个tomcat服务器就不会打入war包了)

    <!--额外添加一个tomcat服务器,实际上是为了添加servlet api。scope设置为provided表示这个不会被打入war包当中。-->
    <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-tomcat</artifactId><scope>provided</scope>
    </dependency>

    第四步:修改主类

    @MapperScan(basePackages = "com.powernode.transaction.repository")
    @SpringBootApplication
    public class Springboot324TransactionApplication extends SpringBootServletInitializer{// 为传统 Servlet 容器提供了一个“入口”,// 让外部 Tomcat 知道:“这个类是 Spring Boot 应用的起点。”@Overrideprotected SpringApplicationBuilder configure(SpringApplicationBuilder application) {return application.sources(Springboot324TransactionApplication.class);}public static void main(String[] args) {SpringApplication.run(Springboot324TransactionApplication.class, args);}}

    第五步:执行package命令打war包

    第六步:配置tomcat环境,将war包放入到webapps目录下,启动tomcat服务器,并访问。

    16. SpringBoot的日志处理

    16.1 Java中的日志框架

    16.1.1 抽象的日志框架

    什么是抽象的日志框架?编译阶段可以使用这些抽象的日志框架,能够正常编译通过,但运行阶段必须提供具体的日志框架,这样做的目的是:具体的日志框架可灵活切换。

    SLF4J (Simple Logging Facade for Java)

    • 简介:SLF4J不是一个具体的日志实现,而是一个简单的抽象层,允许开发者在应用程序中使用统一的日志API,而实际的日志实现可以在部署时决定。
    • 特点:提供了统一的日志记录接口,使得日志框架的选择更加灵活,易于切换不同的日志实现,减少了应用程序对特定日志框架的依赖。
    • 运行时可绑定的具体日志框架:Log4j、Log4j2、Logback、JUL。

    Commons Logging (Jakarta Commons Logging)

    • 简介:Commons Logging是Apache Jakarta项目的一部分。也是一种日志层面的抽象。
    • 特点:允许在运行时动态选择日志实现,但因类加载机制的问题,有时会导致难以预料的行为,因此不如SLF4J受欢迎。
    • 运行时可绑定的具体日志框架:Log4j、Log4j2、Logback、JUL。

    16.1.2 具体的日志框架

    Log4j(太老,没人用了)

    特点:易于配置和使用,支持日志滚动策略,适用于中小规模的应用。

    Log4j 2

    特点:性能更优,支持插件化配置,增强了安全性,支持异步日志记录,减少了线程间的竞争,提高了日志记录的速度。

    Logback

    特点:与SLF4J无缝集成,提供了比Log4j更好的性能表现,支持自动重载配置文件,具有更简洁的API和更少的bug。

    JUL (Java Util Logging)

    • 简介:JUL是Java SE平台自带的日志框架,从Java 1.4版本开始提供。
    • 特点:不需要额外的库文件,配置相对简单,适合小型应用。然而,相对于其他流行的日志框架,JUL的功能较为有限,配置不够灵活。

    SpringBoot框架默认使用的日志框架是:Logback。

    16.2 日志级别

    常见的日志级别从低到高通常包括以下几种:

    1. TRACE:这是最低级别的日志信息,用于记录最详细的信息,通常是在调试应用时使用。
    2. DEBUG:用于记录程序运行时的详细信息,比如变量的值、进入或退出某个方法等,主要用于开发阶段的调试。
    3. INFO:记录应用程序的一般信息,如系统启动、服务初始化完成等,表示程序运行正常。
    4. WARN:警告信息,表示可能存在问题或者异常的情况,但是还不至于导致应用停止工作。
    5. ERROR:错误信息,表示发生了一个错误事件,该错误可能会导致某些功能无法正常工作。

    通过设置不同的日志级别,可以在生产环境中控制输出的日志量,从而减少对性能的影响。例如,

    • 在生产环境中,我们可能会将日志级别设置为INFO或更高级别,以避免输出过多的调试信息;
    • 而在开发或测试环境中,则可以将日志级别降低至DEBUG甚至TRACE,以便于进行详细的错误追踪和调试。

    日志级别从低到高的排序是:TRACE < DEBUG < INFO < WARN < ERROR

    级别越低,打印的日志信息越多。SpringBoot默认的日志级别是INFO。

    开发环境下可以打印多一些,一般是用INFO级别。

    生产环境下要严格控制,因为日志级别越低,磁盘空间受不了。

    SpringBoot默认将日志打印到控制台。(通过配置可以改变打印到日志文件)


    16.3 更改日志级别

    使用Lombok的 @Slf4j 注解自动维护一个log对象:

    @Slf4j
    @SpringBootApplication
    public class TestApplication {public static void main(String[] args) {SpringApplication.run(TestApplication.class, args);log.trace("trace级别日志");log.debug("debug级别日志");log.info("info级别日志");log.warn("warn级别日志");log.error("error级别日志");}
    }

    默认情况下,SpringBoot默认的日志隔离级别是INFO,因此:INFO,WARN,ERROR三个级别的日志都会打印。

    // 更改日志级别
    logging.level.root=DEBUG

    16.4 丰富启动日志

    trace=true
    debug=true

    这两个配置项主要影响Spring Boot框架本身的启动日志和跟踪信息,不影响在应用程序中编写的日志记录。

    • debug=true:启用Spring Boot的调试模式,增加启动日志的详细程度并显示自动配置报告。
    • trace=true:启用Spring Boot的启动跟踪,生成包含启动信息的详细跟踪文件,内容是包含debug=true输出的内容的。

    16.5 日志的粗细粒度

    # 设置根日志级别为 INFO(整个项目都使用INFO日志级别,这是粗粒度的配置。)
    logging.level.root=INFO# 为特定的包设置日志级别为 DEBUG
    logging.level.com.powernode=DEBUG# 为特定的类设置日志级别为 TRACE
    logging.level.com.powernode.MyService=TRACE

    项目中打印SQL语句

    logging.level.root=INFO
    logging.level.com.powernode.mapper=DEBUG

    16.6 日志输出到文件

    如果日志要输出文件,可以进行如下配置:

    logging.file.path=./log/logging.file.path=D:/log

    以上配置表示将日志文件输出到当前工程根目录下的log目录当中,文件名默认叫做spring.log。并且文件名不可设置。

    logging.file.name=my.log
    

    以上的配置表示在工程的根目录下直接生成my.log文件。并且路径不可设置。

    以上两个配置同时存在时,只有logging.file.name生效。本质上两个配置不可共存。

    16.7 滚动日志

    滚动日志是一种日志管理机制,用于防止日志文件无限增长,通过将日志文件分割成多个文件,每个文件只包含一定时间段或大小的日志记录。滚动日志可以帮助你更好地管理和维护日志文件,避免单个日志文件过大导致难以处理。

    # 日志文件达到多大时进行归档
    logging.logback.rollingpolicy.max-file-size=100MB# 所有的归档日志文件总共达到多大时进行删除,默认是0B表示不删除
    logging.logback.rollingpolicy.total-size-cap=50GB# 归档日志文件最多保留几天
    logging.logback.rollingpolicy.max-history=60# 启动项目时是否要清理归档日志文件
    logging.logback.rollingpolicy.clean-history-on-start=false# 归档日志文件名的格式
    logging.logback.rollingpolicy.file-name-pattern=${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz

    16.8 日志框架切换

    <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><exclusions><!--排除掉默认的日志依赖--><exclusion><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-logging</artifactId></exclusion></exclusions>
    </dependency><!--使用Log4j2日志依赖-->
    <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-log4j2</artifactId>
    </dependency>
    http://www.dtcms.com/a/393370.html

    相关文章:

  • Python 中的 Builder 模式实践 —— 以 UserProfileBuilder 为例
  • 探秘陌讯AIGC检测算法优化:详解MPS加速与模型热重载的实现原理
  • 1.3 管道(Pipe)核心知识点总结
  • GLUE:自然语言理解评估的黄金基准
  • 第13章 智能监测-设备数据处理
  • GEO技术科普
  • B004基于三菱FX2NPLC智能自提柜控制系统仿真
  • MTK CPU温度调节一知半解
  • V90伺服驱动器“速度模式“双极性模拟量速度控制
  • 课前练习题-20250919
  • C++类与对象
  • 企业级Docker镜像仓库Harbor
  • ESD防护设计宝典(七):生命线的秩序——关键信号线布线规则
  • 【ROS2】Beginner : CLI tools - 理解 ROS 2 话题
  • RL知识回顾
  • Java多线程编程指南
  • 【论文速读】基于地面激光扫描(TLS)和迭 代最近点(ICP)算法的土坝监测变形分析
  • GAMES101:现代计算机图形学入门(Chapter2 向量与线性代数)迅猛式学线性代数学习笔记
  • 汉语构词智慧:从历史优势到现实考量——兼论“汉语全面改造英语”的可能性
  • 仿tcmalloc高并发内存池
  • 墨者学院-通关攻略(持续更新持续改进)
  • 10厘米钢板矫平机:把“波浪”压成“镜面”的科学
  • ESP32- 项目应用1 智能手表之网络配置 #6
  • TCP/IP 互联网的真相:空间域和时间域的统计学
  • 同步与异步
  • C++中char与string的终极对比指南
  • Java基础 9.20
  • U228721 反转单链表
  • 串行总线、并行总线
  • `HTML`实体插入软连字符: `shy;`