代码之家  ›  专栏  ›  技术社区  ›  rslemos

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

  •  1
  • rslemos  · 技术社区  · 6 年前

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

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

    现在,鉴于 分泌数据 传递一些非公开信息,当它来自外部源(通过特定的端点)时,我希望对其进行加密 someExternalService )

    加密过程不是这里的重点。 重点是,对于同一类数据,我有两种表示。

    我不能有静电 valueOf() fromString() 在课堂上实施 分泌数据 ,因为这也会影响另一个端点。

    我如何为 分泌数据 仅适用于 一些外部服务 端点?

    1 回复  |  直到 6 年前
        1
  •  1
  •   Carlitos Way    6 年前

    如何为仅适用于someExternalservice端点的secretdata类提供自定义封送拆收器?

    嗯,阿法克,你不能(见注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 伊斯塔 数据 实例,可以将此类对象传递给接收 数据 实例作为输入!所以,您不需要进行任何其他转换…

    注2: 显然,如果您使用resteasy作为JAXRS实现,那么您可以定义一个可定制的字符串序列化程序…看见 StringConverter

    注3: 检查RestEasy文档, JAX-RS 2 不包含创建自定义序列化程序的方法…看见 ParamConverter …在这个策略下,您需要创建两个paramconverter(一个用于plain 分泌数据 一个是不透明的 分泌数据 );和参数转换器工厂(接口的实现 ParamConverterProvider )如果检查接口文档,则该接口只公开一个方法,并且该方法接收应用于要(反)序列化的参数的注释…因此,您将收到(我认为)如下内容: @QueryParam("data") @QueryParam("opaque") 根据这些值,您可以相应地创建参数转换器!