Spring Boot 3 patterns for controllers, services, configuration, and validation
Spring Boot 3.x best practices for enterprise Java APIs. Architecture and clarity over framework tricks.
Read only files relevant to the request. Use the content map to focus.
| File | Description | When to Read |
|---|---|---|
layered-arch.md |
Controller -> Service -> Repository | Architecture design |
rest-api.md |
REST endpoints, DTOs, validation | API development |
configuration.md |
@ConfigurationProperties, profiles | Config and envs |
exceptions.md |
@ControllerAdvice, ProblemDetail | Error handling |
observability.md |
Actuator, logging, metrics | Production readiness |
Controller -> Service -> Repository
Keep controllers thin, services own business rules, repositories focus on data access.
@RestController
@RequestMapping("/api/v1/users")
@RequiredArgsConstructor
@Validated
public class UserController {
private final UserService userService;
@GetMapping("/{id}")
public UserResponse findById(@PathVariable String id) {
return userService.findById(id)
.map(UserResponse::from)
.orElseThrow(() -> new ResourceNotFoundException("User", id));
}
@PostMapping
@ResponseStatus(HttpStatus.CREATED)
public UserResponse create(@Valid @RequestBody CreateUserRequest request) {
return UserResponse.from(userService.create(request.toCommand()));
}
}
public record CreateUserRequest(
@NotBlank @Email String email,
@NotBlank @Size(min = 2, max = 100) String name
) {
public CreateUserCommand toCommand() {
return new CreateUserCommand(email, name);
}
}
@ConfigurationProperties(prefix = "app")
@Validated
public record AppProperties(
@NotBlank String name,
@NotNull SecurityProperties security
) {
public record SecurityProperties(
@NotBlank String jwtSecret,
@Positive int jwtExpirationMinutes
) {}
}
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(ResourceNotFoundException.class)
public ProblemDetail handleNotFound(ResourceNotFoundException ex) {
return ProblemDetail.forStatusAndDetail(HttpStatus.NOT_FOUND, ex.getMessage());
}
}
| Anti-Pattern | Why Bad | Better Approach |
|---|---|---|
| Business logic in controller | Hard to test | Move to service |
| Field injection | Hidden deps | Constructor injection |
| Entity in response | Leaks internals | DTO pattern |
| open-in-view true | Hidden queries | Fetch explicitly |
| Need | Skill |
|---|---|
| Data access | @[skills/spring-data-jpa] |
| Security | @[skills/spring-security] |
| Testing | @[skills/spring-testing] |