簡體   English   中英

解組XML或JSON以使用@InjectParam注釋來訓練球衣中的注入對象

[英]Unmarshalling XML or JSON to guice injected object in jersey using @InjectParam annotation

我有一個問題,正確地解組XML數據。 我正在使用guice和jersey技術。 奇怪的是,當我嘗試使用JAXB手動解組時,一切正常:

StringBuilder xml = new StringBuilder();
xml.append("<role>");
xml.append("  <name><values><value>Administrator</value><value l=\"en\">Administrator</value></values></name>");
xml.append("  <permissions>");
xml.append("    <permission>READ_XX</permission>");
xml.append("    <permission>WRITE_XX</permission>");
xml.append("  </permissions>");
xml.append("</role>");

JAXBContext jaxbContext = JAXBContext.newInstance(DefaultRole.class);
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
Object o = jaxbUnmarshaller.unmarshal(new StringReader(xml.toString()));

我最終得到了正確填充的對象:DefaultRole [id = null,name = [{val = Administrator},{l = en,val = Administrator}],permissions = [READ_XX,WRITE_XX]]

但是當使用jersey並注入我的Role接口時,它不起作用:

@POST
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
public JSONObject processLogin(@InjectParam Role role) throws JSONException
{
  System.out.println(role);

  return null;
}

該對象已實例化,但未填充:DefaultRole [id = null,name = null,permissions = []]

奇怪的是,當我用默認類替換接口參數(@InjectParam Role role)時:

@POST
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
public JSONObject processLogin(DefaultRole role) throws JSONException
{
  System.out.println(role);

  return null;
}

它工作,我再次正確填充我的對象。

使用界面使用guice注入對象時,我需要做什么才能正確填充對象?

我的DefaultRole類看起來像這樣:

@XmlRootElement(name = "role")
@XmlAccessorType(XmlAccessType.FIELD)
public class DefaultRole implements Role
{
  private Id id = null;

  @XmlJavaTypeAdapter(ContextObjectAdapter.class)
  private ContextObject<String> name = null;

  @XmlElementWrapper(name = "permissions")
  @XmlElement(name = "permission")
  private List<String> permissions = Lists.newArrayList();

  @Inject
  private DefaultRole()
  {
  }
  [...]

我已經嘗試將JAXB注釋添加到接口,但這也沒有幫助。 有人可以對此有所了解。 我花了好幾個小時試圖讓這個工作現在沒有任何運氣。

任何有關這方面的幫助將不勝感激。 邁克爾,提前謝謝

回答web.xml問題:

我實際上並沒有通過WEB-INF進行標准路由,但這是我的代碼注冊了jersey組件(當然,如果你仍然希望看到我的web.xml,我很樂意提供它):

    Injector injector = ModuleInjector.get().createChildInjector(new JerseyServletModule()
    {
        @Override
        protected void configureServlets()
        {
            bind(GuiceContainer.class);

            Set<Class<?>> foundClasses1 = Reflect.getReflections().getTypesAnnotatedWith(Path.class, false);
            Set<Class<?>> foundClasses2 = Reflect.getReflections().getTypesAnnotatedWith(Provider.class, false);

            Set<Class<?>> foundClasses = Sets.newHashSet();
            foundClasses.addAll(foundClasses1);
            foundClasses.addAll(foundClasses2);

            if (foundClasses != null && foundClasses.size() > 0)
            {
                for (Class<?> foundClass : foundClasses)
                {
                    if (foundClass == null)
                        continue;

                    if (ResourceConfig.isProviderClass(foundClass)
                        || ResourceConfig.isRootResourceClass(foundClass))
                    {
                        bind(foundClass);
                    }
                }
            }

            serve("/restws/*").with(GuiceContainer.class, ImmutableMap.of(JSONConfiguration.FEATURE_POJO_MAPPING, "true"));
        }
    });

好的,我會發布它。 這是我的web.xml的一部分:

    <!-- WHERE THE JERSEY COMPONENTS ARE BEING REGISTERED -->
<filter>
     <display-name>Bootstrap Filter</display-name>
     <filter-name>BootstrapFilter</filter-name>
     <filter-class>xxx.BootstrapFilter</filter-class>
 </filter>

<filter>
    <filter-name>Guice Filter</filter-name>
    <filter-class>com.google.inject.servlet.GuiceFilter</filter-class>
</filter>


    <!-- WHERE THE JERSEY COMPONENTS ARE BEING REGISTERED -->
<filter-mapping>
    <filter-name>BootstrapFilter</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>REQUEST</dispatcher>
</filter-mapping>

<filter-mapping>
    <filter-name>Guice Filter</filter-name>
    <url-pattern>/restws/*</url-pattern>
    <dispatcher>REQUEST</dispatcher>
</filter-mapping>

在我在澤西島郵件列表中得到回復后說,球衣沒有支持guice,我已經進一步嘗試並想出一個解決方案。 這是消息:

“Jersey 2.0不支持Guice。請參閱https://java.net/jira/browse/JERSEY-1950 ”。 http://jersey.576304.n2.nabble.com/Guice-integration-td7581958.html

為了完整起見,我也會在這里發布解決方案。 我提出的解決方案可能不是每個人的通用解決方案,但如果滿足以下條件,可能會給出一些想法或幫助:

  1. 所有要注入的對象都使用類級注釋進行“標記”。
  2. 要注入的所有對象都實現了一些接口(盡管它可以在不指定Object的情況下工作)。
  3. 您很高興創建自己的自定義參數注釋。

在我的特定情況下,我的所有bean都標有@Model注釋並實現我的“模型”界面。 其他類,例如存儲庫或服務,無論如何都可以通過guice正常注入到澤西資源中。 我遇到的問題僅僅是與@InjectParam注釋有關。

我認為它的神奇之處主要在於:

    model = request.getEntity(model.getClass());" 

它通過反序列化的內容(無論是JSON還是XML)神奇地填充guice注入對象。 我很驚訝在使用@InjectParam時內置解決方案不會發生這種情況,因為畢竟實際注入不是問題 - 它只是沒有填充對象。

所以這就是我如何解決它:

  1. 創建了一個名為“ModelParam”的注釋:

     @Target({ PARAMETER, METHOD, FIELD }) @Retention(RUNTIME) @Documented public @interface ModelParam { } 
  2. 使用新的“ModelParam”注釋替換了我的資源“RoleRestWS”中的“InjectParam”注釋:

     @POST @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) public Role createRole(@ModelParam Role role) throws JSONException { return userService.createRole(role); } 
  3. 為新的“ModelParam”注釋創建了一個InjectableProvider:

     @Provider @Singleton public class ModelInjectableProvider extends AbstractHttpContextInjectable<Model> implements InjectableProvider<ModelParam, Type> { private final Type type; public ModelInjectableProvider() { type = null; } public ModelInjectableProvider(Type type) { this.type = type; } @Override public ComponentScope getScope() { return ComponentScope.Undefined; } @Override public Injectable<Model> getInjectable(ComponentContext ic, ModelParam mp, Type type) { if (type instanceof Class && Model.class.isAssignableFrom((Class<?>) type)) { return new ModelInjectableProvider(type); } return null; } @Override public Model getValue(HttpContext ctx) { if (type instanceof Class && Model.class.isAssignableFrom((Class<?>) type)) { HttpRequestContext request = ctx.getRequest(); Model model = null; if (HttpMethod.POST.equals(request.getMethod()) || HttpMethod.PUT.equals(request.getMethod())) { model = (Model) MyGuiceInjector.inject((Class<?>) type); if (model != null) model = request.getEntity(model.getClass()); } return model; } return null; } } 

希望這可以幫助有類似問題的人。

最好的問候,邁克爾

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM