以下文档在原有代码风格约定基础上,已同步并补充当前项目实际实现的约定(例如:使用 Jakarta 包、异常基类为 RuntimeException、拦截器 token 优先级等)。请以此文档为团队规范。
work.baiyun.chronicdiseaseappSpringAPP、WeChatController、UserServicegetOpenid、generateToken、addInterceptorsweChatService、username、authInterceptorTOKEN_TTL_HOURS、REFRESH_THRESHOLD_HOURSMALE、FEMALEa + b。method(a, b, c)。if (condition)。jakarta.servlet.*, jakarta.validation.*),而非旧的 javax.* 命名空间。/** */。示例:
/**
* 性别枚举,数据库存储为整数:1=男, 2=女
*/
public enum Gender { ... }
/** */ 注释字段,描述字段含义并可配合 @Schema 等注解提供文档。@Getter, @Setter, @RequiredArgsConstructor 等)以减少样板代码。以下约定是从当前代码实现中抽取的,文档应与代码保持一致。
@EnumValue(MyBatis-Plus)标记用于数据库存储的值。getCode()、getDescription() 方法;通常还包含 fromCode(int) 的静态方法用于反序列化,以及 toString() 返回描述字符串。示例(摘自 work.baiyun.chronicdiseaseapp.enums.Gender):
public enum Gender {
MALE(1, "男"),
FEMALE(2, "女");
@EnumValue
private final int code;
private final String description;
public int getCode() { return code; }
public String getDescription() { return description; }
public static Gender fromCode(int code) { ... }
}
com.github.pagehelper.PageInfo 来计算总数,分页返回封装类为 work.baiyun.chronicdiseaseapp.common.Page<T>,并使用 Lombok 的 @Getter/@Setter。CustomException 继承自 RuntimeException(运行时异常),由全局异常处理器 CustomExceptionHandler 处理。@RestControllerAdvice,并处理如下异常类型:
BindException(参数绑定错误)ConstraintViolationException(参数校验错误)CustomException(业务异常)Exception(未捕获的通用异常)work.baiyun.chronicdiseaseapp.common.R,并使用 work.baiyun.chronicdiseaseapp.enums.ExceptionResultCode 中的 code/msg。Authorization: Bearer <token> (优先,且忽略大小写的 Bearer 前缀)Authorization 未提供 token,则回退到 X-Token header 或 token headercurrentUserId(用户 id)和 currentUserRole(权限组,PermissionGroup)放入 HttpServletRequest 的 attribute 中以供 Controller 使用。示例摘录(来自 work.baiyun.chronicdiseaseapp.config.AuthInterceptor)中的行为:
// 优先处理 Authorization: Bearer <token>
String authHeader = request.getHeader("Authorization");
String xToken = request.getHeader("X-Token");
String tokenHeader = request.getHeader("token");
// 解析逻辑:优先 Authorization(支持 Bearer),回退 X-Token,再回退 token
WebMvcConfig 使用构造函数注入 AuthInterceptor(带 @Autowired 构造器),并在 addInterceptors 中注册拦截器。/**,但排除登录/Swagger/OpenAPI 相关路径,示例排除路径列表:/, /get_openid, /v3/api-docs/**, /swagger-ui/**, /doc.html, /webjars/**, /favicon.ico 等。SpringAPP 使用 @EnableKnife4j 启用 Knife4j(API 文档增强),并在 @SpringBootApplication 中排除 ThymeleafAutoConfiguration(项目未使用 Thymeleaf)。work.baiyun.chronicdiseaseapp.enums.PermissionGroup,用于表示用户权限组并用于访问控制。SYS_ADMIN(1, "管理员")DOCTOR(2, "医生")PATIENT(3, "患者")PATIENT_FAMILY(4, "患者家属")@EnumValue 标记的 code(用于数据库存储)和 description,并提供 getCode()、getDescription()、fromCode(int) 方法。R)work.baiyun.chronicdiseaseapp.common.R<T> 作为统一响应体。核心字段:
Integer code:响应码String message:提示消息T data:响应主体数据R.success(Integer code, String message) 返回无数据的成功响应R.success(Integer code, String message, T data) 返回带数据的成功响应R.fail(Integer code, String message) 返回无数据的失败响应R.fail(Integer code, String message, T data) 返回带数据的失败响应work.baiyun.chronicdiseaseapp.service.TokenService 是令牌管理的接口,重要方法:
String createToken(Long userId):为用户生成并保存新的 token,返回 token 字符串(通常在登录或刷新时调用)。AuthPrincipal validateToken(String token):校验 token 并返回 AuthPrincipal(包含 userId 与 PermissionGroup);若 token 无效或过期返回 null。实现中会处理接近过期时的续期逻辑(例如小于 24 小时时延长有效期)。void revokeToken(String token):撤销 token(例如登出时使用)。AuthPrincipal/currentUserId 作为当前请求用户的来源,而不是重新解析 token。文档已根据仓库中实际实现同步关键点,若需要我可以:
下面的片段示例展示如何在 Controller 中读取由 AuthInterceptor 放入的当前用户信息,并返回基于 R 的响应:
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import work.baiyun.chronicdiseaseapp.common.R;
@RestController
public class ExampleController {
@GetMapping("/me")
public R<Long> getCurrentUser(HttpServletRequest request) {
Long currentUserId = (Long) request.getAttribute("currentUserId");
if (currentUserId == null) {
return R.fail(401, "未登录");
}
return R.success(200, "ok", currentUserId);
}
}