Serving Web Content with Spring MVC
ตัวอย่างนี้เป็นตัวอย่างที่อ่านและทดลองทำจากบทความต้นฉบับนี้ Serving Web Content with Spring MVC โดยใช้เครื่องมือคือ Spring Tool Suite
Stack
- ระบบปฎิบัติการที่ใช้ : Ubuntu 14.04
- เครื่องมือ : Spring Tool Suite 3.6.3
- Java JDK 7 update 65 (1.7.0_65)
- เวลาที่ใช้ : ประมาณ 45 นาที (รวมการอ่าน ทำความเข้าใจด้วย)
สร้างโปรเจ็ค
เปิด Spring Tool Suite ขึ้นมา จากนั้นทำการ Import โปรเจ็ค โดยค้นหา "Serving web content"
- Build Type : เลือกเป็น Gradle
เมื่อ Import ได้แล้ว จะเห็นโปรเจ็คอยู่สองตัว คือ
- gs-serving-web-content-initial
- gs-serving-web-content-complete
ตัว gs-serving-web-content-initial เป็นโปรเจ็คเปล่าๆ เราจะใช้ตัวนี้ ส่วนอีกตัว gs-serving-web-content-complete เป็นโปรเจ็คที่เสร็จแล้ว เผื่อเอาไว้ดูเปรียบเทียบว่าเราทำตรงไหนผิดพลาด
สร้าง Web Controller
ใน Spring, ตัว Controller จะเป็นตัวควบคุม HTTP request ต่างๆ ง่ายๆ โดยการใส่ annotation @Controller
อย่างเช่น ตัวอย่าง GreetingController
เป็นตัวจัดการ GET
สำหรับ /greeting
โดย return เป็น ชื่อของ View
กลับมาเพื่อทำการ render เป็น HTML
ไฟล์ /src/main/java/hello/GreetingController.java
package hello;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
@Controller
public class GreetingController {
@RequestMapping("/greeting")
public String greeting(
@RequestParam(value="name", required=false, defaultValue="world")
String name,
Model model) {
model.addAttribute("name", name);
return "greeting";
}
}
@RequestMapping
: เป็น annotation สำหรับ mapping ระหว่าง HTTP request/greeting
กับเมธอดgreeting()
@RequestParam
: จะทำการ bind ค่าจาก query String parametername
เข้ากับ parametername
ของเมธอดgreeting()
โดย query String parameter เซตค่าrequired
เป็น false คือไม่บังคับว่าจะต้องมีหรือไม่มีก็ได้ ถ้าไม่มีก็จะใช้ค่าdefaultValue
แทน โดยค่าของname
ก็จะถูกเพิ่มเข้าไปในออปเจ็คModel
เพื่อสามารถเข้าถึงได้ในหน้า View Template (ใช้ Thymeleaf)
@RequestMapping
โดย default นั้น map ทุก HTTP reqeust เช่นGET
,PUT
,POST
ถ้าเราจะเจาะจงว่าจะ map เฉพาะGET
ก็ทำได้เช่น@ReqeustMapping(method=GET)
ต่อมาที่ไฟล์ src/main/resources/templates/greeting.html
ทำการเพิ่มโค๊ดด้านล่างลงไป
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Getting Started : Serving Web Content</title>
</head>
<body>
<p th:text="'Hello, ' + ${name} + '!'" />
</body>
</html>
ไฟล์ html ด้านบนนี้จะใช้ view technology ในเคสนี้คือ Themeleaf เพื่อทำการเรนเดอร์ HTML ข้อดีคือเราสามารถที่จะเข้าถึงตัวแปร ออปเจ็คของ Java ผ่านหน้า HTML ได้ เช่น
xmlns:th="http://www.thymeleaf.org"
: เป็นการกำหนด xml schema โดยเวลาจะใช้ thymeleaf ก็แค่ใช้ตัวย่อว่าth
th:text
: เป็น expression ที่ทำการ render ค่า parameter${name}
จาก controller
สร้างคลาส Application
เปิดไฟล์ src/main/java/hello/Application.java
ขึ้นมา แล้วเพิ่มโค๊ดด้านล่างนี้ลงไป
package hello;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
@ComponentScan
@EnableAutoConfiguration
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
เมธอด main()
จะมี SpringApplication
ทำการรันคลาส Application
โดยใช้ component ใน ApplicationContext
เป็นตัวจัดการ ตัว @ComponentScan
เป็น annotation ที่บอก Spring ให้ทำการค้นหา แพคเกต hello
ว่ามีคลาสไหนทำการ register @Component
ไว้บ้าง ซึ่งจะเห็นได้ว่า คลาส GreetingController
ได้ทำการ register ไว้เพราะว่ามี @Controller
อยู่ (@Controller
เป็นส่วนหนึ่งของ @Component
annotation @EnableAutoConfiguration
เป็นการตั้งค่า auto configuration ให้เราเองโดยตัว DispatcherServlet โดยที่ไม่ต้องมีไฟล์ web.xml
เลย
Test the Service
ทดสอบรันโปรแกรม Run As => Spring Boot App ตัว Spring Boot App จะทำการรันโดยใช้ Tomcat Server
. _ __ _ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |_ __| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v1.1.10.RELEASE)
Starting Application on
Starting Servlet Engine: Apache Tomcat/7.0.57
Tomcat started on port(s): 8080/http
...
...
Started Application in 4.937 seconds (JVM running for 6.005)
เมื่อ start Application เรียบร้อยแล้ว ก็เปิด Browser แล้วเข้าหน้า URL นี้ http://localhost:8080/greeting จะเห็นข้อมูลด้านล่างนี้ปรากฎอยู่
"Hello, World!"
สามารถส่ง parameter ก็ได้เช่นกัน โดยตัวอย่าง ส่ง name
เป็น query string parameter จะได้ URL ดังนี้ http://locahost:8080/greeting?name=Devahoy จะเห็นได้ว่าผลลัพธ์เปลี่ยนไปแล้ว จาก Hello, World!
เป็น Hello, Devahoy!
"Hello, Devahoy!"
แสดงว่า @RequestParam
ใน GreetingController
นั้นทำงานได้ตามที่เราคาดหวัง โดย parameter name
ค่า default มันคือคำว่า "World" แต่เมื่อไหร่ที่เราส่ง parameter มาด้วย มันก็จะไป override ค่า default และใช้ค่า parameter ของเราเอง
สรุปจากบทความนี้
@RequestMapping
: map HTTP request กับเมธอดใน Java@RequestParam
: ไว้ bind ค่า query string parameter กับ String หรือ Object@Controller
: เป็น component เพื่อ handle HTTP request โดยมีHttpServletRequest
และHttpServletResponse
@ComponentScan
: เอาไว้ค้นหาทั้งแพคเกจ เพื่อหา component ที่ใช้ในโปรเจ็คSpringApplication
: เอาไว้สั่ง launch ตัว Spring Application จาก main classTomcat
: เป็น Servlet Container ที่เอาไว้รัน Spring ได้Spring Boot
: เป็น stand-alone สำหรับ Spring โดยรวม Tomcat, Jetty เข้าไปด้วย (ไม่ต้อง deploy โดยใช้ ไฟล์ WAR)thymeleaf
: เป็น Template Engine ที่สามารถ render ออปเจ็คของ Java ในไฟล์ HTML ได้ คล้ายๆ Handlebars, Jade หรือ erb ของ Ruby
สิ่งที่ต้องเรียนรู้เพิ่มเติม
- อ่าน API และ Reference เพิ่มเติม
- ไปค้นคว้าเกี่ยวกับ Themeleaf ต่อ
- ลองสร้างโปรเจ็คแบบ Command Line ไม่ใช้ IDE โดยใช้ Gradle/Maven และ Text Editor
Reference
- Authors
- Name
- Chai Phonbopit
- Website
- @Phonbopit