[Из песочницы] Простой webdev на Java 8
Хочу рассказать о том, как мне пришла в голову идея заняться веб-разработкой на Java.Итак, как только я созрел для этого дела, составил небольшой список, которому должны соответствовать выбранные мною инструменты разработки:
Сборка при помощи maven; Простой процесс деплоя и запуска; Библиотеки должны быть легковесны; Возможность использования шаблонизатора. Усиленно погуглив, я нашел то, что мне нужно: Spark, jade4j и OrmLite.Итак, инструменты выбраны, рассмотрим каждый из них в отдельности.
Spark FrameworkЯ выбрал последнюю версию, для работы которой требуется Java 8. Сам фреймворк позиционируется как Sinatra-inspired, так как я с синатрой знаком не слишком близко, он мне скорее напомнил Express для Node.js.Идея была близка, тем более что позитивный опыт работы с Express уже был. Документация кажется бедноватой, но в процессе разработки убеждаешься, что её более чем достаточно. Большим его плюсом я считаю и то, что для разработки не требуется предварительная настройка окружения, установка контейнера сервлетов и так далее. Всё, что нужно — это добавить зависимость в pom.xml, написать пару строк — и всё взлетит.
Jade4j Если вы работали с Node.js шаблонизаторами, в частности с jade, то вам наверняка захочется его использовать ещё. Легкочитаемый код, хорошая документация, множество красивых фич и опыт использования ранее заставили меня остановить свой выбор именно на этом шаблонизаторе.Небольшой пример layout.jade:
doctype html html head block headsection body header div#main block content footer Элементы {block blockname} реализуем в других файлов таким образом: extends layout block headsection title Привет, Хабр! block content h1 Hello, habr! OrmLite Скорее всего, некоторые андроид-разработчики хорошо знакомы с этой ORM. Она проста в использовании, легковесна и конфигурируется аннотациями.Вот простой пример pojo класса Пользователь:
package com.vagga.pojo;
import com.j256.ormlite.field.DatabaseField; import com.j256.ormlite.table.DatabaseTable;
@DatabaseTable (tableName = «users») public class User { @DatabaseField (columnName = «user_id», generatedId = true) private int userId; @DatabaseField (columnName = «username», unique = true, canBeNull = false) private String userName; @DatabaseField (columnName = «user_pass») private String password;
public User () { }
/* * Далее геттеры-сеттеры */ } Взаимодействие с БД может осуществляться через встроенный в ORM Dao. Я написал небольшой синглтон-класс, чтобы упростить себе жизнь (возможно, код ниже вас немного расстроит, поэтому оговорюсь ещё раз: главной целью ставилась простота реализации и использования): package com.vagga.utils;
import com.j256.ormlite.dao.Dao; import com.j256.ormlite.dao.DaoManager; import com.j256.ormlite.jdbc.JdbcConnectionSource; import com.vagga.pojo.Category; import com.vagga.pojo.Comment; import com.vagga.pojo.Post; import com.vagga.pojo.User;
import java.sql.SQLException;
public class DbUtil {
private static DbUtil ourInstance = new DbUtil ();
private JdbcConnectionSource dbSource;
private Dao
public static DbUtil getInstance () { return ourInstance; }
private DbUtil () { try { dbSource = new JdbcConnectionSource («jdbc: mysql://localhost:3306/vagga? user=root&characterEncoding=utf8»); userDao = DaoManager.createDao (dbSource, User.class); postDao = DaoManager.createDao (dbSource, Post.class); categoryDao = DaoManager.createDao (dbSource, Category.class); commentDao = DaoManager.createDao (dbSource, Comment.class); } catch (SQLException e) { e.printStackTrace (); System.out.println («Cannot establish DB connection » + e.getMessage () + » » + e.getCause ()); } }
public Dao
public Dao
public Dao
public Dao
В той же гуглогруппе я нашел вот этот вполне рабочий код:
package com.vagga.utils;
import de.neuland.jade4j.JadeConfiguration; import de.neuland.jade4j.exceptions.JadeException; import de.neuland.jade4j.model.JadeModel; import de.neuland.jade4j.template.FileTemplateLoader; import de.neuland.jade4j.template.JadeTemplate; import de.neuland.jade4j.template.TemplateLoader; import spark.ModelAndView; import spark.TemplateEngine;
import java.io.File; import java.io.IOException; import java.io.StringWriter; import java.util.Map;
public class JadeEngine extends TemplateEngine {
private JadeConfiguration configuration; private String directory = new File (».»).getCanonicalPath (); public JadeEngine () throws IOException { this.configuration = new JadeConfiguration (); this.directory = this.directory + »/src/main/resources/templates/»; TemplateLoader loader = new FileTemplateLoader (directory, «UTF-8»); configuration.setTemplateLoader (loader); }
@SuppressWarnings («unchecked»)
@Override
public String render (ModelAndView modelAndView) {
StringWriter stringWriter = new StringWriter ();
try {
JadeTemplate template = this.configuration.getTemplate (modelAndView.getViewName ());
JadeModel jadeModel = new JadeModel ((Map
public interface BaseRoute { public void initBeforeAction (); public void initActions (); public void initAfterActions (); } Далее я создал базовый класс маршрута, в котором проинициализировал хелперы рендеринга шаблонов: package com.vagga.routes;
import com.vagga.utils.JadeEngine; import com.vagga.utils.JsonTransformer;
import java.io.IOException;
public class Route { protected JadeEngine templateEngine; protected JsonTransformer jsonTransformer; protected Route () throws IOException { templateEngine = new JadeEngine (); jsonTransformer = new JsonTransformer (); } } Реализация конечного класса-маппера тут: package com.vagga.routes;
import com.vagga.pojo.Category; import com.vagga.pojo.User; import com.vagga.utils.DbUtil; import spark.ModelAndView;
import java.io.IOException; import java.sql.SQLException; import java.util.HashMap; import java.util.List; import java.util.Map;
import static spark.Spark.*; public class HomeRoute extends Route implements BaseRoute {
public HomeRoute () throws IOException { super (); }
@Override public void initBeforeAction () { }
@Override public void initActions () {
get (»/», (req, res) → {
Map
@Override
public void initAfterActions () {
}
}
Теперь все классы-мапперы надо как-то инстанциировать. Я это делаю прямо в main классе, ибо ничего умнее пока не придумал (буду благодарен, если кто-нибудь наведет на мысль как это можно сделать лучше):
public class VaggaMain {
public static void main (String[] args) {
try {
ArrayList