Spring Web MVC Advanced
Deep Knowledge: Use
mcp__documentation__fetch_docswith technology:spring-webfor comprehensive documentation.
Quick Start
@RestController
@RequestMapping("/api/v1")
@RequiredArgsConstructor
public class ApiController {
private final RestClient restClient;
@GetMapping("/proxy/{id}")
public ResponseEntity<Resource> proxyRequest(@PathVariable Long id) {
return restClient.get()
.uri("/external/resource/{id}", id)
.retrieve()
.toEntity(Resource.class);
}
}
@Configuration
public class RestClientConfig {
@Bean
public RestClient restClient(RestClient.Builder builder) {
return builder
.baseUrl("https://api.external.com")
.defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
.connectTimeout(Duration.ofSeconds(5))
.readTimeout(Duration.ofSeconds(30))
.build();
}
}
RestClient Essentials (Spring 6.1+)
RestClient is the new synchronous HTTP client replacing RestTemplate.
@Service
@RequiredArgsConstructor
public class UserApiClient {
private final RestClient restClient;
// GET
public UserDto getUser(Long id) {
return restClient.get()
.uri("/users/{id}", id)
.retrieve()
.body(UserDto.class);
}
// POST
public UserDto createUser(CreateUserRequest request) {
return restClient.post()
.uri("/users")
.body(request)
.retrieve()
.body(UserDto.class);
}
// With error handling
public UserDto getUserSafe(Long id) {
return restClient.get()
.uri("/users/{id}", id)
.retrieve()
.onStatus(HttpStatusCode::is4xxClientError, (req, res) -> {
throw new ResourceNotFoundException("User not found: " + id);
})
.body(UserDto.class);
}
}
Full Reference: See http-clients.md for complete RestClient and WebClient documentation.
ResponseEntity Quick Patterns
@RestController
@RequestMapping("/api/v1/users")
public class UserController {
// Created with Location
@PostMapping
public ResponseEntity<UserResponse> create(
@Valid @RequestBody CreateUserRequest req,
UriComponentsBuilder uriBuilder) {
UserResponse created = service.create(req);
URI location = uriBuilder.path("/api/v1/users/{id}")
.buildAndExpand(created.getId()).toUri();
return ResponseEntity.created(location).body(created);
}
// With ETag
@GetMapping("/{id}")
public ResponseEntity<UserResponse> get(@PathVariable Long id) {
UserResponse user = service.findById(id);
return ResponseEntity.ok()
.eTag("\"" + user.getVersion() + "\"")
.cacheControl(CacheControl.maxAge(60, TimeUnit.SECONDS))
.body(user);
}
// No Content
@DeleteMapping("/{id}")
public ResponseEntity<Void> delete(@PathVariable Long id) {
service.delete(id);
return ResponseEntity.noContent().build();
}
}
Full Reference: See patterns.md for ResponseEntity, Content Negotiation, and Streaming.
File Upload/Download Quick Start
// Upload
@PostMapping("/upload")
public ResponseEntity<FileResponse> upload(@RequestParam("file") MultipartFile file) {
String fileName = storageService.store(file);
return ResponseEntity.ok(new FileResponse(fileName, file.getSize()));
}
// Download
@GetMapping("/download/{fileName}")
public ResponseEntity<Resource> download(@PathVariable String fileName) {
Resource resource = storageService.loadAsResource(fileName);
return ResponseEntity.ok()
.contentType(MediaType.APPLICATION_OCTET_STREAM)
.header(HttpHeaders.CONTENT_DISPOSITION,
"attachment; filename=\"" + fileName + "\"")
.body(resource);
}
Full Reference: See file-handling.md for complete file operations.
Interceptors Quick Start
@Slf4j
@Component
public class LoggingInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) {
MDC.put("requestId", UUID.randomUUID().toString());
request.setAttribute("startTime", System.currentTimeMillis());
log.info("==> {} {}", request.getMethod(), request.getRequestURI());
return true;
}
@Override
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response,
Object handler, Exception ex) {
long duration = System.currentTimeMillis() -
(Long) request.getAttribute("startTime");
log.info("<== {} ({} ms)", response.getStatus(), duration);
MDC.clear();
}
}
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(loggingInterceptor).addPathPatterns("/api/**");
}
}
Full Reference: See advanced.md for Interceptors, Argument Resolvers, Exception Handling, and Testing.
Best Practices
| Do | Don't | |----|-------| | Use RestClient for sync calls (Spring 3.2+) | Use deprecated RestTemplate | | Configure explicit timeouts | Rely on default timeouts | | Implement retry with exponential backoff | Retry immediately without delay | | Use interceptors for centralized logging | Log in each method | | Wrap responses in ResponseEntity | Return raw objects |
When NOT to Use This Skill
- Reactive applications - Use
spring-webfluxskill - Basic REST controllers - Use
spring-restskill - WebSocket communication - Use
spring-websocketskill - GraphQL APIs - Use
spring-graphqlskill
Anti-Patterns
| Anti-Pattern | Problem | Solution | |--------------|---------|----------| | Using RestTemplate | Deprecated, not type-safe | Use RestClient (sync) or WebClient (async) | | No timeout configuration | Requests hang indefinitely | Configure connect/read timeout | | Memory leak with streams | Stream not closed | Use try-with-resources | | N+1 HTTP calls | Calls in loop | Use batch endpoints or parallel calls | | Blocking in WebFlux | .block() in reactive stack | Keep chain reactive |
Quick Troubleshooting
| Problem | Diagnostic | Fix | |---------|------------|-----| | Connection timeout | Check network/firewall | Configure proper timeout values | | SSL handshake fails | Check certificates | Configure SSLContext properly | | Response not mapped | Check Content-Type | Configure message converters | | Interceptor not called | Check registration | Verify interceptor order | | File upload fails | Check size limits | Configure multipart settings |
Reference Files
| File | Content | |------|---------| | http-clients.md | RestClient, WebClient, Interceptors | | patterns.md | ResponseEntity, Content Negotiation, Streaming | | file-handling.md | File Upload, Download, Storage Service | | advanced.md | Argument Resolvers, HandlerInterceptors, Exception Handling, Testing |
Scan to join WeChat group