Java 生态系统笔记
1. 构建工具
1.1 Maven
Maven 是一个基于项目对象模型(POM)的构建工具,用于管理项目的依赖、构建、测试和部署。
核心概念:
- POM:Project Object Model,项目配置文件
- 坐标:groupId、artifactId、version
- 仓库:中央仓库、私有仓库、本地仓库
- 依赖管理:传递依赖、排除依赖
- 生命周期:clean、compile、test、package、install、deploy
- 插件:用于执行具体的构建任务
示例 POM 文件:
<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>myapp</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>jar</packaging>
<!-- 属性配置 -->
<properties>
<java.version>17</java.version>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring-boot.version>3.2.0</spring-boot.version>
</properties>
<!-- 依赖管理 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<!-- 依赖声明 -->
<dependencies>
<!-- Spring Boot 依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- 数据库依赖 -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<!-- 测试依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<!-- 构建配置 -->
<build>
<plugins>
<!-- Spring Boot Maven 插件 -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring-boot.version}</version>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Maven 编译器插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
<!-- Maven 资源插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>3.3.1</version>
<configuration>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
<!-- 资源过滤 -->
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
<!-- 仓库配置 -->
<repositories>
<!-- 中央仓库 -->
<repository>
<id>central</id>
<name>Central Repository</name>
<url>https://repo.maven.apache.org/maven2</url>
<layout>default</layout>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>central</id>
<name>Central Repository</name>
<url>https://repo.maven.apache.org/maven2</url>
<layout>default</layout>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
</project><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>myapp</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>jar</packaging>
<!-- 属性配置 -->
<properties>
<java.version>17</java.version>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring-boot.version>3.2.0</spring-boot.version>
</properties>
<!-- 依赖管理 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<!-- 依赖声明 -->
<dependencies>
<!-- Spring Boot 依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- 数据库依赖 -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<!-- 测试依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<!-- 构建配置 -->
<build>
<plugins>
<!-- Spring Boot Maven 插件 -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring-boot.version}</version>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Maven 编译器插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
<!-- Maven 资源插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>3.3.1</version>
<configuration>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
<!-- 资源过滤 -->
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
<!-- 仓库配置 -->
<repositories>
<!-- 中央仓库 -->
<repository>
<id>central</id>
<name>Central Repository</name>
<url>https://repo.maven.apache.org/maven2</url>
<layout>default</layout>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>central</id>
<name>Central Repository</name>
<url>https://repo.maven.apache.org/maven2</url>
<layout>default</layout>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
</project>常用 Maven 命令:
# 清理目标目录
mvn clean
# 编译源代码
mvn compile
# 运行测试
mvn test
# 打包项目
mvn package
# 安装到本地仓库
mvn install
# 部署到远程仓库
mvn deploy
# 运行 Spring Boot 应用
mvn spring-boot:run
# 跳过测试编译和执行
mvn package -DskipTests
mvn package -Dmaven.test.skip=true
# 指定配置文件
mvn package -Pproduction# 清理目标目录
mvn clean
# 编译源代码
mvn compile
# 运行测试
mvn test
# 打包项目
mvn package
# 安装到本地仓库
mvn install
# 部署到远程仓库
mvn deploy
# 运行 Spring Boot 应用
mvn spring-boot:run
# 跳过测试编译和执行
mvn package -DskipTests
mvn package -Dmaven.test.skip=true
# 指定配置文件
mvn package -Pproduction1.2 Gradle
Gradle 是一个基于 Groovy 或 Kotlin 语言的构建工具,结合了 Maven 和 Ant 的优点,提供了更灵活的构建配置。
核心概念:
- 项目:一个 Gradle 构建对应一个项目
- 任务:构建过程中的一个操作
- 插件:扩展 Gradle 功能
- 依赖管理:支持 Maven 和 Ivy 仓库
- 构建脚本:build.gradle(Groovy)或 build.gradle.kts(Kotlin)
示例 build.gradle 文件:
plugins {
id 'org.springframework.boot' version '3.2.0'
id 'io.spring.dependency-management' version '1.1.4'
id 'java'
id 'war' // 如果是 Web 应用
}
group = 'com.example'
version = '1.0.0-SNAPSHOT'
// Java 配置
java {
sourceCompatibility = '17'
targetCompatibility = '17'
}
// 仓库配置
repositories {
mavenCentral()
// 本地仓库
mavenLocal()
// 自定义仓库
maven {
url = uri('https://repo.example.com/maven2')
credentials {
username = project.findProperty('repoUsername') ?: System.getenv('REPO_USERNAME')
password = project.findProperty('repoPassword') ?: System.getenv('REPO_PASSWORD')
}
}
}
// 依赖配置
dependencies {
// Spring Boot 依赖
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-security'
// 数据库依赖
runtimeOnly 'com.mysql:mysql-connector-j'
// 测试依赖
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.junit.jupiter:junit-jupiter-api'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine'
}
// 测试配置
tasks.named('test') {
useJUnitPlatform()
}
// 打包配置
tasks.named('bootJar') {
archiveFileName = "${project.name}-${project.version}.jar"
}
// 自定义任务
task hello {
doLast {
println 'Hello from Gradle!'
}
}plugins {
id 'org.springframework.boot' version '3.2.0'
id 'io.spring.dependency-management' version '1.1.4'
id 'java'
id 'war' // 如果是 Web 应用
}
group = 'com.example'
version = '1.0.0-SNAPSHOT'
// Java 配置
java {
sourceCompatibility = '17'
targetCompatibility = '17'
}
// 仓库配置
repositories {
mavenCentral()
// 本地仓库
mavenLocal()
// 自定义仓库
maven {
url = uri('https://repo.example.com/maven2')
credentials {
username = project.findProperty('repoUsername') ?: System.getenv('REPO_USERNAME')
password = project.findProperty('repoPassword') ?: System.getenv('REPO_PASSWORD')
}
}
}
// 依赖配置
dependencies {
// Spring Boot 依赖
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-security'
// 数据库依赖
runtimeOnly 'com.mysql:mysql-connector-j'
// 测试依赖
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.junit.jupiter:junit-jupiter-api'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine'
}
// 测试配置
tasks.named('test') {
useJUnitPlatform()
}
// 打包配置
tasks.named('bootJar') {
archiveFileName = "${project.name}-${project.version}.jar"
}
// 自定义任务
task hello {
doLast {
println 'Hello from Gradle!'
}
}常用 Gradle 命令:
# 清理构建目录
./gradlew clean
# 编译源代码
./gradlew compileJava
# 运行测试
./gradlew test
# 打包项目
./gradlew build
# 安装到本地仓库
./gradlew publishToMavenLocal
# 运行 Spring Boot 应用
./gradlew bootRun
# 跳过测试
./gradlew build -x test
# 查看任务列表
./gradlew tasks
# 查看依赖树
./gradlew dependencies# 清理构建目录
./gradlew clean
# 编译源代码
./gradlew compileJava
# 运行测试
./gradlew test
# 打包项目
./gradlew build
# 安装到本地仓库
./gradlew publishToMavenLocal
# 运行 Spring Boot 应用
./gradlew bootRun
# 跳过测试
./gradlew build -x test
# 查看任务列表
./gradlew tasks
# 查看依赖树
./gradlew dependencies2. 测试框架
2.1 JUnit 5
JUnit 5 是 Java 单元测试的标准框架,于 2017 年发布,分为三个模块:
- JUnit Platform:测试执行引擎
- JUnit Jupiter:测试 API 和扩展模型
- JUnit Vintage:向后兼容 JUnit 3 和 JUnit 4
示例:
import org.junit.jupiter.api.*;
// 测试类
@TestInstance(TestInstance.Lifecycle.PER_CLASS) // 每个类创建一个实例
@DisplayName("User Service Tests") // 测试类名称
public class UserServiceTest {
private UserService userService;
// 在所有测试方法之前执行
@BeforeAll
static void beforeAll() {
System.out.println("Before all tests");
}
// 在每个测试方法之前执行
@BeforeEach
void setUp() {
userService = new UserServiceImpl(new InMemoryUserRepository());
System.out.println("Before each test");
}
// 测试方法
@Test
@DisplayName("Test create user") // 测试方法名称
void testCreateUser() {
// 准备数据
User user = new User("John", "Doe", "john.doe@example.com");
// 执行操作
User createdUser = userService.createUser(user);
// 断言
Assertions.assertNotNull(createdUser);
Assertions.assertEquals("John", createdUser.getFirstName());
Assertions.assertEquals("Doe", createdUser.getLastName());
Assertions.assertEquals("john.doe@example.com", createdUser.getEmail());
}
@Test
@DisplayName("Test get user by id")
void testGetUserById() {
// 准备数据
User user = new User("John", "Doe", "john.doe@example.com");
User createdUser = userService.createUser(user);
// 执行操作
User foundUser = userService.getUserById(createdUser.getId());
// 断言
Assertions.assertNotNull(foundUser);
Assertions.assertEquals(createdUser.getId(), foundUser.getId());
}
@Test
@DisplayName("Test delete user")
void testDeleteUser() {
// 准备数据
User user = new User("John", "Doe", "john.doe@example.com");
User createdUser = userService.createUser(user);
// 执行操作
userService.deleteUser(createdUser.getId());
// 断言:预期抛出异常
Assertions.assertThrows(UserNotFoundException.class, () -> {
userService.getUserById(createdUser.getId());
});
}
// 参数化测试
@ParameterizedTest
@DisplayName("Test with parameters")
@ValueSource(strings = {"John", "Jane", "Bob"}) // 参数源
void testWithParameters(String firstName) {
User user = new User(firstName, "Doe", firstName.toLowerCase() + ".doe@example.com");
User createdUser = userService.createUser(user);
Assertions.assertEquals(firstName, createdUser.getFirstName());
}
// 禁用测试
@Test
@Disabled("This test is disabled for now")
void disabledTest() {
// 测试内容
}
// 在每个测试方法之后执行
@AfterEach
void tearDown() {
System.out.println("After each test");
}
// 在所有测试方法之后执行
@AfterAll
static void afterAll() {
System.out.println("After all tests");
}
}import org.junit.jupiter.api.*;
// 测试类
@TestInstance(TestInstance.Lifecycle.PER_CLASS) // 每个类创建一个实例
@DisplayName("User Service Tests") // 测试类名称
public class UserServiceTest {
private UserService userService;
// 在所有测试方法之前执行
@BeforeAll
static void beforeAll() {
System.out.println("Before all tests");
}
// 在每个测试方法之前执行
@BeforeEach
void setUp() {
userService = new UserServiceImpl(new InMemoryUserRepository());
System.out.println("Before each test");
}
// 测试方法
@Test
@DisplayName("Test create user") // 测试方法名称
void testCreateUser() {
// 准备数据
User user = new User("John", "Doe", "john.doe@example.com");
// 执行操作
User createdUser = userService.createUser(user);
// 断言
Assertions.assertNotNull(createdUser);
Assertions.assertEquals("John", createdUser.getFirstName());
Assertions.assertEquals("Doe", createdUser.getLastName());
Assertions.assertEquals("john.doe@example.com", createdUser.getEmail());
}
@Test
@DisplayName("Test get user by id")
void testGetUserById() {
// 准备数据
User user = new User("John", "Doe", "john.doe@example.com");
User createdUser = userService.createUser(user);
// 执行操作
User foundUser = userService.getUserById(createdUser.getId());
// 断言
Assertions.assertNotNull(foundUser);
Assertions.assertEquals(createdUser.getId(), foundUser.getId());
}
@Test
@DisplayName("Test delete user")
void testDeleteUser() {
// 准备数据
User user = new User("John", "Doe", "john.doe@example.com");
User createdUser = userService.createUser(user);
// 执行操作
userService.deleteUser(createdUser.getId());
// 断言:预期抛出异常
Assertions.assertThrows(UserNotFoundException.class, () -> {
userService.getUserById(createdUser.getId());
});
}
// 参数化测试
@ParameterizedTest
@DisplayName("Test with parameters")
@ValueSource(strings = {"John", "Jane", "Bob"}) // 参数源
void testWithParameters(String firstName) {
User user = new User(firstName, "Doe", firstName.toLowerCase() + ".doe@example.com");
User createdUser = userService.createUser(user);
Assertions.assertEquals(firstName, createdUser.getFirstName());
}
// 禁用测试
@Test
@Disabled("This test is disabled for now")
void disabledTest() {
// 测试内容
}
// 在每个测试方法之后执行
@AfterEach
void tearDown() {
System.out.println("After each test");
}
// 在所有测试方法之后执行
@AfterAll
static void afterAll() {
System.out.println("After all tests");
}
}2.2 Mockito
Mockito 是一个流行的 Java 测试框架,用于创建和配置模拟对象,简化单元测试。
示例:
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import static org.mockito.Mockito.*;
// 使用 Mockito 扩展
@ExtendWith(MockitoExtension.class)
public class UserServiceMockitoTest {
// 模拟 UserRepository
@Mock
private UserRepository userRepository;
// 将模拟对象注入到 UserService 中
@InjectMocks
private UserServiceImpl userService;
@Test
void testGetUserById() {
// 准备数据
Long userId = 1L;
User mockUser = new User("John", "Doe", "john.doe@example.com");
mockUser.setId(userId);
// 配置模拟对象的行为
when(userRepository.findById(userId)).thenReturn(Optional.of(mockUser));
// 执行操作
User foundUser = userService.getUserById(userId);
// 断言
Assertions.assertNotNull(foundUser);
Assertions.assertEquals(userId, foundUser.getId());
Assertions.assertEquals("John", foundUser.getFirstName());
// 验证模拟对象的方法是否被调用
verify(userRepository, times(1)).findById(userId);
verifyNoMoreInteractions(userRepository);
}
@Test
void testCreateUser() {
// 准备数据
User user = new User("John", "Doe", "john.doe@example.com");
User mockUser = new User("John", "Doe", "john.doe@example.com");
mockUser.setId(1L);
// 配置模拟对象
when(userRepository.save(user)).thenReturn(mockUser);
// 执行操作
User createdUser = userService.createUser(user);
// 断言
Assertions.assertNotNull(createdUser);
Assertions.assertEquals(1L, createdUser.getId());
// 验证
verify(userRepository, times(1)).save(user);
}
@Test
void testDeleteUser() {
// 准备数据
Long userId = 1L;
User mockUser = new User("John", "Doe", "john.doe@example.com");
mockUser.setId(userId);
// 配置模拟对象
when(userRepository.findById(userId)).thenReturn(Optional.of(mockUser));
doNothing().when(userRepository).delete(mockUser);
// 执行操作
userService.deleteUser(userId);
// 验证
verify(userRepository, times(1)).findById(userId);
verify(userRepository, times(1)).delete(mockUser);
}
}import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import static org.mockito.Mockito.*;
// 使用 Mockito 扩展
@ExtendWith(MockitoExtension.class)
public class UserServiceMockitoTest {
// 模拟 UserRepository
@Mock
private UserRepository userRepository;
// 将模拟对象注入到 UserService 中
@InjectMocks
private UserServiceImpl userService;
@Test
void testGetUserById() {
// 准备数据
Long userId = 1L;
User mockUser = new User("John", "Doe", "john.doe@example.com");
mockUser.setId(userId);
// 配置模拟对象的行为
when(userRepository.findById(userId)).thenReturn(Optional.of(mockUser));
// 执行操作
User foundUser = userService.getUserById(userId);
// 断言
Assertions.assertNotNull(foundUser);
Assertions.assertEquals(userId, foundUser.getId());
Assertions.assertEquals("John", foundUser.getFirstName());
// 验证模拟对象的方法是否被调用
verify(userRepository, times(1)).findById(userId);
verifyNoMoreInteractions(userRepository);
}
@Test
void testCreateUser() {
// 准备数据
User user = new User("John", "Doe", "john.doe@example.com");
User mockUser = new User("John", "Doe", "john.doe@example.com");
mockUser.setId(1L);
// 配置模拟对象
when(userRepository.save(user)).thenReturn(mockUser);
// 执行操作
User createdUser = userService.createUser(user);
// 断言
Assertions.assertNotNull(createdUser);
Assertions.assertEquals(1L, createdUser.getId());
// 验证
verify(userRepository, times(1)).save(user);
}
@Test
void testDeleteUser() {
// 准备数据
Long userId = 1L;
User mockUser = new User("John", "Doe", "john.doe@example.com");
mockUser.setId(userId);
// 配置模拟对象
when(userRepository.findById(userId)).thenReturn(Optional.of(mockUser));
doNothing().when(userRepository).delete(mockUser);
// 执行操作
userService.deleteUser(userId);
// 验证
verify(userRepository, times(1)).findById(userId);
verify(userRepository, times(1)).delete(mockUser);
}
}2.3 Spring Boot Test
Spring Boot Test 提供了用于测试 Spring Boot 应用的工具和注解。
示例:
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.web.servlet.MockMvc;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
// 启动 Spring Boot 应用上下文
@SpringBootTest
// 自动配置 MockMvc
@AutoConfigureMockMvc
public class UserControllerTest {
// 注入 MockMvc
@Autowired
private MockMvc mockMvc;
// 模拟 UserService
@MockBean
private UserService userService;
@Test
void testGetUserById() throws Exception {
// 准备数据
Long userId = 1L;
User user = new User("John", "Doe", "john.doe@example.com");
user.setId(userId);
// 配置模拟对象
when(userService.getUserById(userId)).thenReturn(user);
// 执行 HTTP 请求
mockMvc.perform(get("/api/users/{id}", userId))
.andExpect(status().isOk())
.andExpect(content().contentType("application/json"))
.andExpect(jsonPath("$.id").value(userId))
.andExpect(jsonPath("$.firstName").value("John"))
.andExpect(jsonPath("$.lastName").value("Doe"))
.andExpect(jsonPath("$.email").value("john.doe@example.com"));
// 验证
verify(userService, times(1)).getUserById(userId);
}
@Test
void testCreateUser() throws Exception {
// 准备数据
User user = new User("John", "Doe", "john.doe@example.com");
User createdUser = new User("John", "Doe", "john.doe@example.com");
createdUser.setId(1L);
// 配置模拟对象
when(userService.createUser(any(User.class))).thenReturn(createdUser);
// 执行 HTTP 请求
mockMvc.perform(post("/api/users")
.contentType("application/json")
.content("{\"firstName\":\"John\",\"lastName\":\"Doe\",\"email\":\"john.doe@example.com\"}"))
.andExpect(status().isCreated())
.andExpect(content().contentType("application/json"))
.andExpect(jsonPath("$.id").value(1L))
.andExpect(jsonPath("$.firstName").value("John"));
// 验证
verify(userService, times(1)).createUser(any(User.class));
}
}import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.web.servlet.MockMvc;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
// 启动 Spring Boot 应用上下文
@SpringBootTest
// 自动配置 MockMvc
@AutoConfigureMockMvc
public class UserControllerTest {
// 注入 MockMvc
@Autowired
private MockMvc mockMvc;
// 模拟 UserService
@MockBean
private UserService userService;
@Test
void testGetUserById() throws Exception {
// 准备数据
Long userId = 1L;
User user = new User("John", "Doe", "john.doe@example.com");
user.setId(userId);
// 配置模拟对象
when(userService.getUserById(userId)).thenReturn(user);
// 执行 HTTP 请求
mockMvc.perform(get("/api/users/{id}", userId))
.andExpect(status().isOk())
.andExpect(content().contentType("application/json"))
.andExpect(jsonPath("$.id").value(userId))
.andExpect(jsonPath("$.firstName").value("John"))
.andExpect(jsonPath("$.lastName").value("Doe"))
.andExpect(jsonPath("$.email").value("john.doe@example.com"));
// 验证
verify(userService, times(1)).getUserById(userId);
}
@Test
void testCreateUser() throws Exception {
// 准备数据
User user = new User("John", "Doe", "john.doe@example.com");
User createdUser = new User("John", "Doe", "john.doe@example.com");
createdUser.setId(1L);
// 配置模拟对象
when(userService.createUser(any(User.class))).thenReturn(createdUser);
// 执行 HTTP 请求
mockMvc.perform(post("/api/users")
.contentType("application/json")
.content("{\"firstName\":\"John\",\"lastName\":\"Doe\",\"email\":\"john.doe@example.com\"}"))
.andExpect(status().isCreated())
.andExpect(content().contentType("application/json"))
.andExpect(jsonPath("$.id").value(1L))
.andExpect(jsonPath("$.firstName").value("John"));
// 验证
verify(userService, times(1)).createUser(any(User.class));
}
}3. 代码质量工具
3.1 SonarQube
SonarQube 是一个开源的代码质量管理平台,用于检测代码中的 bugs、漏洞和代码异味。
主要功能:
- 代码质量分析
- 安全漏洞检测
- 代码覆盖率报告
- 持续集成支持
- 多种语言支持
使用方法:
- 安装 SonarQube 服务器
- 在项目中添加 SonarQube Maven 或 Gradle 插件
- 运行分析命令
- 在 SonarQube 界面查看报告
Maven 配置:
<plugin>
<groupId>org.sonarsource.scanner.maven</groupId>
<artifactId>sonar-maven-plugin</artifactId>
<version>3.10.0.2594</version>
</plugin><plugin>
<groupId>org.sonarsource.scanner.maven</groupId>
<artifactId>sonar-maven-plugin</artifactId>
<version>3.10.0.2594</version>
</plugin>运行分析:
# Maven
mvn sonar:sonar -Dsonar.projectKey=myapp -Dsonar.host.url=http://localhost:9000 -Dsonar.login=my-token
# Gradle
./gradlew sonar -Dsonar.projectKey=myapp -Dsonar.host.url=http://localhost:9000 -Dsonar.login=my-token# Maven
mvn sonar:sonar -Dsonar.projectKey=myapp -Dsonar.host.url=http://localhost:9000 -Dsonar.login=my-token
# Gradle
./gradlew sonar -Dsonar.projectKey=myapp -Dsonar.host.url=http://localhost:9000 -Dsonar.login=my-token3.2 Checkstyle
Checkstyle 是一个开发工具,用于检查 Java 代码是否符合编码标准。
主要功能:
- 检查命名约定
- 检查代码格式
- 检查代码复杂度
- 支持自定义规则
- 与 IDE 集成
Maven 配置:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<version>3.3.0</version>
<configuration>
<configLocation>checkstyle.xml</configLocation>
<failOnViolation>true</failOnViolation>
</configuration>
<executions>
<execution>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin><plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<version>3.3.0</version>
<configuration>
<configLocation>checkstyle.xml</configLocation>
<failOnViolation>true</failOnViolation>
</configuration>
<executions>
<execution>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>运行检查:
# Maven
mvn checkstyle:check
# Gradle
./gradlew checkstyleMain checkstyleTest# Maven
mvn checkstyle:check
# Gradle
./gradlew checkstyleMain checkstyleTest3.3 PMD
PMD 是一个源代码分析器,用于检测代码中的问题,如未使用的变量、空的 catch 块等。
主要功能:
- 代码异味检测
- 重复代码检测
- 安全漏洞检测
- 支持多种语言
Maven 配置:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-pmd-plugin</artifactId>
<version>3.20.0</version>
<configuration>
<rulesets>
<ruleset>rulesets/java/quickstart.xml</ruleset>
</rulesets>
<failOnViolation>true</failOnViolation>
</configuration>
<executions>
<execution>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin><plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-pmd-plugin</artifactId>
<version>3.20.0</version>
<configuration>
<rulesets>
<ruleset>rulesets/java/quickstart.xml</ruleset>
</rulesets>
<failOnViolation>true</failOnViolation>
</configuration>
<executions>
<execution>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>运行检查:
# Maven
mvn pmd:check
# Gradle
./gradlew pmdMain pmdTest# Maven
mvn pmd:check
# Gradle
./gradlew pmdMain pmdTest4. 部署工具
4.1 Docker
Docker 是一个开源的容器化平台,用于打包、分发和运行应用程序。
Dockerfile 示例:
# 使用官方 OpenJDK 17 镜像作为基础镜像
FROM openjdk:17-jdk-alpine
# 设置工作目录
WORKDIR /app
# 复制打包好的 JAR 文件到容器中
COPY target/myapp-1.0.0.jar app.jar
# 暴露端口
EXPOSE 8080
# 运行应用
ENTRYPOINT ["java", "-jar", "app.jar"]# 使用官方 OpenJDK 17 镜像作为基础镜像
FROM openjdk:17-jdk-alpine
# 设置工作目录
WORKDIR /app
# 复制打包好的 JAR 文件到容器中
COPY target/myapp-1.0.0.jar app.jar
# 暴露端口
EXPOSE 8080
# 运行应用
ENTRYPOINT ["java", "-jar", "app.jar"]Docker Compose 示例:
version: '3.8'
services:
# 应用服务
app:
build: .
ports:
- "8080:8080"
environment:
- SPRING_PROFILES_ACTIVE=prod
- SPRING_DATASOURCE_URL=jdbc:mysql://db:3306/mydb
- SPRING_DATASOURCE_USERNAME=root
- SPRING_DATASOURCE_PASSWORD=password
depends_on:
- db
restart: always
networks:
- my-network
# 数据库服务
db:
image: mysql:8.0
ports:
- "3306:3306"
environment:
- MYSQL_ROOT_PASSWORD=password
- MYSQL_DATABASE=mydb
- MYSQL_CHARSET=utf8mb4
- MYSQL_COLLATION=utf8mb4_unicode_ci
volumes:
- mysql-data:/var/lib/mysql
- ./init.sql:/docker-entrypoint-initdb.d/init.sql
restart: always
networks:
- my-network
# 网络配置
networks:
my-network:
driver: bridge
# 数据卷配置
volumes:
mysql-data:
driver: localversion: '3.8'
services:
# 应用服务
app:
build: .
ports:
- "8080:8080"
environment:
- SPRING_PROFILES_ACTIVE=prod
- SPRING_DATASOURCE_URL=jdbc:mysql://db:3306/mydb
- SPRING_DATASOURCE_USERNAME=root
- SPRING_DATASOURCE_PASSWORD=password
depends_on:
- db
restart: always
networks:
- my-network
# 数据库服务
db:
image: mysql:8.0
ports:
- "3306:3306"
environment:
- MYSQL_ROOT_PASSWORD=password
- MYSQL_DATABASE=mydb
- MYSQL_CHARSET=utf8mb4
- MYSQL_COLLATION=utf8mb4_unicode_ci
volumes:
- mysql-data:/var/lib/mysql
- ./init.sql:/docker-entrypoint-initdb.d/init.sql
restart: always
networks:
- my-network
# 网络配置
networks:
my-network:
driver: bridge
# 数据卷配置
volumes:
mysql-data:
driver: local常用 Docker 命令:
# 构建镜像
docker build -t myapp:1.0.0 .
# 运行容器
docker run -d -p 8080:8080 --name myapp-container myapp:1.0.0
# 查看容器日志
docker logs -f myapp-container
# 进入容器
docker exec -it myapp-container /bin/sh
# 停止容器
docker stop myapp-container
# 删除容器
docker rm myapp-container
# 查看镜像
docker images
# 删除镜像
docker rmi myapp:1.0.0
# 使用 Docker Compose 启动服务
docker-compose up -d
# 停止 Docker Compose 服务
docker-compose down
# 查看 Docker Compose 日志
docker-compose logs -f# 构建镜像
docker build -t myapp:1.0.0 .
# 运行容器
docker run -d -p 8080:8080 --name myapp-container myapp:1.0.0
# 查看容器日志
docker logs -f myapp-container
# 进入容器
docker exec -it myapp-container /bin/sh
# 停止容器
docker stop myapp-container
# 删除容器
docker rm myapp-container
# 查看镜像
docker images
# 删除镜像
docker rmi myapp:1.0.0
# 使用 Docker Compose 启动服务
docker-compose up -d
# 停止 Docker Compose 服务
docker-compose down
# 查看 Docker Compose 日志
docker-compose logs -f4.2 Kubernetes
Kubernetes 是一个开源的容器编排平台,用于自动化部署、扩展和管理容器化应用程序。
核心概念:
- Pod:最小的部署单元,包含一个或多个容器
- Deployment:管理 Pod 的部署和更新
- Service:暴露 Pod 给其他服务或外部访问
- Ingress:管理外部访问
- ConfigMap:存储配置数据
- Secret:存储敏感数据
- Volume:持久化存储
- Namespace:资源隔离
Deployment 示例:
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-deployment
namespace: default
labels:
app: myapp
spec:
replicas: 3 # 副本数量
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: myapp:1.0.0
ports:
- containerPort: 8080
env:
- name: SPRING_PROFILES_ACTIVE
value: "prod"
- name: SPRING_DATASOURCE_URL
value: "jdbc:mysql://mysql-service:3306/mydb"
- name: SPRING_DATASOURCE_USERNAME
valueFrom:
secretKeyRef:
name: mysql-secret
key: username
- name: SPRING_DATASOURCE_PASSWORD
valueFrom:
secretKeyRef:
name: mysql-secret
key: password
resources:
requests:
memory: "512Mi"
cpu: "500m"
limits:
memory: "1Gi"
cpu: "1"apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-deployment
namespace: default
labels:
app: myapp
spec:
replicas: 3 # 副本数量
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: myapp:1.0.0
ports:
- containerPort: 8080
env:
- name: SPRING_PROFILES_ACTIVE
value: "prod"
- name: SPRING_DATASOURCE_URL
value: "jdbc:mysql://mysql-service:3306/mydb"
- name: SPRING_DATASOURCE_USERNAME
valueFrom:
secretKeyRef:
name: mysql-secret
key: username
- name: SPRING_DATASOURCE_PASSWORD
valueFrom:
secretKeyRef:
name: mysql-secret
key: password
resources:
requests:
memory: "512Mi"
cpu: "500m"
limits:
memory: "1Gi"
cpu: "1"Service 示例:
apiVersion: v1
kind: Service
metadata:
name: myapp-service
namespace: default
spec:
selector:
app: myapp
type: LoadBalancer # 暴露服务给外部
ports:
- port: 80
targetPort: 8080
protocol: TCPapiVersion: v1
kind: Service
metadata:
name: myapp-service
namespace: default
spec:
selector:
app: myapp
type: LoadBalancer # 暴露服务给外部
ports:
- port: 80
targetPort: 8080
protocol: TCPIngress 示例:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: myapp-ingress
namespace: default
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx
rules:
- host: myapp.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: myapp-service
port:
number: 80apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: myapp-ingress
namespace: default
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx
rules:
- host: myapp.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: myapp-service
port:
number: 80ConfigMap 示例:
apiVersion: v1
kind: ConfigMap
metadata:
name: myapp-config
namespace: default
data:
application.properties: |
spring.application.name=myapp
spring.profiles.active=prod
logging.level.root=INFO
logging.level.com.example=DEBUGapiVersion: v1
kind: ConfigMap
metadata:
name: myapp-config
namespace: default
data:
application.properties: |
spring.application.name=myapp
spring.profiles.active=prod
logging.level.root=INFO
logging.level.com.example=DEBUGSecret 示例:
apiVersion: v1
kind: Secret
metadata:
name: mysql-secret
namespace: default
type: Opaque
data:
username: cm9vdA== # base64 编码的 "root"
password: cGFzc3dvcmQ= # base64 编码的 "password"apiVersion: v1
kind: Secret
metadata:
name: mysql-secret
namespace: default
type: Opaque
data:
username: cm9vdA== # base64 编码的 "root"
password: cGFzc3dvcmQ= # base64 编码的 "password"常用 Kubernetes 命令:
# 查看所有 Pod
kubectl get pods -n default
# 查看 Deployment
kubectl get deployments -n default
# 查看 Service
kubectl get services -n default
# 查看 Ingress
kubectl get ingress -n default
# 查看 ConfigMap
kubectl get configmaps -n default
# 查看 Secret
kubectl get secrets -n default
# 应用配置
kubectl apply -f deployment.yaml
# 删除资源
kubectl delete -f deployment.yaml
# 查看 Pod 日志
kubectl logs -f myapp-deployment-xxx
# 进入 Pod
kubectl exec -it myapp-deployment-xxx -- /bin/sh
# 查看 Pod 描述
kubectl describe pod myapp-deployment-xxx
# 扩容 Deployment
kubectl scale deployment myapp-deployment --replicas=5
# 查看节点
kubectl get nodes
# 查看集群信息
kubectl cluster-info# 查看所有 Pod
kubectl get pods -n default
# 查看 Deployment
kubectl get deployments -n default
# 查看 Service
kubectl get services -n default
# 查看 Ingress
kubectl get ingress -n default
# 查看 ConfigMap
kubectl get configmaps -n default
# 查看 Secret
kubectl get secrets -n default
# 应用配置
kubectl apply -f deployment.yaml
# 删除资源
kubectl delete -f deployment.yaml
# 查看 Pod 日志
kubectl logs -f myapp-deployment-xxx
# 进入 Pod
kubectl exec -it myapp-deployment-xxx -- /bin/sh
# 查看 Pod 描述
kubectl describe pod myapp-deployment-xxx
# 扩容 Deployment
kubectl scale deployment myapp-deployment --replicas=5
# 查看节点
kubectl get nodes
# 查看集群信息
kubectl cluster-info5. 监控和日志
5.1 Spring Boot Actuator
Spring Boot Actuator 提供了生产就绪的特性,用于监控和管理 Spring Boot 应用。
添加依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency><dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>配置:
# 暴露所有端点
management.endpoints.web.exposure.include=*
# 暴露的健康检查详情
management.endpoint.health.show-details=always
# 配置健康检查路径
management.endpoints.web.base-path=/actuator
# 配置 Prometheus 端点
management.endpoint.prometheus.enabled=true# 暴露所有端点
management.endpoints.web.exposure.include=*
# 暴露的健康检查详情
management.endpoint.health.show-details=always
# 配置健康检查路径
management.endpoints.web.base-path=/actuator
# 配置 Prometheus 端点
management.endpoint.prometheus.enabled=true常用端点:
/actuator/health- 健康检查/actuator/info- 应用信息/actuator/metrics- 指标信息/actuator/prometheus- Prometheus 格式的指标/actuator/env- 环境变量/actuator/configprops- 配置属性/actuator/loggers- 日志配置/actuator/threaddump- 线程转储/actuator/heapdump- 堆转储
5.2 Prometheus 和 Grafana
Prometheus 是一个开源的监控系统,用于收集和存储指标数据。 Grafana 是一个开源的可视化平台,用于展示 Prometheus 收集的数据。
Docker Compose 配置:
version: '3.8'
services:
prometheus:
image: prom/prometheus:latest
ports:
- "9090:9090"
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
- prometheus-data:/prometheus
restart: always
grafana:
image: grafana/grafana:latest
ports:
- "3000:3000"
volumes:
- grafana-data:/var/lib/grafana
environment:
- GF_SECURITY_ADMIN_USER=admin
- GF_SECURITY_ADMIN_PASSWORD=admin123
restart: always
depends_on:
- prometheus
volumes:
prometheus-data:
grafana-data:version: '3.8'
services:
prometheus:
image: prom/prometheus:latest
ports:
- "9090:9090"
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
- prometheus-data:/prometheus
restart: always
grafana:
image: grafana/grafana:latest
ports:
- "3000:3000"
volumes:
- grafana-data:/var/lib/grafana
environment:
- GF_SECURITY_ADMIN_USER=admin
- GF_SECURITY_ADMIN_PASSWORD=admin123
restart: always
depends_on:
- prometheus
volumes:
prometheus-data:
grafana-data:Prometheus 配置文件:
global:
scrape_interval: 15s
evaluation_interval: 15s
rule_files:
# - "first_rules.yml"
# - "second_rules.yml"
scrape_configs:
- job_name: 'spring-actuator'
metrics_path: '/actuator/prometheus'
scrape_interval: 5s
static_configs:
- targets: ['host.docker.internal:8080'] # 应用地址global:
scrape_interval: 15s
evaluation_interval: 15s
rule_files:
# - "first_rules.yml"
# - "second_rules.yml"
scrape_configs:
- job_name: 'spring-actuator'
metrics_path: '/actuator/prometheus'
scrape_interval: 5s
static_configs:
- targets: ['host.docker.internal:8080'] # 应用地址5.3 ELK Stack
ELK Stack 是 Elasticsearch、Logstash 和 Kibana 的组合,用于日志收集、存储和分析。
Docker Compose 配置:
version: '3.8'
services:
# Elasticsearch 服务
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:8.8.0
ports:
- "9200:9200"
- "9300:9300"
environment:
- discovery.type=single-node
- ES_JAVA_OPTS=-Xms512m -Xmx512m
- ELASTIC_PASSWORD=password
- xpack.security.enabled=true
- xpack.security.http.ssl.enabled=false
volumes:
- es-data:/usr/share/elasticsearch/data
restart: always
# Logstash 服务
logstash:
image: docker.elastic.co/logstash/logstash:8.8.0
ports:
- "5044:5044"
- "9600:9600"
volumes:
- ./logstash.conf:/usr/share/logstash/pipeline/logstash.conf
environment:
- LS_JAVA_OPTS=-Xms256m -Xmx256m
depends_on:
- elasticsearch
restart: always
# Kibana 服务
kibana:
image: docker.elastic.co/kibana/kibana:8.8.0
ports:
- "5601:5601"
environment:
- ELASTICSEARCH_HOSTS=http://elasticsearch:9200
- ELASTICSEARCH_USERNAME=elastic
- ELASTICSEARCH_PASSWORD=password
depends_on:
- elasticsearch
restart: always
# Filebeat 服务(可选,用于收集日志)
filebeat:
image: docker.elastic.co/beats/filebeat:8.8.0
volumes:
- ./filebeat.yml:/usr/share/filebeat/filebeat.yml
- /var/lib/docker/containers:/var/lib/docker/containers:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
depends_on:
- logstash
restart: always
volumes:
es-data:
driver: localversion: '3.8'
services:
# Elasticsearch 服务
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:8.8.0
ports:
- "9200:9200"
- "9300:9300"
environment:
- discovery.type=single-node
- ES_JAVA_OPTS=-Xms512m -Xmx512m
- ELASTIC_PASSWORD=password
- xpack.security.enabled=true
- xpack.security.http.ssl.enabled=false
volumes:
- es-data:/usr/share/elasticsearch/data
restart: always
# Logstash 服务
logstash:
image: docker.elastic.co/logstash/logstash:8.8.0
ports:
- "5044:5044"
- "9600:9600"
volumes:
- ./logstash.conf:/usr/share/logstash/pipeline/logstash.conf
environment:
- LS_JAVA_OPTS=-Xms256m -Xmx256m
depends_on:
- elasticsearch
restart: always
# Kibana 服务
kibana:
image: docker.elastic.co/kibana/kibana:8.8.0
ports:
- "5601:5601"
environment:
- ELASTICSEARCH_HOSTS=http://elasticsearch:9200
- ELASTICSEARCH_USERNAME=elastic
- ELASTICSEARCH_PASSWORD=password
depends_on:
- elasticsearch
restart: always
# Filebeat 服务(可选,用于收集日志)
filebeat:
image: docker.elastic.co/beats/filebeat:8.8.0
volumes:
- ./filebeat.yml:/usr/share/filebeat/filebeat.yml
- /var/lib/docker/containers:/var/lib/docker/containers:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
depends_on:
- logstash
restart: always
volumes:
es-data:
driver: local6. 开发工具
6.1 IDE
IntelliJ IDEA:
- 功能强大的 Java IDE
- 支持 Spring Boot、Maven、Gradle 等
- 内置代码检查和重构工具
- 支持 Docker 和 Kubernetes
- 强大的调试功能
Eclipse:
- 开源的 Java IDE
- 支持多种插件
- 适合大型项目
- 支持团队协作
VS Code:
- 轻量级的代码编辑器
- 支持 Java 插件
- 跨平台
- 支持多种语言
6.2 其他工具
Postman:用于测试 API Swagger/OpenAPI:用于 API 文档生成 Lombok:简化 Java 代码,减少样板代码 MapStruct:用于对象映射 DBeaver:数据库管理工具 Git:版本控制工具
7. 总结
Java 生态系统非常丰富,提供了从开发到部署的全方位支持。本文涵盖了:
- 构建工具:Maven 和 Gradle,用于管理依赖和构建项目
- 测试框架:JUnit 5、Mockito 和 Spring Boot Test,用于编写和执行测试
- 代码质量工具:SonarQube、Checkstyle 和 PMD,用于保证代码质量
- 部署工具:Docker 和 Kubernetes,用于容器化和编排
- 监控和日志:Spring Boot Actuator、Prometheus、Grafana 和 ELK Stack,用于监控和日志管理
- 开发工具:IDE 和其他辅助工具,用于提高开发效率
掌握这些工具和技术,将有助于开发高质量、可维护的 Java 应用程序。随着技术的不断发展,Java 生态系统也在不断演进,开发者需要持续学习,跟上最新的技术趋势。
Cao Note