在 Jersey 中,我可以将 QueryParams 和 FormParams 合并为一个方法的一个值吗?

发布于 2024-12-23 20:03:41 字数 1049 浏览 0 评论 0原文

我有一个类似的函数:

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

我希望“名称”参数来自表单或来自查询参数。如果用户发布到 /playlist/create/?name=bob 那么我希望它能够工作。 (这主要是为了帮助测试 API,但也为了在不同的非浏览器平台上使用它。)

我愿意对使魔术绑定起作用的任何内容进行子类化... (@BothParam("name") String name )但需要一些帮助才能实现这一点,因为我是 Jersey/Java Servlet 的新手。


更新:第二天...

我通过实现 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);
    }
}

我仍然很高兴知道是否有更好的方法来做到这一点,所以我暂时保留这个问题。

I've got a function like:

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

I want the "name" parameter to come from the form OR from the query parameter. If the user posts to /playlist/create/?name=bob then I want it to work. (This is mostly to aid with testing the API, but also for consuming it on different non-browser platforms.)

I'd be willing to subclass whatever makes the magic binding work... (@BothParam("name") String name) but would need some help to make that happen as I'm new to Jersey/Java Servlets.


Update: The next day...

I've solved this by implementing a ContainerRequestFilter that merges the form parameters into the query parameters. This isn't the best solution, but it does seem to work. I didn't have any luck merging anything into the form parameters.

Here's the code in case someone comes looking for it:

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

I would still appreciate knowing if there is a better way to do this so I'll leave this question open for now.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

爱*していゐ 2024-12-30 20:03:41

实现此目的的一种方法是使用 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表单参数。用其中任何一个注释的目标都会以更复杂的方式注入。但是,如果您的需求足够有限,上述方法可能适合您。

One way you could do this is with an InjectableProvider.

First, you'd define a BothParam annotation:

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

Then, define an InjectableProvider for it:

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

Note, this is not truly a coupling of QueryParam and FormParam. Targets annotated with either of those are injected in a much more sophisticated manner. However, if your needs are sufficiently limited, the method outlined above might work for you.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文