diff --git a/src/main/java/org/redkale/net/http/Rest.java b/src/main/java/org/redkale/net/http/Rest.java index b13b98281..f046446ff 100644 --- a/src/main/java/org/redkale/net/http/Rest.java +++ b/src/main/java/org/redkale/net/http/Rest.java @@ -5,23 +5,20 @@ */ package org.redkale.net.http; -import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; -import static org.redkale.asm.ClassWriter.COMPUTE_FRAMES; -import static org.redkale.asm.Opcodes.*; -import static org.redkale.util.Utility.isEmpty; - import java.io.*; import java.lang.annotation.*; +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.reflect.*; import java.net.InetSocketAddress; import java.nio.channels.CompletionHandler; import java.util.*; import java.util.concurrent.CompletionStage; import org.redkale.annotation.*; -import org.redkale.annotation.ClassDepends; import org.redkale.annotation.Comment; import org.redkale.asm.*; +import static org.redkale.asm.ClassWriter.COMPUTE_FRAMES; +import static org.redkale.asm.Opcodes.*; import org.redkale.asm.Type; import org.redkale.convert.*; import org.redkale.convert.json.*; @@ -33,6 +30,7 @@ import org.redkale.service.*; import org.redkale.source.Flipper; import org.redkale.util.*; import org.redkale.util.RedkaleClassLoader.DynBytesClassLoader; +import static org.redkale.util.Utility.isEmpty; /** * 详情见: https://redkale.org @@ -1349,20 +1347,11 @@ public final class Rest { continue; } - RestMapping[] mappings = method.getAnnotationsByType(RestMapping.class); - if (!controller.autoMapping() && mappings.length < 1) { - continue; - } - boolean ignore = false; - for (RestMapping mapping : mappings) { - if (mapping.ignore()) { - ignore = true; - break; - } - } - if (ignore) { + List mappings = MappingAnn.paraseMappingAnns(controller, method); + if (mappings == null) { continue; } + java.lang.reflect.Type[] ptypes = TypeToken.getGenericType(method.getGenericParameterTypes(), serviceType); for (java.lang.reflect.Type t : ptypes) { @@ -1378,14 +1367,19 @@ public final class Rest { + ", serviceType is " + serviceType.getName()); } retvalTypes.add(rtype); - if (mappings.length == 0) { // 没有Mapping,设置一个默认值 + if (mappings.isEmpty()) { // 没有Mapping,设置一个默认值 MappingEntry entry = new MappingEntry( - serRpcOnly, methodIdex, parentNonBlocking, null, bigModuleName, method); + serRpcOnly, + methodIdex, + parentNonBlocking, + new MappingAnn(method, MappingEntry.DEFAULT__MAPPING), + bigModuleName, + method); entrys.add(entry); } else { - for (RestMapping mapping : mappings) { + for (MappingAnn ann : mappings) { MappingEntry entry = new MappingEntry( - serRpcOnly, methodIdex, parentNonBlocking, mapping, defModuleName, method); + serRpcOnly, methodIdex, parentNonBlocking, ann, defModuleName, method); entrys.add(entry); } } @@ -1920,21 +1914,10 @@ public final class Rest { continue; } - RestMapping[] mappings = method.getAnnotationsByType(RestMapping.class); - if (!controller.autoMapping() && mappings.length < 1) { + List mappings = MappingAnn.paraseMappingAnns(controller, method); + if (mappings == null) { continue; } - boolean ignore = false; - for (RestMapping mapping : mappings) { - if (mapping.ignore()) { - ignore = true; - break; - } - } - if (ignore) { - continue; - } - Class[] extypes = method.getExceptionTypes(); if (extypes.length > 0) { for (Class exp : extypes) { @@ -1958,18 +1941,23 @@ public final class Rest { + ", serviceType is " + serviceType.getName()); } retvalTypes.add(rtype); - if (mappings.length == 0) { // 没有Mapping,设置一个默认值 - MappingEntry entry = - new MappingEntry(serRpcOnly, methodidex, parentNonBlocking, null, bigModuleName, method); + if (mappings.isEmpty()) { // 没有Mapping,设置一个默认值 + MappingEntry entry = new MappingEntry( + serRpcOnly, + methodidex, + parentNonBlocking, + new MappingAnn(method, MappingEntry.DEFAULT__MAPPING), + bigModuleName, + method); if (entrys.contains(entry)) { throw new RestException(serviceType.getName() + " on " + method.getName() + " 's mapping(" + entry.name + ") is repeat"); } entrys.add(entry); } else { - for (RestMapping mapping : mappings) { + for (MappingAnn ann : mappings) { MappingEntry entry = - new MappingEntry(serRpcOnly, methodidex, parentNonBlocking, mapping, defModuleName, method); + new MappingEntry(serRpcOnly, methodidex, parentNonBlocking, ann, defModuleName, method); if (entrys.contains(entry)) { throw new RestException(serviceType.getName() + " on " + method.getName() + " 's mapping(" + entry.name + ") is repeat"); @@ -4373,9 +4361,229 @@ public final class Rest { return true; } + private static class MappingAnn { + + public final boolean ignore; + + public final String name; + + public final String example; + + public final String comment; + + public final boolean rpcOnly; + + public final boolean auth; + + public final int actionid; + + public final int cacheSeconds; + + public final String[] methods; + + public MappingAnn(Method method, RestDeleteMapping mapping) { + this( + mapping.ignore(), + mapping.name().trim().isEmpty() + ? method.getName() + : mapping.name().trim(), + mapping.example(), + mapping.comment(), + mapping.rpcOnly(), + mapping.auth(), + mapping.actionid(), + mapping.cacheSeconds(), + new String[] {"DELETE"}); + } + + public MappingAnn(Method method, RestPatchMapping mapping) { + this( + mapping.ignore(), + mapping.name().trim().isEmpty() + ? method.getName() + : mapping.name().trim(), + mapping.example(), + mapping.comment(), + mapping.rpcOnly(), + mapping.auth(), + mapping.actionid(), + mapping.cacheSeconds(), + new String[] {"PATCH"}); + } + + public MappingAnn(Method method, RestPutMapping mapping) { + this( + mapping.ignore(), + mapping.name().trim().isEmpty() + ? method.getName() + : mapping.name().trim(), + mapping.example(), + mapping.comment(), + mapping.rpcOnly(), + mapping.auth(), + mapping.actionid(), + mapping.cacheSeconds(), + new String[] {"PUT"}); + } + + public MappingAnn(Method method, RestPostMapping mapping) { + this( + mapping.ignore(), + mapping.name().trim().isEmpty() + ? method.getName() + : mapping.name().trim(), + mapping.example(), + mapping.comment(), + mapping.rpcOnly(), + mapping.auth(), + mapping.actionid(), + mapping.cacheSeconds(), + new String[] {"POST"}); + } + + public MappingAnn(Method method, RestGetMapping mapping) { + this( + mapping.ignore(), + mapping.name().trim().isEmpty() + ? method.getName() + : mapping.name().trim(), + mapping.example(), + mapping.comment(), + mapping.rpcOnly(), + mapping.auth(), + mapping.actionid(), + mapping.cacheSeconds(), + new String[] {"GET"}); + } + + public MappingAnn(Method method, RestMapping mapping) { + this( + mapping.ignore(), + mapping.name().trim().isEmpty() + ? method.getName() + : mapping.name().trim(), + mapping.example(), + mapping.comment(), + mapping.rpcOnly(), + mapping.auth(), + mapping.actionid(), + mapping.cacheSeconds(), + mapping.methods()); + } + + public MappingAnn( + boolean ignore, + String name, + String example, + String comment, + boolean rpcOnly, + boolean auth, + int actionid, + int cacheSeconds, + String[] methods) { + this.ignore = ignore; + this.name = name; + this.example = example; + this.comment = comment; + this.rpcOnly = rpcOnly; + this.auth = auth; + this.actionid = actionid; + this.cacheSeconds = cacheSeconds; + this.methods = methods; + } + + public static List paraseMappingAnns(RestService controller, Method method) { + RestMapping[] mappings = method.getAnnotationsByType(RestMapping.class); + RestGetMapping[] mappings2 = method.getAnnotationsByType(RestGetMapping.class); + RestPostMapping[] mappings3 = method.getAnnotationsByType(RestPostMapping.class); + RestPutMapping[] mappings4 = method.getAnnotationsByType(RestPutMapping.class); + RestPatchMapping[] mappings5 = method.getAnnotationsByType(RestPatchMapping.class); + RestDeleteMapping[] mappings6 = method.getAnnotationsByType(RestDeleteMapping.class); + int len = mappings.length + + mappings2.length + + mappings3.length + + mappings4.length + + mappings5.length + + mappings6.length; + if (!controller.autoMapping() && len < 1) { + return null; + } + boolean ignore = false; + for (RestMapping mapping : mappings) { + if (mapping.ignore()) { + ignore = true; + break; + } + } + if (!ignore) { + for (RestGetMapping mapping : mappings2) { + if (mapping.ignore()) { + ignore = true; + break; + } + } + } + if (!ignore) { + for (RestPostMapping mapping : mappings3) { + if (mapping.ignore()) { + ignore = true; + break; + } + } + } + if (!ignore) { + for (RestPutMapping mapping : mappings4) { + if (mapping.ignore()) { + ignore = true; + break; + } + } + } + if (!ignore) { + for (RestPatchMapping mapping : mappings5) { + if (mapping.ignore()) { + ignore = true; + break; + } + } + } + if (!ignore) { + for (RestDeleteMapping mapping : mappings6) { + if (mapping.ignore()) { + ignore = true; + break; + } + } + } + if (ignore) { + return null; + } + List list = new ArrayList<>(); + for (RestMapping mapping : mappings) { + list.add(new MappingAnn(method, mapping)); + } + for (RestGetMapping mapping : mappings2) { + list.add(new MappingAnn(method, mapping)); + } + for (RestPostMapping mapping : mappings3) { + list.add(new MappingAnn(method, mapping)); + } + for (RestPutMapping mapping : mappings4) { + list.add(new MappingAnn(method, mapping)); + } + for (RestPatchMapping mapping : mappings5) { + list.add(new MappingAnn(method, mapping)); + } + for (RestDeleteMapping mapping : mappings6) { + list.add(new MappingAnn(method, mapping)); + } + return list; + } + } + private static class MappingEntry implements Comparable { - private static final RestMapping DEFAULT__MAPPING; + static final RestMapping DEFAULT__MAPPING; static { try { @@ -4414,27 +4622,20 @@ public final class Rest { final boolean serRpcOnly, int methodIndex, Boolean typeNonBlocking, - RestMapping mapping, + MappingAnn mapping, final String defModuleName, Method method) { - if (mapping == null) { - mapping = DEFAULT__MAPPING; - } this.methodIdx = methodIndex; - this.ignore = mapping.ignore(); - String n = mapping.name(); - if (n.isEmpty()) { - n = method.getName(); - } - this.name = n.trim(); - this.example = mapping.example(); this.mappingMethod = method; - this.methods = mapping.methods(); - this.auth = mapping.auth(); - this.rpcOnly = serRpcOnly || mapping.rpcOnly(); - this.actionid = mapping.actionid(); - this.cacheSeconds = mapping.cacheSeconds(); - this.comment = mapping.comment(); + this.ignore = mapping.ignore; + this.name = mapping.name; + this.example = mapping.example; + this.methods = mapping.methods; + this.auth = mapping.auth; + this.rpcOnly = serRpcOnly || mapping.rpcOnly; + this.actionid = mapping.actionid; + this.cacheSeconds = mapping.cacheSeconds; + this.comment = mapping.comment; boolean pound = false; Parameter[] params = method.getParameters(); for (Parameter param : params) { @@ -4479,22 +4680,22 @@ public final class Rest { public final Method mappingMethod; - public final boolean ignore; - public final String newMethodName; public final String newActionClassName; + public final boolean nonBlocking; + + public final boolean existsPound; // 是否包含#的参数 + + public final boolean ignore; + public final String name; public final String example; public final String comment; - public final String[] methods; - - public final boolean nonBlocking; - public final boolean rpcOnly; public final boolean auth; @@ -4503,7 +4704,7 @@ public final class Rest { public final int cacheSeconds; - public final boolean existsPound; // 是否包含#的参数 + public final String[] methods; String mappingurl; // 在生成方法时赋值, 供 _createRestActionEntry 使用 diff --git a/src/main/java/org/redkale/net/http/RestDeleteMapping.java b/src/main/java/org/redkale/net/http/RestDeleteMapping.java new file mode 100644 index 000000000..e6a25dc16 --- /dev/null +++ b/src/main/java/org/redkale/net/http/RestDeleteMapping.java @@ -0,0 +1,93 @@ +/* + +*/ + +package org.redkale.net.http; + +import java.lang.annotation.Documented; +import static java.lang.annotation.ElementType.METHOD; +import java.lang.annotation.Repeatable; +import java.lang.annotation.Retention; +import static java.lang.annotation.RetentionPolicy.RUNTIME; +import java.lang.annotation.Target; + +/** + * DELETE方法版{@link org.redkale.net.http.RestMapping} + * + *

详情见: https://redkale.org + * + * @since 2.8.0 + * @org.redkale.net.http.RestMapping + * @see org.redkale.net.http.RestService + * @author zhangjx + */ +@Documented +@Target({METHOD}) +@Retention(RUNTIME) +@Repeatable(RestDeleteMapping.RestDeleteMappings.class) +public @interface RestDeleteMapping { + + /** + * 是否屏蔽该方法进行HttpMapping转换 + * + * @return boolean + */ + boolean ignore() default false; + + /** + * 请求的方法名, 不能含特殊字符 + * + * @return String + */ + String name() default ""; + + /** + * 备注描述, 对应@HttpMapping.comment + * + * @return String + */ + String comment() default ""; + + /** + * 是否只接收RPC请求, 对应@HttpMapping.rpcOnly + * + * @return boolean + */ + boolean rpcOnly() default false; + + /** + * 是否鉴权,默认需要鉴权, 对应@HttpMapping.auth + * + * @return boolean + */ + boolean auth() default true; + + /** + * 操作ID值,鉴权时用到, 对应@HttpMapping.actionid + * + * @return int + */ + int actionid() default 0; + + /** + * 结果缓存的秒数, 为0表示不缓存, 对应@HttpMapping.cacheSeconds + * + * @return int + */ + int cacheSeconds() default 0; + + /** + * 返回结果的样例 for OpenAPI Specification 3.1.0 + * + * @return String + */ + String example() default ""; + + @Documented + @Target({METHOD}) + @Retention(RUNTIME) + @interface RestDeleteMappings { + + RestDeleteMapping[] value(); + } +} diff --git a/src/main/java/org/redkale/net/http/RestGetMapping.java b/src/main/java/org/redkale/net/http/RestGetMapping.java new file mode 100644 index 000000000..288335a48 --- /dev/null +++ b/src/main/java/org/redkale/net/http/RestGetMapping.java @@ -0,0 +1,93 @@ +/* + +*/ + +package org.redkale.net.http; + +import java.lang.annotation.Documented; +import static java.lang.annotation.ElementType.METHOD; +import java.lang.annotation.Repeatable; +import java.lang.annotation.Retention; +import static java.lang.annotation.RetentionPolicy.RUNTIME; +import java.lang.annotation.Target; + +/** + * GET方法版{@link org.redkale.net.http.RestMapping} + * + *

详情见: https://redkale.org + * + * @since 2.8.0 + * @org.redkale.net.http.RestMapping + * @see org.redkale.net.http.RestService + * @author zhangjx + */ +@Documented +@Target({METHOD}) +@Retention(RUNTIME) +@Repeatable(RestGetMapping.RestGetMappings.class) +public @interface RestGetMapping { + + /** + * 是否屏蔽该方法进行HttpMapping转换 + * + * @return boolean + */ + boolean ignore() default false; + + /** + * 请求的方法名, 不能含特殊字符 + * + * @return String + */ + String name() default ""; + + /** + * 备注描述, 对应@HttpMapping.comment + * + * @return String + */ + String comment() default ""; + + /** + * 是否只接收RPC请求, 对应@HttpMapping.rpcOnly + * + * @return boolean + */ + boolean rpcOnly() default false; + + /** + * 是否鉴权,默认需要鉴权, 对应@HttpMapping.auth + * + * @return boolean + */ + boolean auth() default true; + + /** + * 操作ID值,鉴权时用到, 对应@HttpMapping.actionid + * + * @return int + */ + int actionid() default 0; + + /** + * 结果缓存的秒数, 为0表示不缓存, 对应@HttpMapping.cacheSeconds + * + * @return int + */ + int cacheSeconds() default 0; + + /** + * 返回结果的样例 for OpenAPI Specification 3.1.0 + * + * @return String + */ + String example() default ""; + + @Documented + @Target({METHOD}) + @Retention(RUNTIME) + @interface RestGetMappings { + + RestGetMapping[] value(); + } +} diff --git a/src/main/java/org/redkale/net/http/RestMapping.java b/src/main/java/org/redkale/net/http/RestMapping.java index c63f1c2ee..4d9ca54f6 100644 --- a/src/main/java/org/redkale/net/http/RestMapping.java +++ b/src/main/java/org/redkale/net/http/RestMapping.java @@ -5,11 +5,10 @@ */ package org.redkale.net.http; +import java.lang.annotation.*; import static java.lang.annotation.ElementType.*; import static java.lang.annotation.RetentionPolicy.*; -import java.lang.annotation.*; - /** * 只能依附在Service实现类的public方法上,且方法如果throws只能是IOException
* value默认为"/" + Service的类名去掉Service字样的小写字符串 (如HelloService,的默认路径为/hello)。
@@ -74,13 +73,6 @@ public @interface RestMapping { */ int cacheSeconds() default 0; - /** - * 允许方法(不区分大小写),如:GET/POST/PUT,为空表示允许所有方法, 对应@HttpMapping.methods - * - * @return String[] - */ - String[] methods() default {}; - /** * 返回结果的样例 for OpenAPI Specification 3.1.0 * @@ -88,6 +80,13 @@ public @interface RestMapping { */ String example() default ""; + /** + * 允许方法(不区分大小写),如:GET/POST/PUT,为空表示允许所有方法, 对应@HttpMapping.methods + * + * @return String[] + */ + String[] methods() default {}; + @Documented @Target({METHOD}) @Retention(RUNTIME) diff --git a/src/main/java/org/redkale/net/http/RestPatchMapping.java b/src/main/java/org/redkale/net/http/RestPatchMapping.java new file mode 100644 index 000000000..7be4a08e5 --- /dev/null +++ b/src/main/java/org/redkale/net/http/RestPatchMapping.java @@ -0,0 +1,93 @@ +/* + +*/ + +package org.redkale.net.http; + +import java.lang.annotation.Documented; +import static java.lang.annotation.ElementType.METHOD; +import java.lang.annotation.Repeatable; +import java.lang.annotation.Retention; +import static java.lang.annotation.RetentionPolicy.RUNTIME; +import java.lang.annotation.Target; + +/** + * PATCH方法版{@link org.redkale.net.http.RestMapping} + * + *

详情见: https://redkale.org + * + * @since 2.8.0 + * @org.redkale.net.http.RestMapping + * @see org.redkale.net.http.RestService + * @author zhangjx + */ +@Documented +@Target({METHOD}) +@Retention(RUNTIME) +@Repeatable(RestPatchMapping.RestPatchMappings.class) +public @interface RestPatchMapping { + + /** + * 是否屏蔽该方法进行HttpMapping转换 + * + * @return boolean + */ + boolean ignore() default false; + + /** + * 请求的方法名, 不能含特殊字符 + * + * @return String + */ + String name() default ""; + + /** + * 备注描述, 对应@HttpMapping.comment + * + * @return String + */ + String comment() default ""; + + /** + * 是否只接收RPC请求, 对应@HttpMapping.rpcOnly + * + * @return boolean + */ + boolean rpcOnly() default false; + + /** + * 是否鉴权,默认需要鉴权, 对应@HttpMapping.auth + * + * @return boolean + */ + boolean auth() default true; + + /** + * 操作ID值,鉴权时用到, 对应@HttpMapping.actionid + * + * @return int + */ + int actionid() default 0; + + /** + * 结果缓存的秒数, 为0表示不缓存, 对应@HttpMapping.cacheSeconds + * + * @return int + */ + int cacheSeconds() default 0; + + /** + * 返回结果的样例 for OpenAPI Specification 3.1.0 + * + * @return String + */ + String example() default ""; + + @Documented + @Target({METHOD}) + @Retention(RUNTIME) + @interface RestPatchMappings { + + RestPatchMapping[] value(); + } +} diff --git a/src/main/java/org/redkale/net/http/RestPostMapping.java b/src/main/java/org/redkale/net/http/RestPostMapping.java new file mode 100644 index 000000000..9f18c60be --- /dev/null +++ b/src/main/java/org/redkale/net/http/RestPostMapping.java @@ -0,0 +1,93 @@ +/* + +*/ + +package org.redkale.net.http; + +import java.lang.annotation.Documented; +import static java.lang.annotation.ElementType.METHOD; +import java.lang.annotation.Repeatable; +import java.lang.annotation.Retention; +import static java.lang.annotation.RetentionPolicy.RUNTIME; +import java.lang.annotation.Target; + +/** + * POST方法版{@link org.redkale.net.http.RestMapping} + * + *

详情见: https://redkale.org + * + * @since 2.8.0 + * @org.redkale.net.http.RestMapping + * @see org.redkale.net.http.RestService + * @author zhangjx + */ +@Documented +@Target({METHOD}) +@Retention(RUNTIME) +@Repeatable(RestPostMapping.RestPostMappings.class) +public @interface RestPostMapping { + + /** + * 是否屏蔽该方法进行HttpMapping转换 + * + * @return boolean + */ + boolean ignore() default false; + + /** + * 请求的方法名, 不能含特殊字符 + * + * @return String + */ + String name() default ""; + + /** + * 备注描述, 对应@HttpMapping.comment + * + * @return String + */ + String comment() default ""; + + /** + * 是否只接收RPC请求, 对应@HttpMapping.rpcOnly + * + * @return boolean + */ + boolean rpcOnly() default false; + + /** + * 是否鉴权,默认需要鉴权, 对应@HttpMapping.auth + * + * @return boolean + */ + boolean auth() default true; + + /** + * 操作ID值,鉴权时用到, 对应@HttpMapping.actionid + * + * @return int + */ + int actionid() default 0; + + /** + * 结果缓存的秒数, 为0表示不缓存, 对应@HttpMapping.cacheSeconds + * + * @return int + */ + int cacheSeconds() default 0; + + /** + * 返回结果的样例 for OpenAPI Specification 3.1.0 + * + * @return String + */ + String example() default ""; + + @Documented + @Target({METHOD}) + @Retention(RUNTIME) + @interface RestPostMappings { + + RestPostMapping[] value(); + } +} diff --git a/src/main/java/org/redkale/net/http/RestPutMapping.java b/src/main/java/org/redkale/net/http/RestPutMapping.java new file mode 100644 index 000000000..747d4868f --- /dev/null +++ b/src/main/java/org/redkale/net/http/RestPutMapping.java @@ -0,0 +1,93 @@ +/* + +*/ + +package org.redkale.net.http; + +import java.lang.annotation.Documented; +import static java.lang.annotation.ElementType.METHOD; +import java.lang.annotation.Repeatable; +import java.lang.annotation.Retention; +import static java.lang.annotation.RetentionPolicy.RUNTIME; +import java.lang.annotation.Target; + +/** + * PUT方法版{@link org.redkale.net.http.RestMapping} + * + *

详情见: https://redkale.org + * + * @since 2.8.0 + * @org.redkale.net.http.RestMapping + * @see org.redkale.net.http.RestService + * @author zhangjx + */ +@Documented +@Target({METHOD}) +@Retention(RUNTIME) +@Repeatable(RestPutMapping.RestPutMappings.class) +public @interface RestPutMapping { + + /** + * 是否屏蔽该方法进行HttpMapping转换 + * + * @return boolean + */ + boolean ignore() default false; + + /** + * 请求的方法名, 不能含特殊字符 + * + * @return String + */ + String name() default ""; + + /** + * 备注描述, 对应@HttpMapping.comment + * + * @return String + */ + String comment() default ""; + + /** + * 是否只接收RPC请求, 对应@HttpMapping.rpcOnly + * + * @return boolean + */ + boolean rpcOnly() default false; + + /** + * 是否鉴权,默认需要鉴权, 对应@HttpMapping.auth + * + * @return boolean + */ + boolean auth() default true; + + /** + * 操作ID值,鉴权时用到, 对应@HttpMapping.actionid + * + * @return int + */ + int actionid() default 0; + + /** + * 结果缓存的秒数, 为0表示不缓存, 对应@HttpMapping.cacheSeconds + * + * @return int + */ + int cacheSeconds() default 0; + + /** + * 返回结果的样例 for OpenAPI Specification 3.1.0 + * + * @return String + */ + String example() default ""; + + @Documented + @Target({METHOD}) + @Retention(RUNTIME) + @interface RestPutMappings { + + RestPutMapping[] value(); + } +}