JAX-RS @*Param
注释,包括 @QueryParam
、@MatrixParam
、@HeaderParam
、@Path
Param 和 @FormParam
,以原始 HTTP 请求中的字符串表示。如果这些对象具有 valueOf(String)
静态方法或采用一个 String
参数的构造器,这些注入的参数可转换为对象。
如果您有一个类,其中 valueOf()
方法或字符串构造器不存在或不适合 HTTP 请求,JAX-RS 提供了 javax.ws.rs.ext.ParamConverterProvider
和 javax.ws.rs.ext.ParamConverter
,以帮助将消息参数值转换为对应的自定义 Java 类型。ParamConverterProvider
必须在 JAX-RS 运行时以编程方式注册,并且必须标上 @Provider
注释,以便在提供程序扫描阶段由 JAX-RS 运行时自动发现。
例如:以下步骤演示了如何创建自定义 POJO 对象。从消息参数值(如 @QueryParam
、@PathParam
、@MatrixParam
、@HeaderParam
转换为 POJO 对象的转换是通过实施 ParamConverter
Provider
接口实现的。
创建自定义 POJO 类。
public class POJO {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class POJO {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Copy to Clipboard
Copied!
Toggle word wrap
Toggle overflow
创建自定义 POJO Converter 类。
public class POJOConverter implements ParamConverter<POJO> {
public POJO fromString(String str) {
System.out.println("FROM STRNG: " + str);
POJO pojo = new POJO();
pojo.setName(str);
return pojo;
}
public String toString(POJO value) {
return value.getName();
}
}
public class POJOConverter implements ParamConverter<POJO> {
public POJO fromString(String str) {
System.out.println("FROM STRNG: " + str);
POJO pojo = new POJO();
pojo.setName(str);
return pojo;
}
public String toString(POJO value) {
return value.getName();
}
}
Copy to Clipboard
Copied!
Toggle word wrap
Toggle overflow
创建自定义 POJO Converter Provider 类。
public class POJOConverterProvider implements ParamConverterProvider {
@Override
public <T> ParamConverter<T> getConverter(Class<T> rawType, Type genericType, Annotation[] annotations) {
if (!POJO.class.equals(rawType)) return null;
return (ParamConverter<T>)new POJOConverter();
}
}
public class POJOConverterProvider implements ParamConverterProvider {
@Override
public <T> ParamConverter<T> getConverter(Class<T> rawType, Type genericType, Annotation[] annotations) {
if (!POJO.class.equals(rawType)) return null;
return (ParamConverter<T>)new POJOConverter();
}
}
Copy to Clipboard
Copied!
Toggle word wrap
Toggle overflow
创建自定义 MyResource 类。
@Path("/")
public class MyResource {
@Path("{pojo}")
@PUT
public void put(@QueryParam("pojo") POJO q, @PathParam("pojo") POJO pp, @MatrixParam("pojo") POJO mp,
@HeaderParam("pojo") POJO hp) {
...
}
}
@Path("/")
public class MyResource {
@Path("{pojo}")
@PUT
public void put(@QueryParam("pojo") POJO q, @PathParam("pojo") POJO pp, @MatrixParam("pojo") POJO mp,
@HeaderParam("pojo") POJO hp) {
...
}
}
Copy to Clipboard
Copied!
Toggle word wrap
Toggle overflow
扩展 ParamConverter 的功能
在 JAX-RS 语义中,ParamConverter
转换代表单个对象的单个字符串。RESTEasy 扩展语义,以允许 ParamConverter
解析多个对象的字符串表示,并生成 List<T>
、Set<T>
、Sorted Set<T>、
数组
或任何其他多值数据结构。
例如,请考虑以下资源:
@Path("queryParam")
public static class TestResource {
@GET
@Path("")
public Response conversion(@QueryParam("q") List<String> list) {
return Response.ok(stringify(list)).build();
}
}
private static <T> String stringify(List<T> list) {
StringBuffer sb = new StringBuffer();
for (T s : list) {
sb.append(s).append(',');
}
return sb.toString();
}
@Path("queryParam")
public static class TestResource {
@GET
@Path("")
public Response conversion(@QueryParam("q") List<String> list) {
return Response.ok(stringify(list)).build();
}
}
private static <T> String stringify(List<T> list) {
StringBuffer sb = new StringBuffer();
for (T s : list) {
sb.append(s).append(',');
}
return sb.toString();
}
Copy to Clipboard
Copied!
Toggle word wrap
Toggle overflow
按照如下所示调用 TestResource
,使用标准表示法:
@Test
public void testQueryParamStandard() throws Exception {
ResteasyClient client = new ResteasyClientBuilder().build();
Invocation.Builder request = client.target("http://localhost:8081/queryParam?q=20161217&q=20161218&q=20161219").request();
Response response = request.get();
System.out.println("response: " + response.readEntity(String.class));
}
@Test
public void testQueryParamStandard() throws Exception {
ResteasyClient client = new ResteasyClientBuilder().build();
Invocation.Builder request = client.target("http://localhost:8081/queryParam?q=20161217&q=20161218&q=20161219").request();
Response response = request.get();
System.out.println("response: " + response.readEntity(String.class));
}
Copy to Clipboard
Copied!
Toggle word wrap
Toggle overflow
结果结果 :20161217,20161218,20161219.
如果要使用用逗号分开的表示法,您可以添加:
public static class MultiValuedParamConverterProvider implements ParamConverterProvider
@SuppressWarnings("unchecked")
@Override
public <T> ParamConverter<T> getConverter(Class<T> rawType, Type genericType, Annotation[] annotations) {
if (List.class.isAssignableFrom(rawType)) {
return (ParamConverter<T>) new MultiValuedParamConverter();
}
return null;
}
}
public static class MultiValuedParamConverter implements ParamConverter<List<?>> {
@Override
public List<?> fromString(String param) {
if (param == null || param.trim().isEmpty()) {
return null;
}
return parse(param.split(","));
}
@Override
public String toString(List<?> list) {
if (list == null || list.isEmpty()) {
return null;
}
return stringify(list);
}
private static List<String> parse(String[] params) {
List<String> list = new ArrayList<String>();
for (String param : params) {
list.add(param);
}
return list;
}
}
public static class MultiValuedParamConverterProvider implements ParamConverterProvider
@SuppressWarnings("unchecked")
@Override
public <T> ParamConverter<T> getConverter(Class<T> rawType, Type genericType, Annotation[] annotations) {
if (List.class.isAssignableFrom(rawType)) {
return (ParamConverter<T>) new MultiValuedParamConverter();
}
return null;
}
}
public static class MultiValuedParamConverter implements ParamConverter<List<?>> {
@Override
public List<?> fromString(String param) {
if (param == null || param.trim().isEmpty()) {
return null;
}
return parse(param.split(","));
}
@Override
public String toString(List<?> list) {
if (list == null || list.isEmpty()) {
return null;
}
return stringify(list);
}
private static List<String> parse(String[] params) {
List<String> list = new ArrayList<String>();
for (String param : params) {
list.add(param);
}
return list;
}
}
Copy to Clipboard
Copied!
Toggle word wrap
Toggle overflow
现在,您可以按如下方式调用 TestResource
:
@Test
public void testQueryParamCustom() throws Exception {
ResteasyClient client = new ResteasyClientBuilder().build();
Invocation.Builder request = client.target("http://localhost:8081/queryParam?q=20161217,20161218,20161219").request();
Response response = request.get();
System.out.println("response: " + response.readEntity(String.class));
}
@Test
public void testQueryParamCustom() throws Exception {
ResteasyClient client = new ResteasyClientBuilder().build();
Invocation.Builder request = client.target("http://localhost:8081/queryParam?q=20161217,20161218,20161219").request();
Response response = request.get();
System.out.println("response: " + response.readEntity(String.class));
}
Copy to Clipboard
Copied!
Toggle word wrap
Toggle overflow
获得 回复:20161217,20161218,20161219.
在本例中,MultiValuedParamConverter.fromString()
函数会创建并返回 aArrayList
,以便可以重写 TestResource.conversion()
功能:
@Path("queryParam")
public static class TestResource {
@GET
@Path("")
public Response conversion(@QueryParam("q") ArrayList<String> list) {
return Response.ok(stringify(list)).build();
}
}
@Path("queryParam")
public static class TestResource {
@GET
@Path("")
public Response conversion(@QueryParam("q") ArrayList<String> list) {
return Response.ok(stringify(list)).build();
}
}
Copy to Clipboard
Copied!
Toggle word wrap
Toggle overflow
另外,还可重写 MultiValuedParamConverter
以返回 LinkList
,TestResource.conversion()中的
参数列表可以是 List
或 LinkedList
。
最后,请注意,此扩展也适用于数组。例如,
public static class Foo {
private String foo;
public Foo(String foo) {
this.foo = foo;
}
public String getFoo() {
return foo;
}
}
public static class FooArrayParamConverter implements ParamConverter < Foo[] > {
@Override
public Foo[] fromString(String value) {
String[] ss = value.split(",");
Foo[] fs = new Foo[ss.length];
int i = 0;
for (String s: ss) {
fs[i++] = new Foo(s);
}
return fs;
}
@Override
public String toString(Foo[] values) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < values.length; i++) {
sb.append(values[i].getFoo()).append(",");
}
if (sb.length() > 0) {
sb.deleteCharAt(sb.length() - 1);
}
return sb.toString();
}
}
@Provider
public static class FooArrayParamConverterProvider implements ParamConverterProvider {
@SuppressWarnings("unchecked")
@Override
public < T > ParamConverter < T > getConverter(Class < T > rawType, Type genericType, Annotation[] annotations) {
if (rawType.equals(Foo[].class));
return (ParamConverter < T > ) new FooArrayParamConverter();
}
}
@Path("")
public static class ParamConverterResource {
@GET
@Path("test")
public Response test(@QueryParam("foos") Foo[] foos) {
return Response.ok(new FooArrayParamConverter().toString(foos)).build();
}
}
public static class Foo {
private String foo;
public Foo(String foo) {
this.foo = foo;
}
public String getFoo() {
return foo;
}
}
public static class FooArrayParamConverter implements ParamConverter < Foo[] > {
@Override
public Foo[] fromString(String value) {
String[] ss = value.split(",");
Foo[] fs = new Foo[ss.length];
int i = 0;
for (String s: ss) {
fs[i++] = new Foo(s);
}
return fs;
}
@Override
public String toString(Foo[] values) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < values.length; i++) {
sb.append(values[i].getFoo()).append(",");
}
if (sb.length() > 0) {
sb.deleteCharAt(sb.length() - 1);
}
return sb.toString();
}
}
@Provider
public static class FooArrayParamConverterProvider implements ParamConverterProvider {
@SuppressWarnings("unchecked")
@Override
public < T > ParamConverter < T > getConverter(Class < T > rawType, Type genericType, Annotation[] annotations) {
if (rawType.equals(Foo[].class));
return (ParamConverter < T > ) new FooArrayParamConverter();
}
}
@Path("")
public static class ParamConverterResource {
@GET
@Path("test")
public Response test(@QueryParam("foos") Foo[] foos) {
return Response.ok(new FooArrayParamConverter().toString(foos)).build();
}
}
Copy to Clipboard
Copied!
Toggle word wrap
Toggle overflow
java.util.Optional
Parameter Types
RESTEasy 提供了多种额外的 java.util.Optional
参数类型。这些参数类型充当打包程序对象类型。它们允许用户输入可选类型参数,并使用 Optional.orElse()
等方法取消所有 null 检查。
@Path("/double")
@GET
public String optDouble(@QueryParam("value") OptionalDouble value) {
return Double.toString(value.orElse(4242.0));
}
@Path("/double")
@GET
public String optDouble(@QueryParam("value") OptionalDouble value) {
return Double.toString(value.orElse(4242.0));
}
Copy to Clipboard
Copied!
Toggle word wrap
Toggle overflow
上例演示了 OptionalDouble
可用作参数类型。如果 @QueryParam
中未提供值,则将返回默认值。以下参数类型支持可选参数:
-
@QueryParam
-
@MatrixParam
-
@FormParam
-
@HeaderParam
-
@CookieParam