RESTful 웹 서비스-빠른 가이드

REST 아키텍처 란?

REST는 REpresentational State Transfer를 나타냅니다. REST는 웹 표준 기반 아키텍처이며 HTTP 프로토콜을 사용합니다. 모든 구성 요소가 리소스이고 HTTP 표준 방법을 사용하여 공통 인터페이스에서 리소스에 액세스하는 리소스를 중심으로 회전합니다. REST는 2000 년 Roy Fielding에 의해 처음 소개되었습니다.

REST 아키텍처에서 REST 서버는 단순히 리소스에 대한 액세스를 제공하고 REST 클라이언트는 리소스에 액세스하고 수정합니다. 여기서 각 리소스는 URI / 글로벌 ID로 식별됩니다. 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 웹 서비스 생성

다음 장에서는 다음과 같은 기능으로 사용자 관리라는 웹 서비스를 만들 것입니다.

Sr. 아니. URI HTTP 방식 POST 본문 결과
1 / UserService / 사용자 가져 오기 모든 사용자의 목록을 표시합니다.
2 / UserService / addUser 우편 JSON 문자열 새 사용자의 세부 사항을 추가하십시오.
/ UserService / getUser / : id 가져 오기 사용자의 세부 사항을 표시합니다.

이 튜토리얼은 작업을 시작하기 위해 개발 환경을 준비하는 방법을 안내합니다. Jersey FrameworkRESTful 웹 서비스를 생성합니다. Jersey 프레임 워크 구현JAX-RS 2.0RESTful 웹 서비스를 생성하기위한 표준 사양 인 API. 이 튜토리얼은 또한 설정 방법을 알려줍니다.JDK, TomcatEclipse Jersey Framework를 설정하기 전에 컴퓨터에서.

JDK (Java Development Kit) 설정

Oracle의 Java 사이트 -Java SE Downloads 에서 최신 버전의 SDK를 다운로드 할 수 있습니다 . 다운로드 한 파일에서 JDK 설치 지침을 찾을 수 있습니다. 주어진 지침에 따라 설정을 설치하고 구성하십시오. 마지막으로PATHJAVA_HOME 다음을 포함하는 디렉토리를 참조하는 환경 변수 JavaJavac, 일반적으로 각각 java_install_dir / bin 및 java_install_dir.

Windows를 실행 중이고 C : \ jdk1.7.0_75에 JDK를 설치 한 경우 C : \ autoexec.bat 파일에 다음 행을 입력해야합니다.

set PATH = C:\jdk1.7.0_75\bin;%PATH% 
set JAVA_HOME = C:\jdk1.7.0_75

또는 Windows NT / 2000 / XP에서는 내 컴퓨터를 마우스 오른쪽 버튼으로 클릭하고 → 속성 → 고급 → 환경 변수를 선택할 수도 있습니다. 그런 다음 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

또는 Borland JBuilder, Eclipse, IntelliJ IDEA 또는 Sun ONE Studio와 같은 IDE (통합 개발 환경)를 사용하는 경우 간단한 프로그램을 컴파일하고 실행하여 IDE가 Java를 설치 한 위치를 알고 있는지 확인하고 그렇지 않으면 주어진 문서에 따라 적절한 설정을 수행합니다. IDE의.

Eclipse IDE 설정

이 튜토리얼의 모든 예제는 Eclipse IDE를 사용하여 작성되었습니다. 따라서 컴퓨터에 최신 버전의 Eclipse가 설치되어 있어야합니다.

Eclipse IDE를 설치하려면 다음에서 최신 Eclipse 바이너리를 다운로드하십시오. https://www.eclipse.org/downloads/. 설치를 다운로드 한 후 편리한 위치에 바이너리 배포의 압축을 풉니 다. 예를 들어 Windows의 C : \ eclipse 또는 Linux / Unix의 / usr / local / eclipse에서 마지막으로 PATH 변수를 적절하게 설정하십시오.

Windows 컴퓨터에서 다음 명령을 실행하여 Eclipse를 시작하거나 eclipse.exe를 두 번 클릭하면됩니다.

%C:\eclipse\eclipse.exe

Eclipse는 Unix (Solaris, Linux 등) 시스템에서 다음 명령을 실행하여 시작할 수 있습니다.

$/usr/local/eclipse/eclipse

성공적으로 시작한 후 모든 것이 정상이면 화면에 다음 결과가 표시됩니다.

Jersey Framework 라이브러리 설정

이제 모든 것이 정상이면 Jersey 프레임 워크 설정을 진행할 수 있습니다. 다음은 시스템에 프레임 워크를 다운로드하고 설치하는 몇 가지 간단한 단계입니다.

  • Jersey를 Windows 또는 Unix에 설치할 것인지 선택한 후 다음 단계로 진행하여 Windows 용 .zip 파일을 다운로드 한 다음 Unix 용 .tz 파일을 다운로드합니다.

  • 다음 링크에서 최신 버전의 Jersey 프레임 워크 바이너리를 다운로드합니다. https://jersey.java.net/download.html.

  • 이 튜토리얼을 작성할 때 jaxrs-ri-2.17.zip 내 Windows 시스템에서 다운로드 한 파일의 압축을 풀면 다음 스크린 샷과 같이 E : \ jaxrs-ri-2.17 \ jaxrs-ri 내부의 디렉토리 구조가 제공됩니다.

디렉토리에서 모든 Jersey 라이브러리를 찾을 수 있습니다. C:\jaxrs-ri-2.17\jaxrs-ri\lib 및 종속성 C:\jaxrs-ri-2.17\jaxrs-ri\ext. 이 디렉토리에서 CLASSPATH 변수를 올바르게 설정했는지 확인하십시오. 그렇지 않으면 응용 프로그램을 실행하는 동안 문제가 발생합니다. Eclipse를 사용하는 경우 모든 설정이 Eclipse를 통해 수행되므로 CLASSPATH를 설정할 필요가 없습니다.

Apache Tomcat 설정

최신 버전의 Tomcat을 다음에서 다운로드 할 수 있습니다. https://tomcat.apache.org/. 설치를 다운로드 한 후 편리한 위치에 바이너리 배포판의 압축을 풉니 다. 예를 들어 Windows의 C : \ apache-tomcat-7.0.59 또는 Linux / Unix의 /usr/local/apache-tomcat-7.0.59에서 설치 위치를 가리키는 CATALINA_HOME 환경 변수를 설정합니다.

Windows 시스템에서 다음 명령을 실행하여 Tomcat을 시작하거나 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.

Windows 시스템에서 다음 명령을 실행하여 Tomcat을 중지 할 수 있습니다.

%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 예제를 진행할 준비가 된 것입니다.

Jersey Framework로 실제 RESTful 웹 서비스 작성을 시작하겠습니다. Jersey Framework를 사용하여 첫 번째 예제를 작성하기 전에 RESTful 웹 서비스-환경 설정 장에 설명 된대로 Jersey 환경을 올바르게 설정했는지 확인해야합니다 . 여기에서는 Eclipse IDE에 대한 약간의 작업 지식이 있다고 가정합니다.

따라서 사용자 목록을 표시하는 웹 서비스 메서드를 노출하는 간단한 Jersey 애플리케이션을 작성해 보겠습니다.

자바 프로젝트 생성

첫 번째 단계는 Eclipse IDE를 사용하여 동적 웹 프로젝트를 만드는 것입니다. 옵션을 따르십시오File → New → Project 마지막으로 Dynamic Web Project마법사 목록에서 마법사. 이제 프로젝트 이름을UserManagement 다음 스크린 샷과 같이 마법사 창을 사용하여-

프로젝트가 성공적으로 생성되면 다음 콘텐츠가 Project Explorer

필요한 라이브러리 추가

두 번째 단계로 Jersey Framework와 해당 종속성 (라이브러리)을 프로젝트에 추가하겠습니다. 프로젝트의 WEB-INF / lib 디렉토리에있는 download jersey zip 폴더의 다음 디렉토리에서 모든 jar를 복사합니다.

  • \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 빌드 경로 창을 표시합니다.

이제 사용 Add JARs 아래에서 사용할 수있는 버튼 Libraries 탭을 클릭하여 WEBINF / lib 디렉토리에있는 JAR을 추가합니다.

소스 파일 만들기

이제 실제 소스 파일을 UserManagement계획. 먼저 다음과 같은 패키지를 만들어야합니다.com.tutorialspoint. 이렇게하려면 패키지 탐색기 섹션에서 src를 마우스 오른쪽 버튼으로 클릭하고 옵션을 따르십시오.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

  • 첫 번째 단계는 UserService에 대한 @Path 주석을 사용하여 웹 서비스의 경로를 지정하는 것입니다.

  • 두 번째 단계는 UserService의 메소드에 @Path 주석을 사용하여 특정 웹 서비스 메소드에 대한 경로를 지정하는 것입니다.

Web.xml 구성 파일 만들기

XML 파일이며 애플리케이션에 대한 Jersey 프레임 워크 서블릿을 지정하는 데 사용되는 Web 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에 배포합니다.

Eclipse를 사용하여 WAR 파일을 작성하려면 다음 옵션을 따르십시오. File → export → Web → War File마지막으로 프로젝트 UserManagement 및 대상 폴더를 선택하십시오. Tomcat에 war 파일을 배포하려면 UserManagement.war를Tomcat Installation Directory → webapps directory Tomcat을 시작하십시오.

프로그램 실행

웹 서비스를 테스트하기 위해 Chrome 확장 프로그램 인 Postman 을 사용 하고 있습니다.

UserManagement에 요청하여 모든 사용자 목록을 가져옵니다. GET 요청과 함께 http : // localhost : 8080 / UserManagement / rest / UserService / users를 POSTMAN에 넣고 다음 결과를 확인하십시오.

축하합니다. 첫 번째 RESTful 애플리케이션을 성공적으로 만들었습니다.

자원이란 무엇입니까?

REST 아키텍처는 모든 콘텐츠를 리소스로 취급합니다. 이러한 리소스는 텍스트 파일, Html 페이지, 이미지, 비디오 또는 동적 비즈니스 데이터 일 수 있습니다. REST 서버는 단순히 리소스에 대한 액세스를 제공하고 REST 클라이언트는 리소스에 액세스하고 수정합니다. 여기서 각 리소스는 URI / 글로벌 ID로 식별됩니다. REST는 다양한 표현을 사용하여 Text, JSON, XML이있는 리소스를 나타냅니다. 가장 많이 사용되는 리소스 표현은 XML과 JSON입니다.

자원의 표현

REST의 리소스는 객체 지향 프로그래밍의 유사한 객체이거나 데이터베이스의 엔티티와 같습니다. 리소스가 식별되면 서버가 위에서 언급 한 형식으로 리소스를 보낼 수 있고 클라이언트가 동일한 형식을 이해할 수 있도록 표준 형식을 사용하여 그 표현이 결정됩니다.

예를 들어, RESTful 웹 서비스-첫 번째 애플리케이션 장에서 사용자는 다음 XML 형식을 사용하여 표현되는 리소스입니다.

<user> 
   <id>1</id> 
   <name>Mahesh</name>
   <profession>Teacher</profession> 
</user>

동일한 리소스는 다음과 같이 JSON 형식으로 나타낼 수 있습니다.

{ 
   "id":1, 
   "name":"Mahesh", 
   "profession":"Teacher" 
}

좋은 자원 표현

REST는 자원 표현의 형식에 제한을 두지 않습니다. 클라이언트는 JSON 표현을 요청할 수 있지만 다른 클라이언트는 서버 등에 동일한 리소스의 XML 표현을 요청할 수 있습니다. 클라이언트가 이해하는 형식으로 클라이언트에게 리소스를 전달하는 것은 REST 서버의 책임입니다.

다음은 RESTful 웹 서비스에서 리소스의 표현 형식을 디자인 할 때 고려해야 할 몇 가지 중요한 사항입니다.

  • Understandability − 서버와 클라이언트 모두 리소스의 표현 형식을 이해하고 활용할 수 있어야합니다.

  • Completeness− Format은 자원을 완전히 표현할 수 있어야합니다. 예를 들어 리소스에 다른 리소스가 포함될 수 있습니다. 형식은 단순하고 복잡한 리소스 구조를 나타낼 수 있어야합니다.

  • Linkablity − 리소스는 다른 리소스와 연결될 수 있으며, 형식은 그러한 상황을 처리 할 수 ​​있어야합니다.

그러나 현재 대부분의 웹 서비스는 XML 또는 JSON 형식을 사용하여 리소스를 나타냅니다. XML 및 JSON 데이터를 이해, 구문 분석 및 수정할 수있는 많은 라이브러리와 도구가 있습니다.

RESTful 웹 서비스는 클라이언트와 서버 간의 통신 매체로 HTTP 프로토콜을 사용합니다. 클라이언트는 HTTP 요청 형식으로 메시지를 보내고 서버는 HTTP 응답 형식으로 응답합니다. 이 기술을 메시징이라고합니다. 이러한 메시지에는 메시지 데이터와 메타 데이터, 즉 메시지 자체에 대한 정보가 포함됩니다. HTTP 1.1에 대한 HTTP 요청 및 HTTP 응답 메시지를 살펴 보겠습니다.

HTTP 요청

HTTP 요청에는 다섯 가지 주요 부분이 있습니다.

  • Verb − GET, POST, DELETE, PUT 등과 같은 HTTP 메소드를 나타냅니다.

  • URI − 서버의 리소스를 식별하기위한 URI (Uniform Resource Identifier).

  • 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 웹 서비스-첫 번째 애플리케이션 장 에서 설명했듯이 GET 요청을 사용하여 http : // localhost : 8080 / UserManagement / rest / UserService / users를 POSTMAN에 넣습니다. Postman의 보내기 버튼 근처에있는 미리보기 버튼을 클릭 한 후 보내기 버튼을 클릭하면 다음과 같은 출력을 볼 수 있습니다.

여기에서 브라우저가 GET 요청을 보내고 응답 본문을 XML로 수신 한 것을 볼 수 있습니다.

주소 지정은 서버에있는 리소스 또는 여러 리소스를 찾는 것을 의미합니다. 사람의 우편 주소를 찾는 것과 유사합니다.

REST 아키텍처의 각 리소스는 URI (Uniform Resource Identifier)로 식별됩니다. URI는 다음 형식입니다-

<protocol>://<service-name>/<ResourceType>/<ResourceID>

URI의 목적은 웹 서비스를 호스팅하는 서버에서 리소스를 찾는 것입니다. 요청의 또 다른 중요한 속성은 리소스에서 수행 할 작업을 식별하는 VERB입니다. 예를 들어 RESTful 웹 서비스-첫 번째 애플리케이션 장에서 URI는http://localhost:8080/UserManagement/rest/UserService/users 그리고 동사는 GET입니다.

표준 URI 구성

다음은 URI를 설계 할 때 고려해야 할 중요한 사항입니다.

  • Use Plural Noun− 자원을 정의하기 위해 복수 명사를 사용합니다. 예를 들어 사용자를 리소스로 식별하기 위해 사용자를 사용했습니다.

  • Avoid using spaces− 긴 리소스 이름을 사용할 때는 밑줄 (_) 또는 하이픈 (-)을 사용하십시오. 예를 들어, authorized % 20users 대신 authorized_users를 사용하십시오.

  • Use lowercase letters − URI는 대소 문자를 구분하지 않지만 URL을 소문자로만 유지하는 것이 좋습니다.

  • Maintain Backward Compatibility− 웹 서비스는 공용 서비스이므로 일단 공개 된 URI는 항상 사용할 수 있어야합니다. URI가 업데이트되는 경우 HTTP 상태 코드 300을 사용하여 이전 URI를 새 URI로 리디렉션합니다.

  • Use HTTP Verb− 리소스에 대한 작업을 수행하려면 항상 GET, PUT 및 DELETE와 같은 HTTP 동사를 사용하십시오. URI에서 작업 이름을 사용하는 것은 좋지 않습니다.

다음은 사용자를 가져 오기위한 잘못된 URI의 예입니다.

http://localhost:8080/UserManagement/rest/UserService/getUser/1

다음은 사용자를 가져 오기위한 좋은 URI의 예입니다.

http://localhost:8080/UserManagement/rest/UserService/users/1

이전 장에서 RESTful 웹 서비스는 많은 HTTP 동사를 사용하여 지정된 리소스에 대해 수행 할 작업을 결정한다는 것을 논의했습니다. 다음 표에는 가장 일반적으로 사용되는 HTTP 동사의 예가 나와 있습니다.

Sr. 아니. HTTP 방법, URI 및 작업

1

GET

http : // localhost : 8080 / UserManagement / rest / UserService / users

사용자 목록을 가져옵니다.

(읽기 전용)

2

GET

http : // localhost : 8080 / UserManagement / rest / UserService / users / 1

ID 1의 사용자를 가져옵니다.

(읽기 전용)

PUT

http : // localhost : 8080 / UserManagement / rest / UserService / users / 2

ID 2로 사용자 삽입

(멱 등성)

4

POST

http : // localhost : 8080 / UserManagement / rest / UserService / users / 2

Id 2로 사용자 업데이트

(해당 없음)

5

DELETE

http : // localhost : 8080 / UserManagement / rest / UserService / users / 1

ID가 1 인 사용자를 삭제합니다.

(멱 등성)

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 웹 서비스-첫 번째 애플리케이션 장 에서 만든 예제를 업데이트하여 CRUD (만들기, 읽기, 업데이트, 삭제) 작업을 수행 할 수있는 웹 서비스를 만듭니다. 간단하게 데이터베이스 작업을 대체하기 위해 파일 I / O를 사용했습니다.

업데이트하겠습니다. User.java, UserDao.javaUserService.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 FileTomcat에서 동일하게 배포하십시오. eclipse를 사용하여 WAR 파일을 작성하려면 다음 경로를 따르십시오.File → export → Web → War File마지막으로 프로젝트 UserManagement와 대상 폴더를 선택합니다. Tomcat에 WAR 파일을 배포하려면 UserManagement.war를Tomcat Installation Directory → webapps 디렉토리 및 시작 Tomcat.

웹 서비스 테스트

Jersey는 웹 서비스를 테스트하기위한 웹 서비스 클라이언트를 만드는 API를 제공합니다. 샘플 테스트 클래스를 만들었습니다.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 웹 서비스는 서버에서 클라이언트 상태를 유지해서는 안됩니다. 이 제한을 Statelessness라고합니다. 컨텍스트를 서버에 전달하는 것은 클라이언트의 책임이며 서버는이 컨텍스트를 저장하여 클라이언트의 추가 요청을 처리 할 수 ​​있습니다. 예를 들어 서버가 유지 관리하는 세션은 클라이언트가 전달한 세션 식별자로 식별됩니다.

RESTful 웹 서비스는이 제한을 준수해야합니다. 우리는이를 보았다 방법 - RESTful 웹 서비스 웹 서비스 방법은 그들이에서 호출 된 클라이언트의 정보를 저장하지 않는 것을 장.

Consider the following URL −

https : // localhost : 8080 / UserManagement / rest / UserService / users / 1

브라우저를 사용하거나 Java 기반 클라이언트를 사용하거나 Postman을 사용하여 위의 URL을 입력하면 서버가 클라이언트에 대한 정보를 저장하지 않기 때문에 결과는 항상 ID가 1 인 사용자 XML이됩니다.

<user> 
   <id>1</id> 
   <name>mahesh</name> 
   <profession>1</profession> 
</user>

무국적자의 장점

다음은 RESTful 웹 서비스에서 상태 비 저장의 이점입니다.

  • 웹 서비스는 각 메서드 요청을 독립적으로 처리 할 수 ​​있습니다.

  • 웹 서비스는 클라이언트의 이전 상호 작용을 유지할 필요가 없습니다. 애플리케이션 설계를 단순화합니다.

  • HTTP 자체가 상태 비 저장 프로토콜이므로 RESTful 웹 서비스는 HTTP 프로토콜과 원활하게 작동합니다.

무국적자의 단점

다음은 RESTful 웹 서비스에서 상태 비 저장의 단점입니다-

  • 웹 서비스는 각 요청에서 추가 정보를 얻은 다음 클라이언트 상호 작용이 처리 될 경우 클라이언트의 상태를 가져 오기 위해 해석해야합니다.

캐싱은 클라이언트 자체에 서버 응답을 저장하는 것을 의미하므로 클라이언트가 동일한 리소스에 대해 서버 요청을 반복 할 필요가 없습니다. 서버 응답에는 캐싱이 수행되는 방법에 대한 정보가 있어야 클라이언트가 일정 기간 동안 응답을 캐시하거나 서버 응답을 캐시하지 않도록합니다.

다음은 클라이언트의 캐싱을 구성하기 위해 서버 응답이 가질 수있는 헤더입니다.

Sr. 아니. 헤더 및 설명

1

Date

리소스가 생성 된 날짜 및 시간입니다.

2

Last Modified

리소스가 마지막으로 수정 된 날짜 및 시간입니다.

Cache-Control

캐싱을 제어하는 ​​기본 헤더입니다.

4

Expires

캐싱 만료 날짜 및 시간입니다.

5

Age

서버에서 리소스를 가져온 후의 기간 (초)입니다.

캐시 제어 헤더

다음은 Cache-Control 헤더의 세부 사항입니다-

Sr. 아니. 지침 및 설명

1

Public

모든 구성 요소에서 리소스를 캐시 할 수 있음을 나타냅니다.

2

Private

리소스가 클라이언트와 서버에서만 캐시 가능하며 중개자가 리소스를 캐시 할 수 없음을 나타냅니다.

no-cache/no-store

리소스를 캐시 할 수 없음을 나타냅니다.

4

max-age

캐싱이 최대 max-age (초)까지 유효 함을 나타냅니다. 그 후 클라이언트는 다른 요청을해야합니다.

5

must-revalidate

max-age가 지난 경우 자원을 재 검증하도록 서버에 표시합니다.

모범 사례

  • 이미지, CSS, 자바 스크립트와 같은 정적 콘텐츠는 항상 2 ~ 3 일의 만료 날짜와 함께 캐시 가능한 상태로 유지하세요.

  • 만료일을 너무 높게 유지하지 마십시오.

  • 동적 콘텐츠는 몇 시간 동안 만 캐시되어야합니다.

RESTful 웹 서비스가 HTTP URL 경로와 함께 작동하므로 웹 사이트가 보안되는 것과 동일한 방식으로 RESTful 웹 서비스를 보호하는 것이 매우 중요합니다.

다음은 RESTful 웹 서비스를 설계하는 동안 준수해야 할 모범 사례입니다.

  • Validation− 서버의 모든 입력을 확인합니다. SQL 또는 NoSQL 주입 공격으로부터 서버를 보호하십시오.

  • Session Based Authentication − 세션 기반 인증을 사용하여 웹 서비스 방법에 대한 요청이있을 때마다 사용자를 인증합니다.

  • No Sensitive Data in the URL − URL에 사용자 이름, 암호 또는 세션 토큰을 사용하지 마십시오. 이러한 값은 POST 방법을 통해 웹 서비스에 전달되어야합니다.

  • Restriction on Method Execution− GET, POST 및 DELETE 메서드와 같은 메서드의 제한된 사용을 허용합니다. GET 메소드는 데이터를 삭제할 수 없어야합니다.

  • Validate Malformed XML/JSON − 웹 서비스 메소드에 전달 된 올바른 형식의 입력을 확인합니다.

  • Throw generic Error Messages − 웹 서비스 방법은 403과 같은 HTTP 오류 메시지를 사용하여 접근 금지 등을 표시해야합니다.

HTTP 코드

Sr. 아니. HTTP 코드 및 설명

1

200

OK − 성공을 보여줍니다.

2

201

CREATED− POST 또는 PUT 요청을 사용하여 리소스가 성공적으로 생성 된 경우. 위치 헤더를 사용하여 새로 생성 된 리소스에 대한 링크를 반환합니다.

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-RSRESTful 웹 서비스 용 JAVA API를 나타냅니다. JAX-RS는 작성된 RESTful 웹 서비스에 대한 지원을 제공하는 JAVA 기반 프로그래밍 언어 API 및 사양입니다. 2.0 버전은 2013 년 5 월 24 일에 출시되었습니다. JAX-RS는 Java SE 5에서 제공되는 주석을 사용하여 JAVA 기반 웹 서비스 생성 및 배포의 개발을 단순화합니다. 또한 RESTful 웹 서비스 용 클라이언트 생성을 지원합니다.

명세서

다음은 리소스를 웹 서비스 리소스로 매핑하는 데 가장 일반적으로 사용되는 주석입니다.

Sr. 아니. 주석 및 설명

1

@Path

리소스 클래스 / 메서드의 상대 경로입니다.

2

@GET

리소스를 가져 오는 데 사용되는 HTTP Get 요청입니다.

@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 요청 유형을 나타냅니다. 예를 들어, POST 요청 중에 HTTP 본문에서 양식 데이터를 수락하도록 application / x-www-formurlencoded.

9

@PathParam

메서드에 전달 된 매개 변수를 경로의 값에 바인딩합니다.

10

@QueryParam

메서드에 전달 된 매개 변수를 경로의 쿼리 매개 변수에 바인딩합니다.

11

@MatrixParam

메서드에 전달 된 매개 변수를 경로의 HTTP 행렬 매개 변수에 바인딩합니다.

12

@HeaderParam

메서드에 전달 된 매개 변수를 HTTP 헤더에 바인딩합니다.

13

@CookieParam

메서드에 전달 된 매개 변수를 Cookie에 바인딩합니다.

14

@FormParam

메서드에 전달 된 매개 변수를 양식 값에 바인딩합니다.

15

@DefaultValue

메서드에 전달 된 매개 변수에 기본값을 할당합니다.

16

@Context

자원의 컨텍스트. 예를 들어 HTTPRequest를 컨텍스트로 사용합니다.

Note− RESTful 웹 서비스-첫 번째 애플리케이션 및 RESTful 웹 서비스-방법 장 에서 Oracle의 JAX-RS 2.0 참조 구현 인 Jersey를 사용했습니다 .