# serve Spring Boot 3.5 + Java 17 + MyBatis-Plus + PostgreSQL + JWT auth backend. ## Quick start ```bash # env vars required by application.yaml export databaseHost=localhost databaseUsername=postgres databasePassword=postgres # build & test ./gradlew build # run ./gradlew bootRun # run a single test class ./gradlew test --tests 'space.anyi.serve.ServeApplicationTests' ``` ## Architecture - **Single module**, root package `space.anyi.serve`. - **Entrypoint**: `src/main/java/space/anyi/serve/ServeApplication.java` - **Security**: Stateless JWT in `Authorization: Bearer ` header. Public endpoints: `/auth/login`, `/auth/register`, `/swagger-ui/**`, `/v3/api-docs/**`. Everything else requires auth. Roles: `ROLE_admin`, `ROLE_user`, `ROLE_expert`. Method-level security via `@PreAuthorize`. - **ORM**: MyBatis-Plus `BaseMapper` + `ServiceImpl`. Logical delete field = `deleteFlag`. Mapper XML at `src/main/resources/mapper/`. - **DB**: PostgreSQL, schema `dev`. Credentials from env vars. Druid connection pool. - **API docs**: Swagger UI at `http://localhost:8080/swagger-ui.html` (SpringDoc OpenAPI). - **CORS**: Allows `http://localhost:5173` (Vite dev server). - **Exception handling**: `GlobalExceptionHandler` returns `Response` JSON (`code`, `message`, `data`). - **Pagination**: `PageVo` wraps MyBatis-Plus `Page`. ## Conventions - `@PreAuthorize("hasRole('admin')")` for admin-only endpoints. - `application.yaml` uses `${placeholder}` for secrets; never hardcode credentials. - SQL logging to stdout via MyBatis-Plus `log-impl: StdOutImpl`. - Actuator endpoints fully exposed (`management.endpoints.web.exposure.include: "*"`). - No Dockerfile, no CI, no Makefile.