# 校园活动组织与报名系统 - 后端开发规范

## 1. 技术选型

### 1.1 核心框架
| 技术 | 版本 | 说明 |
|------|------|------|
| Java | 21 | LTS版本，支持现代语法特性 |
| Spring Boot | 3.2.x | 主框架 |
| Spring Security | 6.x | 安全认证框架 |
| MyBatis-Plus | 3.5.x | ORM框架，简化CRUD操作 |
| MySQL | 8.0+ | 关系型数据库 |

### 1.2 工具库
| 技术 | 版本 | 说明 |
|------|------|------|
| JWT | 0.12.x (jjwt) | Token认证 |
| ZXing | 3.5.x | 二维码生成与解析 |
| iText | 7.x | PDF电子票生成 |
| EasyExcel | 3.3.x | Excel导出 |
| Knife4j | 4.x | API文档(基于OpenAPI 3) |
| Hutool | 5.8.x | 工具类库 |
| Lombok | 1.18.x | 简化实体类代码 |

### 1.3 项目结构
```
campus-activity-system/
├── src/main/java/com/campus/activity/
│   ├── CampusActivityApplication.java    # 启动类
│   ├── config/                           # 配置类
│   │   ├── SecurityConfig.java
│   │   ├── MybatisPlusConfig.java
│   │   ├── CorsConfig.java
│   │   └── Knife4jConfig.java
│   ├── controller/                       # 控制器层
│   │   ├── AuthController.java
│   │   ├── ActivityController.java
│   │   ├── RegistrationController.java
│   │   ├── CheckInController.java
│   │   ├── ReviewController.java
│   │   └── StatisticsController.java
│   ├── service/                          # 服务层
│   │   ├── impl/
│   │   └── ...Service.java
│   ├── mapper/                           # 数据访问层
│   ├── entity/                           # 实体类
│   ├── dto/                              # 数据传输对象
│   │   ├── request/                      # 请求DTO
│   │   └── response/                     # 响应DTO
│   ├── vo/                               # 视图对象
│   ├── common/                           # 公共模块
│   │   ├── Result.java                   # 统一响应
│   │   ├── ResultCode.java               # 状态码枚举
│   │   └── PageResult.java               # 分页响应
│   ├── exception/                        # 异常处理
│   │   ├── BusinessException.java
│   │   └── GlobalExceptionHandler.java
│   ├── security/                         # 安全模块
│   │   ├── JwtTokenProvider.java
│   │   ├── JwtAuthenticationFilter.java
│   │   └── UserDetailsServiceImpl.java
│   └── util/                             # 工具类
│       ├── QrCodeUtil.java
│       ├── PdfUtil.java
│       └── ExcelUtil.java
├── src/main/resources/
│   ├── application.yml
│   ├── application-dev.yml
│   ├── application-prod.yml
│   └── mapper/                           # MyBatis XML映射文件
└── pom.xml
```

## 2. 编码规范

### 2.1 命名规范

#### 类命名
- Controller类：`XxxController`
- Service接口：`XxxService`
- Service实现：`XxxServiceImpl`
- Mapper接口：`XxxMapper`
- Entity实体：`Xxx`（与表名对应，驼峰命名）
- DTO类：`XxxDTO` 或 `XxxRequest`/`XxxResponse`
- VO类：`XxxVO`

#### 方法命名
| 操作 | 命名规范 | 示例 |
|------|----------|------|
| 新增 | save/add/create | `saveActivity()` |
| 删除 | remove/delete | `removeActivity()` |
| 修改 | update/modify | `updateActivity()` |
| 查询单个 | get/find | `getActivityById()` |
| 查询列表 | list/find | `listActivities()` |
| 分页查询 | page | `pageActivities()` |

### 2.2 统一响应格式

```java
@Data
public class Result<T> {
    private Integer code;
    private String message;
    private T data;
    private Long timestamp;

    public static <T> Result<T> success(T data) {
        Result<T> result = new Result<>();
        result.setCode(200);
        result.setMessage("success");
        result.setData(data);
        result.setTimestamp(System.currentTimeMillis());
        return result;
    }

    public static <T> Result<T> error(Integer code, String message) {
        Result<T> result = new Result<>();
        result.setCode(code);
        result.setMessage(message);
        result.setTimestamp(System.currentTimeMillis());
        return result;
    }
}
```

### 2.3 状态码定义

| 状态码 | 说明 |
|--------|------|
| 200 | 成功 |
| 400 | 请求参数错误 |
| 401 | 未认证 |
| 403 | 无权限 |
| 404 | 资源不存在 |
| 409 | 业务冲突（如已报名、时间冲突） |
| 500 | 服务器内部错误 |

### 2.4 分页响应格式

```java
@Data
public class PageResult<T> {
    private List<T> records;
    private Long total;
    private Long pages;
    private Long current;
    private Long size;
}
```

## 3. 安全规范

### 3.1 JWT Token设计
- Access Token有效期：2小时
- Refresh Token有效期：7天
- Token存储位置：前端localStorage或Cookie(httpOnly)

### 3.2 接口权限控制

```java
// 使用注解控制接口权限
@PreAuthorize("hasRole('ADMIN')")      // 仅管理员
@PreAuthorize("hasRole('STUDENT')")    // 仅学生
@PreAuthorize("isAuthenticated()")     // 已登录用户
```

### 3.3 密码安全
- 使用BCrypt加密存储
- 密码强度：至少8位，包含字母和数字

## 4. 接口设计规范

### 4.1 RESTful API规范

| 操作 | HTTP方法 | URL示例 |
|------|----------|---------|
| 创建 | POST | `/api/activities` |
| 查询 | GET | `/api/activities/{id}` |
| 更新 | PUT | `/api/activities/{id}` |
| 删除 | DELETE | `/api/activities/{id}` |
| 列表 | GET | `/api/activities` |

### 4.2 URL命名规范
- 使用小写字母和连字符
- 使用复数名词表示资源集合
- 版本号放在URL中：`/api/v1/...`

### 4.3 请求参数规范

**查询参数示例**：
```
GET /api/activities?status=1&page=1&size=10&keyword=运动
```

**请求体示例**：
```json
{
    "name": "校园篮球赛",
    "description": "年度篮球比赛",
    "startTime": "2025-06-01 09:00:00",
    "endTime": "2025-06-01 17:00:00",
    "location": "体育馆",
    "maxParticipants": 100
}
```

## 5. 日志规范

### 5.1 日志级别使用
- ERROR：系统错误，需要立即处理
- WARN：警告信息，潜在问题
- INFO：重要业务操作日志
- DEBUG：调试信息（生产环境关闭）

### 5.2 日志格式
```yaml
logging:
  pattern:
    console: "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n"
```

## 6. 数据校验规范

使用Jakarta Validation进行参数校验：

```java
@Data
public class ActivityCreateRequest {
    @NotBlank(message = "活动名称不能为空")
    @Size(max = 100, message = "活动名称不能超过100个字符")
    private String name;

    @NotNull(message = "开始时间不能为空")
    @Future(message = "开始时间必须是未来时间")
    private LocalDateTime startTime;

    @NotNull(message = "结束时间不能为空")
    private LocalDateTime endTime;

    @Min(value = 1, message = "人数上限至少为1")
    @Max(value = 10000, message = "人数上限不能超过10000")
    private Integer maxParticipants;
}
```

## 7. 异常处理规范

### 7.1 自定义业务异常

```java
@Getter
public class BusinessException extends RuntimeException {
    private final Integer code;

    public BusinessException(Integer code, String message) {
        super(message);
        this.code = code;
    }
}
```

### 7.2 全局异常处理

```java
@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(BusinessException.class)
    public Result<?> handleBusinessException(BusinessException e) {
        return Result.error(e.getCode(), e.getMessage());
    }

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Result<?> handleValidationException(MethodArgumentNotValidException e) {
        String message = e.getBindingResult().getFieldErrors().stream()
            .map(FieldError::getDefaultMessage)
            .collect(Collectors.joining(", "));
        return Result.error(400, message);
    }
}
```

## 8. 开发环境配置

### 8.1 application.yml 示例

```yaml
server:
  port: 8080

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/campus_activity?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
    username: root
    password: ${DB_PASSWORD}

  jackson:
    date-format: yyyy-MM-dd HH:mm:ss
    time-zone: Asia/Shanghai

mybatis-plus:
  mapper-locations: classpath:/mapper/**/*.xml
  global-config:
    db-config:
      id-type: auto
      logic-delete-field: deleted
      logic-delete-value: 1
      logic-not-delete-value: 0
  configuration:
    map-underscore-to-camel-case: true

jwt:
  secret: ${JWT_SECRET}
  expiration: 7200000
  refresh-expiration: 604800000
```
