with tutorial servlet example java jersey

tutorial - web service rest java eclipse



¿Cómo asigna múltiples parámetros de consulta a los campos de un bean en la solicitud GET de Jersey? (5)

En Jersey 2.0 , querrá usar BeanParam para proporcionar sin problemas lo que está buscando en el estilo de Jersey normal.

Desde la página del documento vinculado anteriormente, puedes usar BeanParam para hacer algo como:

@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; }

Y entonces ParameterBean.java contendría:

public class ParameterBean { @QueryParam("prop1") public String prop1; @QueryParam("prop2") public String prop2; @QueryParam("prop3") public String prop3; @QueryParam("prop4") public String prop4; }

Prefiero las propiedades públicas en mis beans de parámetros, pero también puede usar los getters / setters y los campos privados si lo desea.

Una clase de servicio tiene una operación @GET que acepta múltiples parámetros. Estos parámetros se pasan como parámetros de consulta a la @GET servicio @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, ...)

La lista de estos parámetros está creciendo, por lo que me gustaría ubicarlos en un solo bean que contenga todos estos parámetros.

@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(); }

¿Cómo harías esto? ¿Es esto posible?


Es posible que desee utilizar el siguiente enfoque. Esta es una solución muy compatible con los estándares y no hay hacks allí. La solución anterior también funciona, pero es un tanto intrincada porque sugiere que trata solo con el cuerpo de la solicitud, mientras que en su lugar extrae los datos del contexto.

En mi caso, quería crear una anotación que permitiera asignar los parámetros de consulta "límite" y "desplazamiento" a un solo objeto. La solución es la siguiente:

@Provider public class SelectorParamValueFactoryProvider extends AbstractValueFactoryProvider { public static final String OFFSET_PARAM = "offset"; public static final String LIMIT_PARAM = "limit"; @Singleton public static final class InjectionResolver extends ParamInjectionResolver<SelectorParam> { public InjectionResolver() { super(SelectorParamValueFactoryProvider.class); } } private static final class SelectorParamValueFactory extends AbstractContainerRequestValueFactory<Selector> { @Context private ResourceContext context; private Parameter parameter; public SelectorParamValueFactory(Parameter parameter) { this.parameter = parameter; } public Selector provide() { UriInfo uriInfo = context.getResource(UriInfo.class); MultivaluedMap<String, String> params = uriInfo.getQueryParameters(); SelectorParam selectorParam = parameter.getAnnotation(SelectorParam.class); long offset = selectorParam.defaultOffset(); if(params.containsKey(OFFSET_PARAM)) { String offsetString = params.getFirst(OFFSET_PARAM); offset = Long.parseLong(offsetString); } int limit = selectorParam.defaultLimit(); if(params.containsKey(LIMIT_PARAM)) { String limitString = params.getFirst(LIMIT_PARAM); limit = Integer.parseInt(limitString); } return new BookmarkSelector(offset, limit); } } @Inject public SelectorParamValueFactoryProvider(MultivaluedParameterExtractorProvider mpep, ServiceLocator injector) { super(mpep, injector, Parameter.Source.UNKNOWN); } @Override public AbstractContainerRequestValueFactory<?> createValueFactory(Parameter parameter) { Class<?> classType = parameter.getRawType(); if (classType == null || (!classType.equals(Selector.class))) { return null; } return new SelectorParamValueFactory(parameter); } }

Lo que también necesitas hacer es registrarlo.

public class JerseyApplication extends ResourceConfig { public JerseyApplication() { register(JacksonFeature.class); register(new InjectionBinder()); } private static final class InjectionBinder extends AbstractBinder { @Override protected void configure() { bind(SelectorParamValueFactoryProvider.class).to(ValueFactoryProvider.class).in(Singleton.class); bind(SelectorParamValueFactoryProvider.InjectionResolver.class).to( new TypeLiteral<InjectionResolver<SelectorParam>>() { }).in(Singleton.class); } } }

También necesitas la anotación en sí.

@Target({java.lang.annotation.ElementType.PARAMETER, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.FIELD}) @Retention(java.lang.annotation.RetentionPolicy.RUNTIME) public @interface SelectorParam { long defaultOffset() default 0; int defaultLimit() default 25; }

y un frijol

public class BookmarkSelector implements Bookmark, Selector { private long offset; private int limit; public BookmarkSelector(long offset, int limit) { this.offset = offset; this.limit = limit; } @Override public long getOffset() { return 0; } @Override public int getLimit() { return 0; } @Override public boolean matches(Object object) { return false; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; BookmarkSelector that = (BookmarkSelector) o; if (limit != that.limit) return false; if (offset != that.offset) return false; return true; } @Override public int hashCode() { int result = (int) (offset ^ (offset >>> 32)); result = 31 * result + limit; return result; } }

Entonces podrías usarlo así.

@GET @Path(GET_ONE) public SingleResult<ItemDTO> getOne(@NotNull @PathParam(ID_PARAM) String itemId, @SelectorParam Selector selector) { Item item = auditService.getOneItem(ItemId.create(itemId)); return singleResult(mapOne(Item.class, ItemDTO.class).select(selector).using(item)); }


Intenta algo como esto. Use UriInfo para obtener todos los parámetros de solicitud en un mapa e intente acceder a ellos. Esto se hace en lugar de pasar parámetros individuales.

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


Puede crear un proveedor personalizado.

@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; }


Puede utilizar 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; } }; } }

En su recurso, solo tiene que usar @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(); }

El proveedor será llamado automáticamente.