2014-04-01 47 views
0

我需要在基本URI,我familliar這個Uri工廠有全球基地嗎?

@Context 
UriInfo uriInfo; 

我的問題是我需要的基本URI中的一段代碼,我不能注入,(實體的子對象) 。我可以通過uriInfo或建設者,但這似乎並不理想,因爲大多數對象都沒有業務知道它。最終目標是HATEOAS URI在我的JSON響應中,但我不需要它是JAX-RS特定的解決方案,我想我是否可以在我的jackson轉換器或實體中獲得基本URI,我可以創建URIBuilder從那裏。

回答

0

UriInfo由JAX-RS實現和AFAIK管理,你不能在代碼的其他地方注入它(它不是CDI bean)。如果您的目標是實現HATEOAS,那麼您可以編寫自己的MessageBodyWriter,它將負責將您的實體對象圖解組爲一個JSON響應,並且您可以在其中注入此UriInfo

HTH。

+0

是不是MessageBodyWriter傑克遜做了什麼?手串行化所有對象的每個部分聽起來都很不愉快,而且容易出錯。即使它是CDI bean也無濟於事,因爲你無法注入到實體中......我不確定是否有jax-rs級別的解決方案...... – xenoterracide

0

更新:在我寫完所有這些之後的幾分鐘中,我找到了第12章。聲明式超鏈接在Jersey 2.13規範中。它仍然處於「正在開發和試驗階段」,但看起來它更加優雅地解決了這個問題。在原崗位的所有代碼可以通過這個如果你需要將任意數據發送到傑克遜串行那麼下面的解決方案仍然有效替代...

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插入到每個資源中。

事實證明,從傑克遜2.3開始,有一個很好的方法來做到這一點。傑克遜支持一個名爲ObjectWriterInjector的類。使用其靜態設置方法,您可以爲每個請求提供一次ObjectWriterModifier自己的實例。該實例可以在UriInfo可用的Jersey資源方法中創建和設置。在傑克遜寫出JSON之前,它會調用您的ObjectWriterModifier,讓您有機會調整它將使用的ObjectWriter。在這種情況下,您可以使用withAttribute方法將UriInfo附加到ObjectWriter。

那麼ObjectWriter的屬性有什麼好處?事實證明,這些屬性可以通過JsonSerializer實現的serialize方法中的SerializerProvider參數獲得。在我的情況下,我只想修改一個字段,所以我在getter上使用了@JsonSerialize。然後,在serialize方法中,調用SerializerProvider參數的getAttribute方法來檢索UriInfo,然後使用它構造完整的URI。

在任何情況下,如果要將信息推送到Jackson序列化程序,此方法應該可以工作。

簡單新澤西資源...

@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... 

主要生產.. 。

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

的GET ...

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

主要生產...

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

注意,ObjectWriterInjector使用一個線程局部變量內部因此使用更多通用的方法來傳遞數據下跌在每個請求的基礎上似乎同樣有效。