← Назад к вопросам

Опиши цепочку обработки входящего запроса в Spring MVC

2.4 Senior🔥 131 комментариев
#Spring Framework

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Ответ: Цепочка обработки входящего запроса в 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 включает фильтры, перехватчики, маппинг, адаптеры и резолверы. Каждый компонент отвечает за определённый этап обработки, что обеспечивает модульность и гибкость фреймворка.

Опиши цепочку обработки входящего запроса в Spring MVC | PrepBro