java-ee
Java RESTful 웹 서비스 (JAX-RS)
수색…
비고
W3C 표준으로 지정된 SOAP 및 WS- 스택과 달리 REST는 실제로 웹 기반 인터페이스를 설계하고 사용하기위한 일련의 원칙입니다. REST / RESTful 애플리케이션은 다른 표준에 크게 의존합니다.
HTTP
URI, URL
XML, JSON, HTML, GIF, JPEG, and so forth (resource representations)
JAX-RS (RESTful Web Services 용 Java API)의 역할은 RESTful 서비스를 빌드하는 것을 지원하는 API를 제공하는 것이다. 그러나 JAX-RS는 이를 수행하는 한 가지 방법 일뿐입니다. RESTful 서비스는 Java와 다른 많은 프로그래밍 언어에서 (다른 방법으로) 구현 될 수있다.
단순 자원
우선 JAX-RS 애플리케이션의 경우 모든 리소스를 사용할 수있는 기본 URI를 설정해야합니다. 이를 위해 javax.ws.rs.core.Application
클래스를 확장하고 javax.ws.rs.ApplicationPath
주석으로 주석을 추가해야합니다. 어노테이션은 기본 URI를 정의하는 문자열 인수를 승인합니다.
@ApplicationPath(JaxRsActivator.ROOT_PATH)
public class JaxRsActivator extends Application {
/**
* JAX-RS root path.
*/
public static final String ROOT_PATH = "/api";
}
리소스는 @Path
어노테이션으로 주석이 달린 간단한 POJO 클래스이다.
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
@Path("/hello")
public class HelloWorldResource {
public static final String MESSAGE = "Hello StackOverflow!";
@GET
@Produces("text/plain")
public String getHello() {
return MESSAGE;
}
}
HTTP GET
요청이 /hello
로 보내지면 리소스는 Hello StackOverflow!
응답합니다 Hello StackOverflow!
메시지.
GET 메소드 유형
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
@Path("/hello")
public class HelloWorldResource {
public static final String MESSAGE = "Hello World!";
@GET
@Produces("text/plain")
public String getHello() {
return MESSAGE;
}
@GET
@Path("/{letter}")
@Produces("text/plain")
public String getHelloLetter(@PathParam("letter") int letter){
if (letter >= 0 && letter < MESSAGE.length()) {
return MESSAGE.substring(letter, letter + 1);
} else {
return "";
}
}
}
매개 변수가없는 GET
은 모든 내용 ( "Hello World!")을 제공하고 경로 매개 변수와 함께 GET
은 해당 문자열에서 특정 문자를 제공합니다.
몇 가지 예 :
$ curl http://localhost/hello Hello World!
$ curl http://localhost/hello/0 H
$ curl http://localhost/hello/4 o
참고 : 메소드 유형 주석 (예 : 위의 @GET
)을 생략하면 요청 메소드는 기본적으로 GET 요청 핸들러가됩니다.
DELETE 메서드
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Response;
@Path("hello")
public class HelloWorldResource {
private String message = "Hello StackOverflow!";
@GET
@Produces("text/plain")
public String getHello() {
return message;
}
@DELETE
public Response deleteMessage() {
message = null;
return Response.noContent().build();
}
}
곱슬 곱슬하게 그것을 소비하십시오 :
$ curl http://localhost/hello
Hello StackOverflow!
$ curl -X "DELETE" http://localhost/hello
$ curl http://localhost/hello
null
POST 메서드
import javax.ws.rs.FormParam;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.core.Response;
@Path("hello")
public class HelloWorldResource {
@POST
@Path("/receiveParams")
public Response receiveHello(@FormParam("name") String name, @FormParam("message") String message) {
//process parameters
return Response.status(200).build();
}
@POST
@Path("/saveObject")
@Consumes("application/json")
public Response saveMessage(Message message) {
//process message json
return Response.status(200).entity("OK").build();
}
}
첫 번째 메소드는 캡처 된 입력 매개 변수를 전송하여 HTML 양식 제출을 통해 호출 할 수 있습니다. 양식 제출 조치가 -
/hello/receiveParams
두 번째 방법은 getters / setter가있는 POJO 메시지가 필요합니다. 모든 REST 클라이언트는 JSON 입력을 -
{"sender":"someone","message":"Hello SO!"}
POJO는 JSON과 동일한 속성을 가지고 직렬화 작업을 수행해야합니다.
public class Message {
String sender;
String message;
public String getSender() {
return sender;
}
public void setSender(String sender) {
this.sender = sender;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
예외 매퍼
@Provider
public class IllegalArgumentExceptionMapper implements ExceptionMapper<IllegalArgumentException> {
@Override
public Response toResponse(IllegalArgumentException exception) {
return Response.serverError().entity("Invalid input: " + exception.getMessage()).build();
}
}
이 예외 매퍼는 응용 프로그램에서 throw 된 모든 IllegalArgumentExceptions를 catch하고 사용자에게 스택 추적 대신 명확한 메시지를 표시합니다.
UriInfo
사용자 에이전트가 리소스에 액세스하는 데 사용한 URI에 대한 정보를 얻으려면 @Context
매개 변수 주석을 UriInfo
매개 변수와 함께 사용할 수 있습니다. UriInfo
객체에는 URI의 다른 부분을 가져 오는 데 사용할 수있는 몇 가지 메서드가 있습니다.
//server is running on https://localhost:8080,
// webapp is at /webapp, servlet at /webapp/servlet
@Path("class")
class Foo {
@GET
@Path("resource")
@Produces(MediaType.TEXT_PLAIN)
public Response getResource(@Context UriInfo uriInfo) {
StringBuilder sb = new StringBuilder();
sb.append("Path: " + uriInfo.getPath() + "\n");
sb.append("Absolute Path: " + uriInfo.getAbsolutePath() + "\n");
sb.append("Base URI: " + uriInfo.getBaseUri() + "\n");
sb.append("Request URI: " + uriInfo.getRequestUri() + "\n");
return Response.ok(sb.toString()).build();
}
}
https://localhost:8080/webapp/servlet/class/resource
에 대한 GET 출력 :
Path: class/resource
Absolute Path: https://localhost:8080/webapp/servlet/class/resource#
Base URI: https://localhost:8080/webapp/servlet/
Request URI: https://localhost:8080/webapp/servlet/class/resource
서브 소스
때로는 조직적인 이유로 또는 다른 이유로 인해 최상위 리소스가 다음과 같은 하위 리소스를 반환하도록하는 것이 좋습니다. 하위 리소스는 내부 클래스 일 필요는 없습니다.
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
@Path("items")
public class ItemsResource {
@Path("{id}")
public String item(@PathParam("id") String id) {
return new ItemSubResource(id);
}
public static class ItemSubResource {
private final String id;
public ItemSubResource(String id) {
this.id = id;
}
@GET
@Produces("text/plain")
public Item item() {
return "The item " + id;
}
}
}
맞춤 매개 변수 변환기
이것은 JAX-RS 엔드 포인트 용 사용자 정의 매개 변수 변환기를 구현하는 방법의 예입니다. 이 예제는 Java 8의 java.time
라이브러리에서 두 개의 클래스를 보여줍니다.
@Provider
public class ParamConverters implements ParamConverterProvider {
@Override
public <T> ParamConverter<T> getConverter(Class<T> rawType,
Type genericType,
Annotation[] annotations)
{
if (rawType == LocalDate.class)
return (ParamConverter<T>) new ParamConverter<LocalDate>() {
@Override
public LocalDate fromString(String value) {
return LocalDate.parse(value);
}
@Override
public String toString(LocalDate value) {
return null;
}
};
else if (rawType == MonthDay.class)
return (ParamConverter<T>) new ParamConverter<MonthDay>() {
@Override
public MonthDay fromString(String value) {
int[] ddmm = Arrays.stream(value.split("/"))
.mapToInt(Integer::parseInt)
.toArray();
return MonthDay.of(ddmm[1], ddmm[0]);
}
@Override
public String toString(MonthDay value) {
return null;
}
};
return null;
}
}
이름 바인딩
이름 바인딩 은 특정 필터 또는 인터셉터가 특정 리소스 메소드에 대해서만 실행될 것이라고 JAX-RS 런타임에 말할 수있는 개념입니다. 필터 또는 인터셉터가 특정 리소스 메소드에만 제한되어있을 때 이름이나 바인드 가 있다고합니다. 이러한 제한이없는 필터와 인터셉터를 전역 이라고합니다.
이름 바인딩 주석 정의
@NameBinding
어노테이션을 사용하여 필터 또는 인터셉터를 자원 메소드에 지정할 수 있습니다. 이 주석은 공급자 및 자원 메소드에 적용되는 다른 사용자 구현 주석에 대한 메타 주석으로 사용됩니다. 다음 예제를 참조하십시오.
@NameBinding
@Retention(RetentionPolicy.RUNTIME)
public @interface Compress {}
위의 예는 새 정의 @Compress
가 주석대로 주석을 바인딩 이름 주석 @NameBinding
. @Compress
어노테이션은 필터와 인터셉터를 엔드 포인트에 바인드하는 데 사용될 수 있습니다.
엔드 포인트에 필터 또는 인터셉터 바인드
GZIP 압축을 수행하는 인터셉터를 가지고 있고 이러한 인터셉터를 리소스 메소드에 바인딩하려고한다고 가정하십시오. 이를 수행하려면 다음과 같이 자원 메소드와 인터셉터에 모두 주석을 추가하십시오.
@Compress
public class GZIPWriterInterceptor implements WriterInterceptor {
@Override
public void aroundWriteTo(WriterInterceptorContext context)
throws IOException, WebApplicationException {
final OutputStream outputStream = context.getOutputStream();
context.setOutputStream(new GZIPOutputStream(outputStream));
context.proceed();
}
}
@Path("helloworld")
public class HelloWorldResource {
@GET
@Produces("text/plain")
public String getHello() {
return "Hello World!";
}
@GET
@Path("too-much-data")
@Compress
public String getVeryLongString() {
String str = ... // very long string
return str;
}
}
@Compress
는 리소스 메소드 getVeryLongString()
과 인터셉터 GZIPWriterInterceptor
됩니다. 인터셉터는 그러한 주석이있는 리소스 메소드가 실행될 때만 실행됩니다.
위의 예에서 인터셉터는 getVeryLongString()
메소드에 대해서만 실행됩니다. 인터셉터는 getHello()
메소드에 대해 실행되지 않습니다. 이 예에서 이유는 분명합니다. 긴 데이터 만 압축하려고하므로 "Hello World!"
짧은 응답을 압축 할 필요가 없습니다 "Hello World!"
.
이름 바인딩은 자원 클래스에 적용될 수 있습니다. 이 예제에서 HelloWorldResource
는 @Compress
로 주석 처리됩니다. 이 경우 모든 리소스 메소드가 압축을 사용함을 의미합니다.
전역 필터는 항상 실행되므로 이름 바인딩 주석이있는 리소스 메소드의 경우에도 마찬가지입니다.