문제

저지를 사용하여 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
    }
}

이것은 훌륭하게 작동하며 날짜 (문자열) 생성자 (YYYY/MM/DD 및 MM/DD/YYYY)에 의해 이해되는 현재 로케일의 모든 형식을 처리합니다. 그러나 유효하지 않거나 이해되지 않는 값을 제공하면 404 응답을받습니다.

예를 들어:

GET /hello?name=Mark&birthDate=X

404 Not Found

이 동작을 어떻게 사용자 정의 할 수 있습니까? 어쩌면 다른 응답 코드 (아마도 "400 불량 요청")? 오류를 기록하는 것은 어떻습니까? 문제 해결을 돕기 위해 사용자 정의 헤더에 문제에 대한 설명 ( "나쁜 날짜 형식")에 대한 설명을 추가 할 수 있습니까? 아니면 5xx 상태 코드와 함께 세부 사항으로 전체 오류 응답을 반환합니까?

도움이 되었습니까?

해결책

JAX-RS로 오류 처리 동작을 사용자 정의하는 몇 가지 방법이 있습니다. 다음은 쉬운 방법 중 세 가지가 있습니다.

첫 번째 접근법은 웹 applicationException을 확장하는 예외 클래스를 만드는 것입니다.

예시:

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

그리고이 새로 생성 예외를 던지려면 간단히 말합니다.

@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 응답 코드를 생성 할 수 있습니다.

또 다른 방법은 @provider 주석으로 주석이 붙은 ExceptionMapper 인터페이스에 구현하는 작은 래퍼 클래스를 사용하여 기존 예외를 래핑하는 것입니다. 이것은 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)를 처리하고 여기에서 Torponse Method에서 사용자 정의 응답을 제공 할 수 있습니다. 마찬가지로 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 응답을 던지기)이 클래스를 사용하면 일반적으로 로깅 등을 포함 할 수있는 매개 변수 처리를 활성화 할 수 있습니다.

명백한 해결책 중 하나 : 현악기를 가져 가서 데이트 할 때까지 변환하십시오. 이렇게하면 원하는 형식을 정의하고 예외를 포착하고 전송되는 오류를 다시 배 또는 사용자 정의 할 수 있습니다. 구문 분석의 경우 SimpledateFormat이 제대로 작동해야합니다.

데이터 유형에 핸들러를 연결하는 방법이 있다고 확신하지만이 경우 간단한 코드가 거의 필요하지 않습니다.

나도 좋아 Staxman 아마도 해당 QueryParam을 문자열로 구현 한 다음 변환을 처리하고 필요에 따라 재조정 할 것입니다.

로케일 특정 동작이 원하는 및 예상 행동 인 경우 다음을 사용하여 400 불량 요청 오류를 반환합니다.

throw new WebApplicationException(Response.Status.BAD_REQUEST);

Javadoc을 참조하십시오 javax.ws.rs.core.response.status 더 많은 옵션.

@QueryParam 문서에 따르면

"주석이 달린 매개 변수, 필드 또는 속성의 유형 T는 다음과 같습니다.

1) 원시 유형이 되십시오
2) 단일 문자열 인수를 수락하는 생성자가 있습니다.
3) 단일 문자열 인수를 받아들이는 valueof 또는 Fromstring이라는 정적 메소드가 있습니다 (예 : integer.valueof (string) 참조).
4) javax.ws.rs.ext.paramconverterprovider jax-rs extension spi를 javax.ws.rs.rs.rs.ext.ext.paramconverter 인스턴스를 반환하는 javax.ws.rs.rs.ext.paramconverterprovider jax-rs extension spi의 등록 된 구현을 보유하고 있습니다.
5) 위의 2, 3 또는 4를 만족시키는 목록, 세트 또는 정렬 세트를 사용하십시오. 결과 컬렉션은 읽기 전용입니다. "

문자열 양식의 쿼리 매개 변수를 유형 T로 변환 할 수 없을 때 사용자에게 어떤 응답이 발생하는지 제어하려면 웹 applicationException을 던질 수 있습니다. Dropwizard는 필요에 사용할 수있는 *매개 변수 클래스와 함께 제공됩니다.

Booleanparam, Datetimeparam, Intparam, Longparam, LocalDateParam, NonimptyStringParam, 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();
    }
}

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

이것은 실제로 올바른 행동입니다. 저지는 입력에 대한 핸들러를 찾으려고 노력하고 제공된 입력에서 객체를 구성하려고합니다. 이 경우 생성자에 제공된 x x가있는 새 날짜 개체를 만들려고합니다. 이것은 잘못된 날짜이기 때문에 컨벤션에 의해 저지는 404를 반환합니다.

당신이 할 수있는 일은 출생 날짜를 문자열로 재 작성하고 넣는 것입니다. 그런 다음 구문 분석하고 원하는 것을 얻지 못하면 예외 매핑 메커니즘에 대해 원하는 예외를 자유롭게 던질 수 있습니다 (여러 가지가 있습니다. ).

브라우저 로그인 창을 열려면 @steven Lavine 답변에 대한 연장과 마찬가지로. 응답을 올바르게 반환하기가 어렵다는 것을 알았습니다 (MDN HTTP 인증) 사용자가 아직 인증되지 않은 경우 필터에서

이를 통해 Force Browser 로그인에 대한 응답을 구축하는 데 도움이되었으며 헤더의 추가 수정에 유의하십시오. 상태 코드를 401로 설정하고 브라우저가 사용자 이름/암호 대화 상자를 열게하는 헤더를 설정합니다.

// The extended Exception class
public class NotLoggedInException extends WebApplicationException {
  public NotLoggedInException(String message) {
    super(Response.status(Response.Status.UNAUTHORIZED)
      .entity(message)
      .type(MediaType.TEXT_PLAIN)
      .header("WWW-Authenticate", "Basic realm=SecuredApp").build()); 
  }
}

// Usage in the Filter
if(headers.get("Authorization") == null) { throw new NotLoggedInException("Not logged in"); }
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top