47.3. 参数转换器


概述

使用参数转换器,可以将参数(字符串类型)注入 任何类型的 字段、bean 属性或资源方法参数。通过实施和绑定合适的参数转换器,您可以扩展 JAX-RS 运行时,使其能够将参数 String 值转换为目标类型。

自动转换

参数作为 String 的实例接收,因此始终可以将它们直接注入 String 类型的字段、bean 属性和方法参数。此外,JAX-RS 运行时具有将参数字符串自动转换为以下类型的功能:

  1. 原语类型。
  2. 具有接受单个 String 参数的构造器的类型。
  3. 具有名为 valueOffromString 的静态方法的类型,它带有一个 String 参数,该参数返回一个类型实例。
  4. 如果 T 是 2 或 3 中描述的类型之一,则列出 <T >、Set< T > 或 SortedSet <T>。

参数转换器

要将参数注入没有由自动转换涵盖的类型,您可以为 类型定义自定义参数转换器。参数转换器是 JAX-RS 扩展,允许您定义从 String 到自定义类型的转换,以及从自定义类型到 String 的反向方向。

工厂模式

JAX-RS 参数转换器机制使用工厂模式。因此,您可以按需注册参数转换器提供程序(类型为 javax.ws.rs.ext.ParamConverterProvider),而不是直接注册参数转换器(类型为 javax.ws.rs.ext.ParamConverterProvider)。

ParamConverter 接口

javax.ws.rs.ext.ParamConverter 接口定义如下:

// Java
package javax.ws.rs.ext;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import javax.ws.rs.DefaultValue;

public interface ParamConverter<T> {

    @Target({ElementType.TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public static @interface Lazy {}

    public T fromString(String value);

    public String toString(T value);
}

要实现自己的 ParamConverter 类,您必须实施这个接口,覆盖 fromString 方法(将参数字符串转换为目标类型)和 toString 方法(将目标类型转换为字符串)。

ParamConverterProvider 接口

javax.ws.rs.ext.ParamConverterProvider 接口定义如下:

// Java
package javax.ws.rs.ext;

import java.lang.annotation.Annotation;
import java.lang.reflect.Type;

public interface ParamConverterProvider {
    public <T> ParamConverter<T> getConverter(Class<T> rawType, Type genericType, Annotation annotations[]);
}

要实现自己的 ParamConverterProvider 类,您必须实现这个接口,覆盖 getConverter 方法,这是创建 ParamConverter 实例的 factory 方法。

绑定参数转换器供应商

要将参数转换器提供程序 绑定到 JAX-RS 运行时(使其可用于应用程序),您必须使用 @Provider 注释给您的实施类添加注解,如下所示:

// Java
...
import javax.ws.rs.ext.ParamConverterProvider;
import javax.ws.rs.ext.Provider;

@Provider
public class TargetTypeProvider implements ParamConverterProvider {
    ...
}

此注解可确保在部署的扫描阶段自动注册参数转换器供应商。

示例

以下示例演示了如何实现 ParamConverterProvider 和一个 ParamConverter,它能够将参数字符串转换为 TargetType 类型:

// Java
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 TargetTypeProvider implements ParamConverterProvider {

    @Override
    public <T> ParamConverter<T> getConverter(
        Class<T> rawType,
        Type genericType,
        Annotation[] annotations
    ) {
        if (rawType.getName().equals(TargetType.class.getName())) {
            return new ParamConverter<T>() {

                @Override
                public T fromString(String value) {
                    // Perform conversion of value
                    // ...
                    TargetType convertedValue = // ... ;
                    return convertedValue;
                }

                @Override
                public String toString(T value) {
                    if (value == null) { return null; }
                    // Assuming that TargetType.toString is defined
                    return value.toString();
                }
            };
        }
        return null;
    }

}

使用参数转换器

现在,您为 TargetType 定义了参数转换器,现在可以直接将参数注入 TargetType 字段和参数,例如:

// Java
import javax.ws.rs.FormParam;
import javax.ws.rs.POST;
...
@POST
public Response updatePost(@FormParam("target") TargetType target)
{
  ...
}

默认值的 lazy 转换

如果您为参数指定默认值(使用 @DefaultValue 注释),您可以选择默认值是否立即转换为目标类型(默认行为),或者是否仅在需要时转换默认值(延迟转换)。要选择 lazy 转换,请将 @ParamConverter.Lazy 注释添加到目标类型。例如:

// Java
import javax.ws.rs.FormParam;
import javax.ws.rs.POST;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.ext.ParamConverter.Lazy;
...
@POST
public Response updatePost(
    @FormParam("target")
    @DefaultValue("default val")
    @ParamConverter.Lazy
    TargetType target)
{
  ...
}
Red Hat logoGithubRedditYoutubeTwitter

学习

尝试、购买和销售

社区

关于红帽文档

通过我们的产品和服务,以及可以信赖的内容,帮助红帽用户创新并实现他们的目标。

让开源更具包容性

红帽致力于替换我们的代码、文档和 Web 属性中存在问题的语言。欲了解更多详情,请参阅红帽博客.

關於紅帽

我们提供强化的解决方案,使企业能够更轻松地跨平台和环境(从核心数据中心到网络边缘)工作。

© 2024 Red Hat, Inc.