← Назад к вопросам
Какой Scope нужно добавить контроллеру для управления ходом запросов в контроллер?
2.2 Middle🔥 201 комментариев
#Основы Java
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Scope REQUEST для управления ходом запросов в контроллер
Вопрос касается одного из ключевых аспектов Spring Framework — управления жизненным циклом bean'ов в контексте HTTP-запроса. Чтобы контроллер мог эффективно управлять ходом запросов, необходимо использовать REQUEST scope (или точнее, beans'ы с REQUEST scope в зависимостях контроллера).
Что такое REQUEST Scope
REQUEST scope — это область видимости bean'а, которая существует на протяжении одного HTTP-запроса. Каждый новый запрос получает новый экземпляр bean'а, что обеспечивает:
- Изоляцию данных между запросами
- Отсутствие race conditions в многопоточной среде
- Автоматическую очистку после завершения запроса
Как использовать REQUEST Scope в контроллере
// Сервис с REQUEST scope
@Component
@Scope(WebApplicationContext.SCOPE_REQUEST)
public class RequestTracker {
private String requestId;
private LocalDateTime startTime;
private Map<String, Object> requestAttributes = new HashMap<>();
public void initRequest() {
this.requestId = UUID.randomUUID().toString();
this.startTime = LocalDateTime.now();
}
public void setAttribute(String key, Object value) {
requestAttributes.put(key, value);
}
public String getRequestId() {
return requestId;
}
}
// Контроллер использует REQUEST-scoped сервис
@RestController
@RequestMapping("/api/users")
public class UserController {
private final UserService userService;
private final RequestTracker requestTracker; // REQUEST scope
@Autowired
public UserController(UserService userService, RequestTracker requestTracker) {
this.userService = userService;
this.requestTracker = requestTracker;
}
@GetMapping("/{id}")
public ResponseEntity<UserDTO> getUser(@PathVariable Long id) {
requestTracker.initRequest();
logger.info("Request ID: {}", requestTracker.getRequestId());
User user = userService.findById(id);
requestTracker.setAttribute("userFound", user != null);
return ResponseEntity.ok(new UserDTO(user));
}
}
Альтернативные Scope'ы
// SESSION scope — существует на протяжении сессии пользователя
@Component
@Scope(WebApplicationContext.SCOPE_SESSION)
public class UserSession {
private User currentUser;
}
// APPLICATION scope (SINGLETON) — один экземпляр на всё приложение
@Component
@Scope(WebApplicationContext.SCOPE_APPLICATION)
public class AppConfig {
private ApplicationProperties properties;
}
// PROTOTYPE — новый экземпляр каждый раз при инъекции
@Component
@Scope(WebApplicationContext.SCOPE_PROTOTYPE)
public class RequestProcessor {
}
Практический пример с управлением ходом запроса
@Component
@Scope(WebApplicationContext.SCOPE_REQUEST)
public class RequestContextManager {
private String correlationId;
private List<String> executionSteps = new ArrayList<>();
private boolean isProcessing = false;
public void startProcessing() {
this.correlationId = UUID.randomUUID().toString();
this.isProcessing = true;
executionSteps.add("Processing started at " + LocalDateTime.now());
}
public void addExecutionStep(String step) {
executionSteps.add(step);
}
public void completeProcessing() {
isProcessing = false;
executionSteps.add("Processing completed at " + LocalDateTime.now());
}
public List<String> getExecutionLog() {
return new ArrayList<>(executionSteps);
}
}
@RestController
@RequestMapping("/api/orders")
public class OrderController {
private final OrderService orderService;
private final RequestContextManager requestManager;
@PostMapping
public ResponseEntity<OrderDTO> createOrder(@RequestBody CreateOrderRequest request) {
requestManager.startProcessing();
try {
requestManager.addExecutionStep("Validating order...");
Order order = orderService.validateAndCreate(request);
requestManager.addExecutionStep("Order created with ID: " + order.getId());
requestManager.completeProcessing();
return ResponseEntity.status(HttpStatus.CREATED).body(new OrderDTO(order));
} catch (Exception e) {
requestManager.addExecutionStep("Error: " + e.getMessage());
throw e;
}
}
}
Важные моменты
- Request scope требует web-контекста: работает только в Spring MVC или WebFlux приложениях
- Не используй request-scoped beans в Singleton'ах: это приводит к AOP proxy проблемам
- Потокобезопасность: REQUEST scope автоматически обеспечивает безопасность, т.к. каждый поток имеет свой bean
Использование REQUEST scope позволяет контроллерам эффективно управлять состоянием на протяжении жизненного цикла одного HTTP-запроса.