每个端点@QueryParam的自定义JAX-RS序列化器和反序列化器

时间:2019-01-11 19:31:48

标签: java jax-rs deserialization unmarshalling

我有一些REST端点必须接收SecretData类的参数,例如:

@GET
@Path(/*...*/)
public someInternalService(@QueryParam("data") SecretData outLittleSecret) {/*...*/}

@GET
@Path(/*...*/)
public someExternalService(@QueryParam("opaque") SecretData outLittleSecret) {/*...*/}

现在,鉴于SecretData传达了一些非公开信息,当我从外部来源(通过特定端点someExternalService)获得非公开信息时,我想对其进行加密。

此处的加密过程不是重点。 关键是我对相同类别的数据有2种表示形式。

我不能在类valueOf()中实现静态fromString()SecretData,因为这也会影响另一个端点。

如何为SecretData类提供仅适用于someExternalService端点的自定义编组器?

1 个答案:

答案 0 :(得分:1)

  

如何为SecretData类提供仅适用于someExternalService端点的自定义编组器?

好吧,AFAIK,您做不到(请参阅注释3)。但是您可以使用关注点分离并创建API的分层设计来解决您的问题...让我解释一下...

假定Data是您的主对象(现在称为“普通” SecretData),它包含内部(或外部)服务要传输的信息...

public class Data {
    protected int attribA;
    ...
    protected String attribN;

    public static Data valueOf(String data) {
        // here, you transform the string and set
        // the corresponding attributes values
    }
}

然后,您可以这样定义一个端点:

@GET
@Path(/*...*/)
public someInternalService(@QueryParam("data") Data data) {/*...*/}

现在,对于外部服务,您将创建一个新的POJO(“关注点分离”),如下所示:

public class EncryptedData extends Data {
    // any attribute is inherited from data
    // this class does not expose new attributes

    /**
     * Copy constructor.
     */
    EncryptedData(Data data) {
        super();
        this.attribA = data.attribA;
        ...
    };

    public static EncryptedData valueOf(String opaque) {
        // here, you transform the encrypted String into
        // a regular String, then you call Data.valueOf ...
        // example:
        String decrypted = decrypt(opaque);
        return new EncryptedData( Data.valueOf(decrypted) );
    }
}

然后,您的外部服务端点将如下所示:

@GET
@Path(/*...*/)
public someExternalService(@QueryParam("opaque") EncryptedData data) {/*...*/}

注意::由于EncryptedData IS_A Data实例,您可以将该对象传递给接收Data实例作为输入的任何其他方法!因此,您不需要进行任何其他转换...

注意2::显然,如果您将RestEasy用作JAXRS实现,则可以定义可自定义的String序列化程序...请参见StringConverter

注意3::检查restEasy文档, JAX-RS 2.0 确实包含一种创建自定义序列化器的方法...请参见ParamConverter ...在使用此策略,您将需要创建两个ParamConverters(一个用于普通SecretData,一个用于不透明SecretData);和ParameterConverter Factory(接口ParamConverterProvider的实现)...如果您检查接口文档,则该接口仅公开一种方法,并且该方法接收应用于要(反)序列化的参数的注释...因此,您会收到(我认为)类似的内容:@QueryParam("data")@QueryParam("opaque"),并根据这些值可以相应地创建ParameterConverter!