Spark — Потрясающий веб-микрофреймворк для Java

image

Небольшое вступление


Spark — это просто чудесный микрофреймворк для создания веб-приложений на джаве без особых усилий.  Spark стремится к простоте и обеспечивает только минимальный набор функций. Тем не менее он предоставляет все необходимое для создания веб-приложения, которые поместятся в несколько строк кода. С синтаксисом, вдохновленным Sinatra, код выглядит очень чистым.

Давайте начнем со вездесущого хеллоуворлда.

Создаём новый проект и импортируем Spark. Лично я использую maven для управления зависимостями.

Добавляем в pom.xml.

<dependency>
    <groupId>com.sparkjava</groupId>
    <artifactId>spark-core</artifactId>
    <version>2.6.0</version>
</dependency>

Теперь приступим непосредственно к «хеллоу ворлду».

import static spark.Spark.*;

public class Main {
    public static void main(String[] args) {
        get("/hello", (req, res) -> "Hello, World!");
    }
}

Вот и всё. Всё настолько просто!

Теперь spark прослушивает GET запросы на /hello. Всякий раз, когда мы переходим на  localhost:4567/hello, вызывается метод handle(). Внутри него мы возвращаем объект, который должен быть отправлен клиенту (в этом случае «Hello World»).

Лично мое мнение, что данный код настолько лаконичный, что даже не требует пояснений.

Стоп-стоп. Что насчет запуска/остановки сервера?

  1. Остановка — надо всего лишь вызвать метод stop().
  2. Запуск — а вот здесь все интересно.  Сервер автоматически запускается, когда вы делаете что-то, что требует запуска сервера (я знаю что звучит действительно странно). Но можно запустить и вручную, вызвав метод init().

Поддержка шаблонизаторов


Хотел бы затронуть такую тему как шаблонизаторы. Спарк имеет большую нативную поддержку оных. А именно:

  • Velocity
  • Freemarker
  • Mustache
  • Handlebars
  • Jade
  • Thymeleaf
  • Pebble
  • Water
  • jTwig
  • Jinjava
  • Jetbrick

Для всех них есть «обёртки» от спарка. Для примера давайте рассмотрим мой любимый Freemarker.

Для начала давайте импортируем доп. зависимость.

 <dependency>
            <groupId>com.sparkjava</groupId>
            <artifactId>spark-template-freemarker</artifactId>
            <version>2.5.5</version>
        </dependency>

Создадим шаблон «hello.ftl» в директории src/main/resources.

<html>
<head>
</head>
<body>
    <h1>Hello, ${name}!</h1>
</body>
</html>

Теперь надо сконфигурировать freemarker дабы он искал шаблоны в ресурсах. Это всего лишь 4 строчки кода.

FreeMarkerEngine freeMarkerEngine = new FreeMarkerEngine();
Configuration freeMarkerConfiguration = new Configuration();
freeMarkerConfiguration.setTemplateLoader(new ClassTemplateLoader(Main.class, "/"));
freeMarkerEngine.setConfiguration(freeMarkerConfiguration);

Вот и всё, можно спокойно использовать фримаркер.

get("/", (request, response) -> {
        Map<String, Object> model = new HashMap<>();
        model.put("name", "Freemarker");
        return freeMarkerEngine.render(new ModelAndView(model, "hello.ftl"));
});



Почти полноценный проект


Давайте напишем, какой-то лёгкий, но достаточный что бы показать хотя бы малую часть возможностей спарка? Мне из того что можно реально быстро написать, пришел в голову только сокращатель ссылок. Что ж, начнем?

Надо добавить еще одну зависимость Google Guava. В итоге у нас получается 3 зависимости.

    <dependencies>
        <dependency>
            <groupId>com.sparkjava</groupId>
            <artifactId>spark-core</artifactId>
            <version>2.6.0</version>
        </dependency>
        <dependency>
            <groupId>com.sparkjava</groupId>
            <artifactId>spark-template-freemarker</artifactId>
            <version>2.5.5</version>
        </dependency>
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>23.0</version>
        </dependency>

Нам Guava нужна, потому что в ней реализована хэш-функция Murmur3. Весь плюс в том что она достаточно сильна устойчива к коллизиям. Так же что бы не тратить лишнее время, мы будем все данные хранить только в переменных, без всяких бд и т.д.

Сделаем костяк программы.


staticFileLocation("/static");
get("/shortener", (request, response) -> {
});
get("/:url", (request, response) -> {
});

:url это параметр который можно достать через метод params(). К примеру:

get("/hello/:name", (request, response) -> {
    return "Hello: " + request.params(":name");
});

Что-то я отвлекся, продолжим.

Создадим коллекцию(Map) для хранения, настроим шаблонизатор(как я говорил freemarker мой любимый, так что будет именно он) и укажем спарку где у нас будут храниться статистические файлы. staticFiles.location("/static") укажет ему что файлы будут лежать в src/main/resources/static. К примеру файл /static/css/style.css будет доступен по адресу http://{host}:{port}/css/style.css. Если же вы хотите хранить файлы предположим в /var/www/public_html, тогда используем метод staticFiles.externalLocation("/var/www/public_html").

 ConcurrentHashMap<String, String> urls = new ConcurrentHashMap<String, String>();
        FreeMarkerEngine freeMarkerEngine = new FreeMarkerEngine();
        Configuration freemarkerConfiguration = new Configuration();
        freemarkerConfiguration.setTemplateLoader(new ClassTemplateLoader(Main.class, "/templates/"));
        freeMarkerEngine.setConfiguration(freemarkerConfiguration);
        staticFileLocation("/static");

Настроим перенаправление.

 get("/:url", (request, response) -> {
            if(urls.containsKey(request.url()))
                response.redirect(urls.get(request.url()));
            response.redirect("/");
            return null;
        });

Теперь когда пользователь переходит по короткой ссылке, если ссылка есть в коллекции, мы перемещаем его на нужный сайт, если нету, то на главную.

Давайте поработаем с фронтендом, а то мы совсем про него забыли. Начнем с главной.
Здесь мы создадим простую минималистическую форму. И еще запихнем шрифтик Proxima Nova. Заигрался конечно… ну да ладно.

<!DOCTYPE html> 
<html lang="en" style="height:100%;">
<head> 
    <meta charset='utf-8'>
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <div id="main"> 
        <form action="/shortener" method="GET">
            <input type="text" id="input" name="url" autocomplete="off" autofocus size="44" maxlength="512" />
	 </form>
    </div>
</body>     
</html>

@font-face {
    font-family: Proxima Nova;
    src: url(pn.otf);
}
* {
    font-family: Proxima Nova;
    background: #2a2826;
    color: #9C9C9C;
    margin: 0;
    padding: 0;
}
body, html {
    height: 100%;

}
#main {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 100%;
    font-size: 1.5em;

}
#input {
    border: none;
    outline:none;
    font-size: 1.5em;
}

В итоге все это добро выглядит так.



Теперь страница на которую будет выводится ссылка «shortener.ftl».


<!DOCTYPE html>
<html lang="en" style="height:100%;">
<head>
    <meta charset='utf-8'>
    <link rel="stylesheet" href="style.css">
</head>
<body>
<div id="main" style="text-align: center">
    ${url}
</div>
</body>
</html>

Итоговая структура проекта.



Что ж, дописываем последние строки. В итоге Main класс, выглядит так.

import com.google.common.hash.Hashing;
import freemarker.cache.ClassTemplateLoader;
import freemarker.template.Configuration;
import spark.ModelAndView;
import spark.Request;
import spark.Response;
import spark.template.freemarker.FreeMarkerEngine;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import static spark.Spark.*;

public class Main {
    public static void main(String[] args) {
        ConcurrentHashMap<String, String> urls = new ConcurrentHashMap<String, String>();
        FreeMarkerEngine freeMarkerEngine = new FreeMarkerEngine();
        Configuration freemarkerConfiguration = new Configuration();
        freemarkerConfiguration.setTemplateLoader(new ClassTemplateLoader(Main.class, "/templates/"));
        freeMarkerEngine.setConfiguration(freemarkerConfiguration);
        staticFileLocation("/static");
        get("/shortener", (request, response) -> {
            String shortURL = "http://localhost:4567/" +
                    Hashing.murmur3_32().hashString(request.queryParams("url"), StandardCharsets.UTF_8).toString();
            Map<String, Object> model = new HashMap<>();
            if(!urls.containsKey(shortURL)) {
                model.put("url", shortURL);
                urls.put(shortURL, request.queryParams("url"));
                return freeMarkerEngine.render(new ModelAndView(model, "shortener.ftl"));
            }
            model.put("url", shortURL);
            return freeMarkerEngine.render(new ModelAndView(model, "shortener.ftl"));
        });
        get("/:url", (request, response) -> {
            if(urls.containsKey(request.url()))
                response.redirect(urls.get(request.url()));
            response.redirect("/");
            return null;
        });
    }
}

Вот и всё. 41 строка кода и мы написали сокращатель ссылок.

Заключение


На этом моменте, я закончу эту немного затянувшуюся «Getting started» статью. Мне очень жаль что в рунете этот проект обошли стороной. Если вам понравится, я продолжу писать о Spark`е и раскрою больше его возможностей.

Ссылки


Сайт проекта
Исходные коды SparkJava
Share post

Similar posts

AdBlock has stolen the banner, but banners are not teeth — they will be back

More
Ads

Comments 67

    +2

    Интересно, как легко гуглить вопросы по этому микрофреймворку? Ведь есть еще Apache Spark, а Big Data сейчас в почете

      +1
      Гуглить по sparkjava. Да, трудно, пока собирал про него информацию измучался.
        0

        Почему же разработчики не переименуют проект? Для таких микрофреймворков это не должно быть проблемой

          0

          Я, честно говоря, не помню, подходили ли Apache Spark PMC к товарищам из sparkjava, но PMC не сильно парится насчёт совпадения названия, т. к. существенно разные области и это не мешает трейдмарку Apache Spark.

            0

            Я не думаю, что это будет каким-то образом мешать Apache Spark, но я сейчас работаю над проектом Apache Spark с Java API и при гуглении spark java мне этот фреймворк ниразу не попадался. Хотя может это гугл такой умный, фильтрует поиск для меня

              0
              Я гуглил spark web framework.
        0
        Cisco Spark, Chevrolet Spark…
          0

          Не согласен, не пересекающиеся ниши, а вот сабж и Apache Spark — оба фреймворка имеют Java API

          0
          Участвовал в двух проектах со спарком как-то. В целом не было проблемой поискать в гугле. Просто запросы писал поподробнее. На самом деле искать что-то по нему вполне можно)
          0

          На сколько оно легковесно и что с поддержкой стандартов?
          Например, есть undertow, часть проекта WildFly (ex. JBoss). Jar весит около мегабайта, чистый сервер ест всего 4Мб хипа. Но самый большой плюс — поддержка стандартов (Servlet 3.1, JSR-356 для вебсокетов).

            +2
            Spark – это сахар поверх jetty: github.com/perwendel/spark/blob/master/pom.xml

            Но самый большой плюс — поддержка стандартов (Servlet 3.1, JSR-356 для вебсокетов).

            Servlet API – это крутой стандарт, но он уже монстроузорный :-(

            Servlet API – это не HTTP стандарт, это абстракция над гораздо большим количеством протоколов. С чистым Servlet API крайне неудобно работать. И над ним делают еще парочку абстракций, чтобы добавить удобства. А потом это все выливается в довольно медленный код и раздутый хип.

            Servlet API нужно омолаживать; его уже нужно чем-то заменить! Делать какой-то Java HTTP API.
              –9
              Бредишь? Очень удобная штука, главно врубиться.
                +3
                Чистый Servlet API – крайне неудобная вещь.
                • Нужно оверрайдить нужные http методы сервлетов (doGet, doPost, etc).
                • Нужно приводить ServletRequest в HttpServletRequest.
                • Нужно самому руками вычитывать энтити из InputStream и парсить их!!
                • Нужно так же делать сериализацию энтитей и писать в OutputStream!!

                Где же тут удобство?

                Фреймворки и дополнительные уровни абстракций появляются потому, что сервлеты в чистом виде – это боль и унижение.
                  –6
                  Точно бредишь :) Я на wildfly держу несколько проектов. Сериализация-десериализация автоматом. Я оперирую только объектами. Реализация методов для запросов — это ООП, родной. Там же наследование и переопределение… для тех кто понимает конечно. С Request я напрямую вообще дел не имею, ибо JSON-API уже изобрели давно.

                    0
                    Ну вообще круто!!! /s
            0
            Мне Jooby больше нравится. Если смотреть на API, то он Spark и не отличишь, но у него: DI (via Guice) из коробки, в разы лучше документация, очень гибкая концепция модулей, поддержка роутинга в стиле JAX-RS, несколько серверов (Netty, Jetty, Undertow) на выбор и другие плюшки. Жалко комьюнити пока не очень большое, Spark поболее раскручен, конечно.

            Хотел бы затронуть такую тему как шаблонизаторы. Спарк имеет большую нативную поддержку оных.

            А server-side rendering сейчас еще нужен? Как-то казалось что сейчас микрофреймворк это для REST сервиса или для SPA.
              0
              Конечно нужен. Я использовал sparkjava для небольшого инфраструктурного сервиса. SPA городить слишком жирно, вывести-то всего пару табличек. В целом, было несколько более трудоемко, по сравнению с большими фреймворками.
                0
                Порльзуясь случаем спрошу — а что сейчас в джава мире для клиент-сайда популярно?
                Хотелось бы что-то вроде GWT, чтобы делать интерфейс из компонентов и не думать о джаваскрипте, GWT актуален ещё?
                  +2

                  Вроде бы Vaadin сейчас в моде.

                    0
                    Vaadin медленный, слишком много логики обрабатывается на стороне сервера.
                    Нынче в моде React/VueJS/Angular и прочие client-side JavaScript фреймворки.
                      0

                      А в JavaScript-фреймворках всё обрабатывается и тормозит на клиенте :3 И вообще, автор хотел обойтись без JS.

                    0
                    Если кратко, то нет, не актуален.
                    На мой взгляд это такой Delphi в java мире. Legacy думаю еще достаточно много, но вот начинать на нем что-то новое на мой взгляд не надо.
                      0
                      А аналогов не появилось?
                        0
                        Разве что какие-нибудь Kotlin или Scala.js, но они, конечно, без библиотеки виджетов, насколько я знаю. Такой себе урезанный аналог.
                        0
                        начинать на нем что-то новое на мой взгляд не надо

                        А можно услышать какие-нибудь аргументы? Просто интересно

                          0

                          Потому что он безнадежно отстал от прогресса.


                          Например Element.querySelector() уже более 5 лет доступен в браузерах, а в GWT его так и не поддержали: https://stackoverflow.com/questions/2406002/find-an-element-by-css-selector-in-gwt/3164919


                          И такие флешбеки при разработке на GWT встречаются регулярно. Хочется заиспользовать какую-нибудь браузерную особенность, а нет – GWT о ней не знает и вызвать не дает. Можно выкрутиться через JSNI, но зачем тогда вообще тащить GWT.


                          В соседних комментах предлагают Kotlin или Scala.js, в них с актуальностью все получше.

                            +1
                            Например Element.querySelector() уже более 5 лет доступен в браузерах, а в GWT его так и не поддержали

                            А зачем его вызывать вручную? Я всегда думал, что выбор элементов за меня сделает библиотека виджетов. А сделает она это через JSNI или через overlay-тип — мне какая разница? Конечно, иногда надо напрямую сделать что-то с DOM, но это настолько редко требуется, что кусочек JSNI не проблема написать. Зато остальные 99% кода пишутся на Java без проблем.


                            но зачем тогда вообще тащить GWT

                            Причина одна, но для кого-то может быть крайне весомой — возможность писать клиентский код на Java.

                        +1

                        Клиент-сайд состоит из двух частей: фреймворка и библиотеки виджетов. В качестве фреймворка довольно давно использую GWT + GQuery + RestyGWT. Доволен. Из печалек: медленная компиляция и неудобный дебаг в superdevmode. В качестве библиотеки виджетов можно использовать GWTBootstrap, GWT-Material, gwt-polymer-elements, любую CSS-based библиотеку, или даже интегрировать практически любой bullshit.js.


                        Про упомянутый Vaadin: да, подтормаживает (постоянная синхронизация состояния виджетов с сервером), спорно годится для интернет-проектов, но для энтерпрайзных админок и дэшбоардов — самое то. При помощи GWT можно использовать весь widgetset Vaadin-a на клиентской стороне без использования серверной части, что значительно разгоняет UI. Кроме того, есть полностью js-ный Vaadin Elements. Из печалек: из пресловутый Vaading Grid тормозит гораздо больше на клиенте, чем на сервере.


                        P.S. Хочу попробовать подергать Kotlin.js. Кстати, если уж о котлине заговорили, то вот фреймворк со схожим функционалом: https://github.com/Kotlin/ktor

                          0
                          GWT актуален ещё

                          Зачем вам этот тормозной монстр? Имхо проще отдельного фронтэндера иметь, чем работать с GWT...

                            0
                            Удваиваю ненужность GWT и прочих. У меня коллега интерфейсы шпарит махом на jquery чистом. Я только REST подгоняю, который JSON выдает и принимает, и все.
                              0
                              Ответил тут.
                              +2

                              Пользуясь случаем, попиарю свой проект: http://teavm.org/
                              Поддерживаются Java, Scala, Kotlin, есть Angular-образный фреймворк в комплекте

                                0
                                А насколько он аналогичен? GWT в теории хорош тем что:
                                1. Не надо писать на джаваскрипте
                                2. Можно делать гуй на высоком уровне — есть готовые компоненты
                                  +1
                                  1. В TeaVM не надо писать на JavaScript, для того он и создан
                                  2. Есть возможность делать гуй на шаблонах (с биндингом, перерисовкой только изменившегося DOM). Пишите шаблоны под bootstrap — будут и компоненты. Можно создавать свои компоненты для шаблонизатора, можно биндиться к JavaScript-компонентам (как и в GWT). Но, разумеется, т.к. мой проект пока не нашёл широкого применения, под него есть только небольшой набор стандартных компонентов.
                                  0

                                  Я думал, Вы забросили этот проект. Ан-нет, уже даже достаточно юзабельная версия! На выходных попробую. Из пожеланий: добавить автоматический генератор врапперов к JS-библиотекам из TypeScript на DefinetlyTyped.

                                  +1
                                  Вполне актуален. Последняя версия поддерживает практически все фичи из Java 8. Java 9 как компилятор обещают скоро, фичи из Java 9 чуть позже. Как и колега, иcпользую GWT + GQuery + Gin + RestyGWT, хотя и посматриваю на Dagger ‡ и RxJava. В общем, доволен как слон :)
                                +1

                                Мне всегда было интересно, как создатели таких проектов предполагают жить без reverse URL resolution.

                                  0
                                  reverse URL resolution.
                                  А не могли бы вы рассказать, что это за зверь такой?
                                  ps: за 5+ лет еще не приходилось сталкиваться с этим термином; может эта фича не столь и нужная?
                                    +1

                                    Это когда фреймворк даёт возможность сгенерировать URL для ссылки, сославшись на соответствующий роут по имени и передав нужные параметры.


                                    Например, в Рельсах:


                                    link_to "Мой профиль", @profile   # @profile — переменная с экземпляром класса Profile

                                    генерирует:


                                    <a href="/profiles/1">Мой профиль</a>
                                      0
                                      Звучит, как удобная фича с удобством для поддержки – меняешь роут, меняется и реверс урл.

                                      Но для того, чтобы она работала, нужно чтобы фреймворк на себя брал очень много обязанностей, как минимум фреймворку нужно, чтобы он знал все его роуты по именам; а чтобы это все корректно работало, то еще и по параметрам (PathParams, QueryParams, etc), т.е. сам фреймворк уже становится раздутым и сложным.

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

                                      Это без сомнения крутая фича, но в микрофреймворке она избыточна. Если нужно этот функционал можно прикрутить через стороннюю библиотеку.
                                        0
                                        В JVM-фреймворках с этим, к сожалению, печально.
                                        Искал JVM замену рельсам.
                                        Rails-alike фреймворки существуют, но почему то они не переняли некоторых удобных деталей.
                                        Эти самые URL, миграции, routes.rb с resources :foo, only: [:index, :show], лейауты. Разве что грусть-тоска по asset pipeline отпадает сама собой с появлением webpack и подобных.
                                        jruby on rails сначала показались находкой. Но jruby быстро разочаровала страшными тормозами, очень сильная деградация в зависимости от количества библиотек/кода. TDD-ить невозможно. Прелоадеры глючат. Боль короче)
                                          +1
                                          Посмотрите vibed.org
                                            0
                                            Спасибо. Забавно конечно, но не JVM (есть 3rd party библиотека, ради которой весь сыр-бор). А если устраивать межпроцессное взаимодействие а-ля микросервисы, проще взять те же рельсы и не мучиться. Да и не все привычные фичи в vibe.d есть. Не нашел route resources и миграций например.
                                            –1
                                              0
                                              Да, и почему-то роуты описываются индивидуально.
                                              Нельзя взять и объявить resources :users скажем (такая фича есть разве что в grails, но до лаконичности рельсовой версии ей далеко).
                                              Зачем это нужно? Проще менять роуты.
                                              Database Evolutions не предоставляет никакого обобщенного DSL, нужно писать сырой SQL.
                                              Да, контроля больше. Но с другой стороны, в 95% случаях мне хватало и рельсового DSL, а если уж не хватает, ничего не мешает (почти — автоотката все же не будет) написать специфичный сырой SQL.
                                              Не покидает ощущение недоделанности. При всех недостатках рельсов, у них есть основная идея — удобство разработчика (да, я понимаю, зачастую в ущерб каким-то другим вещам). И вот эту идею в JVM-фреймворках реализуют, на мой взгляд, не в полной мере.

                                              P.S. я разрабатываю и на RoR и на Java, т считаю, что RoR в JVM можно назвать лишь ее же но на jruby. Однако мне она не подошла — см. коммент выше.
                                                0
                                                Зачем это нужно? Проще менять роуты.
                                                Ну а в Play есть автокомплит для роутов и они проверяются во время компиляции.
                                                Database Evolutions
                                                Можно взять Liquibase или другую библиотеку
                                          0

                                          Я так и не нашел какого-то единого устоявшегося термина, но да, это возможность сгенерировать ссылку, исходя из обработчика или идентификатора роута и параметров.


                                          Пример из рельсов несколько чересчур магический и высокоуровневый, но суть верно передает.

                                        0

                                        Я понимаю, что это сильно за пределами вводной статьи, но это какой-то очень уж сферический пример. Поэтому у меня вопросы:


                                        1. как это все работает, когда тело метода handle() требует асинхронных операций. В базу, например сходить. И, поскольку Java многопоточная, то как обстоят дела с конкурентным доступом к одному и тому же request/response из разных потоков.
                                        2. как использовать композицию? Например, накрутить кастомную авторизацию, чтобы сбегать в базу и найти пользователя по сессии.
                                          0
                                          Я вот как раз такими же вопросами задался некоторое время назад и из этого родилось вот такое чудовище, там точно так же как и в экспрессе можно сделать чтобы несколько handlers отработали в определенном порядке.
                                          +1
                                          Хотел бы затронуть такую тему как шаблонизаторы. Спарк имеет большую нативную поддержку оных
                                          А Rocker поддерживается?
                                          github.com/fizzed/rocker
                                            0
                                            Вкратце, можно ли объяснить:
                                            1. Можно ли обойтись без Guava?
                                            2. В чем необходимость использования «хэш-функция Murmur3»?
                                            3. Можно ли Guava заменить на коллекцию из cuncerrent?
                                            Спасибо за овтеты.
                                              0
                                              1. Вполне
                                              2.
                                              Нам Guava нужна, потому что в ней реализована хэш-функция Murmur3. Весь плюс в том что она достаточно сильна устойчива к коллизиям.
                                              . Мы используем её для сокращение ссылки.
                                              3. Я и так не использую коллекции из гуавы
                                              0
                                              Как нельзя кстати! Спасибо вам огромное!

                                              Жаль, что не на волне хайпа спрашиваю, и, вполне вероятно, мой вопрос никто не заметит.
                                              Но как привязать конкретное доменном имя сайта к проекту на SparkJava?

                                              Понятное дело, что через A запись мы можем указать IP:Port, но не указывать же IP:4567. Ведь есть еще HTTPS со своим 443 портом.

                                              А если на сервере 2 сайта, то еще запутаннее становится.

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

                                              Спасибо!
                                                +1

                                                Как и с любым другим приложением: запускаете приложение на нужном порту, ставите перед ним reverse proxy (я предпочитаю nginx), который слушает 80 и 443 порты, выбирает нужный upstream на основе server_name и выполняет tls offloading, чтобы приложению не нужно было заморачиваться с tls/ssl.

                                                  0
                                                  Спасибо, изучу. Получается, что теперь reverse proxy стал обязательным пунктом. Раньше я просто использовал Apache Web Server (Httpd), в котором и прописывал сайты (на PHP, Python).
                                                    +1

                                                    Получается, что раньше вы использовали Apache HTTP Server в качестве reverse proxy для ваших приложений на php/python/whatever. Никто не мешает использовать его в этой роли, если вы ближе знакомы с его конфигами. Если у вас нагрузка маленькая (а это с вероятностью в 4 девятки так), то это не принципиально. Если захотите экономить память, то имеет смысл пощупать nginx.


                                                    Также рекомендую при запуске java-приложений явно указывать -Xmx и -Xms, чтобы ограничить потребляемую память (например, -Xmx512m ограничит верхнюю границу 512 MiB памяти в куче).

                                                      0
                                                      Если так, то опять проблема. Как связать Apache + SparkJava или Nginx + SparkJava? Нагуглить что-то толковое не получается. Возможно, что стоит сделать по аналогии с более популярным фреймворком, тогда с каким?

                                                      Про флаги виртуальномй машины для ограничения размером кучи уже в курсе. Уже использовал и Xms, Xmx и даже Xss. Спасибо.
                                                        0

                                                        Proxy pass на порт, где у вас запущено java приложение и все. От используемого фреймворка это никак не зависит

                                                          0
                                                          Благодарю вас за наводку!
                                                            –1

                                                            Только скорее в http модуле, а не в stream: https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_pass

                                                              0

                                                              Интересно, за что минус. Учитывая, что proxy_pass в stream module про проксирование L4 (tcp, udp) потоков, а не про L7 http reverse proxy.

                                                    –1
                                                    Хоть бы кто доки изучил прежде чем отвечать.
                                                    port(80);

                                                    Вот ваше решение без всяких костылей.
                                                      0
                                                      А как же SSL и 443 порт? А как же множество доменов? Выходит, что не совсем рабочее решение.
                                                        0
                                                        Все есть в доках. Будет время, напишу вторую статью.
                                                        +2

                                                        Для занятия портов меньше 1024 нужны привелегии суперпользователя.


                                                        А запускать Java-процесс с такими правами — опасная затея.

                                                          0

                                                          В системах, где нужны привилегии суперпользователя, обычно имеется iptables:
                                                          iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j DNAT --to a.b.c.d:8080

                                                          0

                                                          Несколько vhost'ов вы будете в одном приложении разводить, писать свой reverse proxy и так далее? Зачем, если есть готовые человеческие решения?

                                                      Only users with full accounts can post comments. Log in, please.