Spring-boot Reactive Example
ตัวอย่างการเขียน Java Spring-boot Reactive (WebFlux) ซึ่งเป็นการเขียน Spring-boot แบบ Non-Blocking I/O หรือ Asynchronous
เชิญชวน
อยากเชิญชวน คนที่มีความรู้ความสามารถด้านใดด้านหนึ่งตามที่ตัวเองถนัด ทำตัวอย่างอะไรทำนองนี้ไว้
เพื่อให้ผู้เริ่มต้น หรือมือใหม่ได้มีตัวอย่างอ้างอิงที่สามารถเอาไปประยุกต์ใช้ได้
ตัวผมเองก็ใช้อันนี้สอนน้อง ๆ สอนเด็กฝึกงานที่บริษัท อีกทั้งเอาไว้ทบทวนตัวเองด้วย
กับเห็นว่ามันมีประโยชน์สำหรับทุกคน เลยแชร์ไว้ครับ
ปัญหา / ข้อเสนอแนะ
หากพบปัญหา หรือ ต้องการให้ทำอะไรเพิ่ม รบกวนช่วยเปิด issue หรือ fork/pull request ให้ด้วยน่ะครับ
ขอบคุณครับ :)
การสนันสนุน หรือ Donate
สำหรับคนที่นำ Repository นี้ไปใช้ในการเรียนรู้ หรือสร้างสรรค์ผลงานให้เกิดมูลค่า
ถ้าอยากที่จะสนับสนุนหรือ Support Repository นี้ สามารถทำได้ 3 ทางครับ คือ
- ผ่านทาง Prompt Pay QR Code
- ผ่านบัญชีธนาคาร
- ผ่านทาง Buy Me a Coffee
ทั้งนี้เพื่อเป็นค่ากาแฟ และค่าแพมเพิส (ผ้าอนามัย) ลูกสาวครับ
Prompt Pay QR
บัญชีธนาคาร
ธนาคารไทยพาณิชย์
เลขที่บัญชี 274-214985-3
ชื่อบัญชี นายจิตกร พิทักษ์เมธากุล
By Me a Coffee
คลิกที่ปุ่มนี้
ถ้ามีข้อสงสัยอะไร สามารถ Inbox ไปสอบถามใน Facebook ส่วนตัวได้ครับ
https://www.facebook.com/jittagornp
Spring
Spring เป็น Framework ฝั่งภาษา Java สำหรับใช้เขียน Web และ Back-end Application ที่ได้รับความนิยมอย่างมากในปัจจุบัน มีระบบนิเวศ หรือ Ecosystem ต่าง ๆ มากมาย ทำให้สามารถนำ Spring ไปใช้สร้างสรรค์ผลงานต่าง ๆ ได้อย่างรวดเร็ว
Spring-boot
Spring-boot เป็น Subset (Project นึง) ของ Spring Framework เป็นการเอา Ecosystem ต่าง ๆ ของ Spring ที่มีอยู่ มาประกอบร่างรวมกัน เพื่อให้ใช้งาน Spring ได้ง่ายขึ้น โดยมีจุดเด่นดังนี้
- สามารถใช้ Spring-boot ทำ Stand Alone หรือ Micro Service Application ได้
- มี Embeded Application Server ภายในตัว สามารถ Start ตัวเองได้ โดยไม่ต้องพึ่งพา Application Server จากภายนอก
- มีระบบ Auto Configuration
- Config ง่าย
- ใช้งานง่าย
- Deploy ง่าย
- อื่น ๆ
Spring-boot มี 2 แบบ คือ
- แบบ Servlet Stack
- แบบ Reactive Stack
Servlet Stack
- เป็นการเขียน Code แบบ Blocking I/O
- ใช้ Web MVC เป็น Base
- เขียนง่าย ตรงไปตรงมา
- Application Server จะใช้เทคนิคในการจัดการ Request/Response ด้วย Thread Pool Connection
Reactive Stack
- เป็นการเขียน Code แบบ Non-Blocking I/O
- เขียน Code แบบ Reactive (เป็นการเขียนโปรแกรมรูปแบบหนึ่ง ที่ตอบสนองต่อเหตุการณ์ที่เกิดขึ้น)
- ใช้ WebFlux เป็น Base
- เขียน/เข้าใจ ยากกว่าแบบ Servlet Stack
- Application Server จะใช้เทคนิคในการจัดการ Request/Response ด้วย Event Loop
- กิน Resources (CPU, RAM) น้อยกว่าแบบ Servlet Stack
- รองรับ Concurrent ได้มากกว่าแบบ Servlet Stack
Spring-boot Reactive
สามารถเขียนได้ 2 แบบ คือ
- แบบ Annotated Controllers
- แบบ Functional Endpoints
จากตัวอย่าง โดยส่วนมากจะใช้เป็นแบบ Annotated Controllers
เอกสาร Spring-boot Reactive
สำหรับคนที่เขียน Spring-boot ใหม่ ๆ แล้วสงสัยว่า เราจะรู้ได้ยังไงว่าเราสามารถ Config Application Properties อะไรได้บ้าง ให้ดูจากหน้านี้
ข้อแตกต่าง
WebFlux Performance
- SpringBoot 2 performance — servlet stack vs WebFlux reactive stack
- Spring Boot performance battle: blocking vs non-blocking vs reactive
- https://blog.ippon.tech/spring-5-webflux-performance-tests/
Prerequisites
สิ่งที่ต้องรู้ก่อนเขียน Spring-boot Reactive
- java 11+ ตอนนี้ผมใช้ OpenJdk 11
- Apache Maven
- Reactive Programming ลองอ่านนี่ดูได้ครับ RxJava series - part 1 - ตอน อะไรเอ่ย ReactiveX? ขอบคุณสำหรับบทความครับ
- Spring-boot ใช้ Reactor ซึ่งเป็น lib reactive ตัวนึง มีความคล้ายกันกับ ReactiveX สามารถอ่านทฤษฎีแทนกันได้ Concept เหมือนกัน
- Event Loop
- พื้นฐาน Spring Framework เช่น
- ทฤษฏี IoC (Inversion of Control) และ (DI) Dependency Injection
ตัวอย่างการเขียน Reactor
เริ่ม
Code บางตัวอาจจะไม่สามารถเอาไป Run ได้เลย เนื่องจากต้องเตรียม environment ต่าง ๆ ให้พร้อมก่อน เช่น Postgresql, Mongodb, Redis เป็นต้น ต้องมี database หรือ data source ปลายทางก่อน
ให้เรียนรู้/ดูตัวอย่างตามลำดับต่อไปนี้
ปรับ Code เป็น Java 11 แล้ว
- spring-boot-reactive-helloworld - Hello World!
- spring-boot-reactive-change-server-port - การเปลี่ยน Server Port
- spring-boot-reactive-dockerfile - การเขียน Dockerfile, การ Build Docker Image และการ Run Container
- spring-boot-reactive-jenkinsfile - การเขียน Jenkinsfile
- spring-boot-reactive-logging - การ Config และใช้งาน Logging
- spring-boot-reactive-default-timezone - การตั้งค่า Default Time Zone
- spring-boot-reactive-default-locale - การตั้งค่า Default Locale
- spring-boot-reactive-static-resources - การดึง Static Resources
- spring-boot-reactive-static-resources-custom-path - การ Custom Path เพื่อดึง Static Resources
- spring-boot-reactive-static-resources-http-caching - การกำหนด Http Caching ให้ Static Resources
- spring-boot-reactive-controller - การเขียน Controller
- spring-boot-reactive-cors - การ config Cors (Cross-origin resource sharing)
- spring-boot-reactive-form-data - การรับค่าจาก Html Form
- spring-boot-reactive-lombok-mapstruct - การใช้งาน Lombok + MapStruct
- spring-boot-reactive-download-file - การ Download File
- spring-boot-reactive-upload-file - การ Upload File
- spring-boot-reactive-session - พื้นฐานการใช้ Session
- spring-boot-reactive-cookie - พื้นฐานการใช้ Cookie
- spring-boot-reactive-configuration-properties - การอ่าน Config จาก application.properties
- spring-boot-reactive-i18n - การทำระบบให้รองรับหลายภาษา (i18n)
- spring-boot-reactive-thymleaf - การใช้ Thymleaf ทำ View (Server Site) Rendering (HTML)
- spring-boot-reactive-web-filter - การเขียน Web Filter
- spring-boot-reactive-error-handler - การจัดการ Exception หรือ Error
- spring-boot-reactive-custom-error-handler - การ Custom ตัวจัดการ Exception หรือ Error
- spring-boot-reactive-validation - การ Validate ข้อมูล
- spring-boot-reactive-manual-validation - การ Validate ข้อมูลแบบ Manual
- spring-boot-reactive-custom-validator - การ custom validator
- spring-boot-reactive-scheduling - การ Run Job/Task แบบ Scheduling
- spring-boot-reactive-unit-test-junit5 - การเขียน Unit Test ด้วย JUnit 5
- spring-boot-reactive-security - พื้นฐานการ Config Spring Security สำหรับทำการ Login
- spring-boot-reactive-security-custom-login - การ Custom หน้า Login
- spring-boot-reactive-security-authority - การกำหนดสิทธิ์การเข้าถึง
- spring-boot-reactive-security-jwt - การใช้ Spring-security ทำงานร่วมกับ JWT
- spring-boot-reactive-swagger - การทำ API Document ด้วย Swagger
- spring-boot-reactive-pagination - การทำ Pagination
- spring-boot-reactive-r2dbc-postgresql - การเขียน Code เชื่อมต่อ Database PosgreSQL ด้วย R2DBC
- spring-boot-reactive-r2dbc-database-client - Manual Query ด้วย R2DBC Database Client
- spring-boot-reactive-r2dbc-native-sql - Native SQL ด้วย R2DBC Database Client
- spring-boot-reactive-r2dbc-entity-template - Manual Query ด้วย R2DBC Entity Template
- spring-boot-reactive-r2dbc-pagination - การทำ Pagination สำหรับ R2DBC
- spring-boot-reactive-r2dbc-pool-postgresql - การทำ Connection Pool สำหรับ R2DBC PosgreSQL
- spring-boot-reactive-gmail - การส่ง email ด้วย Gmail
- spring-boot-reactive-oauth-client - การเขียน Code เพื่อ Login ผ่าน OAuth ของ Google, Facebook
- spring-boot-reactive-google-cloud-storage - การเขียน Code เพื่อเชื่อมต่อกับ Google Cloud Storage
- spring-boot-reactive-digitalocean-spaces - การเขียน Code เพื่อเชื่อมต่อกับ DigitalOcean Spaces
- spring-boot-reactive-neo4j - การเขียน Code เชื่อมต่อ Graph Database Neo4j
- spring-boot-reactive-redis-pubsub - การเขียน Code เชื่อมต่อ Redis แบบ Pub/Sub
- spring-boot-reactive-websocket - การเขียน WebSocket
- spring-boot-reactive-full-example - การนำตัวอย่างต่าง ๆ มาประกอบเข้าด้วยกัน
- spring-boot-reactive-kafka-example - การเขียน Code เชื่อมต่อ Kafka
รอการปรับ Code เป็น Java 11
- spring-boot-webflux-unit-test-mockito - การเขียน Unit Test + Mockito
- spring-boot-webflux-test-coverage - Test Coverage ด้วย JaCoCo
- spring-boot-webflux-postgresql - การเชื่อมต่อ Postgresql (Relational Database)
- spring-boot-webflux-jdbc-template - การเขียน Native Query จาก JDBC Template
- spring-boot-webflux-entity - การเขียน Entity Class
- spring-boot-webflux-simple-service - พื้นฐานการเขียน Service
- spring-boot-webflux-mongodb - การเชื่อมต่อ Mongodb (NoSQL Document Database)
- spring-boot-webflux-mongo-operations - การเขียน Query ผ่าน Mogo Operations
- spring-boot-webflux-redis - การเชื่อมต่อ Redis (Key/Value NoSQL)
- spring-boot-webflux-nuxtjs - การเขียน Spring-boot Reactive + Nuxt.js
- spring-boot-webflux-javadoc - การ Generate Java Document API