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

Что в иерархии находится над сессией

2.0 Middle🔥 111 комментариев
#ORM и Hibernate#Базы данных и SQL

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

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

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

Иерархия выше Session в веб-приложениях

Краткий ответ

В иерархии веб-приложения Session находится внутри ServletContext, и выше неё расположены следующие уровни:

ApplicationContext (Application scope) — доступно всему приложению
  ↓
ServletContext — общие ресурсы для всех сессий
  ↓
HttpSession (Session scope) — данные пользователя в сессии
  ↓
HttpServletRequest (Request scope) — данные конкретного запроса

1. HttpServletRequest (Request Scope)

Это самый нижний уровень, содержит данные конкретного HTTP запроса:

@WebServlet("/login")
public class LoginServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) 
            throws ServletException, IOException {
        // Request scope — это данные ВНЕ сессии
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        
        // Проверка аутентификации
        if (authenticate(username, password)) {
            // Сохраняем пользователя в сессию (Session scope)
            HttpSession session = request.getSession(true);
            session.setAttribute("user", username);
            session.setAttribute("loginTime", new Date());
            
            response.sendRedirect("/dashboard");
        }
    }
}

Жизненный цикл Request:

1. Клиент отправляет HTTP запрос
2. Сервер создаёт HttpServletRequest
3. Сервлет обрабатывает запрос
4. Сервер отправляет ответ
5. HttpServletRequest удаляется из памяти

2. HttpSession (Session Scope)

Session содержит данные, которые сохраняются между запросами одного пользователя:

public class DashboardServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) 
            throws ServletException, IOException {
        // Получаем сессию
        HttpSession session = request.getSession(false);
        
        if (session == null) {
            // Нет сессии — перенаправляем на login
            response.sendRedirect("/login");
            return;
        }
        
        // Получаем данные из сессии (они сохранены от предыдущего запроса)
        String user = (String) session.getAttribute("user");
        Date loginTime = (Date) session.getAttribute("loginTime");
        
        // Сессия существует 30 минут (или пока пользователь активен)
    }
}

// Фильтр для отслеживания активности сессии
@WebFilter("/*")
public class SessionFilter implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, 
                        FilterChain chain) throws IOException, ServletException {
        HttpServletRequest httpReq = (HttpServletRequest) request;
        HttpSession session = httpReq.getSession(false);
        
        if (session != null) {
            // Сессия будет истечать через 30 минут неактивности
            long lastActivity = (Long) session.getAttribute("lastActivity");
            long now = System.currentTimeMillis();
            
            if (now - lastActivity > 30 * 60 * 1000) {
                // Сессия устарела
                session.invalidate();
            } else {
                // Обновляем время активности
                session.setAttribute("lastActivity", now);
            }
        }
        
        chain.doFilter(request, response);
    }
}

3. ServletContext (Application Scope)

ServletContext содержит данные, которые доступны всему приложению (всем пользователям):

// Инициализация при запуске приложения
@WebListener
public class AppContextListener implements ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        ServletContext context = sce.getServletContext();
        
        // Данные доступны всему приложению
        context.setAttribute("appVersion", "1.0.0");
        context.setAttribute("appName", "MyApp");
        
        // Инициализация БД pool'а (доступен всем потокам)
        DataSource dataSource = initializeDataSource();
        context.setAttribute("dataSource", dataSource);
        
        // Глобальный счётчик пользователей
        context.setAttribute("activeUsers", new AtomicInteger(0));
    }
    
    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        // Очистка ресурсов при выключении приложения
        ServletContext context = sce.getServletContext();
        DataSource ds = (DataSource) context.getAttribute("dataSource");
        if (ds != null) {
            // Закрыть соединения
        }
    }
}

// Использование в сервлете
public class MainServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) 
            throws ServletException, IOException {
        ServletContext context = getServletContext();
        
        // Доступ к приложению scope данным
        String appVersion = (String) context.getAttribute("appVersion");
        DataSource dataSource = (DataSource) context.getAttribute("dataSource");
        AtomicInteger activeUsers = (AtomicInteger) context.getAttribute("activeUsers");
        
        // Увеличиваем счётчик активных пользователей
        activeUsers.incrementAndGet();
        
        response.getWriter().println("App: " + appVersion);
        response.getWriter().println("Active users: " + activeUsers.get());
    }
}

ServletContext жизненный цикл:

1. Сервер запускается
2. Сервер создаёт ServletContext для приложения
3. Вызывает ServletContextListener.contextInitialized()
4. Все сервлеты и фильтры могут обращаться к контексту
5. Сервер выключается
6. Вызывает ServletContextListener.contextDestroyed()
7. ServletContext удаляется

4. ApplicationContext (Spring Framework)

В Spring это находится ещё выше — это вся конфигурация приложения:

// Spring Boot Application
@SpringBootApplication
public class MyApp {
    public static void main(String[] args) {
        SpringApplication.run(MyApp.class, args);
        // ApplicationContext создаётся и инициализируется
    }
}

// Spring beans живут в ApplicationContext
@Configuration
public class AppConfig {
    
    @Bean
    public DataSource dataSource() {
        // Этот bean создаётся один раз для всего приложения
        return new HikariDataSource();
    }
    
    @Bean
    public JdbcTemplate jdbcTemplate(DataSource dataSource) {
        return new JdbcTemplate(dataSource);
    }
}

// Доступ к ApplicationContext из сервлета
@RestController
public class MainController {
    private final ApplicationContext context;
    
    @Autowired
    public MainController(ApplicationContext context) {
        this.context = context;
    }
    
    @GetMapping("/beans")
    public List<String> getBeans() {
        // Доступ ко всем beans в ApplicationContext
        return Arrays.asList(context.getBeanDefinitionNames());
    }
}

Полная иерархия в Spring WebMvc

┌─────────────────────────────────────┐
│     ApplicationContext (Spring)     │  ← Application Scope (синглтоны)
│  - Все beans (Services, DAOs)       │
│  - Конфигурация приложения          │
│  - Жизненный цикл: Spring up → down │
└──────────────────┬──────────────────┘
                   │
┌──────────────────▼──────────────────┐
│   ServletContext (всё приложение)   │  ← Application Scope (Servlet)
│  - initParameters                   │
│  - shared attributes                │
│  - Доступ: getServletContext()      │
└──────────────────┬──────────────────┘
                   │
┌──────────────────▼──────────────────┐
│  HttpSession (один пользователь)    │  ← Session Scope
│  - user ID                          │
│  - preferences                      │
│  - Доступ: request.getSession()     │
│  - Время жизни: 30 мин без активн.  │
└──────────────────┬──────────────────┘
                   │
┌──────────────────▼──────────────────┐
│  HttpServletRequest (один запрос)   │  ← Request Scope
│  - parameters                       │
│  - headers                          │
│  - attributes (для форвардинга)     │
│  - Доступ: в методе doGet/doPost    │
│  - Время жизни: длительность запроса│
└─────────────────────────────────────┘

Практический пример: вся иерархия в действии

@WebListener
public class MyListener implements ServletContextListener, HttpSessionListener {
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        // Application Scope
        ServletContext ctx = sce.getServletContext();
        ctx.setAttribute("appStartTime", new Date());
        System.out.println("App started");
    }
    
    @Override
    public void sessionCreated(HttpSessionEvent se) {
        // Session Scope
        HttpSession session = se.getSession();
        session.setAttribute("sessionStartTime", new Date());
        System.out.println("Session created: " + session.getId());
    }
}

@WebServlet("/example")
public class ExampleServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) 
            throws ServletException, IOException {
        // Request Scope: get parameters
        String name = req.getParameter("name");
        
        // Request Scope: forward to JSP
        req.setAttribute("message", "Hello " + name);
        
        // Session Scope
        HttpSession session = req.getSession();
        Integer visitCount = (Integer) session.getAttribute("visitCount");
        if (visitCount == null) visitCount = 0;
        visitCount++;
        session.setAttribute("visitCount", visitCount);
        
        // Application Scope
        ServletContext context = getServletContext();
        Date appStartTime = (Date) context.getAttribute("appStartTime");
        
        req.getRequestDispatcher("/example.jsp").forward(req, resp);
    }
}

Сравнение scopes

ScopeЖизненный циклДоступПримеры
RequestDuration запросаrequest.getAttribute()параметры, заголовки
Session30 мин без активностиsession.getAttribute()данные пользователя, корзина
ApplicationЗапуск-выключение приложенияcontext.getAttribute()конфиги, пулы соединений
Spring ScopeЗависит от scope bean'а@Autowiredсинглтоны, прототипы, web scopes

Итоговый вывод

В иерархии выше Session находятся:

  1. HttpServletRequest (Request scope) — самый узкий, один запрос
  2. HttpSession — один пользователь, несколько запросов
  3. ServletContext — всё приложение, все пользователи
  4. ApplicationContext (Spring) — вся инфраструктура приложения

Всё это скоординировано в слоистой архитектуре Servlet API, где каждый уровень имеет свой жизненный цикл и область видимости.