Skip to content

Embedded jetty server (часть 1)

Синопсис

В этом посте мы создадим небольшое приложение, которое будет поднимать jetty веб-сервер. Приложение будет из себя представлять простой джарник с main методом, в котором будет запускаться jetty сервер. В дальнейшем (это уже будет другой пост) мы до вешаем на наш веб сервер веб сокеты и REST колы. Специально для REST колов мы переделаем джарник в варник с сохранением функции запускаемого приложения, почему так будет понятно позже. А сейчас приступим к созданию простого приложения, которое поднимает jetty сервер, а сейчас это будет jar-архив, который будет запускаться как обычное java-приложение, а позже, когда мы переделаем его в war-архив, он так же будет запускаться как обычное java приложение, несмотря на то, что это будет варник, и так же будет одновременно еще и вэб прилжением, который можно будет положить в контейнер сервлетов.

Готовый проект можно взять с gitHub по ссылке: https://github.com/dev-blogs/JettyServer

Реквайментс

  1. Java
  2. Maven
  3. Eclipse

Структура проекта

Проект будет из себя представлять мавенское приложение, создавать его будем в гуевой среде eclipse в операционной системе виндовс 7. И так запускаем eclipse, доставляем к нему мавенский плагин если кто еще этого не сделал (о том как доставлять к eclipse мавенский плагин написано в этом посте) и создаем в нем мавенский проект.
Берем мышку в руки, выбираем пункты меню Филе->Нев->Отхерс… (File->New->Others…), в появившимся диалоговом окне New находим тип проекта Maven в котором выбираем сабтайп проекта Maven Project. Все должно выглядеть так:

1
На следующем шаге ничего не выбираем, а просто кликаем на Next:

2
На третьем шаге выбираем дефолтовый маванский проект квикстарт:

3
На четвертом шаге определяем группу, артифакт и версию для нашего проекта, пусть это будет соответственно out.task, JettyWebSocket и 0.0.1-SNAPSHOT:

4
Нажимаешь на Finish и проект добавится в Паскаджехплорер (па-ска-джех-пло-рер или Package Explorer) эклипса:

5

JettWebSocket
    ├──src
    │   ├─main
    │   │  └─java
    │   │     └─our
    │   │        └─task
    │   │            └─JettyWebSocket
    │   │                └─JettyStarter.java
    │   └─test
    │      └─java
    │         └─our
    │            └─task
    │                └─JettyWebSocket
    └──pom.xml

Java классы

JettyStarter.java

Начнем с добавления класса our.task.JettyWebSocket.JettyStarter:

package our.task.JettyWebSocket;

import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.handler.ResourceHandler;

public class JettyStarter {
	public static void main(String [] args) {
		Server server = new Server();
        ServerConnector connector = new ServerConnector(server);
        connector.setPort(8080);
        server.addConnector(connector);

        // add handler
        ResourceHandler resource_handler = new ResourceHandler();
        resource_handler.setDirectoriesListed(true);
        resource_handler.setWelcomeFiles(new String[]{ "index.html" });
        resource_handler.setResourceBase(".");
        
        server.setHandler(resource_handler);

        try {
            server.start();
            server.join();
        } catch (Throwable t) {
            t.printStackTrace(System.err);
        }
	}
}

Теперь исправим xml файл pom.xml файл, но сначала посмотрим на его дефолтовую версию. В дефолтовую версию было автоматически включена группа проекта, его артифакт айди, версия и какой пакет будет на выходе, в данном случае это jar архив. Кроме того в pom.xml включена зависимость на junit но на старую версию джейюнита 3.8.1:

pom.xml — исходный

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>our.task</groupId>
  <artifactId>JettyWebSocket</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>JettyWebSocket</name>
  <url>http://maven.apache.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
</project>

Исправим xml файл pom.xml в соответствии с нашими нуждами. То что подсвечено, это было добавлено или изменено:

pom.xml — измененный

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>our.task</groupId>
  <artifactId>JettyWebSocket</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>JettyWebSocket</name>
  <url>http://maven.apache.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <dependencies>
  	<!-- Server, ServerConnector -->
  	<dependency>	
		<groupId>org.eclipse.jetty</groupId>
		<artifactId>jetty-server</artifactId>
		<version>9.1.3.v20140225</version>
	</dependency>
	
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
  
  <build>
    <plugins>
      <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>exec-maven-plugin</artifactId>
        <version>1.3.2</version>
	  </plugin>
	</plugins>
   </build>
</project>

Артифакт jetty-server группы org.eclipse.jetty необходим для обеспечения проекта классами Server и ServerConnector, то есть, для того чтобы мы могли воспользоваться этими классами, нам нужно подключить к проекту библиотеку jetty-server версии 9.1.3.v20140225 в котором находятся данные классы. Так как это эклсипс, то для того, чтобы подключить необходимые библиотеки, мы обычно идем в меню Projects->Properties, далее появляется окно Properties for ProjectName, выбираем категорию Java Build Path, в появившейся категории Java Build Path выбираем вкладку Libraries, затем нажимаем на кнопку Add External JARs… и в открывшемся диалоговом окне ищем необходимую библиотеку в файловой системе. Но сегодня мы создаем мавенский проект, стало быть этого всего делать на надо, так как что именно искать (какую библиотеку) мы сообщили мавену в pom.xml файле, и далее мавен уже без нас отыщет необходимый джарник (естественно не в файловой системе, а в удаленном репозитории) и подключит его к проекту . О том, что мавен нашел и подключил необходимые джарники (не сейчас, а после выполнения мавенской команды), мы можем увидеть на той же вкладке Libraries появится раскрывающийся список библиотек Maven Dependencies:

8
Мы видим, что нужная библиотека в проекте есть и подключена. Но откуда взялись другие библиотеки, например jetty-http-9.1.3.v20140225.jar или jetty-util-9.1.3.v20140225.jar? Их то мы не указывали в pom.xml. Дело в том, что когда мы подключаем какую-нибудь одну библиотеку, скорее всего, для ее работы нужны другие библиотеки, называемые зависимостями, которые указаны в ее собственном pom.xml файле, и которые тоже будут подтягиваться вместе с нужной нам библиотекой, это и объясняет почему их так много.

Info
И в этом пожалуй главное преимущество мавена, то что он берет на себя подтягивание сторонних зависимостей, мы бы задолбались искать причину почему проект не компилится, если бы мы подключили к проекту только один джарник, который в свою очередь для успешной компиляции требует кучу других

На этом этапе мы можем только скомпилировать проект, а нам бы хотелось еще его запускать из эклипса. Сделать это можно с помощью мавенского плагина exec-maven-plugin, который мы подключили в pom.xml файле в теге builds:

<build>
   <plugins>
      <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>exec-maven-plugin</artifactId>
        <version>1.3.2</version>
      </plugin>
   </plugins>
</build>

После этого мы можем кликнуть правой кнопкой по проекту выбрать Run As->Maven install и после этого мавен подтянет все плагины и либы:

9

Как подтянуть исходники

Не стал бы я использовать для этого примера эклсипс если бы у него не было возможности заглянуть в исходники любого класса, который мавен нам вытянул из репозитория. Надеюсь заглядывать в исходники умеют все, для этого на клавиатуре зажимаем кнопочку ктрл а мышкой кликаем по интересующему нас классу. Однако, если мы так сделаем, то мы не увидим ничего, потому что мавен вытягивает из репозитория только исполняемые классы. Для того, чтобы можно было просмотреть исходники, нам нужно их вытянуть из того же репозитория, но другой командой, эта команда:

mvn dependency:sources

Выкачались сорсы хорошо, но нам надо еще долго и нудно их подключать к эклсипсовскому проекту, это не удобно особенно если их много, поэтому было бы неплохо если бы эклипс умел все делать сам, и выкачивать и подключить, как это он делает с исполняемыми библиотеками, мы ведь эти библиотеки к нему не подключвали, мы только запустили мавенскую команду, и эклипс подлючил эти библиотеки к проекту сам. Конечно же эклипс это умеет делать и с исходниками тоже. Для этого заходим в окно Рун Конфигуратионс (Run->Run Configurations…) добавляем новую конфигурацию путем клика на самой левой верхней кнопке New launch configuration, выбираем Base direcotry кликнув на кнопку Browse Workspace… в поле Goals вводим dependency:sources и нажимаем кнопку Run:

10
После этого эклипс начнет подтягивать исходники. О том, что он их подтянул можно убедиться (по мимо клика на классе) если мы откроем окно Properties for ProjectName, выберем вкладку Libraries, развернем список подтянутых мавеном библиотек Maven Dependencies и развернем один из джарников, например jetty-server-9.1.3.v20140225.jar и посмотрим путь к исходникам в свойстве Source attachment. Мы должны увидеть название файла исходников jetty-server-9.1.3.v20140225-sources.jar и путь к нему C:\Users\zheka\.m2\repository\org\eclipse\jetty\jetty-server\9.1.3.v20140225:

11

Запуск проекта

Теперь мы почти готовы запустить мавенский проект, но надо еще кое-что сделать, нам надо добавить конфигурацию, где надо указать запускающий класс, то есть класс с main методом.
Для этого выбираем пункты меню Рун->Рун Конфигуратионс… (Run->Run Configurations…) появится окно Run Configurations:

6
После того как это окно появится, нажмите на маленькую кнопочку New lounch configurations, которая находится в самом верхнем левом углу (не отмечена красным маркером) и заполните все остальные поля в этой конфигурации. Нам надо создать конфигурацию, которая заменяет такую строку в командлайне:

mvn exec:java -Dexec.mainClass="our.task.WebSocket.JettyStarter"

Сначала выбираем Base Workspace для этого кликаем на одноименную кнопку и выбираем текущий проект. В поле Goals добавляем текст exec:java, добавляем параметр с именем exec.mainClass со значением our.task.WebSocket.JettyStarter.
После того как все добавлено, нажимаем кнопку Run

[INFO] Scanning for projects...
[INFO] 
[INFO] Using the builder org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder with a thread count of 1
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building JettyWebSocket 0.0.1-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO] 
[INFO] --- exec-maven-plugin:1.3.2:java (default-cli) @ JettyWebSocket ---
WARNING Warning: killAfter is now deprecated. Do you need it ? Please comment on MEXEC-6.
2014-10-16 12:49:07.950:INFO::our.task.JettyWebSocket.JettyStarter.main(): Logging initialized @2333ms
2014-10-16 12:49:07.998:INFO:oejs.Server:our.task.JettyWebSocket.JettyStarter.main(): jetty-9.1.3.v20140225
2014-10-16 12:49:08.047:INFO:oejs.ServerConnector:our.task.JettyWebSocket.JettyStarter.main(): Started ServerConnector@26b38c81{HTTP/1.1}{0.0.0.0:8080}
2014-10-16 12:49:08.047:INFO:oejs.Server:our.task.JettyWebSocket.JettyStarter.main(): Started @2430ms

Тест

Если все запустилось без ошибок, то при вводе в браузере адреса http://localhost:8080 должна появится страница Directory:

7

Ссылки

Get source JARs from Maven repository
How do I create an embedded WebSocket server Jetty 9?
jetty server push example
3 ways to run Java main from Maven

Поделиться в социальных сетях

Опубликовать в Google Plus
Опубликовать в LiveJournal
Опубликовать в Мой Мир
Опубликовать в Одноклассники
Опубликовать в Яндекс