有没有什么方法可以实现像这样的自动 DTO 检索,但需要使用 sitebricks 服务。
我正在寻找以下解决方案:
@Post
public Reply<?> post(Request request) {
DTO dto = request.read(DTO.class).as(Json.class);
//some dto operations
.....
return Reply.saying().ok();
}
可以转换成这样的:
@Post
public Reply<?> post(@TransportedBy(Json.class) DTO dto) {
//some dto operations
.....
return Reply.saying().ok();
}
其中@TransoportedBy 是自定义注释。
使用这样的技术测试会容易得多,因为我不需要模拟请求并期望它的调用。
..........更新..........
在这个阶段,我已经设法实现了一些类似的东西:
@Post
@TransportedBy(Json.class)//any transport can be used
public Reply<?> post(Request request, @Named("DTO") SomeDto dto) {
//dto must be annotated with @Named("DTO")
//some dto operations
.....
return Reply.saying().ok();
}
我的实现是这样的,但我对此并不满意。
注释
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD})
@BindingAnnotation
public @interface TransportedBy {
Class value();
}
监听 post 方法的方法拦截器
public class DtoTransportInterceptor implements MethodInterceptor{
@Override
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
Object[] arguments = methodInvocation.getArguments();
Method method = methodInvocation.getMethod();
Annotation[] declaredAnnotations = method.getDeclaredAnnotations();
//retrieve the request
Request request = null;
for(Object argument : arguments){
if(argument instanceof Request){
request = (Request) argument;
break;
}
}
if (request == null) {
return methodInvocation.proceed();
}
//find transport type
Class transport = null;
for(Annotation annotation : declaredAnnotations){
if(annotation instanceof TransportedBy){
Method m = annotation.getClass().getMethod("value");
transport = (Class) m.invoke(annotation);
break;
}
}
if (transport == null){
return methodInvocation.proceed();
}
//get the class type of the dto
Class dtoClass = null;
Annotation[][] parametersAnnotations = method.getParameterAnnotations();//all annotations for all parameters
int dtoParameterId = 0;
int parameterId = -1;
for (Annotation[] paramAnnotations : parametersAnnotations){//iterate all parameters and return all annotations for the parameter
parameterId++;
for(Annotation annotation : paramAnnotations){//iterate all annotations for a single parameter
if(annotation instanceof Named){
Method m = annotation.getClass().getMethod("value");
String namedValue = (String) m.invoke(annotation);
if("DTO".equals(namedValue)){
dtoClass = method.getParameterTypes()[parameterId];
dtoParameterId = parameterId;
}
}
}
}
if(dtoClass == null){
return methodInvocation.proceed();
}
//if the dto is null initialize it and call the method again with the initialized dto, if the dto is not null proceed the method
if (arguments[dtoParameterId] == null) {
return method.invoke(methodInvocation.getThis(), request, request.read(dtoClass).as(transport));
} else {
return methodInvocation.proceed();
}
}
}
绑定拦截器以侦听 guice 模块中的 post 方法,如下所示
DtoTransportInterceptor dtoTransportInterceptor = new DtoTransportInterceptor();
bindInterceptor(any(), annotatedWith(Post.class), dtoTransportInterceptor);
由于 guice 方法拦截器不支持注入,因此请求对象仍需要传递给 post 方法并在拦截器内通过反射检索。
这个解决方案并不令人满意,因为我们仍然必须在测试中模拟请求并将其传递给 post 方法。至少我们不必期望在检索 dto 的每个测试中调用“request.read(....)”。
我愿意接受其他解决方案。