2014-04-01 2 views
0
내가 기저 URI에서 얻을 필요가

, 내 문제는 내가, 내가로 주입 할 수없는 코드의 조각 (엔티티의 하위 개체) 기저 URI가 필요하다이글로벌 기반 Uri 공장이 있습니까?

@Context 
UriInfo uriInfo; 

와 familliar 해요 . 나는 uriInfo 또는 빌더를 내릴 수 있지만, 대부분의 오브젝트는 비즈니스에 대해 알지 못하기 때문에 이상하지 않은 것으로 보입니다. 최종 목표는 내 JSON 응답에 HATEOAS URI가 있지만 JAX-RS 고유의 솔루션 일 필요는 없습니다. JAXA 변환기 나 엔티티에서 Base URI를 얻을 수 있다면 거기에서 URIBuilder.

답변

0

UriInfo은 JAX-RS 구현과 AFAIK에 의해 관리되며 실제로 코드의 다른 위치 (CDI 빈 없음)에 삽입 할 수 없습니다. HATEOAS를 구현하는 것이 목표라면 엔티티 객체 그래프를 JSON 응답으로 언 마샬링하고이 객체를 삽입 할 수있는 MessageBodyWriter를 작성하면된다. UriInfo.

HTH.

+0

은 MessageBodyWriter가 아닌 잭슨이 무엇입니까? 모든 객체의 모든 부분을 직렬화하는 손이 불편하고 오류가 발생하기 쉽습니다. 엔티티에 삽입 할 수 없기 때문에 도움이되지 않는 CDI 빈이라 할지라도 jax-rs 레벨 솔루션이 있는지 확신하지 못합니다 ... – xenoterracide

0

업데이트 :이 모든 것을 작성한 후 분 (Jersey 2.13 사양의 제 12 장 선언 하이퍼 링크)이 발견되었습니다. 여전히 "개발 및 실험 중"이지만이 문제를 훨씬 더 우아하게 해결하는 것처럼 보입니다. 당신이 잭슨의 시리얼에 임의의 데이터를 보낼 필요가 다음 아래의 해결책은 여전히 ​​유효하면 원래의 게시물의 모든 코드는

public class Pie { 

    private String name; 

    Pie(String name) { 
    this.name = name; 
    } 

    @JsonIgnore 
    public String getName() { 
    return name; 
    } 

    @InjectLink(value="pies/{name}", style=Style.ABSOLUTE) 
    public URI url; 
} 

...이 교체 할 수 있습니다.

ORIGINAL 나는 동일한 문제가있었습니다. 구체적으로는 리소스에 ID (URI 끝에있는 것) 만 포함하고 Jackson이 JSON을 생성 할 때만 UriInfo를 사용하여 전체 URI를 생성하는 방법을 찾고 싶습니다. 각 요청에 대해 내 리소스에 새로운 커버 객체를 만들거나 직렬화되기 전에 각 리소스에 UriInfo를 삽입해야하는 솔루션을 피하고자했습니다.

Jackson 2.3의 경우이 작업을 수행하는 아주 좋은 방법이 있습니다. Jackson은 ObjectWriterInjector라는 클래스를 지원합니다. 정적 세트 메서드를 사용하면 요청 당 한 번씩 ObjectWriterModifier의 고유 한 인스턴스를 제공 할 수 있습니다. 이 인스턴스는 UriInfo를 사용할 수있는 Jersey 리소스 메소드에서 생성하고 설정할 수 있습니다. Jackson은 JSON을 작성하기 전에 ObjectWriterModifier를 호출하여 사용할 ObjectWriter를 조정할 수있는 기회를 제공합니다. 이 경우 withAttribute 메서드를 사용하여 UriInfo를 ObjectWriter에 연결할 수 있습니다.

그래서 ObjectWriter의 속성은 무엇입니까? 이러한 특성은 JsonSerializer 구현의 serialize 메서드에서 SerializerProvider 매개 변수를 통해 사용할 수 있습니다. 제 경우에는 getter에서 @JsonSerialize를 사용하기 때문에 하나의 필드 만 수정하고 싶었습니다. serialize 메서드에서 SerializerProvider 매개 변수의 getAttribute 메서드를 호출하여 UriInfo를 검색 한 다음이를 사용하여 전체 URI를 생성합니다.

이 방법론은 정보를 Jackson serializer로 푸시하려는 경우에 유용합니다.

간단한 저지 자원 ...

@Path("/pies") 
public class Pies { 

    static List<Pie> pies; 

    static 
    { 
     pies = new ArrayList<Pie>(); 
     pies.add(new Pie("apple")); 
     pies.add(new Pie("pumpkin")); 
    } 

    @GET 
    @Produces(MediaType.APPLICATION_JSON) 
    public List<Pie> getPies(@Context UriInfo uriInfo) { 

     // This is the good stuff!!!! 
     ObjectWriterInjector.set(new ObjectWriterPlusUriInfo(uriInfo)); 

     // Notice I don't have to anything to the objects in the Pies list 
     return pies; 
    } 
} 

ObjectWriter을 꼬집는 클래스 ...

class ObjectWriterPlusUriInfo extends ObjectWriterModifier { 

private UriInfo uriInfo; 

ObjectWriterPlusUriInfo(UriInfo uriInfo) { 
    this.uriInfo = uriInfo; 
} 

@Override 
public ObjectWriter modify(EndpointConfigBase<?> endpoint, 
     MultivaluedMap<String, Object> responseHeaders, Object value, 
     ObjectWriter ow, JsonGenerator gen) throws IOException { 
    // Adding the UriInfo attribute 
    return ow.withAttribute("JerseyUriInfo", uriInfo); 
    } 
} 

잭슨 주석 파이 클래스

...

public class Pie { 

private String name; 

Pie(String name) { 
    this.name = name; 
} 

@JsonProperty(value="url") 
@JsonSerialize(using=JacksonIdToUrlSerializer.class) 
public String getName() { 
    return name; 
    } 
} 

시리얼 ...

public class JacksonIdToUrlSerializer extends JsonSerializer<String>{ 

@Override 
public void serialize(String value, JsonGenerator jgen, 
     SerializerProvider provider) throws IOException, 
     JsonProcessingException { 

    UriInfo uriInfo = (UriInfo)provider.getAttribute("JerseyUriInfo"); 
    jgen.writeString(uriInfo.getRequestUriBuilder().path(value).build().toString()); 
    } 
} 

의 GET ...

http://localhost:8080/service/api/pies... 

는 생산 .. .

http://127.0.0.1:8080/service/api/pies... 

가 생산

363,210
[ 
    { 
    url: "http://localhost:8080/service/api/pies/apple" 
    }, 
    { 
    url: "http://localhost:8080/service/api/pies/pumpkin" 
    } 
] 

의 GET ... ObjectWriterInjector 그래서보다 일반적인 방법은 아래의 데이터를 전달하는 것을 이용한 내부 스레드 로컬 변수를 사용

[ 
    { 
    url: "http://127.0.0.1:8080/service/api/pies/apple" 
    }, 
    { 
    url: "http://127.0.0.1:8080/service/api/pies/pumpkin" 
    } 
] 

참고 요청 당 기준은 똑같이 유효합니다.

관련 문제