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

Как JBoss понимает с чего начинать выполнение кода

1.7 Middle🔥 81 комментариев
#Spring Framework

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

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

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

# Как JBoss понимает с чего начинать выполнение кода

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

JBoss (WildFly) использует стандартное Java веб-приложение развёртывание (deployment) на основе дескриптора развёртывания (deployment descriptor) и конфигурации. Точка входа зависит от типа приложения - для веб-приложений это Servlet, для EJB это аннотации и конфиг, для микросервисов это точка входа Spring/Quarkus.

Основные механизмы запуска

1. Для Web приложений (WAR)

JBoss ищет точку входа в файле web.xml (deployment descriptor):

<!-- WEB-INF/web.xml -->
<web-app>
    <!-- Определяем listener - он запускается первым -->
    <listener>
        <listener-class>com.example.MyAppListener</listener-class>
    </listener>
    
    <!-- Определяем основной servlet -->
    <servlet>
        <servlet-name>MainServlet</servlet-name>
        <servlet-class>com.example.MainServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    
    <servlet-mapping>
        <servlet-name>MainServlet</servlet-name>
        <url-pattern>/api/*</url-pattern>
    </servlet-mapping>
</web-app>

Порядок запуска:

  1. ServletContextListener.contextInitialized() - инициализация приложения
  2. Servlet с load-on-startup - загружаются в порядке номеров
  3. Остальные сервлеты - загружаются при первом обращении

2. Слушатель (Listener) контекста

@WebListener
public class ApplicationStartupListener implements ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        System.out.println("Приложение запущено");
        ServletContext context = sce.getServletContext();
        // Инициализация БД, кешей, пула соединений
        initializeDatabase();
        initializeCaches();
    }
    
    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        System.out.println("Приложение остановлено");
        // Очистка ресурсов
        closeConnections();
    }
}

3. Фильтры (Filters)

@WebFilter(urlPatterns = "/*", order = 1)
public class LoggingFilter implements Filter {
    @Override
    public void init(FilterConfig config) {
        System.out.println("Фильтр инициализирован");
    }
    
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, 
                        FilterChain chain) throws IOException, ServletException {
        // Выполняется ДО сервлета
        System.out.println("Request: " + ((HttpServletRequest)request).getRequestURI());
        chain.doFilter(request, response);
        // Выполняется ПОСЛЕ сервлета
        System.out.println("Response sent");
    }
}

Для EJB приложений

JBoss использует аннотации для определения точки входа:

@Singleton
@Startup
@Lock(LockType.READ)
public class StartupBean {
    // Этот бин загружается при запуске JBoss
    
    @PostConstruct
    public void initialize() {
        System.out.println("EJB Startup Bean инициализирован");
        loadConfiguration();
        startBackgroundServices();
    }
}

Stateless EJB для обработки запросов

@Stateless
public class OrderService {
    @EJB
    private DatabaseService dbService;
    
    public Order getOrder(Long orderId) {
        return dbService.findOrder(orderId);
    }
}

Для Spring Boot приложений на JBoss

@SpringBootApplication
public class MyApplication {
    
    @Bean
    public ApplicationRunner applicationRunner() {
        return args -> {
            System.out.println("Spring Boot приложение запущено на JBoss");
            // Выполняется в момент запуска приложения
        };
    }
    
    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }
}

Конфигурация JBoss (jboss-web.xml)

<!-- jboss-web.xml определяет параметры для JBoss -->
<jboss-web>
    <!-- Context path приложения -->
    <context-root>/myapp</context-root>
    
    <!-- Использование JNDI datasource -->
    <resource-ref>
        <res-ref-name>jdbc/MyDS</res-ref-name>
        <jndi-name>java:/MyDS</jndi-name>
    </resource-ref>
    
    <!-- Конфигурация сессии -->
    <session-config>
        <tracking-mode>COOKIE</tracking-mode>
    </session-config>
</jboss-web>

Процесс загрузки приложения в JBoss

1. JBoss START
   ↓
2. Сканирование развёртываемых приложений (WAR/EAR)
   ↓
3. Чтение web.xml, jboss-web.xml, @WebListener аннотаций
   ↓
4. Создание ServletContext
   ↓
5. Вызов ServletContextListener.contextInitialized()
   ↓
6. Инициализация Filter-ов с load-on-startup
   ↓
7. Инициализация Servlet-ов с load-on-startup
   ↓
8. Приложение ГОТОВО к получению запросов
   ↓
9. Первый HTTP запрос → Router → нужный Servlet/Filter
   ↓
10. Выполнение кода обработчика (handler)

Практический пример: полный цикл

// 1. Listener инициализирует приложение
@WebListener
public class AppStartupListener implements ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        System.out.println("1. Инициализация приложения");
        ServletContext ctx = sce.getServletContext();
        ctx.setAttribute("startTime", System.currentTimeMillis());
    }
}

// 2. Filter обрабатывает все запросы
@WebFilter(urlPatterns = "/*")
public class RequestLoggingFilter implements Filter {
    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) 
            throws IOException, ServletException {
        System.out.println("2. Filter: входящий запрос");
        chain.doFilter(req, res);
        System.out.println("3. Filter: исходящий ответ");
    }
}

// 3. Servlet обрабатывает конкретный запрос
@WebServlet(urlPatterns = "/api/orders/*", loadOnStartup = 1)
public class OrderServlet extends HttpServlet {
    @Override
    public void init() {
        System.out.println("4. Servlet инициализирован");
    }
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse res) 
            throws ServletException, IOException {
        System.out.println("5. Servlet: обработка GET запроса");
        res.getWriter().println("Orders list");
    }
}

// Порядок вывода при первом запросе:
// 1. Инициализация приложения (один раз)
// 4. Servlet инициализирован (один раз)
// 2. Filter: входящий запрос (на каждый запрос)
// 5. Servlet: обработка GET запроса (на каждый запрос)
// 3. Filter: исходящий ответ (на каждый запрос)

Определение точки входа

JBoss определяет точку входа по:

  1. web.xml - стандартный дескриптор развёртывания
  2. Аннотации (@WebServlet, @WebFilter, @WebListener)
  3. Порядок загрузки - load-on-startup определяет порядок инициализации
  4. URL routing - сопоставление URL с обработчиком
  5. Конфигурация jboss-web.xml - специфические для JBoss параметры

Для микросервисов (если JBoss используется с microservices)

# Если используется Quarkus/Smallrye:
quarkus.application.name=my-service
quarkus.http.port=8080

# main (EntryPoint):
@QuarkusMain
public class Main {
    public static void main(String[] args) {
        Quarkus.run(args);
    }
}

Итоги

JBoss понимает с чего начинать выполнение кода через:

  • web.xml - дескриптор развёртывания с listener и servlet-ами
  • Аннотации - @WebListener, @WebServlet, @WebFilter
  • load-on-startup - параметр, определяющий порядок инициализации
  • ServletContextListener - слушатель события инициализации контекста
  • URL routing - сопоставление URL с нужным обработчиком
  • jboss-web.xml - конфигурация специфичная для JBoss

Это стандартизованный способ развёртывания Java веб-приложений на любом application server-е (Tomcat, WildFly, GlassFish и т.д.).