Перенос сообщества ВКонтакте
Дорогие подписчики!
Тем, кто хочет вырасти, или уже вырос из Java-программиста в разработчика, предлагаю вступить в сообщество ВКонтакте:
В этой группе я постараюсь не завязываться на конкретном языке разработки, а обратить внимание на архитектуру систем, стиль написания кода, командную работу и саморазвитие.
Буду рад, если присоединитесь :)
Когда Hello world уже не достаточно.
Привет всем кто учит какие либо языки программирования, а в особенности Java.
Я далекий от про уровня человек, но люблю на досуге писать код. И вот я не так давно (благодаря упоминанию тут), открыл для себя ресурс codewars.
Ресурс поддерживает много языков программирования, так что одни и те же задачи можно решать разными языками. Пользователи сами могут создавать задачи для других и тд.
Но причина создания не в рекламе ресурса, а том что бы найти других людей у которых хобби как у меня и вместе решать задачки, обсуждать их, а может и создавать.
Spark — Потрясающий веб-микрофреймворк для Java
Изначально пилил всё это для хабра, но может и на пикабу зайдут такого вида посты. Сразу прошу прошение за табуляцию, так и не понял как на пикабу организовать её. У кого совсем кровоточат глаза, читайте пост на хабре.
Небольшое вступление
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»).
Лично мое мнение, что данный код настолько лаконичный, что даже не требует пояснений.
Стоп-стоп. Что насчет запуска/остановки сервера?
Остановка — надо всего лишь вызвать метод stop().
Запуск — а вот здесь все интересно. Сервер автоматически запускается, когда вы делаете что-то, что требует запуска сервера (я знаю что звучит действительно странно). Но можно запустить и вручную, вызвав метод 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>
</dependencies>
Нам 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`е и раскрою больше его возможностей.
Ссылки
Альтернативные варианты названий известных фильмов или как их видит программист.
Властелин колец: Братство Js'а.
Властелин колец: Два сорванных релиза .
Властелин колец: Возвращение тимлида.
Звездные войны. Эпизод 1. Скрытая фича.
Звездные войны. Эпизод 2. DDOS атака.
Звездные войны. Эпизод 3. Месть заказчика.
Звездные войны. Эпизод 4. Новое ТЗ.
Звездные войны. Эпизод 5. Заказчик вносит новые правки.
Звездные войны. Эпизод 6. Возвращение в разработку.
Трасформеры. Обратная сторона front-end.
Шерлок Холмс.Игра на php.
Готовы к Евро-2024? А ну-ка, проверим!
Для всех поклонников футбола Hisense подготовил крутой конкурс в соцсетях. Попытайте удачу, чтобы получить классный мерч и технику от глобального партнера чемпионата.
А если не любите полагаться на случай и сразу отправляетесь за техникой Hisense, не прячьте далеко чек. Загрузите на сайт и получите подписку на Wink на 3 месяца в подарок.
Реклама ООО «Горенье БТ», ИНН: 7704722037