文章目录
- SpringBoot概述
- 自动装配(部分)
- 概述
- 原理
- 简述
- 相关解释
- 源码位置
- @EnableAutoConfiguration
- AutoConfigurationImportSelector
- 配置文件
- yaml语法
- 单双引号
- 列表
- 多行字符串
- 配置文件的位置和加载顺序
- 配置文件取值
- 运行jar包
- Springboot整合springmvc
- 自动管理
- Springboot扩展springmvc
- 注册视图控制器(请求转发)
- 消息转换器
- 格式化器
- 注册拦截器
- WebMvcConfigurer
- SpringBoot数据层开发
- 数据源自动管理
- 配置 Druid 数据源
- Spring Boot 整合 JdbcTemplate
- Spring Boot 整合 MyBatis
- 配置嵌入式服务器
- 如何修改Servlet容器的相关配置
- 注册Servlet三大组件Servlet、Filter、Listener
- Servlet
- Listener
- Filter
- 注册
- 自定义DispatcherServlet
- 使用外置的Servlet容器
- Web开发
- 静态资源的处理
- 静态资源的映射路径
- 自定义静态资源路径和映射
- 模板引擎(Thymeleaf)
- 概述
- 引入thymeleaf
- 源码
- 使用
- 语法
- 1. 变量表达式
- 2. 选择(星号)表达式
- 3. 文字国际化表达式
- 4. URL 表达式
- 5.其他语法
- 6.文件传输&表单提交
SpringBoot概述
Spring Boot 是一个用于简化 Spring 应用开发的框架,它具有以下主要特性:
- 自动配置:Spring Boot 能依据项目的依赖自动配置 Spring 应用。
- 起步依赖:Spring Boot 提供了一系列的起步依赖(Starter Dependencies),它们是一些预定义的依赖集合,能帮助你快速添加项目所需的依赖。例如,
spring-boot-starter-web
包含了 Spring MVC、Tomcat 等 Web 开发所需的依赖,你只需在pom.xml
(Maven 项目)中添加以下依赖,就可以快速搭建 Web 应用 - 嵌入式服务器:将应用打包成一个可执行的 JAR 文件,其中包含嵌入式服务器,直接运行 JAR 文件即可启动应用,无需单独部署到外部服务器。
- 无代码生成和 XML 配置:Spring Boot 提倡零配置或最少配置,尽量避免使用代码生成和 XML 配置。通过注解和自动配置,你可以用简洁的代码构建复杂的 Spring 应用。
- 微服务支持
自动装配(部分)
概述
Spring Boot 自动装配是 Spring Boot 的核心特性之一,它能够根据项目中引入的依赖,自动为应用程序进行合理的配置,减少开发者手动配置的工作量。下面从自动装配的原理、实现步骤、核心注解以及示例等方面详细介绍。
原理
简述
Spring Boot 自动装配的核心原理基于 Java 的 SPI(Service Provider Interface)机制和 Spring 的条件注解。具体来说:
- SPI 机制:Spring Boot 利用
META - INF/spring.factories
文件,该文件定义了一系列的自动配置类。当 Spring Boot 应用启动时,会读取这个文件,获取所有可能的自动配置类的全限定名。 - 条件注解:Spring Boot 提供了一系列的条件注解,如
@ConditionalOnClass
、@ConditionalOnMissingBean
等。这些注解可以根据类路径上是否存在某个类、容器中是否已经存在某个 Bean 等条件来决定是否加载某个自动配置类。
- **启动类@SpringBootApplication注解:**SpringBoot的应用入口是一个带有@SpringBootApplication注解的主类。而@SpringBootApplication是一个组合注解。它包含了@EnableAutoConfiguration,@ComponentScan和@Configuration(间接来自@SpringBootConfiguration)等。
- **@EnableAutoConfiguration注解:**通过@Import(AutoConfigurationImportSelector.class)导入了AutoConfigurationImportSelector这个类。这个类的作用是决定哪些自动配置类应该被注入到当前Spring应用中。
- **AutoConfigurationImportSelector类:**此类有很多方法,通过这些方法来筛选需要注入的自动配置类。它实现了ImportSelector接口,在其中的selectImports方法中,它会调用AutoConfigurationImportSelector类中的其他方法来读取spring.factories文件中的全限定名(包含类所在的包名以及类名本身)。SpringBoot和其他依赖库都会在spring.factories中定义一系列的自动配置类。然后根据应用的依赖情况被自动加载。
- **spring.factories文件:**在
spring-boot-autoconfigure
模块中,META-INF/spring.factories
文件定义了大量的自动配置类。例如,当项目中引入了 Spring Web 的依赖时,spring.factories
中关于 Web 相关的自动配置类(如WebMvcAutoConfiguration
)就会被读取并注册到 Spring 容器中。 - **条件注解:**自动配置类中使用了各种条件注解(如
@ConditionalOnClass
、@ConditionalOnProperty
、@ConditionalOnMissingBean
等)来控制配置的生效条件。@ConditionalOnClass
表示当类路径下存在指定的类时才生效;@ConditionalOnProperty
表示当指定的属性存在且满足一定条件时生效;@ConditionalOnMissingBean
表示当 Spring 容器中不存在指定类型的 Bean 时生效。 - 配置属性绑定:自动配置类通常会与配置属性进行绑定,使用
@ConfigurationProperties
注解将配置文件(如application.properties
或application.yml
)中的属性值绑定到对应的 Java 对象上。这样,开发者可以通过配置文件来定制自动配置的行为。 - Bean 的注册:自动配置类本质上是 Spring 的配置类,通过
@Bean
等 注解在 Spring 容器中注册各种 Bean。
相关解释
源码位置
这个包在starter包下。
@EnableAutoConfiguration
@EnableAutoConfiguration
:这个注解包含了@Import(AutoConfigurationImpotSelector.class),而它是自动装配的核心。
AutoConfigurationImportSelector
AutoConfigurationImportSelector
就是实现自动配置的关键组件,它能够根据项目中引入的依赖,从众多的自动配置类中筛选出适合当前应用的配置类,并将它们注册到 Spring 应用上下文中。
AutoConfigurationImportSelector工作原理:
- 查找自动配置类:
AutoConfigurationImportSelector
会从类路径下的META - INF/spring.factories
文件中查找所有的自动配置类。这个文件中定义了一系列的键值对,其中org.springframework.boot.autoconfigure.EnableAutoConfiguration
作为键,对应的值就是所有可能的自动配置类的全限定名。 - 排除不需要的配置类:根据
@EnableAutoConfiguration
注解中的exclude
和excludeName
属性,排除一些不需要的自动配置类。 - 过滤自动配置类:使用
AutoConfigurationImportFilter
对自动配置类进行进一步的过滤,根据类路径上的类、配置属性等条件判断哪些自动配置类是可用的。 - 导入筛选后的配置类:将筛选后的自动配置类注册到 Spring 应用上下文中,从而实现自动配置。
AutoConfigurationImportSelector执行流程:
当 Spring 框架处理 @EnableAutoConfiguration
注解时,会触发 AutoConfigurationImportSelector
的执行。在整个过程中,selectImports
方法是入口,它会调用其他方法完成具体的筛选和导入逻辑。
isEnabled(annotationMetadata)
:该方法是selectImports
中首先调用的方法,用于检查是否启用了自动配置。如果没有启用,直接返回空数组NO_IMPORTS
,表示不进行自动配置类的导入。AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader)
:加载自动配置元数据,这些元数据是用于描述自动配置类的相关属性和条件信息的数据集合,这些信息存储在META - INF/spring - autoconfigure - metadata.properties
文件中。这些信息可以帮助 Spring Boot 在启动时快速判断某个自动配置类是否应该被应用到当前的应用环境中,避免不必要的类加载和配置尝试。后续的过滤操作会用到这些信息。getAttributes(annotationMetadata)
:获取@EnableAutoConfiguration
注解的属性,例如exclude
和excludeName
,这些属性用于指定需要排除的自动配置类。getCandidateConfigurations(annotationMetadata, attributes)
:从类路径下的AutoConfiguration.imports(用来代替spring.factories)和META - INF/spring.factories
文件中查找所有可能的自动配置类,将它们作为候选配置类。(Candidate:候选人)removeDuplicates(configurations)
:去除候选配置类中的重复项。getExclusions(annotationMetadata, attributes)
:根据@EnableAutoConfiguration
注解的属性,获取需要排除的自动配置类。checkExcludedClasses(configurations, exclusions)
:检查开发者指定要排除的自动配置类是否存在于候选配置类列表中。若存在,就会抛出异常,以此确保开发者不会意外地排除了无法加载的配置类。configurations.removeAll(exclusions)
:从候选配置类中移除需要排除的配置类。- 其他过滤方法。
StringUtils.toStringArray(configurations)
:将筛选后的自动配置类列表转换为字符串数组并返回。
总之,selectImports()方法会被Spring自动地调用,该方法的作用是得到返回的全类名字符串数组,把这些全类名的bean对象注册到ioc容器里面。
配置文件
Spring Boot 常见的配置文件类型有 .properties
和 .yml
(.yaml
)两种。
yaml语法
单双引号
“”:双引号;不会转义字符串里面的特殊字符;特殊字符会作为本身想表示的意思
name: “zhangsan \n lisi”:输出;zhangsan 换行 lisi
‘’:单引号;会转义特殊字符,特殊字符最终只是一个普通的字符串数据
name: ‘zhangsan \n lisi’:输出;zhangsan \n lisi
列表
列表使用短横线 -
来表示,每个元素占一行。例如:
fruits:- apple- banana- cherry
也可以是包含对象的列表:
students:- name: Aliceage: 20grade: A- name: Bobage: 21grade: B
多行字符串
有两种表示多行字符串的方式:
- 折叠式(>`):文本会被折叠成一行,连续的换行符会被替换为一个空格,例如:
description: >This is a multi-line string.It will be folded into a single line.
最终的字符串为 This is a multi-line string. It will be folded into a single line.
- 字面量式(|`):保留换行符,文本按照原样呈现,例如:
longText: |This is a multi-line string.Each line will be preserved as it is.
配置文件的位置和加载顺序
同一目录下, .properties
和 .yml
都存在且有冲突(一样的配置),.properties
优先。
- springboot_01/config/application.yml
- springboot_01/application.yml
- resources/config/application.yml
- resources/config/application.yml
配置文件取值
@ConfigurationProperties
- 作用:该注解用于将配置文件中的属性批量绑定到一个 Java 类上,支持类型安全的配置绑定,尤其适合处理复杂的配置结构,如嵌套对象、列表等。
@Value
- 作用:用于从配置文件中获取单个属性值,并将其注入到类的字段、方法参数或构造函数参数中。支持使用 SpEL(Spring 表达式语言)进行表达式计算。
@PropertySource
- 作用:用于指定额外的配置文件位置,主要用于加载
.properties
格式的配置文件。
- 作用:用于指定额外的配置文件位置,主要用于加载
@ImportResource
- 作用:用于导入传统的 Spring XML 配置文件,在一些旧项目迁移或者需要使用 XML 配置的场景中非常有用。虽然 Spring Boot 更推荐使用 Java 配置,但在某些情况下,XML 配置仍然有其优势。
@Bean
@Bean
注解通常与@Configuration
注解配合使用,@Configuration
注解用于标记一个类为配置类,而@Bean
注解则用于该配置类中的方法,方法的返回值会被注册为 Spring 容器中的一个 Bean。
@Data方便测试时输出相应的toString()。
-------------@ConfigurationProperties------------
@ConfigurationProperties(prefix = "hello")
@Configuration
@Data
public class TypeConfig {private List<String> fruits;private List<Student> students;
}
hello:fruits:- apple- banana- orangestudents:- name: "luxiya"age: 18address: "China"- name: "lifu"age: 17address: "English"
-----------@Value-------------------
@Configuration
@Data
public class ValueConfig {@Value("${person.name}")private String name;@Value("${person.age}")private Integer age;
}
person:name: "luxiya"age: 18address: "China"
--------------@ImportResource-----------
@ImportResource("classpath:beans.xml")
@Configuration
public class OldConfig {}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"><bean id="messageService" class="com.luxiya.springboot_01.model.OldImport"><property name="message" value="Hello from XML-configured Bean!"/></bean></beans>
-----------@PropertySource--------------@PropertySource("classpath:custom.proprities")
@Configuration
@Data
public class CustomConfig {@Value("${myapp.name}")private String name;@Value("${myapp.version}")private String version;
}
myapp.name=My Custom Application
myapp.version=1.0.0
---------------@Bean----------
@Configuration
public class HuiYaConfig {@Beanpublic HuiYa huiYa() {HuiYa huiYa = new HuiYa();huiYa.setName("huiya");huiYa.setAge(100);huiYa.setAddress("空中花园");return huiYa;}
}
运行jar包
基础
java -jar jar包名称
所有的配置都可以在命令行上进行指定。多个配置用空格分开; --配置项=值
java -jar spring-boot-02-config-02-0.0.1-SNAPSHOT.jar --server.port=8087 --server.context-path=/abcjava -jar spring-boot-02-config-02-0.0.1-SNAPSHOT.jar --spring.config.location=C:/appliction.properties
项目之外的配置文件运行
//spring.config.location......应该在“--”后面,只是换行了
java -jar springboot_01-0.0.1-SNAPSHOT.jar --spring.config.location=file:D:\AllCode\IdeaProjects\testArea\application-out.yml
Springboot整合springmvc
在 Spring Boot 中,Spring MVC 大部分组件都能实现自动配置管理。
中央转发器(DispatcherServlet)
控制器
视图解析器
静态资源访问,静态资源管理
消息转换器
格式化
自动管理
- 中央转发器:
DispatcherServlet
是 Spring MVC 的核心前端控制器,负责接收所有 HTTP 请求并将其分发给相应的处理器进行处理。在 Spring Boot 里,DispatcherServlet
会被自动配置。当你添加了spring-boot-starter-web
依赖后,Spring Boot 会自动创建一个DispatcherServlet
实例,并将其映射到/
路径,这意味着它会处理所有的 HTTP 请求。 - **控制器:**Spring Boot 能够自动扫描带有
@Controller
或@RestController
注解的类,并将其中使用@RequestMapping
等注解标注的方法注册为请求处理方法。 - **视图解析器:**Spring Boot 会根据你添加的依赖自动配置视图解析器。例如,如果你添加了 Thymeleaf 依赖,Spring Boot 会自动配置
ThymeleafViewResolver
;如果你使用 JSP,Spring Boot 也会相应地配置 JSP 视图解析器。 - **静态资源访问,管理:**web开发下有介绍。
- **格式化:**Spring Boot 支持自动格式化日期、数字等类型的数据。例如,你可以在实体类的属性上使用
@DateTimeFormat
- **消息转换器:**Spring Boot 会自动配置多种消息转换器,用于处理 HTTP 请求和响应的消息转换。常见的消息转换器包括
MappingJackson2HttpMessageConverter
(用于处理 JSON 数据)、StringHttpMessageConverter
(用于处理字符串数据)等。
Springboot扩展springmvc
在 Spring Boot 里,可通过实现 WebMvcConfigurer
接口重写相应方法,实现注册视图控制器、格式化器、消息转换器扩展 FastJSON 以及注册拦截器等 Spring MVC 扩展功能。
注册视图控制器(请求转发)
registry.addInterceptor
方法用于把一个拦截器添加到拦截器注册表中。
addPathPatterns
方法用于指定拦截器要拦截的请求路径。"/**"
是一个路径通配符,表示拦截所有的请求路径。也就是说,MyInterceptor
会对应用中所有的请求进行拦截处理。
@Override
public void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**");
}
消息转换器
注解:@RequestBody
是 Spring 框架中的一个注解,主要用于处理 HTTP 请求中的消息体(body),并将其绑定到方法的参数上。当客户端向服务器发送的数据以 JSON、XML 等格式包含在 HTTP 请求体中时,服务器端需要解析这些数据并将其转换为 Java 对象进行处理,此时就可以使用 @RequestBody
注解。
Spring MVC 框架在处理请求时,会根据请求的 Content-Type
头信息选择合适的 HttpMessageConverter
来将请求体中的数据转换为 Java 对象。例如,如果请求的 Content-Type
是 application/json
,Spring 会使用 MappingJackson2HttpMessageConverter
(默认情况下)将 JSON 数据转换为对应的 Java 对象。@RequestBody
注解的作用就是告诉 Spring MVC 从请求体中读取数据,并使用合适的消息转换器进行转换。
**方法:**其参数 converters
是一个存储 HttpMessageConverter
类型对象的列表,这个列表包含了 Spring MVC 中所有已注册的消息转换器。此方法将 fastJsonConverter
添加到 converters
列表的第一个位置。在 Spring MVC 处理请求和响应时,会按照消息转换器在列表中的顺序依次尝试使用它们。将 FastJsonHttpMessageConverter
放在首位,意味着在处理 JSON 数据时会优先使用它。
@RequestMapping("/converters")
@ResponseBody
public String converters(@RequestBody BlogComments blogComments)
{System.out.println(blogComments);return blogComments.toString();
}
-----------MyMVCCofnig------------@Overridepublic void configureMessageConverters(List<HttpMessageConverter<?>> converters) {FastJsonHttpMessageConverter fastJsonConverter = new FastJsonHttpMessageConverter();converters.add(0, fastJsonConverter);}
格式化器
@Overridepublic void addFormatters(FormatterRegistry registry) {registry.addFormatter(new LocalDateFormatter());}
----------自定义 LocalDate 格式化器----------
public class LocalDateFormatter implements Formatter<LocalDate> {// 定义日期格式private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");// 将字符串解析为 LocalDate 类型@Overridepublic LocalDate parse(String text, Locale locale) throws ParseException {return LocalDate.parse(text, FORMATTER);}// 将 LocalDate 类型格式化为字符串@Overridepublic String print(LocalDate object, Locale locale) {return FORMATTER.format(object);}
}
注册拦截器
//注册拦截器@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**");}
---------自定义拦截器--------------
@Configuration
public class MyInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("前置拦截");return true;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println("后置拦截");}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.out.println("最终拦截");}
}
WebMvcConfigurer
WebMvcConfigurer
接口重写相应方法,实现springMVC扩展。
@Configuration
public class MyMVCCofnig implements WebMvcConfigurer {//注册拦截器@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**");}/*** 配置消息转换器*/@Overridepublic void configureMessageConverters(List<HttpMessageConverter<?>> converters) {FastJsonHttpMessageConverter fastJsonConverter = new FastJsonHttpMessageConverter();converters.add(0, fastJsonConverter);}/*** 在容器中注册视图控制器(请求转发)* 自定义url,“hhh”,“nihao”,访问其会转发至success.html和world.html*/@Overridepublic void addViewControllers(ViewControllerRegistry registry) {registry.addViewController("/hhh").setViewName("success");registry.addViewController("/nihao").setViewName("world");}//void addFormatter(Formatter<?> formatter);@Overridepublic void addFormatters(FormatterRegistry registry) {registry.addFormatter(new DateFormatter());System.out.println("addFormatters");}
}
SpringBoot数据层开发
数据源自动管理
在 Spring Boot 中进行数据层开发,首先要配置数据源。这里我们借助 Spring Boot 的自动配置功能,通过引入相关依赖和配置文件来达成。
引入依赖:在pom.xml
文件里添加如下依赖:
spring-boot-starter-jdbc
:为 Spring Boot 提供 JDBC 支持。commons-dbcp2
:提供数据库连接池。mysql-connector-java
:MySQL 数据库的驱动。
配置数据源:采用application.yml
文件来配置数据源:
spring:datasource:username: rootpassword: rooturl: jdbc:mysql://localhost:3306/boot_demodriver-class-name: com.mysql.cj.jdbc.Driver
配置 Druid 数据源
引入依赖:在pom.xml
文件中添加 Druid 相关依赖:
- druid
- log4j:在 Druid 连接池的配置中引入
log4j
依赖主要是为了支持filters
配置中的log4j
过滤器。这个过滤器可以将 Druid 连接池的相关日志信息(如 SQL 执行日志、连接池状态日志等)输出到日志文件中,方便开发者进行调试和监控。
spring:datasource:username: rootpassword: rooturl: jdbc:mysql://localhost:3306/boot_demodriver-class-name: com.mysql.cj.jdbc.Drivertype: com.alibaba.druid.pool.DruidDataSource
driver-class-name
:指定数据库驱动类的全限定名,com.mysql.cj.jdbc.Driver
是 MySQL 8.x 及以上版本推荐使用的 JDBC 驱动类。
Spring Boot 整合 JdbcTemplate
在添加了 spring-boot-starter-jdbc
依赖之后,Spring Boot 会自动配置 JdbcTemplate
这个 Bean。
所以直接用。很少用JDBC了,了解即可。
@Controller
@RequestMapping("/jdbc")
public class JDBCController {@Autowiredprivate JdbcTemplate jdbcTemplate;@Autowiredprivate BlogCommentsMapper blogCommentsMapper;@RequestMapping("/test")@ResponseBodypublic String test(){List<Map<String, Object>> list = jdbcTemplate.queryForList("select * from accounts");return list.toString();}
}
Spring Boot 整合 MyBatis
引入依赖:在pom.xml
文件中添加 MyBatis 相关依赖:
- mybatis-spring-boot-starter
步骤:
-
创建JavaBean,建表。
-
@MapperScan("com.luxiya.springboot_02.mapper")
- 这是 MyBatis 提供的注解,用于指定要扫描的 Mapper 接口所在的包路径。将它们注册为 MyBatis 的 Mapper 接口,生成代理实现类。这样,在项目中就可以直接使用这些 Mapper 接口进行数据库操作。
- 方法一:当项目中有多个 Mapper 接口时,使用
@MapperScan
注解可以简化配置。方法二:在每个 Mapper 接口上都添加@Mapper
注解。
-
写mapper接口和相应的xml文件。运行即可。
配置:
ConfigurationCustomizer
:这是 MyBatis 提供的一个函数式接口,用于自定义 MyBatis 的配置。通过实现这个接口,可以在 MyBatis 配置加载完成后对其进行一些定制化的设置。(不会自动装配。可以有多个但只有一个生效,可以借助@ConditionalOnProperty和yml实现选择性生效。)
@Configuration
@MapperScan("com.luxiya.springboot_02.mapper")
public class MybatisConfig {@Beanpublic ConfigurationCustomizer configurationCustomizer() {return configuration -> {// 开启驼峰命名自动映射configuration.setMapUnderscoreToCamelCase(true);// 开启使用生成的主键//configuration.setUseGeneratedKeys(true);};}
}
配置嵌入式服务器
如何修改Servlet容器的相关配置
-
配置文件
-
通用配置
- 端口设置:
server.port
用于设置应用的监听端口,如server.port=8081
将端口设置为 8081。 - 上下文路径:
server.servlet.context-path
可自定义应用的根上下文路径,默认是空字符串(“/”)。例如server.servlet.context-path=/myapp
,后续所有路由都基于此路径,如访问主页变为http://localhost:8080/myapp
。 - 编码设置:
server.tomcat.uri-encoding
可设置 Tomcat 的 URI 编码,如server.tomcat.uri-encoding=UTF-8
。
- 端口设置:
-
Tomcat 特定设置
Spring Boot 默认使用 Tomcat 作为 Servlet 容器,可通过server.tomcat.xxx的形式设置 Tomcat 相关参数,例如:
server.tomcat.max-threads
:设置最大线程数。server.tomcat.min-spare-threads
:设置最小空闲线程数。server.tomcat.max-http-post-size
:设置最大 HTTP POST 请求大小。
-
注册Servlet三大组件Servlet、Filter、Listener
Servlet
@WebServlet("/myservletone")
public class MyServletOne extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {resp.getWriter().write("hello servlet one");}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {this.doGet(req, resp);}
}@WebServlet("/myservlettwo")
public class MyServletTwo extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {resp.getWriter().write("MyServletTwo");}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {this.doGet(req, resp);}
}
Listener
@WebListener此注解用于把一个类标记为 Servlet 监听器。监听器能监听 Web 应用中的各类事件,像 Servlet 上下文(ServletContext
)、会话(HttpSession
)以及请求(ServletRequest
)的生命周期事件。
- 监听 ServletContext 的生命周期事件:ServletContextListener
- 监听 HttpSession 的生命周期事件:HttpSessionListener
- 监听 ServletRequest 的生命周期事件:ServletRequestListener
@WebListener
public class MyListener implements ServletContextListener {@Overridepublic void contextInitialized(ServletContextEvent sce) {System.out.println("MyListener-------- contextInitialized");}@Overridepublic void contextDestroyed(ServletContextEvent sce) {System.out.println("MyListener-------- contextDestroyed");}
}
Filter
@WebFilter这个注解用于把一个类标记为 Servlet 过滤器。过滤器可在请求到达 Servlet 之前或者响应返回客户端之前对请求和响应进行拦截与处理。@WebFilter
注解里的参数可用于指定过滤器的名称、拦截的 URL 模式等。
@WebFilter("/*")
public class MyFliter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {System.out.println("MyFliter----- init");}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {System.out.println("MyFliter----- 前doFilter");filterChain.doFilter(servletRequest,servletResponse);System.out.println("MyFliter----- 后doFilter");}@Overridepublic void destroy() {System.out.println("MyFliter----- destroy");}
}
注册
这是一个 Spring Boot 的配置类,主要用于注册 Servlet、Filter、Listener 和DispatcherServlet
等组件。
-
注册自定义 Servlet
ServletRegistrationBean
是 Spring Boot 提供的用于注册 Servlet 的工具类,通过构造函数传入自定义 Servlet 的实例,并使用addUrlMappings
方法指定 Servlet 的映射路径。 -
注册自定义 Filter
FilterRegistrationBean
用于注册 Filter,通过构造函数传入自定义 Filter 的实例,并使用addUrlPatterns
方法指定 Filter 要拦截的 URL 模式,这里指定拦截/myservletone
路径。 -
注册自定义 Listener
ServletListenerRegistrationBean
用于注册 Servlet 监听器,通过构造函数传入自定义监听器的实例。
@Configuration
public class ServletInitializer {@Beanpublic ServletRegistrationBean<MyServletOne> myServletOne(){ServletRegistrationBean<MyServletOne> bean = new ServletRegistrationBean<>(new MyServletOne());bean.addUrlMappings("/myservletone");return bean;}@Beanpublic ServletRegistrationBean<MyServletTwo> myServletTwo(){ServletRegistrationBean<MyServletTwo> bean = new ServletRegistrationBean<>(new MyServletTwo());bean.addUrlMappings("/myservlettwo");return bean;}@Beanpublic FilterRegistrationBean<MyFliter> myFliter(){FilterRegistrationBean<MyFliter> bean = new FilterRegistrationBean<>(new MyFliter());bean.addUrlPatterns("/myservletone");return bean;}@Beanpublic ServletListenerRegistrationBean<MyListener> myListener(){ServletListenerRegistrationBean<MyListener> bean = new ServletListenerRegistrationBean<>(new MyListener());return bean;}
}
自定义DispatcherServlet
@ConditionalOnBean
注解表示只有当 Spring 容器中存在指定名称和类型的 Bean 时,才会创建当前的 Bean。这里表示只有当容器中存在名为dispatcherServlet_mine_one
的DispatcherServlet
类型的 Bean 时,才会注册dispatcherServlet_registration_mine_one
这个ServletRegistrationBean
。customDispatcherServlet
方法创建并返回一个自定义的DispatcherServlet
实例,名称为dispatcherServlet_mine_one
。dispatcherServlet
方法接收一个DispatcherServlet
实例作为参数,将其注册到 Servlet 容器中,映射路径为/
,设置启动加载顺序为 1(数值越小,加载的优先级越高),并指定名称为dispatcherServlet_mine_one
。
--------------自定义DispatcherServlet类
public class CustomDispatcherServlet extends DispatcherServlet {private static final Logger logger = LoggerFactory.getLogger(CustomDispatcherServlet.class);//请求到达 DispatcherServlet时,执行doService方法@Overrideprotected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {logger.info("Custom DispatcherServlet is handling the request.");super.doService(request, response);}
}
--------------注册------------@Bean(name = "dispatcherServlet_registration_mine_one")//name:指定了要检查的 Bean 的名称//value:指定了要检查的 Bean 的类型@ConditionalOnBean(name = "dispatcherServlet_mine_one", value = DispatcherServlet.class)public ServletRegistrationBean<DispatcherServlet> dispatcherServlet(DispatcherServlet dispatcherServlet){ServletRegistrationBean<DispatcherServlet> bean = new ServletRegistrationBean<>(dispatcherServlet);bean.addUrlMappings("/");bean.setLoadOnStartup(1);bean.setName("dispatcherServlet_mine_one");return bean;}// 首先注册一个符合条件的 DispatcherServlet Bean@Bean(name = "dispatcherServlet_mine_one")public DispatcherServlet customDispatcherServlet() {return new CustomDispatcherServlet();}
使用外置的Servlet容器
不常用。
springboot 使用外置servlet 容器_springboot配置外部得servlet-CSDN博客
Web开发
静态资源的处理
静态资源的映射路径
Spring Boot 会自动从以下默认的类路径(classpath
)目录里查找静态资源:(按照优先级顺序排列)
classpath:/META-INF/resources/
classpath:/resources/
classpath:/static/
classpath:/public/
例如,你可以在 src/main/resources/static
目录下创建一个名为 index.html
的文件,当你访问应用的根路径(如 http://localhost:8080
)时,Spring Boot 会自动将该文件返回给客户端。(只有index可以,index是默认的。)
Spring Boot 默认会将静态资源映射到 /
路径下。这意味着,如果你在 classpath:/static/images
目录下有一张名为 logo.png
的图片,你可以通过 http://localhost:8080/images/logo.png
来访问它。
自定义静态资源路径和映射
可以通过配置类或者配置文件来自定义。
--------配置文件yml---------
spring:resources:static-locations:- classpath:/my-resources/- classpath:/custom-static/mvc:static-path-pattern: /static-resources/**
-------------配置类--------
@Configuration
public class WebConfig implements WebMvcConfigurer {@Overridepublic void addResourceHandlers(ResourceHandlerRegistry registry) {registry.addResourceHandler("/custom-resources/**").addResourceLocations("classpath:/custom-static/");}
}
模板引擎(Thymeleaf)
概述
引入thymeleaf
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId><version>2.7.6</version>
</dependency>
源码
以下是thymeleaf配置默认源码。
默认路径是classpath:/templates/
支持类型为.html
@ConfigurationProperties(prefix = "spring.thymeleaf"
)
public class ThymeleafProperties {private static final Charset DEFAULT_ENCODING;public static final String DEFAULT_PREFIX = "classpath:/templates/";public static final String DEFAULT_SUFFIX = ".html";private boolean checkTemplate = true;private boolean checkTemplateLocation = true;private String prefix = "classpath:/templates/";private String suffix = ".html";private String mode = "HTML";private Charset encoding;private boolean cache;private Integer templateResolverOrder;private String[] viewNames;private String[] excludedViewNames;private boolean enableSpringElCompiler;private boolean renderHiddenMarkersBeforeCheckboxes;private boolean enabled;private final Servlet servlet;private final Reactive reactive;
使用
- 在templates下创建一个success.html
- 在html中引入thymeleaf的命名空间
<html lang="en" xmlns:th="http://www.thymeleaf.org">
- 创建一个Controller提供一个访问的方法
@Controller
public class HelloController {@RequestMapping("/hello")public String hello(Model model){model.addAttribute("name", "luxiya");return "success";}}
-------success.html---------
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
<!--文本替换-->
<div th:text="${name}"></div>
</body>
</html>
语法
1. 变量表达式
变量表达式用于访问上下文变量,在 Spring 环境中,这些变量通常是控制器传递到视图的模型属性。它使用 ${}
语法
- 简单变量访问:
<div th:text="${name}"></div>
--------------------------
@RequestMapping("/hello")
public String hello(Model model){model.addAttribute("name", "luxiya");return "success";
}
- 嵌套对象访问:
@RequestMapping("/bookAndAuthor")
public String bookAndAuthor(Model model){Book book = new Book();book.setName("空中花园");book.setAuthor("luxiya");book.setPrice(100);model.addAttribute("book", book);Author author = new Author();author.setName("luxiya");author.setAge(18);author.setAddress("kh");model.addAttribute("author", author);return "success";
}
----------------------
<!--变量表达式-->
<div>变量表达式</div>
<div th:text="${book.name}"></div>
<div th:text="${book.author}"></div>
<div th:text="${book.price}"></div>
<div th:text="${author.name}"></div>
<div th:text="${author.age}"></div>
<div th:text="${author.address}"></div>
2. 选择(星号)表达式
选择表达式与变量表达式类似,但它是基于 th:object
属性预先选择的对象来执行的。使用 *{}
语法。
<!--选择表达式-->
<div>选择表达式</div>
<div th:object="${book}"><div th:text="*{name}"></div><div th:text="*{author}"></div><div th:text="*{price}"></div>
</div>
在上述示例中,th:object="${book}"
指定了一个上下文对象 book
,之后在 <div>
标签内部就可以使用 *{}
表达式来访问 book
对象的属性。
3. 文字国际化表达式
文字国际化表达式用于从外部属性文件(.properties
)中获取本地化文本信息。使用 #{}
语法,通过键来索引对应的值,还可以提供一组可选参数。
默认情况下,Spring Boot 会在 src/main/resources
目录下查找名为 messages.properties
的文件作为默认的国际化属性文件。如果需要支持多语言,文件名可以按照 messages_{language}_{country}.properties
的格式命名,例如:
messages.properties
:默认语言(一般是英语或应用的默认语言)的属性文件。messages_zh_CN.properties
:简体中文(中国)的属性文件。messages_en_US.properties
:美式英语的属性文件。
举例代码:
<!--文字国际化表达式-->
<div>文字国际化表达式</div>
<h1 th:utext="#{main.title}">默认标题</h1>
<h1 th:utext="#{main.team}">默认标题</h1>
-------hello_zh_CN.properities-----------
main.title=空中花园
main.team=灰鸦小队
-------yml配置文件-----
spring:messages:basename: hello_zh_CNencoding: utf-8
自定义国际化属性文件的名称和位置:
配置完成后,在 Thymeleaf 模板中使用 #{main.title}
等表达式时,Spring Boot 就会从指定的属性文件中读取国际化信息。
spring:messages:basename: my-i18n/messages
--------指定多个配置文件--------
spring:messages:basename: my-i18n/messages,other-i18n/extra-messages
如果出现前端呈现???,注意文件的编码形式是否是utf-8,ide右下角可看。
4. URL 表达式
URL 表达式用于生成 URL,并且可以自动添加上下文或会话信息(URL 重写)。使用 @{}
语法,不需要指定项目名称。
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head><title>URL Expression Example</title>
</head>
<body><!-- 生成一个指向 /order/list 的 URL --><a th:href="@{/order/list}">View Order List</a><!-- 假设在控制器中传递了一个名为 'bookId' 的变量 --><a th:href="@{/book/detail(id=${bookId})}">View Book Details</a>
</body>
</html>
5.其他语法
-
动态设置类名:th:class
-
条件显示内容:th:if,th:unless,th:switch和th:case
-
**循环遍历:**th:each
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><style>.class1 {color: green;}.class2 {color: orange;}</style>
</head>
<body>
<!--循环遍历-->
<div th:each="product:${products}"><div th:text="${product}"></div><div th:text="${product}"></div>
</div><!--动态设置类名-->
<a th:class="${author.getAge() > 2}?'class1':'class2'" >年龄</a><!--判断显示内容-->
<p th:if="${book.getPrice() > 60}">贵了</p>
<p th:unless="${book.getPrice() > 60}">便宜了</p><span th:switch="${book1.getPrice()}"><p th:case="0">shi</p><p th:case="80">神作</p>
</span>
<span th:switch="${book2.getPrice()}"><p th:case="0">shi</p><p th:case="300">神作</p>
</span>
</body>
</html>
----------循环遍历------------@RequestMapping("/products")public String products(Model model){model.addAttribute("products", new String[]{"apple", "banana", "orange"});return "products";}
6.文件传输&表单提交
文件传输:
@RequestMapping("/file")
@Controller
public class FileController {@RequestMapping(method = RequestMethod.POST,value = "/upload")@ResponseBodypublic String upload(@RequestParam("pic") MultipartFile file, HttpServletRequest request){String contentType = file.getContentType();String fileName = file.getOriginalFilename();String filePath = "C:/Users/saber/Desktop/demoDataBase/springboot";try {this.uploadFile(file.getBytes(), filePath, fileName);} catch (Exception e) {throw new RuntimeException(e);}return "success";}public static void uploadFile(byte[] file, String filePath, String fileName) throws Exception {File targetFile = new File(filePath);if (!targetFile.exists()) {targetFile.mkdirs();}FileOutputStream out = new FileOutputStream(filePath + fileName);out.write(file);out.flush();out.close();}
}
------------------------------------
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
<form action="/file/upload" method="post" enctype="multipart/form-data"><input name="pic" type="file"><input type="submit">
</form>
</body>
</html>
表单提交:
- th:action:表单提交地址
@RequestMapping("/saveAuthor")
public String saveAuthor(Author author){System.out.println(author);//返回一个成功页面return "formSuccess";
}
--------------------------
<!--表单提交-->
<form th:action="@{/saveAuthor}" th:method="post" th:object="${author}"><label for="name">姓名:</label><input type="text" id="name" th:field="*{name}"><br><label for="email">邮箱:</label><input type="email" id="email" th:field="*{email}"><br><input type="submit" value="保存">
</form>