RESTful Web Hizmetleri - Hızlı Kılavuz
REST mimarisi nedir?
REST, Temsili Durum Transferi anlamına gelir. REST, web standartları tabanlı bir mimaridir ve HTTP Protokolünü kullanır. Her bileşenin bir kaynak olduğu ve bir kaynağa HTTP standart yöntemlerini kullanan ortak bir arayüzle erişildiği bir kaynak etrafında döner. REST, ilk olarak 2000 yılında Roy Fielding tarafından tanıtıldı.
REST mimarisinde, bir REST Sunucusu basitçe kaynaklara erişim sağlar ve REST istemcisi kaynaklara erişir ve bunları değiştirir. Burada her bir kaynak, URI'ler / global ID'ler ile tanımlanır. REST, metin, JSON, XML gibi bir kaynağı temsil etmek için çeşitli temsiller kullanır. JSON en popüler olanıdır.
HTTP yöntemleri
Aşağıdaki dört HTTP yöntemi, REST tabanlı mimaride yaygın olarak kullanılmaktadır.
GET - Bir kaynağa salt okunur erişim sağlar.
POST - Yeni bir kaynak oluşturmak için kullanılır.
DELETE - Bir kaynağı kaldırmak için kullanılır.
PUT - Mevcut bir kaynağı güncellemek veya yeni bir kaynak oluşturmak için kullanılır.
RESTFul web hizmetlerine giriş
Web hizmeti, uygulamalar veya sistemler arasında veri alışverişi için kullanılan açık protokoller ve standartların bir koleksiyonudur. Çeşitli programlama dillerinde yazılan ve çeşitli platformlarda çalışan yazılım uygulamaları, tek bir bilgisayarda süreçler arası iletişime benzer bir şekilde İnternet gibi bilgisayar ağları üzerinden veri alışverişi yapmak için web hizmetlerini kullanabilir. Bu birlikte çalışabilirlik (örneğin, Java ve Python veya Windows ve Linux uygulamaları arasında) açık standartların kullanımından kaynaklanmaktadır.
REST Mimarisine dayalı web servisleri, RESTful web servisleri olarak bilinir. Bu web hizmetleri, REST mimarisi konseptini uygulamak için HTTP yöntemlerini kullanır. RESTful bir web hizmeti genellikle bir URI, Tekdüzen Kaynak Tanımlayıcı bir hizmet tanımlar, JSON ve HTTP Yöntemleri kümesi gibi kaynak gösterimi sağlar.
RESTFul Webservice Oluşturuluyor
Sonraki bölümlerde, aşağıdaki işlevlere sahip kullanıcı yönetimi diyen bir web hizmeti oluşturacağız -
Sr.No. | URI | HTTP Yöntemi | POST gövdesi | Sonuç |
---|---|---|---|---|
1 | / UserService / users | ALMAK | boş | Tüm kullanıcıların listesini göster. |
2 | / UserService / addUser | İLETİ | JSON Dizesi | Yeni kullanıcının ayrıntılarını ekleyin. |
3 | / UserService / getUser /: id | ALMAK | boş | Bir kullanıcının ayrıntılarını gösterin. |
Bu eğitim, çalışmanıza başlamak için bir geliştirme ortamını nasıl hazırlayacağınız konusunda size rehberlik edecektir. Jersey FrameworkRESTful Web Hizmetleri oluşturmak için. Jersey çerçevesi uygularJAX-RS 2.0RESTful Web Hizmetleri oluşturmak için standart bir özellik olan API. Bu eğitici ayrıca size nasıl kurulacağını öğretecekJDK, Tomcat ve Eclipse Jersey Framework kurulmadan önce makinenizde.
Java Geliştirme Kiti'ni (JDK) kurun
En son SDK sürümünü Oracle'ın Java sitesinden indirebilirsiniz - Java SE İndirmeleri . İndirilen dosyalarda JDK kurulumu talimatlarını bulacaksınız. Kurulumu kurmak ve yapılandırmak için verilen talimatları izleyin. Sonunda ayarlayınPATH ve JAVA_HOME içeren dizine başvurmak için ortam değişkenleri Java ve Javac, tipik olarak sırasıyla java_install_dir / bin ve java_install_dir.
Windows çalıştırıyorsanız ve JDK'yı C: \ jdk1.7.0_75'e yüklüyorsanız, aşağıdaki satırı C: \ autoexec.bat dosyanıza koymanız gerekir.
set PATH = C:\jdk1.7.0_75\bin;%PATH%
set JAVA_HOME = C:\jdk1.7.0_75
Alternatif olarak, Windows NT / 2000 / XP'de Bilgisayarım'a sağ tıklayabilir → Özellikler → ardından Gelişmiş → ardından Ortam Değişkenleri'ni seçebilirsiniz. Ardından, PATH değerini güncellersiniz ve OK düğmesine basarsınız.
Unix'te (Solaris, Linux, vb.), SDK /usr/local/jdk1.7.0_75'e kurulursa ve C Kabuğu kullanıyorsanız, aşağıdakileri .cshrc dosyanıza koyarsınız.
setenv PATH /usr/local/jdk1.7.0_75/bin:$PATH
setenv JAVA_HOME /usr/local/jdk1.7.0_75
Alternatif olarak, Borland JBuilder, Eclipse, IntelliJ IDEA veya Sun ONE Studio gibi bir Entegre Geliştirme Ortamı (IDE) kullanıyorsanız, IDE'nin Java'yı nereye yüklediğinizi bildiğini doğrulamak için basit bir program derleyin ve çalıştırın, aksi takdirde verilen belgeye göre uygun kurulumu yapın IDE'nin.
Eclipse IDE'yi kurun
Bu eğitimdeki tüm örnekler Eclipse IDE kullanılarak yazılmıştır. Bu yüzden, makinenize Eclipse'in en son sürümünü yüklemenizi öneririm.
Eclipse IDE'yi kurmak için en son Eclipse ikili dosyalarını indirin https://www.eclipse.org/downloads/. Kurulumu indirdikten sonra, ikili dağıtımı uygun bir konuma açın. Örneğin, Windows'ta C: \ eclipse'de veya Linux / Unix'te / usr / local / eclipse'de ve son olarak PATH değişkenini uygun şekilde ayarlayın.
Eclipse, bir Windows makinesinde aşağıdaki komutları çalıştırarak başlatılabilir veya eclipse.exe'ye çift tıklayabilirsiniz.
%C:\eclipse\eclipse.exe
Eclipse, Unix (Solaris, Linux, vb.) Makinesinde aşağıdaki komutlar çalıştırılarak başlatılabilir -
$/usr/local/eclipse/eclipse
Başarılı bir başlangıçtan sonra, her şey yolundaysa, ekranınız aşağıdaki sonucu göstermelidir -
Jersey Framework Kitaplıklarını Kur
Şimdi, her şey yolundaysa, Jersey çerçevesini kurmaya devam edebilirsiniz. Aşağıdakiler, çerçeveyi makinenize indirip kurmak için birkaç basit adımdır.
Jersey'i Windows'a mı yoksa Unix'e mi yüklemek istediğinizi seçin ve ardından pencereler için .zip dosyasını ve ardından Unix için .tz dosyasını indirmek için bir sonraki adıma geçin.
Jersey framework ikili dosyalarının en son sürümünü aşağıdaki bağlantıdan indirin - https://jersey.java.net/download.html.
Bu öğreticiyi yazarken, indirdim jaxrs-ri-2.17.zip Windows makinemde ve indirilen dosyayı açtığınızda, aşağıdaki ekran görüntüsünde gösterildiği gibi size E: \ jaxrs-ri-2.17 \ jaxrs-ri içindeki dizin yapısını verecektir.
Tüm Jersey kitaplıklarını dizinlerde bulacaksınız C:\jaxrs-ri-2.17\jaxrs-ri\lib ve içindeki bağımlılıklar C:\jaxrs-ri-2.17\jaxrs-ri\ext. Bu dizinde CLASSPATH değişkeninizi doğru bir şekilde ayarladığınızdan emin olun, aksi takdirde uygulamanızı çalıştırırken sorunlarla karşılaşacaksınız. Eclipse kullanıyorsanız, CLASSPATH'ı ayarlamanız gerekmez çünkü tüm ayarlar Eclipse aracılığıyla yapılacaktır.
Apache Tomcat'i Kur
Tomcat'in son sürümünü şu adresten indirebilirsiniz: https://tomcat.apache.org/. Kurulumu indirdikten sonra, ikili dağıtımı uygun bir konuma açın. Örneğin, Windows'ta C: \ apache-tomcat-7.0.59'da veya Linux / Unix'te /usr/local/apache-tomcat-7.0.59'da ve kurulum konumlarını işaret eden CATALINA_HOME ortam değişkenini ayarlayın.
Tomcat, bir Windows makinesinde aşağıdaki komutları çalıştırarak başlatılabilir veya startup.bat dosyasına çift tıklayabilirsiniz.
%CATALINA_HOME%\bin\startup.bat
veya
C:\apache-tomcat-7.0.59\bin\startup.bat
Tomcat, bir Unix (Solaris, Linux, vb.) Makinesinde aşağıdaki komutları çalıştırarak başlatılabilir -
$CATALINA_HOME/bin/startup.sh
veya
/usr/local/apache-tomcat-7.0.59/bin/startup.sh
Başarılı bir başlangıçtan sonra, Tomcat'in içerdiği varsayılan web uygulamaları şu adrese ziyaret edilerek kullanılabilir olacaktır: http://localhost:8080/. Her şey yolundaysa, aşağıdaki sonucu göstermelidir -
Tomcat'in yapılandırılması ve çalıştırılması hakkında daha fazla bilgi, bu sayfada bulunan belgelerde bulunabilir. Bu bilgi Tomcat web sitesinde de bulunabilir -https://tomcat.apache.org.
Tomcat, bir Windows makinesinde aşağıdaki komutlar çalıştırılarak durdurulabilir -
%CATALINA_HOME%\bin\shutdown
veya
C:\apache-tomcat-7.0.59\bin\shutdown
Tomcat, Unix (Solaris, Linux, vb.) Makinesinde aşağıdaki komutlar çalıştırılarak durdurulabilir -
$CATALINA_HOME/bin/shutdown.sh
veya
/usr/local/apache-tomcat-7.0.59/bin/shutdown.sh
Bu son adımı tamamladığınızda, bir sonraki bölümde göreceğiniz ilk Jersey örneğinize geçmeye hazırsınız.
Jersey Framework ile gerçek RESTful web hizmetlerini yazmaya başlayalım. Jersey Çerçevesini kullanarak ilk örneğinizi yazmaya başlamadan önce, Jersey ortamınızı RESTful Web Hizmetleri - Ortam Kurulumu bölümünde açıklandığı gibi doğru şekilde kurduğunuzdan emin olmalısınız . Burada, Eclipse IDE hakkında biraz çalışma bilginiz olduğunu da varsayıyorum.
Öyleyse, kullanıcıların listesini görüntülemek için bir web hizmeti yöntemini ortaya çıkaracak basit bir Jersey Uygulaması yazmaya devam edelim.
Java Projesi Oluşturmak
İlk adım Eclipse IDE'yi kullanarak Dinamik Web Projesi oluşturmaktır. Seçeneği takip edinFile → New → Project ve son olarak seçin Dynamic Web Projectsihirbaz listesinden sihirbaz. Şimdi projenizi şu şekilde adlandırın:UserManagement aşağıdaki ekran görüntüsünde gösterildiği gibi sihirbaz penceresini kullanarak -
Projeniz başarıyla oluşturulduktan sonra, aşağıdaki içeriğe sahip olacaksınız. Project Explorer -
Gerekli Kitaplıkları Ekleme
İkinci adım olarak projemize Jersey Framework ve bağımlılıklarını (kitaplıkları) ekleyelim. Tüm kavanozları, projenin WEB-INF / lib dizinindeki indirme Jersey zip klasörünün aşağıdaki dizinlerinden kopyalayın.
- \jaxrs-ri-2.17\jaxrs-ri\api
- \jaxrs-ri-2.17\jaxrs-ri\ext
- \jaxrs-ri-2.17\jaxrs-ri\lib
Şimdi, proje adınıza sağ tıklayın UserManagement ve ardından içerik menüsünde bulunan seçeneği takip edin - Build Path → Configure Build Path Java Build Path penceresini görüntülemek için.
Şimdi kullan Add JARs altında bulunan düğme Libraries WEBINF / lib dizininde bulunan JAR'ları eklemek için sekme.
Kaynak Dosyaları Oluşturma
Şimdi asıl kaynak dosyalarını şu altında oluşturalım: UserManagementproje. Önce adında bir paket oluşturmalıyızcom.tutorialspoint. Bunu yapmak için, paket gezgini bölümünde src'ye sağ tıklayın ve seçeneği izleyin -New → Package.
Sonra yaratacağız UserService.java, User.java,UserDao.java com.tutorialspoint paketi altındaki dosyalar.
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();
}
}
Ana programla ilgili dikkat edilmesi gereken iki önemli nokta vardır:
UserService.java
İlk adım, UserService'e @Path ek açıklamasını kullanarak web hizmeti için bir yol belirlemektir.
İkinci adım, UserService yöntemine @Path ek açıklamasını kullanarak belirli web hizmeti yöntemi için bir yol belirlemektir.
Web.xml yapılandırma Dosyasını oluşturma
Bir XML dosyası olan ve uygulamamız için Jersey çerçeve sunucu uygulamasını belirtmek için kullanılan bir Web xml Yapılandırma dosyası oluşturmanız gerekir.
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>
Programı Dağıtma
Kaynak ve web yapılandırma dosyalarını oluşturmayı tamamladığınızda, programınızı derleyen ve çalıştıran bu adıma hazırsınız. Bunu yapmak için Eclipse kullanarak uygulamanızı bir savaş dosyası olarak dışa aktarın ve aynısını tomcat'te dağıtın.
Eclipse kullanarak bir WAR dosyası oluşturmak için şu seçeneği takip edin: File → export → Web → War Fileve son olarak proje UserManagement ve hedef klasörü seçin. Tomcat'te bir savaş dosyasını dağıtmak için UserManagement.war'ıTomcat Installation Directory → webapps directory ve Tomcat'i başlatın.
Programı Çalıştırmak
Web hizmetlerimizi test etmek için bir Chrome uzantısı olan Postman kullanıyoruz .
Tüm kullanıcıların listesini almak için UserManagement'a bir istekte bulunun. GET isteği ile POSTMAN'e http: // localhost: 8080 / UserManagement / rest / UserService / users yazın ve aşağıdaki sonucu görün.
Tebrikler, ilk RESTful Uygulamanızı başarıyla oluşturdunuz.
Kaynak nedir?
REST mimarisi, her içeriği bir kaynak olarak ele alır. Bu kaynaklar Metin Dosyaları, Html Sayfaları, Resimler, Videolar veya Dinamik İş Verileri olabilir. REST Sunucusu, kaynaklara ve REST istemcisine erişim sağlar ve kaynakları değiştirir. Burada her bir kaynak, URI'ler / Global ID'ler ile tanımlanır. REST, Metin, JSON, XML'in bulunduğu bir kaynağı temsil etmek için çeşitli temsiller kullanır. Kaynakların en popüler temsilleri XML ve JSON'dur.
Kaynakların Temsili
REST'teki bir kaynak, Nesne Yönelimli Programlamadaki benzer bir Nesnedir veya bir Veritabanındaki Varlık gibidir. Bir kaynak tanımlandıktan sonra, sunucunun kaynağı yukarıda belirtilen formatta gönderebilmesi ve müşterinin aynı formatı anlayabilmesi için standart bir format kullanılarak temsiline karar verilecektir.
Örneğin, RESTful Web Services - First Application bölümünde, bir kullanıcı aşağıdaki XML formatı kullanılarak temsil edilen bir kaynaktır -
<user>
<id>1</id>
<name>Mahesh</name>
<profession>Teacher</profession>
</user>
Aynı kaynak, aşağıdaki gibi JSON formatında temsil edilebilir -
{
"id":1,
"name":"Mahesh",
"profession":"Teacher"
}
İyi Kaynak Temsili
REST, bir kaynak gösteriminin formatına herhangi bir kısıtlama getirmez. Bir istemci JSON temsilini isteyebilirken, başka bir istemci aynı kaynağın sunucuya XML temsilini isteyebilir ve bu böyle devam edebilir. İstemciye, istemcinin anlayacağı biçimde kaynak iletmek REST sunucusunun sorumluluğundadır.
RESTful Web Servislerinde bir kaynağın temsil formatı tasarlanırken dikkat edilmesi gereken bazı önemli noktalar aşağıdadır.
Understandability - Hem Sunucu hem de Müşteri, kaynağın temsil biçimini anlayabilmeli ve kullanabilmelidir.
Completeness- Biçim, bir kaynağı tam olarak temsil edebilmelidir. Örneğin, bir kaynak başka bir kaynak içerebilir. Biçim, basit ve karmaşık kaynak yapılarını temsil edebilmelidir.
Linkablity - Bir kaynak başka bir kaynağa bağlantıya sahip olabilir, bir format bu tür durumları ele alabilmelidir.
Ancak, şu anda web hizmetlerinin çoğu, XML veya JSON biçimini kullanarak kaynakları temsil etmektedir. XML ve JSON verilerini anlamak, ayrıştırmak ve değiştirmek için kullanılabilecek çok sayıda kitaplık ve araç vardır.
RESTful Web Hizmetleri, istemci ve sunucu arasında bir iletişim aracı olarak HTTP protokollerini kullanır. İstemci, HTTP İsteği biçiminde bir mesaj gönderir ve sunucu bir HTTP Yanıtı biçiminde yanıt verir. Bu teknik, Mesajlaşma olarak adlandırılır. Bu mesajlar, mesaj verilerini ve meta verileri, yani mesajın kendisiyle ilgili bilgileri içerir. HTTP 1.1 için HTTP İsteği ve HTTP Yanıt mesajlarına bir göz atalım.
HTTP İsteği
Bir HTTP İsteğinin beş ana bölümü vardır -
Verb - GET, POST, DELETE, PUT vb. HTTP yöntemlerini gösterir.
URI - Sunucudaki kaynağı tanımlamak için Tekdüzen Kaynak Tanımlayıcı (URI).
HTTP Version- HTTP sürümünü gösterir. Örneğin, HTTP v1.1.
Request Header- Anahtar-değer çiftleri olarak HTTP İstek mesajı için meta verileri içerir. Örneğin, istemci (veya tarayıcı) tipi, istemci tarafından desteklenen format, mesaj gövdesinin formatı, önbellek ayarları vb.
Request Body - Mesaj içeriği veya Kaynak gösterimi.
HTTP Yanıtı
Bir HTTP Yanıtının dört ana bölümü vardır -
Status/Response Code- İstenen kaynak için Sunucu durumunu gösterir. Örneğin, 404, kaynak bulunamadı anlamına gelir ve 200, yanıtın uygun olduğu anlamına gelir.
HTTP Version- HTTP sürümünü gösterir. Örneğin, HTTP v1.1.
Response Header- Anahtar değer çiftleri olarak HTTP Yanıt mesajı için meta verileri içerir. Örneğin, içerik uzunluğu, içerik türü, yanıt tarihi, sunucu türü vb.
Response Body - Yanıt mesajı içeriği veya Kaynak gösterimi.
Misal
Biz açıkladığımız gibi RESTful Web Hizmetleri - Birinci Uygulama bölümde , bize http koyalım: // localhost: GET isteği ile postacı içinde 8080 / UserManagemeNT / dinlenme / UserService / kullanıcıları. Postacının gönder butonunun yanında bulunan Önizle butonuna tıkladıktan sonra Gönder butonuna tıklarsanız aşağıdaki çıktıyı görebilirsiniz.
Burada, tarayıcının bir GET isteği gönderdiğini ve XML olarak bir yanıt gövdesi aldığını görebilirsiniz.
Adresleme, bir kaynağı veya sunucuda bulunan birden çok kaynağı bulmayı ifade eder. Bir kişinin posta adresini bulmak da benzerdir.
REST mimarisindeki her kaynak, kendi URI'si (Tekdüzen Kaynak Tanımlayıcısı) ile tanımlanır. Bir URI aşağıdaki biçimdedir -
<protocol>://<service-name>/<ResourceType>/<ResourceID>
Bir URI'nin amacı, web hizmetini barındıran sunucuda bir kaynak (lar) bulmaktır. Bir talebin diğer bir önemli özelliği, kaynak üzerinde gerçekleştirilecek işlemi tanımlayan VERB'dir. Örneğin, RESTful Web Services - First Application bölümünde, URIhttp://localhost:8080/UserManagement/rest/UserService/users ve FİİL GET'tir.
Standart URI Oluşturma
Aşağıdakiler, bir URI tasarlarken dikkate alınması gereken önemli noktalardır -
Use Plural Noun- Kaynakları tanımlamak için çoğul isim kullanın. Örneğin, kullanıcıları kaynak olarak tanımlamak için kullanıcıları kullandık.
Avoid using spaces- Uzun bir kaynak adı kullanırken alt çizgi (_) veya kısa çizgi (-) kullanın. Örneğin, yetkili% 20users yerine yetkili_users kullanın.
Use lowercase letters - URI büyük / küçük harf duyarlı olmasa da, url'yi yalnızca küçük harflerle tutmak iyi bir uygulamadır.
Maintain Backward Compatibility- Web Hizmeti bir kamu hizmeti olduğundan, bir kez halka açık hale getirilen bir URI her zaman erişilebilir olmalıdır. URI'nin güncellenmesi durumunda, eski URI'yi 300 HTTP Durum kodunu kullanarak yeni bir URI'ye yönlendirin.
Use HTTP Verb- Kaynak üzerindeki işlemleri yapmak için her zaman GET, PUT ve DELETE gibi HTTP Fiillerini kullanın. URI'de işlem adını kullanmak iyi değildir.
Misal
Aşağıda, bir kullanıcıyı getirmek için zayıf bir URI örneği verilmiştir.
http://localhost:8080/UserManagement/rest/UserService/getUser/1
Aşağıda, bir kullanıcıyı getirmek için iyi bir URI örneği verilmiştir.
http://localhost:8080/UserManagement/rest/UserService/users/1
Daha önceki bölümlerde tartıştığımız gibi, RESTful Web Service, belirtilen kaynak (lar) üzerinde gerçekleştirilecek işlemi belirlemek için birçok HTTP fiili kullanır. Aşağıdaki tablo, en sık kullanılan HTTP Fiillerinin örneklerini göstermektedir.
Sr.No. | HTTP Yöntemi, URI ve İşlem |
---|---|
1 | GET http: // localhost: 8080 / UserManagement / rest / UserService / users Kullanıcıların listesini alır. (Sadece oku) |
2 |
GET http: // localhost: 8080 / UserManagement / rest / UserService / kullanıcılar / 1 Kullanıcı Kimliği 1'i alır (Sadece oku) |
3 |
PUT http: // localhost: 8080 / UserManagement / rest / UserService / kullanıcılar / 2 Kimliği 2 olan Kullanıcı Ekler (Etkisiz) |
4 |
POST http: // localhost: 8080 / UserManagement / rest / UserService / kullanıcılar / 2 Kullanıcıyı Kimlik 2 ile Günceller (Yok) |
5 |
DELETE http: // localhost: 8080 / UserManagement / rest / UserService / kullanıcılar / 1 Kimliği 1 olan Kullanıcıyı siler (Etkisiz) |
6 |
OPTIONS http: // localhost: 8080 / UserManagement / rest / UserService / users Bir web hizmetinde desteklenen işlemleri listeler. (Sadece oku) |
7 |
HEAD http: // localhost: 8080 / UserManagement / rest / UserService / users Yalnızca HTTP Başlığını döndürür, Gövde yok. (Sadece oku) |
Aşağıdaki noktalar dikkate alınmalıdır.
GET işlemleri salt okunurdur ve güvenlidir.
PUT ve DELETE işlemleri idempotenttir, yani bu işlemler kaç kez çalıştırılırsa çalıştırılsın sonuçlarının her zaman aynı olacağı anlamına gelir.
PUT ve POST işlemi, yalnızca PUT işleminin idempotent olduğu ve POST işleminin farklı bir sonuca neden olabileceği sonuçta yatan farkla hemen hemen aynıdır.
Misal
CRUD (Oluşturma, Okuma, Güncelleme, Silme) işlemlerini gerçekleştirebilen bir Web hizmeti oluşturmak için RESTful Web Services - First Application bölümünde oluşturulan bir Örneği güncelleyelim . Basit olması için, Veritabanı işlemlerini değiştirmek için bir dosya G / Ç kullandık.
Güncelleyelim User.java, UserDao.java ve UserService.java com.tutorialspoint paketi altındaki dosyalar.
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;
}
}
User Dao.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>";
}
}
Şimdi Eclipse kullanarak, uygulamanızı bir WAR Fileve aynısını Tomcat'te dağıtın. Eclipse kullanarak bir WAR dosyası oluşturmak için şu yolu izleyin -File → export → Web → War Fileve son olarak proje UserManagement ve hedef klasörü seçin. Tomcat'te bir WAR dosyasını dağıtmak için UserManagement.war'ıTomcat Installation Directory → webapps dizin ve başlangıç Tomcat.
Web Hizmetini Test Etme
Jersey, web hizmetlerini test etmek için bir Web Hizmeti İstemcisi oluşturmak için API'ler sağlar. Örnek bir test sınıfı oluşturdukWebServiceTester.java aynı projede com.tutorialspoint paketi altında.
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);
}
}
Şimdi Eclipse kullanarak test cihazını çalıştırın. Dosyaya sağ tıklayın ve seçeneği takip edinRun as → Java Application. Eclipse konsolunda aşağıdaki sonucu göreceksiniz -
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 mimarisine göre, bir RESTful Web Hizmeti, sunucuda bir istemci durumunu tutmamalıdır. Bu kısıtlamaya Vatansızlık denir. Bağlamını sunucuya iletmek istemcinin sorumluluğundadır ve ardından sunucu, istemcinin diğer isteğini işlemek için bu içeriği depolayabilir. Örneğin, sunucu tarafından sürdürülen oturum, istemci tarafından iletilen oturum tanımlayıcıyla tanımlanır.
RESTful Web Hizmetleri bu kısıtlamaya uymalıdır. Bunu, RESTful Web Hizmetleri - Yöntemler bölümünde, web hizmeti yöntemlerinin çağrıldıkları istemciden herhangi bir bilgi depolamadığını gördük .
Consider the following URL −
https: // localhost: 8080 / UserManagement / rest / UserService / kullanıcılar / 1
Tarayıcınızı kullanarak veya java tabanlı bir istemci kullanarak veya Postman kullanarak yukarıdaki url'ye ulaşırsanız, sonuç her zaman Kimliği 1 olan Kullanıcı XML'si olur, çünkü sunucu istemci hakkında herhangi bir bilgi depolamaz.
<user>
<id>1</id>
<name>mahesh</name>
<profession>1</profession>
</user>
Vatansızlığın Avantajları
RESTful Web Hizmetlerinde vatansızlığın faydaları aşağıdadır -
Web hizmetleri, her yöntem talebini bağımsız olarak ele alabilir.
Web hizmetleri, müşterinin önceki etkileşimlerini sürdürmek zorunda değildir. Uygulama tasarımını basitleştirir.
HTTP'nin kendisi bir vatansızlık protokolü olduğundan, RESTful Web Servisleri HTTP protokolleriyle sorunsuz bir şekilde çalışır.
Vatansızlığın Dezavantajları
RESTful Web Hizmetlerinde vatansızlığın dezavantajları şunlardır:
Web hizmetlerinin her talepte ekstra bilgi alması ve ardından müşteri etkileşimlerinin halledilmesi durumunda müşterinin durumunu almak için yorum yapması gerekir.
Önbelleğe alma, sunucu yanıtını istemcinin kendisinde depolamayı ifade eder, böylece bir istemcinin aynı kaynak için tekrar tekrar bir sunucu talebinde bulunması gerekmez. Bir sunucu yanıtı, önbelleğe almanın nasıl yapılacağı hakkında bilgi içermelidir, böylece bir istemci yanıtı bir süre boyunca önbelleğe alır veya sunucu yanıtını hiçbir zaman önbelleğe almaz.
Aşağıda, bir istemcinin önbelleğini yapılandırmak için bir sunucu yanıtının sahip olabileceği başlıklar verilmiştir -
Sr.No. | Üstbilgi ve Açıklama |
---|---|
1 |
Date Kaynağın oluşturulduğu tarih ve saati. |
2 |
Last Modified Kaynağın en son değiştirildiği Tarih ve Saat. |
3 |
Cache-Control Önbelleğe almayı kontrol etmek için birincil başlık. |
4 |
Expires Önbelleğe almanın sona erme tarihi ve saati. |
5 |
Age Kaynağın sunucudan alınmasından itibaren saniye cinsinden süre. |
Önbellek Kontrol Başlığı
Aşağıda, Cache-Control başlığının ayrıntıları verilmiştir -
Sr.No. | Yönerge ve Açıklama |
---|---|
1 |
Public Kaynağın herhangi bir bileşen tarafından önbelleğe alınabileceğini gösterir. |
2 |
Private Kaynağın yalnızca istemci ve sunucu tarafından önbelleğe alınabileceğini, hiçbir aracının kaynağı önbelleğe alamayacağını belirtir. |
3 |
no-cache/no-store Bir kaynağın önbelleğe alınabilir olmadığını gösterir. |
4 |
max-age Önbelleğe almanın saniye cinsinden maksimum yaşa kadar geçerli olduğunu gösterir. Bundan sonra müşterinin başka bir talepte bulunması gerekir. |
5 |
must-revalidate Maksimum yaşın geçmesi durumunda kaynağı yeniden doğrulamak için sunucuya gösterge. |
En İyi Uygulamalar
Resimler, CSS, JavaScript gibi statik içerikleri her zaman 2 ila 3 günlük sona erme tarihi ile önbelleğe alınabilir tutun.
Son kullanma tarihini asla çok yüksek tutmayın.
Dinamik içerik yalnızca birkaç saat önbelleğe alınmalıdır.
RESTful Web Hizmetleri, HTTP URL Yolları ile çalıştığından, bir RESTful Web Hizmetinin, bir web sitesinin güvenliğiyle aynı şekilde korunması çok önemlidir.
RESTful Web Hizmeti tasarlarken uyulması gereken en iyi uygulamalar aşağıdadır -
Validation- Sunucudaki tüm girişleri doğrulayın. Sunucunuzu SQL veya NoSQL enjeksiyon saldırılarına karşı koruyun.
Session Based Authentication - Bir Web Hizmeti yöntemine her istek yapıldığında bir kullanıcının kimliğini doğrulamak için oturum tabanlı kimlik doğrulamasını kullanın.
No Sensitive Data in the URL - Bir URL'de asla kullanıcı adı, parola veya oturum belirteci kullanmayın, bu değerler POST yöntemi aracılığıyla Web Hizmetine aktarılmalıdır.
Restriction on Method Execution- GET, POST ve DELETE yöntemleri gibi yöntemlerin sınırlı kullanımına izin verin. GET yöntemi verileri silememelidir.
Validate Malformed XML/JSON - Bir web hizmeti yöntemine geçirilen iyi biçimlendirilmiş girdileri kontrol edin.
Throw generic Error Messages - Bir web hizmeti yöntemi, erişimin yasaklandığını vb. Göstermek için 403 gibi HTTP hata mesajlarını kullanmalıdır.
HTTP Kodu
Sr.No. | HTTP Kodu ve Açıklaması |
---|---|
1 |
200 OK - başarıyı gösterir. |
2 |
201 CREATED- bir kaynak POST veya PUT isteği kullanılarak başarıyla oluşturulduğunda. Konum başlığını kullanarak yeni oluşturulan kaynağa bağlantıyı döndürür. |
3 |
204 NO CONTENT- yanıt gövdesi boş olduğunda. Örneğin, bir DELETE isteği. |
4 |
304 NOT MODIFIED- koşullu GET istekleri durumunda ağ bant genişliği kullanımını azaltmak için kullanılır. Yanıt gövdesi boş olmalıdır. Başlıklarda tarih, konum vb. Bulunmalıdır. |
5 |
400 BAD REQUEST- geçersiz bir giriş sağlandığını belirtir. Örneğin, doğrulama hatası, eksik veriler. |
6 |
401 UNAUTHORIZED - kullanıcının geçersiz veya yanlış kimlik doğrulama belirteci kullandığını belirtir. |
7 |
403 FORBIDDEN- Kullanıcının kullanılan yönteme erişimi olmadığını belirtir. Örneğin, yönetici hakları olmadan erişimi silin. |
8 |
404 NOT FOUND - yöntemin mevcut olmadığını belirtir. |
9 |
409 CONFLICT- yöntemi uygularken çatışma durumunu belirtir. Örneğin, yinelenen giriş eklemek. |
10 |
500 INTERNAL SERVER ERROR - yöntemi çalıştırırken sunucunun bazı istisnalar attığını belirtir. |
JAX-RSRESTful Web Hizmetleri için JAVA API anlamına gelir. JAX-RS, oluşturulan RESTful Web Servisleri için destek sağlayan JAVA tabanlı bir programlama dili API'si ve belirtimidir. 2.0 sürümü 24 Mayıs 2013'te piyasaya sürüldü. JAX-RS, JAVA tabanlı web hizmetleri oluşturma ve dağıtımını basitleştirmek için Java SE 5'te bulunan açıklamaları kullanır. Ayrıca, RESTful Web Hizmetleri için istemciler oluşturmaya yönelik destekler sağlar.
Teknik Özellikler
Aşağıda, bir kaynağı bir web hizmeti kaynağı olarak eşlemek için en sık kullanılan ek açıklamalar verilmiştir.
Sr.No. | Ek Açıklama ve Açıklama |
---|---|
1 |
@Path Kaynak sınıfının / yönteminin göreli yolu. |
2 |
@GET HTTP Alma isteği, kaynağı almak için kullanılır. |
3 |
@PUT Kaynağı güncellemek için kullanılan HTTP PUT isteği. |
4 |
@POST Yeni bir kaynak oluşturmak için kullanılan HTTP POST isteği. |
5 |
@DELETE Kaynağı silmek için kullanılan HTTP DELETE isteği. |
6 |
@HEAD Yöntem kullanılabilirliği durumunu almak için kullanılan HTTP HEAD isteği. |
7 |
@Produces Web hizmeti tarafından oluşturulan HTTP Yanıtını belirtir. Örneğin, UYGULAMA / XML, METİN / HTML, UYGULAMA / JSON vb. |
8 |
@Consumes HTTP İstek türünü belirtir. Örneğin, uygulama / x-www-formurlencoded POST isteği sırasında form verilerini HTTP gövdesinde kabul edecek şekilde kodlandı. |
9 |
@PathParam Yönteme iletilen parametreyi yoldaki bir değere bağlar. |
10 |
@QueryParam Yönteme iletilen parametreyi yoldaki bir sorgu parametresine bağlar. |
11 |
@MatrixParam Yönteme iletilen parametreyi yoldaki bir HTTP matrix parametresine bağlar. |
12 |
@HeaderParam Yönteme iletilen parametreyi bir HTTP başlığına bağlar. |
13 |
@CookieParam Yönteme iletilen parametreyi bir Çerez'e bağlar. |
14 |
@FormParam Yönteme iletilen parametreyi bir form değerine bağlar. |
15 |
@DefaultValue Yönteme iletilen bir parametreye varsayılan bir değer atar. |
16 |
@Context Kaynağın bağlamı. Örneğin, bağlam olarak HTTPRequest. |
Note- Oracle tarafından JAX-RS 2.0'ın bir referans uygulaması olan Jersey'i RESTful Web Hizmetleri - İlk Uygulama ve RESTful Web Hizmetleri - Yöntemler bölümlerinde kullandık.