gpt4 book ai didi

java - 我们可以传递方法参数的值和注释吗

转载 作者:行者123 更新时间:2023-12-02 01:12:31 25 4
gpt4 key购买 nike

为了管理 swagger 文档,我对调用 API 的方法使用自定义注释

@SwagRef(method = POST, url = "/my/api/{pathParam1}")
public Response callMyAPI(
@MyParam(name = "pathParam1", required = true, in = PATH) String p1,
@MyParam(name = "param2", required = false, in = QUERY) String p2) {
return given()
.pathParam("pathParam1", p1)
.queryParam("param2", p2)
.get();
}

有一段单独的代码可以验证 Swagger/api/docs 与注释。但是我想知道是否有可能以某种方式使用注释中已提供的所有数据,并有一个通用代码,我可以在其中传递方法引用或参数引用,并且可以使用注释构建 RequestSpecification。

我尝试使用反射,但无法使用方法中的反射获取参数值

我只能推断出方法类型和 API,因为它是使用 methodName 和 stackTrace 保持不变的

    private SwagRef defineSwaggerInfo() {
List<StackTraceElement> stackTrace = asList(currentThread().getStackTrace());
return stackTrace.stream()
.map(tryOrNull(element -> Pair.with(element.getMethodName(), forName(element.getClassName()))))
.filter(Objects::nonNull)
.filter(pair -> MyAPI.class.isAssignableFrom(pair.getValue1()))
.map(pair -> with(pair.getValue0(), asList(pair.getValue1().getDeclaredMethods())))
.flatMap(
tryOrNull(
pair ->
pair.getValue1().stream()
.filter(method -> Objects.equals(method.getName(), pair.getValue0()))
.peek(method -> method.setAccessible(true))
.map(method -> method.getAnnotation(SwagRef.class))))
.filter(Objects::nonNull)
.findFirst()
.orElseThrow();
}

但是我无法提出使用方法参数构建请求规范的通用函数

我尝试查看 AspectJ 但无法正确嵌入它

最佳答案

无法通过反射从堆栈中获取实际参数值。事实上,甚至不能保证正在进行的调用的参数值此时仍在堆栈上。

执行自动参数处理最接近的方法是在接口(interface)中声明方法并生成 proxy :

interface FrontEnd {
public static FrontEnd get() {
return (FrontEnd)Proxy.newProxyInstance(FrontEnd.class.getClassLoader(),
new Class<?>[]{FrontEnd.class}, (proxy, method, args) -> {
if(method.getDeclaringClass() == Object.class) {
switch(method.getName()) {
case "toString": return
FrontEnd.class.getName()+'@'+System.identityHashCode(proxy);
case "equals": return proxy == args[0];
case "hashCode": return System.identityHashCode(proxy);
default: throw new AssertionError();
}
}
SwagRef swagRef = method.getAnnotation(SwagRef.class);
if(swagRef == null) throw new IncompatibleClassChangeError();
MyParam[] p = Arrays.stream(method.getParameterAnnotations())
.map(pa -> Arrays.stream(pa)
.filter(a -> a.annotationType() == MyParam.class)
.findFirst().orElseThrow(
() -> new IllegalStateException("missing required @MyParam")))
.toArray(MyParam[]::new);
Map<String,String> map = IntStream.range(0, args.length).boxed()
.filter(i -> p[i].required() || args[i] != null)
.collect(Collectors.toMap(i -> p[i].name(), i -> args[i].toString()));
// do actual invocation logic here
System.out.println(
"operation: "+swagRef.method()+' '+swagRef.url()+", "+map);
return null;
});
}

@SwagRef(method = POST, url = "/my/api/{pathParam1}")
public Response callMyAPI(
@MyParam(name = "pathParam1", required = true, in = PATH) String p1,
@MyParam(name = "param2", required = false, in = QUERY) String p2);
}

您可以向该接口(interface)添加更多方法,以相同的方式进行处理,假设它们都有必要的注释。

从 Java 9 开始,您可以在接口(interface)中使用私有(private)方法,我在这里更喜欢这种方法。

interface FrontEnd {
public static FrontEnd get() {
return (FrontEnd)Proxy.newProxyInstance(FrontEnd.class.getClassLoader(),
new Class<?>[]{FrontEnd.class}, FrontEnd::callImpl);
}
@SwagRef(method = POST, url = "/my/api/{pathParam1}")
public Response callMyAPI(
@MyParam(name = "pathParam1", required = true, in = PATH) String p1,
@MyParam(name = "param2", required = false, in = QUERY) String p2);

private static Object callImpl(Object proxy, Method method, Object[] args) {
if(method.getDeclaringClass() == Object.class) {
switch(method.getName()) {
case "toString": return
FrontEnd.class.getName()+'@'+System.identityHashCode(proxy);
case "equals": return proxy == args[0];
case "hashCode": return System.identityHashCode(proxy);
default: throw new AssertionError();
}
}
SwagRef swagRef = method.getAnnotation(SwagRef.class);
if(swagRef == null) throw new IncompatibleClassChangeError();
MyParam[] p = Arrays.stream(method.getParameterAnnotations())
.map(pa -> Arrays.stream(pa)
.filter(a -> a.annotationType() == MyParam.class)
.findFirst().orElseThrow(
() -> new IllegalStateException("missing required @MyParam")))
.toArray(MyParam[]::new);
Map<String,String> map = IntStream.range(0, args.length).boxed()
.filter(i -> p[i].required() || args[i] != null)
.collect(Collectors.toMap(i -> p[i].name(), i -> args[i].toString()));
// do actual invocation logic here
System.out.println("operation: "+swagRef.method()+' '+swagRef.url()+", "+map);
return null;
}
}

或者,您可以将接口(interface)和辅助类(可能是非公共(public)的)之间的逻辑分开。

关于java - 我们可以传递方法参数的值和注释吗,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59161045/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com