REST 웹 서비스에서 HTTP 상태 코드를 설정하는 몇 가지 유스 케이스가 있으며 기존 응답에 최소한 하나는 충분히 문서화되어 있지 않습니다 (예 : JAXB를 사용하여 자동 마법 JSON / XML 직렬화를 사용하는 경우) 직렬화 할 개체뿐만 아니라 기본 200과 다른 상태 코드).
서로 다른 사용 사례와 각 솔루션에 대한 솔루션을 시도하고 열거 해 보겠습니다.
1. 오류 코드 (500, 404, ...)
200 OK
오류가 발생한 경우 와 다른 상태 코드를 반환하려는 경우 가장 일반적인 사용 사례 입니다.
예를 들면 다음과 같습니다.
- 엔티티가 요청되었지만 존재하지 않습니다 (404)
- 요청이 의미 상 올바르지 않습니다 (400)
- 사용자에게 권한이 부여되지 않음 (401)
- 데이터베이스 연결에 문제가 있습니다 (500).
- 기타..
a) 예외를 던져라
이 경우 문제를 처리하는 가장 깨끗한 방법은 예외를 throw하는 것입니다. 이 예외는에 의해 처리되어 ExceptionMapper
예외를 적절한 오류 코드가 포함 된 응답으로 변환합니다.
ExceptionMapper
Jersey로 사전 구성된 기본값 을 사용하고 (다른 구현과 동일하다고 생각합니다)의 기존 하위 클래스를 던질 수 javax.ws.rs.WebApplicationException
있습니다. 이들은 서로 다른 오류 코드로 사전 맵핑되는 사전 정의 된 예외 유형입니다. 예를 들면 다음과 같습니다.
- BadRequestException (400)
- InternalServerErrorException (500)
- NotFoundException (404)
기타 목록은 API 에서 찾을 수 있습니다.
또는 고유 한 사용자 정의 예외 및 ExceptionMapper
클래스를 정의하고 @Provider
어노테이션 ( 이 예제의 소스)을 통해 이러한 맵퍼를 Jersey에 추가 할 수 있습니다 .
public class MyApplicationException extends Exception implements Serializable
{
private static final long serialVersionUID = 1L;
public MyApplicationException() {
super();
}
public MyApplicationException(String msg) {
super(msg);
}
public MyApplicationException(String msg, Exception e) {
super(msg, e);
}
}
공급자 :
@Provider
public class MyApplicationExceptionHandler implements ExceptionMapper<MyApplicationException>
{
@Override
public Response toResponse(MyApplicationException exception)
{
return Response.status(Status.BAD_REQUEST).entity(exception.getMessage()).build();
}
}
참고 : 사용하는 기존 예외 유형에 대해 ExceptionMappers를 작성할 수도 있습니다.
b) 응답 빌더 사용
상태 코드를 설정하는 또 다른 방법은 Response
빌더를 사용 하여 원하는 코드로 응답을 빌드하는 것입니다.
이 경우 메소드의 리턴 유형은이어야합니다 javax.ws.rs.core.Response
. 이것은 hisdrewness의 승인 된 답변과 같은 다양한 다른 답변에 설명되어 있으며 다음과 같습니다.
@GET
@Path("myresource({id}")
public Response retrieveSomething(@PathParam("id") String id) {
...
Entity entity = service.getById(uuid);
if(entity == null) {
return Response.status(Response.Status.NOT_FOUND).entity("Resource not found for ID: " + uuid).build();
}
...
}
2. 성공, 그러나 200은 아님
반환 상태를 설정하려는 또 다른 경우는 작업이 성공했지만 본문에 반환하는 내용과 함께 200과 다른 성공 코드를 반환하려는 경우입니다.
빈번한 유스 케이스는 새 엔티티 ( POST
요청) 를 작성 하고이 새 엔티티 또는 엔티티 자체에 대한 정보를 201 Created
상태 코드 와 함께 리턴하려는 경우 입니다.
한 가지 방법은 위에서 설명한 것처럼 응답 객체를 사용하고 요청 본문을 직접 설정하는 것입니다. 그러나 이렇게하면 JAXB에서 제공하는 XML 또는 JSON으로 자동 직렬화 기능을 사용할 수 없게됩니다.
다음은 JAXB에 의해 JSON으로 직렬화 될 엔티티 객체를 리턴하는 원래 메소드입니다.
@Path("/")
@POST
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public User addUser(User user){
User newuser = ... do something like DB insert ...
return newuser;
}
새로 만든 사용자의 JSON 표현이 반환되지만 반환 상태는 201이 아니라 200입니다.
이제 문제는 Response
빌더를 사용하여 리턴 코드를 설정 하려는 경우 Response
메소드에서 오브젝트 를 리턴해야한다는 것입니다. User
직렬화 할 개체를 계속 반환하려면 어떻게합니까 ?
a) 서블릿 응답에 코드를 설정하십시오.
이 문제를 해결하는 한 가지 방법은 가렛 윌슨의 답변에서 볼 수 있듯이 서블릿 요청 객체를 얻고 직접 응답 코드를 직접 설정하는 것입니다.
@Path("/")
@POST
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public User addUser(User user, @Context final HttpServletResponse response){
User newUser = ...
//set HTTP code to "201 Created"
response.setStatus(HttpServletResponse.SC_CREATED);
try {
response.flushBuffer();
}catch(Exception e){}
return newUser;
}
이 메소드는 여전히 엔티티 오브젝트를 리턴하며 상태 코드는 201입니다.
작동하게하려면 응답을 플러시해야했습니다. 이것은 우리의 JAX_RS 리소스에서 저수준 서블릿 API 코드의 불쾌한 재생이며, 훨씬 더 나쁜 것은 헤더로 이미 헤더로 전송 되었기 때문에 헤더를 수정할 수 없게 만듭니다.
b) 개체와 함께 응답 개체 사용
이 경우 가장 좋은 솔루션은 Response 오브젝트를 사용하고이 응답 오브젝트에서 엔티티가 직렬화되도록 설정하는 것입니다. 이 경우 페이로드 엔터티의 유형을 나타 내기 위해 Response 객체를 일반으로 만드는 것이 좋지만 현재는 아닙니다.
@Path("/")
@POST
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public Response addUser(User user){
User newUser = ...
return Response.created(hateoas.buildLinkUri(newUser, "entity")).entity(restResponse).build();
}
이 경우 상태 코드를 201로 설정하기 위해 Response 빌더 클래스의 작성된 메소드를 사용합니다. entity () 메소드를 통해 엔티티 오브젝트 (사용자)를 응답에 전달합니다.
결과적으로 HTTP 코드는 원하는대로 401이며 응답 본문은 User 객체를 방금 반환했을 때와 똑같은 JSON입니다. 또한 위치 헤더를 추가합니다.
Response 클래스에는 다음과 같은 다양한 상태 (stati?)에 대한 여러 가지 빌더 메소드가 있습니다.
Response.accepted () Response.ok () Response.noContent () Response.notAcceptable ()
NB : hateoas 객체는 리소스 URI 생성을 돕기 위해 개발 한 도우미 클래스입니다. 여기서 자신의 메커니즘을 생각해 내야합니다.)
그게 다야.
이 긴 응답이 누군가에게 도움이되기를 바랍니다 :)