如何在Jersey GET请求中将多个查询参数映射到bean的字段?

one*_*jig 50 java jax-rs jersey

服务类具有@GET接受多个参数的操作.这些参数作为查询参数传递给@GET服务调用.

@GET
@Path("find")
@Produces(MediaType.APPLICATION_XML)
public FindResponse find(@QueryParam("prop1") String prop1, 
                         @QueryParam("prop2") String prop2, 
                         @QueryParam("prop3") String prop3, 
                         @QueryParam("prop4") String prop4, ...) 
Run Code Online (Sandbox Code Playgroud)

这些参数的列表正在增长,因此我想将它们放入包含所有这些参数的单个bean中.

@GET
@Path("find")
@Produces(MediaType.APPLICATION_XML)
public FindResponse find(ParameterBean paramBean) 
{
    String prop1 = paramBean.getProp1();
    String prop2 = paramBean.getProp2();
    String prop3 = paramBean.getProp3();
    String prop4 = paramBean.getProp4();
}
Run Code Online (Sandbox Code Playgroud)

你会怎么做?这甚至可能吗?

Pat*_*ick 99

Jersey 2.0中,您将希望使用BeanParam以正常的Jersey样式无缝地提供您正在寻找的内容.

从上面链接的文档页面,您可以使用BeanParam执行以下操作:

@GET
@Path("find")
@Produces(MediaType.APPLICATION_XML)
public FindResponse find(@BeanParam ParameterBean paramBean) 
{
    String prop1 = paramBean.prop1;
    String prop2 = paramBean.prop2;
    String prop3 = paramBean.prop3;
    String prop4 = paramBean.prop4;
}
Run Code Online (Sandbox Code Playgroud)

然后ParameterBean.java将包含:

public class ParameterBean {
     @QueryParam("prop1") 
     public String prop1;

     @QueryParam("prop2") 
     public String prop2;

     @QueryParam("prop3") 
     public String prop3;

     @QueryParam("prop4") 
     public String prop4;
}
Run Code Online (Sandbox Code Playgroud)

我更喜欢我的参数bean上的公共属性,但如果你愿意,也可以使用getter/setter和private字段.

  • 有没有什么方法可以避免为我的bean中的每个属性放置`@QueryParam`,如果我希望它们全部可用? (4认同)
  • @pavel_kazlou我不知道有一种预先定义的方式来说"这个bean中的所有内容都是一个单独的QueryParam".Apache CXF确实存在[this](http://fusesource.com/docs/esb/4.3/cxf_rest/RESTParametersCXF.html).您也可以在此页面上编写自己的注入式提供程序(如[选择的答案](http://stackoverflow.com/a/6124014/1449525)).最后,您可以将查询参数作为[`Map <String,String>`通过`@Context UriInfo`](http://stackoverflow.com/a/57188​​74/1449525).除此之外,我并不认为泽西岛2.x已经出现了任何具体的事情. (2认同)

ken*_*ohn 25

尝试这样的事情.使用UriInfo将所有请求参数放入映射并尝试访问它们.这是在传递单个参数的情况下完成的.

// showing only the relavent code
public FindResponse find( @Context UriInfo allUri ) {
    MultivaluedMap<String, String> mpAllQueParams = allUri.getQueryParameters();
    String prop1 = mpAllQueParams.getFirst("prop1");
}
Run Code Online (Sandbox Code Playgroud)

  • 我试图避免这种情况.如果我可以避免取决于我的服务类上的UriInfo类,那将会更加清晰. (4认同)

Vla*_*rce 21

你可以用com.sun.jersey.spi.inject.InjectableProvider.

import java.util.List;
import java.util.Map.Entry;

import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.ext.Provider;

import org.springframework.beans.BeanUtils;

import com.sun.jersey.api.core.HttpContext;
import com.sun.jersey.api.model.Parameter;
import com.sun.jersey.core.spi.component.ComponentContext;
import com.sun.jersey.core.spi.component.ComponentScope;
import com.sun.jersey.spi.inject.Injectable;
import com.sun.jersey.spi.inject.InjectableProvider;

@Provider
public final class ParameterBeanProvider implements InjectableProvider<QueryParam, Parameter> {

    @Context
    private final HttpContext hc;

    public ParameterBeanProvider(@Context HttpContext hc) {
        this.hc = hc;
    }

    @Override
    public ComponentScope getScope() {
        return ComponentScope.PerRequest;
    }

    @Override
    public Injectable<ParameterBean> getInjectable(ComponentContext ic, final QueryParam a, final Parameter c) {

        if (ParameterBean.class != c.getParameterClass()) {
            return null;
        }

        return new Injectable<ParameterBean>() {

            public ParameterBean getValue() {
                ParameterBean parameterBean = new ParameterBean();
                MultivaluedMap<String, String> params = hc.getUriInfo().getQueryParameters();
                // Populate the parameter bean properties
                for (Entry<String, List<String>> param : params.entrySet()) {
                    String key = param.getKey();
                    Object value = param.getValue().iterator().next();

                    // set the property
                    BeanUtils.setProperty(parameterBean, key, value);
                }
                return parameterBean;
            }
        };
    }
}
Run Code Online (Sandbox Code Playgroud)

在您的资源中,您只需使用@QueryParam("valueWeDontCare").

@GET
@Path("find")
@Produces(MediaType.APPLICATION_XML)
public FindResponse find(@QueryParam("paramBean") ParameterBean paramBean) {
    String prop1 = paramBean.getProp1();
    String prop2 = paramBean.getProp2();
    String prop3 = paramBean.getProp3();
    String prop4 = paramBean.getProp4();
}
Run Code Online (Sandbox Code Playgroud)

将自动调用提供程序.

  • 相反,创建一个名为QueryBeanParam的注释:`@Target({ElementType.PARAMETER,ElementType.METHOD,ElementType.FIELD})@Retention(RetentionPolicy.RUNTIME)public @interface QueryBeanParam {}`.然后,在ParameterBeanProvider中实现`InjectableProvider <QueryBeanParam,Parameter>`而不是`InjectableProvider <QueryParam,Parameter>`.最后,在资源中使用`@QueryBeanParam`:`public FindResponse find(@QueryBeanParam ParameterBean paramBean){...}` (6认同)
  • 当您尝试在其他资源方法中使用`@QueryParam`时,这种实现POJO绑定的方法可能会在以后产生问题.最好创建自己的Annotation并使用它而不是`@QueryParam`. (5认同)

one*_*jig 7

您可以创建自定义提供程序.

@Provider
@Component
public class RequestParameterBeanProvider implements MessageBodyReader
{
    // save the uri
    @Context
    private UriInfo uriInfo;

    // the list of bean classes that need to be marshalled from
    // request parameters
    private List<Class> paramBeanClassList;

    // list of enum fields of the parameter beans
    private Map<String, Class> enumFieldMap = new HashMap<String, Class>();

    @Override
    public boolean isReadable(Class type, Type genericType, Annotation[] annotations, MediaType mediaType)
    {
        return paramBeanClassList.contains(type);
    }

    @Override
    public Object readFrom(Class type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap httpHeaders, InputStream entityStream) throws IOException, WebApplicationException
    {
        MultivaluedMap<String, String> params = uriInfo.getQueryParameters();

        Object newRequestParamBean;
        try
        {
            // Create the parameter bean
            newRequestParamBean = type.newInstance();

            // Populate the parameter bean properties
            for (Entry<String, List<String>> param : params.entrySet())
            {
                String key = param.getKey();
                Object value = param.getValue().iterator().next();

                // set the property
                BeanUtils.setProperty(newRequestParamBean, key, value);
            }
        }
        catch (Exception e)
        {
            throw new WebApplicationException(e, 500);
        }

        return newRequestParamBean;
    }

    public void setParamBeanClassList(List<Class> paramBeanClassList)
    {
        this.paramBeanClassList = paramBeanClassList;

    }
Run Code Online (Sandbox Code Playgroud)

  • 你能添加如何使用这个提供商吗?谢谢 (2认同)