Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
# Servlet в Spring
Да, Spring построен на основе Servlet, хотя в повседневной работе разработчики редко работают с Servlet напрямую.
Архитектура: Servlet как фундамент
Spring Web (Spring MVC) работает на базе Java Servlet API:
HTTP запрос
↓
Servlet Container (Tomcat, Jetty)
↓
DispatcherServlet (Spring)
↓
Controllers → Services → Repositories
↓
HTTP ответ
DispatcherServlet - фронт-контроллер Spring
// Spring автоматически регистрирует этот Servlet
public class DispatcherServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// Маршрутизация запроса к контроллерам
// Обработка исключений
// Сериализация ответа
}
}
Kогда вы создаёте @Controller с @GetMapping, Spring под капотом использует DispatcherServlet для обработки HTTP запросов.
Как это работает в Spring Boot
In Spring Boot конфигурация Servlet автоматична:
// application.properties
server.servlet.context-path=/api // Путь Servlet'а
server.port=8080 // Порт
// Java конфигурация (скрыта в Spring Boot)
@Configuration
public class ServletConfig {
@Bean
public DispatcherServlet dispatcherServlet(ApplicationContext context) {
return new DispatcherServlet(context);
}
}
Когда можно работать с Servlet напрямую
1. Кастомные фильтры
@Component
public class LoggingFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain filterChain)
throws ServletException, IOException {
System.out.println("Request: " + request.getRequestURI());
filterChain.doFilter(request, response);
System.out.println("Response status: " + response.getStatus());
}
}
Фильтры работают ДО DispatcherServlet и могут модифицировать запрос/ответ.
2. Кастомные Servlet
@Component
public class CustomServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
resp.setContentType("text/plain");
resp.getWriter().println("Custom Servlet");
}
}
// Регистрация
@Configuration
public class ServletRegistration {
@Bean
public ServletRegistrationBean<CustomServlet> customServlet() {
ServletRegistrationBean<CustomServlet> bean =
new ServletRegistrationBean<>(new CustomServlet(), "/custom/*");
return bean;
}
}
Используется редко, когда нужна специфическая обработка на низком уровне.
3. Доступ к HttpServletRequest/Response в контроллере
@RestController
@RequestMapping("/api/users")
public class UserController {
// Spring внедрит HttpServletRequest из Servlet API
@GetMapping("/{id}")
public ResponseEntity<User> getUser(
@PathVariable Long id,
HttpServletRequest request, // Servlet API
HttpServletResponse response) { // Servlet API
String userAgent = request.getHeader("User-Agent");
String sessionId = request.getSession().getId();
response.setHeader("X-Custom-Header", "value");
return ResponseEntity.ok(new User(id, "John"));
}
}
Servlet контекст в Spring
@Component
public class ServletContextHelper {
@Autowired
private ServletContext servletContext; // Доступ к контексту
public void logServletInfo() {
System.out.println("Server info: " + servletContext.getServerInfo());
System.out.println("Context path: " + servletContext.getContextPath());
}
}
Spring WebFlux - альтернатива без Servlet
Приемущественно для микросервисов и высоконагруженных систем:
// Spring WebFlux (основан на Netty, НЕ Servlet)
@RestController
@RequestMapping("/api/users")
public class UserHandler {
@GetMapping("/{id}")
public Mono<User> getUser(@PathVariable Long id) {
return userService.getUserAsync(id);
}
}
Условия использования:
- Много одновременных подключений (10k+)
- Non-blocking операции (асинхронный код)
- Микросервисная архитектура
Сравнение
| Аспект | Spring MVC (Servlet) | Spring WebFlux (Async) |
|---|---|---|
| Основа | HttpServlet | Netty, non-blocking |
| Модель | Синхронная | Асинхронная (Mono/Flux) |
| Потоки | 1 поток = 1 запрос | Несколько потоков на множество запросов |
| Зависимости | Полно (JPA, Template Engines) | Ограничено (только reactive) |
| Сложность | Простая, привычная | Выше, нужна reactive логика |
| Production примеры | 95% Java приложений | Netflix, Uber (высоконагруженные) |
Жизненный цикл Servlet
public class DispatcherServlet extends HttpServlet {
// 1. init() - один раз при запуске
@Override
public void init(ServletConfig config) throws ServletException {
super.init(config);
// Инициализация Spring контекста
}
// 2. service() - для каждого запроса
@Override
protected void service(HttpServletRequest req, HttpServletResponse res) {
// Обработка HTTP запроса
super.service(req, res);
}
// 3. destroy() - при остановке
@Override
public void destroy() {
// Очистка ресурсов
}
}
Вывод
- Servlet — это базис Spring Web — DispatcherServlet наследует HttpServlet
- Обычно не используешь напрямую — Spring скрывает сложность за абстракциями
- Доступен когда нужен — фильтры, кастомные сервлеты, прямой доступ к HttpServletRequest
- Есть альтернатива — Spring WebFlux для асинхронных систем
- Знание Servlet важно для понимания того, как работает Spring под капотом
То есть: Spring на Servlet'ах, но ты кодишь на более высокоуровневых абстракциях (@Controller, @Service). Это хороший пример дизайна — скрывать сложность для удобства разработчика.