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

news2024/11/17 3:25:18

目录

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 {
    @Override
    public 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 {
    @Override
    public 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 {
                //规则1
                this.addResourceHandler(registry, this.mvcProperties.getWebjarsPathPattern(), "classpath:/META-INF/resources/webjars/");
                //规则2
                this.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 {

    @Override
    public 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;//该属性就是来把对象转成yaml
    public MyYamlHttpMessageConverter(){
        YAMLFactory yamlFactory = new YAMLFactory().disable(YAMLGenerator.Feature.WRITE_DOC_START_MARKER/*取消yaml的文档分隔符*/);
        this.objectMapper = new ObjectMapper(yamlFactory);
    }
    //支持把什么类型写成yaml格式
    @Override
    protected boolean supports(Class<?> clazz) {
        //可以在此判断
        return true;
    }

    @Override //@RequestBody
    protected 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的messageConverter
    public 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.coloradmin.cn/o/1542111.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

AJAX——JSON

目录 一、JSON概述 二、JSON对象语法 三、JSON序列化方法 四、JSON与XML比较 五、Java对象与Json对象的转换 六、Js解析服务器发送过来的JSON字符串 七、$.getJSON() 一、JSON概述 JSON简介:JSON的全称为JavaScript Object Nation(JavaScript 对象表示语法)&#xff0c;…

基于nodejs+vue的BBS论坛系统python-flask-django-php

为了更好地发挥本系统的技术优势&#xff0c;根据BBS论坛系统的需求&#xff0c;本文尝试以B/S架构设计模式中的express框架&#xff0c;nodejs语言为基础&#xff0c;通过必要的编码处理、BBS论坛系统整体框架、功能服务多样化和有效性的高级经验和技术实现方法&#xff0c;旨…

【Web】NKCTF 2024 个人wp(部分)

目录 my first cms 全世界最简单的CTF attack_tacooooo 属实太菜了&#xff0c;3/4 my first cms 一眼搜版本2.2.19 CVE -CVE-2024-27622 GitHub - capture0x/CMSMadeSimple 访问/admin/login.php 爆出弱口令&#xff0c;后台登录 admin Admin123 Extensions > User D…

<Linux> 模拟实现文件流 - 简易版

目录 1. FILE 结构设计 2、函数使用及分析 3、文件打开 fopen 4. 缓冲区刷新fflush 5. 数据写入fwrite 6. 文件关闭 fclose 7. 测试 8. 小结 1. FILE 结构设计 在设计 FILE 结构体前&#xff0c;首先要清楚 FILE 中有自己的缓冲区及冲刷方式 缓冲区的大小和刷新方式因…

【云开发笔记No.6】腾讯CODING平台

腾讯云很酷的一个应用&#xff0c;现在对于研发一体化&#xff0c;全流程管理&#xff0c;各种工具层出不穷。 云时代用云原生&#xff0c;再加上AI&#xff0c;编码方式真是发生了质的变化。 从前&#xff0c;一个人可以写一个很酷的软件&#xff0c;后来&#xff0c;这变得…

Day08 Java复习8 Spring MVC概念

Day09 Java复习9 Spring MVC spring mvc 的核心组件是什么&#xff1f; DispatcherServlet 1.JAVA 和Spring 、Spring Boot 、Spring MVC的关系 你要举办一个生日派对&#xff0c;而且你希望它既特别又好玩。Java就像是举办派对的地方&#xff0c;Spring、Spring Boot和Spri…

javaSSM公司招聘管理系统IDEA开发mysql数据库web结构计算机java编程maven项目

一、源码特点 IDEA开发SSM公司招聘管理系统是一套完善的完整企业内部系统&#xff0c;结合SSM框架和bootstrap完成本系统&#xff0c;对理解JSP java编程开发语言有帮助系统采用SSM框架&#xff08;MVC模式开发&#xff09;MAVEN方式加 载&#xff0c;系统具有完整的源代码和…

银行监管报送系统介绍(六):客户风险数据报送系统

【概念定义】 银监会决定从2013年起实行新版客户风险统计制度&#xff0c;对各政策性银行、国有商业银行、股份制商业银行进行客户信息汇总统计。 客户风险统计信息&#xff0c;是指新版客户风险统计报送信 息。客户风险统计报送信息包括但不限于对公及同业客户授信和 表内外业…

设计模式(十二):中介者模式(行为型模式)

Mediator&#xff0c;中介者模式&#xff1a;用一个中介对象封装一些列的对象交互。属于行为型模式 Facade&#xff0c;外观模式&#xff1a;为子系统中的一组接口提供一致的界面&#xff0c;facade 提供了一高层接口&#xff0c;这个接口使得子系统更容易使用。属于结构型模式…

Rust并发编程thread多线程和channel消息传递

安全高效的处理并发是 Rust 诞生的目的之一&#xff0c;主要解决的是服务器高负载承受能力。 并发&#xff08;concurrent&#xff09;的概念是指程序不同的部分独立执行&#xff0c;这与并行&#xff08;parallel&#xff09;的概念容易混淆&#xff0c;并行强调的是"同…

npm、nrm、nvm详解与应用

本文全面介绍了 npm、nrm 以及 nvm 这三个与 Node.js 开发密切相关的工具。首先&#xff0c;对 npm 进行了定义和功能解释&#xff0c;包括其在依赖管理、项目管理、脚本执行、版本控制和社区贡献等方面的作用。接着&#xff0c;详细介绍了 npm 的常用命令和设置下载源的操作&a…

python综合实战案例-数据分析

Python是进行数据分析的好工具&#xff0c;今天就是借助一个案例给大家进行数据分析讲解。 本例设计一个log.txt⽂件&#xff0c;该文件记录了某个项⽬中某个 api 的调⽤情况&#xff0c;采样时间为每分钟⼀次&#xff0c;包括调⽤次数、响应时间等信息&#xff0c;⼤约18万条数…

java数据结构与算法刷题-----LeetCode451. 根据字符出现频率排序

java数据结构与算法刷题目录&#xff08;剑指Offer、LeetCode、ACM&#xff09;-----主目录-----持续更新(进不去说明我没写完)&#xff1a;https://blog.csdn.net/grd_java/article/details/123063846 文章目录 1. hash统计出现次数后排序2. 桶排序 1. hash统计出现次数后排序…

WebClient 同步、异步调用实现对比

文章目录 一、概述二、pom依赖三、代码结构四、源码传送1、异步代码2、同步代码3、完整代码 一、概述 WebClient是Spring WebFlux模块提供的一个非阻塞的基于响应式编程的进行Http请求的客户端工具&#xff0c;从Spring5.0开始WebClient作为RestTemplete的替代品&#xff0c;有…

初探Flink集群【持续更新】

周末下雨&#xff0c;倒杯茶&#xff0c;在家练习Flink相关。 开发工具&#xff1a;IntelliJ Idea 第一步、创建项目 打开Idea&#xff0c;新建Maven项目&#xff0c;包和项目命名 在pom.xml 文件中添加依赖 <properties><flink.version>1.13.0</flink.vers…

python(django(自动化))之流程接口展示功能前端开发

1、创建模板代码如下&#xff1a; <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><title>测试平台</title> </head> <body role"document"> <nav class "navbar n…

轻量级 C++ UI 库:快速、可移植、自包含 | 开源日报 No.168

ocornut/imgui Stars: 53.4k License: MIT imgui 是 C 的无臃肿图形用户界面&#xff0c;具有最小的依赖关系。 该项目的主要功能、关键特性、核心优势包括&#xff1a; 为 C 提供了一个轻量级的图形用户界面库输出优化的顶点缓冲区&#xff0c;可在 3D 渲染应用程序中随时呈…

2024/03/24----Pycharm社区版本下载以及创建一个新项目

1.本科安装过这个软件&#xff0c;因为系统重置了&#xff0c;所以重头再来一遍。 2.链接 社区版本Pycharm 3.我下载了2023.1.15的版本&#xff0c;越前面一些的版本可能会比较稳定 4.安装步骤 &#xff08;1&#xff09;先把文件安装目录改成其他盘(文件名最好不要有数字和符号…

2025汤家凤考研数学视频,基础网课百度网盘课程+PDF讲义资料

2025汤家凤大神及数学全程 docs.qq.com/doc/DTmtOa0Fzc0V3WElI 复制粘贴到浏览器&#xff0c;可以见所有的Ke 第一轮 夯实基础 1.阅读大纲考查要求&#xff0c;明确每章的学习目标&#xff1b; 2.按节学习数学理论基础知识&#xff0c;吃透书中例题&#xff1b; 3.学习每章…

Django 三板斧、静态文件、request方法

【一】三板斧 【1】HttpResponse &#xff08;1&#xff09;介绍 HttpResponse是Django中的一个类&#xff0c;用于构建HTTP响应对象。它允许创建并返回包含特定内容的HTTP响应。 &#xff08;2&#xff09;使用 导入HttpResponse类 from django.http import HttpResponse创…