我有一些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
类提供自定义编组器? 最佳答案
如何为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!