在 Play Framework 中组合动作时重复相同的动作
Repeating the same action when composition actions in Play Framework
我正在使用 Play Framework 开发服务器。在我的几个方法中,我需要执行一些先前的操作(基本上是输入检查),所以我认为最好的方法是 Action Composition.
我可以毫无问题地使用多个注释
@Action1 // <---------------------------------------- This action is executed
@Action2(value = "someValue") // <------------------- This action is executed
public CompletionStage<Result> doSomething() {
...
}
但是当我尝试重复这些操作之一时,具体操作不会执行:
@Action1 // <---------------------------------------- This action is executed
@Action2(value = "someValue") // <------------------- This action is not executed
@Action2(value = "someOtherValue") // <-------------- This action is not executed
public CompletionStage<Result> doSomething() {
...
}
我的 Action1
注释看起来像 Play Framework example 的 VerboseAnnotation
所以我认为不值得写在这里。由于我的 Action2
注释可以重复,所以我声明了一个 RepeatableAction2
注释,如下所示:
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface RepeatableAction2 {
Action2[] value() default {};
}
和 Action2
看起来像这样:
@With(Action2Impl.class)
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(value = RepeatableAction2.class)
public @interface Action2 {
String value();
}
该方法已正确注释。当我添加:
for (Method m : Application.class.getDeclaredMethods()) {
RequiredJsonValues reqs = m.getAnnotation(RequiredJsonValues.class);
for (RequiredJsonValue req : reqs.value()) {
System.out.println("Method: " + m + " annotation: " + req);
}
}
在我得到的方法的开头
Method: public java.util.concurrent.CompletionStage controllers.SomeController.doSomething() annotation: @util.Action2(value=someValue)
Method: public java.util.concurrent.CompletionStage controllers.SomeController.doSomething() annotation: @util.Action2(value=someOtherValue)
那我做错了什么?有没有其他方法可以用不同的值多次链接相同的操作?
终于成功了
As Explained in here Java 8 编译器不需要编写 RepeatableAction2
但它会在编译时添加它,因此我需要为该注释添加一个实现:
@With(RepeatableAction2Impl.class)
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface RepeatableAction2 {
Action2[] value() default {};
}
并且在实现中我手动链接所有操作:
public class RepeatableAction2Impl extends Action<RepeatableAction2> {
@Override
public CompletionStage<Result> call(Http.Context ctx) {
if (configuration.value().length > 0) {
int actions = configuration.value().length;
List<Action<Action2>> actionList = new ArrayList<>();
// Create actions
for (int i = 0; i < actions; i++) {
Action2Impl action2Impl = new Action2Impl();
action2Impl.configuration = configuration.value()[i];
actionList.add(action2Impl);
}
// Chaining
actionList.get(actions - 1).delegate = delegate;
for (int i = 0; i < actions - 1; i++) {
actionList.get(i).delegate = actionList.get(i + 1);
}
// Delegate the work to actions
return actionList.get(0).call(ctx);
} else {
return delegate.call(ctx);
}
}
}
虽然这是一个可行的解决方案,但对我来说还是有点难看。还有其他我想念的方法吗?
我正在使用 Play Framework 开发服务器。在我的几个方法中,我需要执行一些先前的操作(基本上是输入检查),所以我认为最好的方法是 Action Composition.
我可以毫无问题地使用多个注释
@Action1 // <---------------------------------------- This action is executed
@Action2(value = "someValue") // <------------------- This action is executed
public CompletionStage<Result> doSomething() {
...
}
但是当我尝试重复这些操作之一时,具体操作不会执行:
@Action1 // <---------------------------------------- This action is executed
@Action2(value = "someValue") // <------------------- This action is not executed
@Action2(value = "someOtherValue") // <-------------- This action is not executed
public CompletionStage<Result> doSomething() {
...
}
我的 Action1
注释看起来像 Play Framework example 的 VerboseAnnotation
所以我认为不值得写在这里。由于我的 Action2
注释可以重复,所以我声明了一个 RepeatableAction2
注释,如下所示:
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface RepeatableAction2 {
Action2[] value() default {};
}
和 Action2
看起来像这样:
@With(Action2Impl.class)
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(value = RepeatableAction2.class)
public @interface Action2 {
String value();
}
该方法已正确注释。当我添加:
for (Method m : Application.class.getDeclaredMethods()) {
RequiredJsonValues reqs = m.getAnnotation(RequiredJsonValues.class);
for (RequiredJsonValue req : reqs.value()) {
System.out.println("Method: " + m + " annotation: " + req);
}
}
在我得到的方法的开头
Method: public java.util.concurrent.CompletionStage controllers.SomeController.doSomething() annotation: @util.Action2(value=someValue)
Method: public java.util.concurrent.CompletionStage controllers.SomeController.doSomething() annotation: @util.Action2(value=someOtherValue)
那我做错了什么?有没有其他方法可以用不同的值多次链接相同的操作?
终于成功了
As Explained in here Java 8 编译器不需要编写 RepeatableAction2
但它会在编译时添加它,因此我需要为该注释添加一个实现:
@With(RepeatableAction2Impl.class)
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface RepeatableAction2 {
Action2[] value() default {};
}
并且在实现中我手动链接所有操作:
public class RepeatableAction2Impl extends Action<RepeatableAction2> {
@Override
public CompletionStage<Result> call(Http.Context ctx) {
if (configuration.value().length > 0) {
int actions = configuration.value().length;
List<Action<Action2>> actionList = new ArrayList<>();
// Create actions
for (int i = 0; i < actions; i++) {
Action2Impl action2Impl = new Action2Impl();
action2Impl.configuration = configuration.value()[i];
actionList.add(action2Impl);
}
// Chaining
actionList.get(actions - 1).delegate = delegate;
for (int i = 0; i < actions - 1; i++) {
actionList.get(i).delegate = actionList.get(i + 1);
}
// Delegate the work to actions
return actionList.get(0).call(ctx);
} else {
return delegate.call(ctx);
}
}
}
虽然这是一个可行的解决方案,但对我来说还是有点难看。还有其他我想念的方法吗?