Skip to content

Commit b35701b

Browse files
committed
add spring-boot-reactive-default-timezone
1 parent ea21d2d commit b35701b

File tree

10 files changed

+292
-0
lines changed

10 files changed

+292
-0
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
- [spring-boot-reactive-dockerfile](spring-boot-reactive-dockerfile) - การเขียน Dockerfile, การ Build Docker Image และการ Run Container
5353
- [spring-boot-reactive-jenkinsfile](spring-boot-reactive-jenkinsfile) - การเขียน Jenkinsfile
5454
- [spring-boot-reactive-logging](spring-boot-reactive-logging) - การ Config และใช้งาน Logging
55+
- [spring-boot-reactive-default-timezone](spring-boot-reactive-default-timezone) - การตั้งค่า Default Time Zone
5556
- [spring-boot-reactive-controller](spring-boot-reactive-controller) - การเขียน Controller
5657
- [spring-boot-reactive-cors](spring-boot-reactive-cors) - การ config Cors (Cross-origin resource sharing)
5758
- [spring-boot-reactive-form-data](spring-boot-reactive-form-data) - การรับค่าจาก Html Form
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
# spring-boot-reactive-default-timezone
2+
3+
> ตัวอย่างการเขียน Spring-boot Reactive Default Time Zone
4+
5+
# Prerequisites
6+
7+
- มีความเข้าใจเรื่อง Time Zone
8+
- ถ้าไม่เข้าใจสามารถเรียนรู้ได้จาก [สรุปสั้น ๆ เรื่องเขตเวลา (Time Zone) และไขข้อสงสัยว่าทำไมเวลาประเทศไทยถึงเป็น UTC+7](https://www.jittagornp.me/blog/short-summary-of-time-zone/)
9+
- ถ้าใครใช้ Server เป็น Ubuntu สามารถดูตัวอย่างการ Set Time Zone ได้จาก [ตั้งค่า Time Zone สำหรับ Ubuntu 20.04 LTS](https://www.jittagornp.me/blog/set-timezone-for-ubuntu20.04/)
10+
11+
# 1. เพิ่ม Dependencies และ Plugins
12+
13+
pom.xml
14+
``` xml
15+
...
16+
<parent>
17+
<groupId>org.springframework.boot</groupId>
18+
<artifactId>spring-boot-starter-parent</artifactId>
19+
<version>2.3.2.RELEASE</version>
20+
</parent>
21+
22+
<dependencies>
23+
<dependency>
24+
<groupId>org.springframework.boot</groupId>
25+
<artifactId>spring-boot-starter-webflux</artifactId>
26+
</dependency>
27+
28+
<dependency>
29+
<groupId>org.projectlombok</groupId>
30+
<artifactId>lombok</artifactId>
31+
<scope>provided</scope>
32+
</dependency>
33+
</dependencies>
34+
35+
<build>
36+
<plugins>
37+
<plugin>
38+
<groupId>org.springframework.boot</groupId>
39+
<artifactId>spring-boot-maven-plugin</artifactId>
40+
<executions>
41+
<execution>
42+
<id>build-info</id>
43+
<goals>
44+
<goal>build-info</goal>
45+
</goals>
46+
<configuration>
47+
<additionalProperties>
48+
<java.version>${java.version}</java.version>
49+
</additionalProperties>
50+
</configuration>
51+
</execution>
52+
</executions>
53+
</plugin>
54+
</plugins>
55+
</build>
56+
...
57+
```
58+
59+
# 2. เขียน Main Class
60+
61+
``` java
62+
@SpringBootApplication
63+
@ComponentScan(basePackages = {"me.jittagornp"})
64+
public class AppStarter {
65+
66+
public static void main(String[] args) {
67+
SpringApplication.run(AppStarter.class, args);
68+
}
69+
70+
}
71+
```
72+
73+
# 3. Config Default Time Zone
74+
75+
สร้าง Java Class Config ขึ้นมา แล้วกำหนด Time Zone ตามที่ต้องการ
76+
77+
```java
78+
@Slf4j
79+
@Configuration
80+
public class TimeZoneConfig {
81+
82+
@PostConstruct
83+
public void setDefaultTimeZone(){
84+
85+
TimeZone.setDefault(TimeZone.getTimeZone("Asia/Bangkok"));
86+
87+
log.info("set Default Time Zone => {}", TimeZone.getDefault().getID());
88+
89+
}
90+
91+
}
92+
```
93+
94+
**คำอธิบาย**
95+
96+
- โดยปกติ `TimeZone.getDefault()` จะทำการอ่านค่า Time Zone มาจากเครื่อง
97+
- ถ้าเครื่องเรา Default Time Zone เป็น `UTC` แล้ว `TimeZone.getDefault()` ก็จะได้ `UTC` เช่นเดียวกัน
98+
- ถ้าเครื่องเรา Default Time Zone เป็น `Asia/Bangkok` แล้ว `TimeZone.getDefault()` ก็จะได้ `Asia/Bangkok` เช่นเดียวกัน
99+
- เพราะฉะนั้น ต้องระวังเวลาเอา App ไป Deploy ให้เช็คเสมอว่าเครื่องนั้น Default Time Zone เป็นอะไร
100+
- เพื่อป้องกันข้อผิดพลาดอีกชั้น เราสามารถ Set Time Zone App เองได้โดยการใช้ `TimeZone.setDefault(...)`
101+
- กำหนดให้ Java (8+ DateTime) ใช้ Default Time Zone เป็น `Asia/Bangkok` หรือ `UTC+7`
102+
103+
# 4. เขียน Controller
104+
``` java
105+
@RestController
106+
@RequestMapping("/time-zones")
107+
public class TimeZoneController {
108+
109+
@GetMapping
110+
public Flux<TimeZone> getAvailableTimeZones(){
111+
return Flux.fromIterable(Arrays.asList(TimeZone.getAvailableIDs()))
112+
.map(TimeZone::getTimeZone);
113+
}
114+
115+
@GetMapping("/default")
116+
public Mono<TimeZone> getDefault() {
117+
return Mono.just(TimeZone.getDefault());
118+
}
119+
120+
}
121+
```
122+
123+
# 5. Build Code
124+
cd ไปที่ root ของ project จากนั้น
125+
``` sh
126+
$ mvn clean package
127+
```
128+
129+
# 6. Run
130+
``` sh
131+
$ mvn spring-boot:run
132+
```
133+
134+
![](./console.png)
135+
136+
# 7. เข้าใช้งาน
137+
138+
เปิด browser แล้วเข้า [http://localhost:8080/times-zones](http://localhost:8080/times-zones)
139+
140+
![](./available-timezones.png)
141+
142+
Default Time Zone
143+
144+
![](./default-timezone.png)
Loading
Loading
Loading
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
3+
<modelVersion>4.0.0</modelVersion>
4+
5+
<groupId>me.jittagornp.example</groupId>
6+
<artifactId>spring-boot-reactive-default-timezone</artifactId>
7+
<version>1.0.0-SNAPSHOT</version>
8+
<packaging>jar</packaging>
9+
10+
<properties>
11+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
12+
<maven.compiler.source>11</maven.compiler.source>
13+
<maven.compiler.target>11</maven.compiler.target>
14+
</properties>
15+
16+
<parent>
17+
<groupId>org.springframework.boot</groupId>
18+
<artifactId>spring-boot-starter-parent</artifactId>
19+
<version>2.3.2.RELEASE</version>
20+
</parent>
21+
22+
<dependencies>
23+
<dependency>
24+
<groupId>org.springframework.boot</groupId>
25+
<artifactId>spring-boot-starter-webflux</artifactId>
26+
</dependency>
27+
28+
<dependency>
29+
<groupId>org.projectlombok</groupId>
30+
<artifactId>lombok</artifactId>
31+
<scope>provided</scope>
32+
</dependency>
33+
</dependencies>
34+
35+
<build>
36+
<plugins>
37+
<plugin>
38+
<groupId>org.springframework.boot</groupId>
39+
<artifactId>spring-boot-maven-plugin</artifactId>
40+
<executions>
41+
<execution>
42+
<id>build-info</id>
43+
<goals>
44+
<goal>build-info</goal>
45+
</goals>
46+
<configuration>
47+
<additionalProperties>
48+
<java.version>${java.version}</java.version>
49+
</additionalProperties>
50+
</configuration>
51+
</execution>
52+
</executions>
53+
</plugin>
54+
</plugins>
55+
</build>
56+
57+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/*
2+
* Copyright 2019-Current jittagornp.me
3+
*/
4+
package me.jittagornp.example.reactive;
5+
6+
import org.springframework.boot.SpringApplication;
7+
import org.springframework.boot.autoconfigure.SpringBootApplication;
8+
import org.springframework.context.annotation.ComponentScan;
9+
10+
/**
11+
* @author jitta
12+
*/
13+
@SpringBootApplication
14+
@ComponentScan(basePackages = {"me.jittagornp"})
15+
public class AppStarter {
16+
17+
public static void main(String[] args) {
18+
SpringApplication.run(AppStarter.class, args);
19+
}
20+
21+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package me.jittagornp.example.reactive.config;
2+
3+
import lombok.extern.slf4j.Slf4j;
4+
import org.springframework.context.annotation.Configuration;
5+
6+
import javax.annotation.PostConstruct;
7+
import java.util.TimeZone;
8+
9+
@Slf4j
10+
@Configuration
11+
public class TimeZoneConfig {
12+
13+
@PostConstruct
14+
public void setDefaultTimeZone(){
15+
16+
TimeZone.setDefault(TimeZone.getTimeZone("Asia/Bangkok"));
17+
18+
log.info("set Default Time Zone => {}", TimeZone.getDefault().getID());
19+
20+
}
21+
22+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/*
2+
* Copyright 2019-Current jittagornp.me
3+
*/
4+
package me.jittagornp.example.reactive.controller;
5+
6+
import org.springframework.web.bind.annotation.GetMapping;
7+
import org.springframework.web.bind.annotation.RestController;
8+
import reactor.core.publisher.Mono;
9+
10+
/**
11+
* @author jitta
12+
*/
13+
@RestController
14+
public class HomeController {
15+
16+
@GetMapping({"", "/"})
17+
public Mono<String> hello() {
18+
return Mono.just("Hello world.");
19+
}
20+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package me.jittagornp.example.reactive.controller;
2+
3+
import org.springframework.web.bind.annotation.GetMapping;
4+
import org.springframework.web.bind.annotation.RequestMapping;
5+
import org.springframework.web.bind.annotation.RestController;
6+
import reactor.core.publisher.Flux;
7+
import reactor.core.publisher.Mono;
8+
9+
import java.util.Arrays;
10+
import java.util.TimeZone;
11+
12+
@RestController
13+
@RequestMapping("/time-zones")
14+
public class TimeZoneController {
15+
16+
@GetMapping
17+
public Flux<TimeZone> getAvailableTimeZones(){
18+
return Flux.fromIterable(Arrays.asList(TimeZone.getAvailableIDs()))
19+
.map(TimeZone::getTimeZone);
20+
}
21+
22+
@GetMapping("/default")
23+
public Mono<TimeZone> getDefault() {
24+
return Mono.just(TimeZone.getDefault());
25+
}
26+
27+
}

0 commit comments

Comments
 (0)