主题
Spring Boot
Spring Boot解决了什么问题?
Spring Framework 解决的问题
Spring Framework 主要解决了以下几方面的问题:
- 依赖注入(Dependency Injection, DI):通过反转控制(Inversion of Control, IoC)容器,Spring Framework 实现了对象之间的依赖关系的管理。DI 允许开发人员声明式地定义组件间依赖,由容器负责在运行时注入,降低了代码耦合度,提高了组件的可重用性和可测试性。
- 面向切面编程(Aspect-Oriented Programming, AOP):Spring 提供了对 AOP 的全面支持,使得开发人员可以将横切关注点(如事务管理、日志记录、权限校验等)从主业务逻辑中解耦,以切面的形式集中管理,增强了代码的模块化和可维护性。
- 简化企业级服务集成:Spring Framework 提供了对 JDBC、JMS、事务管理、邮件发送、任务调度等企业级服务的抽象封装,简化了与这些底层技术的交互,减轻了开发人员处理底层细节的负担。
- MVC 框架:Spring Web MVC 是一个强大的模型-视图-控制器(Model-View-Controller)框架,用于构建灵活且松耦合的 web 应用。它提供了一种清晰的分离关注点的方式,便于组织和管理复杂的 web 应用程序。
- 测试支持:Spring 提供了方便的测试工具和模拟对象(Mock Objects),简化了对依赖于 Spring 容器的组件进行单元测试和集成测试的过程。
Spring Framework 没有解决的问题
尽管 Spring Framework 解决了许多企业级应用开发中的痛点,但它也存在一些未直接解决的问题或挑战:
- 繁重的配置:虽然 Spring 通过 DI 和 AOP 等机制简化了代码结构,但早期版本的 Spring 应用往往需要编写大量的 XML 配置文件或使用复杂的 Java 配置类。这种配置过程既繁琐又容易出错,尤其是对于大型项目来说,配置管理变得相当复杂。
- 依赖管理复杂:在构建 Spring 应用时,开发者需要手动管理各个库的版本和依赖关系,确保它们相互兼容。特别是在项目初期,设置和维护这些依赖关系可能耗费大量时间。
- 项目启动与部署:传统的 Spring 应用通常需要打包成 WAR 文件部署到外部应用服务器(如 Tomcat、Jetty),这个过程涉及多个步骤,且每个项目的启动参数和配置可能有所不同,导致部署不够标准化和便捷。
- 微服务架构支持不够直接:虽然 Spring Framework 提供了构建单个服务所需的基础功能,但对于构建和管理包含多个微服务的分布式系统,缺乏开箱即用的服务发现、配置管理、熔断限流等微服务特性的支持。
Spring Boot 解决 Spring Framework 的问题
Spring Boot 主要是为了解决上述 Spring Framework 没有很好解决或开发者在实际使用过程中感到困扰的问题:
- 简化配置:Spring Boot 强调“约定优于配置”,提供了大量的默认配置,大幅减少了手动编写配置的需求。许多常见的应用配置(如数据库连接、HTTP 缓存、安全性等)只需简单的属性设置或注解即可完成。
- 自动化依赖管理:通过引入“Starter”依赖,Spring Boot 为特定类型的应用提供了预配置的依赖集合,确保了依赖版本的一致性和兼容性,避免了手动管理依赖的复杂性。
- 独立运行与快速部署:Spring Boot 应用可以被打包为一个自包含的可执行 JAR 或 WAR 文件,其中包含了嵌入式服务器(如 Tomcat)。这样,开发者可以直接通过
java -jar命令启动应用,无需部署到外部应用服务器,简化了部署流程,加快了开发迭代速度。 - 微服务支持:Spring Boot 与 Spring Cloud 生态紧密结合,为构建微服务架构提供了诸多开箱即用的解决方案,包括服务注册与发现、配置中心、负载均衡、熔断降级、API 网关等,极大地简化了微服务系统的开发和运维工作。
总的来说,Spring Boot 通过提供自动化配置、简化依赖管理、实现独立运行能力以及对微服务架构的深度支持,有效地解决了 Spring Framework 在易用性、部署复杂性以及微服务支持等方面的不足,进一步提升了 Java 开发的效率和体验。
Spring Boot的启动过程深入了解
深入了解Spring Boot的启动过程不仅需要理论上的理解,结合代码示例更能直观地展现其实现细节。以下是一系列代码示例,配合文字说明,帮助您更深入地理解Spring Boot的启动过程:
一、Spring Boot启动入口
java
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}这是典型的Spring Boot启动入口,主类Application使用@SpringBootApplication注解,并在main()方法中调用SpringApplication.run()启动应用程序。
二、SpringApplication的初始化
创建SpringApplication实例并调用run()方法时,Spring Boot开始执行一系列初始化操作:
java
SpringApplication app = new SpringApplication(Application.class);
app.run(args);这里简略展示了SpringApplication的创建,实际的初始化还包括加载配置属性、注册监听器、发布事件等。
三、Spring Boot配置属性
外部配置文件(如application.properties)中定义的属性可以通过@Value注解注入到Bean中:
java
@Service
public class MyService {
@Value("${my.service.config.value}")
private String configValue;
// ...
}四、创建和刷新ApplicationContext
在SpringApplication.run()内部,Spring Boot创建并刷新ApplicationContext:
java
ApplicationContext context = app.run(args);刷新上下文的过程涉及Bean定义的加载、实例化、依赖注入、初始化与后置处理等。
五、自动配置
Spring Boot自动配置基于@EnableAutoConfiguration注解。例如,当检测到HSQLDB依赖时,会自动配置一个内存数据库:
java
@Configuration
@EnableAutoConfiguration
public class DatabaseConfig {
@Autowired
private DataSource dataSource; // 自动配置的DataSource
// ...
}六、Spring Boot Actuator
Actuator提供了一系列生产就绪的功能,如健康检查、指标监控、审计日志等。启用Actuator只需添加相应依赖,并在配置文件中开启端点:
yaml
# application.properties
management.endpoints.web.exposure.include=health,metrics然后可以在应用运行时访问/actuator/health或/actuator/metrics等端点获取相关信息。
七、嵌入式Web容器
Spring Boot支持内嵌的Web容器。以下示例展示了如何使用WebMvcConfigurer自定义MVC配置:
java
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/static/**")
.addResourceLocations("classpath:/static/");
}
// ...
}八、启动任务与CommandLineRunner
实现CommandLineRunner或ApplicationRunner接口,可以在应用启动后执行特定任务:
java
@Component
public class StartupTask implements CommandLineRunner {
@Override
public void run(String... args) throws Exception {
System.out.println("Application started with arguments: " + Arrays.toString(args));
// 执行其他启动任务...
}
}九、Spring Boot DevTools
启用DevTools以实现自动重启、LiveReload等功能,只需添加相关依赖:
xml
<!-- pom.xml -->
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
</dependencies>十、无缝切换与热部署
结合IDE(如IntelliJ IDEA)和Spring Loaded等工具,可以实现在开发过程中修改代码后无需手动重启应用。配置IDE支持Spring Loaded,通常涉及设置JVM代理和编译器选项。
以上代码示例涵盖了Spring Boot启动过程中的关键环节,包括启动入口、配置属性、自动配置、Actuator、嵌入式Web容器、启动任务、DevTools以及无缝切换与热部署。通过这些示例,您可以更具体地了解Spring Boot启动过程中的各个组成部分及其实际用法。
Spring Boot集成各种示例
集成数据库
Spring Boot集成MySQL - 基于Spring Data JDBC的封装
在Spring Boot中使用MySQL数据库,并基于Spring JDBC进行数据访问层的封装是一个相对直接的过程。
Spring JDBC是Spring框架提供的一个JDBC抽象层,它简化了数据库访问并消除了样板代码。
下面是集成MySQL数据库并使用Spring JDBC的详细步骤。
1. 添加依赖
首先,在pom.xml文件中添加Spring Boot Starter for MySQL数据库和Spring JDBC的依赖。
xml
<?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>cn.org.bsfc</groupId>
<artifactId>spring-boot-example-0210</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.0</version>
<relativePath/>
</parent>
<dependencies>
<!-- Spring Boot Starter for Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Spring Boot Starter for Data Jdbc -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>
<!-- MySQL Driver -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!-- Spring Boot Starter Test for testing -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
</project>2. 配置数据库连接
在application.properties中配置MySQL数据库连接信息。
properties
# application.properties 示例
# server
server.port=8080
# spring datasource
spring.datasource.url=jdbc:mysql://localhost:3306/db-example?useSSL=false&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver3. 创建实体类(Optional)
虽然不是必须的,但通常我们会为数据库表创建对应的Java实体类。
java
public class User {
private Long id;
private String name;
private String email;
// Getter and Setter methods...
}4. 数据访问层(Repository)
使用Spring Data JDBC的接口方式定义数据访问操作。如果需要自定义查询,可以继承JdbcRepository并实现所需方法。
java
import org.springframework.data.repository.CrudRepository;
public interface UserRepository extends CrudRepository<User, Long> {
// Additional custom methods if needed...
}5. 服务层(Service)
在服务层中注入Repository并使用它来执行数据库操作。
java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UserService {
private final UserRepository userRepository;
@Autowired
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
public User saveUser(User user) {
return userRepository.save(user);
}
// Other service methods...
}6. 控制器(Controller)
最后,在控制器中调用服务层的方法来处理HTTP请求。
java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class UserController {
private final UserService userService;
@Autowired
public UserController(UserService userService) {
this.userService = userService;
}
@PostMapping("/users")
public User createUser(@RequestBody User user) {
return userService.saveUser(user);
}
}以上就是集成MySQL数据库并使用Spring Data JDBC进行数据访问的基本配置和代码示例。请根据实际需求调整实体类、Repository接口以及业务逻辑。
Spring Boot集成Redis
在Spring Boot中集成Redis是一个简单直接的过程,主要涉及添加依赖、配置Redis连接信息、以及在应用中使用Redis。
以下是如何在Spring Boot应用中集成Redis的步骤。
1. 添加依赖
在项目的pom.xml文件中,添加Spring Boot Starter Data Redis的依赖项:
xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
</dependencies>2. 配置Redis
在application.properties中配置Redis服务器的信息。例如:
properties
# application.properties
spring.redis.host=localhost
spring.redis.port=6379
spring.redis.password= # 如果有密码的话,取消注释并设置3. 使用RedisTemplate操作Redis
Spring Boot会自动配置RedisTemplate,你可以通过@Autowired直接在需要使用Redis的地方注入它。
java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
@Component
public class RedisService {
private final RedisTemplate<String, Object> redisTemplate;
@Autowired
public RedisService(RedisTemplate<String, Object> redisTemplate) {
this.redisTemplate = redisTemplate;
}
public void setValue(String key, Object value) {
redisTemplate.opsForValue().set(key, value);
}
public Object getValue(String key) {
return redisTemplate.opsForValue().get(key);
}
// 更多操作如删除、列表操作等...
}4. 高级配置与特性
- 序列化配置:默认情况下,Spring Boot使用JDK序列化。为了提高性能和易用性,你可以配置使用Jackson或其他序列化工具。
- 缓存管理:Spring Boot还提供了对Spring Cache的支持,允许你通过添加简单的注解(如
@Cacheable,@CacheEvict)来利用Redis作为缓存存储。 - 连接池配置:可以通过配置
spring.redis.jedis.pool或spring.redis.lettuce.pool属性来调整连接池设置。 - Redis哨兵或集群:对于高可用部署,你可以在配置中指定哨兵或集群信息。
5. 测试Redis集成
确保Redis服务正在运行,然后启动你的Spring Boot应用,你可以编写单元测试来验证Redis的读写操作是否正常。
这只是一个基础的集成示例,根据具体需求,你可能还需要配置更多高级特性和优化选项。
集成中间件
集成其他
Spring Boot应用部署
JAR包部署
Spring Boot应用部署采用打包成JAR文件的方式,旨在利用其内置的嵌入式Tomcat或其他Servlet容器,简化传统Web应用部署流程。以下是详细的步骤和说明:
1. 使用Maven进行打包
在Spring Boot项目中,确保pom.xml文件已经包含了Spring Boot Maven插件。如果未添加,需添加如下配置:
xml
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>然后在命令行或IDE中执行打包命令:
bash
mvn clean package这将清理旧的构建产物,编译项目,执行测试(如果有),并最终打包成一个可执行的JAR文件。生成的JAR通常位于target目录下,文件名格式为your-project-name-<version>.jar。
这将完成同样的清理、编译、测试和打包过程,生成的JAR文件同样位于build/libs目录下,文件名类似your-project-name-<version>.jar。
2. 打包类型
Spring Boot应用默认被打包为“fat JAR”或“über JAR”,这种类型的JAR不仅包含了项目的字节码,还包含了所有依赖库以及嵌入式Servlet容器(如Tomcat)。这意味着一个单一的JAR文件就包含了应用运行所需的所有组件,无需在目标环境中预先安装或配置Servlet容器。
3. 部署JAR文件
本地部署
要运行打包好的JAR文件,只需在命令行中使用java -jar命令:
bash
java -jar target/your-project-name-<version>.jar
# 或者对于Gradle项目
java -jar build/libs/your-project-name-<version>.jar根据需要,可以指定各种运行参数、环境变量或配置文件位置。例如:
bash
java -Dserver.port=8081 -jar your-project-name.jar --spring.config.location=file:/path/to/application.properties远程服务器部署
将生成的JAR文件上传到目标服务器,通常放置在合适的应用部署目录下。然后通过SSH登录服务器,执行与本地相同的方式启动应用:
bash
ssh user@remote-server
cd /path/to/deployment/directory
java -jar your-project-name.jar确保服务器上已安装了兼容的Java运行环境(JRE或JDK),且版本与项目构建时使用的Java版本相符。
JAR包Docker部署
要使用Docker部署Spring Boot应用,您需要创建一个Dockerfile来定义如何构建Docker镜像,并且可能还需要在Maven或Gradle构建脚本中集成Docker插件以简化构建过程。以下是详细的步骤:
1. 创建Dockerfile
在Spring Boot项目的根目录下创建一个名为Dockerfile的文件,内容如下:
Dockerfile
# 使用官方的Java基础镜像作为基础环境
FROM adoptopenjdk:11-jre-hotspot
# 设置环境变量(可根据实际需求调整)
ENV SPRING_PROFILES_ACTIVE=prod
ENV SERVER_PORT=8080
# 设置工作目录
WORKDIR /app
# 复制应用所需的文件到容器中
COPY target/my-spring-boot-app.jar app.jar
# 声明应用运行时需要暴露的端口
EXPOSE 8080
# 定义容器启动时执行的命令
ENTRYPOINT ["java", "-jar", "app.jar"]这里的my-spring-boot-app.jar是您构建得到的WAR文件名,请将其替换为您实际的WAR文件名。使用的Java基础镜像是AdoptOpenJDK 11(可替换为您所需的Java版本),并且假设应用监听在端口8080。
2. 构建WAR文件
确保已经按照之前的指导将项目配置为WAR打包,并通过Maven或Gradle构建工具生成WAR文件:
bash
mvn clean package3. 构建Docker镜像
在项目根目录下(含有Dockerfile)执行以下命令构建Docker镜像:
bash
docker build -t my-spring-boot-app:latest .这里my-spring-boot-app是您自定义的镜像名,:latest是标签。构建完成后,您将拥有一个名为my-spring-boot-app:latest的Docker镜像。
4. 运行Docker容器
使用以下命令启动Docker容器:
bash
docker run -d --name my-running-app -p 8080:8080 my-spring-boot-app:latest参数解释:
-d:在后台运行容器。--name my-running-app:为容器指定一个名称。-p 8080:8080:将主机的8080端口映射到容器的8080端口,使得外部可以通过主机IP和端口访问应用。my-spring-boot-app:latest:使用的镜像名及标签。
5. 访问应用
容器启动后,您可以通过以下URL(http://localhost:8080)访问您的Spring Boot应用
WAR包部署
将Spring Boot应用部署为WAR包并部署到外部Tomcat服务器上,需要进行一些特定的配置和步骤。以下是详细说明:
1. 修改打包方式
在项目的构建工具配置文件中(通常是pom.xml for Maven或build.gradle for Gradle),将打包方式改为war。以下是两种构建工具的具体示例:
Maven
在pom.xml中的<packaging>标签设置为war:
xml
<project>
<!-- ... -->
<packaging>war</packaging>
<!-- ... -->
</project>Gradle
在build.gradle中设置apply plugin: 'war'并确认bootWar任务被启用:
groovy
plugins {
id 'org.springframework.boot' version '...' // 使用合适的Spring Boot版本
id 'io.spring.dependency-management' version '...' // 可选,用于管理依赖版本
id 'war' // 添加war插件
}
// 如果使用Kotlin DSL
plugins {
id("org.springframework.boot") version "..." // 使用合适的Spring Boot版本
id("io.spring.dependency-management") version "..." // 可选,用于管理依赖版本
id("war") // 添加war插件
}2. 排除内置Tomcat
为了防止与外部Tomcat服务器产生冲突,需要在构建配置中排除Spring Boot的内嵌Tomcat依赖。在Maven的pom.xml中添加以下依赖排除:
xml
<dependencies>
<!-- ... -->
<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>
<!-- ... -->
</dependencies>对于Gradle,在dependencies块中使用exclude关键字:
groovy
dependencies {
implementation('org.springframework.boot:spring-boot-starter-web') {
exclude group: 'org.springframework.boot', module: 'spring-boot-starter-tomcat'
}
// ...
}3. 配置SpringBootServletInitializer
为了让Spring Boot应用能够由外部Servlet容器如Tomcat加载,需要创建一个继承自SpringBootServletInitializer的类,并重写configure方法:
java
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
public class ServletInitializer extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
}这里Application.class是您的主应用程序类,包含@SpringBootApplication注解。
4. 构建WAR文件
使用对应的构建工具命令生成WAR包:
Maven
bash
mvn clean package生成的WAR文件通常位于target目录下,文件名为your-project-name-<version>.war。
Gradle
bash
./gradlew clean build生成的WAR文件位于build/libs目录下,文件名为your-project-name-<version>.war。
5. 部署到Tomcat
将生成的WAR文件复制到Tomcat的webapps目录下。如果您正在运行Tomcat服务,它会自动检测到新部署的WAR文件并进行解压及部署。如果您尚未启动Tomcat,启动后它同样会处理新部署的WAR文件。
6. 访问应用
部署完成后,您可以使用以下URL(http://localhost:8080/your-project-name)访问您的Spring Boot应用:
这里的your-project-name通常对应WAR文件的基础名称(不带版本号)。如果在部署过程中更改了上下文路径,访问URL应相应调整。
Tomcat容器替换为Jetty容器
要在Spring Boot应用中将默认的Tomcat容器替换为Jetty容器,可以按照以下步骤进行操作:
修改Maven依赖
排除Tomcat依赖:首先,你需要在
pom.xml文件中的spring-boot-starter-web依赖里排除Tomcat。这可以通过<exclusions>标签实现。xml<dependencies> <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> </dependencies>添加Jetty依赖:接下来,在
pom.xml中添加Jetty的起步依赖。xml<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jetty</artifactId> </dependency>
配置文件调整(可选)
虽然通常情况下仅上述步骤就足够了,但如果你需要对Jetty进行额外的配置,可以在application.properties中添加相应的配置项。例如,调整端口:
properties
# 端口配置
server.port=8081
# 启动线程数
server.jetty.acceptors=2
# Selector线程数
server.jetty.selectors=4
# 访问日志配置
server.jetty.accesslog.enabled=true
server.jetty.accesslog.filename=access.log
server.jetty.accesslog.file-date-format=.yyyy-MM-dd
# SSL/TLS配置
server.ssl.key-store=classpath:keystore.p12
server.ssl.key-store-type=PKCS12
server.ssl.key-store-password=changeit
server.ssl.keyAlias=tomcat
# 请求和响应缓冲区大小
server.jetty.max-http-header-size=10KB
server.jetty.max-http-form-post-size=20MB重新构建和运行
完成上述修改后,确保重新构建你的项目,以便Maven下载新的依赖并更新你的应用配置。如果你使用IDE,通常可以通过清理(Clean)和重建(Build)项目来实现这一点。之后,当你再次运行你的Spring Boot应用时,它将会使用Jetty作为Web容器而非Tomcat。
由于实际日志内容会根据你的具体环境(如Spring Boot版本、Jetty版本、具体应用配置等)有所不同,我将提供一个简化的示例来说明Spring Boot应用使用Jetty启动时可能出现的日志输出。请注意,下面的示例是基于文本描述性构造的,并非直接来自某个特定运行实例。
plaintext
:: Spring Boot :: (v2.6.3)
2023-04-09T10:30:45.00+08:00 INFO [main] org.springframework.boot.StartupInfoLogger - Starting application using Java 11.0.13 on DESKTOP-XXXXXX with PID 12344 (C:\workspace\myapp\target\classes started by UserName in C:\workspace\myapp)
2023-04-09T10:30:45.23+08:00 DEBUG [main] org.springframework.boot.logging.ClasspathLoggingApplicationListener - Application failed to start with classpath: [file:/C:/workspace/myapp/target/classes/, ...]
2023-04-09T10:30:46.54+08:00 INFO [main] org.springframework.boot.web.embedded.jetty.JettyWebServer - Starting Jetty web server...
2023-04-09T10:30:46.75+08:00 INFO [main] org.eclipse.jetty.util.log - Logging initialized @139ms to org.eclipse.jetty.util.log.Slf4jLog
2023-04-09T10:30:46.90+08:00 INFO [main] org.eclipse.jetty.server.Server - jetty-9.4.44.v20210927; built: 2021-09-27T11:06:34.143Z; git: 4a1c13d268d4dfe655fb413a2f4aabb09bb33357; jvm 11.0.13+8
2023-04-09T10:30:46.92+08:00 INFO [main] org.eclipse.jetty.server.handler.ContextHandler - Started o.s.b.w.e.j.JettyEmbeddedWebAppContext@764973b: http://0.0.0.0:8080/
2023-04-09T10:30:47.02+08:00 INFO [main] org.eclipse.jetty.server.Server - Started Server@7e2f09d in 2037ms
2023-04-09T10:30:47.03+08:00 INFO [main] org.springframework.boot.StartupInfoLogger - Started application in 2.49 seconds (JVM running for 3.266)这段示例日志展示了Spring Boot应用启动的几个关键步骤,包括Spring Boot的启动信息、Jetty服务器的初始化、以及最终的成功启动消息,包括绑定的端口(在这个例子中是8080)。请注意,日期时间戳、PID、用户名、路径、版本号等信息会根据实际情况有所不同。
以上步骤应该能帮助你成功地将Spring Boot应用中的Tomcat容器替换为Jetty容器。
Tomcat容器替换为Undertow容器
要在Spring Boot应用中将默认的Tomcat容器替换为Undertow容器,可以按照以下步骤进行操作:
Maven项目配置
排除Tomcat依赖:首先,你需要从
spring-boot-starter-web依赖中排除Tomcat。在你的pom.xml文件里,找到或添加这个依赖,并进行如下配置来排除Tomcat:xml<dependencies> <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> </dependencies>添加Undertow依赖:然后,你需要引入Undertow作为新的Web服务器依赖项:
xml<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-undertow</artifactId> </dependency>
配置Undertow(可选)
你还可以通过Spring Boot的配置文件(通常是application.properties)来调整Undertow的行为,综合示例,展示了一些关键配置的组合等:
properties
# 设置端口
server.port=8080
# 开启访问日志
server.undertow.accesslog.enabled=true
server.undertow.accesslog.dir=./logs
server.undertow.accesslog.pattern=%h %l %u %t "%r" %s %b "%{i,Referer}" "%{i,User-Agent}"
# IO线程数和工作线程数
server.undertow.io-threads=2
server.undertow.worker-threads=200
# 缓冲区大小和直接缓冲区
server.undertow.buffer-size=16384
server.undertow.direct-buffers=true
# SSL配置示例
server.ssl.enabled=true
server.ssl.key-store=classpath:keystore.p12
server.ssl.key-store-password=mysecret
server.ssl.keyStoreType=PKCS12
server.ssl.keyAlias=mykey
# 启用HTTP/2
server.http2.enabled=true完成以上步骤后,重新构建并运行你的Spring Boot应用,它现在应该使用Undertow作为Web服务器了。
更改容器后需要根据Undertow的特点调整一些特定的配置或优化,以确保应用正常运行且性能最优。
Tomcat/Jetty/Undertow容器对比和使用场景
那在Spring Boot应用部署中,常见的三种Web容器是Tomcat、Jetty和Undertow,它们各有特点,适用于不同的应用场景:
Tomcat容器
优点:
- 成熟稳定: 作为Apache的项目,Tomcat是最为广泛使用的Servlet容器,拥有庞大的用户基础和丰富的文档资源。
- 全面性: 支持大部分Java EE规范,包括JSP和Servlet,适合需要这些功能的Web应用。
- 易于管理: 提供了一个图形化的管理界面,便于日常运维。
缺点:
- 内存占用: 相比其他轻量级容器,Tomcat的内存占用可能稍高。
- 启动速度: 在某些场景下,Tomcat的启动速度可能不如Jetty或Undertow快。
使用场景:
- 适用于企业级应用,特别是需要全面Java EE支持的场景。
- 对稳定性要求高,且不需要极致性能的应用。
Jetty容器
优点:
- 轻量级: Jetty设计得更为轻量,启动速度快,内存占用低,适合微服务架构。
- 灵活性: Jetty支持动态配置和模块化,容易嵌入到应用程序中。
- 长连接优化: 对于需要维持长时间连接的应用,如WebSocket服务,Jetty表现更佳。
缺点:
- 文档和社区支持: 相对于Tomcat,Jetty的文档和社区资源可能略少。
- 企业级特性: 相比Tomcat,Jetty在一些企业级特性和管理工具方面可能不够完善。
使用场景:
- 微服务架构,尤其是需要快速启动和低资源消耗的场景。
- 需要良好WebSocket支持的应用。
Undertow容器
优点:
- 高性能: Undertow在设计上注重性能,采用非阻塞I/O模型,特别在高并发场景下表现优秀。
- 轻量灵活: Undertow同样是一款轻量级容器,易于嵌入到应用程序中。
- 可扩展性强: 提供了高度可定制的API,方便开发者根据需求进行扩展。
缺点:
- 生态与文档: 相比Tomcat和Jetty,Undertow的生态相对较小,文档和社区支持也可能不如前两者丰富。
- 学习曲线: 对于习惯了Tomcat或Jetty的开发者来说,Undertow可能有一定的学习成本。
使用场景:
- 高性能Web服务,特别是在处理大量并发请求时。
- 需要高度定制化Web服务器行为的场景。
综上所述,选择哪种容器取决于具体的应用需求、性能要求、资源限制以及团队对特定技术的熟悉程度。Spring Boot提供了很好的支持来轻松切换这三种容器,开发者可以根据项目需求做出最佳选择。
Spring Boot进阶
实现自动装配原理
Spring Boot的自动装配(Auto-Configuration)是其核心特性之一,它极大地简化了Spring应用的配置过程。自动装配的原理基于Spring框架的@Configuration、@ConditionalOnClass、@ConditionalOnMissingBean等注解,以及Spring Boot提供的spring.factories文件机制。下面详细解释其实现原理:
1. @SpringBootApplication
首先,Spring Boot应用通常会有一个带有@SpringBootApplication注解的入口类。这个注解是一个组合注解,它包含了@SpringBootConfiguration、@EnableAutoConfiguration和@ComponentScan三个核心注解。
@SpringBootConfiguration继承自@Configuration,标记该类为配置类,其中可以包含@Bean定义来注册bean到Spring容器。@EnableAutoConfiguration是自动配置的核心,它通过@Import(AutoConfigurationImportSelector.class)导入需要的配置类。@ComponentScan用于扫描当前包及其子包下的组件,包括@Component、@Service、@Repository、@Controller等注解标记的类。
2. AutoConfigurationImportSelector
当@EnableAutoConfiguration被处理时,AutoConfigurationImportSelector会被调用。这个类负责决定哪些自动配置类需要被加载。它主要通过以下几个步骤实现:
- 查找候选配置类:从
META-INF/spring.factories文件中读取所有org.springframework.boot.autoconfigure.EnableAutoConfiguration的值,这些就是自动配置的候选类。 - 过滤候选配置类:根据当前应用的类路径(即项目依赖的jar包)、已存在的bean、以及其他条件注解(如
@ConditionalOnClass、@ConditionalOnMissingBean等)来决定哪些候选配置类应该被实际使用。
3. 条件注解
自动装配的核心在于条件注解,比如:
@ConditionalOnClass:只有当指定的类存在于类路径上时,才加载对应的配置。@ConditionalOnMissingBean:如果应用上下文中不存在某个bean,则创建该bean。@ConditionalOnProperty:根据配置文件中的属性值决定是否加载配置。
这些注解使得自动配置具有很高的灵活性和智能性,能够根据应用的实际环境和需求动态调整配置。
4. 示例
假设有一个MyAutoConfiguration类,它使用了@Configuration和一些条件注解来定义一个bean。当满足条件注解指定的条件时,Spring Boot在启动过程中会自动发现并注册这个bean。
java
@Configuration
@ConditionalOnClass(MyService.class)
public class MyAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public MyService myService() {
return new MyServiceImpl();
}
}总结
Spring Boot的自动装配机制通过@SpringBootApplication、@EnableAutoConfiguration、AutoConfigurationImportSelector、条件注解以及spring.factories文件的配合,实现了根据应用环境自动配置bean的功能,大大减轻了开发者的手动配置工作,提高了开发效率。开发者只需关注业务逻辑,而大部分基础设施和服务的配置由Spring Boot自动处理。
Starter原理
Spring Boot Starter的原理主要是为了简化Spring应用的配置和初始化过程,让开发者能够快速启动并运行应用,而不需要手动配置大量的XML或Java配置类。下面是Spring Boot Starter的核心工作原理:
- 自动配置(Auto-Configuration): Spring Boot在启动时,会自动扫描
/META-INF/spring.factories文件来发现自动配置类。这些自动配置类定义在各个Starter中,它们包含了对特定场景(如Web服务、数据库访问、安全等)的默认配置。每个Starter都是一个jar包,里面包含了一些依赖管理和自动配置逻辑。 - 条件化配置(@Conditional): 自动配置类中通常会使用
@Conditional注解来决定配置是否生效。这意味着配置只会在满足特定条件时(例如类路径下存在某个类,或者配置文件中有特定属性)才会被应用。这样可以确保配置的灵活性和按需加载。 - Starter POMs: Spring Boot提供了一系列的Starter POMs(Maven项目对象模型),这些POMs定义了一组依赖关系,用于快速引入一组技术栈所需的库。比如,引入
spring-boot-starter-web会自动加入Tomcat、Spring MVC等相关依赖,无需手动添加每一个依赖。 - Spring Factories: 如之前提到的,
spring.factories文件是Starter自动配置的关键。这个文件列出了自动配置类和其他需要由Spring Boot处理的组件。Spring Boot在启动时读取这些文件,并根据其中的列表注册相应的Bean。 - 自定义Starter: 开发者可以根据自己的需求创建自定义Starter。这通常涉及定义一个包含依赖管理、自动配置逻辑和可能的模板或配置文件的jar包。自定义Starter同样需要在自己的
META-INF/spring.factories文件中声明自动配置类。
通过这种方式,Spring Boot Starter机制大大简化了Spring应用的搭建和配置工作,使得开发者能够更加专注于业务逻辑的实现,而不是基础设施的搭建。
Starter自定义
在Spring Boot中,自定义starter是一种高级用法,它允许你封装特定功能或组件,使得其他开发者能够轻松地在他们的Spring Boot应用中引入和配置这些功能,而无需关注其实现细节。自定义starter本质上是一个jar包,它集合了自动配置、依赖管理和可选的模板代码,以简化集成过程。以下是创建自定义starter的基本步骤:
1. 创建Maven项目
首先,你需要创建一个新的Maven项目作为你的自定义starter。这个项目结构应该遵循一般的Spring Boot项目结构,并且需要包含一些特定的元数据来指示这是一个starter。
2. 添加依赖
在pom.xml中,你需要添加必要的依赖来支持Spring Boot特性以及你想要封装的任何第三方库或服务。通常,这包括但不限于:
spring-boot-starter-parent:提供默认的Maven配置和插件。spring-boot-autoconfigure:用于定义自动配置逻辑。- 你打算封装的特定库或服务的依赖。
xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.5</version> <!-- 使用当前Spring Boot的版本 -->
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<!-- 添加你项目所需的其他依赖 -->
</dependencies>3. 定义自动配置
自动配置是自定义starter的核心部分,它让Spring Boot根据特定条件(如类路径上的某些类或属性的存在)自动设置bean。通常,在src/main/java下创建一个新包,比如com.example.mystarter.config,并在此包下编写配置类。使用@Configuration注解标记该类,并可能使用@ConditionalOnClass、@ConditionalOnProperty等条件注解来控制自动配置的启用。
4. 提供属性
为了使你的starter更加灵活,你可以定义一些外部配置属性,让用户可以通过application.properties或application.yml来调整行为。为此,创建一个@ConfigurationProperties类,并在配置类中通过@EnableConfigurationProperties来启用它。
5. 打包发布
最后,将你的项目打包成jar文件,并发布到私有或公共Maven仓库,或者直接在你的组织内部共享。确保版本号管理得当,以便于后续维护和升级。
示例
假设你要创建一个处理日志记录到数据库的自定义starter,你可能需要定义一个自动配置类来设置数据库连接和日志处理器的bean,同时定义一个@ConfigurationProperties类来管理数据库连接信息。
注意事项
- 命名约定:自定义starter的命名通常遵循
spring-boot-starter-<功能名>的形式,例如my-project-starter。 - 文档:编写清晰的文档对于使用者理解如何配置和使用你的starter至关重要。
- 测试:确保为你的starter编写充分的单元测试和集成测试,验证其在不同环境下的行为。
通过上述步骤,你可以成功创建并分享自己的Spring Boot starter,促进代码复用,提升开发效率。 这里我们通过一个简化的例子来创建一个名为api-starter的自定义Spring Boot Starter,这个starter的目的是提供一些基本的API监控和健康检查功能。这个示例会涵盖自动配置、配置属性和基本的使用说明。
1. 创建Maven项目
首先,创建一个新的Maven项目,编辑pom.xml如下:
xml
<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.example</groupId>
<artifactId>api-starter</artifactId>
<version>1.0.0</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.5</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
</dependencies>
<properties>
<java.version>11</java.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>2. 定义配置属性
在src/main/java/com/example/api/config目录下创建ApiProperties.java,用于定义外部配置属性:
java
package com.example.api.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties(prefix = "api")
public class ApiProperties {
private boolean healthCheckEnabled = true;
// 更多配置属性...
// Getter and Setter
}3. 自动配置
在相同包下创建ApiAutoConfiguration.java,实现自动配置:
java
package com.example.api.config;
import org.springframework.boot.actuate.autoconfigure.health.CompositeHealthContributorConfiguration;
import org.springframework.boot.actuate.health.HealthEndpoint;
import org.springframework.boot.actuate.health.HealthIndicator;
import org.springframework.boot.actuate.health.HttpCodeStatusMapper;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@EnableAutoConfiguration
@EnableConfigurationProperties(ApiProperties.class)
public class ApiAutoConfiguration extends CompositeHealthContributorConfiguration<HealthIndicator, ApiProperties> {
@Bean
@ConditionalOnMissingBean
@ConditionalOnClass(HealthEndpoint.class)
public HealthEndpoint healthEndpoint(HttpCodeStatusMapper httpCodeStatusMapper, ApiProperties properties) {
return new HealthEndpoint(httpCodeStatusMapper, properties.getHealthGroup());
}
// 示例健康指标或其他配置...
}4. 发布和使用
完成以上步骤后,构建并安装此项目到你的本地Maven仓库。然后,在其他Spring Boot应用中使用这个starter,只需在该应用的pom.xml中添加依赖:
xml
<dependency>
<groupId>com.example</groupId>
<artifactId>api-starter</artifactId>
<version>1.0.0</version>
</dependency>并在application.yml中配置相关属性:
yaml
api:
health-check-enabled: true
# 更多配置...请注意,上述代码仅为示例,实际应用中你可能需要根据具体需求实现更复杂的功能和配置。
Actuator监控
Spring Boot 应用监控是指对基于 Spring Boot 构建的应用程序进行性能、健康状况、资源使用情况、日志记录、审计追踪等多方面的实时监控和管理。Spring Boot 自身提供了一个强大的模块 —— Spring Boot Actuator,它极大地简化了对 Spring Boot 应用的监控工作。以下是对 Spring Boot 应用监控的详细说明:
1. 核心功能
Spring Boot Actuator 提供了一系列生产级别的功能,包括但不限于:
- 健康检查(Health Checks):检查应用程序各个组件(如数据库连接、缓存、磁盘空间等)的健康状态,并通过
/health端点返回汇总信息。 - 指标收集(Metrics):收集各种应用指标,如 JVM 内存使用、CPU 利用率、HTTP 请求统计、数据库连接池状态等。这些指标可通过
/metrics或/actuator/metrics端点访问。 - 审计(Auditing):记录应用中的重要事件,如用户登录、系统启动、关键操作等。
- HTTP 跟踪(HTTP Tracing):跟踪 HTTP 请求和响应的详细信息,有助于诊断网络通信问题。
- 端点管理(Endpoints):内置多种端点,允许通过 REST API 查看应用配置、环境变量、beans列表、线程信息、堆栈跟踪等。
2. 端点配置
要启用 Spring Boot Actuator,只需在项目中添加 spring-boot-starter-actuator 依赖。通过 application.properties 或 application.yml 文件可以配置端点的暴露方式(HTTP、JMX等)、安全性以及是否公开特定端点。
例如:
properties
management.endpoints.web.exposure.include=health,info,metrics,loggers
management.endpoint.health.show-details=always3. 安全配置
由于 Actuator 端点可能暴露敏感信息,通常需要对其进行安全保护。这通常通过集成 spring-boot-starter-security 依赖,并配置 Spring Security 来实现。例如,可以创建一个继承 WebSecurityConfigurerAdapter 的配置类,重写其 configure 方法以限制对 Actuator 端点的访问。
4. 自定义监控指标
除了使用 Actuator 提供的内置指标,还可以自定义监控指标。例如,可以使用 Micrometer(Actuator 默认支持的度量库)创建 Counter 和 Gauge 类型的指标。Counter 用于累计值(如请求总数),通常以 _total 结尾;而 Gauge 用于表示可增可减的瞬时值(如当前内存使用量)。自定义指标可以通过 MeterRegistry 注入并调用相应方法(如 counter().increment() 或 gauge().set(value))来更新。
5. 日志监控与审计
Spring Boot 支持多种日志框架(如 Logback、Log4j2),通过配置可以实现日志级别调整、日志文件轮转、远程日志收集等。审计信息可以通过 Actuator 的审计端点或集成第三方审计工具来获取。
6. 可视化监控
虽然 Actuator 提供了丰富的 API,但直接通过 API 查看监控数据可能不够直观。为此,可以使用 Spring Boot Admin 这样的可视化监控工具。Spring Boot Admin 是一个开源项目,它可以自动发现或手动注册 Spring Boot 应用,并通过其前端界面展示应用状态、指标、日志、配置等信息。Spring Boot Admin 本身是一个独立的应用,需单独部署,并在被监控的应用中添加 Spring Boot Admin Client 依赖。
7. 第三方组件监控
针对特定第三方库或中间件的监控,如 Druid 数据源监控,可以通过配置相应的库提供的监控扩展或适配器来实现。例如,Druid 提供了监控功能,可以在 Spring Boot 配置中启用,并通过 Actuator 端点或其他方式暴露监控数据。
综上所述,Spring Boot 应用监控涉及多个层面,从基础的健康检查、性能指标监控,到安全配置、日志审计,再到可视化管理工具集成和特定组件监控。通过合理利用 Spring Boot Actuator 及相关工具,可以构建一套全面且易用的应用监控体系。
基本示例
1. 添加依赖
在 Maven 项目中,你需要在 pom.xml 文件中加入 spring-boot-starter-actuator 依赖:
xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>2. 配置端点暴露
默认情况下,Spring Boot 2.x 版本出于安全考虑不会暴露所有的 Actuator 端点。你可以通过 application.properties 或 application.yml 配置文件来控制哪些端点可以通过 HTTP 访问:
properties
# 暴露所有端点
management.endpoints.web.exposure.include=*
# 或者仅暴露指定端点
management.endpoints.web.exposure.include=health,info,metrics
# 设置健康检查详情级别
management.endpoint.health.show-details=always3. 使用端点示例
以下是一些访问不同端点的示例:
- 访问应用的基本信息:
bash
GET `http://localhost:8080/actuator/info`- 访问应用健康状况:
bash
GET `http://localhost:8080/actuator/health`- 访问应用的所有 metrics(度量指标):
bash
GET `http://localhost:8080/actuator/metrics`- 获取应用中的所有 Bean 信息:
bash
GET `http://localhost:8080/actuator/beans`- 如果你启用了自定义的健康检查指示器,可以访问自定义的健康检查:
bash
GET `http://localhost:8080/actuator/health/<custom-check>`4. 自定义端点示例
如果你需要创建自定义的端点,可以定义一个实现 org.springframework.boot.actuate.endpoint.annotation.Endpoint 接口的类:
java
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
@Endpoint(id = "myCustomEndpoint")
public class MyCustomEndpoint {
@ReadOperation
public String customData() {
// 返回自定义的数据
return "This is data from a custom endpoint";
}
}然后就可以通过 /actuator/myCustomEndpoint 访问这个自定义端点:
bash
GET `http://localhost:8080/actuator/myCustomEndpoint`请注意,以上示例假设你的 Spring Boot 应用正在运行并监听在 http://localhost:8080 端口上。
为了更好地管理和保护 Actuator 端点,还应该考虑添加安全相关的配置,尤其是在生产环境中。这通常涉及到 Spring Security 的配置,确保只有授权的用户或服务才能访问这些敏感的监控信息。