学习SpringBoot笔记--知识点(1)

目录

SpringBoot介绍

创建一个最基础的springbooot项目

使用Spring Initializr创建springboot项目

Spring Boot 自动配置机制

SpringBoot常用注解

1.组件注册

2.条件注解

3.属性绑定

SpringBoot自动配置流程​编辑

学习SpringBoot的方法

​编辑

SpringBoot日志配置

日志格式:

自定义日志格式:

使用日志:

指定日志级别:

日志分组:​编辑

日志文件输出:

日志归档和切割:(默认开启)

自定义日志系统:​编辑

切换默认日志系统:

SpringBoot Web开发

静态资源

WebMvcAutoConfiguration自动配置类分析

默认配置

自定义静态资源规则

路径匹配

内容协商

自定义数据格式返回

WebMvcConfigurationSupport

模板引擎

Thymeleaf整合

使用​编辑

SpringBoot开发工具

国际化

错误处理

MVC处理机制:

boot机制:

最佳实战

​编辑

嵌入式容器

Web新特性

Problemdetails

函数式Web(估计用不到)


版本要求

SpringBoot介绍

SpringBoot 能够帮我们简单、快速地创建一个独立的、生产级别的Spring应用

特性:

  • 快速创建独立Spring应用
  • 直接嵌入tomcat、jetty或Undertow等Servlet容器,无需部署war包
  • 提供可选的starter,简化应用整合
  • 按需自动配置Spring以及第三方库
  • 提供生产级别特性:如 监控指标、健康检查(k8s)、外部化配置等
  • 无代码生成,无xml

创建一个最基础的springbooot项目

1.创建项目

2.将父工程设置为spring-boot-starter-parent,导入springboot web 开发的基础依赖:spring-boot-starter-web,设置springboot打包插件:spring-boot-maven-plugin

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.qiu</groupId><artifactId>boot-1-project</artifactId><version>1.0-SNAPSHOT</version>
<!--    springboot项目必须继承 spring-boot-starter-parent--><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.0.5</version></parent><dependencies>
<!--        web开发的场景启动器--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency></dependencies><build><plugins>
<!--            springboot项目的打包插件--><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

3.编写启动类,springboot web项目可以直接运行该类来启动项目,不需要tomcat等服务器,因为springboot已经内置服务器。

//启动类注解
@SpringBootApplication
public class SpringMain {public static void main(String[] args) {//固定代码:SpringApplication.run(启动类的类对象,main函数的参数);SpringApplication.run(SpringMain.class,args);}
}

4.编写服务

@RestController
// ==  Controller(将该类放入ioc容器) + ResponseBody(以数据格式返回,不添加该注解会经过视图解析器)
public class HelloController {//请求映射:/hello的请求会调用该方法@RequestMapping("hello")public String hello(){//将数据返回return "hello spring boot3 !";}
}

5.启动服务

6.访问服务

7.将项目打包

8.运行项目:把jar包放到有java环境的服务器上就可以直接启动(记得把项目停掉)

9.springboot可以不在源码修改配置文件,在jar包目录下创建一个 .properties 配置文件就可以覆盖配置,还可以创建config文件夹,把配置文件放进去,优先级更高


使用Spring Initializr创建springboot项目

创建服务并启动项目:

@RestController
public class HelloController {@RequestMapping("hello")public String hello(){return "hello spring init";}}


Spring Boot 自动配置机制

  • 自动配置的Tomcat,SpringMVC等
    • springboot自动配置DispatcherServlet、ViewResolver、CharacterEncodingFilter等组件
    • 如果需要哪些组件,只需要把启动器导入,就自动配置到ioc容器
    • 可以使用以下代码查看配置的组件
public static void main(String[] args) {//获取ioc容器ConfigurableApplicationContext run = SpringApplication.run(Boot2ProjectApplication.class, args);//查看所有组件//springboot自动配置好核心组件for (String name : run.getBeanDefinitionNames()) {System.out.println(name);}}
  • 默认的包扫描规则
    • 默认扫描启动类的目录及子目录
    • 可以@SpringBootApplication(scanBasePackages="com.qiu")
    • 也可以@ComponentScan("com.qiu")
  • 配置默认值
    • 配置文件中的所有配置项都是跟某个类的对象值一一对应的。
    • 在application.properties中按住ctrl点击对应的配置项可以跳转到对应的类。
    • 这样的类叫做配置属性类。
    • 比如:ServerProperties包含所有Tomcat服务器相关的配置 , MultipartProperties包含所有文件上传相关的配置。
  • 按需加载自动配置
    • 当导入启动器,如:spring-boot-starter-web时,启动器除了会导入相关功能的依赖,还会导入一个spring-boot-starter
    • spring-boot-starter是所有启动器的启动器,是基础核心starter
    • spring-boot-starter导入了spring-boot-autoconfigure,这个包有所有启动器的AutoConfiguration(自动配置类)
    • 但不会全部开启,只有导入对应的启动器时才会开启相应的自动配置

SpringBoot常用注解

SpringBoot不再使用XML配置方式,使用全注解驱动

1.组件注册

@Configuration:在类上添加,表明是个配置类,替代配置文件。

@SpringBootConfiguration:与@Configuration功能相同,更见名知意。

@Bean:在配置类下的方法上添加,替代<Bean>标签。

@Controller、@Service、@Repository、@Component:在类上使用,表明把这个类放到ioc容器。

@Import:可以导入任意类,当我们需要把第三方的组件放到ioc容器中,除了使用@Bean,还可以直接在配置类上使用@Import( … .class) 将组件放到ioc容器中。

@ComponentScan:在配置类上使用@ComponentScan("路径"),来扫描路径下的组件放到ioc容器中。

2.条件注解

@ConditionalOnXxx:

@ConditionOnClass:如果类路径中存在这个类,则触发指定行为

@ConditionOnMissingClass:如果类路径中不存在这个类,则触发指定行为

@ConditionOnBean:如果容器中存在这个Bean,则触发指定行为

@ConditionOnMissingBean:如果容器中不存在这个Bean,则触发指定行为

解释:当ioc容器中有FastsqlException组件就把Cat类放到ioc容器,没有就把Dog类放到ioc容器中。

如果该注解放到配置类上,这个配置类才生效。

3.属性绑定

@ConfigurationProperties

@EnableConfigurationProperties

将容器的任意组件的属性值和配置文件的配置项的值进行绑定。

示例:编写application配置文件

student.id=1
student.name=qiu
student.age=22

创建pojo类并放到ioc容器


@Component
public class Student {@Overridepublic String toString() {return "Student{" +"id=" + id +", name='" + name + '\'' +", age=" + age +'}';}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}Integer id;String name;Integer age;
}

只要类中属性与配置文件的配置项相同,就在类上添加注解(类属性要有set和get方法)

@ConfigurationProperties(prefix = "student")
@Component
public class Student {@Overridepublic String toString() {return "Student{" +"id=" + id +", name='" + name + '\'' +", age=" + age +'}';}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}Integer id;String name;Integer age;
}

这样启动服务后,就会自动给组件赋值

EnableConfigurationProperties(Student.class)功能:(主要用在第三方)

1.开启Student组件的属性绑定

2.默认把该组件放到ioc容器中


SpringBoot自动配置流程


学习SpringBoot的方法

示例:

1、导入redis的启动器

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

2、导入启动器后就会有相应的自动配置类:RedisAutoConfiguration

     输入 ctrl + n 搜索可查看

3、在类上可以看到@EnableConfigurationProperties({RedisProperties.class}),这个注解开启了RedisProperties类的属性绑定,ctrl + 左键 查看

4、在类上看到@ConfigurationProperties( prefix = "spring.data.redis" ),就知道在配置文件对应配置项

5、在RedisAutoConfiguration中可以看到把哪些Bean放到ioc容器中,可以修改配置或覆盖


SpringBoot日志配置

日志接口日志实现类

JCL(Jakarta Commons Logging)

SLF4j(Simpple Logging Facade for Java)

jboss-logging

Log4j

JUL(java.util.logging)

Log4j2

Logback

Spring5以后把commons-logging作为内部日志,但支持jul,log4j2,logback。默认使用logback

日志格式:

2024-03-23T01:01:09.925+08:00  INFO 27188 --- [boot-2-project] [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
  • 默认格式:
    • 时间和日期:毫秒级精度
    • 日志级别:ERROR,WARN,INFO,DEBUG ,TRACE
    • 进程ID
    • ---:信息分割符
    • 线程名:使用[]包含
    • Logger名:通常是产生日志的类名
    • 消息:日志记录的内容

自定义日志格式:

%d{HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{36} - %msg%n

使用日志:

方法1:从日志工厂获得记录当前类的记录器(一个类可以有一个记录器),调用方法

方法2:在类使用@Slf4j注解(需要添加lombok依赖),它会在底层自动为这个类注入log属性,使用log打印日志。

指定日志级别:

Springboot默认所有日志只要没有指定日志级别就使用root的默认级别(info)或设置的级别:

logging.level.root = debug

日志内容可以使用占位符:

log.info("a:{},b:{}",a,b);

指定某个类或包的日志级别:

logging.level.com.qiu.boot2project.controller = info

日志分组:

日志文件输出:

指定文件名:只写名字生成到当前位置

logging.file.name=D:\\logging\\file.log

指定文件路径:日志文件名默认为spring.log

logging.file.path=D:\\logging\\

同时指定文件名和文件路径只看文件名

日志归档和切割:(默认开启)

# 归档    切割
# LOG_FILE 就是 自己配置的文件名      yyyy-MM-dd 时间       i 当天的第几个文件
# max-file-size 只要文件超过了1MB 切割下一个文件
logging.logback.rollingpolicy.file-name-pattern=${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz
logging.logback.rollingpolicy.max-file-size=1MB

只有logback才能直接配置,如果要使用其他日志系统,需要自行配置(log4j2需要添加log4j2.xml或log4j2-spring.xml)

自定义日志系统:

可以自行编写logback.xml或logback-spring.xml配置文件,这时springboot会读取这个配置文件,不使用默认的日志。

<?xml version="1.0" encoding="UTF-8"?><!-- 配置文件修改时重新加载,默认true -->
<configuration scan="true"><!--定义日志文件的存储地址 勿在 LogBack 的配置中使用相对路径--><property name="CATALINA_BASE" value="logs"></property><!-- 控制台输出 --><appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"><encoder charset="UTF-8"><!-- 输出日志记录格式 --><pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern></encoder></appender><!-- 第一个文件输出,每天产生一个文件 --><appender name="FILE1" class="ch.qos.logback.core.rolling.RollingFileAppender"><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><!-- 输出文件路径+文件名 --><fileNamePattern>${CATALINA_BASE}/aa.%d{yyyyMMdd}.log</fileNamePattern><!-- 保存30天的日志 --><maxHistory>30</maxHistory></rollingPolicy><encoder charset="UTF-8"><!-- 输出日志记录格式 --><pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern></encoder></appender><!-- 第二个文件输出,每天产生一个文件 --><appender name="FILE2" class="ch.qos.logback.core.rolling.RollingFileAppender"><file>${CATALINA_BASE}/bb.log</file><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><fileNamePattern>${CATALINA_BASE}/bb.%d{yyyyMMdd}.log</fileNamePattern><maxHistory>30</maxHistory></rollingPolicy><encoder charset="UTF-8"><pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern></encoder></appender><appender name="CUSTOM" class="ch.qos.logback.core.rolling.RollingFileAppender"><file>${CATALINA_BASE}/custom.log</file><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><!-- daily rollover --><fileNamePattern>${CATALINA_BASE}/custom.%d{yyyy-MM-dd}.log</fileNamePattern><!-- keep 30 days' worth of history --><maxHistory>30</maxHistory></rollingPolicy><encoder charset="UTF-8"><pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern></encoder></appender><!-- 设置日志输出级别 --><root level="ERROR"><appender-ref ref="CONSOLE" /></root><logger name="file1" level="DEBUG"><appender-ref ref="FILE1" /></logger><logger name="file1" level="INFO"><appender-ref ref="FILE2" /></logger><!-- 自定义logger --><logger name="custom" level="INFO"><appender-ref ref="CUSTOM" /></logger>
</configuration>

切换默认日志系统:

        <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><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-log4j</artifactId></dependency>

SpringBoot Web开发

依赖:

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

最佳实战:


静态资源

WebMvcAutoConfiguration自动配置类分析

1.生效条件:

@AutoConfiguration(after = {DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class, ValidationAutoConfiguration.class}
)//在这三个自动配置类后面开始自动配置
@ConditionalOnWebApplication(type = Type.SERVLET
)//如果是web应用,并且还得是servlet类型(还有Reactive 响应式web应用)才能生效
@ConditionalOnClass({Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class})//当存在这些Bean才生效
@ConditionalOnMissingBean({WebMvcConfigurationSupport.class})//当没有这个Bean才生效
@AutoConfigureOrder(-2147483638)//优先级
@ImportRuntimeHints({WebResourcesRuntimeHints.class})
public class WebMvcAutoConfiguration {

2.效果:

1.放了两个Bean:FormContentFilter 和 HiddenHttpMethodFilter

  • HiddenHttpMethodFilter:页面表单提交Rest请求(GET,POST,PUT,DELETE),不然表单只能发送GET和POST
  • FormContentFilter:表单内容Filter,不然只有GET(URL后面)和POST(请求体)能携带数据,PUT和DELETE请求体数据会被忽略。

2.给容器放了WebMvcConfigurer组件:给SpringMvc添加各种定制功能

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

 3.WebMvcConfigurer


4.静态资源的规则源码addResourceHandlers

public void addResourceHandlers(ResourceHandlerRegistry registry) {if (!this.resourceProperties.isAddMappings()) {logger.debug("Default resource handling disabled");} else {//规则1this.addResourceHandler(registry, this.mvcProperties.getWebjarsPathPattern(), "classpath:/META-INF/resources/webjars/");//规则2this.addResourceHandler(registry, this.mvcProperties.getStaticPathPattern(), (registration) -> {registration.addResourceLocations(this.resourceProperties.getStaticLocations());if (this.servletContext != null) {ServletContextResource resource = new ServletContextResource(this.servletContext, "/");registration.addResourceLocations(new Resource[]{resource});}});}}

规则1:访问 /webjars/** 就到 classpath:/META-INF/resources/webjars/ 下找资源。

             maven导入依赖,依赖jar包下的静态资源可以通过/webjars/访问

规则2:访问 /** 就到 "classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/" 这些下找资源。

规则3:静态资源默认都有缓存规则的设置

  • 所有缓存的配置修改,在配置文件的 spring.web
  • cachePeriod:缓存周期:多久不用找服务器要新的,默认没有,以秒为单位
  • cacheControl:HTTP缓存控制
  • useLastModified:是否使用最后一次修改,配合http cache规则

                如果浏览器访问了一个静态资源,如果服务器这个资源没有发生变化,下次访问直接让浏览器用自己缓存中的东西,而不是给服务器发请求。

//addResourceHandler方法内部
registration.setCachePeriod(this.getSeconds(this.resourceProperties.getCache().getPeriod()));
registration.setCacheControl(this.resourceProperties.getCache().getCachecontrol().toHttpCacheControl());
registration.setUseLastModified(this.resourceProperties.getCache().isUseLastModified());

5.EnableWebMvcConfiguration源码

@Configuration(proxyBeanMethods = false)@EnableConfigurationProperties({WebProperties.class})public static class EnableWebMvcConfiguration extends DelegatingWebMvcConfiguration implements ResourceLoaderAware {

 这个类继承了WebMvcConfigurationSupport,就是SpringBoot给容器中放了WebMvcConfigurationSupport组件。

如果我们自己放了这个组件,SpringBoot的WebMvcAutoConfiguration都不会生效;但他自己是在自动配置类生效后放的,不矛盾。

类下有方法WelcomePageHandlerMapping:只要静态资源路径内有index.html,项目启动就默认访问。


默认配置

静态资源映射

  • 访问 /webjars/** 就到 classpath:/META-INF/resources/webjars/ 下找资源。
    • maven导入依赖,依赖jar包下的静态资源可以通过/webjars/访问
  • 访问 /** 就到 "classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/" 这些下找资源。

静态资源缓存

静态资源默认都有缓存规则的设置

  • 所有缓存的配置修改,在配置文件的 spring.web
  • cachePeriod:缓存周期:多久不用找服务器要新的,默认没有,以秒为单位
  • cacheControl:HTTP缓存控制
  • useLastModified:是否使用最后一次修改,配合http cache规则

欢迎页

只要静态资源路径内有index.html,项目启动就默认访问。

Favicon

每次浏览器请求网站时,都会请求 /favicon.ico,只要静态资源路径下有该图标就会返回。

 缓存的一些配置


自定义静态资源规则

自定义静态资源路径,自定义缓存规则

1.配置方式

  • spring.mvc:
    • 静态资源访问前缀路径(你想要访问静态资源要在浏览器输入的路径的前缀)
  • spring.web:
    • 静态资源在服务器的位置前缀
    • 静态资源缓存策略

# 自定义webjars路径前缀
spring.mvc.webjars-path-pattern=/wj/**
# 静态资源访问路径前缀
spring.mvc.static-path-pattern=/static/**
# 自定义静态资源在服务器的位置
spring.web.resources.static-locations=classpath:/a/,classpath:/b/,classpath:/static/

2.代码方式

创建一个配置类,实现WebMvcConfigurer接口,不要添加@EnableWebMvc,它会禁用boot的springMvc自动配置。

@Configuration
public class MyConfig implements WebMvcConfigurer {@Overridepublic void addResourceHandlers(ResourceHandlerRegistry registry) {//保留默认配置WebMvcConfigurer.super.addResourceHandlers(registry);//自己写registry.addResourceHandler("/static/**").addResourceLocations("classpath:/a/","classpath:/b/").setCacheControl(CacheControl.maxAge(1180, TimeUnit.SECONDS));}
}

路径匹配

Spring5.3之前只支持AntPathMatcher,现在提供了PathPatternParser策略,并且可以指定使用哪种策略。默认使用新版策略。


内容协商

1.基于请求头:在请求头添加:Accept:application/数据格式(json,xml)

2.基于请求参数:在请求参数中添加format=数据格式(需要开启)

# 使用参数进行内容协商
spring.mvc.contentnegotiation.favor-parameter=true 
# 自定义参数名 ,默认为format
spring.mvc.contentnegotiation.parameter-name=myparam

SpringBoot会自动就数据转换为对应的数据格式

默认支持把数据对象写成json,因为web启动器默认导入了jackson处理json的包:jackcon-core。

jackson也支持把数据对象写成xml,要导入xml相关的处理依赖

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

在对象上添加注解

这样就可以根据请求返回xml数据对象了。

@Data
@JacksonXmlRootElement
public class People {private String name;private Integer sex;
}
自定义数据格式返回

内容协商原理-HttpMessageConverter

1.@ResponseBody 由 HttpMessageConverter 处理

2.WebMvcAutoConfiguration提供几个默认HttpMessageConverters

系统里功能有限,只能返回json或普通数据,要返回新的类型需要增加新的HttpMessageConverter。


WebMvcConfigurationSupport

提供了很多的默认配置

如果手动把它放到ioc容器,SpringBoot关于web的自动配置就会失效

该类判断系统中是否有相应的包,如果有,就加入相应的HttpMessageConverter,但顶多也就json和xml等,向yaml等依然不支持。

static {ClassLoader classLoader = WebMvcConfigurationSupport.class.getClassLoader();romePresent = ClassUtils.isPresent("com.rometools.rome.feed.WireFeed", classLoader);jaxb2Present = ClassUtils.isPresent("jakarta.xml.bind.Binder", classLoader);jackson2Present = ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper", classLoader) && ClassUtils.isPresent("com.fasterxml.jackson.core.JsonGenerator", classLoader);jackson2XmlPresent = ClassUtils.isPresent("com.fasterxml.jackson.dataformat.xml.XmlMapper", classLoader);jackson2SmilePresent = ClassUtils.isPresent("com.fasterxml.jackson.dataformat.smile.SmileFactory", classLoader);jackson2CborPresent = ClassUtils.isPresent("com.fasterxml.jackson.dataformat.cbor.CBORFactory", classLoader);gsonPresent = ClassUtils.isPresent("com.google.gson.Gson", classLoader);jsonbPresent = ClassUtils.isPresent("jakarta.json.bind.Jsonb", classLoader);kotlinSerializationCborPresent = ClassUtils.isPresent("kotlinx.serialization.cbor.Cbor", classLoader);kotlinSerializationJsonPresent = ClassUtils.isPresent("kotlinx.serialization.json.Json", classLoader);kotlinSerializationProtobufPresent = ClassUtils.isPresent("kotlinx.serialization.protobuf.ProtoBuf", classLoader);}

操作

想要自定义数据格式,只需要编写WebMvcConfigurer接口的实现类提供的configureMessageConverters底层,修改底层的MessageConverter即可。

示例:yaml类型

添加依赖: 

<!--		支持返回yaml包--><dependency><groupId>com.fasterxml.jackson.dataformat</groupId><artifactId>jackson-dataformat-yaml</artifactId></dependency>

配置application文件:

# 增加一种新的内容类型
spring.mvc.contentnegotiation.media-types.yaml = application/yaml

编写一个格式转换器:

public class MyYamlHttpMessageConverter extends AbstractHttpMessageConverter<Object> {private ObjectMapper objectMapper = null;//该属性就是来把对象转成yamlpublic MyYamlHttpMessageConverter(){YAMLFactory yamlFactory = new YAMLFactory().disable(YAMLGenerator.Feature.WRITE_DOC_START_MARKER/*取消yaml的文档分隔符*/);this.objectMapper = new ObjectMapper(yamlFactory);}//支持把什么类型写成yaml格式@Overrideprotected boolean supports(Class<?> clazz) {//可以在此判断return true;}@Override //@RequestBodyprotected Object readInternal(Class<?> clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {return null;}@Override //@ResponseBody 怎么把对象写成对应格式protected void writeInternal(Object methodReturnValue, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {
//        OutputStream body = outputMessage.getBody();
//        try {
//            this.objectMapper.writeValue(body,methodReturnValue);
//        }finally {
//            body.close();
//        }//try-with写法,自动关流try (OutputStream os = outputMessage.getBody()){this.objectMapper.writeValue(os,methodReturnValue);}}
}

把转换器和配置文件设置的类型关联起来:

转换器类继承的抽象类的构造方法可以传入mediatype,在传入的mediatype可以配置和配置文件设置的媒体类型一样的属性,这样两者就关联起来了。

在转换器的构造方法修改:

public MyYamlHttpMessageConverter(){//告诉springboot这个类型转换器支持哪种媒体类型super( new MediaType("application", "yaml", Charset.forName("UTF-8")));YAMLFactory yamlFactory = new YAMLFactory().disable(YAMLGenerator.Feature.WRITE_DOC_START_MARKER/*取消yaml的文档分隔符*/);this.objectMapper = new ObjectMapper(yamlFactory);}

 把转换器配置到springboot:

@Configuration
public class MyConfig implements WebMvcConfigurer {@Override   //配置一个能把对象转换为yaml的messageConverterpublic void configureMessageConverters(List<HttpMessageConverter<?>> converters) {converters.add(new MyYamlHttpMessageConverter());}
}

模板引擎

由于SpringBoot使用嵌入式Servlet容器,默认不能使用JSP。需要服务器页面渲染,优先考虑使用模板引擎。

模板引擎默认放到 /src/main/resources/templates

SpringBoot包含以下模板引擎的自动配置:

  • FreeMarker
  • Groovy
  • Thymeleaf(推荐)官网:Thymeleaf
  • Mustache 
Thymeleaf整合

导入启动器:

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

自动配置原理:

在ThymeleafAutoConfiguration下:

  • 将属性与配置文件下 spring.thymeleaf 绑定
  • 设置前缀 classpath:/templates/ 
  • 设置后缀 .html 

SpringBoot如果整合了Thymeleaf,默认是到 classpath:/templates/下找文件

编写服务:

//这时要返回页面,不能使用RestController
@Controller
public class WelcomeController {//请求路径:localhost:8080/welcome?name=qiu//就是name参数来填写到要返回的页面上@GetMapping("welcome")public String welcome(String name, Model model){//将msg:name放到model中,在模板引擎中就可以直接使用msg映射name的值model.addAttribute("msg",name);//返回页面的话,由于整合了Thymeleaf,将返回的字符串与设置的前后缀拼接在访问器中搜索并返回//    前缀(默认:classpath:/templates/) + welcome(返回字符串) + 后缀(默认:.html)return "welcome";}
}

在 \src\main\resources\templates 下创建文件 welcome.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
<!--                th:... 是 Thymeleaf --><h1>你好:<span th:text="${msg}"></span></h1>
</body>
</html>

启动服务访问:localhost:8080/welcome?name=qiu


使用

 


SpringBoot开发工具

导入SpringBoot提供的依赖

<!--		热启动功能--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId></dependency>

修改代码或页面后按 ctrl + f9, 项目就热启动了。

如果修改的是java代码,最好重启项目,不然可能有一些bug。


国际化

 在resources下创建文件:messages.properties,messages_zh_CN.properties,messages_en_US.properties。

idea会自动识别形成以下目录:

国际化要成功使用,项目编码要是UTF-8:File->Settings->搜索 file encodings

messages.properties:

login=Login
sign=Sign-Up

messages_zh_CN.properties:

login=登录
sign=注册

messages_en_US.properties:

login=Login
sign=Sign-Up-US

在模板中:

<!--    会根据当前状态使用中文或者英文--><button th:text="#{login}"></button><button th:text="#{sign}"></button>


错误处理

错误处理的自动化配置在ErrorMvcAutoConfiguration中,两大核心机制:

1.SpringBoot会自适应处理错误,响应页面或JSON数据

2.SpringMVC的错误处理机制仍然保留,MVC处理不了才会交给boot处理

MVC处理机制:

可以在当前controller上添加处理方法:

    @ResponseBody@ExceptionHandler(Exception.class)public String handlerException(Exception e){System.out.println("异常处理代码");return e.getMessage();}

也可以创建一个异常处理类:

@ControllerAdvice   //这个类集中处理所有controller发生的错误
public class GlobaExceptionHandler {@ResponseBody@ExceptionHandler(Exception.class)public String handlerException(Exception e){System.out.println("异常处理");return e.getMessage();}
}

如果MVC机制无法解决,就提交boot机制处理。

boot机制:

boot会默认将MVC无法处理的异常转发到项目路径为: /error 下 ,boot底层设计了一个BasicErrorController 处理请求,server.error.path不修改默认为 /error 。

@Controller
@RequestMapping({"${server.error.path:${error.path:/error}}"})
public class BasicErrorController extends AbstractErrorController {

在该controller下,会先判断请求的是页面和JSON数据

如果是JSON:

  • boot封装了JSON格式的错误信息:DefaultErrorAttributes
  • 当发生JSON请求错误时,将错误信息放到DefaultErrorAttributes中并返回

如果是页面:

  • 如果发生了500,404,503等错误
    • 如果有模板引擎,默认返回classpath:/templates/error/错误码.html
    • 如果没有,默认返回 静态资源下的错误码.html
  • 如果没有匹配到错误码,就模糊匹配(4xx.html或5xx.html)
    • 如果有模板引擎,默认返回classpath:/templates/error/5xx.html(还真是5xx.html或4xx.html)
    • 如果没有,默认返回 静态资源下的5xx.html
  • 否则返回templates下的error.html(templates/error.html)
  • 如果templates没有error.html,返回SpringBoot自己的默认error页面
最佳实战

嵌入式容器

SpringBoot关于嵌入式容器的自动化配置为:ServletWebServerFactoryAutoConfiguration

SpringBoot默认使用Tomcat为内置Servlet容器。

SpringBoot支持3种Servlet容器:

  • Tomcat(默认)
  • Jetty
  • Undertow

SpringBoot关于各个容器的配置类以 server.容器 为前缀:

server.tomcat.accept-count=100
server.jetty.accesslog.append=false

要替换SpringBoot的Servlet容器方法:

  • 在导入web启动器时手动切换:
		<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><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jetty</artifactId></dependency>

Web新特性

Problemdetails

错误信息返回新格式

在web自动化配置中将 ProblemDetailsExceptionHandler 放到ioc容器中:

    //web自动化配置类static class ProblemDetailsErrorHandlingConfiguration {ProblemDetailsErrorHandlingConfiguration() {}@Bean@ConditionalOnMissingBean({ResponseEntityExceptionHandler.class})@Order(0)ProblemDetailsExceptionHandler problemDetailsExceptionHandler() {return new ProblemDetailsExceptionHandler();}}//ProblemDetailsExceptionHandler源码@ControllerAdvice//异常处理类final class ProblemDetailsExceptionHandler extends ResponseEntityExceptionHandler {ProblemDetailsExceptionHandler() {}}

它来处理以下异常:

    @ExceptionHandler(HttpRequestMethodNotSupportedException.class, HttpMediaTypeNotSupportedException.class, HttpMediaTypeNotAcceptableException.class, MissingPathVariableException.class, MissingServletRequestParameterException.class, MissingServletRequestPartException.class, ServletRequestBindingException.class, MethodArgumentNotValidException.class, NoHandlerFoundException.class, AsyncRequestTimeoutException.class, ErrorResponseException.class, ConversionNotSupportedException.class, TypeMismatchException.class, HttpMessageNotReadableException.class, HttpMessageNotWritableException.class, BindException.class})

如果系统出现这些异常,SpringBoot以 RFC 7807 规范方式返回数据。

不过该功能默认关闭,需要在配置文件中手动开启:

spring.mvc.problemdetails.enabled=true

函数式Web(估计用不到)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/286487.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

西井科技与安通控股签署战略合作协议 共创大物流全新生态

2024年3月21日&#xff0c;西井科技与安通控股在“上海硅巷”新象限空间正式签署战略合作框架协议。双方基于此前在集装箱物流的成功实践与资源优势&#xff0c;积极拓展在AI数字化产品、新能源自动驾驶解决方案和多场景应用&#xff0c;以及绿色物流链等领域的深度探索、强强联…

视频汇聚平台EasyCVR启用图形验证码之后调用login接口的操作方法

视频综合管理平台EasyCVR视频监控系统支持多协议接入、兼容多类型设备&#xff0c;平台可以将区域内所有部署的监控设备进行统一接入与集中汇聚管理&#xff0c;实现对监控区域的实时高清视频监控、录像与存储、设备管理、云台控制、语音对讲、级联共享等&#xff0c;在监控中心…

Windows如何搭建 ElasticSearch 集群

单机 & 集群 单台 Elasticsearch 服务器提供服务&#xff0c;往往都有最大的负载能力&#xff0c;超过这个阈值&#xff0c;服务器 性能就会大大降低甚至不可用&#xff0c;所以生产环境中&#xff0c;一般都是运行在指定服务器集群中。 除了负载能力&#xff0c;单点服务器…

【Unity】从0到1的横版2d制作笔记-DAY3

确定碰撞体积 选择rigidbody2d&#xff0c;创建player重力 创建player碰撞体积 创建瓦片地图碰撞体积 使平台变成一个整体 ​​​​​ 设置Body Type为Static&#xff08;避免平台也因为重力影响下落&#xff09; 回到Player&#xff0c;在Rigidbody2D中设置为冻结旋转 Player设…

2016年认证杯SPSSPRO杯数学建模C题(第二阶段)如何有效的抑制校园霸凌事件的发生全过程文档及程序

2016年认证杯SPSSPRO杯数学建模 C题 如何有效的抑制校园霸凌事件的发生 原题再现&#xff1a; 近年来&#xff0c;我国发生的多起校园霸凌事件在媒体的报道下引发了许多国人的关注。霸凌事件对学生身体和精神上的影响是极为严重而长远的&#xff0c;因此对于这些情况我们应该…

SQL映射文件

一、SQL映射的xml文件 1.1 mapper元素 二、select 三、别名与Java映射 四、resultMap 啊

Java毕业设计 基于SSM网上二手书店系统

Java毕业设计 基于SSM网上二手书店系统 SSM jsp 网上二手书店系统 功能介绍 用户&#xff1a;首页 图片轮播 图书查询 图书分类显示 友情链接 登录 注册 图书信息 图片详情 评价信息 加入购物车 资讯信息 资讯详情 个人中心 个人信息 修改密码 意见信息 图书收藏 已经付款 邮…

Golang基础知识(笔记迁移)

golang 变量作用域 局部作用域&#xff1a;代码块、函数内的全局作用域&#xff1a;顶层作用域&#xff0c;代码块外的就是全局&#xff0c;如果变量名大写&#xff0c;则改变量整个程序都可以使用。 类型断言 golang的类型断言在变量后加上.(type)&#xff0c;如果类型断言…

怿星科技Neptune CHT-S测试系统,让智能座舱测试更加高效便捷

随着汽车“智能化”浪潮的推进&#xff0c;汽车的智能化水平正在持续刷新行业认知。在这股智能化潮流中&#xff0c;智能座舱作为客户体验最为直观的部分&#xff0c;其重要性不言而喻。倘若座舱设备出现死机、黑屏、卡顿等现象&#xff0c;都将对客户的使用体验产生非常大的影…

xmes前端问题,给form表单赋值后,再次从表单拿不到该值

xmes前端&#xff0c;给form表单赋值后&#xff0c;再次从表单拿不到该值&#xff0c;但页面可以展示 赋值 this.$[frm-main].$$([namefilm_num]).value filmNum ; 获取表单的值&#xff0c;这里拿不到之前赋的值 const reqData this.$[frm-main].serializeMyForm(); 原因&…

2.7、创建列表(List)

概述 列表是一种复杂的容器&#xff0c;当列表项达到一定数量&#xff0c;内容超过屏幕大小时&#xff0c;可以自动提供滚动功能。它适合用于呈现同类数据类型或数据类型集&#xff0c;例如图片和文本。在列表中显示数据集合是许多应用程序中的常见要求&#xff08;如通讯录、…

Copilot for Microsoft365使用体验

注&#xff1a;本文来自粉丝投稿。 上周进行了留言抽奖&#xff0c;粉丝获得了一周体验资格&#xff0c;并写下了使用体验&#xff0c;特此赠送1个月copilot使用资格。 留言赠送copilot for Microsoft365一周体验卡 每周一Copilot for Microsoft 365留言赠送 上周一通过陈老…

【CPP】智能指针

引言 智能指针是RAII思想的体现&#xff0c;有时候程序抛异常导致指针指向的内存资源未释放&#xff0c;造成内存泄漏&#xff0c;这时就需要用到智能指针&#xff0c;它可以出作用域自动调用析构函数释放内存资源 内存泄漏 什么是内存泄漏 什么是内存泄漏&#xff1a;内存泄…

基于GA优化的CNN-LSTM-Attention的时间序列回归预测matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 4.1卷积神经网络&#xff08;CNN&#xff09;在时间序列中的应用 4.2 长短时记忆网络&#xff08;LSTM&#xff09;处理序列依赖关系 4.3 注意力机制&#xff08;Attention&#xff09; 5…

9.串口通信

串口基本认识 串行接口简称串口&#xff0c;也称串行通信接口或串行通讯接口&#xff08;通常指COM接口&#xff09;&#xff0c;是采用串行通信方 式的扩展接口。串行接口&#xff08;Serial Interface&#xff09;是指数据一位一位地顺序传送。其特点是通信线路简 单&#x…

【网络爬虫】(2) requests模块,案例:网络图片爬取,附Python代码

1. 基本原理 1.1 requests 模块 requests 是 Python 中一个非常流行的 HTTP 客户端库&#xff0c;用于发送所有的 HTTP 请求类型。它基于 urllib&#xff0c;但比 urllib 更易用。 中文文档地址&#xff1a;Requests: 让 HTTP 服务人类 — Requests 2.18.1 文档 &#xff0…

cookie、localStorage、sessionStorage 详解

目录 cookie 是什么&#xff1f; cookie 不可以跨域请求 cookie 的属性 会话cookie & 永久性cookie cookie 禁用 cookie 的应用 sessionStorage 是什么&#xff1f; 失效时间 存储内容的类型 存储的大小 存储的位置 sessionStorage 的应用 localStorage 是什么…

GTC 2024 火线评论:DPU 重构文件存储访问

编者按&#xff1a;英伟达2024 GTC 大会上周在美国加州召开&#xff0c;星辰天合 CTO 王豪迈在大会现场参与了 GPU 与存储相关的最新技术讨论&#xff0c;继上一篇《GTC 2024 火线评论&#xff1a;GPU 的高效存储利用》之后&#xff0c;这是他发回的第二篇评论文章。 上一篇文章…

【ZZULI数据结构实验一】多项式的三则运算

【ZZULI数据结构实验一】多项式的四则运算 ♋ 结构设计♋ 方法声明♋ 方法实现&#x1f407; 定义一个多项式类型并初始化---CreateDataList&#x1f407; 增加节点---Getnewnode&#x1f407; 打印多项式类型的数据-- PrintPoly&#x1f407; 单链表的尾插--Listpush_back&…

Java多线程实战-从零手搓一个简易线程池(一)定义任务等待队列

&#x1f3f7;️个人主页&#xff1a;牵着猫散步的鼠鼠 &#x1f3f7;️系列专栏&#xff1a;Java全栈-专栏 &#x1f3f7;️本系列源码仓库&#xff1a;多线程并发编程学习的多个代码片段(github) &#x1f3f7;️个人学习笔记&#xff0c;若有缺误&#xff0c;欢迎评论区指正…