Spring Boot 3.5 / Java 17 OJ backend template. Root project is serve (see settings.gradle.kts), Java package space.anyi.serve. Stack and API docs are in README.md; this file only covers non-obvious gotchas.
./gradlew bootRun (serves on :8080)./gradlew test (JUnit Platform). No lint/format/typecheck or CI config exists.databaseHost, databaseUsername, databasePassword — missing any makes the app fail on first DB access. No local dev defaults are provided.oj, all tables live in the dev schema. Initialize via psql -U <user> -f sql/postgersql.sql (note the misspelled filename postgersql.sql).contextLoads test spins up the full context and needs a live PostgreSQL; it fails without one.Response<T> wrapper (Response.ok / Response.error). Validation failures map to HTTP 400; other uncaught exceptions return HTTP 200 with an error body (see GlobalExceptionHandler).Authorization: Bearer <token>. Roles are stored as plain user/coach/admin in the DB, but method-level auth requires the ROLE_ prefix — JwtAuthenticationFilter adds it, so write @PreAuthorize("hasRole('ROLE_admin')"). Only /auth/login, /auth/register, and swagger paths are public.@Resource injection, services use constructor injection.public static final constants in the entity class they belong to (e.g. User.ROLE_ADMIN, Contest.STATUS_RUNNING, Submission.STATUS_AC, Problem.DIFFICULTY_EASY). Use those constants instead of hardcoded string/number literals everywhere in Java code. Exception: SpEL annotation strings (@PreAuthorize("hasRole('ROLE_admin')")), the "ROLE_" + role authority-prefix concatenation, Swagger @Schema/@Parameter description text, and MyBatis XML (which cannot reference Java constants, e.g. status = 'AC' in SubmissionMapper.xml) keep literals — when adding a literal to a mapper XML, mirror the matching entity constant and keep the value in sync.deleteFlag), so deletes are logical. Entities target schema-qualified tables via @TableName("dev.user"). Mapper XML lives in src/main/resources/mapper/.JwtTokenProvider, 24h expiry, using the jjwt 0.12 API (verifyWith/parseSignedClaims)./swagger-ui/index.html.space.anyi.codesandbox)space.anyi.codesandbox(与 space.anyi.serve 平级,不在 serve 包内)。实现未接入 Spring Bean,直接 new JVMNativeCodeSandBox() 调用;CodeSandBox 是接口,控制器/服务依赖抽象。CodeContext.maxMemory 单位为 KB(与 Submission.memoryUsedKb 一致),拼接为 -Xmx<kb>k 传给子 JVM;maxTime 单位为毫秒。不要传字节值(会把 256MB 变成 256GB)。\t/\r)与末尾空行(outputMatches)。MAX_CONCURRENT(默认 10),超限 tryAcquire(5s) 失败返回 SE「系统繁忙」。超时/异常路径由 destroyForcibly() 杀子进程,临时目录 code/<uuid> 在 finally 中删除,不得在早退路径遗漏。javac/java 取 JAVA_HOME(回退 java.home),需指向含 javac/java 的 JDK;环境为 JDK 17 时测试可运行(Gradle toolchain 为 17)。JVMNativeCodeSandBoxTest 需真实 JDK/JVM 子进程,不依赖数据库。UserDto, LoginDto) and return concrete VOs for responses (e.g. UserVo), never raw User entities or generic maps.@Tag/@Operation on controllers and methods, and @Schema on both request DTOs and response VOs (class-level and per-field). Follow the existing DTO/VO examples.UserService), implementations live in service/impl/ (UserServiceImpl). Don't let controllers reference impl classes directly.oj. Commit messages use the # feat: ... / # sql: ... prefix style from git log.