RESTful Web Services - คู่มือฉบับย่อ
สถาปัตยกรรม REST คืออะไร?
REST ย่อมาจาก REpresentational State Transfer REST เป็นสถาปัตยกรรมตามมาตรฐานเว็บและใช้โปรโตคอล HTTP มันหมุนรอบทรัพยากรที่ทุกองค์ประกอบเป็นทรัพยากรและทรัพยากรถูกเข้าถึงโดยอินเทอร์เฟซทั่วไปโดยใช้วิธีมาตรฐาน HTTP REST เปิดตัวครั้งแรกโดย Roy Fielding ในปี 2000
ในสถาปัตยกรรม REST เซิร์ฟเวอร์ REST เพียงแค่ให้การเข้าถึงทรัพยากรและการเข้าถึงไคลเอ็นต์ REST และปรับเปลี่ยนทรัพยากร ที่นี่แต่ละทรัพยากรจะถูกระบุโดย URI / global IDs REST ใช้การแทนค่าต่างๆเพื่อแสดงทรัพยากรเช่นข้อความ, JSON, XML JSON เป็นที่นิยมมากที่สุด
วิธี HTTP
โดยทั่วไปจะใช้วิธี HTTP สี่วิธีต่อไปนี้ในสถาปัตยกรรมที่ใช้ REST
GET - ให้การเข้าถึงทรัพยากรแบบอ่านอย่างเดียว
POST - ใช้เพื่อสร้างทรัพยากรใหม่
DELETE - ใช้เพื่อลบทรัพยากร
PUT - ใช้เพื่ออัปเดตทรัพยากรที่มีอยู่หรือสร้างทรัพยากรใหม่
ข้อมูลเบื้องต้นเกี่ยวกับบริการเว็บ RESTFul
บริการบนเว็บคือชุดของโปรโตคอลและมาตรฐานแบบเปิดที่ใช้สำหรับการแลกเปลี่ยนข้อมูลระหว่างแอปพลิเคชันหรือระบบ แอปพลิเคชันซอฟต์แวร์ที่เขียนด้วยภาษาโปรแกรมต่างๆและทำงานบนแพลตฟอร์มต่างๆสามารถใช้บริการเว็บเพื่อแลกเปลี่ยนข้อมูลผ่านเครือข่ายคอมพิวเตอร์เช่นอินเทอร์เน็ตในลักษณะที่คล้ายกับการสื่อสารระหว่างกระบวนการบนคอมพิวเตอร์เครื่องเดียว ความสามารถในการทำงานร่วมกันนี้ (เช่นระหว่าง Java และ Python หรือแอปพลิเคชัน Windows และ Linux) เกิดจากการใช้มาตรฐานแบบเปิด
บริการเว็บที่ใช้สถาปัตยกรรม REST เรียกว่าบริการเว็บ RESTful บริการเว็บเหล่านี้ใช้วิธี HTTP เพื่อใช้แนวคิดของสถาปัตยกรรม REST บริการเว็บ RESTful มักจะกำหนด URI, Uniform Resource Identifier a service จัดเตรียมการแสดงทรัพยากรเช่น JSON และชุดของวิธี HTTP
การสร้าง RESTFul Webservice
ในบทถัดไปเราจะสร้างบริการเว็บกล่าวว่าการจัดการผู้ใช้ด้วยฟังก์ชันต่อไปนี้ -
ซีเนียร์ | URI | วิธี HTTP | โพสต์ร่างกาย | ผลลัพธ์ |
---|---|---|---|---|
1 | / UserService / ผู้ใช้ | รับ | ว่างเปล่า | แสดงรายชื่อผู้ใช้ทั้งหมด |
2 | / UserService / addUser | โพสต์ | สตริง JSON | เพิ่มรายละเอียดของผู้ใช้ใหม่ |
3 | / UserService / getUser /: id | รับ | ว่างเปล่า | แสดงรายละเอียดของผู้ใช้ |
บทช่วยสอนนี้จะแนะนำคุณเกี่ยวกับวิธีเตรียมสภาพแวดล้อมการพัฒนาเพื่อเริ่มงานของคุณ Jersey Frameworkเพื่อสร้าง RESTful Web Services ใช้กรอบเจอร์ซีย์JAX-RS 2.0API ซึ่งเป็นข้อกำหนดมาตรฐานในการสร้าง RESTful Web Services บทช่วยสอนนี้จะสอนวิธีการตั้งค่าJDK, Tomcat และ Eclipse บนเครื่องของคุณก่อนที่คุณจะติดตั้ง Jersey Framework
ตั้งค่า Java Development Kit (JDK)
คุณสามารถดาวน์โหลด SDK เวอร์ชันล่าสุดจากเว็บไซต์ Java ของออราเคิล - Java SE ดาวน์โหลด คุณจะพบคำแนะนำในการติดตั้ง JDK ในไฟล์ที่ดาวน์โหลด ทำตามคำแนะนำที่กำหนดเพื่อติดตั้งและกำหนดค่าการตั้งค่า สุดท้ายตั้งค่าPATH และ JAVA_HOME ตัวแปรสภาพแวดล้อมเพื่ออ้างถึงไดเร็กทอรีที่มี Java และ Javacโดยทั่วไปคือ java_install_dir / bin และ java_install_dir ตามลำดับ
หากคุณใช้ Windows และติดตั้ง JDK ใน C: \ jdk1.7.0_75 คุณจะต้องใส่บรรทัดต่อไปนี้ในไฟล์ C: \ autoexec.bat ของคุณ
set PATH = C:\jdk1.7.0_75\bin;%PATH%
set JAVA_HOME = C:\jdk1.7.0_75
หรือใน Windows NT / 2000 / XP คุณสามารถคลิกขวาที่ My Computer →เลือก Properties →จากนั้น Advanced →จากนั้น Environment Variables จากนั้นคุณจะอัปเดตค่า PATH และกดปุ่ม OK
ใน Unix (Solaris, Linux ฯลฯ ) หากติดตั้ง SDK ใน /usr/local/jdk1.7.0_75 และคุณใช้ C Shell คุณจะต้องใส่สิ่งต่อไปนี้ลงในไฟล์. cshrc ของคุณ
setenv PATH /usr/local/jdk1.7.0_75/bin:$PATH
setenv JAVA_HOME /usr/local/jdk1.7.0_75
หรือหากคุณใช้ Integrated Development Environment (IDE) เช่น Borland JBuilder, Eclipse, IntelliJ IDEA หรือ Sun ONE Studio ให้คอมไพล์และรันโปรแกรมง่ายๆเพื่อยืนยันว่า IDE รู้ตำแหน่งที่คุณติดตั้ง Java หรือทำการตั้งค่าที่เหมาะสมตามเอกสารที่กำหนด ของ IDE
ตั้งค่า Eclipse IDE
ตัวอย่างทั้งหมดในบทช่วยสอนนี้เขียนขึ้นโดยใช้ Eclipse IDE ดังนั้นฉันขอแนะนำให้คุณติดตั้ง Eclipse เวอร์ชันล่าสุดในเครื่องของคุณ
ในการติดตั้ง Eclipse IDE ให้ดาวน์โหลดไบนารี Eclipse ล่าสุดจาก https://www.eclipse.org/downloads/. เมื่อคุณดาวน์โหลดการติดตั้งแล้วให้แกะการกระจายไบนารีไปยังตำแหน่งที่สะดวก ตัวอย่างเช่นใน C: \ eclipse บน windows หรือ / usr / local / eclipse บน Linux / Unix และสุดท้ายตั้งค่าตัวแปร PATH ให้เหมาะสม
Eclipse สามารถเริ่มต้นได้โดยดำเนินการคำสั่งต่อไปนี้บนเครื่อง windows หรือคุณสามารถดับเบิลคลิกที่ eclipse.exe
%C:\eclipse\eclipse.exe
Eclipse สามารถเริ่มต้นได้โดยดำเนินการคำสั่งต่อไปนี้บนเครื่อง Unix (Solaris, Linux และอื่น ๆ ) -
$/usr/local/eclipse/eclipse
หลังจากเริ่มต้นสำเร็จหากทุกอย่างเรียบร้อยดีหน้าจอของคุณควรแสดงผลลัพธ์ต่อไปนี้ -
ติดตั้งไลบรารีของ Jersey Framework
ตอนนี้ถ้าทุกอย่างเรียบร้อยคุณสามารถดำเนินการตั้งค่าเจอร์ซีย์เฟรมเวิร์คได้ ต่อไปนี้เป็นขั้นตอนง่ายๆในการดาวน์โหลดและติดตั้งเฟรมเวิร์กบนเครื่องของคุณ
เลือกว่าคุณต้องการติดตั้ง Jersey บน Windows หรือ Unix จากนั้นทำตามขั้นตอนต่อไปเพื่อดาวน์โหลดไฟล์. zip สำหรับ windows จากนั้นเลือกไฟล์. tz สำหรับ Unix
ดาวน์โหลดเวอร์ชันล่าสุดของไบนารีเจอร์ซีย์เฟรมเวิร์กจากลิงค์ต่อไปนี้ - https://jersey.java.net/download.html.
ในขณะที่เขียนบทช่วยสอนนี้ฉันดาวน์โหลด jaxrs-ri-2.17.zip บนเครื่อง Windows ของฉันและเมื่อคุณเปิดเครื่องรูดไฟล์ที่ดาวน์โหลดมามันจะให้โครงสร้างไดเร็กทอรีภายใน E: \ jaxrs-ri-2.17 \ jaxrs-ri ดังที่แสดงในภาพหน้าจอต่อไปนี้
คุณจะพบไลบรารีเจอร์ซีย์ทั้งหมดในไดเรกทอรี C:\jaxrs-ri-2.17\jaxrs-ri\lib และการอ้างอิงใน C:\jaxrs-ri-2.17\jaxrs-ri\ext. ตรวจสอบให้แน่ใจว่าคุณได้ตั้งค่าตัวแปร CLASSPATH บนไดเร็กทอรีนี้อย่างถูกต้องมิฉะนั้นคุณจะประสบปัญหาขณะเรียกใช้แอปพลิเคชัน หากคุณใช้ Eclipse คุณไม่จำเป็นต้องตั้งค่า CLASSPATH เนื่องจากการตั้งค่าทั้งหมดจะดำเนินการผ่าน Eclipse
ตั้งค่า Apache Tomcat
คุณสามารถดาวน์โหลด Tomcat เวอร์ชันล่าสุดได้จาก https://tomcat.apache.org/. เมื่อคุณดาวน์โหลดการติดตั้งแล้วให้แกะการกระจายไบนารีในตำแหน่งที่สะดวก ตัวอย่างเช่นใน C: \ apache-tomcat-7.0.59 บน windows หรือ /usr/local/apache-tomcat-7.0.59 บน Linux / Unix และตั้งค่าตัวแปรสภาพแวดล้อม CATALINA_HOME ที่ชี้ไปยังตำแหน่งการติดตั้ง
Tomcat สามารถเริ่มได้โดยดำเนินการคำสั่งต่อไปนี้บนเครื่อง windows หรือคุณสามารถดับเบิลคลิกที่ startup.bat
%CATALINA_HOME%\bin\startup.bat
หรือ
C:\apache-tomcat-7.0.59\bin\startup.bat
Tomcat สามารถเริ่มต้นได้โดยดำเนินการคำสั่งต่อไปนี้บนเครื่อง Unix (Solaris, Linux และอื่น ๆ ) -
$CATALINA_HOME/bin/startup.sh
หรือ
/usr/local/apache-tomcat-7.0.59/bin/startup.sh
หลังจากเริ่มต้นสำเร็จเว็บแอปพลิเคชันเริ่มต้นที่มาพร้อมกับ Tomcat จะพร้อมใช้งานโดยไปที่ http://localhost:8080/. หากทุกอย่างเรียบร้อยดีควรแสดงผลลัพธ์ต่อไปนี้ -
ข้อมูลเพิ่มเติมเกี่ยวกับการกำหนดค่าและการเรียกใช้ Tomcat สามารถพบได้ในเอกสารประกอบในหน้านี้ ข้อมูลนี้สามารถพบได้ในเว็บไซต์ Tomcat -https://tomcat.apache.org.
Tomcat สามารถหยุดได้โดยดำเนินการคำสั่งต่อไปนี้บนเครื่อง windows -
%CATALINA_HOME%\bin\shutdown
หรือ
C:\apache-tomcat-7.0.59\bin\shutdown
Tomcat สามารถหยุดได้โดยดำเนินการคำสั่งต่อไปนี้บนเครื่อง Unix (Solaris, Linux และอื่น ๆ ) -
$CATALINA_HOME/bin/shutdown.sh
หรือ
/usr/local/apache-tomcat-7.0.59/bin/shutdown.sh
เมื่อคุณทำขั้นตอนสุดท้ายนี้เสร็จแล้วคุณก็พร้อมที่จะดำเนินการต่อสำหรับตัวอย่างแรกของ Jersey ซึ่งคุณจะเห็นในบทถัดไป
ให้เราเริ่มเขียนบริการเว็บ RESTful จริงด้วย Jersey Framework ก่อนที่คุณจะเริ่มต้นการเขียนตัวอย่างแรกของคุณโดยใช้ย์กรอบที่คุณต้องให้แน่ใจว่าคุณมีการตั้งค่าสภาพแวดล้อมย์คุณอย่างถูกต้องตามที่ได้อธิบายในสงบ Web Services - สิ่งแวดล้อมการติดตั้งบท ที่นี่ฉันสมมติว่าคุณมีความรู้เกี่ยวกับ Eclipse IDE เพียงเล็กน้อย
ดังนั้นให้เราดำเนินการเขียนแอปพลิเคชัน Jersey แบบง่ายซึ่งจะเปิดเผยวิธีการบริการเว็บเพื่อแสดงรายชื่อผู้ใช้
การสร้างโครงการ Java
ขั้นตอนแรกคือการสร้าง Dynamic Web Project โดยใช้ Eclipse IDE ทำตามตัวเลือกFile → New → Project และสุดท้ายเลือก Dynamic Web Projectตัวช่วยสร้างจากรายการตัวช่วยสร้าง ตอนนี้ตั้งชื่อโครงการของคุณเป็นUserManagement โดยใช้หน้าต่างตัวช่วยสร้างดังที่แสดงในภาพหน้าจอต่อไปนี้ -
เมื่อสร้างโครงการของคุณสำเร็จคุณจะมีเนื้อหาต่อไปนี้ในไฟล์ Project Explorer -
การเพิ่มไลบรารีที่จำเป็น
ในขั้นตอนที่สองให้เราเพิ่ม Jersey Framework และการอ้างอิง (ไลบรารี) ในโครงการของเรา คัดลอกขวดทั้งหมดจากไดเรกทอรีต่อไปนี้ของโฟลเดอร์ดาวน์โหลดเจอร์ซีย์ในไดเรกทอรี WEB-INF / lib ของโครงการ
- \jaxrs-ri-2.17\jaxrs-ri\api
- \jaxrs-ri-2.17\jaxrs-ri\ext
- \jaxrs-ri-2.17\jaxrs-ri\lib
ตอนนี้คลิกขวาที่ชื่อโครงการของคุณ UserManagement จากนั้นทำตามตัวเลือกที่มีอยู่ในเมนูบริบท - Build Path → Configure Build Path เพื่อแสดงหน้าต่าง Java Build Path
ตอนนี้ใช้ Add JARs ปุ่มอยู่ใต้ Libraries เพื่อเพิ่ม JAR ที่มีอยู่ในไดเร็กทอรี WEBINF / lib
การสร้างไฟล์ต้นฉบับ
ตอนนี้ให้เราสร้างไฟล์ต้นฉบับจริงภายใต้ไฟล์ UserManagementโครงการ. ก่อนอื่นเราต้องสร้างแพ็คเกจที่เรียกว่าcom.tutorialspoint. ในการดำเนินการนี้ให้คลิกขวาที่ src ในส่วน package explorer และทำตามตัวเลือก -New → Package.
ต่อไปเราจะสร้าง UserService.java, User.java,UserDao.java ไฟล์ภายใต้แพ็คเกจ com.tutorialspoint
User.java
package com.tutorialspoint;
import java.io.Serializable;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(name = "user")
public class User implements Serializable {
private static final long serialVersionUID = 1L;
private int id;
private String name;
private String profession;
public User(){}
public User(int id, String name, String profession){
this.id = id;
this.name = name;
this.profession = profession;
}
public int getId() {
return id;
}
@XmlElement
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
@XmlElement
public void setName(String name) {
this.name = name;
}
public String getProfession() {
return profession;
}
@XmlElement
public void setProfession(String profession) {
this.profession = profession;
}
}
UserDao.java
package com.tutorialspoint;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.List;
public class UserDao {
public List<User> getAllUsers(){
List<User> userList = null;
try {
File file = new File("Users.dat");
if (!file.exists()) {
User user = new User(1, "Mahesh", "Teacher");
userList = new ArrayList<User>();
userList.add(user);
saveUserList(userList);
}
else{
FileInputStream fis = new FileInputStream(file);
ObjectInputStream ois = new ObjectInputStream(fis);
userList = (List<User>) ois.readObject();
ois.close();
}
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return userList;
}
private void saveUserList(List<User> userList){
try {
File file = new File("Users.dat");
FileOutputStream fos;
fos = new FileOutputStream(file);
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(userList);
oos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
UserService.java
package com.tutorialspoint;
import java.util.List;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
@Path("/UserService")
public class UserService {
UserDao userDao = new UserDao();
@GET
@Path("/users")
@Produces(MediaType.APPLICATION_XML)
public List<User> getUsers(){
return userDao.getAllUsers();
}
}
มีประเด็นสำคัญสองประการที่ควรสังเกตเกี่ยวกับโปรแกรมหลัก
UserService.java
ขั้นตอนแรกคือการระบุเส้นทางสำหรับบริการเว็บโดยใช้คำอธิบายประกอบ @Path ไปยัง UserService
ขั้นตอนที่สองคือการระบุเส้นทางสำหรับวิธีการบริการเว็บเฉพาะโดยใช้คำอธิบายประกอบ @Path ไปยังเมธอดของ UserService
การสร้างไฟล์คอนฟิกูเรชัน Web.xml
คุณต้องสร้างไฟล์คอนฟิกูเรชัน Web xml ซึ่งเป็นไฟล์ XML และใช้เพื่อระบุเจอร์เล็ตเฟรมเวิร์กสำหรับแอปพลิเคชันของเรา
web.xml
<?xml version = "1.0" encoding = "UTF-8"?>
<web-app xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
xmlns = "http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id = "WebApp_ID" version = "3.0">
<display-name>User Management</display-name>
<servlet>
<servlet-name>Jersey RESTful Application</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>com.tutorialspoint</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>Jersey RESTful Application</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
</web-app>
การปรับใช้โปรแกรม
เมื่อคุณสร้างไฟล์ซอร์สและไฟล์คอนฟิกูเรชันเสร็จแล้วคุณก็พร้อมสำหรับขั้นตอนนี้ซึ่งกำลังรวบรวมและรันโปรแกรมของคุณ ในการดำเนินการนี้โดยใช้ Eclipse ส่งออกแอปพลิเคชันของคุณเป็นไฟล์ war และปรับใช้สิ่งเดียวกันใน tomcat
ในการสร้างไฟล์ WAR โดยใช้ eclipse ให้ทำตามตัวเลือก File → export → Web → War Fileและสุดท้ายเลือกโครงการ UserManagement และโฟลเดอร์ปลายทาง ในการปรับใช้ไฟล์สงครามใน Tomcat ให้วาง UserManagement.war ในไฟล์Tomcat Installation Directory → webapps directory และเริ่ม Tomcat
เรียกใช้โปรแกรม
เรากำลังใช้Postmanซึ่งเป็นส่วนขยายของ Chrome เพื่อทดสอบบริการเว็บของเรา
ส่งคำขอไปยัง UserManagement เพื่อรับรายชื่อผู้ใช้ทั้งหมด ใส่ http: // localhost: 8080 / UserManagement / rest / UserService / users ใน POSTMAN ด้วยคำขอ GET และดูผลลัพธ์ต่อไปนี้
ขอแสดงความยินดีคุณได้สร้าง RESTful Application ตัวแรกของคุณสำเร็จแล้ว
ทรัพยากรคืออะไร?
สถาปัตยกรรม REST ถือว่าทุกเนื้อหาเป็นทรัพยากร ทรัพยากรเหล่านี้อาจเป็นไฟล์ข้อความเพจ Html รูปภาพวิดีโอหรือข้อมูลธุรกิจแบบไดนามิก REST Server เพียงแค่ให้การเข้าถึงทรัพยากรและการเข้าถึงไคลเอ็นต์ REST และแก้ไขทรัพยากร ที่นี่แต่ละทรัพยากรถูกระบุโดย URI / Global IDs REST ใช้การแสดงที่หลากหลายเพื่อแสดงทรัพยากรที่ Text, JSON, XML การนำเสนอทรัพยากรที่ได้รับความนิยมมากที่สุด ได้แก่ XML และ JSON
การเป็นตัวแทนของทรัพยากร
ทรัพยากรใน REST เป็น Object ที่คล้ายกันใน Object Oriented Programming หรือเปรียบเสมือนเอนทิตีในฐานข้อมูล เมื่อระบุทรัพยากรแล้วการเป็นตัวแทนจะถูกตัดสินใจโดยใช้รูปแบบมาตรฐานเพื่อให้เซิร์ฟเวอร์สามารถส่งทรัพยากรในรูปแบบดังกล่าวข้างต้นและไคลเอนต์สามารถเข้าใจรูปแบบเดียวกันได้
ตัวอย่างเช่นในRESTful Web Services - First Application Chapter ผู้ใช้คือทรัพยากรที่แสดงโดยใช้รูปแบบ XML ต่อไปนี้ -
<user>
<id>1</id>
<name>Mahesh</name>
<profession>Teacher</profession>
</user>
ทรัพยากรเดียวกันสามารถแสดงในรูปแบบ JSON ดังนี้ -
{
"id":1,
"name":"Mahesh",
"profession":"Teacher"
}
การเป็นตัวแทนทรัพยากรที่ดี
REST ไม่ได้กำหนดข้อ จำกัด ใด ๆ เกี่ยวกับรูปแบบของการแสดงทรัพยากร ไคลเอนต์สามารถขอการแสดง JSON ในขณะที่ไคลเอนต์อื่นอาจขอการแสดง XML ของทรัพยากรเดียวกันไปยังเซิร์ฟเวอร์และอื่น ๆ เป็นความรับผิดชอบของเซิร์ฟเวอร์ REST ในการส่งทรัพยากรในรูปแบบที่ไคลเอ็นต์เข้าใจ
ต่อไปนี้เป็นประเด็นสำคัญที่ต้องพิจารณาในขณะออกแบบรูปแบบการแสดงทรัพยากรใน RESTful Web Services
Understandability - ทั้งเซิร์ฟเวอร์และไคลเอนต์ควรสามารถเข้าใจและใช้รูปแบบการเป็นตัวแทนของทรัพยากรได้
Completeness- รูปแบบควรสามารถแสดงถึงทรัพยากรได้อย่างสมบูรณ์ ตัวอย่างเช่นทรัพยากรสามารถมีทรัพยากรอื่นได้ รูปแบบควรสามารถแสดงโครงสร้างของทรัพยากรที่เรียบง่ายและซับซ้อนได้
Linkablity - ทรัพยากรสามารถมีการเชื่อมโยงไปยังทรัพยากรอื่นรูปแบบควรจะสามารถจัดการกับสถานการณ์ดังกล่าวได้
อย่างไรก็ตามในปัจจุบันบริการเว็บส่วนใหญ่แสดงทรัพยากรโดยใช้รูปแบบ XML หรือ JSON มีไลบรารีและเครื่องมือมากมายสำหรับทำความเข้าใจแยกวิเคราะห์และแก้ไขข้อมูล XML และ JSON
RESTful Web Services ใช้ประโยชน์จากโปรโตคอล HTTP เป็นสื่อกลางในการสื่อสารระหว่างไคลเอนต์และเซิร์ฟเวอร์ ไคลเอนต์ส่งข้อความในรูปแบบของคำขอ HTTP และเซิร์ฟเวอร์ตอบสนองในรูปแบบของการตอบกลับ HTTP เทคนิคนี้เรียกว่าการส่งข้อความ ข้อความเหล่านี้ประกอบด้วยข้อมูลข้อความและข้อมูลเมตา ได้แก่ ข้อมูลเกี่ยวกับข้อความเอง ให้เราดูคำขอ HTTP และข้อความตอบกลับ HTTP สำหรับ HTTP 1.1
คำขอ HTTP
คำขอ HTTP มีห้าส่วนหลัก -
Verb - ระบุวิธีการ HTTP เช่น GET, POST, DELETE, PUT เป็นต้น
URI - Uniform Resource Identifier (URI) เพื่อระบุทรัพยากรบนเซิร์ฟเวอร์
HTTP Version- ระบุเวอร์ชัน HTTP ตัวอย่างเช่น HTTP v1.1
Request Header- มีข้อมูลเมตาสำหรับข้อความคำขอ HTTP เป็นคู่คีย์ - ค่า ตัวอย่างเช่นประเภทไคลเอนต์ (หรือเบราว์เซอร์) รูปแบบที่ไคลเอนต์รองรับรูปแบบของเนื้อหาข้อความการตั้งค่าแคช ฯลฯ
Request Body - เนื้อหาข้อความหรือการแสดงทรัพยากร
การตอบสนอง HTTP
การตอบสนอง HTTP มีสี่ส่วนหลัก ๆ -
Status/Response Code- ระบุสถานะเซิร์ฟเวอร์สำหรับทรัพยากรที่ร้องขอ ตัวอย่างเช่น 404 หมายถึงไม่พบทรัพยากรและ 200 หมายถึงการตอบสนองก็ใช้ได้
HTTP Version- ระบุเวอร์ชัน HTTP ตัวอย่างเช่น HTTP v1.1
Response Header- มีข้อมูลเมตาสำหรับข้อความตอบกลับ HTTP เป็นคู่ค่าคีย์ ตัวอย่างเช่นความยาวของเนื้อหาประเภทเนื้อหาวันที่ตอบกลับประเภทเซิร์ฟเวอร์เป็นต้น
Response Body - เนื้อหาข้อความตอบกลับหรือการแสดงทรัพยากร
ตัวอย่าง
ดังที่เราได้อธิบายไว้ในบทRESTful Web Services - First Applicationให้เราใส่ http: // localhost: 8080 / UserManagement / rest / UserService / users ใน POSTMAN พร้อมกับคำขอ GET หากคุณคลิกที่ปุ่มแสดงตัวอย่างซึ่งอยู่ใกล้กับปุ่มส่งของบุรุษไปรษณีย์จากนั้นคลิกที่ปุ่มส่งคุณอาจเห็นผลลัพธ์ต่อไปนี้
คุณจะเห็นที่นี่เบราว์เซอร์ส่งคำขอ GET และได้รับเนื้อหาตอบกลับเป็น XML
การกำหนดแอดเดรสหมายถึงการค้นหาทรัพยากรหรือทรัพยากรจำนวนมากที่อยู่บนเซิร์ฟเวอร์ คล้ายกับการระบุที่อยู่ทางไปรษณีย์ของบุคคล
ทรัพยากรแต่ละรายการในสถาปัตยกรรม REST ถูกระบุโดย URI (Uniform Resource Identifier) URI เป็นรูปแบบต่อไปนี้ -
<protocol>://<service-name>/<ResourceType>/<ResourceID>
วัตถุประสงค์ของ URI คือการค้นหาทรัพยากรบนเซิร์ฟเวอร์ที่โฮสต์บริการเว็บ แอตทริบิวต์ที่สำคัญอีกประการหนึ่งของคำขอคือ VERB ซึ่งระบุการดำเนินการที่จะดำเนินการกับทรัพยากร ตัวอย่างเช่นในRESTful Web Services - First Application Chapter URI คือhttp://localhost:8080/UserManagement/rest/UserService/users และ VERB คือ GET
การสร้าง URI มาตรฐาน
ต่อไปนี้เป็นประเด็นสำคัญที่ต้องพิจารณาในขณะออกแบบ URI -
Use Plural Noun- ใช้คำนามพหูพจน์เพื่อกำหนดทรัพยากร ตัวอย่างเช่นเราใช้ผู้ใช้เพื่อระบุผู้ใช้เป็นทรัพยากร
Avoid using spaces- ใช้ขีดล่าง (_) หรือยัติภังค์ (-) เมื่อใช้ชื่อทรัพยากรแบบยาว ตัวอย่างเช่นใช้ Authorized_users แทนผู้ใช้ที่ได้รับอนุญาต% 20users
Use lowercase letters - แม้ว่า URI จะไม่คำนึงถึงตัวพิมพ์เล็กและใหญ่ แต่ก็เป็นแนวทางปฏิบัติที่ดีที่จะให้ url เป็นอักษรตัวพิมพ์เล็กเท่านั้น
Maintain Backward Compatibility- เนื่องจาก Web Service เป็นบริการสาธารณะ URI ที่เคยเปิดเผยต่อสาธารณะจึงควรพร้อมใช้งานเสมอ ในกรณีที่ URI ได้รับการอัปเดตเปลี่ยนเส้นทาง URI ที่เก่ากว่าไปยัง URI ใหม่โดยใช้รหัสสถานะ HTTP 300
Use HTTP Verb- ใช้ HTTP Verb เสมอเช่น GET, PUT และ DELETE เพื่อดำเนินการกับทรัพยากร การใช้ชื่อการดำเนินการใน URI ไม่ดี
ตัวอย่าง
ต่อไปนี้เป็นตัวอย่างของ URI ที่ไม่ดีในการดึงข้อมูลผู้ใช้
http://localhost:8080/UserManagement/rest/UserService/getUser/1
ต่อไปนี้เป็นตัวอย่างของ URI ที่ดีในการดึงข้อมูลผู้ใช้
http://localhost:8080/UserManagement/rest/UserService/users/1
ดังที่เราได้กล่าวไปแล้วในบทก่อนหน้านี้ว่า RESTful Web Service ใช้คำกริยา HTTP จำนวนมากเพื่อกำหนดการดำเนินการกับทรัพยากรที่ระบุ ตารางต่อไปนี้ระบุตัวอย่างของคำกริยา HTTP ที่ใช้บ่อยที่สุด
ซีเนียร์ | วิธี HTTP, URI และการทำงาน |
---|---|
1 | GET http: // localhost: 8080 / UserManagement / rest / UserService / users รับรายชื่อผู้ใช้ (อ่านเท่านั้น) |
2 |
GET http: // localhost: 8080 / UserManagement / rest / UserService / users / 1 รับผู้ใช้ Id 1 (อ่านเท่านั้น) |
3 |
PUT http: // localhost: 8080 / UserManagement / rest / UserService / users / 2 แทรกผู้ใช้ด้วยรหัส 2 (Idempotent) |
4 |
POST http: // localhost: 8080 / UserManagement / rest / UserService / users / 2 อัปเดตผู้ใช้ด้วย Id 2 (ไม่มี) |
5 |
DELETE http: // localhost: 8080 / UserManagement / rest / UserService / users / 1 ลบผู้ใช้ที่มี Id 1 (Idempotent) |
6 |
OPTIONS http: // localhost: 8080 / UserManagement / rest / UserService / users แสดงรายการการดำเนินการที่สนับสนุนในบริการบนเว็บ (อ่านเท่านั้น) |
7 |
HEAD http: // localhost: 8080 / UserManagement / rest / UserService / users ส่งคืนส่วนหัว HTTP เท่านั้นไม่มีเนื้อหา (อ่านเท่านั้น) |
ประเด็นต่อไปนี้จะต้องพิจารณา
การดำเนินการ GET เป็นแบบอ่านอย่างเดียวและปลอดภัย
การดำเนินการ PUT และ DELETE เป็นสิ่งที่ไม่สำคัญซึ่งหมายความว่าผลลัพธ์จะเหมือนกันเสมอไม่ว่าการดำเนินการเหล่านี้จะถูกเรียกใช้กี่ครั้งก็ตาม
การดำเนินการ PUT และ POST นั้นใกล้เคียงกันโดยมีความแตกต่างที่แฝงอยู่ในผลลัพธ์เท่านั้นโดยที่การดำเนินการ PUT ไม่ได้มีจุดมุ่งหมายและการดำเนินการ POST อาจทำให้เกิดผลลัพธ์ที่แตกต่างกัน
ตัวอย่าง
ให้เราอัปเดตตัวอย่างที่สร้างขึ้นในRESTful Web Services - First Applicationเพื่อสร้าง Web service ซึ่งสามารถดำเนินการ CRUD (Create, Read, Update, Delete) เพื่อความง่ายเราได้ใช้ไฟล์ I / O เพื่อแทนที่การดำเนินการฐานข้อมูล
ให้เราอัปเดตไฟล์ User.java, UserDao.java และ UserService.java ไฟล์ภายใต้แพ็คเกจ com.tutorialspoint
User.java
package com.tutorialspoint;
import java.io.Serializable;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(name = "user")
public class User implements Serializable {
private static final long serialVersionUID = 1L;
private int id;
private String name;
private String profession;
public User(){}
public User(int id, String name, String profession){
this.id = id;
this.name = name;
this.profession = profession;
}
public int getId() {
return id;
}
@XmlElement
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
@XmlElement
public void setName(String name) {
this.name = name;
}
public String getProfession() {
return profession;
}
@XmlElement
public void setProfession(String profession) {
this.profession = profession;
}
@Override
public boolean equals(Object object){
if(object == null){
return false;
}else if(!(object instanceof User)){
return false;
}else {
User user = (User)object;
if(id == user.getId()
&& name.equals(user.getName())
&& profession.equals(user.getProfession())){
return true;
}
}
return false;
}
}
UserDao.java
package com.tutorialspoint;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.List;
public class UserDao {
public List<User> getAllUsers(){
List<User> userList = null;
try {
File file = new File("Users.dat");
if (!file.exists()) {
User user = new User(1, "Mahesh", "Teacher");
userList = new ArrayList<User>();
userList.add(user);
saveUserList(userList);
}
else{
FileInputStream fis = new FileInputStream(file);
ObjectInputStream ois = new ObjectInputStream(fis);
userList = (List<User>) ois.readObject();
ois.close();
}
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return userList;
}
public User getUser(int id){
List<User> users = getAllUsers();
for(User user: users){
if(user.getId() == id){
return user;
}
}
return null;
}
public int addUser(User pUser){
List<User> userList = getAllUsers();
boolean userExists = false;
for(User user: userList){
if(user.getId() == pUser.getId()){
userExists = true;
break;
}
}
if(!userExists){
userList.add(pUser);
saveUserList(userList);
return 1;
}
return 0;
}
public int updateUser(User pUser){
List<User> userList = getAllUsers();
for(User user: userList){
if(user.getId() == pUser.getId()){
int index = userList.indexOf(user);
userList.set(index, pUser);
saveUserList(userList);
return 1;
}
}
return 0;
}
public int deleteUser(int id){
List<User> userList = getAllUsers();
for(User user: userList){
if(user.getId() == id){
int index = userList.indexOf(user);
userList.remove(index);
saveUserList(userList);
return 1;
}
}
return 0;
}
private void saveUserList(List<User> userList){
try {
File file = new File("Users.dat");
FileOutputStream fos;
fos = new FileOutputStream(file);
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(userList);
oos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
UserService.java
package com.tutorialspoint;
import java.io.IOException;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.OPTIONS;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
@Path("/UserService")
public class UserService {
UserDao userDao = new UserDao();
private static final String SUCCESS_RESULT = "<result>success</result>";
private static final String FAILURE_RESULT = "<result>failure</result>";
@GET
@Path("/users")
@Produces(MediaType.APPLICATION_XML)
public List<User> getUsers(){
return userDao.getAllUsers();
}
@GET
@Path("/users/{userid}")
@Produces(MediaType.APPLICATION_XML)
public User getUser(@PathParam("userid") int userid){
return userDao.getUser(userid);
}
@PUT
@Path("/users")
@Produces(MediaType.APPLICATION_XML)
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public String createUser(@FormParam("id") int id,
@FormParam("name") String name,
@FormParam("profession") String profession,
@Context HttpServletResponse servletResponse) throws IOException{
User user = new User(id, name, profession);
int result = userDao.addUser(user);
if(result == 1){
return SUCCESS_RESULT;
}
return FAILURE_RESULT;
}
@POST
@Path("/users")
@Produces(MediaType.APPLICATION_XML)
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public String updateUser(@FormParam("id") int id,
@FormParam("name") String name,
@FormParam("profession") String profession,
@Context HttpServletResponse servletResponse) throws IOException{
User user = new User(id, name, profession);
int result = userDao.updateUser(user);
if(result == 1){
return SUCCESS_RESULT;
}
return FAILURE_RESULT;
}
@DELETE
@Path("/users/{userid}")
@Produces(MediaType.APPLICATION_XML)
public String deleteUser(@PathParam("userid") int userid){
int result = userDao.deleteUser(userid);
if(result == 1){
return SUCCESS_RESULT;
}
return FAILURE_RESULT;
}
@OPTIONS
@Path("/users")
@Produces(MediaType.APPLICATION_XML)
public String getSupportedOperations(){
return "<operations>GET, PUT, POST, DELETE</operations>";
}
}
ตอนนี้ใช้ Eclipse ส่งออกแอปพลิเคชันของคุณเป็นไฟล์ WAR Fileและปรับใช้สิ่งเดียวกันใน Tomcat ในการสร้างไฟล์ WAR โดยใช้ eclipse ให้ทำตามเส้นทางนี้ -File → export → Web → War Fileและสุดท้ายเลือกโครงการ UserManagement และโฟลเดอร์ปลายทาง ในการปรับใช้ไฟล์ WAR ใน Tomcat ให้วาง UserManagement.war ในไฟล์Tomcat Installation Directory → webapps ไดเรกทอรีและเริ่ม Tomcat
การทดสอบบริการเว็บ
Jersey มี API เพื่อสร้าง Web Service Client เพื่อทดสอบบริการบนเว็บ เราได้สร้างคลาสทดสอบตัวอย่างWebServiceTester.java ภายใต้แพ็คเกจ com.tutorialspoint ในโปรเจ็กต์เดียวกัน
WebServiceTester.java
package com.tutorialspoint;
import java.util.List;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.core.Form;
import javax.ws.rs.core.GenericType;
import javax.ws.rs.core.MediaType;
public class WebServiceTester {
private Client client;
private String REST_SERVICE_URL = "
http://localhost:8080/UserManagement/rest/UserService/users";
private static final String SUCCESS_RESULT = "<result>success</result>";
private static final String PASS = "pass";
private static final String FAIL = "fail";
private void init(){
this.client = ClientBuilder.newClient();
}
public static void main(String[] args){
WebServiceTester tester = new WebServiceTester();
//initialize the tester
tester.init();
//test get all users Web Service Method
tester.testGetAllUsers();
//test get user Web Service Method
tester.testGetUser();
//test update user Web Service Method
tester.testUpdateUser();
//test add user Web Service Method
tester.testAddUser();
//test delete user Web Service Method
tester.testDeleteUser();
}
//Test: Get list of all users
//Test: Check if list is not empty
private void testGetAllUsers(){
GenericType<List<User>> list = new GenericType<List<User>>() {};
List<User> users = client
.target(REST_SERVICE_URL)
.request(MediaType.APPLICATION_XML)
.get(list);
String result = PASS;
if(users.isEmpty()){
result = FAIL;
}
System.out.println("Test case name: testGetAllUsers, Result: " + result );
}
//Test: Get User of id 1
//Test: Check if user is same as sample user
private void testGetUser(){
User sampleUser = new User();
sampleUser.setId(1);
User user = client
.target(REST_SERVICE_URL)
.path("/{userid}")
.resolveTemplate("userid", 1)
.request(MediaType.APPLICATION_XML)
.get(User.class);
String result = FAIL;
if(sampleUser != null && sampleUser.getId() == user.getId()){
result = PASS;
}
System.out.println("Test case name: testGetUser, Result: " + result );
}
//Test: Update User of id 1
//Test: Check if result is success XML.
private void testUpdateUser(){
Form form = new Form();
form.param("id", "1");
form.param("name", "suresh");
form.param("profession", "clerk");
String callResult = client
.target(REST_SERVICE_URL)
.request(MediaType.APPLICATION_XML)
.post(Entity.entity(form,
MediaType.APPLICATION_FORM_URLENCODED_TYPE),
String.class);
String result = PASS;
if(!SUCCESS_RESULT.equals(callResult)){
result = FAIL;
}
System.out.println("Test case name: testUpdateUser, Result: " + result);
}
//Test: Add User of id 2
//Test: Check if result is success XML.
private void testAddUser(){
Form form = new Form();
form.param("id", "2");
form.param("name", "naresh");
form.param("profession", "clerk");
String callResult = client
.target(REST_SERVICE_URL)
.request(MediaType.APPLICATION_XML)
.put(Entity.entity(form,
MediaType.APPLICATION_FORM_URLENCODED_TYPE),
String.class);
String result = PASS;
if(!SUCCESS_RESULT.equals(callResult)){
result = FAIL;
}
System.out.println("Test case name: testAddUser, Result: " + result );
}
//Test: Delete User of id 2
//Test: Check if result is success XML.
private void testDeleteUser(){
String callResult = client
.target(REST_SERVICE_URL)
.path("/{userid}")
.resolveTemplate("userid", 2)
.request(MediaType.APPLICATION_XML)
.delete(String.class);
String result = PASS;
if(!SUCCESS_RESULT.equals(callResult)){
result = FAIL;
}
System.out.println("Test case name: testDeleteUser, Result: " + result);
}
}
ตอนนี้เรียกใช้เครื่องทดสอบโดยใช้ Eclipse คลิกขวาที่ไฟล์และทำตามตัวเลือกRun as → Java Application. คุณจะเห็นผลลัพธ์ต่อไปนี้ในคอนโซล Eclipse -
Test case name: testGetAllUsers, Result: pass
Test case name: testGetUser, Result: pass
Test case name: testUpdateUser, Result: pass
Test case name: testAddUser, Result: pass
Test case name: testDeleteUser, Result: pass
ตามสถาปัตยกรรม REST RESTful Web Service ไม่ควรเก็บสถานะไคลเอ็นต์บนเซิร์ฟเวอร์ ข้อ จำกัด นี้เรียกว่าการไร้สัญชาติ เป็นความรับผิดชอบของไคลเอ็นต์ในการส่งบริบทไปยังเซิร์ฟเวอร์จากนั้นเซิร์ฟเวอร์สามารถจัดเก็บบริบทนี้เพื่อดำเนินการตามคำขอเพิ่มเติมของไคลเอ็นต์ ตัวอย่างเช่นเซสชันที่ดูแลโดยเซิร์ฟเวอร์จะถูกระบุโดยตัวระบุเซสชันที่ส่งผ่านโดยไคลเอนต์
RESTful Web Services ควรปฏิบัติตามข้อ จำกัด นี้ เราได้เห็นสิ่งนี้ในบทRESTful Web Services - Methodsว่าวิธีการบริการเว็บไม่ได้จัดเก็บข้อมูลใด ๆ จากไคลเอนต์ที่เรียกใช้
Consider the following URL −
https: // localhost: 8080 / UserManagement / rest / UserService / users / 1
หากคุณกด url ด้านบนโดยใช้เบราว์เซอร์ของคุณหรือใช้ไคลเอนต์ที่ใช้ java หรือใช้ Postman ผลลัพธ์จะเป็น User XML ที่มี Id เป็น 1 เสมอเนื่องจากเซิร์ฟเวอร์ไม่เก็บข้อมูลใด ๆ เกี่ยวกับไคลเอนต์
<user>
<id>1</id>
<name>mahesh</name>
<profession>1</profession>
</user>
ข้อดีของการไร้สัญชาติ
ต่อไปนี้เป็นประโยชน์ของการไร้สัญชาติใน RESTful Web Services -
บริการบนเว็บสามารถดำเนินการตามคำขอแต่ละวิธีโดยอิสระ
บริการบนเว็บไม่จำเป็นต้องรักษาการโต้ตอบก่อนหน้านี้ของลูกค้า ช่วยลดความยุ่งยากในการออกแบบแอปพลิเคชัน
เนื่องจาก HTTP เป็นโปรโตคอลการไร้สัญชาติตัวเอง RESTful Web Services จึงทำงานร่วมกับโปรโตคอล HTTP ได้อย่างราบรื่น
ข้อเสียของการไร้สัญชาติ
ต่อไปนี้เป็นข้อเสียของการไร้สัญชาติใน RESTful Web Services -
บริการบนเว็บจำเป็นต้องได้รับข้อมูลเพิ่มเติมในแต่ละคำขอจากนั้นจึงตีความเพื่อให้ได้สถานะของลูกค้าในกรณีที่การโต้ตอบกับลูกค้าต้องได้รับการดูแล
การแคชหมายถึงการจัดเก็บการตอบสนองของเซิร์ฟเวอร์ในไคลเอนต์เองดังนั้นไคลเอนต์จึงไม่จำเป็นต้องร้องขอเซิร์ฟเวอร์สำหรับทรัพยากรเดียวกันซ้ำแล้วซ้ำเล่า การตอบกลับของเซิร์ฟเวอร์ควรมีข้อมูลเกี่ยวกับวิธีการแคชเพื่อให้ไคลเอ็นต์แคชการตอบสนองในช่วงเวลาหนึ่งหรือไม่เคยแคชการตอบกลับของเซิร์ฟเวอร์
ต่อไปนี้เป็นส่วนหัวที่สามารถตอบสนองของเซิร์ฟเวอร์เพื่อกำหนดค่าการแคชของไคลเอ็นต์ -
ซีเนียร์ | ส่วนหัวและคำอธิบาย |
---|---|
1 |
Date วันที่และเวลาของทรัพยากรเมื่อสร้างขึ้น |
2 |
Last Modified วันที่และเวลาของทรัพยากรเมื่อแก้ไขล่าสุด |
3 |
Cache-Control ส่วนหัวหลักเพื่อควบคุมการแคช |
4 |
Expires วันหมดอายุและเวลาของการแคช |
5 |
Age ระยะเวลาเป็นวินาทีนับจากเวลาที่ดึงทรัพยากรจากเซิร์ฟเวอร์ |
ส่วนหัวควบคุมแคช
ต่อไปนี้เป็นรายละเอียดของส่วนหัว Cache-Control -
ซีเนียร์ | คำสั่งและคำอธิบาย |
---|---|
1 |
Public ระบุว่ารีซอร์สสามารถแคชได้โดยคอมโพเนนต์ใด ๆ |
2 |
Private ระบุว่ารีซอร์สสามารถแคชได้โดยไคลเอนต์และเซิร์ฟเวอร์เท่านั้นไม่มีตัวกลางใดที่สามารถแคชทรัพยากรได้ |
3 |
no-cache/no-store ระบุว่ารีซอร์สไม่สามารถแคชได้ |
4 |
max-age ระบุว่าการแคชสามารถใช้ได้ถึงอายุสูงสุดเป็นวินาที หลังจากนี้ลูกค้าจะต้องทำการร้องขออีกครั้ง |
5 |
must-revalidate บ่งชี้ไปยังเซิร์ฟเวอร์เพื่อตรวจสอบทรัพยากรอีกครั้งหากอายุสูงสุดผ่านไปแล้ว |
ปฏิบัติที่ดีที่สุด
เก็บเนื้อหาแบบคงที่ไว้เสมอเช่นรูปภาพ CSS JavaScript ที่แคชได้โดยมีวันหมดอายุ 2 ถึง 3 วัน
อย่าให้วันหมดอายุสูงเกินไป
เนื้อหาแบบไดนามิกควรถูกแคชเพียงไม่กี่ชั่วโมงเท่านั้น
เนื่องจาก RESTful Web Services ทำงานร่วมกับ HTTP URL Paths จึงเป็นสิ่งสำคัญมากที่จะต้องปกป้อง RESTful Web Service ในลักษณะเดียวกับที่เว็บไซต์มีความปลอดภัย
ต่อไปนี้เป็นแนวทางปฏิบัติที่ดีที่สุดที่จะต้องปฏิบัติในขณะออกแบบบริการเว็บ RESTful -
Validation- ตรวจสอบอินพุตทั้งหมดบนเซิร์ฟเวอร์ ปกป้องเซิร์ฟเวอร์ของคุณจากการโจมตีด้วย SQL หรือ NoSQL
Session Based Authentication - ใช้การพิสูจน์ตัวตนตามเซสชันเพื่อรับรองความถูกต้องของผู้ใช้เมื่อใดก็ตามที่มีการร้องขอวิธีการบริการเว็บ
No Sensitive Data in the URL - ห้ามใช้ชื่อผู้ใช้รหัสผ่านหรือโทเค็นเซสชันใน URL ค่าเหล่านี้ควรส่งต่อไปยัง Web Service ผ่านวิธีการ POST
Restriction on Method Execution- อนุญาตให้ใช้วิธีการที่ จำกัด เช่นเมธอด GET, POST และ DELETE เมธอด GET ไม่ควรลบข้อมูลได้
Validate Malformed XML/JSON - ตรวจสอบอินพุตที่มีรูปทรงที่ดีที่ส่งผ่านไปยังวิธีการบริการบนเว็บ
Throw generic Error Messages - วิธีการบริการเว็บควรใช้ข้อความแสดงข้อผิดพลาด HTTP เช่น 403 เพื่อแสดงการเข้าถึงที่ถูกห้ามเป็นต้น
รหัส HTTP
ซีเนียร์ | รหัส HTTP และคำอธิบาย |
---|---|
1 |
200 OK - แสดงให้เห็นถึงความสำเร็จ |
2 |
201 CREATED- เมื่อสร้างทรัพยากรสำเร็จโดยใช้คำขอ POST หรือ PUT ส่งกลับลิงก์ไปยังทรัพยากรที่สร้างขึ้นใหม่โดยใช้ส่วนหัวตำแหน่ง |
3 |
204 NO CONTENT- เมื่อร่างกายตอบสนองว่างเปล่า ตัวอย่างเช่นคำขอ DELETE |
4 |
304 NOT MODIFIED- ใช้เพื่อลดการใช้แบนด์วิดท์เครือข่ายในกรณีที่มีการร้องขอ GET ตามเงื่อนไข เนื้อหาตอบสนองควรว่างเปล่า ส่วนหัวควรมีวันที่สถานที่ ฯลฯ |
5 |
400 BAD REQUEST- ระบุว่ามีการป้อนข้อมูลที่ไม่ถูกต้อง ตัวอย่างเช่นข้อผิดพลาดในการตรวจสอบข้อมูลขาดหายไป |
6 |
401 UNAUTHORIZED - ระบุว่าผู้ใช้ใช้โทเค็นการตรวจสอบสิทธิ์ที่ไม่ถูกต้องหรือไม่ถูกต้อง |
7 |
403 FORBIDDEN- ระบุว่าผู้ใช้ไม่สามารถเข้าถึงวิธีการที่ใช้ ตัวอย่างเช่นลบการเข้าถึงโดยไม่มีสิทธิ์ของผู้ดูแลระบบ |
8 |
404 NOT FOUND - ระบุว่าวิธีนี้ไม่สามารถใช้ได้ |
9 |
409 CONFLICT- ระบุสถานการณ์ความขัดแย้งในขณะที่ใช้งานเมธอด ตัวอย่างเช่นการเพิ่มรายการที่ซ้ำกัน |
10 |
500 INTERNAL SERVER ERROR - ระบุว่าเซิร์ฟเวอร์มีข้อยกเว้นบางอย่างขณะเรียกใช้เมธอด |
JAX-RSย่อมาจาก JAVA API สำหรับ RESTful Web Services JAX-RS เป็น API ภาษาการเขียนโปรแกรมที่ใช้ JAVA และข้อกำหนดเพื่อให้การสนับสนุนสำหรับ RESTful Web Services ที่สร้างขึ้น เวอร์ชัน 2.0 เปิดตัวเมื่อวันที่ 24 พฤษภาคม 2556 JAX-RS ใช้คำอธิบายประกอบที่มีให้จาก Java SE 5 เพื่อลดความซับซ้อนในการพัฒนาการสร้างและการปรับใช้บริการเว็บบน JAVA นอกจากนี้ยังรองรับการสร้างไคลเอนต์สำหรับ RESTful Web Services
ข้อมูลจำเพาะ
ต่อไปนี้เป็นคำอธิบายประกอบที่ใช้บ่อยที่สุดในการแมปทรัพยากรเป็นทรัพยากรบริการบนเว็บ
ซีเนียร์ | คำอธิบายประกอบและคำอธิบาย |
---|---|
1 |
@Path เส้นทางสัมพัทธ์ของคลาสทรัพยากร / วิธีการ |
2 |
@GET HTTP Get request ใช้ในการดึงทรัพยากร |
3 |
@PUT คำขอ HTTP PUT ใช้เพื่ออัปเดตทรัพยากร |
4 |
@POST คำขอ HTTP POST ใช้เพื่อสร้างทรัพยากรใหม่ |
5 |
@DELETE คำขอ HTTP DELETE ใช้เพื่อลบทรัพยากร |
6 |
@HEAD คำขอ HTTP HEAD ใช้เพื่อรับสถานะความพร้อมใช้งานของวิธีการ |
7 |
@Produces ระบุการตอบกลับ HTTP ที่สร้างโดยบริการเว็บ ตัวอย่างเช่น APPLICATION / XML, TEXT / HTML, APPLICATION / JSON เป็นต้น |
8 |
@Consumes ระบุประเภทคำขอ HTTP ตัวอย่างเช่น application / x-www-formurlencoded เพื่อยอมรับข้อมูลฟอร์มในเนื้อหา HTTP ระหว่างคำขอ POST |
9 |
@PathParam ผูกพารามิเตอร์ที่ส่งผ่านไปยังเมธอดกับค่าในพา ธ |
10 |
@QueryParam ผูกพารามิเตอร์ที่ส่งผ่านไปยังเมธอดกับพารามิเตอร์เคียวรีในพา ธ |
11 |
@MatrixParam ผูกพารามิเตอร์ที่ส่งผ่านไปยังเมธอดกับพารามิเตอร์เมทริกซ์ HTTP ในพา ธ |
12 |
@HeaderParam ผูกพารามิเตอร์ที่ส่งผ่านไปยังเมธอดกับส่วนหัว HTTP |
13 |
@CookieParam ผูกพารามิเตอร์ที่ส่งผ่านไปยังเมธอดกับคุกกี้ |
14 |
@FormParam ผูกพารามิเตอร์ที่ส่งผ่านไปยังเมธอดกับค่าฟอร์ม |
15 |
@DefaultValue กำหนดค่าเริ่มต้นให้กับพารามิเตอร์ที่ส่งผ่านไปยังเมธอด |
16 |
@Context บริบทของทรัพยากร ตัวอย่างเช่น HTTPRequest เป็นบริบท |
Note- เราได้ใช้ Jersey ซึ่งเป็นการนำไปใช้อ้างอิงของ JAX-RS 2.0 โดย Oracle ในRESTful Web Services - First ApplicationและRESTful Web Services -บทวิธีการ