수색…


비고

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 로 주석 처리됩니다. 이 경우 모든 리소스 메소드가 압축을 사용함을 의미합니다.

전역 필터는 항상 실행되므로 이름 바인딩 주석이있는 리소스 메소드의 경우에도 마찬가지입니다.

선적 서류 비치



Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow