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

Какой класс запускает методы у Controller в Spring?

2.0 Middle🔥 191 комментариев
#ООП#Основы Java

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

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

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

Какой класс запускает методы у Controller в Spring?

Это фундаментальный вопрос о том, как Spring обрабатывает HTTP запросы и маршрутизирует их к методам контроллеров. Ответ — это DispatcherServlet, но давайте разберемся глубже.

Главный класс: DispatcherServlet

DispatcherServlet — это центральный сервлет, который перехватывает все входящие HTTP запросы и маршрутизирует их к соответствующим контроллерам:

// Spring автоматически регистрирует DispatcherServlet
// Для каждого запроса вызывается:
// DispatcherServlet.doDispatch(HttpServletRequest, HttpServletResponse)

// Когда вы делаете:
GET http://localhost:8080/api/users/123

// DispatcherServlet:
// 1. Получает запрос
// 2. Ищет подходящий Handler (контроллер + метод)
// 3. Выполняет цепочку интерцепторов
// 4. Запускает методы контроллера
// 5. Обрабатывает ответ

Архитектура обработки запроса

Полный путь запроса в Spring:

HTTP Request -> DispatcherServlet (главный сервлет) -> HandlerMapping (поиск контроллера и метода) -> Interceptors.preHandle() -> Controller method (ваш метод) -> Interceptors.postHandle() -> ViewResolver -> Interceptors.afterCompletion() -> HTTP Response

Жизненный цикл обработки в Spring

// Упрощенный код DispatcherServlet
public class DispatcherServlet extends FrameworkServlet {
    
    protected void doDispatch(HttpServletRequest request, 
                              HttpServletResponse response) {
        try {
            // 1. Поиск Handler (контроллер + метод)
            HandlerExecutionChain chain = getHandler(request);
            // chain содержит: controller метод + interceptors
            
            // 2. Получение HandlerAdapter (адаптер для вызова метода)
            HandlerAdapter adapter = getHandlerAdapter(chain);
            
            // 3. Выполнить preHandle перехватчиков
            for (HandlerInterceptor interceptor : chain.getInterceptors()) {
                if (!interceptor.preHandle(request, response, chain.getHandler())) {
                    return;  // Прервать обработку
                }
            }
            
            // 4. Запустить метод контроллера (КЛЮЧЕВОЙ МОМЕНТ)
            ModelAndView mav = adapter.handle(request, response, chain.getHandler());
            // adapter вызывает через reflection ваш метод контроллера
            
            // 5. Выполнить postHandle перехватчиков
            for (HandlerInterceptor interceptor : chain.getInterceptors()) {
                interceptor.postHandle(request, response, chain.getHandler(), mav);
            }
            
            // 6. Отправить ответ
            render(mav, request, response);
            
        } catch (Exception ex) {
            // Обработка исключений
        }
    }
}

HandlerMapping — поиск контроллера

HandlerMapping определяет, какой контроллер и какой метод должны обработать запрос:

// Spring использует несколько HandlerMappings в порядке приоритета:

// 1. RequestMappingHandlerMapping (самый распространенный)
// Обрабатывает @RequestMapping, @GetMapping и т.д.
@RestController
@RequestMapping("/api/users")
public class UserController {
    @GetMapping("/{id}")
    public User getUser(@PathVariable Long id) {
        // Этот метод запустит DispatcherServlet
        // через RequestMappingHandlerMapping
        return userService.findById(id);
    }
}

HandlerAdapter — вызов метода

HandlerAdapter отвечает за фактический вызов методов контроллера через reflection:

// RequestMappingHandlerAdapter (для аннотированных методов)
public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter {
    
    public ModelAndView handle(HttpServletRequest request,
                               HttpServletResponse response,
                               Object handler) throws Exception {
        // 1. Разобрать параметры из request
        // 2. Преобразовать их к типам параметров метода
        // 3. Вызвать метод через reflection
        // 4. Преобразовать результат в ответ
        
        return handleInternal(request, response, (HandlerMethod) handler);
    }
}

Пример: как Spring запускает ваш метод

@RestController
@RequestMapping("/api/users")
public class UserController {
    
    @PostMapping
    public ResponseEntity<User> createUser(@RequestBody CreateUserRequest request) {
        User user = new User(request.getName(), request.getEmail());
        return ResponseEntity.status(HttpStatus.CREATED).body(user);
    }
}

// Что происходит:
// 1. DispatcherServlet получает POST /api/users запрос
// 2. RequestMappingHandlerMapping находит метод createUser
// 3. RequestMappingHandlerAdapter:
//    a) Читает @RequestBody
//    b) Десериализует JSON в CreateUserRequest
//    c) Через reflection вызывает: createUser(request)
//    d) Получает результат (ResponseEntity)
//    e) Сериализует ответ в JSON
// 4. DispatcherServlet возвращает HTTP 201 с телом

Важные классы Spring

Класс DispatcherServlet играет роль главного сервлета и входную точку. HandlerMapping отвечает за поиск контроллера по URL. RequestMappingHandlerMapping обрабатывает аннотации. HandlerAdapter запускает методы контроллера. RequestMappingHandlerAdapter — адаптер для аннотированных методов. HandlerInterceptor работает как перехватчики. ArgumentResolver преобразует параметры. ReturnValueHandler преобразует результат метода в ответ. HandlerExceptionResolver обрабатывает исключения.

Debugging: как увидеть процесс

// Добавь логирование Spring
// application.properties
logging.level.org.springframework.web.servlet.mvc.method.annotation=DEBUG
logging.level.org.springframework.web.servlet.DispatcherServlet=DEBUG
logging.level.org.springframework.web.servlet.mvc=DEBUG

// Или создай свой HandlerInterceptor для видимости
@Component
public class DebugInterceptor implements HandlerInterceptor {
    
    @Override
    public boolean preHandle(HttpServletRequest request, 
                             HttpServletResponse response, 
                             Object handler) {
        System.out.println("Handler: " + handler);
        if (handler instanceof HandlerMethod) {
            HandlerMethod method = (HandlerMethod) handler;
            System.out.println("Controller: " + method.getBean().getClass().getName());
            System.out.println("Method: " + method.getMethod().getName());
        }
        return true;
    }
}

Многопоточность

Важно знать: DispatcherServlet один на все приложение, но он потокобезопасен:

// Один экземпляр DispatcherServlet обрабатывает все запросы
// Каждый запрос выполняется в отдельном потоке
// DispatcherServlet разработан для многопоточности

// Поэтому:
// - Контроллеры обычно stateless
// - Services могут быть безопасно синглтонами
// - Избегай state в контроллерах

Итог

DispatcherServlet — это класс, который запускает методы контроллеров в Spring. Он перехватывает все HTTP запросы, использует HandlerMapping для поиска контроллера, использует HandlerAdapter для вызова метода через reflection, обрабатывает перехватчики, параметры и результаты, возвращает HTTP ответ. Это фундаментальная архитектура Spring MVC, которая делает возможным управление HTTP запросами в Java приложениях.

Какой класс запускает методы у Controller в Spring? | PrepBro