habrahabr

Быстрый старт веб-проекта (BE — Java Spring, FE — React Redux, взаимодействие — Rest, WebSocket)

  • четверг, 13 сентября 2018 г. в 00:18:48
https://habr.com/post/422985/
  • ReactJS
  • JavaScript
  • Java




Чтобы разработать современное веб приложение, необходимо иметь навыки как в создании серверной части, так и клиентской. Наиболее часто встречаемое в последнее время сочетание в корпоративной среде — это Java c использованием Spring Framework для сервера и React для клиента. Однако не все разработчики обладают Full stack навыками (знаниями как в серверной так и в клиентской части), а для начинающих разработчиков создание такой конфигурации оказывается совсем непосильной задачей.

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

Более подробно рассмотрим используемые технологии


Серверная часть:


Сборка проекта — gradle 4.8.1 ( дополнительно gradle-node-plugin для сборки фронта)
Язык — Java 1.8 (или старше)
Фреймворк — Spring 5.x
База данных — HSQL 2.3.1 (для начала будет достаточно)

Клиентская часть:


Сборка проекта — webpack 4.17.2
Язык — JS6
Фреймворк — react 16.4.0, redux 3.7.2, bootstrap (reactstrap 6.3.1)
Если вас всё устраивает, то можно продолжить.

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


Думаю будет намного веселее, если сначала мы всё запустим и убедимся что всё работает!
Скачать проект можно отсюда

Для запуска понадобится совсем немного времени и терпения. Главное делать всё по порядку:

  1. Установить java 1.8 (не забываем прописать JAVA_HOME)
  2. Установить node.js
  3. Открыть командную строку (Надеюсь что вы сами разберётесь как это сделать в вашей операционной системе)
  4. Перейти в папку проекта (Например cd C:\Git\react-start)
  5. Выполнить команду npm i (Эта команда скачает все зависимости для фронта и сложит их в папку node_modules)
  6. Выполнить команду gradle build (Эта команда соберёт ваш проект и сложит всё в папку build)
  7. Выполнить команду gradle bootRun (Теперь ваш проект запущен)
  8. Остаётся только перейти по ссылке и насладится результатом.

Вы должны увидеть нечто подобное:



Вступление


Моя основная задача в этой статье показать структуру проекта. Поэтому я буду в основном максимально доступно рассказывать какой файл в проекте за что отвечает с некоторыми лирическими отступлениями. Для бек энд разработчиков будет интересна в основном клиентская часть и наоборот.

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


Я постарался по возможности убрать все лишнее из проекта, то чем любой проект обрастает со временем, но пугает начинающих разработчиков.

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

Сервер:


build.gradle — Главный файл для сборки нашего проекта. в нём описаны все необходимые нам зависимости и ссылки на репозиторий где их брать. А также там прописан плагин gradle-node-plugin который при сборке серверной части автоматически собирает и фронт что несомненно очень удобно.

gradlew и gradlew.bat и папка gradle — необходимые части для запуска сборщика. Кстати если команда gradle build по каким то причинам не выполняется, то возможно вам придется установить gradle. Сделать это можно с помощью официальной инструкции.

README.md — Универсальный файл для отображения в репозитории информации о проекте.

В папке src/main/webapp/WEB-INF/ лежат два файла jboss-web.xml и web.xml при локальной работе они не используются, но если нужно будет запускать проект на web серверах типа WildFly они обязательно понадобятся.

application.yml — также не маловажный файл. В нем описывается конфигурация Spring. В частности там есть port: 8090 — порт на котором будет запущено приложение и настройки подключения к базе данных.

Если уже заговорили про базы данных то в проекте используется HSQL — это файловая база данных работающая на java. При старте проекта в папке пользователя создастся папка db/ в которой и будет храниться сама база данных. Вы можете использовать любую свою базу данных которая Вам больше нравится, например Postgress, на это нет никаких принципиальных ограничений.

Сам код серверной части располагается в папке src/main/java.

Клиент:


.babelrc — здесь хранятся всякие конфигурации для для babel. Для тех кто не знает babel — это штука которая преобразует всякие новомодные вещи во front-end разработке, такие как JS6, JS7, JSX, в обыкновенный js. В этом файле например у меня подключен плагин «plugins»: [«transform-decorators-legacy»] который позволяет использовать decorators — это как @аннотация в java. Я их не использовал, но Вы можете. Для этого всё уже настроено я проверял.

.npmrc — ссылка на репозиторий для js зависимостей.

package.json — очень важный файл здесь хранится описание всего нашего приложения, ссылки на js зависимости и команды для сборки и запуска клиентской части. Причём зависимости разбиты на две части это dependencies — зависимости которые необходимы для работы самого приложения и devDependencies — зависимости необходимые толmко для сборки проекта. В разделе scripts описаны команды buils и start которые используются для запуска только фронтальной части проекта например фронт можно запустить командой npm run start (Запустится он на порту 9090). По сути этот файл — это аналог build.gradle для клиентской части.

webpack.config.babel.js — самый главный файл во всей конфигурации — настройки сборщика webpack. По этому поводу можно писать отдельную статью, но я всё равно хочу пройтись по основным частям этого файла чтобы сформировать у Вас общее представление о его возможностях.

devServer
devServer: {
        contentBase: `/${publicPath}/`,
        historyApiFallback: {
            rewrites: [{from: /./, to: `/index.html`}]
        },
        open: true,
        port: 9090,
        publicPath: `/`,
        proxy: [{
            context: ['/api', '/endpoint'],
            target: {
                host: "localhost",
                protocol: 'http:',
                port: 8090
            }
        }]
    },


DevServer используется для разработки клиентской части. Как уже говорилось выше мы можем запустить наш фронт на отдельном порту npm run start (Запустится он на порту 9090). Все изменения в коде js будут сразу вступать в силу на этом сервере. СontentBase — корневой путь до нашего приложения. Если на сервере будет запущено несколько приложений то это важно. open: true — при запуске сервера приложение будет автоматически открываться в браузере. proxy — раздел который отвечает за пересылку обращений к серверной части которая у нас будет запущена на порту 8090.

output
output: {
        filename: 'assets/javascripts/[hash].js',
        path: path.join(__dirname, 'src/main/resources/static'),
        publicPath: `/`
    },


output — этот раздел задает место сборки нашего проекта. Если выполнить команду npm run build, то в папке src/main/resources появится клиентская часть нашего проекта.

module
module: {
        rules: [
            {
                exclude: /node_modules/,
                include: path.join(__dirname, 'src/main/js/'),
                test: /\.jsx?$/,
                use: 'babel-loader'
            },
            {
                test: /\.css$/,
                use: [MiniCssExtractPlugin.loader, 'css-loader']
            },
            {
                test: /\.less$/,
                use: [MiniCssExtractPlugin.loader, 'css-loader', 'less-loader']
            },
            {
                test: /\.(ico|png|gif|jpe?g)$/,
                use: {
                    loader: 'file-loader',
                    options: {name: 'assets/images/[name]/[hash].[ext]'}
                }
            },
            {
                test: /\.(svg|woff|woff2|eot|ttf)$/,
                use: {
                    loader: 'file-loader',
                    options: {name: 'assets/fonts/[name]/[hash].[ext]'}
                }
            },
            {test: /\.html$/, use: 'html-loader'},
        ]
    },


Раздел module указывает webpack что нужно искать в проекте файлы с расширениями .jsx, файлы стилей, картинок и шрифтов и тоже включать их в наш проект.

Раздел entry содержит ссылку на главный файл нашего js приложения.

Ну и в заключении HtmlWebpackPlugin создаст index.html файл в который включит все созданные зависимости.

Код клиентской части лежит в папке src/main/js.

Структура самого кода


В проекте я для примера сделал связь клиентской и cсерверной части через Rest и WebSocket. Кому что больше нравится. Описание самих технологий Spring Framework и Rect в интернете великое множество. Эта статья для тех у кого что-то не получается, или что-то лень. Это настроенное готовое рабочее решение содержащее в себе все необходимое чтобы перерасти в полноценный большой проект.

Также Вы можете взять этот проект в качестве отправной точки в изучении Java EE или React приложений.controller/RestController.java

Сервер:


Код клиентской части лежит в папке src/main/java.

То как там всё располагается полностью подчиняется структуре Spring Framework. Для тех кто с ним знаком не найдет там ничего интересного, а для тех кто только начинает опять же просто коротко пройдусь по файлам.

Main.java — главный файл. Содержит метод main который и запускает всё приложение.

configuration/WebSocketConfig.java — для точек входа при работе через webSocket

Контролеры — Классы отвечающие за взаимодействие серверной и клиентской частей.

controller/IndexController.java — контроллер отвечающий за отображение нашей клиентской части. Перебрасываем пользователя на url application/** (Это контекстный путь до нашего приложения)

controller/RestController.java — как видно из названия этот контроллер отвечает за обмен данными между клиентской и серверной частью по Rest. Аннотация @RequestMapping(value = "/api/rest", method = RequestMethod.GET) говорит что по запросу по адресу /api/rest сервер отдаст нам список пользователей.

Метод PUT я использовал для добавления пользователей и DELETE соответственно для удаления пользователя по ID.

controller/WebSocketController.java — определяет путь для обмена данными по webSocket. Метод getAndSendMessage получает сообщение от клиента и оправляет его обратно.

Сервисы — обычно отвечают за логику нашего приложения.

service/ORMUserService.java — в моем случае отвечает за формирование списка пользователей, а также добавление и удаление пользователей в базу данных используя в качестве данных параметры полученные от клиентской части. Для удаления пользователя — это id пользователя, а для создания — это имя, роль и пароль пользователя.

Доменные классы — это классы в которых чаще всего содержатся только данные которые проецируются на таблицы в бузе данных. Из логики которая может содержаться в этих классах это проверка данных на корректность или какие то действия которые необходимо выполнить непосредственно перед записью данных в базу или после чтения из неё. Например можно сделать конвертацию из килограммов в граммы.

domain/User.java — класс который будет соответствовать таблице Table(name = «USER») в базе данных.

Данные для колонки @Column(name = «ID») будут генерироваться автоматически.

domain/Message.java — в моем случае не использует сопоставления с базой данных. данные в нём будут храниться пока приложение запущено. Служит у меня для формирования сообщений отправляемых по webSocket.
На этом с серверной частью у меня всё.

Клиент:


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

Что сделано на фронте:

  • Реализован главный layout приложения и несколько вкладок.
  • Реализован перевод для всего приложения.
  • Реализован state приложения на Redux.
  • Реализовано отображение таблицы пользователей получаемых с сервера через Rest
  • Реализовано удаление пользователей по id
  • Реализовано добавление пользователей
  • Реализована отправка и получение сообщений через WebSocket

Думаю для начала этого более чем достаточно.

Заключение


Все ваши вопросы и пожелания оставляйте в комментариях или пишите мне на почту. Буду рад помочь.