Создайте простой API с базой данных PostgreSQL

С самого первого выпуска Java позиционировала себя как язык программирования напиши один раз, запусти везде. Идея заключалась в том, что программист мог разработать приложение на Java, скомпилировать его в байт-код и превратить в исполняемый файл, который может работать на любой платформе, независимо от операционной системы или платформы. Частично это удалось сделать с помощью среды выполнения, известной как виртуальная машина Java или JVM.

К чести Java, JVM была (и остается!) Невероятно точно настроенной средой выполнения, которая абстрагировалась от базового оборудования компьютера. Хотя Java как язык программирования существует и по сей день, его часто считают громоздким, утомительным и представителем устаревшего подхода к реализации решений.

За последние десять лет было разработано все больше и больше языков, которые работают на JVM, но по внешнему виду и ощущениям не похожи на Java. Один из таких языков - Котлин. Из-за JVM он не имеет реальных преимуществ в производительности по сравнению с обычной Java. Тем не менее, его сила заключается в том, что он отдает приоритет удобочитаемости в отличие от Java. Рассмотрим, например, печать подстроки в Java:

// Java
String input = "What is the answer to the Ultimate Question of Life, the Universe, and Everything? 42";
String answer = input.substring(input.indexOf("?") + 1);
System.out.println(answer);

Сначала вы должны получить индекс символа, который вы хотите включить в подстроку, добавить единицу (поскольку строки имеют нулевой индекс) и вызвать System.out.println для записи в стандартный вывод.

В Котлине это намного короче:

// Kotlin
val input = "What is the answer to the Ultimate Question of Life, the Universe, and Everything? 42"
val answer = input.substringAfter("?")
println(answer)

Kotlin вызвал такой большой интерес, что Google даже рекомендует его вместо Java для разработки приложений для Android.

В этом посте мы кратко рассмотрим, как разработать приложение на Kotlin. Мы создадим простой API с базой данных PostgreSQL и развернем его в Heroku, чтобы увидеть его вживую.

Предпосылки

Прежде чем мы начнем, вам необходимо убедиться, что на вашем компьютере установлено следующее программное обеспечение:

  1. Аккаунт на Heroku. Это совершенно бесплатно и не требует какой-либо платежной информации.
  2. Интерфейс командной строки Heroku. Как только ваше приложение будет размещено на Heroku, это значительно упростит управление им.
  3. Вам потребуется установить Kotlin (›= 1.4).
  4. Вам также понадобится установленный Gradle (›= 7.0).

Вам также нужно будет немного познакомиться с Git и установить его на свой компьютер.

Мы собираемся использовать IDE IntelliJ для этого приложения Kotlin. В их документации содержатся некоторые рекомендации по созданию нового проекта. Убедитесь, что вы выбрали следующие параметры:

  • Мы хотим создать приложение Kotlin, которое использует Gradle в качестве системы сборки.
  • Задайте имя проекта kotlin-api
  • Установите версию JDK на 16. Если у вас не установлена ​​эта версия, вы можете выбрать «Загрузить JDK…» в раскрывающемся списке, а затем выбрать Oracle Open JDK версии 16.

После того, как IDE все настроит, у вас должна получиться структура каталогов, которая выглядит примерно так:

kotlin-api
├── build.gradle.kts
└── src
    ├── main
    │   ├── kotlin

Наши файлы Kotlin будут храниться в src/main/kotlin, а наша логика сборки будет в build.gradle.kts.

Начиная

Gradle - это инструмент сборки для множества языков. Он также действует как инструмент управления зависимостями, аналогичный Maven. У вас уже есть несколько строк в вашем build.gradle.kts файле, которые IDE автоматически добавила, чтобы быть полезными. Вы можете удалить все это и вместо этого вставить следующие строки:

plugins {
    id("java")
    id("org.jetbrains.kotlin.jvm") version "1.5.10"
    id("org.springframework.boot") version "2.4.3"
    id("io.spring.dependency-management") version "1.0.11.RELEASE"
}
group "com.example"
version "0.0.1"
repositories {
    mavenCentral()
}
dependencies {
    implementation("org.jetbrains.kotlin:kotlin-stdlib") 
    implementation("org.springframework.boot:spring-boot-starter-web")    
    implementation("org.springframework.boot:spring-boot-starter")
    developmentOnly("org.springframework.boot:spring-boot-devtools")
}

В этих строках указываются зависимости нашего проекта и их местонахождение. Например, мы хотим использовать [org.springframework.boot](https://plugins.gradle.org/plugin/org.springframework.boot) в версии 2.4.3, поэтому он определен в блоке plugins. Мы указываем репозитории, где можно найти пакеты - в mavenCentral() - и какие открытые классы мы хотим использовать (implementation( "org.springframework.boot:spring-boot-starter-web")).

Давайте создадим два небольших файла для проверки нашей настройки. Создайте файл с именем Application.kt в папке src/main/kotlin и вставьте следующее:

package com.example
import org.springframework.boot.SpringApplication
import org.springframework.boot.autoconfigure.SpringBootApplication
@SpringBootApplication
open class Application
fun main(args: Array<String>) {
    SpringApplication.run(Application::class.java, *args)
}

Это запускает приложение по умолчанию, использующее платформу Spring. Настоящая магия происходит в следующем файле Controller.kt, который вы должны создать вместе с Application.kt в src / main / kotlin:

Здесь мы определяем маршрут (@GetMapping("/{name}")), где {name} - динамическое значение. Поместив этот декоратор над методом Kotlin (fun get или «функция с именем get»), мы можем сопоставить маршрут с любым желаемым поведением - в данном случае, возвращая приветствие с именем пути для GET запроса.

Чтобы IDE знала, как запускать наше приложение, нам нужно создать конфигурацию запуска. В верхней части меню IDE нажмите кнопку Добавить конфигурацию…. Выберите Добавить новую конфигурацию запуска, затем выберите Gradle из списка.

В качестве имени проекта Gradle введите kotlin-api. В поле "Задачи" введите bootRun. bootRun - это задача Gradle, предоставляемая фреймворком Spring, которая скомпилирует наш код и запустит сервер. Нажмите «ОК», и теперь у вас должна появиться зеленая кнопка «Воспроизвести» в строке меню IDE. Когда вы щелкнете по нему, IDE выполнит gradle bootRun, чтобы построить это приложение Kotlin и запустить сервер. Когда это закончится, перейдите к http://localhost:8080/world. Вы должны увидеть красивое приветствие.

Взаимодействие с базой данных

А теперь перейдем к (несколько) серьезным вещам. Предположим, мы хотим подключить к этому проекту базу данных. В мире Maven / Java нам нужно обновить XML-файл и добавить ссылку на JAR-файл. В Gradle мы можем обойтись простым добавлением нескольких строк в наш build.gradle.kts файл:

dependencies {
    # ...
    implementation("com.zaxxer:HikariCP:4.0.3")
    runtimeOnly("org.postgresql:postgresql")
    # ...
}

Здесь мы включили в наш проект HikariCP, популярный драйвер подключения к базе данных. Мы также указываем, что хотим загрузить org.postgresql библиотеку во время выполнения. С помощью этих двух строк мы сообщаем нашей конфигурации, что хотим взаимодействовать с базой данных PostgreSQL. Если у вас уже есть база данных PostgreSQL, работающая локально, это прекрасно. Вы сможете продолжить оставшуюся часть этого руководства локально и увидеть результаты при просмотре localhost. Если у вас нет PostgreSQL, не волнуйтесь - мы покажем вам, насколько легко развернуть это приложение на Heroku, которое позаботится об инфраструктуре за вас.

Вернитесь к Controller.kt и замените его содержимым ниже. Это берет кое-что из того, что у нас было раньше, но добавляет к этому. Вскоре мы рассмотрим изменения.

Здесь много всего происходит! Начнем снизу. Мы определяем функцию с именем dataSource, которая обеспечивает соединение с нашей базой данных. Поскольку мы создаем 12-факторное приложение, учетные данные нашей базы данных хранятся в переменной среды с именем DATABASE_URL. Мы получаем этот URL-адрес и вытаскиваем из него имя пользователя и пароль, если он существует. Если нет, мы проверяем еще две переменные среды на предмет этой информации - DATABASE_USERNAME и DATABASE_PASSWORD.

Затем мы объединяем всю эту информацию в формат, необходимый коннектору базы данных. Функция initDb создает таблицу с именем names с единственным текстовым столбцом с именем name. Конечная точка /everyone, как и раньше, имеет декоратор @GetMapping. Это определяет GET /everyone маршрут, который получает все имена из базы данных.

Наконец, мы добавили кое-что новенькое: декоратор @PostMapping. Здесь нам нужно определить, какие типы контента может принимать этот POST маршрут. В данном случае это consumes тип носителя TEXT_PLAIN_VALUE (другими словами, "Content-Type: text/plain"). Какая бы строка информации мы ни поместили в тело запроса, она будет добавлена ​​в базу данных. Всего за несколько строк мы создали небольшой API, который можно добавлять и запрашивать.

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

$ curl -H "Content-Type: text/plain" -X POST http://localhost:8080/add-name -d 'Frank'

Если вы перейдете к http://localhost:8080/everyone, вы увидите, что Frank был включен.

Развертывание на Heroku

Пришло время увидеть, насколько легко запустить Kotlin на Heroku. Во-первых, нам нужно создать файл, специфичный для Heroku: Procfile. Этот текстовый файл определяет, как наше приложение должно загружаться и работать.

Создайте файл с именем Procfile в каталоге корневого уровня, рядом с вашим файлом build.gradle.kts. Скопируйте и вставьте в него следующие строки:

web: java -jar build/libs/kotlin-api.jar --server.port=$PORT

Здесь мы говорим, что хотим, чтобы Heroku запускала java -jar build/libs/kotlin-api.jar. Этот JAR упаковывается и создается в процессе развертывания; Heroku создаст его автоматически, потому что он знает, как выполнить задачу Gradle для этого. Мы также связываем переменную среды $PORT, чтобы Heroku знал, какой порт слушает сервер.

Затем запустите следующие команды Git:

$ git init
$ git add .
$ git commit -m "Preparing my first Kotlin app"

Поскольку у нас установлен Heroku CLI, мы можем вызвать heroku create в командной строке для создания приложения:

$ heroku create
Creating app... done, ⬢ desolate-plains-67007
Created http://desolate-plains-67007.herokuapp.com/ | [email protected]:desolate-plains-67007.git

Вашему приложению будет присвоено случайное имя (в данном примере это desolate-plains-67007), а также общедоступный URL.

Чтобы подготовить базу данных, мы используем команду heroku addons. Вызов его без аргументов даст нам знать, если они существуют:

$ heroku addons
No add-ons for app desolate-plains-67007.

Для нашего приложения не существует надстроек, что имеет смысл - мы только что создали его! Чтобы добавить базу данных PostgreSQL, мы можем использовать команду addons:create следующим образом:

$ heroku addons:create heroku-postgresql:hobby-dev

Heroku предлагает несколько уровней баз данных PostgreSQL. hobby-dev - это уровень бесплатного пользования, поэтому мы можем поиграть с ним, не платя ни копейки.

Ваш код готов; ваше приложение Heroku настроено - вы готовы к развертыванию. Это легкая часть! Просто введите следующую команду:

$ git push heroku master

Ваш код будет отправлен на Heroku. С этого момента Heroku возьмет на себя управление. Вы увидите, как в терминале прокручиваются журналы сборки. Это покажет вам, что Heroku устанавливает от вашего имени и где вы находитесь в процессе сборки. После его завершения вы можете посетить свой специальный URL-адрес в браузере (в данном случае https://desolate-plains-67007.herokuapp.com) и взаимодействовать с API в Интернете!

Узнать больше

Производительный дизайн и разборчивый синтаксис Kotlin в сочетании с простотой Gradle делают его идеальным для предприятий, которым необходимо полагаться на проверенные в боях пакеты Java. Благодаря своей совместимости с Java, Kotlin идеален в качестве переходного языка; обширные участки кода Java можно преобразовать в Kotlin, сохранив при этом работоспособное приложение. Развертывание в Heroku проходит гладко, и я даже не воспользовался преимуществами различных способов тонкой настройки приложений на основе Java и JVM для развертывания.