java - 每个端点的 @QueryParam 的自定义 JAX-RS 序列化器和反序列化器
问题描述
我有一些 REST 端点必须接收SecretData
类参数,例如:
@GET
@Path(/*...*/)
public someInternalService(@QueryParam("data") SecretData outLittleSecret) {/*...*/}
@GET
@Path(/*...*/)
public someExternalService(@QueryParam("opaque") SecretData outLittleSecret) {/*...*/}
现在,鉴于它SecretData
传达了一些非公开信息,我希望在它来自外部来源(通过该特定端点someExternalService
)时对其进行加密。
密码程序不是这里的重点。关键是我对同一类数据有 2 种表示形式。
我不能 staticvalueOf()
或fromString()
在 class 中实现SecretData
,因为这也会影响另一个端点。
如何为SecretData
仅适用于someExternalService
端点的类提供自定义编组器?
解决方案
如何为仅适用于 someExternalService 端点的 SecretData 类提供自定义编组器?
好吧,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 实现,您可以定义一个可自定义的字符串序列化器......请参阅StringConverter
注意 3 :检查 restEasy 文档,JAX-RS 2.0确实包含一种创建自定义序列化程序的方法...请参阅ParamConverter ...在此策略下,您将需要创建两个 ParamConverters (一个用于 plain SecretData
,一个用于 opaque SecretData
);和 ParameterConverter 工厂(接口的实现ParamConverterProvider
)......如果你检查接口文档,接口只公开一个方法,并且这种方法接收应用于要(反)序列化的参数的注释......所以,你会收到(我认为)类似:@QueryParam("data")
或者@QueryParam("opaque")
基于这些值,您可以相应地创建 ParameterConverter !
推荐阅读
- php - 某些 PHP 版本的“未指定输入文件”
- delphi - 如何在 Delphi 10.3.3 中访问 TWebBrowser.Document 时克服内存泄漏
- javascript - onChange 对象在 React 中的状态
- android - 用户池错误:请输入有效的客户端 ID、客户端密码或启用的范围
- java - Spring Boot App + H2(在内存中)不适用于 Docker 容器
- amazon-web-services - 哪个 AWS S3 API 操作将触发哪个事件类型?
- javascript - PHP:将帖子值传递给函数
- java - 菜鸟 Java 问题 - 扫描仪、整数和用户输入
- python - 如何根据两个不同数据框中的匹配值创建新列?
- python - 安装boto3时出现访问错误