@QueryParam如何将没有值的参数转换为布尔值"false"?

lat*_*ell 8 java jax-rs

我想使用像一个URL http://www.example.com/rest/foo?bar,其中bar查询参数没有价值,它的单独存在应表示变量是否truefalse.

目前,缺失值假定为""(空)并传递给new Boolean()它,将其视为false.

是否有更优雅的方式来定义它而不是将参数声明为String并自行转换它?

像一个类javax.rs.BooleanFlag或类似的?

Pho*_*ste 9

我知道这是一个老问题,但我遇到了同样的麻烦.

为了解决我的问题,我使用了Annotation @DefaultValue:

@GET
@Path("/path")
public Response myMethod(@DefaultValue("true") @QueryParam("foo") boolean foo) {
    if (foo) {
       ...
    }
}
Run Code Online (Sandbox Code Playgroud)

因此,当请求包含参数时foo,布尔值将为false,否则将为true.它显示了与现实相反的情况,但如果你意识到它,它的使用起来非常简单.


Pau*_*tha 8

注意:在看到Phoste的答案后,我会选择他/她的解决方案.我正在离开这个答案,因为这里仍然有一些有用的信息.

是否有更优雅的方式来定义它而不是将参数声明为String并自行转换它?像一个类javax.rs.BooleanFlag或类似的?

没有这样的类型(BooleanFlag),如果你查看@QueryParamjavadoc,你会看到一个选项列表,我们可以创建一个自定义类型来使用一个@QueryParam值(大多数情况下,同样适用于其他的@XxxParams)

  • 有一个接受单个String参数的构造函数
  • 有一个static名为valueOffromString接受单个String参数的方法(例如,参见Integer.valueOf(String))
  • 有一个ParamConverterProviderJAX-RS扩展SPI 的注册实现,它返回一个ParamConverter能够为该类型进行"from string"转换的实例.

所以从理论上讲,从第一个选项开始,你应该可以做类似的事情

public class Flag {

    private final boolean  isPresent;
    public Flag(String param) { isPresent = param != null; }
    public boolean isPresent() { return isPresent; }
}
Run Code Online (Sandbox Code Playgroud)
@GET
public String get(@QueryParam("bar") Flag bar) {
    if (bar.isPresent()) {
        return "bar is present";
    } else {
        return "bar is not present";
    }
}
Run Code Online (Sandbox Code Playgroud)

现在这在查询标志存在时有效.但是当它不是时,它就像任何其他非原始类型一样; 它是空的.所以打电话bar.isPresent给NPE.用a测试fromStringvalueOf得到相同的结果.我们可以检查if (bar == null),但仅仅使用String并检查String是否为null并不是更好.它不漂亮.

所以最后一个选项是ParamConverterProvider.哪个确实有效.以下是实施.

import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import javax.ws.rs.ext.ParamConverter;
import javax.ws.rs.ext.ParamConverterProvider;
import javax.ws.rs.ext.Provider;

@Provider
public class FlagParamConverterProvider implements ParamConverterProvider {

    @Override
    public <T> ParamConverter<T> getConverter(
            Class<T> rawType, Type genericType, Annotation[] annotations) {
        if (rawType != Flag.class) {
            return null;
        }

        return new ParamConverter<T>() {

            @Override
            public T fromString(String value) {
                return (T)new Flag(value);
            }

            @Override
            public String toString(T value) { return null; } 
        };
    }  
}
Run Code Online (Sandbox Code Playgroud)

只需确保提供商已注册.在我看来,这是一个非常干净的解决方案.


cas*_*lin 5

您可以尝试以下方法:

@GET
@Path("/some-path")
public Response myMethod(@Context HttpServletRequest request) {

    boolean isParameterPresent = request.getParameterMap().contains("bar");

    ...
}
Run Code Online (Sandbox Code Playgroud)

peeskillet回答中显示的解决方案是实现它的最聪明的方法.