🚀 后端代码生成标准模板与代码规范约束规则

基于 OpenClaw + Claude Code 的端到端研发自动化系统

版本:v1.0.0 | 发布日期:2026 年 3 月 14 日 | 适用技术栈:Java Spring Boot / Python FastAPI / Node.js NestJS

1. 系统架构概述

🎯 核心目标:构建从需求到部署的全流程自动化研发系统,实现 AI 驱动的智能代码生成、测试和部署,支持人机协同的高效开发模式。

1.1 整体架构图

需求分析
PRD 设计
技术方案设计
前后端
API 协议设计
接口定义
AI Coding
代码生成
Unit Test
单元测试
集成测试
E2E 测试
CI/CD 部署
Docker+K8S
UI 自动化验收
质量验证

1.2 核心组件说明

组件名称 技术选型 职责描述 AI 集成度
OpenClaw Agent Node.js + LLM 任务调度、上下文管理、多代理协同 100%
Claude Code Claude Opus 4.6 代码理解、智能生成、重构优化 100%
代码生成引擎 Template Engine + AI 基于模板和 AI 混合的代码生成 80%
测试生成器 JUnit/Pytest/Jest + AI 自动生成单元测试和集成测试 90%
CI/CD 编排器 Jenkins + KubeSphere 自动化构建、测试、部署流水线 70%
质量门禁 SonarQube + AI Review 代码质量检查、安全扫描 85%

1.3 研发角色 Agents 定义

角色 Agent 职责范围 输入 输出
Product Agent 需求分析、PRD 撰写、用户故事拆解 原始需求文档 结构化 PRD、用户故事地图
Backend Architect Agent 后端技术方案设计、数据库设计、API 规划 PRD、业务需求 技术架构文档、ER 图、API 清单
Frontend Architect Agent 前端技术方案设计、组件设计、状态管理 PRD、UI 设计稿 前端架构文档、组件树、状态流
API Designer Agent 前后端 API 接口协议设计、Swagger 文档 技术方案设计 OpenAPI Spec、Mock 数据
Backend Developer Agent 后端代码实现、业务逻辑开发 API 协议、数据库设计 Controller/Service/Repository 代码
Frontend Developer Agent 前端代码实现、页面开发、交互逻辑 API 协议、UI 设计稿 React/Vue组件、页面代码
QA Engineer Agent 测试用例设计、自动化测试编写 功能需求、API 文档 单元测试、集成测试、E2E 测试
DevOps Agent CI/CD 配置、容器化部署、监控告警 代码仓库、环境配置 Jenkinsfile、Dockerfile、K8S YAML

2. 后端代码生成标准模板体系

📦 模板设计原则:标准化、可复用、可扩展、AI 友好、人机协同

2.1 项目结构模板

Java Spring Boot 项目结构

# 标准 Spring Boot 项目结构
project-root/
├── src/main/java/com/company/project/
│   ├── Application.java              # 启动类
│   ├── config/                       # 配置类
│   │   ├── SecurityConfig.java
│   │   ├── SwaggerConfig.java
│   │   └── RedisConfig.java
│   ├── controller/                   # 控制器层
│   │   ├── v1/                       # API 版本控制
│   │   │   ├── UserController.java
│   │   │   └── OrderController.java
│   │   └── advice/                   # 全局异常处理
│   │       └── GlobalExceptionHandler.java
│   ├── service/                      # 服务层
│   │   ├── UserService.java          # 接口
│   │   ├── UserServiceImpl.java      # 实现
│   │   └── dto/                      # 数据传输对象
│   │       ├── request/
│   │       │   ├── UserCreateRequest.java
│   │       │   └── UserUpdateRequest.java
│   │       └── response/
│   │           ├── UserResponse.java
│   │           └── PageResponse.java
│   ├── repository/                   # 数据访问层
│   │   ├── UserRepository.java
│   │   └── entity/                   # 实体类
│   │       ├── User.java
│   │       └── BaseEntity.java
│   ├── common/                       # 公共模块
│   │   ├── exception/                # 自定义异常
│   │   │   ├── BusinessException.java
│   │   │   └── ResourceNotFoundException.java
│   │   ├── result/                   # 统一返回结果
│   │   │   └── Result.java
│   │   └── constants/                # 常量定义
│   │       └── ErrorCode.java
│   └── util/                         # 工具类
│       └── BeanUtils.java
├── src/main/resources/
│   ├── application.yml               # 主配置文件
│   ├── application-dev.yml           # 开发环境
│   ├── application-prod.yml          # 生产环境
│   └── db/migration/                 # 数据库迁移脚本
│       └── V1__init_schema.sql
├── src/test/java/                    # 测试代码
│   ├── controller/
│   ├── service/
│   └── integration/
├── pom.xml                           # Maven 配置
├── Dockerfile                        # Docker 镜像
├── docker-compose.yml                # 本地开发环境
└── README.md                         # 项目文档

Python FastAPI 项目结构

# 标准 FastAPI 项目结构
project-root/
├── app/
│   ├── main.py                       # 应用入口
│   ├── api/                          # API 路由
│   │   ├── v1/
│   │   │   ├── __init__.py
│   │   │   ├── users.py
│   │   │   └── orders.py
│   │   └── deps.py                   # 依赖注入
│   ├── core/                         # 核心配置
│   │   ├── config.py
│   │   ├── security.py
│   │   └── exceptions.py
│   ├── models/                       # 数据库模型
│   │   ├── __init__.py
│   │   ├── user.py
│   │   └── order.py
│   ├── schemas/                      # Pydantic 模型
│   │   ├── __init__.py
│   │   ├── user.py
│   │   └── response.py
│   ├── services/                     # 业务逻辑
│   │   ├── __init__.py
│   │   ├── user_service.py
│   │   └── order_service.py
│   ├── db/                           # 数据库配置
│   │   ├── session.py
│   │   └── base.py
│   └── utils/                        # 工具函数
│       └── helpers.py
├── tests/                            # 测试目录
│   ├── test_api/
│   ├── test_services/
│   └── conftest.py
├── alembic/                          # 数据库迁移
│   └── versions/
├── requirements.txt                  # 依赖管理
├── Dockerfile
└── README.md

2.2 Controller 模板

Java Spring Boot Controller 标准模板

package com.company.project.controller.v1;

import com.company.project.common.result.Result;
import com.company.project.service.UserService;
import com.company.project.service.dto.request.UserCreateRequest;
import com.company.project.service.dto.request.UserUpdateRequest;
import com.company.project.service.dto.response.UserResponse;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/api/v1/users")
@RequiredArgsConstructor
@Tag(name = "用户管理", description = "用户相关 API 接口")
public class UserController {

    private final UserService userService;

    @GetMapping
    @Operation(summary = "分页查询用户列表")
    public Result<Page<UserResponse>> listUsers(Pageable pageable) {
        return Result.success(userService.listUsers(pageable));
    }

    @GetMapping("/{id}")
    @Operation(summary = "根据 ID 查询用户详情")
    public Result<UserResponse> getUserById(@PathVariable Long id) {
        return Result.success(userService.getUserById(id));
    }

    @PostMapping
    @Operation(summary = "创建用户")
    public Result<UserResponse> createUser(
            @Valid @RequestBody UserCreateRequest request) {
        return Result.success(userService.createUser(request));
    }

    @PutMapping("/{id}")
    @Operation(summary = "更新用户信息")
    public Result<UserResponse> updateUser(
            @PathVariable Long id,
            @Valid @RequestBody UserUpdateRequest request) {
        return Result.success(userService.updateUser(id, request));
    }

    @DeleteMapping("/{id}")
    @Operation(summary = "删除用户")
    public Result<Void> deleteUser(@PathVariable Long id) {
        userService.deleteUser(id);
        return Result.success();
    }
}

2.3 Service 模板

Java Spring Boot Service 标准模板

package com.company.project.service;

import com.company.project.common.exception.BusinessException;
import com.company.project.common.constants.ErrorCode;
import com.company.project.repository.UserRepository;
import com.company.project.repository.entity.User;
import com.company.project.service.dto.request.UserCreateRequest;
import com.company.project.service.dto.request.UserUpdateRequest;
import com.company.project.service.dto.response.UserResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Slf4j
@Service
@RequiredArgsConstructor
public class UserServiceImpl implements UserService {

    private final UserRepository userRepository;

    @Override
    @Transactional(readOnly = true)
    public Page<UserResponse> listUsers(Pageable pageable) {
        log.info("查询用户列表,page={}, size={}", 
                pageable.getPageNumber(), pageable.getPageSize());
        return userRepository.findAll(pageable)
                .map(this::convertToResponse);
    }

    @Override
    @Transactional(readOnly = true)
    public UserResponse getUserById(Long id) {
        log.info("查询用户详情,id={}", id);
        User user = userRepository.findById(id)
                .orElseThrow(() -> new BusinessException(
                        ErrorCode.USER_NOT_FOUND, 
                        "用户不存在,ID: " + id));
        return convertToResponse(user);
    }

    @Override
    @Transactional
    public UserResponse createUser(UserCreateRequest request) {
        log.info("创建用户,username={}", request.getUsername());
        
        // 校验用户名是否已存在
        if (userRepository.existsByUsername(request.getUsername())) {
            throw new BusinessException(
                    ErrorCode.USER_ALREADY_EXISTS,
                    "用户名已存在:" + request.getUsername());
        }
        
        User user = User.builder()
                .username(request.getUsername())
                .email(request.getEmail())
                .phone(request.getPhone())
                .build();
        
        user = userRepository.save(user);
        log.info("用户创建成功,id={}", user.getId());
        return convertToResponse(user);
    }

    @Override
    @Transactional
    public UserResponse updateUser(Long id, UserUpdateRequest request) {
        log.info("更新用户信息,id={}", id);
        
        User user = userRepository.findById(id)
                .orElseThrow(() -> new BusinessException(
                        ErrorCode.USER_NOT_FOUND,
                        "用户不存在,ID: " + id));
        
        user.updateFrom(request);
        user = userRepository.save(user);
        
        log.info("用户更新成功,id={}", id);
        return convertToResponse(user);
    }

    @Override
    @Transactional
    public void deleteUser(Long id) {
        log.info("删除用户,id={}", id);
        
        if (!userRepository.existsById(id)) {
            throw new BusinessException(
                    ErrorCode.USER_NOT_FOUND,
                    "用户不存在,ID: " + id);
        }
        
        userRepository.deleteById(id);
        log.info("用户删除成功,id={}", id);
    }

    private UserResponse convertToResponse(User user) {
        return UserResponse.builder()
                .id(user.getId())
                .username(user.getUsername())
                .email(user.getEmail())
                .phone(user.getPhone())
                .createdAt(user.getCreatedAt())
                .updatedAt(user.getUpdatedAt())
                .build();
    }
}

2.4 Repository 模板

Java Spring Data JPA Repository 标准模板

package com.company.project.repository;

import com.company.project.repository.entity.User;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;

import java.util.Optional;

@Repository
public interface UserRepository extends JpaRepository<User, Long> {

    /**
     * 根据用户名查询用户
     * @param username 用户名
     * @return 用户 Optional
     */
    Optional<User> findByUsername(String username);

    /**
     * 检查用户名是否存在
     * @param username 用户名
     * @return 是否存在
     */
    boolean existsByUsername(String username);

    /**
     * 根据邮箱查询用户
     * @param email 邮箱
     * @return 用户 Optional
     */
    Optional<User> findByEmail(String email);

    /**
     * 分页查询用户(支持模糊搜索)
     * @param keyword 搜索关键词
     * @param pageable 分页参数
     * @return 用户分页列表
     */
    @Query("SELECT u FROM User u WHERE " +
            "u.username LIKE %:keyword% OR " +
            "u.email LIKE %:keyword% OR " +
            "u.phone LIKE %:keyword%")
    Page<User> searchUsers(@Param("keyword") String keyword, Pageable pageable);
}

2.5 Entity 实体类模板

Java JPA Entity 标准模板

package com.company.project.repository.entity;

import jakarta.persistence.*;
import lombok.*;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

import java.time.LocalDateTime;

@Entity
@Table(name = "t_user")
@EntityListeners(AuditingEntityListener.class)
@Getter
@Setter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(nullable = false, unique = true, length = 50)
    private String username;

    @Column(nullable = false, unique = true, length = 100)
    private String email;

    @Column(length = 20)
    private String phone;

    @Column(nullable = false, length = 100)
    private String password;

    @Column(length = 500)
    private String avatar;

    @Column(nullable = false)
    @Builder.Default
    private Boolean enabled = true;

    @CreatedDate
    @Column(nullable = false, updatable = false)
    private LocalDateTime createdAt;

    @LastModifiedDate
    @Column(nullable = false)
    private LocalDateTime updatedAt;

    /**
     * 从 DTO 更新实体属性
     */
    public void updateFrom(Object dto) {
        // 使用 BeanUtils 或手动映射
    }
}

2.6 DTO 数据传输对象模板

请求对象 (Request DTO)

package com.company.project.service.dto.request;

import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
import lombok.*;

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class UserCreateRequest {

    @NotBlank(message = "用户名不能为空")
    @Size(min = 3, max = 50, message = "用户名长度必须在 3-50 之间")
    private String username;

    @NotBlank(message = "邮箱不能为空")
    @Email(message = "邮箱格式不正确")
    private String email;

    @Size(max = 20, message = "手机号长度不能超过 20")
    private String phone;

    @NotBlank(message = "密码不能为空")
    @Size(min = 6, max = 100, message = "密码长度必须在 6-100 之间")
    private String password;
}

响应对象 (Response DTO)

package com.company.project.service.dto.response;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.*;

import java.time.LocalDateTime;

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@JsonInclude(JsonInclude.Include.NON_NULL)
public class UserResponse {

    private Long id;

    private String username;

    private String email;

    private String phone;

    private String avatar;

    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime createdAt;

    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime updatedAt;
}

2.7 统一返回结果模板

package com.company.project.common.result;

import com.company.project.common.constants.ErrorCode;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.*;

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@JsonInclude(JsonInclude.Include.NON_NULL)
public class Result<T> {

    private Integer code;

    private String message;

    private T data;

    private Long timestamp;

    public static <T> Result<T> success() {
        return Result.<T>builder()
                .code(ErrorCode.SUCCESS.getCode())
                .message(ErrorCode.SUCCESS.getMessage())
                .timestamp(System.currentTimeMillis())
                .build();
    }

    public static <T> Result<T> success(T data) {
        return Result.<T>builder()
                .code(ErrorCode.SUCCESS.getCode())
                .message(ErrorCode.SUCCESS.getMessage())
                .data(data)
                .timestamp(System.currentTimeMillis())
                .build();
    }

    public static <T> Result<T> error(Integer code, String message) {
        return Result.<T>builder()
                .code(code)
                .message(message)
                .timestamp(System.currentTimeMillis())
                .build();
    }

    public static <T> Result<T> error(ErrorCode errorCode) {
        return Result.<T>builder()
                .code(errorCode.getCode())
                .message(errorCode.getMessage())
                .timestamp(System.currentTimeMillis())
                .build();
    }
}

3. 代码规范约束规则

⚠️ 重要提示:所有代码规范必须被 OpenClaw 和 Claude Code 严格遵守,AI 生成的代码必须通过代码规范检查才能进入下一流程。

3.1 命名规范

元素类型 命名规则 示例 强制级别
类名 (Class) PascalCase (大驼峰) UserController, UserService ● 强制
接口名 (Interface) PascalCase,可加 I 前缀 UserService, IRepository ● 强制
方法名 (Method) camelCase (小驼峰),动词开头 getUserById(), createUser() ● 强制
变量名 (Variable) camelCase,名词或名词短语 userName, orderList ● 强制
常量名 (Constant) UPPER_SNAKE_CASE MAX_RETRY_COUNT ● 强制
包名 (Package) 全小写,单词间用点分隔 com.company.project.service ● 强制
数据库表名 小写,下划线分隔,加模块前缀 t_user, t_order_item ● 强制
数据库字段名 小写,下划线分隔 user_name, created_at ● 强制
REST API 路径 小写,复数名词,kebab-case /api/v1/users, /api/v1/order-items ● 强制

3.2 注释规范

类注释模板

/**
 * 用户服务实现类
 * 
 * <p>提供用户相关的业务逻辑处理,包括:
 * <ul>
 *   <li>用户 CRUD 操作</li>
 *   <li>用户权限验证</li>
 *   <li>用户状态管理</li>
 * </ul></p>
 * 
 * @author OpenClaw AI Agent
 * @version 1.0.0
 * @since 2026-03-14
 * @see UserService
 * @see UserController
 */

方法注释模板

/**
 * 根据 ID 查询用户详情
 *
 * <p>通过用户 ID 查询用户详细信息,如果用户不存在则抛出
 * {@link BusinessException}异常,错误码为{@link ErrorCode#USER_NOT_FOUND}</p>
 *
 * @param id 用户 ID,不能为空,必须大于 0
 * @return 用户响应对象,包含用户完整信息
 * @throws BusinessException 当用户不存在时抛出
 * 
 * @apiNote 此方法为只读事务,不会修改数据库
 * @implNote 使用 Optional 处理空值,避免 NPE
 */

行内注释规则

3.3 异常处理规范

异常分类体系

异常类型 基类 使用场景 HTTP 状态码
业务异常 BusinessException 业务规则校验失败 400 Bad Request
资源未找到 ResourceNotFoundException 请求的资源不存在 404 Not Found
权限异常 AccessDeniedException 无权访问资源 403 Forbidden
数据验证异常 ValidationException 参数校验失败 422 Unprocessable Entity
系统异常 SystemException 系统内部错误 500 Internal Server Error

全局异常处理器模板

package com.company.project.controller.advice;

import com.company.project.common.exception.BusinessException;
import com.company.project.common.result.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;

@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(BusinessException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public Result<Void> handleBusinessException(BusinessException ex) {
        log.warn("业务异常:{}", ex.getMessage(), ex);
        return Result.error(ex.getErrorCode());
    }

    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseStatus(HttpStatus.UNPROCESSABLE_ENTITY)
    public Result<Void> handleValidationException(
            MethodArgumentNotValidException ex) {
        String message = ex.getBindingResult()
                .getFieldErrors()
                .stream()
                .map(error -> error.getField() + ": " + error.getDefaultMessage())
                .findFirst()
                .orElse("参数验证失败");
        log.warn("参数验证异常:{}", message);
        return Result.error(HttpStatus.UNPROCESSABLE_ENTITY.value(), message);
    }

    @ExceptionHandler(Exception.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public Result<Void> handleGenericException(Exception ex) {
        log.error("系统异常:{}", ex.getMessage(), ex);
        return Result.error(
                HttpStatus.INTERNAL_SERVER_ERROR.value(),
                "系统繁忙,请稍后重试");
    }
}

3.4 日志规范

日志级别使用规则

日志级别 使用场景 示例
ERROR 系统错误、异常堆栈、关键业务失败 log.error("订单创建失败", ex)
WARN 业务异常、可恢复错误、重要警告 log.warn("用户不存在,id={}", id)
INFO 关键业务流程、重要状态变更、审计日志 log.info("用户登录成功,userId={}", userId)
DEBUG 调试信息、详细执行过程、开发环境 log.debug("SQL 执行时间:{}ms", duration)
TRACE 最详细的跟踪信息、生产环境禁用 log.trace("方法入参:{}", params)

日志内容规范

3.5 代码质量标准

SonarQube 质量门禁

指标 阈值 强制级别
代码覆盖率 ≥ 80% ● 强制
重复代码率 ≤ 3% ● 强制
Blocker Issues 0 ● 强制
Critical Issues 0 ● 强制
Major Issues ≤ 5 ▲ 建议
技术债务率 ≤ 5% ▲ 建议
圈复杂度 ≤ 15 ▲ 建议

4. API 接口开发协议标准

4.1 RESTful API 设计规范

HTTP 方法语义

方法 语义 幂等性 示例
GET 查询资源 GET /api/v1/users/123
POST 创建资源 POST /api/v1/users
PUT 全量更新资源 PUT /api/v1/users/123
PATCH 部分更新资源 PATCH /api/v1/users/123
DELETE 删除资源 DELETE /api/v1/users/123

4.2 OpenAPI Specification (Swagger) 模板

# OpenAPI 3.0 规范模板
openapi: "3.0.3"
info:
  title: "用户管理系统 API"
  description: "提供用户管理相关的完整 API 接口"
  version: "1.0.0"
  contact:
    name: "API Support Team"
    email: "api-support@company.com"

servers:
  - url: "https://api.company.com/v1"
    description: "生产环境"
  - url: "https://dev-api.company.com/v1"
    description: "开发环境"

tags:
  - name: "users"
    description: "用户管理相关接口"

paths:
  /users:
    get:
      tags: [users]
      summary: "分页查询用户列表"
      operationId: "listUsers"
      parameters:
        - name: page
          in: query
          schema:
            type: integer
            default: 0
        - name: size
          in: query
          schema:
            type: integer
            default: 20
      responses:
        "200":
          description: "成功"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/UserPageResponse"
    
    post:
      tags: [users]
      summary: "创建用户"
      operationId: "createUser"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/UserCreateRequest"
      responses:
        "201":
          description: "创建成功"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/UserResponse"

components:
  schemas:
    UserCreateRequest:
      type: object
      required: [username, email, password]
      properties:
        username:
          type: string
          minLength: 3
          maxLength: 50
        email:
          type: string
          format: email
        password:
          type: string
          minLength: 6
          maxLength: 100
    
    UserResponse:
      type: object
      properties:
        id:
          type: integer
          format: int64
        username:
          type: string
        email:
          type: string
        createdAt:
          type: string
          format: date-time

4.3 API 版本管理策略

📌 版本管理规则:
  • URL 路径版本:/api/v1/resource(推荐)
  • Header 版本:X-API-Version: 1
  • 查询参数版本:?version=1(不推荐)

4.4 接口文档自动生成

✅ AI 自动化流程:
  1. API Designer Agent 根据技术方案生成 OpenAPI Spec
  2. Swagger UI 自动渲染交互式文档
  3. Mock Server 自动生成模拟数据
  4. 前后端并行开发,基于契约测试

5. 单元测试与集成测试规范

5.1 单元测试模板

Java JUnit 5 + Mockito 测试模板

package com.company.project.service;

import com.company.project.common.exception.BusinessException;
import com.company.project.repository.UserRepository;
import com.company.project.repository.entity.User;
import com.company.project.service.dto.request.UserCreateRequest;
import com.company.project.service.dto.response.UserResponse;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
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 java.util.Optional;

import static org.assertj.core.api.Assertions.*;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.BDDMockito.*;

@ExtendWith(MockitoExtension.class)
@DisplayName("UserService 单元测试")
class UserServiceTest {

    @Mock
    private UserRepository userRepository;

    @InjectMocks
    private UserServiceImpl userService;

    private UserCreateRequest createRequest;
    private User user;

    @BeforeEach
    void setUp() {
        createRequest = UserCreateRequest.builder()
                .username("testuser")
                .email("test@example.com")
                .password("password123")
                .build();
        
        user = User.builder()
                .id(1L)
                .username("testuser")
                .email("test@example.com")
                .build();
    }

    @Test
    @DisplayName("创建用户_成功场景")
    void createUser_Success() {
        // Given
        given(userRepository.existsByUsername("testuser")).willReturn(false);
        given(userRepository.save(any(User.class))).willReturn(user);

        // When
        UserResponse response = userService.createUser(createRequest);

        // Then
        assertThat(response).isNotNull();
        assertThat(response.getUsername()).isEqualTo("testuser");
        then(userRepository).should().save(any(User.class));
    }

    @Test
    @DisplayName("创建用户_用户名已存在")
    void createUser_UsernameAlreadyExists() {
        // Given
        given(userRepository.existsByUsername("testuser")).willReturn(true);

        // When & Then
        assertThatThrownBy(() -> userService.createUser(createRequest))
                .isInstanceOf(BusinessException.class)
                .hasMessageContaining("用户名已存在");
    }

    @Test
    @DisplayName("根据 ID 查询用户_成功场景")
    void getUserById_Success() {
        // Given
        given(userRepository.findById(1L)).willReturn(Optional.of(user));

        // When
        UserResponse response = userService.getUserById(1L);

        // Then
        assertThat(response.getId()).isEqualTo(1L);
        assertThat(response.getUsername()).isEqualTo("testuser");
    }

    @Test
    @DisplayName("根据 ID 查询用户_用户不存在")
    void getUserById_NotFound() {
        // Given
        given(userRepository.findById(999L)).willReturn(Optional.empty());

        // When & Then
        assertThatThrownBy(() -> userService.getUserById(999L))
                .isInstanceOf(BusinessException.class)
                .hasMessageContaining("用户不存在");
    }
}

5.2 集成测试模板

Spring Boot 集成测试模板

package com.company.project.integration;

import com.company.project.repository.UserRepository;
import com.company.project.repository.entity.User;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
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.http.MediaType;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.transaction.annotation.Transactional;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;

@SpringBootTest
@AutoConfigureMockMvc
@ActiveProfiles("test")
@Transactional
@DisplayName("用户 API 集成测试")
class UserApiIntegrationTest {

    @Autowired
    private MockMvc mockMvc;

    @Autowired
    private ObjectMapper objectMapper;

    @Autowired
    private UserRepository userRepository;

    @BeforeEach
    void setUp() {
        userRepository.deleteAll();
    }

    @Test
    @DisplayName("创建用户_API 测试")
    void createUser_ApiTest() throws Exception {
        String requestBody = objectMapper.writeValueAsString(Map.of(
                "username", "testuser",
                "email", "test@example.com",
                "password", "password123"
        ));

        mockMvc.perform(post("/api/v1/users")
                .contentType(MediaType.APPLICATION_JSON)
                .content(requestBody))
                .andExpect(status().isCreated())
                .andExpect(jsonPath("$.code").value(200))
                .andExpect(jsonPath("$.data.username").value("testuser"));
    }

    @Test
    @DisplayName("查询用户列表_API 测试")
    void listUsers_ApiTest() throws Exception {
        // 准备测试数据
        User user = User.builder()
                .username("testuser")
                .email("test@example.com")
                .password("password123")
                .build();
        userRepository.save(user);

        mockMvc.perform(get("/api/v1/users")
                .param("page", "0")
                .param("size", "10"))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.code").value(200))
                .andExpect(jsonPath("$.data.content").isArray())
                .andExpect(jsonPath("$.data.totalElements").value(1));
    }
}

5.3 测试覆盖率要求

代码类型 最低覆盖率 测试框架
Service 层 ≥ 90% JUnit 5 + Mockito
Controller 层 ≥ 85% Spring MVC Test
Repository 层 ≥ 80% Spring Data JPA Test
工具类 ≥ 95% JUnit 5
集成测试 核心流程 100% TestContainers

6. CI/CD 流水线配置模板

6.1 Jenkins Pipeline 模板

Jenkinsfile (声明式 Pipeline)

// Jenkinsfile for Spring Boot Project
pipeline {
    agent {
        kubernetes {
            yaml """
apiVersion: v1
kind: Pod
spec:
  containers:
  - name: maven
    image: maven:3.9-openjdk-17
    command:
    - cat
    tty: true
  - name: docker
    image: docker:24-dind
    securityContext:
      privileged: true
    volumeMounts:
    - name: docker-sock
      mountPath: /var/run/docker.sock
  volumes:
  - name: docker-sock
    hostPath:
      path: /var/run/docker.sock
"""
        }
    }

    environment {
        REGISTRY = "registry.company.com"
        IMAGE_NAME = "myapp-backend"
        KUBE_CONFIG = credentials('kubeconfig')
        SONAR_TOKEN = credentials('sonar-token')
    }

    options {
        timestamps()
        timeout(time: 60, unit: 'MINUTES')
        disableConcurrentBuilds()
        buildDiscarder(logRotator(numToKeepStr: '10'))
    }

    triggers {
        pollSCM('*/5 * * * *')
    }

    stages {
        stage('Checkout') {
            steps {
                checkout scm
                script {
                    env.GIT_COMMIT_SHORT = sh(
                        script: 'git rev-parse --short HEAD',
                        returnStdout: true
                    ).trim()
                    env.BUILD_VERSION = "${env.BUILD_NUMBER}-${env.GIT_COMMIT_SHORT}"
                }
            }
        }

        stage('Code Quality Check') {
            steps {
                container('maven') {
                    sh 'mvn -B sonar:sonar \
                        -Dsonar.projectKey=myapp-backend \
                        -Dsonar.host.url=http://sonarqube.company.com \
                        -Dsonar.login=$SONAR_TOKEN'
                    
                    timeout(time: 5, unit: 'MINUTES') {
                        waitForQualityGate abortPipeline: true
                    }
                }
            }
        }

        stage('Unit Test') {
            steps {
                container('maven') {
                    sh 'mvn -B test -DskipITs'
                }
            }
            post {
                always {
                    junit allowEmptyResults: true,
                          testResults: '**/target/surefire-reports/*.xml'
                    publishCoverage adapters: [jacocoAdapter('**/target/site/jacoco/jacoco.xml')]
                }
            }
        }

        stage('Integration Test') {
            steps {
                container('maven') {
                    sh 'mvn -B verify -DskipUnitTests'
                }
            }
        }

        stage('Build Docker Image') {
            steps {
                container('docker') {
                    sh """
                    docker build -t ${REGISTRY}/${IMAGE_NAME}:${BUILD_VERSION} .
                    docker tag ${REGISTRY}/${IMAGE_NAME}:${BUILD_VERSION} ${REGISTRY}/${IMAGE_NAME}:latest
                    """
                }
            }
        }

        stage('Push to Registry') {
            steps {
                container('docker') {
                    withCredentials([usernamePassword(
                        credentialsId: 'docker-registry',
                        usernameVariable: 'DOCKER_USER',
                        passwordVariable: 'DOCKER_PASS'
                    )]) {
                        sh """
                        echo $DOCKER_PASS | docker login ${REGISTRY} -u $DOCKER_USER --password-stdin
                        docker push ${REGISTRY}/${IMAGE_NAME}:${BUILD_VERSION}
                        docker push ${REGISTRY}/${IMAGE_NAME}:latest
                        """
                    }
                }
            }
        }

        stage('Deploy to K8S') {
            when {
                branch 'main'
            }
            steps {
                container('maven') {
                    sh """
                    export KUBECONFIG=$KUBE_CONFIG
                    kubectl set image deployment/myapp-backend \
                        myapp-backend=${REGISTRY}/${IMAGE_NAME}:${BUILD_VERSION} \
                        -n production
                    kubectl rollout status deployment/myapp-backend -n production
                    """
                }
            }
        }
    }

    post {
        always {
            cleanWs()
        }
        success {
            script {
                slackSend channel: '#deployments',
                          color: 'good',
                          message: "✅ 构建成功:${env.JOB_NAME} #${env.BUILD_NUMBER}\n版本:${env.BUILD_VERSION}\n链接:${env.BUILD_URL}"
            }
        }
        failure {
            script {
                slackSend channel: '#deployments',
                          color: 'danger',
                          message: "❌ 构建失败:${env.JOB_NAME} #${env.BUILD_NUMBER}\n链接:${env.BUILD_URL}"
            }
        }
    }
}

6.2 Dockerfile 模板

Java Spring Boot Dockerfile

# 多阶段构建 Dockerfile
# Stage 1: Build
FROM maven:3.9-eclipse-temurin-17 AS builder

WORKDIR /app

COPY pom.xml .
RUN mvn dependency:go-offline -B

COPY src ./src
RUN mvn clean package -DskipTests -B

# Stage 2: Runtime
FROM eclipse-temurin:17-jre-alpine

LABEL maintainer="devops@company.com"
LABEL version="1.0.0"
LABEL description="MyApp Backend Service"

WORKDIR /app

RUN addgroup -g 1001 appgroup && \
    adduser -D -u 1001 -G appgroup appuser

COPY --from=builder --chown=appuser:appgroup /app/target/*.jar app.jar

USER appuser

EXPOSE 8080

ENV JAVA_OPTS="-Xms512m -Xmx1024m -XX:+UseG1GC"
ENV SPRING_PROFILES_ACTIVE=prod

ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -jar app.jar"]

HEALTHCHECK --interval=30s --timeout=3s --start-period=60s --retries=3 \
    CMD wget --no-verbose --tries=1 --spider http://localhost:8080/actuator/health || exit 1

6.3 Kubernetes 部署配置

K8S Deployment YAML

# k8s/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-backend
  namespace: production
  labels:
    app: myapp-backend
    version: v1
spec:
  replicas: 3
  selector:
    matchLabels:
      app: myapp-backend
  template:
    metadata:
      labels:
        app: myapp-backend
        version: v1
      annotations:
        prometheus.io/scrape: "true"
        prometheus.io/port: "8080"
    spec:
      serviceAccountName: myapp-sa
      containers:
      - name: myapp-backend
        image: registry.company.com/myapp-backend:latest
        imagePullPolicy: Always
        ports:
        - containerPort: 8080
          name: http
          protocol: TCP
        env:
        - name: SPRING_PROFILES_ACTIVE
          value: "prod"
        - name: JAVA_OPTS
          value: "-Xms512m -Xmx1024m"
        resources:
          requests:
            memory: "512Mi"
            cpu: "250m"
          limits:
            memory: "1Gi"
            cpu: "1000m"
        livenessProbe:
          httpGet:
            path: /actuator/health/liveness
            port: 8080
          initialDelaySeconds: 60
          periodSeconds: 10
          timeoutSeconds: 3
          failureThreshold: 3
        readinessProbe:
          httpGet:
            path: /actuator/health/readiness
            port: 8080
          initialDelaySeconds: 30
          periodSeconds: 5
          timeoutSeconds: 3
          failureThreshold: 3
        volumeMounts:
        - name: logs
          mountPath: /app/logs
      volumes:
      - name: logs
        emptyDir: {}
      affinity:
        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 100
            podAffinityTerm:
              labelSelector:
                matchLabels:
                  app: myapp-backend
              topologyKey: kubernetes.io/hostname
---
apiVersion: v1
kind: Service
metadata:
  name: myapp-backend-service
  namespace: production
spec:
  selector:
    app: myapp-backend
  ports:
  - port: 80
    targetPort: 8080
    protocol: TCP
  type: ClusterIP
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: myapp-backend-hpa
  namespace: production
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: myapp-backend
  minReplicas: 3
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70
  - type: Resource
    resource:
      name: memory
      target:
        type: Utilization
        averageUtilization: 80

6.4 KubeSphere DevOps 配置

🔧 KubeSphere 特性集成:
  • 可视化 CI/CD 流水线编辑
  • 多分支流水线自动发现
  • 内置代码质量检查(SonarQube)
  • 容器化构建环境
  • 一键部署到多环境
  • 灰度发布和蓝绿部署
  • 流水线即代码(Jenkinsfile)

7. OpenClaw + Claude Code 集成方案

7.1 OpenClaw 配置模板

OpenClaw 配置文件 (.claw/config.yaml)

# OpenClaw 配置文件
version: "2026.3.8"

agents:
  product_agent:
    model: claude-opus-4.6
    system_prompt: "你是资深产品专家,负责需求分析和 PRD 撰写..."
    tools: [file_read, file_write, web_search]
  
  backend_architect_agent:
    model: claude-opus-4.6
    system_prompt: "你是资深后端架构师,负责技术方案设计..."
    tools: [file_read, file_write, execute_command]
  
  backend_developer_agent:
    model: claude-sonnet-4.5
    system_prompt: "你是高级 Java 开发工程师,遵循代码规范..."
    tools: [file_read, file_write, execute_command]
  
  qa_engineer_agent:
    model: claude-sonnet-4.5
    system_prompt: "你是资深测试工程师,负责编写测试用例..."
    tools: [file_read, file_write, execute_command]
  
  devops_agent:
    model: claude-sonnet-4.5
    system_prompt: "你是 DevOps 专家,负责 CI/CD 配置..."
    tools: [file_read, file_write, execute_command]

workflow:
  name: "端到端研发自动化流程"
  stages:
    - name: requirement_analysis
      agent: product_agent
      input: raw_requirements.md
      output: prd.md
      
    - name: technical_design
      agent: backend_architect_agent
      input: prd.md
      output: [architecture.md, api_spec.yaml]
      
    - name: code_generation
      agent: backend_developer_agent
      input: api_spec.yaml
      output: source_code/
      
    - name: unit_test
      agent: qa_engineer_agent
      input: source_code/
      output: tests/
      
    - name: ci_cd_setup
      agent: devops_agent
      input: source_code/
      output: [Jenkinsfile, Dockerfile, k8s/]

llm_providers:
  anthropic:
    api_key: ${ANTHROPIC_API_KEY}
    base_url: https://api.anthropic.com
    models:
      - id: claude-opus-4.6
        context_window: 200000
        max_tokens: 64000
      - id: claude-sonnet-4.5
        context_window: 200000
        max_tokens: 64000

skills:
  - name: code_generator
    enabled: true
    templates_path: ./templates/
    
  - name: test_generator
    enabled: true
    coverage_target: 0.85
    
  - name: code_reviewer
    enabled: true
    ruleset: ./rules/code_quality.yaml

memory:
  type: persistent
  storage_path: ~/.claw/memory/
  max_context_items: 100

security:
  sandbox_mode: true
  allowed_commands: [mvn, npm, docker, kubectl, git]
  blocked_paths: [/etc, /root, /home]

7.2 Claude Code 最佳实践

Claude Code 工作流配置

# .claude/settings.json
{
  "workspaceRules": [
    {
      "pattern": "**/*.java",
      "instructions": "遵循 Java 代码规范:PascalCase 类名、camelCase 方法名、添加 Javadoc 注释"
    },
    {
      "pattern": "**/controller/**/*.java",
      "instructions": "Controller 层必须使用@RestController 注解,返回 Result 包装类"
    },
    {
      "pattern": "**/service/**/*.java",
      "instructions": "Service 层必须添加@Transactional 注解,记录业务日志"
    }
  ],
  "autoCommands": {
    "afterFileCreate": "mvn compile",
    "beforeCommit": "mvn test && mvn checkstyle:check"
  },
  "contextManagement": {
    "maxFiles": 50,
    "includeGitignore": true,
    "respectIgnoreFiles": true
  }
}

7.3 AI 代码生成 Prompt 模板

Controller 生成 Prompt

你是一名资深 Java 开发工程师,请根据以下 API 规范生成 Spring Boot Controller 代码:

【技术要求】
1. 使用 Spring Boot 3.x + Java 17
2. 遵循 RESTful API 设计规范
3. 使用 Swagger/OpenAPI 3.0 注解
4. 统一返回 Result<T>包装类
5. 添加完整的异常处理

【API 规范】
- 路径:/api/v1/users
- 方法:
  - GET / - 分页查询用户列表
  - GET /{id} - 查询用户详情
  - POST / - 创建用户
  - PUT /{id} - 更新用户
  - DELETE /{id} - 删除用户

【代码规范要求】
1. 类名使用 PascalCase
2. 方法名使用 camelCase,动词开头
3. 添加完整的 Javadoc 注释
4. 使用 Lombok 简化代码
5. 参数校验使用@Valid 注解

请生成完整的 UserController 代码。

8. 人机协同工作机制

8.1 人机协同流程

AI 生成代码
Claude Code
人工 Review
代码审查
AI 修复反馈
自动修正
人工确认
最终审核
自动合并
Git Commit

8.2 人工介入节点

研发阶段 AI 自动化程度 人工介入点 介入方式
需求分析 70% 需求确认、优先级排序 Review + 批准
技术方案设计 80% 架构评审、技术选型 讨论 + 决策
代码生成 90% 代码 Review、复杂逻辑 Code Review
测试用例 85% 边界场景、异常流程 补充 + 验证
部署上线 75% 上线审批、回滚决策 审批 + 监控

8.3 代码 Review 检查清单

✅ AI 生成代码人工 Review 要点:
  • 业务逻辑正确性:是否满足需求、边界条件处理
  • 代码规范符合度:命名、注释、格式是否符合规范
  • 异常处理完整性:异常捕获、日志记录、错误提示
  • 安全性检查:SQL 注入、XSS、权限校验
  • 性能考虑:循环嵌套、数据库查询、缓存使用
  • 可测试性:依赖注入、单元测试覆盖

8.4 反馈循环机制

# 人机协同反馈循环
while (feature_not_complete) {
    1. AI 生成代码片段
    2. 自动运行单元测试
    3. IF 测试失败 THEN
        3.1 AI 分析失败原因
        3.2 AI 自动修复代码
        3.3 GOTO 步骤 2
    4. ELSE 测试通过 THEN
        4.1 人工 Code Review
        4.2 IF 发现问题 THEN
            4.2.1 人工标注问题
            4.2.2 AI 学习并修复
            4.2.3 GOTO 步骤 2
        4.3 ELSE 无问题 THEN
            4.3.1 提交代码
            4.3.2 触发 CI/CD 流水线
}