Getting started

Local development

Common commands, directory tour, configuration discipline and troubleshooting.

This page answers three questions: which commands to type, where the code lives, and where to look first when something breaks.

Common commands

CommandWhat it does
./gradlew bootRunStarts the app (Liquibase creates tables and seeds data)
./gradlew buildCompile + tests + architecture guards + contract consistency, all in one run
./gradlew testRuns tests only
./gradlew generateModule -Pname=demoSkeleton generator: module directories, migration script, test skeleton
./gradlew bootJarBuilds the runnable jar (build/libs/)

Note: a single ./gradlew build already runs compilation, tests, architecture guards, contract consistency and the formatting check. You do not run them separately.

Directory tour

minimao/
├── src/main/java/cn/minimao/
│   ├── app/<module>/{controller,service,dto,vo,convert}
│   ├── domain/handler/<module>/{cmd}
│   ├── infra/<module>/{model,mapper,repository,query}
│   ├── data/        # query and write foundation
│   ├── common/      # context, threads, exceptions
│   └── config/      # framework wiring
├── src/main/resources/
│   ├── db/changelog/   # Liquibase migrations (the only way to create tables)
│   ├── mapper/         # hand-written SQL
│   └── i18n/           # error messages in three languages
└── src/test/java/cn/minimao/{arch,behavior,support}

Configuration discipline

  • A new config key must be registered in both application.yml and .env.example; missing either fails the build.
  • Real credentials, intranet addresses and license keys never enter the repository; use <REQUIRED> as the placeholder.
  • Secrets are always injected as environment variables; .env is not versioned.

Debugging and logs

  • Every response body carries a traceId; front-end and back-end debugging use it as the single clue.
  • [] in the log means the line is not inside any request (startup, non-HTTP entry point), not that the chain was lost.
  • Access logging has exactly one print site, and phone numbers and password fields are masked by default.

Troubleshooting

SymptomLook here first
Port already in usechange server.port or stop the process; do not change framework defaults
Migration failure at startupcheck whether someone edited an already executed changeset in db/changelog
Pagination plugin unavailablemybatis-plus-jsqlparser is missing (split out since 3.5.9)
"System busy" instead of a permission errorthe error-code mapping is incomplete; no permission must return the fixed permission code
Empty traceIdconfirm it is a non-HTTP entry point (scheduled task, message consumption, startup)
Last updated 2026-10-09Edit this page →