Возможно, вы захотите использовать следующий подход.Это очень стандартное решение, и в нем нет хаков.Вышеупомянутое решение также работает, но несколько хакерское, потому что оно предполагает, что оно имеет дело только с телом запроса, а вместо этого извлекает данные из контекста.
В моем случае я хотел создать аннотацию, которая позволяла бы сопоставлять параметры запроса "limit" и "offset" одному объекту.Решение заключается в следующем:
@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);
}
}
Вам также необходимо зарегистрировать его.
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);
}
}
}
Вам также нужна сама аннотация
@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;
}
ибоб
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;
}
}
Тогда вы можете использовать его вот так
@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));
}