Java 开发指南

环境准备

Java 版本要求

推荐使用 Java 17 LTS 或更高版本以获得最新的语言特性和性能优化。

# 检查当前 Java 版本
java -version
javac -version

# 推荐使用 SDKMAN 管理 Java 版本
curl -s "https://get.sdkman.io" | bash
source "$HOME/.sdkman/bin/sdkman-init.sh"

# 安装和使用 Java 17
sdk install java 17.0.8-tem
sdk use java 17.0.8-tem
sdk default java 17.0.8-tem

构建工具配置

Maven 配置

推荐的 pom.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>com.example</groupId>
    <artifactId>java-project</artifactId>
    <version>1.0.0</version>
    <packaging>jar</packaging>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        
        <!-- 依赖版本 -->
        <spring.boot.version>3.2.0</spring.boot.version>
        <junit.version>5.10.0</junit.version>
        <mockito.version>5.5.0</mockito.version>
        <slf4j.version>2.0.9</slf4j.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 Starter -->
        <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-validation</artifactId>
        </dependency>

        <!-- 测试依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>${spring.boot.version}</version>
            </plugin>
            
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.11.0</version>
                <configuration>
                    <source>17</source>
                    <target>17</target>
                    <compilerArgs>
                        <arg>--enable-preview</arg>
                    </compilerArgs>
                </configuration>
            </plugin>
            
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>3.1.2</version>
                <configuration>
                    <argLine>--enable-preview</argLine>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

Gradle 配置

推荐的 build.gradle 配置:

plugins {
    id 'java'
    id 'org.springframework.boot' version '3.2.0'
    id 'io.spring.dependency-management' version '1.1.4'
    id 'com.diffplug.spotless' version '6.22.0'
}

group = 'com.example'
version = '1.0.0'

java {
    sourceCompatibility = JavaVersion.VERSION_17
    targetCompatibility = JavaVersion.VERSION_17
}

configurations {
    compileOnly {
        extendsFrom annotationProcessor
    }
}

repositories {
    mavenCentral()
}

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-validation'
    implementation 'org.springframework.boot:spring-boot-starter-security'
    
    // 数据库
    runtimeOnly 'com.h2database:h2'
    runtimeOnly 'org.postgresql:postgresql'
    
    // 工具库
    compileOnly 'org.projectlombok:lombok'
    annotationProcessor 'org.projectlombok:lombok'
    
    // 测试
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    testImplementation 'org.springframework.security:spring-security-test'
}

tasks.named('test') {
    useJUnitPlatform()
    jvmArgs '--enable-preview'
}

tasks.named('compileJava') {
    options.compilerArgs += '--enable-preview'
}

// 代码格式化
spotless {
    java {
        googleJavaFormat('1.17.0')
        removeUnusedImports()
        trimTrailingWhitespace()
        endWithNewline()
    }
}

开发工具和扩展

在 Kiro 中推荐安装以下扩展:

核心扩展

Java 开发必备:
  - Extension Pack for Java: Java 开发工具包
  - Spring Boot Extension Pack: Spring 开发支持
  - Maven for Java: Maven 项目管理
  - Gradle for Java: Gradle 构建支持

代码质量:
  - SonarLint: 代码质量检查
  - Checkstyle: 代码风格检查
  - SpotBugs: 静态代码分析
  - Error Prone: Google 错误检测

测试工具:
  - Java Test Runner: 测试执行
  - Coverage Gutters: 代码覆盖率显示
  - JUnit Test Explorer: JUnit 测试管理

现代 Java 特性应用

Java 17+ 新特性

Record Classes

// 使用 Record 简化数据类
public record User(Long id, String name, String email, LocalDateTime createdAt) {
    // 自定义构造器
    public User {
        if (name == null || name.isBlank()) {
            throw new IllegalArgumentException("Name cannot be null or blank");
        }
        if (email == null || !email.contains("@")) {
            throw new IllegalArgumentException("Invalid email format");
        }
    }
    
    // 自定义方法
    public String getDisplayName() {
        return name.toUpperCase();
    }
    
    // 静态工厂方法
    public static User createNew(String name, String email) {
        return new User(null, name, email, LocalDateTime.now());
    }
}

// 在 Spring Boot 中使用
@RestController
public class UserController {
    
    @PostMapping("/users")
    public ResponseEntity<User> createUser(@RequestBody CreateUserRequest request) {
        User user = User.createNew(request.name(), request.email());
        // 保存用户逻辑
        return ResponseEntity.ok(user);
    }
}

public record CreateUserRequest(String name, String email) {}

Sealed Classes

// 密封类用于限制继承层次
public sealed class PaymentMethod 
    permits CreditCard, BankTransfer, DigitalWallet {
    
    public abstract String getPaymentType();
    public abstract boolean isSecure();
}

public final class CreditCard extends PaymentMethod {
    private final String cardNumber;
    private final String expiryDate;
    
    public CreditCard(String cardNumber, String expiryDate) {
        this.cardNumber = cardNumber;
        this.expiryDate = expiryDate;
    }
    
    @Override
    public String getPaymentType() {
        return "CREDIT_CARD";
    }
    
    @Override
    public boolean isSecure() {
        return true;
    }
}

public final class BankTransfer extends PaymentMethod {
    private final String accountNumber;
    private final String routingNumber;
    
    public BankTransfer(String accountNumber, String routingNumber) {
        this.accountNumber = accountNumber;
        this.routingNumber = routingNumber;
    }
    
    @Override
    public String getPaymentType() {
        return "BANK_TRANSFER";
    }
    
    @Override
    public boolean isSecure() {
        return true;
    }
}

public final class DigitalWallet extends PaymentMethod {
    private final String walletId;
    private final String provider;
    
    public DigitalWallet(String walletId, String provider) {
        this.walletId = walletId;
        this.provider = provider;
    }
    
    @Override
    public String getPaymentType() {
        return "DIGITAL_WALLET";
    }
    
    @Override
    public boolean isSecure() {
        return "TRUSTED_PROVIDER".equals(provider);
    }
}

// 使用 switch 表达式处理密封类
public class PaymentProcessor {
    
    public String processPayment(PaymentMethod method, double amount) {
        return switch (method) {
            case CreditCard cc -> processCreditCard(cc, amount);
            case BankTransfer bt -> processBankTransfer(bt, amount);
            case DigitalWallet dw -> processDigitalWallet(dw, amount);
        };
    }
    
    private String processCreditCard(CreditCard card, double amount) {
        return "Processing $%.2f via credit card".formatted(amount);
    }
    
    private String processBankTransfer(BankTransfer transfer, double amount) {
        return "Processing $%.2f via bank transfer".formatted(amount);
    }
    
    private String processDigitalWallet(DigitalWallet wallet, double amount) {
        return "Processing $%.2f via digital wallet".formatted(amount);
    }
}

Pattern Matching

// 增强的 instanceof
public class ShapeProcessor {
    
    public double calculateArea(Object shape) {
        if (shape instanceof Rectangle rect) {
            return rect.width() * rect.height();
        } else if (shape instanceof Circle circle) {
            return Math.PI * circle.radius() * circle.radius();
        } else if (shape instanceof Triangle triangle) {
            double s = (triangle.a() + triangle.b() + triangle.c()) / 2;
            return Math.sqrt(s * (s - triangle.a()) * (s - triangle.b()) * (s - triangle.c()));
        }
        throw new IllegalArgumentException("Unknown shape: " + shape);
    }
    
    // 使用 switch 表达式的模式匹配
    public String getShapeDescription(Object shape) {
        return switch (shape) {
            case Rectangle rect -> "Rectangle: %.1f x %.1f".formatted(rect.width(), rect.height());
            case Circle circle -> "Circle: radius %.1f".formatted(circle.radius());
            case Triangle triangle -> "Triangle: sides %.1f, %.1f, %.1f"
                .formatted(triangle.a(), triangle.b(), triangle.c());
            case null -> "No shape provided";
            default -> "Unknown shape: " + shape.getClass().getSimpleName();
        };
    }
}

public record Rectangle(double width, double height) {}
public record Circle(double radius) {}
public record Triangle(double a, double b, double c) {}

Text Blocks

public class SqlQueryBuilder {
    
    public static final String COMPLEX_QUERY = """
        SELECT u.id, u.name, u.email, p.title, p.content, p.created_at
        FROM users u
        INNER JOIN posts p ON u.id = p.user_id
        WHERE u.active = true
          AND p.published = true
          AND p.created_at >= ?
        ORDER BY p.created_at DESC
        LIMIT ?
        """;
    
    public static final String JSON_TEMPLATE = """
        {
            "user": {
                "id": %d,
                "name": "%s",
                "email": "%s"
            },
            "preferences": {
                "theme": "dark",
                "notifications": true
            }
        }
        """;
    
    public String generateUserJson(Long id, String name, String email) {
        return JSON_TEMPLATE.formatted(id, name, email);
    }
}

Spring Boot 应用开发

项目结构最佳实践

src/
├── main/
│   ├── java/
│   │   └── com/example/myapp/
│   │       ├── MyAppApplication.java
│   │       ├── config/
│   │       │   ├── SecurityConfig.java
│   │       │   ├── DatabaseConfig.java
│   │       │   └── CacheConfig.java
│   │       ├── controller/
│   │       │   ├── UserController.java
│   │       │   ├── ProductController.java
│   │       │   └── advice/
│   │       │       └── GlobalExceptionHandler.java
│   │       ├── service/
│   │       │   ├── UserService.java
│   │       │   ├── ProductService.java
│   │       │   └── impl/
│   │       │       ├── UserServiceImpl.java
│   │       │       └── ProductServiceImpl.java
│   │       ├── repository/
│   │       │   ├── UserRepository.java
│   │       │   └── ProductRepository.java
│   │       ├── model/
│   │       │   ├── entity/
│   │       │   │   ├── User.java
│   │       │   │   └── Product.java
│   │       │   ├── dto/
│   │       │   │   ├── UserDto.java
│   │       │   │   └── ProductDto.java
│   │       │   └── request/
│   │       │       ├── CreateUserRequest.java
│   │       │       └── UpdateUserRequest.java
│   │       ├── exception/
│   │       │   ├── UserNotFoundException.java
│   │       │   └── BusinessException.java
│   │       └── util/
│   │           ├── DateUtils.java
│   │           └── ValidationUtils.java
│   └── resources/
│       ├── application.yml
│       ├── application-dev.yml
│       ├── application-prod.yml
│       └── db/migration/
│           └── V1__Initial_schema.sql
└── test/
    └── java/
        └── com/example/myapp/
            ├── controller/
            ├── service/
            ├── repository/
            └── integration/

Spring Boot 配置

application.yml 配置

spring:
  application:
    name: my-java-app
  
  profiles:
    active: dev
  
  datasource:
    url: jdbc:postgresql://localhost:5432/myapp
    username: ${DB_USERNAME:postgres}
    password: ${DB_PASSWORD:password}
    hikari:
      maximum-pool-size: 20
      minimum-idle: 5
      connection-timeout: 30000
      idle-timeout: 600000
      max-lifetime: 1800000
  
  jpa:
    hibernate:
      ddl-auto: validate
    show-sql: false
    properties:
      hibernate:
        dialect: org.hibernate.dialect.PostgreSQLDialect
        format_sql: true
        use_sql_comments: true
        jdbc:
          batch_size: 25
          order_inserts: true
          order_updates: true
  
  cache:
    type: redis
    redis:
      time-to-live: 3600s
  
  data:
    redis:
      host: localhost
      port: 6379
      timeout: 2s
      lettuce:
        pool:
          max-active: 8
          max-idle: 8
          min-idle: 0

server:
  port: 8080
  servlet:
    context-path: /api
  compression:
    enabled: true
    mime-types: application/json,application/xml,text/html,text/xml,text/plain

management:
  endpoints:
    web:
      exposure:
        include: health,info,metrics,prometheus
  endpoint:
    health:
      show-details: when_authorized
  metrics:
    export:
      prometheus:
        enabled: true

logging:
  level:
    com.example.myapp: INFO
    org.springframework.security: DEBUG
    org.hibernate.SQL: DEBUG
    org.hibernate.type.descriptor.sql.BasicBinder: TRACE
  pattern:
    console: "%d{yyyy-MM-dd HH:mm:ss} - %msg%n"
    file: "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n"
  file:
    name: logs/application.log
    max-size: 10MB
    max-history: 30

实体和 Repository 设计

实体类设计

@Entity
@Table(name = "users")
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class User {
    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    @Column(name = "username", unique = true, nullable = false, length = 50)
    private String username;
    
    @Column(name = "email", unique = true, nullable = false, length = 100)
    @Email
    private String email;
    
    @Column(name = "password", nullable = false)
    private String password;
    
    @Column(name = "first_name", length = 50)
    private String firstName;
    
    @Column(name = "last_name", length = 50)
    private String lastName;
    
    @Enumerated(EnumType.STRING)
    @Column(name = "status", nullable = false)
    private UserStatus status;
    
    @CreationTimestamp
    @Column(name = "created_at", nullable = false, updatable = false)
    private LocalDateTime createdAt;
    
    @UpdateTimestamp
    @Column(name = "updated_at")
    private LocalDateTime updatedAt;
    
    @Version
    private Long version;
    
    @OneToMany(mappedBy = "user", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    private List<Post> posts = new ArrayList<>();
    
    // 自定义方法
    public String getFullName() {
        return String.format("%s %s", firstName, lastName).trim();
    }
    
    public boolean isActive() {
        return UserStatus.ACTIVE.equals(status);
    }
}

public enum UserStatus {
    ACTIVE,
    INACTIVE,
    SUSPENDED,
    DELETED
}

Repository 接口

@Repository
public interface UserRepository extends JpaRepository<User, Long>, JpaSpecificationExecutor<User> {
    
    Optional<User> findByUsername(String username);
    
    Optional<User> findByEmail(String email);
    
    List<User> findByStatus(UserStatus status);
    
    Page<User> findByStatusAndCreatedAtAfter(UserStatus status, LocalDateTime createdAt, Pageable pageable);
    
    @Query("SELECT u FROM User u WHERE u.firstName LIKE %:name% OR u.lastName LIKE %:name%")
    List<User> findByNameContaining(@Param("name") String name);
    
    @Query(value = "SELECT * FROM users WHERE created_at > :date AND status = :status", nativeQuery = true)
    List<User> findRecentActiveUsers(@Param("date") LocalDateTime date, @Param("status") String status);
    
    @Modifying
    @Query("UPDATE User u SET u.status = :status WHERE u.id IN :ids")
    void updateUserStatus(@Param("ids") List<Long> ids, @Param("status") UserStatus status);
    
    // 使用 Specification 进行动态查询
    static Specification<User> hasStatus(UserStatus status) {
        return (root, query, cb) -> cb.equal(root.get("status"), status);
    }
    
    static Specification<User> createdAfter(LocalDateTime date) {
        return (root, query, cb) -> cb.greaterThan(root.get("createdAt"), date);
    }
    
    static Specification<User> nameContains(String name) {
        return (root, query, cb) -> {
            if (name == null || name.trim().isEmpty()) {
                return cb.conjunction();
            }
            String pattern = "%" + name.toLowerCase() + "%";
            return cb.or(
                cb.like(cb.lower(root.get("firstName")), pattern),
                cb.like(cb.lower(root.get("lastName")), pattern)
            );
        };
    }
}

Service 层设计

@Service
@Transactional(readOnly = true)
@Slf4j
public class UserServiceImpl implements UserService {
    
    private final UserRepository userRepository;
    private final PasswordEncoder passwordEncoder;
    private final UserMapper userMapper;
    private final ApplicationEventPublisher eventPublisher;
    
    public UserServiceImpl(UserRepository userRepository, 
                          PasswordEncoder passwordEncoder,
                          UserMapper userMapper,
                          ApplicationEventPublisher eventPublisher) {
        this.userRepository = userRepository;
        this.passwordEncoder = passwordEncoder;
        this.userMapper = userMapper;
        this.eventPublisher = eventPublisher;
    }
    
    @Override
    @Transactional
    public UserDto createUser(CreateUserRequest request) {
        log.info("Creating new user with username: {}", request.username());
        
        // 验证用户名和邮箱唯一性
        validateUserUniqueness(request.username(), request.email());
        
        // 创建用户实体
        User user = User.builder()
            .username(request.username())
            .email(request.email())
            .password(passwordEncoder.encode(request.password()))
            .firstName(request.firstName())
            .lastName(request.lastName())
            .status(UserStatus.ACTIVE)
            .build();
        
        // 保存用户
        User savedUser = userRepository.save(user);
        
        // 发布用户创建事件
        eventPublisher.publishEvent(new UserCreatedEvent(savedUser.getId()));
        
        log.info("User created successfully with ID: {}", savedUser.getId());
        return userMapper.toDto(savedUser);
    }
    
    @Override
    public Optional<UserDto> findByUsername(String username) {
        return userRepository.findByUsername(username)
            .map(userMapper::toDto);
    }
    
    @Override
    public Page<UserDto> findUsers(UserSearchCriteria criteria, Pageable pageable) {
        Specification<User> spec = buildSpecification(criteria);
        Page<User> users = userRepository.findAll(spec, pageable);
        return users.map(userMapper::toDto);
    }
    
    @Override
    @Transactional
    public UserDto updateUser(Long userId, UpdateUserRequest request) {
        User user = userRepository.findById(userId)
            .orElseThrow(() -> new UserNotFoundException("User not found with ID: " + userId));
        
        // 更新用户信息
        updateUserFields(user, request);
        
        User updatedUser = userRepository.save(user);
        
        log.info("User updated successfully: {}", userId);
        return userMapper.toDto(updatedUser);
    }
    
    @Override
    @Transactional
    public void deleteUser(Long userId) {
        User user = userRepository.findById(userId)
            .orElseThrow(() -> new UserNotFoundException("User not found with ID: " + userId));
        
        user.setStatus(UserStatus.DELETED);
        userRepository.save(user);
        
        eventPublisher.publishEvent(new UserDeletedEvent(userId));
        log.info("User marked as deleted: {}", userId);
    }
    
    private void validateUserUniqueness(String username, String email) {
        if (userRepository.findByUsername(username).isPresent()) {
            throw new BusinessException("Username already exists: " + username);
        }
        if (userRepository.findByEmail(email).isPresent()) {
            throw new BusinessException("Email already exists: " + email);
        }
    }
    
    private Specification<User> buildSpecification(UserSearchCriteria criteria) {
        return Specification.where(UserRepository.hasStatus(criteria.status()))
            .and(UserRepository.nameContains(criteria.name()))
            .and(UserRepository.createdAfter(criteria.createdAfter()));
    }
    
    private void updateUserFields(User user, UpdateUserRequest request) {
        if (request.firstName() != null) {
            user.setFirstName(request.firstName());
        }
        if (request.lastName() != null) {
            user.setLastName(request.lastName());
        }
        if (request.email() != null && !request.email().equals(user.getEmail())) {
            if (userRepository.findByEmail(request.email()).isPresent()) {
                throw new BusinessException("Email already exists: " + request.email());
            }
            user.setEmail(request.email());
        }
    }
}

// 事件类
public record UserCreatedEvent(Long userId) {}
public record UserDeletedEvent(Long userId) {}

// 搜索条件
public record UserSearchCriteria(
    UserStatus status,
    String name,
    LocalDateTime createdAfter
) {}

控制器设计

@RestController
@RequestMapping("/users")
@Validated
@Slf4j
public class UserController {
    
    private final UserService userService;
    
    public UserController(UserService userService) {
        this.userService = userService;
    }
    
    @PostMapping
    @ResponseStatus(HttpStatus.CREATED)
    public ResponseEntity<ApiResponse<UserDto>> createUser(
            @Valid @RequestBody CreateUserRequest request) {
        
        UserDto user = userService.createUser(request);
        
        return ResponseEntity.status(HttpStatus.CREATED)
            .body(ApiResponse.success("User created successfully", user));
    }
    
    @GetMapping("/{id}")
    public ResponseEntity<ApiResponse<UserDto>> getUser(@PathVariable Long id) {
        UserDto user = userService.findById(id)
            .orElseThrow(() -> new UserNotFoundException("User not found with ID: " + id));
        
        return ResponseEntity.ok(ApiResponse.success(user));
    }
    
    @GetMapping
    public ResponseEntity<ApiResponse<Page<UserDto>>> getUsers(
            @RequestParam(required = false) UserStatus status,
            @RequestParam(required = false) String name,
            @RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime createdAfter,
            @PageableDefault(size = 20, sort = "createdAt", direction = Sort.Direction.DESC) Pageable pageable) {
        
        UserSearchCriteria criteria = new UserSearchCriteria(status, name, createdAfter);
        Page<UserDto> users = userService.findUsers(criteria, pageable);
        
        return ResponseEntity.ok(ApiResponse.success(users));
    }
    
    @PutMapping("/{id}")
    public ResponseEntity<ApiResponse<UserDto>> updateUser(
            @PathVariable Long id,
            @Valid @RequestBody UpdateUserRequest request) {
        
        UserDto user = userService.updateUser(id, request);
        
        return ResponseEntity.ok(ApiResponse.success("User updated successfully", user));
    }
    
    @DeleteMapping("/{id}")
    @ResponseStatus(HttpStatus.NO_CONTENT)
    public ResponseEntity<Void> deleteUser(@PathVariable Long id) {
        userService.deleteUser(id);
        return ResponseEntity.noContent().build();
    }
}

// 通用 API 响应格式
public record ApiResponse<T>(
    boolean success,
    String message,
    T data,
    LocalDateTime timestamp
) {
    public static <T> ApiResponse<T> success(T data) {
        return new ApiResponse<>(true, "Success", data, LocalDateTime.now());
    }
    
    public static <T> ApiResponse<T> success(String message, T data) {
        return new ApiResponse<>(true, message, data, LocalDateTime.now());
    }
    
    public static <T> ApiResponse<T> error(String message) {
        return new ApiResponse<>(false, message, null, LocalDateTime.now());
    }
}

Kiro 核心功能应用

智能代码分析

Kiro 可以分析 Java 代码并提供优化建议:

// Kiro 会建议的代码改进示例

// 原始代码 - 存在性能和可读性问题
public class OrderProcessor {
    
    public List<Order> processOrders(List<Order> orders) {
        List<Order> result = new ArrayList<>();
        for (Order order : orders) {
            if (order.getStatus().equals("PENDING")) {
                order.setStatus("PROCESSING");
                calculateTotal(order);
                validateOrder(order);
                if (order.isValid()) {
                    result.add(order);
                }
            }
        }
        return result;
    }
    
    private void calculateTotal(Order order) {
        double total = 0;
        for (OrderItem item : order.getItems()) {
            total += item.getPrice() * item.getQuantity();
        }
        order.setTotal(total);
    }
}

// Kiro 建议的改进版本
@Service
@Slf4j
public class OrderProcessor {
    
    private final OrderValidator orderValidator;
    private final OrderCalculationService calculationService;
    
    public OrderProcessor(OrderValidator orderValidator, 
                         OrderCalculationService calculationService) {
        this.orderValidator = orderValidator;
        this.calculationService = calculationService;
    }
    
    public List<Order> processOrders(List<Order> orders) {
        if (orders == null || orders.isEmpty()) {
            return Collections.emptyList();
        }
        
        return orders.parallelStream()
            .filter(order -> OrderStatus.PENDING.equals(order.getStatus()))
            .peek(order -> order.setStatus(OrderStatus.PROCESSING))
            .peek(calculationService::calculateTotal)
            .filter(orderValidator::validateOrder)
            .collect(Collectors.toList());
    }
}

@Component
public class OrderCalculationService {
    
    public void calculateTotal(Order order) {
        BigDecimal total = order.getItems().stream()
            .map(item -> item.getPrice().multiply(BigDecimal.valueOf(item.getQuantity())))
            .reduce(BigDecimal.ZERO, BigDecimal::add);
        
        order.setTotal(total);
    }
}

// 使用枚举替代字符串常量
public enum OrderStatus {
    PENDING,
    PROCESSING,
    COMPLETED,
    CANCELLED
}

代理钩子配置

配置针对 Java 项目的自动化钩子:

Maven 项目管理钩子

name: "Maven 依赖检查"
trigger: onSave
filePattern: "pom.xml"
instructions: |
  检查 Maven 项目的依赖和配置:
  
  1. 运行 `mvn dependency:analyze` 检查未使用的依赖
  2. 运行 `mvn versions:display-dependency-updates` 检查依赖更新
  3. 检查安全漏洞 `mvn org.owasp:dependency-check-maven:check`
  4. 验证 Java 版本兼容性
  5. 提供优化建议和安全更新计划

代码质量检查钩子

name: "Java 代码质量检查"
trigger: onSave
filePattern: "src/**/*.java"
instructions: |
  执行全面的 Java 代码质量检查:
  
  1. 运行 Checkstyle 检查代码风格
  2. 使用 SpotBugs 进行静态代码分析
  3. 运行 PMD 检查代码质量
  4. 检查单元测试覆盖率
  5. 验证 Javadoc 文档完整性
  6. 提供具体的改进建议

Spring Boot 配置检查钩子

name: "Spring Boot 配置验证"
trigger: onSave
filePattern: "src/main/resources/application*.yml"
instructions: |
  验证 Spring Boot 配置:
  
  1. 检查配置属性的正确性
  2. 验证数据库连接配置
  3. 检查安全配置最佳实践
  4. 验证生产环境配置
  5. 提供性能优化建议

测试生成钩子

name: "JUnit 测试生成器"
trigger: onSave
filePattern: "src/main/java/**/*.java"
instructions: |
  为新的或修改的 Java 类生成 JUnit 测试:
  
  1. 分析类的公共方法和业务逻辑
  2. 生成基本的单元测试用例
  3. 包含边界条件和异常情况测试
  4. 添加模拟对象测试(使用 Mockito)
  5. 确保测试覆盖主要代码路径
  6. 遵循 AAA 模式(Arrange, Act, Assert)

测试策略

JUnit 5 测试配置

// 基础测试类配置
@ExtendWith(MockitoExtension.class)
class UserServiceTest {
    
    @Mock
    private UserRepository userRepository;
    
    @Mock
    private PasswordEncoder passwordEncoder;
    
    @Mock
    private UserMapper userMapper;
    
    @Mock
    private ApplicationEventPublisher eventPublisher;
    
    @InjectMocks
    private UserServiceImpl userService;
    
    @Test
    @DisplayName("应该成功创建新用户")
    void shouldCreateUserSuccessfully() {
        // Given
        CreateUserRequest request = new CreateUserRequest(
            "testuser", "test@example.com", "password123", "John", "Doe"
        );
        
        User user = User.builder()
            .id(1L)
            .username("testuser")
            .email("test@example.com")
            .build();
        
        UserDto expectedDto = new UserDto(1L, "testuser", "test@example.com", "John", "Doe");
        
        when(userRepository.findByUsername("testuser")).thenReturn(Optional.empty());
        when(userRepository.findByEmail("test@example.com")).thenReturn(Optional.empty());
        when(passwordEncoder.encode("password123")).thenReturn("encodedPassword");
        when(userRepository.save(any(User.class))).thenReturn(user);
        when(userMapper.toDto(user)).thenReturn(expectedDto);
        
        // When
        UserDto result = userService.createUser(request);
        
        // Then
        assertThat(result).isNotNull();
        assertThat(result.username()).isEqualTo("testuser");
        assertThat(result.email()).isEqualTo("test@example.com");
        
        verify(userRepository).save(any(User.class));
        verify(eventPublisher).publishEvent(any(UserCreatedEvent.class));
    }
    
    @Test
    @DisplayName("用户名重复时应该抛出异常")
    void shouldThrowExceptionWhenUsernameExists() {
        // Given
        CreateUserRequest request = new CreateUserRequest(
            "existinguser", "test@example.com", "password123", "John", "Doe"
        );
        
        when(userRepository.findByUsername("existinguser"))
            .thenReturn(Optional.of(new User()));
        
        // When & Then
        assertThatThrownBy(() -> userService.createUser(request))
            .isInstanceOf(BusinessException.class)
            .hasMessageContaining("Username already exists");
        
        verify(userRepository, never()).save(any(User.class));
    }
    
    @ParameterizedTest
    @ValueSource(strings = {"", " ", "a", "ab"})
    @DisplayName("用户名长度不足时应该失败")
    void shouldFailWithInvalidUsernameLength(String username) {
        CreateUserRequest request = new CreateUserRequest(
            username, "test@example.com", "password123", "John", "Doe"
        );
        
        assertThatThrownBy(() -> userService.createUser(request))
            .isInstanceOf(ValidationException.class);
    }
}

集成测试

@SpringBootTest
@Testcontainers
@Transactional
class UserControllerIntegrationTest {
    
    @Container
    static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:15")
            .withDatabaseName("testdb")
            .withUsername("test")
            .withPassword("test");
    
    @Autowired
    private TestRestTemplate restTemplate;
    
    @Autowired
    private UserRepository userRepository;
    
    @DynamicPropertySource
    static void configureProperties(DynamicPropertyRegistry registry) {
        registry.add("spring.datasource.url", postgres::getJdbcUrl);
        registry.add("spring.datasource.username", postgres::getUsername);
        registry.add("spring.datasource.password", postgres::getPassword);
    }
    
    @Test
    @DisplayName("POST /users 应该创建新用户")
    void shouldCreateNewUser() {
        // Given
        CreateUserRequest request = new CreateUserRequest(
            "newuser", "new@example.com", "password123", "New", "User"
        );
        
        // When
        ResponseEntity<ApiResponse> response = restTemplate.postForEntity(
            "/users", request, ApiResponse.class
        );
        
        // Then
        assertThat(response.getStatusCode()).isEqualTo(HttpStatus.CREATED);
        assertThat(response.getBody().success()).isTrue();
        
        Optional<User> savedUser = userRepository.findByUsername("newuser");
        assertThat(savedUser).isPresent();
        assertThat(savedUser.get().getEmail()).isEqualTo("new@example.com");
    }
    
    @Test
    @DisplayName("GET /users 应该返回分页的用户列表")
    void shouldReturnPagedUsers() {
        // Given
        createTestUsers();
        
        // When
        ResponseEntity<String> response = restTemplate.getForEntity(
            "/users?size=10&page=0", String.class
        );
        
        // Then
        assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
        // 进一步的 JSON 解析和验证
    }
    
    private void createTestUsers() {
        for (int i = 1; i <= 15; i++) {
            User user = User.builder()
                .username("user" + i)
                .email("user" + i + "@example.com")
                .firstName("User")
                .lastName(String.valueOf(i))
                .status(UserStatus.ACTIVE)
                .build();
            userRepository.save(user);
        }
    }
}

性能优化

JVM 调优

# 生产环境 JVM 参数推荐
java -XX:+UseG1GC \
     -XX:MaxGCPauseMillis=200 \
     -XX:G1HeapRegionSize=16m \
     -XX:+UseStringDeduplication \
     -XX:+OptimizeStringConcat \
     -XX:+UseCompressedOops \
     -Xms2g \
     -Xmx4g \
     -XX:MetaspaceSize=256m \
     -XX:MaxMetaspaceSize=512m \
     -XX:+HeapDumpOnOutOfMemoryError \
     -XX:HeapDumpPath=/var/log/heapdump.hprof \
     -XX:+PrintGCDetails \
     -XX:+PrintGCTimeStamps \
     -Xloggc:/var/log/gc.log \
     -jar myapp.jar

数据库优化

// 批量操作优化
@Repository
public class OptimizedUserRepository {
    
    @PersistenceContext
    private EntityManager entityManager;
    
    @Transactional
    public void batchInsertUsers(List<User> users) {
        int batchSize = 25;
        for (int i = 0; i < users.size(); i++) {
            entityManager.persist(users.get(i));
            if (i % batchSize == 0 && i > 0) {
                entityManager.flush();
                entityManager.clear();
            }
        }
        entityManager.flush();
        entityManager.clear();
    }
    
    // 使用投影优化查询
    @Query("SELECT new com.example.dto.UserSummary(u.id, u.username, u.email) " +
           "FROM User u WHERE u.status = :status")
    List<UserSummary> findUserSummariesByStatus(@Param("status") UserStatus status);
}

// DTO 投影
public record UserSummary(Long id, String username, String email) {}

缓存策略

@Service
@CacheConfig(cacheNames = "users")
public class CachedUserService {
    
    @Cacheable(key = "#id")
    public UserDto findById(Long id) {
        // 数据库查询逻辑
    }
    
    @Cacheable(key = "#username")
    public UserDto findByUsername(String username) {
        // 数据库查询逻辑
    }
    
    @CacheEvict(key = "#user.id")
    public UserDto updateUser(UserDto user) {
        // 更新逻辑
    }
    
    @CacheEvict(allEntries = true)
    public void clearAllCache() {
        // 清除所有缓存
    }
}

// Redis 配置
@Configuration
@EnableCaching
public class CacheConfig {
    
    @Bean
    public RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory) {
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
            .entryTtl(Duration.ofHours(1))
            .serializeKeysWith(RedisSerializationContext.SerializationPair
                .fromSerializer(new StringRedisSerializer()))
            .serializeValuesWith(RedisSerializationContext.SerializationPair
                .fromSerializer(new GenericJackson2JsonRedisSerializer()));
        
        return RedisCacheManager.builder(connectionFactory)
            .cacheDefaults(config)
            .build();
    }
}

推荐资源

官方文档

工具和框架

构建工具:
  - Maven: 项目管理和构建
  - Gradle: 现代构建工具
  - SBT: Scala/Java 构建工具

开发框架:
  - Spring Boot: 企业级应用框架
  - Quarkus: 云原生 Java 框架
  - Micronaut: 微服务框架

测试框架:
  - JUnit 5: 单元测试框架
  - Mockito: 模拟框架
  - Testcontainers: 集成测试
  - WireMock: API 模拟

代码质量:
  - Checkstyle: 代码风格检查
  - SpotBugs: 静态代码分析
  - SonarQube: 代码质量平台
  - JaCoCo: 代码覆盖率

性能监控

  • APM 工具:New Relic、AppDynamics、Datadog
  • JVM 监控:JVisualVM、JProfiler、Async Profiler
  • 日志分析:ELK Stack、Splunk、Fluentd

页面最后更新:2025年7月21日