Опиши цепочку обработки входящего запроса в Spring MVC
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Ответ: Цепочка обработки входящего запроса в Spring MVC
Обзор процесса
В Spring MVC входящий HTTP запрос проходит через несколько ключевых компонентов. Этот процесс называется диспетчеризацией (dispatching) и включает взаимодействие между сервлетом, фильтрами, контроллерами и видениями.
1. Попадание в DispatcherServlet
DispatcherServlet — это центральный сервлет, который является точкой входа для всех запросов в Spring MVC приложение:
// web.xml или конфигурация Boot
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/dispatcher-servlet.xml</param-value>
</init-param>
</servlet>
2. Прохождение через Filter цепь
Перед попаданием в DispatcherServlet запрос проходит через все зарегистрированные фильтры (Filters):
- CharacterEncodingFilter — установка кодировки (UTF-8)
- CorsFilter — обработка CORS
- SecurityFilter — Spring Security фильтры
- Пользовательские фильтры — ваша собственная логика
@Component
public class LoggingFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain chain) throws ServletException, IOException {
System.out.println("Request: " + request.getRequestURI());
chain.doFilter(request, response);
System.out.println("Response Status: " + response.getStatus());
}
}
3. Обработка в DispatcherServlet
Когда запрос достигает DispatcherServlet, происходит следующее:
a) Определение HandlerMapping
HandlerMapping ищет подходящий обработчик запроса по URL:
@RestController
@RequestMapping("/api/users")
public class UserController {
@GetMapping("/{id}")
public User getUser(@PathVariable Long id) {
return userService.findById(id);
}
}
Spring сопоставляет запрос GET /api/users/123 с методом getUser().
b) Получение HandlerExecutionChain
HandlerMapping возвращает HandlerExecutionChain, который содержит:
- Сам обработчик (handler)
- Список перехватчиков (Interceptors)
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new RequestTimingInterceptor())
.addPathPatterns("/api/**");
}
}
public class RequestTimingInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) {
request.setAttribute("startTime", System.currentTimeMillis());
return true;
}
@Override
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response,
Object handler, Exception ex) {
long startTime = (Long) request.getAttribute("startTime");
long duration = System.currentTimeMillis() - startTime;
System.out.println("Request took " + duration + "ms");
}
}
4. Выполнение preHandle Интерцепторов
До вызова контроллера выполняются все preHandle методы интерцепторов:
public interface HandlerInterceptor {
default boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) throws Exception {
return true; // true = продолжить, false = остановить цепь
}
}
5. Вызов HandlerAdapter и выполнение контроллера
HandlerAdapter вызывает нужный метод контроллера с параметрами, полученными из запроса:
@PostMapping("/users")
public ResponseEntity<User> createUser(@RequestBody User user,
@RequestHeader("Authorization") String token) {
User created = userService.save(user);
return ResponseEntity.status(HttpStatus.CREATED).body(created);
}
AdapterAdapter автоматически:
- Парсит JSON body в объект User
- Извлекает заголовки
- Внедряет зависимости (@Autowired сервисы)
6. Обработка ошибок (Exception Handling)
Если в контроллере возникла ошибка, она перехватывается:
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(ResourceNotFoundException.class)
public ResponseEntity<ErrorResponse> handleNotFound(ResourceNotFoundException ex) {
return ResponseEntity.status(HttpStatus.NOT_FOUND)
.body(new ErrorResponse("Not found: " + ex.getMessage()));
}
}
7. Выполнение postHandle Интерцепторов
После выполнения контроллера, но до рендеринга вида, вызываются postHandle методы:
default void postHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler,
ModelAndView modelAndView) throws Exception {
// modelAndView всё ещё может быть модифицирован здесь
}
8. Выбор ViewResolver
ViewResolver преобразует имя представления в объект View:
@Configuration
public class ViewResolverConfig {
@Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".jsp");
return resolver;
}
}
// В контроллере
@GetMapping("/users")
public String listUsers(Model model) {
model.addAttribute("users", userService.findAll());
return "users/list"; // Будет найден /WEB-INF/views/users/list.jsp
}
9. Рендеринг View
View объект рендерит ответ (HTML, JSON, XML и т.д.):
// Для REST APIs обычно используется JSON
@RestController // Автоматически сериализует в JSON
public class UserController {
@GetMapping("/users")
public List<User> getUsers() {
return userService.findAll();
}
}
10. Выполнение afterCompletion Интерцепторов
Финальный этап — все afterCompletion методы интерцепторов вызываются для очистки ресурсов:
void afterCompletion(HttpServletRequest request,
HttpServletResponse response,
Object handler,
Exception ex) throws Exception {
// Логирование ошибок, очистка ресурсов
}
Полная диаграмма процесса
HTTP Request
↓
[Filter Chain] → preHandle → postHandle → afterCompletion
↓
DispatcherServlet
↓
HandlerMapping (find matching handler)
↓
HandlerExecutionChain (handler + interceptors)
↓
[Interceptors.preHandle]
↓
HandlerAdapter (call controller method)
↓
Controller Method (@GetMapping, @PostMapping и т.д.)
↓
ModelAndView (or ResponseEntity)
↓
[Exception Handling if needed]
↓
[Interceptors.postHandle]
↓
ViewResolver (resolve view name)
↓
View.render() (generate HTML/JSON/etc)
↓
[Interceptors.afterCompletion]
↓
HTTP Response
Ключевые компоненты
| Компонент | Назначение |
|---|---|
| DispatcherServlet | Главный сервлет, управляет всем процессом |
| HandlerMapping | Находит контроллер по URL |
| HandlerAdapter | Вызывает метод контроллера |
| Interceptor | Перехватывает запрос до/после контроллера |
| ViewResolver | Переводит имя вида в объект View |
| View | Рендерит финальный ответ |
| ExceptionHandler | Обрабатывает ошибки |
Практический пример
@RestController
@RequestMapping("/api/products")
public class ProductController {
@Autowired
private ProductService productService;
@GetMapping("/{id}")
public ResponseEntity<Product> getProduct(@PathVariable Long id) {
// 1. HandlerMapping нашёл этот метод
// 2. HandlerAdapter вытащил id из URL
// 3. Вызвал этот метод
Product product = productService.findById(id);
if (product == null) {
// 4. ExceptionHandler поймает исключение (если оно выброшено)
throw new ResourceNotFoundException("Product not found");
}
// 5. ResponseEntity будет сериализован в JSON
return ResponseEntity.ok(product);
}
}
Итог
Цепочка обработки запроса в Spring MVC включает фильтры, перехватчики, маппинг, адаптеры и резолверы. Каждый компонент отвечает за определённый этап обработки, что обеспечивает модульность и гибкость фреймворка.