增加RestGetMapping/RestPostMapping

This commit is contained in:
redkale
2024-06-12 20:42:01 +08:00
parent fd4aa227d3
commit 0ccddc04c0
7 changed files with 740 additions and 75 deletions

View File

@@ -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<MappingAnn> 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<MappingAnn> 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<MappingAnn> 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<MappingAnn> 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<MappingEntry> {
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 使用

View File

@@ -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}
*
* <p>详情见: 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 "";
/**
* 备注描述, 对应&#64;HttpMapping.comment
*
* @return String
*/
String comment() default "";
/**
* 是否只接收RPC请求, 对应&#64;HttpMapping.rpcOnly
*
* @return boolean
*/
boolean rpcOnly() default false;
/**
* 是否鉴权,默认需要鉴权, 对应&#64;HttpMapping.auth
*
* @return boolean
*/
boolean auth() default true;
/**
* 操作ID值鉴权时用到, 对应&#64;HttpMapping.actionid
*
* @return int
*/
int actionid() default 0;
/**
* 结果缓存的秒数, 为0表示不缓存, 对应&#64;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();
}
}

View File

@@ -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}
*
* <p>详情见: 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 "";
/**
* 备注描述, 对应&#64;HttpMapping.comment
*
* @return String
*/
String comment() default "";
/**
* 是否只接收RPC请求, 对应&#64;HttpMapping.rpcOnly
*
* @return boolean
*/
boolean rpcOnly() default false;
/**
* 是否鉴权,默认需要鉴权, 对应&#64;HttpMapping.auth
*
* @return boolean
*/
boolean auth() default true;
/**
* 操作ID值鉴权时用到, 对应&#64;HttpMapping.actionid
*
* @return int
*/
int actionid() default 0;
/**
* 结果缓存的秒数, 为0表示不缓存, 对应&#64;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();
}
}

View File

@@ -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 <br>
* value默认为"/" + Service的类名去掉Service字样的小写字符串 (如HelloService的默认路径为/hello)。 <br>
@@ -74,13 +73,6 @@ public @interface RestMapping {
*/
int cacheSeconds() default 0;
/**
* 允许方法(不区分大小写),如:GET/POST/PUT,为空表示允许所有方法, 对应&#64;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,为空表示允许所有方法, 对应&#64;HttpMapping.methods
*
* @return String[]
*/
String[] methods() default {};
@Documented
@Target({METHOD})
@Retention(RUNTIME)

View File

@@ -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}
*
* <p>详情见: 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 "";
/**
* 备注描述, 对应&#64;HttpMapping.comment
*
* @return String
*/
String comment() default "";
/**
* 是否只接收RPC请求, 对应&#64;HttpMapping.rpcOnly
*
* @return boolean
*/
boolean rpcOnly() default false;
/**
* 是否鉴权,默认需要鉴权, 对应&#64;HttpMapping.auth
*
* @return boolean
*/
boolean auth() default true;
/**
* 操作ID值鉴权时用到, 对应&#64;HttpMapping.actionid
*
* @return int
*/
int actionid() default 0;
/**
* 结果缓存的秒数, 为0表示不缓存, 对应&#64;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();
}
}

View File

@@ -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}
*
* <p>详情见: 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 "";
/**
* 备注描述, 对应&#64;HttpMapping.comment
*
* @return String
*/
String comment() default "";
/**
* 是否只接收RPC请求, 对应&#64;HttpMapping.rpcOnly
*
* @return boolean
*/
boolean rpcOnly() default false;
/**
* 是否鉴权,默认需要鉴权, 对应&#64;HttpMapping.auth
*
* @return boolean
*/
boolean auth() default true;
/**
* 操作ID值鉴权时用到, 对应&#64;HttpMapping.actionid
*
* @return int
*/
int actionid() default 0;
/**
* 结果缓存的秒数, 为0表示不缓存, 对应&#64;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();
}
}

View File

@@ -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}
*
* <p>详情见: 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 "";
/**
* 备注描述, 对应&#64;HttpMapping.comment
*
* @return String
*/
String comment() default "";
/**
* 是否只接收RPC请求, 对应&#64;HttpMapping.rpcOnly
*
* @return boolean
*/
boolean rpcOnly() default false;
/**
* 是否鉴权,默认需要鉴权, 对应&#64;HttpMapping.auth
*
* @return boolean
*/
boolean auth() default true;
/**
* 操作ID值鉴权时用到, 对应&#64;HttpMapping.actionid
*
* @return int
*/
int actionid() default 0;
/**
* 结果缓存的秒数, 为0表示不缓存, 对应&#64;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();
}
}