Можно ли в Джерси объединить QueryParams и FormParams в одно значение для метода? - PullRequest
6 голосов
/ 04 января 2012

У меня есть такая функция:

@POST
@Path("/create")
@Produces({MediaType.APPLICATION_JSON})
public Playlist createPlaylist(@FormParam("name") String name)
{
    Playlist p = playlistDao.create();
    p.setName(name);
    playlistDao.insert(p);
    return p;
}

Я хочу, чтобы параметр "name" пришел из формы ИЛИ из параметра запроса. Если пользователь публикует в / playlist / create /? Name = bob, я хочу, чтобы он работал. (Это главным образом для помощи в тестировании API, но также и для использования его на разных платформах без браузера.)

Я бы хотел создать подкласс того, что делает магическое связывание работоспособным ... (@BothParam ("name") имя строки), но мне понадобится некоторая помощь, чтобы это произошло, поскольку я новичок в сервлетах Джерси / Java.


Обновление: на следующий день ...

Я решил эту проблему, реализовав ContainerRequestFilter, который объединяет параметры формы с параметрами запроса. Это не лучшее решение, но, похоже, оно работает. Мне не повезло слить что-либо в параметры формы.

Вот код на тот случай, если кто-то его ищет:

@Override
public ContainerRequest filter(ContainerRequest request) 
{
    MultivaluedMap<String, String> qParams = request.getQueryParameters();
    Form fParams = request.getFormParameters();
    for(String key : fParams.keySet())
    {
        String value = fParams.get(key).get(0);
        qParams.add(key, value);
    }
}

Я все равно буду признателен, если есть лучший способ сделать это, поэтому я пока оставлю этот вопрос открытым.

1 Ответ

3 голосов
/ 23 сентября 2012

Один из способов сделать это можно с помощью InjectableProvider.

Сначала вы определите аннотацию BothParam:

@Target({ ElementType.PARAMETER, ElementType.METHOD, ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
public @interface BothParam { String value(); }

Затем определите InjectableProviderдля него:

@Provider
public class BothParamProvider implements Injectable<String>, InjectableProvider<BothParam, Type> {    
    @Context private HttpContext httpContext;
    private String parameterName;

    public BothParamProvider(@Context HttpContext httpContext) {
        this.httpContext = httpContext;
    }

    public String getValue() {        
        if (httpContext.getRequest().getQueryParameters().containsKey(parameterName)) {
            return httpContext.getRequest().getQueryParameters().getFirst(parameterName);
        } else if(httpContext.getRequest().getFormParameters().containsKey(parameterName)) {
            return httpContext.getRequest().getFormParameters().getFirst(parameterName);
        }
        return null;
    }

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

    public Injectable getInjectable(ComponentContext cc, BothParam a, Type c) {        
        parameterName = a.value();
        return this;
    }    
}

Обратите внимание, что это не совсем сочетание QueryParam и FormParam.Цели, отмеченные любым из них, вводятся гораздо более изощренным способом.Однако, если ваши потребности достаточно ограничены, описанный выше метод может сработать для вас.

...