结构化查询参数的JAX-RS映射

时间:2015-08-24 15:12:39

标签: java jax-rs dropwizard

我们的查询参数有一个结构(实际上,它们形成Map<String,Bindings>),这导致JAX-RS绑定中的重复。

我们可以更改绑定以消除重复吗?

@GET @Produces("application/json;charset=UTF-8")
List<BoundThings> getSomeBoundThings(
        @PathParam("id") UUID id,
        @QueryParam("bindings.organisation") Bindings orgBindings,
        @QueryParam("bindings.person") Bindings personBindings,
        @QueryParam("bindings.location") Bindings locBindings,
        @QueryParam("bindings.brand") Bindings brandBindings,
        @QueryParam("bindings.genre") Bindings genreBindings,
        @QueryParam("bindings.icb") Bindings icbBindings,
        @QueryParam("bindings.iptc") Bindings iptcBindings,
        @QueryParam("bindings.section") Bindings sectionBindings,
        @QueryParam("bindings.subject") Bindings subjBindings,
        @QueryParam("bindings.topic") Bindings topicBindings,
        @QueryParam("bindings.specialreport") Bindings rptBindings) {
}

仅针对上下文,该方法查找由UUID标识的特定实体的元数据。 Bindings是一个枚举,用于标识要使用的绑定类型。每个绑定都定义了一种关系。

是否可以使用Map<String,Bindings>?怎么样?

1 个答案:

答案 0 :(得分:0)

有几种方法可以清理它。

注意:这仅适用于DW [8.0,)

你可以 ......

只需注入UriInfo即可获得MultivaluedMap<String, String>。 (虽然你不能得到MultivaluedMap<String, Bindings>

@GET
public Response get(@Context UriInfo uriInfo) {
    MultivaluedMap<String, String> queryMap = uriInfo.getQueryParameters();
}

你可以 ......

使用@BeanParam将所有内容放入bean中。

public class BindingsBean {

    @QueryParam("bindings.organisation") 
    Bindings orgBindings;

    @QueryParam("bindings.person") 
    Bindings personBindings;
}

@GET
public Response get(@BeanParam BindingsBean bindingsBean) {}

你可以 ......

创建一个类似地图的bean类并创建一个Factory [ 1 ] ,这样就可以用@Context注入它。例如

地图包装

public class BindingsMap {

    public static final String BINDINGS_ORGANIZATION = "bindings.organisation";
    public static final String BINDINGS_PERSON = "bindings.person";

    private final Map<String, Bindings> bindings = new HashMap<>();

    public void put(String key, Bindings bindings) {
        this.bindings.put(key, bindings);
    }

    public Bindings get(String key) {
        return this.bindings.get(key);
    }
}

public class QueryBindingsFactory
        extends AbstractContainerRequestValueFactory<BindingsMap> {

    @Override
    public BindingsMap provide() {
        BindingsMap bindingsMap = new BindingsMap();
        put(bindingsMap, BindingsMap.BINDINGS_ORGANIZATION);
        put(bindingsMap, BindingsMap.BINDINGS_PERSON);
        return bindingsMap;
    }

    private void put(BindingsMap bindingsMap, String key) {
        ContainerRequest request = getContainerRequest();
        MultivaluedMap<String, String> queryParams
                = request.getUriInfo().getQueryParameters();
        bindingsMap.put(key, Bindings.fromString(queryParams.getFirst(key)));
    }

    @Override
    public void dispose(BindingsMap t) {
    }
}

资源方法

@GET
public Response get(@Context BindingsMap bindingsMap) {}

然后你需要注册工厂

env.jersey().register(new AbstractBinder(){
    @Override
    public void configure() {
        bindFactory(QueryBindingsFactory.class)
                .to(BindingsMap.class)
                .in(RequestScoped.class);
    }
});

[ 1 ]请参阅Custom Injection and Lifecycle Management

你可以 ......

如果您不喜欢BindingsMap注释,请创建自定义注释以注入上述@Context。您可以在this answer中看到完整的示例。它几乎只是建立在上面的选项之上。它需要额外的:

  1. 自定义注释
  2. InjectionResolver
  3. AbstractValueFactoryProvider
  4. 所有示例都可以在链接中看到。如果您对@Context注释感到满意,那么可能更简单。