برنامه نویسی

Kotlin CRUD Rest Api با استفاده از Spring Boot، Hibernate، Postgres، Docker و Docker Compose

بیایید یک CRUD Rest API در Kotlin ایجاد کنیم، با استفاده از:

  • چکمه بهاره
  • گریدل
  • خواب زمستانی
  • Postgres
  • داکر
  • Docker Compose

اگر نسخه ویدیویی را ترجیح می دهید:

https://www.youtube.com/watch?v=BbT1PCAOS2s

تمام کدها در مخزن GitHub موجود است (لینک در توضیحات ویدیو): https://youtube.com/live/BbT1PCAOS2s


🏁 معرفی

در اینجا طرحی از معماری برنامه ای که می خواهیم ایجاد کنیم آمده است:

crud، خواندن، به روز رسانی، حذف، به یک برنامه Spring Boot (لوگوی Kotlin) و سرویس Postgres، متصل به Docker compose.  پستچی و Tableplus برای آزمایش آن

ما 5 نقطه پایانی برای عملیات اصلی CRUD ایجاد خواهیم کرد:

  • ايجاد كردن
  • همه اش را بخوان
  • یکی را بخوانید
  • به روز رسانی
  • حذف

در اینجا مراحلی است که ما طی می کنیم:

  1. با استفاده از Spring Initializr یک پروژه Spring Boot ایجاد کنید
  2. اتصال پایگاه داده را پیکربندی کنید
  3. User.kt، UserRepository.kt و UserService.kt را ایجاد کنید
  4. برنامه را داکر کنید
  5. برای اجرای پایگاه داده و برنامه، docker-compose.yml را ایجاد کنید
  6. برنامه را با Postman و Tableplus تست کنید

ما با یک راهنمای گام به گام همراه خواهیم بود، بنابراین شما می توانید با آن همراه باشید.


الزامات:

  • Kotlin نصب شده است
  • Docker نصب شده و در حال اجرا است
  • (اختیاری): پستچی و Tableplus را دنبال کنید، اما هر ابزار آزمایشی کار خواهد کرد

اختیاری: کد VS با پسوندهای زیر:

  • بسته برنامه افزودنی جاوا
  • بسته الحاقی بوت بهار

🚀 یک پروژه جدید Kotlin ایجاد کنید

راه های زیادی برای ایجاد یک پروژه جدید Kotlin وجود دارد، اما من از Spring Initializr در VS Code استفاده خواهم کرد.

برای این کار باید بسته برنامه افزودنی جاوا و بسته برنامه افزودنی Spring Boot را نصب کرده باشید.

VS Code را باز کنید و روی دکمه “ایجاد پروژه جاوا” کلیک کنید:

دکمه ایجاد پروژه جاوا

با این کار یک درخواست در بالای صفحه باز می شود. به ترتیب روی موارد زیر کلیک کنید:

  • چکمه بهاره
  • گریدل
  • 3.0.5 (ممکن است در آینده تغییر کند)
  • کاتلین
  • com.example (فقط روی enter کلیک کنید)
  • دمو (فقط روی enter کلیک کنید)
  • شیشه
  • جاوا 17

با این کار یک اعلان دیگر باز می شود. به ترتیب روی موارد زیر کلیک کنید:

  • Spring Web (وابستگی به ایجاد Rest API)
  • Spring Data JPA (وابستگی به استفاده از Hibernate)
  • درایور PostgreSQL (وابستگی به اتصال به Postgres)

سپس باید پوشه ای را که می خواهید پروژه را در آن ایجاد کنید انتخاب کنید.

یک پوشه را انتخاب کنید و روی «Generate into this folder» ساعت کنید.

دکمه ایجاد پروژه جاوا

اکنون روی دکمه سمت راست پایین صفحه کلیک کنید تا پروژه در یک پنجره جدید باز شود.

دکمه باز کردن در سمت چپ پایین VS Code

ما با ایجاد پروژه تمام شده است.

اکنون می توانیم برنامه نویسی را شروع کنیم.


👩‍💻 برنامه را کدگذاری کنید

دو مرحله برای کدنویسی برنامه وجود دارد:

  • اتصال پایگاه داده را پیکربندی کنید
  • موجودیت کاربر، UserRepository و UserService را ایجاد کنید

🔗 پیکربندی اتصال پایگاه داده

باز کن application.properties فایل در src/main/resources پوشه (باید خالی باشد).

مطالب زیر را اضافه کنید:

spring.datasource.url=${DB_URL}
spring.datasource.username=${PG_USER}
spring.datasource.password=${PG_PASSWORD}

spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

توضیح:

  • spring.datasource.url: آدرس پایگاه داده.

  • spring.datasource.username: نام کاربری پایگاه داده.

  • spring.datasource.password: رمز عبور پایگاه داده

  • spring.jpa.hibernate.ddl-auto: روشی که می خواهیم پایگاه داده را به روز کنیم. ما استفاده خواهیم کرد update برای ایجاد جداول در صورت عدم وجود، و به روز رسانی آنها در صورت وجود.

  • spring.jpa.properties.hibernate.dialect: گویش پایگاه داده. ما از PostgreSQL استفاده خواهیم کرد.

بعداً از متغیرهای محیطی استفاده خواهیم کرد (و کمی مشکل خواهد بود).

📁 ساختار منبع را ایجاد کنید

یک پوشه جدید به نام ایجاد کنید users در demo پوشه (یا هر نام دیگری که پروژه خود را نامگذاری کرده اید).

در این پوشه سه فایل ایجاد کنید:

  • User.kt
  • UserRepository.kt
  • UserController.kt

پوشه شما باید شبیه این باشد:

ساختار پوشه

حالا بیایید فایل ها را پر کنیم.

User.kt

فایل User.kt حاوی موجودیت کاربر خواهد بود.

فایل را باز کنید و محتوای زیر را اضافه کنید (نام بسته را برای مطابقت با پروژه خود تغییر دهید):

package com.example.demo.users

import jakarta.persistence.*

@Entity
@Table(name = "users")
data class User(
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    val id: Long,
    val name: String,
    val email: String
)
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

توضیح:

  • @Entity: decorator به Hibernate بگوید که این کلاس یک موجودیت است.

  • @Table: decorator برای گفتن Hibernate نام جدول در پایگاه داده (“users in this case”).

  • @Id: دکوراتور به Hibernate بگوید که این فیلد کلید اصلی است.

  • @GeneratedValue: دکوراتور برای افزایش خودکار شناسه هر زمان که کاربر جدیدی ایجاد می کنیم.

یک کاربر سه فیلد خواهد داشت: id، name و email.

UserRepository.kt

فایل UserRepository.kt شامل رابطی برای تعامل با پایگاه داده خواهد بود.

فایل را باز کنید UserRepository.kt و محتوای زیر را اضافه کنید (اگر از بسته دیگری استفاده می کنید، نام بسته را تغییر دهید):

package com.example.demo.users

import org.springframework.data.repository.CrudRepository

interface UserRepository : CrudRepository<User, Long>
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

توضیح:

  • interface UserRepository: رابطی که شامل متدهای تعامل با پایگاه داده است. از نوع خواهد بود CrudRepository. این یک رابط عمومی است که شامل روش های اساسی برای تعامل با پایگاه داده است. یک نوع خواهد داشت User و یک Int (نوع کلید اصلی).

UserController.kt

فایل UserController.kt حاوی Rest API خواهد بود.

فایل را باز کنید UserController.kt و محتوای زیر را اضافه کنید (اگر از بسته دیگری استفاده می کنید، نام بسته را تغییر دهید):

package com.example.demo.users


import org.springframework.beans.factory.annotation.Autowired
import org.springframework.http.HttpStatus
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.*

@RestController
@RequestMapping("/api/users")
class UserController(@Autowired private val userRepository: UserRepository) {

    @GetMapping("")
    fun getAllUsers(): List<User> =
        userRepository.findAll().toList()

    @PostMapping("")
    fun createUser(@RequestBody user: User): ResponseEntity<User> {
        val createdUser = userRepository.save(user)
        return ResponseEntity(createdUser, HttpStatus.CREATED)
    }

    @GetMapping("/{id}")
    fun getUserById(@PathVariable("id") userId: Int): ResponseEntity<User> {
        val user = userRepository.findById(userId).orElse(null)
        return if (user != null) ResponseEntity(user, HttpStatus.OK)
               else ResponseEntity(HttpStatus.NOT_FOUND)
    }

    @PutMapping("/{id}")
    fun updateUserById(@PathVariable("id") userId: Int, @RequestBody user: User): ResponseEntity<User> {

        val existingUser = userRepository.findById(userId).orElse(null)

        if (existingUser == null) {
            return ResponseEntity(HttpStatus.NOT_FOUND)
        }

        val updatedUser = existingUser.copy(name = user.name, email = user.email)
        userRepository.save(updatedUser)
        return ResponseEntity(updatedUser, HttpStatus.OK)
    }

    @DeleteMapping("/{id}")
    fun deleteUserById(@PathVariable("id") userId: Int): ResponseEntity<User> {
        if (!userRepository.existsById(userId)) {
            return ResponseEntity(HttpStatus.NOT_FOUND)
        }
        userRepository.deleteById(userId)
        return ResponseEntity(HttpStatus.NO_CONTENT)
    }
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

توضیح:

  • @RestController: دکوراتور برای بهار.

  • @RequestMapping: برای گفتن به Spring url پایه Rest API. در این صورت خواهد بود /api/users.

  • @Autowired: به بهار بگویم که تزریق کند UserRepository.

سپس ما پنج روش برای تعامل با پایگاه داده داریم:

  • getAllUsers: برای دریافت همه کاربران.
  • createUser: برای ایجاد یک کاربر جدید.
  • getUserById: برای بدست آوردن کاربر با شناسه.
  • updateUserById: برای به روز رسانی یک کاربر با شناسه.
  • deleteUserById: برای حذف یک کاربر با شناسه.

Rest API ما برای Dockerized آماده است.


🐳 داکرسازی

اکنون بخش سرگرم کننده: Dockerization.

در این پروژه تصمیم گرفتم پروژه کاتلین را مستقیماً در داخل تصویر داکر بسازم.

گزینه دیگر این است که پروژه را به صورت محلی بسازید و سپس فایل jar را در تصویر داکر کپی کنید.

🐋 داکرفایل

یک فایل جدید به نام ایجاد کنید Dockerfile در ریشه پروژه

مطالب زیر را اضافه کنید (توضیحات در نظرات موجود است):

# Start with a base image containing Java runtime
FROM amazoncorretto:17-alpine-jdk

# Create a directory
WORKDIR /app

# Copy all the files from the current directory to the image
COPY . .

# build the project avoiding tests
RUN ./gradlew clean build -x test

# Expose port 8080
EXPOSE 8080

# Run the jar file
CMD ["java", "-jar", "./build/libs/demo-0.0.1-SNAPSHOT.jar"]
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

⚠️ بخش غیرمعمول در اینجا خطوط ARG هستند. آنها برای ارسال آرگومان ها به تصویر Docker استفاده می شوند. آنها در تعریف شده اند docker-compose.yml فایل.

🐙 docker-compose.yml

بیایید ایجاد کنیم docker-compose.yml فایل در ریشه پروژه

مطالب زیر را اضافه کنید (توضیحات در نظرات موجود است):

version: '3.9'

services: 
  kotlinapp: 
    container_name: kotlinapp
    build: # this is the build context: .  
      context: .
      dockerfile: Dockerfile
      args: # these are the arguments that are passed to the dockerfile
        DB_URL: ${DB_URL} 
        PG_USER: ${PG_USER}
        PG_PASSWORD: ${PG_PASSWORD}
    ports: # port exposed to the host machine
      - "8080:8080"
    environment: # these are the environment variables that are passed to the dockerfile
      DB_URL: jdbc:postgresql://db:5432/postgres
      PG_USER: postgres
      PG_PASSWORD: postgres
    depends_on: # this is the dependency on the db service
      - db
  db:
    container_name: db
    image: postgres:12
    environment: # environment variables for the Postgres container
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: postgres
      POSTGRES_DB: postgres
    ports: # port exposed to the host machine
      - "5432:5432"
    volumes: # volume used to persist data
      - pgdata:/var/lib/postgresql/data

volumes: # volume creation
  pgdata: {}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید


پروژه را بسازید و اجرا کنید

اکنون می توانیم پروژه را بسازیم و اجرا کنیم.

💽 پایگاه داده Postgres را اجرا کنید

ابتدا باید پایگاه داده Postgres را اجرا کنیم.

docker compose up -d db
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

برای بررسی اینکه آیا در حال اجرا است، می توانید از دستور زیر استفاده کنید:

docker compose logs
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

و

docker ps -a
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

اگر خروجی مانند خروجی زیر است، خوب است که بروید:

داکر ps -a

شما باید چنین چیزی را ببینید، شما خوب هستید که بروید.

به عنوان آزمایش اضافی، می توانید با استفاده از TablePlus (یا هر مشتری پایگاه داده دیگر) به پایگاه داده متصل شوید.

می توانید با استفاده از پارامترهای زیر یک اتصال جدید ایجاد کنید:

  • میزبان: localhost
  • بندر: 5432
  • پایگاه داده: postgres
  • کاربر: postgres
  • رمز عبور: postgres

سپس بر روی آن کلیک کنید Test Connection دکمه. پایگاه داده متصل است اما در حال حاضر خالی است.

جدول پلاس

🏗️ پروژه را بسازید

بیایید پروژه را در داخل تصویر داکر بسازیم.

docker compose build
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

و خروجی باید چیزی شبیه به این باشد:

ساخت docker compose

🏃‍♂️ پروژه را اجرا کنید

اکنون می توانیم پروژه را اجرا کنیم.

docker compose up kotlinapp
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

و این باید خروجی باشد:

docker compose up kotlinapp


🧪 پروژه را تست کنید

اکنون می توانیم پروژه را آزمایش کنیم. ما از Postman استفاده خواهیم کرد، اما شما می توانید از هر ابزار دیگری استفاده کنید.

📝 یک کاربر ایجاد کنید

برای ایجاد یک کاربر جدید، a را ایجاد کنید POST request to localhost:8080/api/users.

بدنه درخواست باید به این صورت باشد:

{
    "name": "aaa",
    "email": "aaa@mail"
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

خروجی باید چیزی شبیه به این باشد:

کاربر ایجاد کنید

بیایید دو کاربر دیگر ایجاد کنیم، یک POST request to localhost:8080/api/users.

{
    "name": "bbb",
    "email": "bbb@mail"
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

{
    "name": "ccc",
    "email": "ccc@mail"
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

📝 همه کاربران را دریافت کنید

برای دریافت همه کاربران، یک را بسازید GET request to localhost:8000/api/users.

خروجی باید چیزی شبیه به این باشد:

همه کاربران را دریافت کنید

📝 یک کاربر دریافت کنید

برای به دست آوردن یک کاربر، a GET request to localhost:8000/api/users/{id}.

مثلا GET request to localhost:8000/api/users/1.

خروجی باید چیزی شبیه به این باشد:

کاربر دریافت کنید

📝 یک کاربر را به روز کنید

برای به روز رسانی یک کاربر، یک را ایجاد کنید PUT request to localhost:8000/api/users/{id}.

مثلا PUT request to localhost:8000/api/users/2.

بدنه درخواست باید به این صورت باشد:

{
    "name": "Francesco",
    "email": "francesco@mail"
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

خروجی باید چیزی شبیه به این باشد:

یک کاربر را به روز کنید

📝 حذف یک کاربر

برای حذف یک کاربر، یک علامت بزنید DELETE request to localhost:8000/api/users/{id}.

مثلا DELETE request to localhost:8000/api/users/1.

در پستچی باید چیزی شبیه به آن را ببینید:

یک کاربر را حذف کنید

تست نهایی

به عنوان تست نهایی، می توانیم پایگاه داده را با استفاده از TablePlus بررسی کنیم.

جدول پلاس


🏁نتیجه گیری

ما ساختیمش! ما یک CRUD rest API در Kotlin ساخته‌ایم که با استفاده از:

  • چکمه بهاره
  • گریدل
  • خواب زمستانی
  • Postgres
  • داکر
  • Docker Compose

اگر نسخه ویدیویی را ترجیح می دهید:

https://www.youtube.com/watch?v=BbT1PCAOS2s

تمام کدها در مخزن GitHub موجود است (لینک در توضیحات ویدیو): https://youtube.com/live/BbT1PCAOS2s

همین.

اگر سوالی دارید، در زیر نظر دهید.

فرانچسکو

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا