JAX-RS / Jersey 오류 처리를 사용자 정의하는 방법은 무엇입니까? 가지고 놀고 있습니다. @Path(“/hello”) public class HelloWorldResource

Jersey를 사용하여 JAX-RS (일명 JSR-311)를 배우고 있습니다. 루트 리소스를 성공적으로 만들었으며 매개 변수를 가지고 놀고 있습니다.

@Path("/hello")
public class HelloWorldResource {

    @GET
    @Produces("text/html")
    public String get(
        @QueryParam("name") String name,
        @QueryParam("birthDate") Date birthDate) {

         // Return a greeting with the name and age
    }
}

이것은 잘 작동하며 Date (String) 생성자가 이해하는 현재 로케일의 모든 형식을 처리합니다 (예 : YYYY / mm / dd 및 mm / dd / YYYY). 그러나 유효하지 않거나 이해할 수없는 값을 제공하면 404 응답이 발생합니다.

예를 들면 다음과 같습니다.

GET /hello?name=Mark&birthDate=X

404 Not Found

이 동작을 어떻게 사용자 정의 할 수 있습니까? 다른 응답 코드 (아마도 “400 Bad Request”)가 있습니까? 오류를 기록하는 것은 어떻습니까? 문제 해결을 위해 사용자 정의 헤더에 문제에 대한 설명 ( “잘못된 날짜 형식”)을 추가 하시겠습니까? 또는 5xx 상태 코드와 함께 세부 정보가 포함 된 전체 오류 응답을 반환합니까?



답변

JAX-RS를 사용하여 오류 처리 동작을 사용자 정의하는 방법에는 여러 가지가 있습니다. 다음은 쉬운 세 가지 방법입니다.

첫 번째 방법은 WebApplicationException을 확장하는 Exception 클래스를 만드는 것입니다.

예:

public class NotAuthorizedException extends WebApplicationException {
     public NotAuthorizedException(String message) {
         super(Response.status(Response.Status.UNAUTHORIZED)
             .entity(message).type(MediaType.TEXT_PLAIN).build());
     }
}

그리고이 새로 생성 된 예외를 throw하려면 다음을 수행하십시오.

@Path("accounts/{accountId}/")
    public Item getItem(@PathParam("accountId") String accountId) {
       // An unauthorized user tries to enter
       throw new NotAuthorizedException("You Don't Have Permission");
}

WebApplicationException은 런타임 예외이므로 throws 절에서 예외를 선언 할 필요는 없습니다. 클라이언트에게 401 응답을 반환합니다.

두 번째로 쉬운 방법은 WebApplicationException코드 에서 직접 인스턴스를 만드는 것 입니다. 이 방법은 자체 응용 프로그램 예외를 구현할 필요가없는 한 작동합니다.

예:

@Path("accounts/{accountId}/")
public Item getItem(@PathParam("accountId") String accountId) {
   // An unauthorized user tries to enter
   throw new WebApplicationException(Response.Status.UNAUTHORIZED);
}

이 코드도 클라이언트에 401을 반환합니다.

물론 이것은 단순한 예일뿐입니다. 필요한 경우 예외를 훨씬 더 복잡하게 만들 수 있으며 필요한 HTTP 응답 코드를 생성 할 수 있습니다.

또 다른 방법은 아마도, 기존의 예외를 래핑하는 것입니다 ObjectNotFoundException작은 래퍼 클래스와 그 구현ExceptionMapper@Provider 입니다. 아노 테이션으로 주석이 달린 인터페이스 . 이는 JAX-RS 런타임에 랩핑 된 예외가 발생하면에 정의 된 응답 코드를 리턴하도록 알려줍니다 ExceptionMapper.


답변

@Provider
public class BadURIExceptionMapper implements ExceptionMapper<NotFoundException> {

public Response toResponse(NotFoundException exception){

    return Response.status(Response.Status.NOT_FOUND).
    entity(new ErrorResponse(exception.getClass().toString(),
                exception.getMessage()) ).
    build();
}
}

위의 클래스를 만듭니다. 이것은 404 (NotFoundException)를 처리하고 여기 toResponse 메소드에서 사용자 정의 응답을 제공 할 수 있습니다. 마찬가지로 사용자 정의 응답을 제공하기 위해 매핑해야하는 ParamException 등이 있습니다.


답변

Jersey는 매개 변수를 비 정렬 화하지 못하면 com.sun.jersey.api.ParamException을 발생시켜 한 가지 해결책은 다음 유형의 예외를 처리하는 ExceptionMapper를 작성하는 것입니다.

@Provider
public class ParamExceptionMapper implements ExceptionMapper<ParamException> {
    @Override
    public Response toResponse(ParamException exception) {
        return Response.status(Status.BAD_REQUEST).entity(exception.getParameterName() + " incorrect type").build();
    }
}


답변

QueryParam 어노테이션이있는 변수에 재사용 가능한 클래스를 작성할 수도 있습니다.

public class DateParam {
  private SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");

  private Calendar date;

  public DateParam(String in) throws WebApplicationException {
    try {
      date = Calendar.getInstance();
      date.setTime(format.parse(in));
    }
    catch (ParseException exception) {
      throw new WebApplicationException(400);
    }
  }
  public Calendar getDate() {
    return date;
  }
  public String format() {
    return format.format(value.getTime());
  }
}

다음과 같이 사용하십시오 :

private @QueryParam("from") DateParam startDateParam;
private @QueryParam("to") DateParam endDateParam;
// ...
startDateParam.getDate();

이 경우 오류 처리는 사소한 것이지만 (400 응답 발생)이 클래스를 사용하면 일반적으로 로깅 등을 포함 할 수있는 매개 변수 처리를 제외 할 수 있습니다.


답변

하나의 확실한 해결책 : String을 가져 와서 Date로 직접 변환하십시오. 이렇게하면 원하는 형식을 정의하고 예외를 포착하며 전송되는 오류를 다시 발생 시키거나 사용자 지정할 수 있습니다. 구문 분석의 경우 SimpleDateFormat이 제대로 작동합니다.

데이터 유형에 대한 핸들러도 후크하는 방법이 있다고 확신하지만이 경우에는 약간의 간단한 코드 만 있으면됩니다.


답변

나도 좋아 StaxMan을 한다 이 QueryParam을 String으로 구현 한 다음 변환을 처리하고 필요에 따라 다시 던지기를 합니다.

로캘 별 동작이 원하는 동작 일 경우 다음을 사용하여 400 BAD REQUEST 오류를 반환합니다.

throw new WebApplicationException(Response.Status.BAD_REQUEST);

자세한 옵션 은 javax.ws.rs.core.Response.Status에 대한 JavaDoc을 참조하십시오 .


답변

@QueryParam 설명서에 따르면

“주석이 달린 매개 변수, 필드 또는 특성의 유형 T는 다음 중 하나 여야합니다.

1) 기본 유형이어야합니다.
2) 단일 문자열 인수를 허용하는 생성자를
갖습니다. 3) 단일 문자열 인수 를 허용하는 valueOf 또는 fromString이라는 정적 메소드를 갖습니다 (예 : Integer.valueOf (String)).
4) javax.ws.rs.ext.ParamConverterProvider의 등록 구현 JAX-RS 확장 SPI는 유형에 대해 “문자열에서”변환이 가능한 javax.ws.rs.ext.ParamConverter 인스턴스를 리턴합니다.
5) T는 위의 2, 3 또는 4를 만족하는 목록, 집합 또는 정렬 집합이어야합니다. 결과 모음은 읽기 전용입니다. “

문자열 형식의 쿼리 매개 변수를 유형 T로 변환 할 수 없을 때 사용자에게 전달되는 응답을 제어하려면 WebApplicationException을 발생시킬 수 있습니다. Dropwizard에는 다음과 같은 * Param 클래스가 포함되어 있습니다.

BooleanParam, DateTimeParam, IntParam, LongParam, LocalDateParam, NonEmptyStringParam, UUIDParam. 보다 https://github.com/dropwizard/dropwizard/tree/master/dropwizard-jersey/src/main/java/io/dropwizard/jersey/params를

Joda DateTime이 필요한 경우 Dropwizard DateTimeParam을 사용하십시오. .

위의 목록이 필요에 맞지 않으면 AbstractParam을 확장하여 자신을 정의하십시오. 구문 분석 방법을 재정의하십시오. 오류 응답 본문을 제어해야하는 경우 오류 방법을 대체하십시오.

Coda Hale의 좋은 기사는 http://codahale.com/what-makes-jersey-interesting-parameter-classes/ 에 있습니다 .

import io.dropwizard.jersey.params.AbstractParam;

import java.util.Date;

import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;

public class DateParam extends AbstractParam<Date> {

    public DateParam(String input) {
        super(input);
    }

    @Override
    protected Date parse(String input) throws Exception {
        return new Date(input);
    }

    @Override
    protected Response error(String input, Exception e) {
        // customize response body if you like here by specifying entity
        return Response.status(Status.BAD_REQUEST).build();
    }
}

Date (String arg) 생성자는 더 이상 사용되지 않습니다. Java 8을 사용하는 경우 Java 8 날짜 클래스를 사용합니다. 그렇지 않으면 joda 날짜 시간이 권장됩니다.