Compare commits
43 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f9f2e080da | ||
|
|
027fa3a18b | ||
|
|
d9f50d63f0 | ||
|
|
181486c348 | ||
|
|
74adfdfc99 | ||
|
|
c3783eb041 | ||
|
|
77451561e6 | ||
|
|
59d30b05f2 | ||
|
|
2fcf0bb644 | ||
|
|
71ab9c9728 | ||
|
|
09165127e3 | ||
|
|
c28310e0df | ||
|
|
51435a1c33 | ||
|
|
83c70b9767 | ||
|
|
5534dcd476 | ||
|
|
d18a55deaf | ||
|
|
ae2d64991c | ||
|
|
ecb6b80e5e | ||
|
|
cf332fa67a | ||
|
|
ffa80c9212 | ||
|
|
7463a8f6b5 | ||
|
|
a168897784 | ||
|
|
d39b3856ca | ||
|
|
ca9f74185b | ||
|
|
c35e421ba3 | ||
|
|
65755e0787 | ||
|
|
366c3becc4 | ||
|
|
a1ac6ec543 | ||
|
|
b27bbb7836 | ||
|
|
a57574dd10 | ||
|
|
a7dd22569c | ||
|
|
0bc0755fb3 | ||
|
|
c2edb60218 | ||
|
|
60c1a82a62 | ||
|
|
e3205128b4 | ||
|
|
a9dff0360f | ||
|
|
1e871cbee5 | ||
|
|
41aadf33f3 | ||
|
|
679567c85a | ||
|
|
b77050250c | ||
|
|
e178d1120b | ||
|
|
eca138b671 | ||
|
|
0366aef672 |
32
assembly.xml
Normal file
32
assembly.xml
Normal file
@@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/2.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/2.0.0 http://maven.apache.org/xsd/assembly-2.0.0.xsd">
|
||||
<id>redkale</id>
|
||||
<formats>
|
||||
<format>tar.gz</format>
|
||||
</formats>
|
||||
<includeBaseDirectory>false</includeBaseDirectory>
|
||||
<fileSets>
|
||||
<fileSet>
|
||||
<directory>${project.basedir}/bin</directory>
|
||||
<outputDirectory>bin</outputDirectory>
|
||||
</fileSet>
|
||||
<fileSet>
|
||||
<directory>${project.basedir}/conf</directory>
|
||||
<outputDirectory>conf</outputDirectory>
|
||||
</fileSet>
|
||||
<fileSet>
|
||||
<directory>${project.basedir}/logs</directory>
|
||||
<outputDirectory>logs</outputDirectory>
|
||||
</fileSet>
|
||||
</fileSets>
|
||||
<dependencySets>
|
||||
<dependencySet>
|
||||
<useProjectArtifact>true</useProjectArtifact>
|
||||
<useTransitiveDependencies>false</useTransitiveDependencies>
|
||||
<outputDirectory>lib</outputDirectory>
|
||||
<scope>runtime</scope>
|
||||
</dependencySet>
|
||||
</dependencySets>
|
||||
</assembly>
|
||||
@@ -1,6 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<application port="5050">
|
||||
|
||||
<!-- 详细配置说明见: http://redkale.org/redkale.html#redkale_confxml -->
|
||||
|
||||
<resources>
|
||||
<!--
|
||||
<properties>
|
||||
@@ -8,7 +11,8 @@
|
||||
</properties>
|
||||
-->
|
||||
</resources>
|
||||
|
||||
|
||||
|
||||
<server protocol="HTTP" host="0.0.0.0" port="6060" root="root">
|
||||
<!--
|
||||
<request>
|
||||
|
||||
40
pom.xml
40
pom.xml
@@ -6,7 +6,7 @@
|
||||
<packaging>jar</packaging>
|
||||
<url>http://redkale.org</url>
|
||||
<description>redkale -- java framework</description>
|
||||
<version>1.4.0-SNAPSHOT</version>
|
||||
<version>1.6.2</version>
|
||||
<licenses>
|
||||
<license>
|
||||
<name>Apache 2</name>
|
||||
@@ -121,20 +121,30 @@
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<version>3.0.0</version>
|
||||
<configuration>
|
||||
<appendAssemblyId>false</appendAssemblyId>
|
||||
<descriptors>
|
||||
<descriptor>assembly.xml</descriptor>
|
||||
</descriptors>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>redkale</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>single</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.codehaus.plexus</groupId>
|
||||
<artifactId>plexus-compiler-javac</artifactId>
|
||||
<version>2.7</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.codehaus.plexus</groupId>
|
||||
<artifactId>plexus-utils</artifactId>
|
||||
<version>3.0.22</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
@@ -23,7 +23,7 @@
|
||||
port: required 程序的管理Server的端口,用于关闭或者与监管系统进行数据交互
|
||||
lib: 加上额外的lib路径,多个路径用分号;隔开; 默认为空。 例如: ${APP_HOME}/lib/a.jar;${APP_HOME}/lib2/b.jar;
|
||||
-->
|
||||
<application port="6560" lib="">
|
||||
<application port="6560" lib="">
|
||||
|
||||
<!--
|
||||
【节点全局唯一】
|
||||
|
||||
@@ -52,13 +52,13 @@ public class ApiDocs extends HttpBaseServlet {
|
||||
}
|
||||
final Map<String, Object> servletmap = new LinkedHashMap<>();
|
||||
String prefix = _prefix(servlet);
|
||||
String[] mappings = ws.value();
|
||||
String[] urlregs = ws.value();
|
||||
if (prefix != null && !prefix.isEmpty()) {
|
||||
for (int i = 0; i < mappings.length; i++) {
|
||||
mappings[i] = prefix + mappings[i];
|
||||
for (int i = 0; i < urlregs.length; i++) {
|
||||
urlregs[i] = prefix + urlregs[i];
|
||||
}
|
||||
}
|
||||
servletmap.put("mappings", mappings);
|
||||
servletmap.put("urlregs", urlregs);
|
||||
servletmap.put("moduleid", ws.moduleid());
|
||||
servletmap.put("name", ws.name());
|
||||
servletmap.put("comment", ws.comment());
|
||||
@@ -179,9 +179,9 @@ public class ApiDocs extends HttpBaseServlet {
|
||||
servletsList.add(servletmap);
|
||||
}
|
||||
servletsList.sort((o1, o2) -> {
|
||||
String[] mappings1 = (String[]) o1.get("mappings");
|
||||
String[] mappings2 = (String[]) o2.get("mappings");
|
||||
return mappings1.length > 0 ? (mappings2.length > 0 ? mappings1[0].compareTo(mappings2[0]) : 1) : -1;
|
||||
String[] urlregs1 = (String[]) o1.get("urlregs");
|
||||
String[] urlregs2 = (String[]) o2.get("urlregs");
|
||||
return urlregs1.length > 0 ? (urlregs2.length > 0 ? urlregs1[0].compareTo(urlregs2[0]) : 1) : -1;
|
||||
});
|
||||
}
|
||||
Map<String, Object> resultmap = new LinkedHashMap<>();
|
||||
|
||||
@@ -338,6 +338,7 @@ public final class Application {
|
||||
String name = prop.getValue("name");
|
||||
String value = prop.getValue("value");
|
||||
if (name == null || value == null) continue;
|
||||
value = value.replace("${APP_HOME}", home.getCanonicalPath()).replace('\\', '/');
|
||||
if (name.startsWith("system.property.")) {
|
||||
System.setProperty(name.substring("system.property.".length()), value);
|
||||
} else if (name.startsWith("mimetype.property.")) {
|
||||
@@ -350,11 +351,6 @@ public final class Application {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this.localAddress != null && this.resourceFactory.find("property.datasource.nodeid", String.class) == null) {
|
||||
byte[] bs = this.localAddress.getAddress();
|
||||
int v = (0xff & bs[bs.length - 2]) % 10 * 100 + (0xff & bs[bs.length - 1]);
|
||||
this.resourceFactory.register("property.datasource.nodeid", "" + v);
|
||||
}
|
||||
this.resourceFactory.register(BsonFactory.root());
|
||||
this.resourceFactory.register(JsonFactory.root());
|
||||
this.resourceFactory.register(BsonFactory.root().getConvert());
|
||||
|
||||
@@ -74,7 +74,7 @@ public class NodeHttpServer extends NodeServer {
|
||||
synchronized (regFactory) {
|
||||
Service nodeService = (Service) rf.find(resourceName, WebSocketNode.class);
|
||||
if (nodeService == null) {
|
||||
nodeService = Sncp.createLocalService(resourceName, getExecutor(), application.getResourceFactory(), WebSocketNodeService.class, (InetSocketAddress) null, (Transport) null, (Collection<Transport>) null);
|
||||
nodeService = Sncp.createLocalService(resourceName, getExecutor(), application.getResourceFactory(), WebSocketNodeService.class, (InetSocketAddress) null, (String) null, (Set<String>) null, (AnyValue) null, (Transport) null, (Collection<Transport>) null);
|
||||
regFactory.register(resourceName, WebSocketNode.class, nodeService);
|
||||
resourceFactory.inject(nodeService, self);
|
||||
logger.fine("[" + Thread.currentThread().getName() + "] Load Service " + nodeService);
|
||||
@@ -109,13 +109,6 @@ public class NodeHttpServer extends NodeServer {
|
||||
final String[] mappings = ws.value();
|
||||
String pref = ws.repair() ? prefix : "";
|
||||
DefaultAnyValue servletConf = (DefaultAnyValue) en.getProperty();
|
||||
WebInitParam[] webparams = ws.initParams();
|
||||
if (webparams.length > 0) {
|
||||
if (servletConf == null) servletConf = new DefaultAnyValue();
|
||||
for (WebInitParam webparam : webparams) {
|
||||
servletConf.addValue(webparam.name(), webparam.value());
|
||||
}
|
||||
}
|
||||
this.httpServer.addHttpServlet(servlet, pref, servletConf, mappings);
|
||||
if (ss != null) {
|
||||
for (int i = 0; i < mappings.length; i++) {
|
||||
@@ -124,9 +117,9 @@ public class NodeHttpServer extends NodeServer {
|
||||
ss.add(new AbstractMap.SimpleEntry<>(clazz.getName(), mappings));
|
||||
}
|
||||
}
|
||||
int max = 0;
|
||||
if (ss != null && sb != null) {
|
||||
Collections.sort(ss, (AbstractMap.SimpleEntry<String, String[]> o1, AbstractMap.SimpleEntry<String, String[]> o2) -> o1.getKey().compareTo(o2.getKey()));
|
||||
int max = 0;
|
||||
for (AbstractMap.SimpleEntry<String, String[]> as : ss) {
|
||||
if (as.getKey().length() > max) max = as.getKey().length();
|
||||
}
|
||||
@@ -138,18 +131,17 @@ public class NodeHttpServer extends NodeServer {
|
||||
sb.append(" mapping to ").append(Arrays.toString(as.getValue())).append(LINE_SEPARATOR);
|
||||
}
|
||||
}
|
||||
if (sb != null && sb.length() > 0) logger.log(Level.INFO, sb.toString());
|
||||
if (rest && serverConf != null) {
|
||||
for (AnyValue restConf : serverConf.getAnyValues("rest")) {
|
||||
loadRestServlet(prefix, restConf);
|
||||
loadRestServlet(prefix, restConf, sb);
|
||||
}
|
||||
}
|
||||
if (sb != null && sb.length() > 0) logger.log(Level.INFO, sb.toString());
|
||||
}
|
||||
|
||||
protected void loadRestServlet(final String prefix, final AnyValue restConf) throws Exception {
|
||||
protected void loadRestServlet(final String prefix, final AnyValue restConf, final StringBuilder sb) throws Exception {
|
||||
if (!rest) return;
|
||||
if (restConf == null) return; //不存在REST服务
|
||||
final StringBuilder sb = logger.isLoggable(Level.INFO) ? new StringBuilder() : null;
|
||||
final String threadName = "[" + Thread.currentThread().getName() + "] ";
|
||||
final List<AbstractMap.SimpleEntry<String, String[]>> ss = sb == null ? null : new ArrayList<>();
|
||||
|
||||
@@ -170,8 +162,9 @@ public class NodeHttpServer extends NodeServer {
|
||||
|
||||
final ClassFilter restFilter = ClassFilter.create(restConf.getValue("includes", ""), restConf.getValue("excludes", ""), includeValues, excludeValues);
|
||||
|
||||
super.interceptorServiceWrappers.forEach((wrapper) -> {
|
||||
final Class stype = wrapper.getType();
|
||||
super.interceptorServices.forEach((service) -> {
|
||||
final Class stype = Sncp.getServiceType(service);
|
||||
final String name = Sncp.getResourceName(service);
|
||||
RestService rs = (RestService) stype.getAnnotation(RestService.class);
|
||||
if (rs != null && rs.ignore()) return;
|
||||
if (mustsign && rs == null) return;
|
||||
@@ -181,17 +174,15 @@ public class NodeHttpServer extends NodeServer {
|
||||
if (!autoload && !includeValues.contains(stypename)) return;
|
||||
if (!restFilter.accept(stypename)) return;
|
||||
|
||||
RestHttpServlet servlet = httpServer.addRestServlet(wrapper.getName(), stype, wrapper.getService(), baseServletClass, prefix, (AnyValue) null);
|
||||
RestHttpServlet servlet = httpServer.addRestServlet(name, stype, service, baseServletClass, prefix, (AnyValue) null);
|
||||
resourceFactory.inject(servlet, NodeHttpServer.this);
|
||||
if (finest) logger.finest("Create RestServlet[resource=" + wrapper.getName() + "] = " + servlet);
|
||||
if (finest) logger.finest(threadName + " Create RestServlet(resource.name='" + name + "') = " + servlet);
|
||||
if (ss != null) {
|
||||
String[] mappings = servlet.getClass().getAnnotation(WebServlet.class).value();
|
||||
for (int i = 0; i < mappings.length; i++) {
|
||||
mappings[i] = prefix + mappings[i];
|
||||
}
|
||||
if (servlet.getClass().getSimpleName().charAt(0) != '_') {
|
||||
ss.add(new AbstractMap.SimpleEntry<>(servlet.getClass().getName(), mappings));
|
||||
}
|
||||
ss.add(new AbstractMap.SimpleEntry<>(servlet.getClass().getName(), mappings));
|
||||
}
|
||||
});
|
||||
//输出信息
|
||||
@@ -201,6 +192,7 @@ public class NodeHttpServer extends NodeServer {
|
||||
for (AbstractMap.SimpleEntry<String, String[]> as : ss) {
|
||||
if (as.getKey().length() > max) max = as.getKey().length();
|
||||
}
|
||||
sb.append(threadName).append(" ").append(LINE_SEPARATOR);
|
||||
for (AbstractMap.SimpleEntry<String, String[]> as : ss) {
|
||||
sb.append(threadName).append(" Load ").append(as.getKey());
|
||||
for (int i = 0; i < max - as.getKey().length(); i++) {
|
||||
@@ -209,6 +201,5 @@ public class NodeHttpServer extends NodeServer {
|
||||
sb.append(" mapping to ").append(Arrays.toString(as.getValue())).append(LINE_SEPARATOR);
|
||||
}
|
||||
}
|
||||
if (sb != null && sb.length() > 0) logger.log(Level.INFO, sb.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,9 +5,6 @@
|
||||
*/
|
||||
package org.redkale.boot;
|
||||
|
||||
import java.util.Objects;
|
||||
import org.redkale.service.Service;
|
||||
|
||||
/**
|
||||
* NodeServer的拦截类
|
||||
*
|
||||
@@ -38,63 +35,4 @@ public class NodeInterceptor {
|
||||
|
||||
}
|
||||
|
||||
public static class InterceptorServiceWrapper<T extends Service> {
|
||||
|
||||
private String name;
|
||||
|
||||
private Class<T> type;
|
||||
|
||||
private T service;
|
||||
|
||||
public InterceptorServiceWrapper() {
|
||||
}
|
||||
|
||||
public InterceptorServiceWrapper(String name, Class<T> type, T service) {
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
this.service = service;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Class<T> getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(Class<T> type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public T getService() {
|
||||
return service;
|
||||
}
|
||||
|
||||
public void setService(T service) {
|
||||
this.service = service;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = 7;
|
||||
hash = 97 * hash + Objects.hashCode(this.name);
|
||||
hash = 97 * hash + Objects.hashCode(this.type);
|
||||
return hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) return true;
|
||||
if (obj == null) return false;
|
||||
if (getClass() != obj.getClass()) return false;
|
||||
final InterceptorServiceWrapper<?> other = (InterceptorServiceWrapper<?>) obj;
|
||||
return Objects.equals(this.name, other.name) && Objects.equals(this.type, other.type);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@ public abstract class NodeServer {
|
||||
private InetSocketAddress sncpAddress;
|
||||
|
||||
//加载Service时的处理函数
|
||||
protected Consumer<ServiceWrapper> consumer;
|
||||
protected Consumer<Service> consumer;
|
||||
|
||||
//server节点的配置
|
||||
protected AnyValue serverConf;
|
||||
@@ -78,13 +78,17 @@ public abstract class NodeServer {
|
||||
protected NodeInterceptor interceptor;
|
||||
|
||||
//供interceptor使用的Service对象集合
|
||||
protected final Set<NodeInterceptor.InterceptorServiceWrapper> interceptorServiceWrappers = new LinkedHashSet<>();
|
||||
protected final Set<Service> interceptorServices = new LinkedHashSet<>();
|
||||
|
||||
//本地模式的Service对象集合
|
||||
protected final Set<ServiceWrapper> localServiceWrappers = new LinkedHashSet<>();
|
||||
protected final Set<Service> localServices = new LinkedHashSet<>();
|
||||
|
||||
//远程模式的Service对象集合
|
||||
protected final Set<ServiceWrapper> remoteServiceWrappers = new LinkedHashSet<>();
|
||||
protected final Set<Service> remoteServices = new LinkedHashSet<>();
|
||||
|
||||
private volatile int maxClassNameLength = 0;
|
||||
|
||||
private volatile int maxNameLength = 0;
|
||||
|
||||
public NodeServer(Application application, Server server) {
|
||||
this.application = application;
|
||||
@@ -116,7 +120,7 @@ public abstract class NodeServer {
|
||||
if (context == null) {
|
||||
t.run();
|
||||
} else {
|
||||
context.submit(t);
|
||||
context.submitAsync(t);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -228,19 +232,18 @@ public abstract class NodeServer {
|
||||
Transport sameGroupTransport = Sncp.getSameGroupTransport((Service) src);
|
||||
List<Transport> diffGroupTransports = Arrays.asList(Sncp.getDiffGroupTransports((Service) src));
|
||||
final InetSocketAddress sncpAddr = client == null ? null : client.getClientAddress();
|
||||
if ((src instanceof DataSource) && sncpAddr != null && resourceFactory.find(resourceName, DataCacheListener.class) == null) { //只有DataSourceService 才能赋值 DataCacheListener
|
||||
Service cacheListenerService = Sncp.createLocalService(resourceName, getExecutor(), appResFactory, DataCacheListenerService.class, sncpAddr, sameGroupTransport, diffGroupTransports);
|
||||
appResFactory.register(resourceName, DataCacheListener.class, cacheListenerService);
|
||||
if ((src instanceof DataSource) && sncpAddr != null && resourceFactory.find(resourceName, DataCacheListener.class) == null) { //只有DataSourceService 才能赋值 DataCacheListener
|
||||
final NodeSncpServer sncpServer = application.findNodeSncpServer(sncpAddr);
|
||||
Set<String> gs = application.findSncpGroups(sameGroupTransport, diffGroupTransports);
|
||||
ServiceWrapper wrapper = new ServiceWrapper(DataCacheListenerService.class, cacheListenerService, resourceName, sncpServer.getSncpGroup(), gs, null);
|
||||
localServiceWrappers.add(wrapper);
|
||||
sncpServer.consumerAccept(wrapper);
|
||||
Service cacheListenerService = Sncp.createLocalService(resourceName, getExecutor(), appResFactory, DataCacheListenerService.class, sncpAddr, sncpServer.getSncpGroup(), gs, Sncp.getConf((Service) src), sameGroupTransport, diffGroupTransports);
|
||||
appResFactory.register(resourceName, DataCacheListener.class, cacheListenerService);
|
||||
localServices.add(cacheListenerService);
|
||||
sncpServer.consumerAccept(cacheListenerService);
|
||||
rf.inject(cacheListenerService, self);
|
||||
logger.info("[" + Thread.currentThread().getName() + "] Load Service " + wrapper.getService());
|
||||
logger.info("[" + Thread.currentThread().getName() + "] Load Service " + cacheListenerService);
|
||||
}
|
||||
field.set(src, source);
|
||||
rf.inject(source, self); // 给 "datasource.nodeid" 赋值;
|
||||
rf.inject(source, self); // 给其可能包含@Resource的字段赋值;
|
||||
} catch (Exception e) {
|
||||
logger.log(Level.SEVERE, "DataSource inject error", e);
|
||||
}
|
||||
@@ -250,14 +253,14 @@ public abstract class NodeServer {
|
||||
resourceFactory.register((ResourceFactory rf, final Object src, final String resourceName, Field field, final Object attachment) -> {
|
||||
try {
|
||||
if (field.getAnnotation(Resource.class) == null) return;
|
||||
if ((src instanceof Service) && Sncp.isRemote((Service) src)) return; //远程模式不得注入 CacheSource
|
||||
|
||||
SncpClient client = Sncp.getSncpClient((Service) src);
|
||||
Transport sameGroupTransport = Sncp.getSameGroupTransport((Service) src);
|
||||
if ((src instanceof Service) && Sncp.isRemote((Service) src)) return; //远程模式不需要注入 CacheSource
|
||||
final Service srcService = (Service) src;
|
||||
SncpClient client = Sncp.getSncpClient(srcService);
|
||||
Transport sameGroupTransport = Sncp.getSameGroupTransport(srcService);
|
||||
Transport[] dts = Sncp.getDiffGroupTransports((Service) src);
|
||||
List<Transport> diffGroupTransports = dts == null ? new ArrayList<>() : Arrays.asList(dts);
|
||||
final InetSocketAddress sncpAddr = client == null ? null : client.getClientAddress();
|
||||
final CacheSourceService source = Sncp.createLocalService(resourceName, getExecutor(), appResFactory, CacheSourceService.class, sncpAddr, sameGroupTransport, diffGroupTransports);
|
||||
final CacheMemorySource source = Sncp.createLocalService(resourceName, getExecutor(), appResFactory, CacheMemorySource.class, sncpAddr, Sncp.getSncpGroup(srcService), Sncp.getGroups(srcService), Sncp.getConf(srcService), sameGroupTransport, diffGroupTransports);
|
||||
Type genericType = field.getGenericType();
|
||||
ParameterizedType pt = (genericType instanceof ParameterizedType) ? (ParameterizedType) genericType : null;
|
||||
Type valType = pt == null ? null : pt.getActualTypeArguments()[1];
|
||||
@@ -270,12 +273,11 @@ public abstract class NodeServer {
|
||||
rf.inject(source, self); //
|
||||
((Service) source).init(null);
|
||||
|
||||
if ((src instanceof WebSocketNodeService) && sncpAddr != null) { //只有WebSocketNodeService的服务才需要给SNCP服务注入CacheSourceService
|
||||
if ((src instanceof WebSocketNodeService) && sncpAddr != null) { //只有WebSocketNodeService的服务才需要给SNCP服务注入CacheMemorySource
|
||||
NodeSncpServer sncpServer = application.findNodeSncpServer(sncpAddr);
|
||||
Set<String> gs = application.findSncpGroups(sameGroupTransport, diffGroupTransports);
|
||||
ServiceWrapper wrapper = new ServiceWrapper(CacheSourceService.class, (Service) source, resourceName, sncpServer.getSncpGroup(), gs, null);
|
||||
sncpServer.getSncpServer().addSncpServlet(wrapper);
|
||||
logger.info("[" + Thread.currentThread().getName() + "] Load Service " + wrapper.getService());
|
||||
sncpServer.getSncpServer().addSncpServlet((Service) source);
|
||||
logger.info("[" + Thread.currentThread().getName() + "] Load Service " + source);
|
||||
}
|
||||
logger.info("[" + Thread.currentThread().getName() + "] Load Source " + source);
|
||||
} catch (Exception e) {
|
||||
@@ -292,55 +294,55 @@ public abstract class NodeServer {
|
||||
ResourceFactory regFactory = isSNCP() ? application.getResourceFactory() : resourceFactory;
|
||||
|
||||
for (FilterEntry<Service> entry : entrys) { //service实现类
|
||||
final Class<? extends Service> type = entry.getType();
|
||||
if (Modifier.isFinal(type.getModifiers())) continue; //修饰final的类跳过
|
||||
if (!Modifier.isPublic(type.getModifiers())) continue;
|
||||
final Class<? extends Service> serviceImplClass = entry.getType();
|
||||
if (Modifier.isFinal(serviceImplClass.getModifiers())) continue; //修饰final的类跳过
|
||||
if (!Modifier.isPublic(serviceImplClass.getModifiers())) continue;
|
||||
if (entry.isExpect()) {
|
||||
if (Modifier.isAbstract(type.getModifiers())) continue; //修饰abstract的类跳过
|
||||
if (DataSource.class.isAssignableFrom(type)) continue;
|
||||
if (CacheSource.class.isAssignableFrom(type)) continue;
|
||||
if (DataCacheListener.class.isAssignableFrom(type)) continue;
|
||||
if (WebSocketNode.class.isAssignableFrom(type)) continue;
|
||||
if (Modifier.isAbstract(serviceImplClass.getModifiers())) continue; //修饰abstract的类跳过
|
||||
if (DataSource.class.isAssignableFrom(serviceImplClass)) continue;
|
||||
if (CacheSource.class.isAssignableFrom(serviceImplClass)) continue;
|
||||
if (DataCacheListener.class.isAssignableFrom(serviceImplClass)) continue;
|
||||
if (WebSocketNode.class.isAssignableFrom(serviceImplClass)) continue;
|
||||
}
|
||||
if (entry.getName().contains("$")) throw new RuntimeException("<name> value cannot contains '$' in " + entry.getProperty());
|
||||
Service oldother = resourceFactory.find(entry.getName(), type);
|
||||
Service oldother = resourceFactory.find(entry.getName(), serviceImplClass);
|
||||
if (oldother != null) { //Server加载Service时需要判断是否已经加载过了。
|
||||
interceptorServiceWrappers.add(new NodeInterceptor.InterceptorServiceWrapper(entry.getName(), type, oldother));
|
||||
interceptorServices.add(oldother);
|
||||
continue;
|
||||
}
|
||||
final HashSet<String> groups = entry.getGroups(); //groups.isEmpty()表示<services>没有配置groups属性。
|
||||
if (groups.isEmpty() && isSNCP() && this.sncpGroup != null) groups.add(this.sncpGroup);
|
||||
|
||||
final boolean localed = (this.sncpAddress == null && entry.isEmptyGroups() && !type.isInterface() && !Modifier.isAbstract(type.getModifiers())) //非SNCP的Server,通常是单点服务
|
||||
final boolean localed = (this.sncpAddress == null && entry.isEmptyGroups() && !serviceImplClass.isInterface() && !Modifier.isAbstract(serviceImplClass.getModifiers())) //非SNCP的Server,通常是单点服务
|
||||
|| groups.contains(this.sncpGroup) //本地IP含在内的
|
||||
|| (this.sncpGroup == null && entry.isEmptyGroups()) //空的SNCP配置
|
||||
|| type.getAnnotation(LocalService.class) != null;//本地模式
|
||||
if (localed && (type.isInterface() || Modifier.isAbstract(type.getModifiers()))) continue; //本地模式不能实例化接口和抽象类的Service类
|
||||
|| serviceImplClass.getAnnotation(LocalService.class) != null;//本地模式
|
||||
if (localed && (serviceImplClass.isInterface() || Modifier.isAbstract(serviceImplClass.getModifiers()))) continue; //本地模式不能实例化接口和抽象类的Service类
|
||||
final BiConsumer<ResourceFactory, Boolean> runner = (ResourceFactory rf, Boolean needinject) -> {
|
||||
try {
|
||||
Service service;
|
||||
if (localed) { //本地模式
|
||||
service = Sncp.createLocalService(entry.getName(), getExecutor(), application.getResourceFactory(), type,
|
||||
NodeServer.this.sncpAddress, loadTransport(NodeServer.this.sncpGroup), loadTransports(groups));
|
||||
service = Sncp.createLocalService(entry.getName(), getExecutor(), application.getResourceFactory(), serviceImplClass,
|
||||
NodeServer.this.sncpAddress, NodeServer.this.sncpGroup, groups, entry.getProperty(), loadTransport(NodeServer.this.sncpGroup), loadTransports(groups));
|
||||
} else {
|
||||
service = Sncp.createRemoteService(entry.getName(), getExecutor(), type, NodeServer.this.sncpAddress, loadTransport(groups));
|
||||
service = Sncp.createRemoteService(entry.getName(), getExecutor(), serviceImplClass, NodeServer.this.sncpAddress, null, groups, entry.getProperty(), loadTransport(groups));
|
||||
}
|
||||
if (SncpClient.parseMethod(type).isEmpty()) return; //class没有可用的方法, 通常为BaseService
|
||||
final ServiceWrapper wrapper = new ServiceWrapper(type, service, entry.getName(), localed ? NodeServer.this.sncpGroup : null, groups, entry.getProperty());
|
||||
for (final Class restype : wrapper.getTypes()) {
|
||||
if (resourceFactory.find(wrapper.getName(), restype) == null) {
|
||||
regFactory.register(wrapper.getName(), restype, wrapper.getService());
|
||||
if (needinject) rf.inject(wrapper.getService()); //动态加载的Service也存在按需加载的注入资源
|
||||
if (SncpClient.parseMethod(serviceImplClass).isEmpty()) return; //class没有可用的方法, 通常为BaseService
|
||||
//final ServiceWrapper wrapper = new ServiceWrapper(serviceImplClass, service, entry.getName(), localed ? NodeServer.this.sncpGroup : null, groups, entry.getProperty());
|
||||
for (final Class restype : Sncp.getResourceTypes(service)) {
|
||||
if (resourceFactory.find(entry.getName(), restype) == null) {
|
||||
regFactory.register(entry.getName(), restype, service);
|
||||
if (needinject) rf.inject(service); //动态加载的Service也存在按需加载的注入资源
|
||||
} else if (isSNCP() && !entry.isAutoload()) {
|
||||
throw new RuntimeException(ServiceWrapper.class.getSimpleName() + "(class:" + type.getName() + ", name:" + entry.getName() + ", group:" + groups + ") is repeat.");
|
||||
throw new RuntimeException(restype.getSimpleName() + "(class:" + serviceImplClass.getName() + ", name:" + entry.getName() + ", group:" + groups + ") is repeat.");
|
||||
}
|
||||
}
|
||||
if (wrapper.isRemote()) {
|
||||
remoteServiceWrappers.add(wrapper);
|
||||
if (Sncp.isRemote(service)) {
|
||||
remoteServices.add(service);
|
||||
} else {
|
||||
localServiceWrappers.add(wrapper);
|
||||
interceptorServiceWrappers.add(new NodeInterceptor.InterceptorServiceWrapper(entry.getName(), type, service));
|
||||
if (consumer != null) consumer.accept(wrapper);
|
||||
localServices.add(service);
|
||||
interceptorServices.add(service);
|
||||
if (consumer != null) consumer.accept(service);
|
||||
}
|
||||
} catch (RuntimeException ex) {
|
||||
throw ex;
|
||||
@@ -352,7 +354,9 @@ public abstract class NodeServer {
|
||||
ResourceFactory.ResourceLoader resourceLoader = (ResourceFactory rf, final Object src, final String resourceName, Field field, final Object attachment) -> {
|
||||
runner.accept(rf, true);
|
||||
};
|
||||
for (final Class restype : ServiceWrapper.parseTypes(entry.getType())) {
|
||||
ResourceType rty = entry.getType().getAnnotation(ResourceType.class);
|
||||
Class[] resTypes = rty == null ? new Class[]{} : rty.value();
|
||||
for (final Class restype : resTypes) {
|
||||
resourceFactory.register(resourceLoader, restype);
|
||||
}
|
||||
} else {
|
||||
@@ -366,30 +370,38 @@ public abstract class NodeServer {
|
||||
|
||||
final StringBuilder sb = logger.isLoggable(Level.INFO) ? new StringBuilder() : null;
|
||||
//---------------- inject ----------------
|
||||
new ArrayList<>(localServiceWrappers).forEach(y -> {
|
||||
resourceFactory.inject(y.getService(), NodeServer.this);
|
||||
new ArrayList<>(localServices).forEach(y -> {
|
||||
resourceFactory.inject(y, NodeServer.this);
|
||||
calcMaxLength(y);
|
||||
});
|
||||
new ArrayList<>(remoteServiceWrappers).forEach(y -> {
|
||||
resourceFactory.inject(y.getService(), NodeServer.this);
|
||||
new ArrayList<>(remoteServices).forEach(y -> {
|
||||
resourceFactory.inject(y, NodeServer.this);
|
||||
calcMaxLength(y);
|
||||
});
|
||||
|
||||
if (sb != null) {
|
||||
remoteServiceWrappers.forEach(y -> {
|
||||
sb.append(threadName).append(y.toSimpleString()).append(" load and inject").append(LINE_SEPARATOR);
|
||||
remoteServices.forEach(y -> {
|
||||
sb.append(threadName).append(Sncp.toSimpleString(y, maxNameLength, maxClassNameLength)).append(" load and inject").append(LINE_SEPARATOR);
|
||||
});
|
||||
}
|
||||
//----------------- init -----------------
|
||||
List<ServiceWrapper> swlist = new ArrayList<>(localServiceWrappers);
|
||||
Collections.sort(swlist);
|
||||
localServiceWrappers.clear();
|
||||
localServiceWrappers.addAll(swlist);
|
||||
List<Service> swlist = new ArrayList<>(localServices);
|
||||
Collections.sort(swlist, (o1, o2) -> {
|
||||
int rs = Sncp.getResourceTypes(o1)[0].getName().compareTo(Sncp.getResourceTypes(o2)[0].getName());
|
||||
if (rs == 0) rs = Sncp.getResourceName(o1).compareTo(Sncp.getResourceName(o2));
|
||||
return rs;
|
||||
});
|
||||
localServices.clear();
|
||||
localServices.addAll(swlist);
|
||||
final List<String> slist = sb == null ? null : new CopyOnWriteArrayList<>();
|
||||
CountDownLatch clds = new CountDownLatch(localServiceWrappers.size());
|
||||
localServiceWrappers.parallelStream().forEach(y -> {
|
||||
CountDownLatch clds = new CountDownLatch(localServices.size());
|
||||
localServices.parallelStream().forEach(y -> {
|
||||
try {
|
||||
long s = System.currentTimeMillis();
|
||||
y.getService().init(y.getConf());
|
||||
y.init(Sncp.getConf(y));
|
||||
long e = System.currentTimeMillis() - s;
|
||||
if (slist != null) slist.add(new StringBuilder().append(threadName).append(y.toSimpleString()).append(" load and init in ").append(e).append(" ms").append(LINE_SEPARATOR).toString());
|
||||
String serstr = Sncp.toSimpleString(y, maxNameLength, maxClassNameLength);
|
||||
if (slist != null) slist.add(new StringBuilder().append(threadName).append(serstr).append(" load and init in ").append(e).append(" ms").append(LINE_SEPARATOR).toString());
|
||||
} finally {
|
||||
clds.countDown();
|
||||
}
|
||||
@@ -405,6 +417,20 @@ public abstract class NodeServer {
|
||||
if (sb != null && sb.length() > 0) logger.log(Level.INFO, sb.toString());
|
||||
}
|
||||
|
||||
private void calcMaxLength(Service y) { //计算toString中的长度
|
||||
maxNameLength = Math.max(maxNameLength, Sncp.getResourceName(y).length());
|
||||
StringBuilder s = new StringBuilder();
|
||||
Class[] types = Sncp.getResourceTypes(y);
|
||||
if (types.length == 1) {
|
||||
s.append(types[0].getName());
|
||||
} else {
|
||||
s.append('[');
|
||||
s.append(Arrays.asList(types).stream().map((Class t) -> t.getName()).collect(Collectors.joining(",")));
|
||||
s.append(']');
|
||||
}
|
||||
maxClassNameLength = Math.max(maxClassNameLength, s.length() + 1);
|
||||
}
|
||||
|
||||
protected List<Transport> loadTransports(final HashSet<String> groups) {
|
||||
if (groups == null) return null;
|
||||
final List<Transport> transports = new ArrayList<>();
|
||||
@@ -559,12 +585,12 @@ public abstract class NodeServer {
|
||||
public void shutdown() throws IOException {
|
||||
if (interceptor != null) interceptor.preShutdown(this);
|
||||
final StringBuilder sb = logger.isLoggable(Level.INFO) ? new StringBuilder() : null;
|
||||
localServiceWrappers.forEach(y -> {
|
||||
localServices.forEach(y -> {
|
||||
long s = System.currentTimeMillis();
|
||||
y.getService().destroy(y.getConf());
|
||||
y.destroy(Sncp.getConf(y));
|
||||
long e = System.currentTimeMillis() - s;
|
||||
if (e > 2 && sb != null) {
|
||||
sb.append(y.toSimpleString()).append(" destroy ").append(e).append("ms").append(LINE_SEPARATOR);
|
||||
sb.append(Sncp.toSimpleString(y, maxNameLength, maxClassNameLength)).append(" destroy ").append(e).append("ms").append(LINE_SEPARATOR);
|
||||
}
|
||||
});
|
||||
if (sb != null && sb.length() > 0) logger.log(Level.INFO, sb.toString());
|
||||
@@ -575,16 +601,16 @@ public abstract class NodeServer {
|
||||
return (T) server;
|
||||
}
|
||||
|
||||
public Set<NodeInterceptor.InterceptorServiceWrapper> getInterceptorServiceWrappers() {
|
||||
return new LinkedHashSet<>(interceptorServiceWrappers);
|
||||
public Set<Service> getInterceptorServices() {
|
||||
return new LinkedHashSet<>(interceptorServices);
|
||||
}
|
||||
|
||||
public Set<ServiceWrapper> getLocalServiceWrappers() {
|
||||
return new LinkedHashSet<>(localServiceWrappers);
|
||||
public Set<Service> getLocalServices() {
|
||||
return new LinkedHashSet<>(localServices);
|
||||
}
|
||||
|
||||
public Set<ServiceWrapper> getRemoteServiceWrappers() {
|
||||
return new LinkedHashSet<>(remoteServiceWrappers);
|
||||
public Set<Service> getRemoteServices() {
|
||||
return new LinkedHashSet<>(remoteServices);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import java.util.*;
|
||||
import java.util.logging.*;
|
||||
import org.redkale.net.*;
|
||||
import org.redkale.net.sncp.*;
|
||||
import org.redkale.service.Service;
|
||||
import org.redkale.util.*;
|
||||
|
||||
/**
|
||||
@@ -48,8 +49,8 @@ public class NodeSncpServer extends NodeServer {
|
||||
return sncpServer == null ? null : sncpServer.getSocketAddress();
|
||||
}
|
||||
|
||||
public void consumerAccept(ServiceWrapper wrapper) {
|
||||
if (this.consumer != null) this.consumer.accept(wrapper);
|
||||
public void consumerAccept(Service service) {
|
||||
if (this.consumer != null) this.consumer.accept(service);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -109,8 +109,12 @@ public class Context {
|
||||
return charset;
|
||||
}
|
||||
|
||||
public void submit(Runnable r) {
|
||||
executor.submit(r);
|
||||
public Future<?> submitAsync(Runnable r) {
|
||||
return executor.submit(r);
|
||||
}
|
||||
|
||||
public void runAsync(Runnable r) {
|
||||
executor.execute(r);
|
||||
}
|
||||
|
||||
public int getBufferCapacity() {
|
||||
|
||||
@@ -92,7 +92,7 @@ public abstract class ProtocolServer {
|
||||
SocketAddress address = serchannel.receive(buffer);
|
||||
buffer.flip();
|
||||
AsyncConnection conn = AsyncConnection.create(serchannel, address, false, readTimeoutSecond, writeTimeoutSecond);
|
||||
context.submit(new PrepareRunner(context, conn, buffer));
|
||||
context.runAsync(new PrepareRunner(context, conn, buffer));
|
||||
} catch (Exception e) {
|
||||
context.offerBuffer(buffer);
|
||||
}
|
||||
@@ -160,7 +160,7 @@ public abstract class ProtocolServer {
|
||||
@Override
|
||||
public void completed(final AsynchronousSocketChannel channel, Void attachment) {
|
||||
serchannel.accept(null, this);
|
||||
context.submit(new PrepareRunner(context, AsyncConnection.create(channel, null, context.readTimeoutSecond, context.writeTimeoutSecond), null));
|
||||
context.submitAsync(new PrepareRunner(context, AsyncConnection.create(channel, null, context.readTimeoutSecond, context.writeTimeoutSecond), null));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -117,7 +117,7 @@ public abstract class Response<C extends Context, R extends Request<C>> {
|
||||
request.recycle();
|
||||
if (channel != null) {
|
||||
if (keepAlive) {
|
||||
this.context.submit(new PrepareRunner(context, channel, null));
|
||||
this.context.runAsync(new PrepareRunner(context, channel, null));
|
||||
} else {
|
||||
try {
|
||||
if (channel.isOpen()) channel.close();
|
||||
@@ -162,12 +162,14 @@ public abstract class Response<C extends Context, R extends Request<C>> {
|
||||
}
|
||||
|
||||
public void finish(boolean kill) {
|
||||
if (!this.inited) return; //避免重复关闭
|
||||
//System.println("耗时: " + (System.currentTimeMillis() - request.createtime));
|
||||
if (kill) refuseAlive();
|
||||
this.context.responsePool.offer(this);
|
||||
}
|
||||
|
||||
public void finish(final byte[] bs) {
|
||||
if (!this.inited) return; //避免重复关闭
|
||||
if (this.context.bufferCapacity == bs.length) {
|
||||
ByteBuffer buffer = this.context.pollBuffer();
|
||||
buffer.put(bs);
|
||||
@@ -179,19 +181,23 @@ public abstract class Response<C extends Context, R extends Request<C>> {
|
||||
}
|
||||
|
||||
public void finish(ByteBuffer buffer) {
|
||||
if (!this.inited) return; //避免重复关闭
|
||||
this.channel.write(buffer, buffer, finishHandler);
|
||||
}
|
||||
|
||||
public void finish(boolean kill, ByteBuffer buffer) {
|
||||
if (!this.inited) return; //避免重复关闭
|
||||
if (kill) refuseAlive();
|
||||
this.channel.write(buffer, buffer, finishHandler);
|
||||
}
|
||||
|
||||
public void finish(ByteBuffer... buffers) {
|
||||
if (!this.inited) return; //避免重复关闭
|
||||
this.channel.write(buffers, buffers, finishHandler2);
|
||||
}
|
||||
|
||||
public void finish(boolean kill, ByteBuffer... buffers) {
|
||||
if (!this.inited) return; //避免重复关闭
|
||||
if (kill) refuseAlive();
|
||||
this.channel.write(buffers, buffers, finishHandler2);
|
||||
}
|
||||
|
||||
@@ -25,8 +25,8 @@ public class WorkThread extends Thread {
|
||||
this.setDaemon(true);
|
||||
}
|
||||
|
||||
public void submit(Runnable runner) {
|
||||
executor.submit(runner);
|
||||
public void runAsync(Runnable runner) {
|
||||
executor.execute(runner);
|
||||
}
|
||||
|
||||
public ExecutorService getExecutor() {
|
||||
|
||||
@@ -13,6 +13,7 @@ import java.nio.channels.*;
|
||||
import java.nio.file.*;
|
||||
import java.text.*;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.logging.Level;
|
||||
import org.redkale.convert.json.JsonConvert;
|
||||
@@ -311,12 +312,69 @@ public class HttpResponse extends Response<HttpContext, HttpRequest> {
|
||||
finish(convert.convertTo(context.getBufferSupplier(), ret));
|
||||
}
|
||||
|
||||
/**
|
||||
* 将CompletableFuture的结果对象以JSON格式输出
|
||||
*
|
||||
* @param future 输出对象的句柄
|
||||
*/
|
||||
public void finishJson(final CompletableFuture future) {
|
||||
finishJson(request.getJsonConvert(), future);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将CompletableFuture的结果对象以JSON格式输出
|
||||
*
|
||||
* @param convert 指定的JsonConvert
|
||||
* @param future 输出对象的句柄
|
||||
*/
|
||||
public void finishJson(final JsonConvert convert, final CompletableFuture future) {
|
||||
future.whenComplete((v, e) -> {
|
||||
if (e != null) {
|
||||
context.getLogger().log(Level.WARNING, "Servlet occur, forece to close channel. request = " + request, e);
|
||||
finish(500, null);
|
||||
return;
|
||||
}
|
||||
if (v instanceof CharSequence) {
|
||||
finish(v.toString());
|
||||
} else if (v instanceof org.redkale.service.RetResult) {
|
||||
finishJson(convert, (org.redkale.service.RetResult) v);
|
||||
} else {
|
||||
finishJson(convert, v);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 将CompletableFuture的结果对象以JSON格式输出
|
||||
*
|
||||
* @param convert 指定的JsonConvert
|
||||
* @param type 指定的类型
|
||||
* @param future 输出对象的句柄
|
||||
*/
|
||||
public void finishJson(final JsonConvert convert, final Type type, final CompletableFuture future) {
|
||||
future.whenComplete((v, e) -> {
|
||||
if (e != null) {
|
||||
context.getLogger().log(Level.WARNING, "Servlet occur, forece to close channel. request = " + request, e);
|
||||
finish(500, null);
|
||||
return;
|
||||
}
|
||||
if (v instanceof CharSequence) {
|
||||
finish(v.toString());
|
||||
} else if (v instanceof org.redkale.service.RetResult) {
|
||||
finishJson(convert, (org.redkale.service.RetResult) v);
|
||||
} else {
|
||||
finishJson(convert, type, v);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 将指定字符串以响应结果输出
|
||||
*
|
||||
* @param obj 输出内容
|
||||
*/
|
||||
public void finish(String obj) {
|
||||
if (isClosed()) return;
|
||||
if (this.recycleListener != null) this.output = obj;
|
||||
if (obj == null || obj.isEmpty()) {
|
||||
final ByteBuffer headbuf = createHeader();
|
||||
@@ -358,6 +416,7 @@ public class HttpResponse extends Response<HttpContext, HttpRequest> {
|
||||
* @param message 输出内容
|
||||
*/
|
||||
public void finish(int status, String message) {
|
||||
if (isClosed()) return;
|
||||
this.status = status;
|
||||
if (status != 200) super.refuseAlive();
|
||||
finish(message);
|
||||
@@ -384,6 +443,7 @@ public class HttpResponse extends Response<HttpContext, HttpRequest> {
|
||||
*/
|
||||
@Override
|
||||
public void finish(final byte[] bs) {
|
||||
if (isClosed()) return; //避免重复关闭
|
||||
if (this.context.getBufferCapacity() == bs.length) {
|
||||
ByteBuffer buffer = this.context.pollBuffer();
|
||||
buffer.put(bs);
|
||||
@@ -412,6 +472,7 @@ public class HttpResponse extends Response<HttpContext, HttpRequest> {
|
||||
*/
|
||||
@Override
|
||||
public void finish(boolean kill, ByteBuffer buffer) {
|
||||
if (isClosed()) return; //避免重复关闭
|
||||
if (!this.headsended) {
|
||||
this.contentLength = buffer == null ? 0 : buffer.remaining();
|
||||
ByteBuffer headbuf = createHeader();
|
||||
@@ -444,6 +505,7 @@ public class HttpResponse extends Response<HttpContext, HttpRequest> {
|
||||
*/
|
||||
@Override
|
||||
public void finish(boolean kill, ByteBuffer... buffers) {
|
||||
if (isClosed()) return; //避免重复关闭
|
||||
if (bufferHandler != null) {
|
||||
ByteBuffer[] bufs = bufferHandler.execute(this, buffers);
|
||||
if (bufs != null) buffers = bufs;
|
||||
|
||||
@@ -11,6 +11,7 @@ import static java.lang.annotation.ElementType.*;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
import java.lang.reflect.*;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import jdk.internal.org.objectweb.asm.*;
|
||||
import static jdk.internal.org.objectweb.asm.ClassWriter.COMPUTE_FRAMES;
|
||||
import static jdk.internal.org.objectweb.asm.Opcodes.*;
|
||||
@@ -110,11 +111,14 @@ public final class Rest {
|
||||
if (!java.lang.reflect.Modifier.isPublic(mod)) return null;
|
||||
if (java.lang.reflect.Modifier.isAbstract(mod)) return null;
|
||||
|
||||
final java.lang.reflect.Type futureRestOutputType = new TypeToken<CompletableFuture<RestOutput>>() {
|
||||
}.getType();
|
||||
final String serviceDesc = Type.getDescriptor(serviceType);
|
||||
final String webServletDesc = Type.getDescriptor(WebServlet.class);
|
||||
final String reqDesc = Type.getDescriptor(HttpRequest.class);
|
||||
final String respDesc = Type.getDescriptor(HttpResponse.class);
|
||||
final String retDesc = Type.getDescriptor(RetResult.class);
|
||||
final String futureDesc = Type.getDescriptor(CompletableFuture.class);
|
||||
final String flipperDesc = Type.getDescriptor(Flipper.class);
|
||||
final String restoutputDesc = Type.getDescriptor(RestOutput.class);
|
||||
final String attrDesc = Type.getDescriptor(org.redkale.util.Attribute.class);
|
||||
@@ -257,6 +261,7 @@ public final class Rest {
|
||||
for (final MappingEntry entry : entrys) {
|
||||
final Method method = entry.mappingMethod;
|
||||
final Class returnType = method.getReturnType();
|
||||
final java.lang.reflect.Type returnGenericType = method.getGenericReturnType();
|
||||
final String methodDesc = Type.getMethodDescriptor(method);
|
||||
final Parameter[] params = method.getParameters();
|
||||
|
||||
@@ -923,6 +928,21 @@ public final class Rest {
|
||||
mv.visitMethodInsn(INVOKEVIRTUAL, respInternalName, "finish", "(Ljava/lang/String;)V", false);
|
||||
mv.visitInsn(RETURN);
|
||||
maxLocals++;
|
||||
} else if (futureRestOutputType == returnGenericType) {
|
||||
mv.visitVarInsn(ASTORE, maxLocals);
|
||||
mv.visitVarInsn(ALOAD, 0);
|
||||
mv.visitVarInsn(ALOAD, 2);
|
||||
mv.visitVarInsn(ALOAD, maxLocals);
|
||||
mv.visitMethodInsn(INVOKEVIRTUAL, newDynName, "finishJson", "(" + respDesc + futureDesc + ")V", false);
|
||||
mv.visitInsn(RETURN);
|
||||
maxLocals++;
|
||||
} else if (CompletableFuture.class.isAssignableFrom(returnType)) {
|
||||
mv.visitVarInsn(ASTORE, maxLocals);
|
||||
mv.visitVarInsn(ALOAD, 2);//response
|
||||
mv.visitVarInsn(ALOAD, maxLocals);
|
||||
mv.visitMethodInsn(INVOKEVIRTUAL, respInternalName, "finishJson", "(" + futureDesc + ")V", false);
|
||||
mv.visitInsn(RETURN);
|
||||
maxLocals++;
|
||||
} else {
|
||||
mv.visitVarInsn(ASTORE, maxLocals);
|
||||
mv.visitVarInsn(ALOAD, 2); //response
|
||||
|
||||
@@ -6,7 +6,8 @@
|
||||
package org.redkale.net.http;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.logging.Level;
|
||||
import jdk.internal.org.objectweb.asm.*;
|
||||
import static jdk.internal.org.objectweb.asm.Opcodes.*;
|
||||
import org.redkale.util.*;
|
||||
@@ -22,6 +23,22 @@ public abstract class RestHttpServlet<T> extends HttpBaseServlet {
|
||||
|
||||
protected abstract T currentUser(HttpRequest req) throws IOException;
|
||||
|
||||
protected void finishJson(final HttpResponse response, CompletableFuture<RestOutput> future) throws IOException {
|
||||
future.whenComplete((output, e) -> {
|
||||
if (e != null) {
|
||||
response.getContext().getLogger().log(Level.WARNING, "Servlet occur, forece to close channel. request = " + response.getRequest(), e);
|
||||
response.finish(500, null);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
finishJson(response, output);
|
||||
} catch (IOException ioe) {
|
||||
response.getContext().getLogger().log(Level.WARNING, "Servlet finish RestOutput occur, forece to close channel. request = " + response.getRequest(), ioe);
|
||||
response.finish(500, null);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected void finishJson(final HttpResponse response, RestOutput output) throws IOException {
|
||||
if (output == null) {
|
||||
response.finishJson(output);
|
||||
@@ -30,11 +47,13 @@ public abstract class RestHttpServlet<T> extends HttpBaseServlet {
|
||||
if (output.getContentType() != null) response.setContentType(output.getContentType());
|
||||
response.addHeader(output.getHeaders());
|
||||
response.addCookie(output.getCookies());
|
||||
|
||||
response.setStatus(output.getStatus() < 1 ? 200 : output.getStatus());
|
||||
if (output.getResult() instanceof File) {
|
||||
response.finish((File) output.getResult());
|
||||
} else if (output.getResult() instanceof String) {
|
||||
response.finish((String) output.getResult());
|
||||
} else if (output.getResult() == null) {
|
||||
response.finish(output.getMessage());
|
||||
} else {
|
||||
response.finishJson(output.getResult());
|
||||
}
|
||||
|
||||
@@ -27,6 +27,10 @@ public class RestOutput<T> {
|
||||
|
||||
private T result;
|
||||
|
||||
private int status = 0; //不设置则为 200
|
||||
|
||||
private String message;
|
||||
|
||||
public RestOutput() {
|
||||
}
|
||||
|
||||
@@ -78,4 +82,20 @@ public class RestOutput<T> {
|
||||
this.result = result;
|
||||
}
|
||||
|
||||
public int getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(int status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public void setMessage(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.net.http;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* 功能同JSR 315 (java-servlet 3.0) 规范中的 @WebInitParam
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
@Target({ElementType.TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface WebInitParam {
|
||||
|
||||
/**
|
||||
* 参数名
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
String name();
|
||||
|
||||
/**
|
||||
* 参数值
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
String value();
|
||||
|
||||
/**
|
||||
* 参数描述
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
String description() default "";
|
||||
}
|
||||
@@ -49,13 +49,6 @@ public @interface WebServlet {
|
||||
*/
|
||||
int moduleid() default 0;
|
||||
|
||||
/**
|
||||
* 参数
|
||||
*
|
||||
* @return WebInitParam[]
|
||||
*/
|
||||
WebInitParam[] initParams() default {};
|
||||
|
||||
/**
|
||||
* 备注描述
|
||||
*
|
||||
|
||||
@@ -10,6 +10,7 @@ import java.io.*;
|
||||
import java.net.*;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import org.redkale.convert.json.JsonConvert;
|
||||
import org.redkale.net.*;
|
||||
import org.redkale.util.Comment;
|
||||
|
||||
@@ -76,6 +77,8 @@ public abstract class WebSocket {
|
||||
|
||||
String _remoteAddr;//不可能为空
|
||||
|
||||
JsonConvert _jsonConvert; //不可能为空
|
||||
|
||||
private final long createtime = System.currentTimeMillis();
|
||||
|
||||
private final Map<String, Object> attributes = new ConcurrentHashMap<>();
|
||||
@@ -162,15 +165,30 @@ public abstract class WebSocket {
|
||||
}
|
||||
|
||||
/**
|
||||
* 给自身发送消息, 消息类型是String或byte[]
|
||||
* 给自身发送消息, 消息类型是String或byte[]或可JSON化对象
|
||||
*
|
||||
* @param message 不可为空, 只能是String或者byte[]
|
||||
* @param message 不可为空, 只能是String或byte[]或可JSON化对象
|
||||
*
|
||||
* @return 0表示成功, 非0表示错误码
|
||||
*/
|
||||
public final int send(Object message) {
|
||||
return send(message, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 给自身发送消息, 消息类型是String或byte[]或可JSON化对象
|
||||
*
|
||||
* @param message 不可为空, 只能是String或byte[]或可JSON化对象
|
||||
* @param last 是否最后一条
|
||||
*
|
||||
* @return 0表示成功, 非0表示错误码
|
||||
*/
|
||||
public final int send(Serializable message, boolean last) {
|
||||
return send(new WebSocketPacket(message, last));
|
||||
public final int send(Object message, boolean last) {
|
||||
if (message == null || message instanceof CharSequence || message instanceof byte[]) {
|
||||
return send(new WebSocketPacket((Serializable) message, last));
|
||||
} else {
|
||||
return send(new WebSocketPacket(_jsonConvert.convertTo(message), last));
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------
|
||||
@@ -195,7 +213,19 @@ public abstract class WebSocket {
|
||||
* @return 为0表示成功, 其他值表示异常
|
||||
*/
|
||||
public final int sendEachMessage(Serializable groupid, byte[] data) {
|
||||
return WebSocket.this.sendEachMessage(groupid, data, true);
|
||||
return sendEachMessage(groupid, data, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 给指定groupid的WebSocketGroup下所有WebSocket节点发送可JSON化对象消息
|
||||
*
|
||||
* @param groupid groupid
|
||||
* @param message 不可为空
|
||||
*
|
||||
* @return 为0表示成功, 其他值表示异常
|
||||
*/
|
||||
public final int sendEachMessage(Serializable groupid, Object message) {
|
||||
return sendEachMessage(groupid, message, true);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -224,6 +254,19 @@ public abstract class WebSocket {
|
||||
return sendMessage(groupid, false, data, last);
|
||||
}
|
||||
|
||||
/**
|
||||
* 给指定groupid的WebSocketGroup下所有WebSocket节点发送可JSON化对象消息
|
||||
*
|
||||
* @param groupid groupid
|
||||
* @param message 不可为空
|
||||
* @param last 是否最后一条
|
||||
*
|
||||
* @return 为0表示成功, 其他值表示异常
|
||||
*/
|
||||
public final int sendEachMessage(Serializable groupid, Object message, boolean last) {
|
||||
return sendMessage(groupid, false, message, last);
|
||||
}
|
||||
|
||||
/**
|
||||
* 给指定groupid的WebSocketGroup下最近接入的WebSocket节点发送文本消息
|
||||
*
|
||||
@@ -248,6 +291,18 @@ public abstract class WebSocket {
|
||||
return sendRecentMessage(groupid, data, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 给指定groupid的WebSocketGroup下最近接入的WebSocket节点发送可JSON化对象消息
|
||||
*
|
||||
* @param groupid groupid
|
||||
* @param message 不可为空
|
||||
*
|
||||
* @return 为0表示成功, 其他值表示异常
|
||||
*/
|
||||
public final int sendRecentMessage(Serializable groupid, Object message) {
|
||||
return sendMessage(groupid, true, message, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 给指定groupid的WebSocketGroup下最近接入的WebSocket节点发送文本消息
|
||||
*
|
||||
@@ -274,6 +329,19 @@ public abstract class WebSocket {
|
||||
return sendMessage(groupid, true, data, last);
|
||||
}
|
||||
|
||||
/**
|
||||
* 给指定groupid的WebSocketGroup下最近接入的WebSocket节点发送可JSON化对象消息
|
||||
*
|
||||
* @param groupid groupid
|
||||
* @param message 不可为空
|
||||
* @param last 是否最后一条
|
||||
*
|
||||
* @return 为0表示成功, 其他值表示异常
|
||||
*/
|
||||
public final int sendRecentMessage(Serializable groupid, Object message, boolean last) {
|
||||
return sendMessage(groupid, true, message, last);
|
||||
}
|
||||
|
||||
private int sendMessage(Serializable groupid, boolean recent, String text, boolean last) {
|
||||
if (_engine.node == null) return RETCODE_NODESERVICE_NULL;
|
||||
int rs = _engine.node.sendMessage(groupid, recent, text, last);
|
||||
@@ -288,6 +356,13 @@ public abstract class WebSocket {
|
||||
return rs;
|
||||
}
|
||||
|
||||
private int sendMessage(Serializable groupid, boolean recent, Object message, boolean last) {
|
||||
if (_engine.node == null) return RETCODE_NODESERVICE_NULL;
|
||||
int rs = _engine.node.sendMessage(groupid, recent, message, last);
|
||||
if (_engine.finest) _engine.logger.finest("wsgroupid:" + groupid + " " + (recent ? "recent " : "") + "send websocket result is " + rs + " on " + this + " by message(" + _jsonConvert.convertTo(message) + ")");
|
||||
return rs;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定groupid在线用户的节点地址列表
|
||||
*
|
||||
|
||||
@@ -15,7 +15,9 @@ import org.redkale.util.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* <p> 详情见: https://redkale.org
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
public final class WebSocketEngine {
|
||||
|
||||
@@ -83,7 +83,7 @@ public final class WebSocketGroup {
|
||||
attributes.put(name, value);
|
||||
}
|
||||
|
||||
public final int send(boolean recent, Serializable message, boolean last) {
|
||||
public final int send(boolean recent, Object message, boolean last) {
|
||||
if (recent) {
|
||||
return recentWebSocket.send(message, last);
|
||||
} else {
|
||||
@@ -91,7 +91,7 @@ public final class WebSocketGroup {
|
||||
}
|
||||
}
|
||||
|
||||
public final int sendEach(Serializable message) {
|
||||
public final int sendEach(Object message) {
|
||||
return sendEach(message, true);
|
||||
}
|
||||
|
||||
@@ -111,7 +111,7 @@ public final class WebSocketGroup {
|
||||
return rs;
|
||||
}
|
||||
|
||||
public final int sendRecent(Serializable message) {
|
||||
public final int sendRecent(Object message) {
|
||||
return sendRecent(message, true);
|
||||
}
|
||||
|
||||
@@ -119,7 +119,10 @@ public final class WebSocketGroup {
|
||||
return recentWebSocket.send(packet);
|
||||
}
|
||||
|
||||
public final int sendEach(Serializable message, boolean last) {
|
||||
public final int sendEach(Object message, boolean last) {
|
||||
if (message != null && !(message instanceof byte[]) && !(message instanceof CharSequence)) {
|
||||
message = recentWebSocket._jsonConvert.convertTo(message);
|
||||
}
|
||||
int rs = 0;
|
||||
for (WebSocket s : list) {
|
||||
rs |= s.send(message, last);
|
||||
@@ -127,7 +130,7 @@ public final class WebSocketGroup {
|
||||
return rs;
|
||||
}
|
||||
|
||||
public final int sendRecent(Serializable message, boolean last) {
|
||||
public final int sendRecent(Object message, boolean last) {
|
||||
return recentWebSocket.send(message, last);
|
||||
}
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@ public abstract class WebSocketNode {
|
||||
|
||||
protected abstract List<String> getOnlineRemoteAddresses(@RpcTargetAddress InetSocketAddress targetAddress, Serializable groupid);
|
||||
|
||||
protected abstract int sendMessage(@RpcTargetAddress InetSocketAddress targetAddress, Serializable groupid, boolean recent, Serializable message, boolean last);
|
||||
protected abstract int sendMessage(@RpcTargetAddress InetSocketAddress targetAddress, Serializable groupid, boolean recent, Object message, boolean last);
|
||||
|
||||
protected abstract void connect(Serializable groupid, InetSocketAddress addr);
|
||||
|
||||
@@ -133,7 +133,7 @@ public abstract class WebSocketNode {
|
||||
engines.put(engine.getEngineid(), engine);
|
||||
}
|
||||
|
||||
public final int sendMessage(Serializable groupid, boolean recent, Serializable message, boolean last) {
|
||||
public final int sendMessage(Serializable groupid, boolean recent, Object message, boolean last) {
|
||||
final Set<String> engineids = localNodes.get(groupid);
|
||||
if (finest) logger.finest("websocket want send message {groupid:" + groupid + ", content:'" + message + "'} from locale node to " + engineids);
|
||||
int rscode = RETCODE_GROUP_EMPTY;
|
||||
@@ -187,44 +187,44 @@ public abstract class WebSocketNode {
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
public final int sendEachMessage(Serializable groupid, String text) {
|
||||
return sendMessage(groupid, false, text);
|
||||
return sendMessage(groupid, false, (Object) text, true);
|
||||
}
|
||||
|
||||
public final int sendEachMessage(Serializable groupid, String text, boolean last) {
|
||||
return sendMessage(groupid, false, text, last);
|
||||
return sendMessage(groupid, false, (Object) text, last);
|
||||
}
|
||||
|
||||
public final int sendRecentMessage(Serializable groupid, String text) {
|
||||
return sendMessage(groupid, true, text);
|
||||
return sendMessage(groupid, true, (Object) text, true);
|
||||
}
|
||||
|
||||
public final int sendRecentMessage(Serializable groupid, String text, boolean last) {
|
||||
return sendMessage(groupid, true, text, last);
|
||||
return sendMessage(groupid, true, (Object) text, last);
|
||||
}
|
||||
|
||||
public final int sendMessage(Serializable groupid, boolean recent, String text) {
|
||||
return sendMessage(groupid, recent, text, true);
|
||||
return sendMessage(groupid, recent, (Object) text, true);
|
||||
}
|
||||
|
||||
public final int sendMessage(Serializable groupid, boolean recent, String text, boolean last) {
|
||||
return sendMessage(groupid, recent, (Serializable) text, last);
|
||||
return sendMessage(groupid, recent, (Object) text, last);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
public final int sendEachMessage(Serializable groupid, byte[] data) {
|
||||
return sendMessage(groupid, false, data);
|
||||
return sendMessage(groupid, false, (Object) data, true);
|
||||
}
|
||||
|
||||
public final int sendEachMessage(Serializable groupid, byte[] data, boolean last) {
|
||||
return sendMessage(groupid, false, data, last);
|
||||
return sendMessage(groupid, false, (Object) data, last);
|
||||
}
|
||||
|
||||
public final int sendRecentMessage(Serializable groupid, byte[] data) {
|
||||
return sendMessage(groupid, true, data);
|
||||
return sendMessage(groupid, true, (Object) data, true);
|
||||
}
|
||||
|
||||
public final int sendRecentMessage(Serializable groupid, byte[] data, boolean last) {
|
||||
return sendMessage(groupid, true, data, last);
|
||||
return sendMessage(groupid, true, (Object) data, last);
|
||||
}
|
||||
|
||||
public final int sendMessage(Serializable groupid, boolean recent, byte[] data) {
|
||||
@@ -232,6 +232,28 @@ public abstract class WebSocketNode {
|
||||
}
|
||||
|
||||
public final int sendMessage(Serializable groupid, boolean recent, byte[] data, boolean last) {
|
||||
return sendMessage(groupid, recent, (Serializable) data, last);
|
||||
return sendMessage(groupid, recent, (Object) data, last);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
public final int sendEachMessage(Serializable groupid, Object message) {
|
||||
return sendMessage(groupid, false, message, true);
|
||||
}
|
||||
|
||||
public final int sendEachMessage(Serializable groupid, Object message, boolean last) {
|
||||
return sendMessage(groupid, false, message, last);
|
||||
}
|
||||
|
||||
public final int sendRecentMessage(Serializable groupid, Object message) {
|
||||
return sendMessage(groupid, true, message, true);
|
||||
}
|
||||
|
||||
public final int sendRecentMessage(Serializable groupid, Object message, boolean last) {
|
||||
return sendMessage(groupid, true, message, last);
|
||||
}
|
||||
|
||||
public final int sendMessage(Serializable groupid, boolean recent, Object message) {
|
||||
return sendMessage(groupid, recent, message, true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import java.security.*;
|
||||
import java.util.*;
|
||||
import java.util.logging.*;
|
||||
import javax.annotation.*;
|
||||
import org.redkale.convert.json.JsonConvert;
|
||||
import org.redkale.service.WebSocketNodeService;
|
||||
import org.redkale.util.*;
|
||||
|
||||
@@ -62,6 +63,9 @@ public abstract class WebSocketServlet extends HttpServlet implements Resourcabl
|
||||
@Comment("是否用于二进制流传输")
|
||||
protected final boolean wsbinary = getClass().getAnnotation(WebSocketBinary.class) != null;
|
||||
|
||||
@Resource
|
||||
protected JsonConvert jsonConvert;
|
||||
|
||||
@Resource(name = "$")
|
||||
protected WebSocketNode node;
|
||||
|
||||
@@ -109,6 +113,7 @@ public abstract class WebSocketServlet extends HttpServlet implements Resourcabl
|
||||
}
|
||||
final WebSocket webSocket = this.createWebSocket();
|
||||
webSocket._engine = engine;
|
||||
webSocket._jsonConvert = jsonConvert;
|
||||
webSocket._remoteAddress = request.getRemoteAddress();
|
||||
webSocket._remoteAddr = request.getRemoteAddr();
|
||||
Serializable sessionid = webSocket.onOpen(request);
|
||||
@@ -141,7 +146,7 @@ public abstract class WebSocketServlet extends HttpServlet implements Resourcabl
|
||||
}
|
||||
webSocket._groupid = groupid;
|
||||
engine.add(webSocket);
|
||||
context.submit(new WebSocketRunner(context, webSocket, response.removeChannel(), wsbinary));
|
||||
context.runAsync(new WebSocketRunner(context, webSocket, response.removeChannel(), wsbinary));
|
||||
response.finish(true);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,156 +0,0 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.net.sncp;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import org.redkale.service.Service;
|
||||
import org.redkale.util.*;
|
||||
|
||||
/**
|
||||
* Service对象的封装类
|
||||
*
|
||||
*
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <T> Service的子类
|
||||
*/
|
||||
public final class ServiceWrapper<T extends Service> implements Comparable<ServiceWrapper> {
|
||||
|
||||
private static volatile int maxClassNameLength = 0;
|
||||
|
||||
private static volatile int maxNameLength = 0;
|
||||
|
||||
private final T service;
|
||||
|
||||
private final AnyValue conf;
|
||||
|
||||
private final String sncpGroup; //自身的组节点名 可能为null
|
||||
|
||||
private final Set<String> groups; //所有的组节点,包含自身
|
||||
|
||||
private final String name;
|
||||
|
||||
private final boolean remote;
|
||||
|
||||
private final Class[] types;
|
||||
|
||||
public ServiceWrapper(T service, String name, String sncpGroup, Set<String> groups, AnyValue conf) {
|
||||
this(null, service, name, sncpGroup, groups, conf);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public ServiceWrapper(Class<T> type, T service, String name, String sncpGroup, Set<String> groups, AnyValue conf) {
|
||||
this.service = service;
|
||||
this.conf = conf;
|
||||
this.sncpGroup = sncpGroup;
|
||||
this.groups = groups;
|
||||
this.name = name;
|
||||
this.remote = Sncp.isRemote(service);
|
||||
ResourceType rty = service.getClass().getAnnotation(ResourceType.class);
|
||||
this.types = rty == null ? new Class[]{type == null ? (Class<T>) service.getClass() : type} : rty.value();
|
||||
|
||||
maxNameLength = Math.max(maxNameLength, name.length());
|
||||
StringBuilder s = new StringBuilder();
|
||||
if (this.types.length == 1) {
|
||||
s.append(types[0].getName());
|
||||
} else {
|
||||
s.append('[');
|
||||
s.append(Arrays.asList(this.types).stream().map((Class t) -> t.getName()).collect(Collectors.joining(",")));
|
||||
s.append(']');
|
||||
}
|
||||
maxClassNameLength = Math.max(maxClassNameLength, s.length() + 1);
|
||||
}
|
||||
|
||||
public static Class[] parseTypes(final Class<? extends Service> servicetype) {
|
||||
ResourceType rty = servicetype.getAnnotation(ResourceType.class);
|
||||
return rty == null ? new Class[]{servicetype} : rty.value();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return toSimpleString();
|
||||
}
|
||||
|
||||
public String toSimpleString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(remote ? "RemoteService" : "LocalService ");
|
||||
int len;
|
||||
if (types.length == 1) {
|
||||
sb.append("(type= ").append(types[0].getName());
|
||||
len = maxClassNameLength - types[0].getName().length();
|
||||
} else {
|
||||
StringBuilder s = new StringBuilder();
|
||||
s.append('[');
|
||||
s.append(Arrays.asList(this.types).stream().map((Class t) -> t.getName()).collect(Collectors.joining(",")));
|
||||
s.append(']');
|
||||
sb.append("(types=").append(s);
|
||||
len = maxClassNameLength - s.length();
|
||||
}
|
||||
|
||||
for (int i = 0; i < len; i++) {
|
||||
sb.append(' ');
|
||||
}
|
||||
sb.append(", name='").append(name).append("'");
|
||||
for (int i = 0; i < maxNameLength - name.length(); i++) {
|
||||
sb.append(' ');
|
||||
}
|
||||
sb.append(")");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == this) return true;
|
||||
if (obj == null) return false;
|
||||
if (!(obj instanceof ServiceWrapper)) return false;
|
||||
ServiceWrapper other = (ServiceWrapper) obj;
|
||||
return (this.types[0].equals(other.types[0]) && this.remote == other.remote && this.name.equals(other.name) && Objects.equals(this.sncpGroup, other.sncpGroup));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = 3;
|
||||
hash = 67 * hash + Objects.hashCode(this.types[0]);
|
||||
hash = 67 * hash + Objects.hashCode(this.sncpGroup);
|
||||
hash = 67 * hash + Objects.hashCode(this.name);
|
||||
hash = 67 * hash + (this.remote ? 1 : 0);
|
||||
return hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(ServiceWrapper o) {
|
||||
int rs = this.types[0].getName().compareTo(o.types[0].getName());
|
||||
if (rs == 0) rs = this.name.compareTo(o.name);
|
||||
return rs;
|
||||
}
|
||||
|
||||
public Class[] getTypes() {
|
||||
return types;
|
||||
}
|
||||
|
||||
public Service getService() {
|
||||
return service;
|
||||
}
|
||||
|
||||
public AnyValue getConf() {
|
||||
return conf;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public boolean isRemote() {
|
||||
return remote;
|
||||
}
|
||||
|
||||
public Set<String> getGroups() {
|
||||
return groups;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -11,6 +11,7 @@ import java.net.InetSocketAddress;
|
||||
import java.security.*;
|
||||
import java.util.*;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.annotation.Resource;
|
||||
import static jdk.internal.org.objectweb.asm.ClassWriter.COMPUTE_FRAMES;
|
||||
import jdk.internal.org.objectweb.asm.*;
|
||||
@@ -55,11 +56,6 @@ public abstract class Sncp {
|
||||
private Sncp() {
|
||||
}
|
||||
|
||||
public static long nodeid(InetSocketAddress ip) {
|
||||
byte[] bytes = ip.getAddress().getAddress();
|
||||
return ((0L + ip.getPort()) << 32) | ((0xffffffff & bytes[0]) << 24) | ((0xffffff & bytes[1]) << 16) | ((0xffff & bytes[2]) << 8) | (0xff & bytes[3]);
|
||||
}
|
||||
|
||||
public static DLong hash(final java.lang.reflect.Method method) {
|
||||
if (method == null) return DLong.ZERO;
|
||||
StringBuilder sb = new StringBuilder(); //不能使用method.toString() 因为包含declaringClass信息导致接口与实现类的方法hash不一致
|
||||
@@ -97,6 +93,62 @@ public abstract class Sncp {
|
||||
return dyn != null && dyn.remote();
|
||||
}
|
||||
|
||||
public static String getResourceName(Service service) {
|
||||
if (service == null) return null;
|
||||
Resource res = service.getClass().getAnnotation(Resource.class);
|
||||
return res == null ? null : res.name();
|
||||
}
|
||||
|
||||
public static Class getServiceType(Service service) {
|
||||
if (service == null) return null;
|
||||
try {
|
||||
Field ts = service.getClass().getDeclaredField(FIELDPREFIX + "_service_type");
|
||||
ts.setAccessible(true);
|
||||
return (Class) ts.get(service);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(service + " not found " + FIELDPREFIX + "_service_type");
|
||||
}
|
||||
}
|
||||
|
||||
public static Class[] getResourceTypes(Service service) {
|
||||
if (service == null) return null;
|
||||
ResourceType types = service.getClass().getAnnotation(ResourceType.class);
|
||||
return types == null ? new Class[]{getServiceType(service)} : types.value();
|
||||
}
|
||||
|
||||
public static String getSncpGroup(Service service) {
|
||||
if (service == null) return null;
|
||||
try {
|
||||
Field ts = service.getClass().getDeclaredField(FIELDPREFIX + "_sncpGroup");
|
||||
ts.setAccessible(true);
|
||||
return (String) ts.get(service);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(service + " not found " + FIELDPREFIX + "_sncpGroup");
|
||||
}
|
||||
}
|
||||
|
||||
public static Set<String> getGroups(Service service) {
|
||||
if (service == null) return null;
|
||||
try {
|
||||
Field ts = service.getClass().getDeclaredField(FIELDPREFIX + "_groups");
|
||||
ts.setAccessible(true);
|
||||
return (Set) ts.get(service);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(service + " not found " + FIELDPREFIX + "_groups");
|
||||
}
|
||||
}
|
||||
|
||||
public static AnyValue getConf(Service service) {
|
||||
if (service == null) return null;
|
||||
try {
|
||||
Field ts = service.getClass().getDeclaredField(FIELDPREFIX + "_conf");
|
||||
ts.setAccessible(true);
|
||||
return (AnyValue) ts.get(service);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(service + " not found " + FIELDPREFIX + "_conf");
|
||||
}
|
||||
}
|
||||
|
||||
public static SncpClient getSncpClient(Service service) {
|
||||
if (service == null) return null;
|
||||
try {
|
||||
@@ -160,10 +212,43 @@ public abstract class Sncp {
|
||||
throw new RuntimeException(param + "'s sncp_getParams method cannot final modifier");
|
||||
} else if (m.getName().equals("sncp_setParams") && Modifier.isFinal(m.getModifiers())) {
|
||||
throw new RuntimeException(param + "'s sncp_setParams method cannot final modifier");
|
||||
} else if (m.getName().equals("sncp_setFuture") && Modifier.isFinal(m.getModifiers())) {
|
||||
throw new RuntimeException(param + "'s sncp_setFuture method cannot final modifier");
|
||||
} else if (m.getName().equals("sncp_getFuture") && Modifier.isFinal(m.getModifiers())) {
|
||||
throw new RuntimeException(param + "'s sncp_getFuture method cannot final modifier");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static String toSimpleString(final Service service, int maxNameLength, int maxClassNameLength) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(isRemote(service) ? "RemoteService" : "LocalService ");
|
||||
int len;
|
||||
Class[] types = getResourceTypes(service);
|
||||
String name = getResourceName(service);
|
||||
if (types.length == 1) {
|
||||
sb.append("(type= ").append(types[0].getName());
|
||||
len = maxClassNameLength - types[0].getName().length();
|
||||
} else {
|
||||
StringBuilder s = new StringBuilder();
|
||||
s.append('[');
|
||||
s.append(Arrays.asList(types).stream().map((Class t) -> t.getName()).collect(Collectors.joining(",")));
|
||||
s.append(']');
|
||||
sb.append("(types=").append(s);
|
||||
len = maxClassNameLength - s.length();
|
||||
}
|
||||
|
||||
for (int i = 0; i < len; i++) {
|
||||
sb.append(' ');
|
||||
}
|
||||
sb.append(", name='").append(name).append("'");
|
||||
for (int i = 0; i < maxNameLength - name.length(); i++) {
|
||||
sb.append(' ');
|
||||
}
|
||||
sb.append(")");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* <blockquote><pre>
|
||||
* public class TestService implements Service{
|
||||
@@ -173,14 +258,14 @@ public abstract class Sncp {
|
||||
* }
|
||||
*
|
||||
* @RpcMultiRun(selfrun = false)
|
||||
* public void createSomeThing(TestBean bean){
|
||||
* //do something
|
||||
* }
|
||||
* public void createSomeThing(TestBean bean){
|
||||
* //do something
|
||||
* }
|
||||
*
|
||||
* @RpcMultiRun
|
||||
* public String updateSomeThing(String id){
|
||||
* return "hello" + id;
|
||||
* }
|
||||
* @RpcMultiRun
|
||||
* public String updateSomeThing(String id){
|
||||
* return "hello" + id;
|
||||
* }
|
||||
* }
|
||||
* </pre></blockquote>
|
||||
*
|
||||
@@ -190,12 +275,20 @@ public abstract class Sncp {
|
||||
* @ResourceType({TestService.class})
|
||||
* public final class _DynLocalTestService extends TestService{
|
||||
*
|
||||
* private static final Class _redkale_service_type = TestService.class;
|
||||
*
|
||||
* @Resource
|
||||
* private BsonConvert _redkale_bsonConvert;
|
||||
*
|
||||
* @Resource
|
||||
* private JsonConvert _redkale_jsonConvert;
|
||||
*
|
||||
* private AnyValue _redkale_conf;
|
||||
*
|
||||
* private String _redkale_sncpGroup; //自身的组节点名 可能为null
|
||||
*
|
||||
* private Set<String> groups; //所有的组节点,包含自身
|
||||
*
|
||||
* private Transport _redkale_sameGroupTransport;
|
||||
*
|
||||
* private Transport[] _redkale_diffGroupTransports;
|
||||
@@ -218,8 +311,8 @@ public abstract class Sncp {
|
||||
* public void _redkale_createSomeThing(boolean selfrunnable, boolean samerunnable, boolean diffrunnable, TestBean bean){
|
||||
* if(selfrunnable) super.createSomeThing(bean);
|
||||
* if (_redkale_client== null) return;
|
||||
* if (samerunnable) _redkale_client.remoteSameGroup(_redkale_bsonConvert, _redkale_jsonConvert, _sameGroupTransport, 0, true, false, false, bean);
|
||||
* if (diffrunnable) _redkale_client.remoteDiffGroup(_redkale_bsonConvert, _redkale_jsonConvert, _diffGroupTransports, 0, true, true, false, bean);
|
||||
* if (samerunnable) _redkale_client.remoteSameGroup(_redkale_bsonConvert, _redkale_jsonConvert, _redkale_sameGroupTransport, 0, true, false, false, bean);
|
||||
* if (diffrunnable) _redkale_client.remoteDiffGroup(_redkale_bsonConvert, _redkale_jsonConvert, _redkale_diffGroupTransports, 0, true, true, false, bean);
|
||||
* }
|
||||
*
|
||||
* @Override
|
||||
@@ -230,9 +323,9 @@ public abstract class Sncp {
|
||||
* @SncpDyn(remote = false, index = 1)
|
||||
* public String _redkale_updateSomeThing(boolean selfrunnable, boolean samerunnable, boolean diffrunnable, String id){
|
||||
* String rs = super.updateSomeThing(id);
|
||||
* if (_redkale_client== null) return;
|
||||
* if (samerunnable) _redkale_client.remoteSameGroup(_redkale_bsonConvert, _redkale_jsonConvert, _sameGroupTransport, 1, true, false, false, id);
|
||||
* if (diffrunnable) _redkale_client.remoteDiffGroup(_redkale_bsonConvert, _redkale_jsonConvert, _diffGroupTransports, 1, true, true, false, id);
|
||||
* if (_redkale_client== null) return rs;
|
||||
* if (samerunnable) _redkale_client.remoteSameGroup(_redkale_bsonConvert, _redkale_jsonConvert, _redkale_sameGroupTransport, 1, true, false, false, id);
|
||||
* if (diffrunnable) _redkale_client.remoteDiffGroup(_redkale_bsonConvert, _redkale_jsonConvert, _redkale_diffGroupTransports, 1, true, true, false, id);
|
||||
* return rs;
|
||||
* }
|
||||
* }
|
||||
@@ -240,36 +333,38 @@ public abstract class Sncp {
|
||||
*
|
||||
* 创建Service的本地模式Class
|
||||
*
|
||||
* @param <T> Service子类
|
||||
* @param name 资源名
|
||||
* @param serviceClass Service类
|
||||
* @param <T> Service子类
|
||||
* @param name 资源名
|
||||
* @param serviceImplClass Service类
|
||||
*
|
||||
* @return Service实例
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
protected static <T extends Service> Class<? extends T> createLocalServiceClass(final String name, final Class<T> serviceClass) {
|
||||
if (serviceClass == null) return null;
|
||||
if (!Service.class.isAssignableFrom(serviceClass)) return serviceClass;
|
||||
int mod = serviceClass.getModifiers();
|
||||
if (!java.lang.reflect.Modifier.isPublic(mod)) return serviceClass;
|
||||
if (java.lang.reflect.Modifier.isAbstract(mod)) return serviceClass;
|
||||
final List<Method> methods = SncpClient.parseMethod(serviceClass);
|
||||
final String supDynName = serviceClass.getName().replace('.', '/');
|
||||
protected static <T extends Service> Class<? extends T> createLocalServiceClass(final String name, final Class<T> serviceImplClass) {
|
||||
if (serviceImplClass == null) return null;
|
||||
if (!Service.class.isAssignableFrom(serviceImplClass)) return serviceImplClass;
|
||||
int mod = serviceImplClass.getModifiers();
|
||||
if (!java.lang.reflect.Modifier.isPublic(mod)) return serviceImplClass;
|
||||
if (java.lang.reflect.Modifier.isAbstract(mod)) return serviceImplClass;
|
||||
final List<Method> methods = SncpClient.parseMethod(serviceImplClass);
|
||||
final String supDynName = serviceImplClass.getName().replace('.', '/');
|
||||
final String clientName = SncpClient.class.getName().replace('.', '/');
|
||||
final String clientDesc = Type.getDescriptor(SncpClient.class);
|
||||
final String bsonConvertDesc = Type.getDescriptor(BsonConvert.class);
|
||||
final String jsonConvertDesc = Type.getDescriptor(JsonConvert.class);
|
||||
final String stringDesc = Type.getDescriptor(String.class);
|
||||
final String anyValueDesc = Type.getDescriptor(AnyValue.class);
|
||||
final String sncpDynDesc = Type.getDescriptor(SncpDyn.class);
|
||||
final String transportDesc = Type.getDescriptor(Transport.class);
|
||||
final String transportsDesc = Type.getDescriptor(Transport[].class);
|
||||
ClassLoader loader = Sncp.class.getClassLoader();
|
||||
String newDynName = supDynName.substring(0, supDynName.lastIndexOf('/') + 1) + LOCALPREFIX + serviceClass.getSimpleName();
|
||||
String newDynName = supDynName.substring(0, supDynName.lastIndexOf('/') + 1) + LOCALPREFIX + serviceImplClass.getSimpleName();
|
||||
if (!name.isEmpty()) {
|
||||
boolean normal = true;
|
||||
for (char ch : name.toCharArray()) {
|
||||
if (!((ch >= '0' && ch <= '9') || ch == '_' || (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'))) normal = false;
|
||||
}
|
||||
if (!normal) throw new RuntimeException(serviceClass + "'s resource name is illegal, must be 0-9 _ a-z A-Z");
|
||||
if (!normal) throw new RuntimeException(serviceImplClass + "'s resource name is illegal, must be 0-9 _ a-z A-Z");
|
||||
newDynName += "_" + (normal ? name : hash(name));
|
||||
}
|
||||
try {
|
||||
@@ -294,7 +389,7 @@ public abstract class Sncp {
|
||||
av0.visitEnd();
|
||||
}
|
||||
{ //给新类加上 原有的Annotation
|
||||
for (Annotation ann : serviceClass.getAnnotations()) {
|
||||
for (Annotation ann : serviceImplClass.getAnnotations()) {
|
||||
if (ann instanceof Resource || ann instanceof SncpDyn || ann instanceof ResourceType) continue;
|
||||
visitAnnotation(cw.visitAnnotation(Type.getDescriptor(ann.annotationType()), true), ann);
|
||||
}
|
||||
@@ -303,9 +398,9 @@ public abstract class Sncp {
|
||||
av0 = cw.visitAnnotation(Type.getDescriptor(ResourceType.class), true);
|
||||
{
|
||||
AnnotationVisitor av1 = av0.visitArray("value");
|
||||
ResourceType rty = serviceClass.getAnnotation(ResourceType.class);
|
||||
ResourceType rty = serviceImplClass.getAnnotation(ResourceType.class);
|
||||
if (rty == null) {
|
||||
av1.visit(null, Type.getType(Type.getDescriptor(serviceClass)));
|
||||
av1.visit(null, Type.getType(Type.getDescriptor(serviceImplClass)));
|
||||
} else {
|
||||
for (Class cl : rty.value()) {
|
||||
av1.visit(null, Type.getType(Type.getDescriptor(cl)));
|
||||
@@ -315,7 +410,10 @@ public abstract class Sncp {
|
||||
}
|
||||
av0.visitEnd();
|
||||
}
|
||||
|
||||
{
|
||||
fv = cw.visitField(ACC_PRIVATE + ACC_FINAL + ACC_STATIC, FIELDPREFIX + "_service_type", "Ljava/lang/Class;", null, null);
|
||||
fv.visitEnd();
|
||||
}
|
||||
{
|
||||
fv = cw.visitField(ACC_PRIVATE, FIELDPREFIX + "_bsonConvert", bsonConvertDesc, null, null);
|
||||
av0 = fv.visitAnnotation("Ljavax/annotation/Resource;", true);
|
||||
@@ -328,6 +426,18 @@ public abstract class Sncp {
|
||||
av0.visitEnd();
|
||||
fv.visitEnd();
|
||||
}
|
||||
{
|
||||
fv = cw.visitField(ACC_PRIVATE, FIELDPREFIX + "_conf", anyValueDesc, null, null);
|
||||
fv.visitEnd();
|
||||
}
|
||||
{
|
||||
fv = cw.visitField(ACC_PRIVATE, FIELDPREFIX + "_sncpGroup", stringDesc, null, null);
|
||||
fv.visitEnd();
|
||||
}
|
||||
{
|
||||
fv = cw.visitField(ACC_PRIVATE, FIELDPREFIX + "_groups", "Ljava/util/Set;", "Ljava/util/Set<Ljava/lang/String;>;", null);
|
||||
fv.visitEnd();
|
||||
}
|
||||
{
|
||||
fv = cw.visitField(ACC_PRIVATE, FIELDPREFIX + "_sameGroupTransport", transportDesc, null, null);
|
||||
fv.visitEnd();
|
||||
@@ -345,6 +455,14 @@ public abstract class Sncp {
|
||||
fv = cw.visitField(ACC_PRIVATE, FIELDPREFIX + "_selfstring", "Ljava/lang/String;", null, null);
|
||||
fv.visitEnd();
|
||||
}
|
||||
{//静态构造函数
|
||||
mv = new AsmMethodVisitor(cw.visitMethod(ACC_STATIC, "<clinit>", "()V", null, null));
|
||||
mv.visitLdcInsn(Type.getType(Type.getDescriptor(serviceImplClass)));
|
||||
mv.visitFieldInsn(PUTSTATIC, newDynName, FIELDPREFIX + "_service_type", "Ljava/lang/Class;");
|
||||
mv.visitInsn(RETURN);
|
||||
mv.visitMaxs(1, 0);
|
||||
mv.visitEnd();
|
||||
}
|
||||
{ //构造函数
|
||||
mv = new AsmMethodVisitor(cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null));
|
||||
//mv.setDebug(true);
|
||||
@@ -549,7 +667,7 @@ public abstract class Sncp {
|
||||
mv.visitVarInsn(ALOAD, 0); //传递 _sameGroupTransport
|
||||
mv.visitFieldInsn(GETFIELD, newDynName, FIELDPREFIX + "_sameGroupTransport", transportDesc);
|
||||
|
||||
final int preparams = 4; //调用selfrunnable之前的参数个数; _client/_bsonConvert/_jsonConvert/_sameGroupTransport
|
||||
final int preparams = 3; //调用selfrunnable之前的参数个数; _client/_bsonConvert/_jsonConvert/_sameGroupTransport
|
||||
|
||||
if (index <= 5) { //第几个 SncpAction
|
||||
mv.visitInsn(ICONST_0 + index);
|
||||
@@ -572,13 +690,13 @@ public abstract class Sncp {
|
||||
|
||||
mv.visitInsn(DUP);
|
||||
mv.visitInsn(ICONST_1);
|
||||
mv.visitInsn(ICONST_0); //第一个参数 samerunnable
|
||||
mv.visitInsn(ICONST_0); //第二个参数 samerunnable
|
||||
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;", false);
|
||||
mv.visitInsn(AASTORE);
|
||||
|
||||
mv.visitInsn(DUP);
|
||||
mv.visitInsn(ICONST_2);
|
||||
mv.visitInsn(ICONST_0); //第二个参数 diffrunnable
|
||||
mv.visitInsn(ICONST_0); //第三个参数 diffrunnable
|
||||
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;", false);
|
||||
mv.visitInsn(AASTORE);
|
||||
|
||||
@@ -767,6 +885,10 @@ public abstract class Sncp {
|
||||
}
|
||||
}
|
||||
|
||||
public static <T extends Service> T createSimpleLocalService(final String name, final Class<T> serviceImplClass, final InetSocketAddress clientAddress, final Transport sameGroupTransport) {
|
||||
return createLocalService(name, null, ResourceFactory.root(), serviceImplClass, clientAddress, null, new HashSet<>(), null, sameGroupTransport, null);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* 创建本地模式Service实例
|
||||
@@ -775,18 +897,30 @@ public abstract class Sncp {
|
||||
* @param name 资源名
|
||||
* @param executor 线程池
|
||||
* @param resourceFactory 资源容器
|
||||
* @param serviceClass Service类
|
||||
* @param serviceImplClass Service类
|
||||
* @param clientAddress 本地IP地址
|
||||
* @param sncpGroup 自身的组节点名 可能为null
|
||||
* @param groups 所有的组节点,包含自身
|
||||
* @param conf 启动配置项
|
||||
* @param sameGroupTransport 同组的通信组件
|
||||
* @param diffGroupTransports 异组的通信组件列表
|
||||
*
|
||||
* @return Service的本地模式实例
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T extends Service> T createLocalService(final String name, final Consumer<Runnable> executor, final ResourceFactory resourceFactory,
|
||||
final Class<T> serviceClass, final InetSocketAddress clientAddress, final Transport sameGroupTransport, final Collection<Transport> diffGroupTransports) {
|
||||
public static <T extends Service> T createLocalService(
|
||||
final String name,
|
||||
final Consumer<Runnable> executor,
|
||||
final ResourceFactory resourceFactory,
|
||||
final Class<T> serviceImplClass,
|
||||
final InetSocketAddress clientAddress,
|
||||
final String sncpGroup,
|
||||
final Set<String> groups,
|
||||
final AnyValue conf,
|
||||
final Transport sameGroupTransport,
|
||||
final Collection<Transport> diffGroupTransports) {
|
||||
try {
|
||||
final Class newClazz = createLocalServiceClass(name, serviceClass);
|
||||
final Class newClazz = createLocalServiceClass(name, serviceImplClass);
|
||||
T rs = (T) newClazz.newInstance();
|
||||
//--------------------------------------
|
||||
Service remoteService = null;
|
||||
@@ -818,7 +952,7 @@ public abstract class Sncp {
|
||||
}
|
||||
}
|
||||
if (remoteService == null && remoteTransport != null) {
|
||||
remoteService = createRemoteService(name, executor, serviceClass, clientAddress, remoteTransport);
|
||||
remoteService = createRemoteService(name, executor, serviceImplClass, clientAddress, sncpGroup, groups, conf, remoteTransport);
|
||||
}
|
||||
if (remoteService != null) field.set(rs, remoteService);
|
||||
}
|
||||
@@ -829,7 +963,7 @@ public abstract class Sncp {
|
||||
try {
|
||||
Field e = newClazz.getDeclaredField(FIELDPREFIX + "_client");
|
||||
e.setAccessible(true);
|
||||
client = new SncpClient(name, serviceClass, rs, executor, false, newClazz, clientAddress);
|
||||
client = new SncpClient(name, serviceImplClass, rs, executor, false, newClazz, clientAddress);
|
||||
e.set(rs, client);
|
||||
} catch (NoSuchFieldException ne) {
|
||||
}
|
||||
@@ -841,13 +975,13 @@ public abstract class Sncp {
|
||||
sb.append(", serviceid = ").append(client.getServiceid());
|
||||
sb.append(", serviceversion = ").append(client.getServiceversion());
|
||||
sb.append(", action.size = ").append(client.getActionCount());
|
||||
List<String> groups = new ArrayList<>();
|
||||
if (sameGroupTransport != null) groups.add(sameGroupTransport.getName());
|
||||
if (diffGroupTransports != null) {
|
||||
for (Transport t : diffGroupTransports) {
|
||||
groups.add(t.getName());
|
||||
}
|
||||
}
|
||||
// List<String> groups = new ArrayList<>();
|
||||
// if (sameGroupTransport != null) groups.add(sameGroupTransport.getName());
|
||||
// if (diffGroupTransports != null) {
|
||||
// for (Transport t : diffGroupTransports) {
|
||||
// groups.add(t.getName());
|
||||
// }
|
||||
// }
|
||||
sb.append(", address = ").append(clientAddress).append(", groups = ").append(groups);
|
||||
sb.append(", sameaddrs = ").append(sameGroupTransport == null ? null : Arrays.asList(sameGroupTransport.getRemoteAddresses()));
|
||||
|
||||
@@ -867,6 +1001,21 @@ public abstract class Sncp {
|
||||
s.set(rs, sb.toString());
|
||||
}
|
||||
if (client == null) return rs;
|
||||
{
|
||||
Field c = newClazz.getDeclaredField(FIELDPREFIX + "_sncpGroup");
|
||||
c.setAccessible(true);
|
||||
c.set(rs, sncpGroup);
|
||||
}
|
||||
{
|
||||
Field c = newClazz.getDeclaredField(FIELDPREFIX + "_groups");
|
||||
c.setAccessible(true);
|
||||
c.set(rs, groups);
|
||||
}
|
||||
{
|
||||
Field c = newClazz.getDeclaredField(FIELDPREFIX + "_conf");
|
||||
c.setAccessible(true);
|
||||
c.set(rs, conf);
|
||||
}
|
||||
{
|
||||
Field c = newClazz.getDeclaredField(FIELDPREFIX + "_sameGroupTransport");
|
||||
c.setAccessible(true);
|
||||
@@ -886,6 +1035,10 @@ public abstract class Sncp {
|
||||
|
||||
}
|
||||
|
||||
public static <T extends Service> T createSimpleRemoteService(final String name, final Class<T> serviceTypeOrImplClass, final InetSocketAddress clientAddress, final Transport transport) {
|
||||
return createRemoteService(name, null, serviceTypeOrImplClass, clientAddress, (String) null, new HashSet<>(), (AnyValue) null, transport);
|
||||
}
|
||||
|
||||
/**
|
||||
* <blockquote><pre>
|
||||
* @Resource(name = "")
|
||||
@@ -893,12 +1046,20 @@ public abstract class Sncp {
|
||||
* @ResourceType({TestService.class})
|
||||
* public final class _DynRemoteTestService extends TestService{
|
||||
*
|
||||
* private static final Class _redkale_service_type = TestService.class;
|
||||
*
|
||||
* @Resource
|
||||
* private BsonConvert _redkale_bsonConvert;
|
||||
*
|
||||
* @Resource
|
||||
* private JsonConvert _redkale_jsonConvert;
|
||||
*
|
||||
* private String _redkale_sncpGroup; //自身的组节点名 可能为null
|
||||
*
|
||||
* private Set<String> groups; //所有的组节点,包含自身
|
||||
*
|
||||
* private AnyValue _redkale_conf;
|
||||
*
|
||||
* private Transport _redkale_transport;
|
||||
*
|
||||
* private SncpClient _redkale_client;
|
||||
@@ -939,37 +1100,48 @@ public abstract class Sncp {
|
||||
*
|
||||
* 创建远程模式的Service实例
|
||||
*
|
||||
* @param <T> Service泛型
|
||||
* @param name 资源名
|
||||
* @param executor 线程池
|
||||
* @param serviceClass Service类
|
||||
* @param clientAddress 本地IP地址
|
||||
* @param transport 通信组件
|
||||
* @param <T> Service泛型
|
||||
* @param name 资源名
|
||||
* @param executor 线程池
|
||||
* @param serviceTypeOrImplClass Service类
|
||||
* @param clientAddress 本地IP地址
|
||||
* @param sncpGroup 自身的组节点名 可能为null
|
||||
* @param groups 所有的组节点,包含自身
|
||||
* @param conf 启动配置项
|
||||
* @param transport 通信组件
|
||||
*
|
||||
* @return Service的远程模式实例
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T extends Service> T createRemoteService(final String name, final Consumer<Runnable> executor, final Class<T> serviceClass,
|
||||
final InetSocketAddress clientAddress, final Transport transport) {
|
||||
if (serviceClass == null) return null;
|
||||
if (!Service.class.isAssignableFrom(serviceClass)) return null;
|
||||
int mod = serviceClass.getModifiers();
|
||||
boolean realed = !(java.lang.reflect.Modifier.isAbstract(mod) || serviceClass.isInterface());
|
||||
public static <T extends Service> T createRemoteService(
|
||||
final String name,
|
||||
final Consumer<Runnable> executor,
|
||||
final Class<T> serviceTypeOrImplClass,
|
||||
final InetSocketAddress clientAddress,
|
||||
final String sncpGroup,
|
||||
final Set<String> groups,
|
||||
final AnyValue conf,
|
||||
final Transport transport) {
|
||||
if (serviceTypeOrImplClass == null) return null;
|
||||
if (!Service.class.isAssignableFrom(serviceTypeOrImplClass)) return null;
|
||||
int mod = serviceTypeOrImplClass.getModifiers();
|
||||
boolean realed = !(java.lang.reflect.Modifier.isAbstract(mod) || serviceTypeOrImplClass.isInterface());
|
||||
if (!java.lang.reflect.Modifier.isPublic(mod)) return null;
|
||||
final String supDynName = serviceClass.getName().replace('.', '/');
|
||||
final String supDynName = serviceTypeOrImplClass.getName().replace('.', '/');
|
||||
final String clientName = SncpClient.class.getName().replace('.', '/');
|
||||
final String clientDesc = Type.getDescriptor(SncpClient.class);
|
||||
final String sncpDynDesc = Type.getDescriptor(SncpDyn.class);
|
||||
final String bsonConvertDesc = Type.getDescriptor(BsonConvert.class);
|
||||
final String jsonConvertDesc = Type.getDescriptor(JsonConvert.class);
|
||||
final String transportDesc = Type.getDescriptor(Transport.class);
|
||||
final String stringDesc = Type.getDescriptor(String.class);
|
||||
final String anyValueDesc = Type.getDescriptor(AnyValue.class);
|
||||
ClassLoader loader = Sncp.class.getClassLoader();
|
||||
String newDynName = supDynName.substring(0, supDynName.lastIndexOf('/') + 1) + REMOTEPREFIX + serviceClass.getSimpleName();
|
||||
String newDynName = supDynName.substring(0, supDynName.lastIndexOf('/') + 1) + REMOTEPREFIX + serviceTypeOrImplClass.getSimpleName();
|
||||
try {
|
||||
Class newClazz = Class.forName(newDynName.replace('/', '.'));
|
||||
T rs = (T) newClazz.newInstance();
|
||||
SncpClient client = new SncpClient(name, serviceClass, rs, executor, true, realed ? createLocalServiceClass(name, serviceClass) : serviceClass, clientAddress);
|
||||
SncpClient client = new SncpClient(name, serviceTypeOrImplClass, rs, executor, true, realed ? createLocalServiceClass(name, serviceTypeOrImplClass) : serviceTypeOrImplClass, clientAddress);
|
||||
Field c = newClazz.getDeclaredField(FIELDPREFIX + "_client");
|
||||
c.setAccessible(true);
|
||||
c.set(rs, client);
|
||||
@@ -998,7 +1170,7 @@ public abstract class Sncp {
|
||||
AsmMethodVisitor mv;
|
||||
AnnotationVisitor av0;
|
||||
|
||||
cw.visit(V1_8, ACC_PUBLIC + ACC_FINAL + ACC_SUPER, newDynName, null, serviceClass.isInterface() ? "java/lang/Object" : supDynName, serviceClass.isInterface() ? new String[]{supDynName} : null);
|
||||
cw.visit(V1_8, ACC_PUBLIC + ACC_FINAL + ACC_SUPER, newDynName, null, serviceTypeOrImplClass.isInterface() ? "java/lang/Object" : supDynName, serviceTypeOrImplClass.isInterface() ? new String[]{supDynName} : null);
|
||||
{
|
||||
av0 = cw.visitAnnotation("Ljavax/annotation/Resource;", true);
|
||||
av0.visit("name", name);
|
||||
@@ -1008,9 +1180,9 @@ public abstract class Sncp {
|
||||
av0 = cw.visitAnnotation(Type.getDescriptor(ResourceType.class), true);
|
||||
{
|
||||
AnnotationVisitor av1 = av0.visitArray("value");
|
||||
ResourceType rty = serviceClass.getAnnotation(ResourceType.class);
|
||||
ResourceType rty = serviceTypeOrImplClass.getAnnotation(ResourceType.class);
|
||||
if (rty == null) {
|
||||
av1.visit(null, Type.getType(Type.getDescriptor(serviceClass)));
|
||||
av1.visit(null, Type.getType(Type.getDescriptor(serviceTypeOrImplClass)));
|
||||
} else {
|
||||
for (Class cl : rty.value()) {
|
||||
av1.visit(null, Type.getType(Type.getDescriptor(cl)));
|
||||
@@ -1026,11 +1198,15 @@ public abstract class Sncp {
|
||||
av0.visitEnd();
|
||||
}
|
||||
{ //给新类加上 原有的Annotation
|
||||
for (Annotation ann : serviceClass.getAnnotations()) {
|
||||
for (Annotation ann : serviceTypeOrImplClass.getAnnotations()) {
|
||||
if (ann instanceof Resource || ann instanceof SncpDyn || ann instanceof ResourceType) continue;
|
||||
visitAnnotation(cw.visitAnnotation(Type.getDescriptor(ann.annotationType()), true), ann);
|
||||
}
|
||||
}
|
||||
{
|
||||
fv = cw.visitField(ACC_PRIVATE + ACC_FINAL + ACC_STATIC, FIELDPREFIX + "_service_type", "Ljava/lang/Class;", null, null);
|
||||
fv.visitEnd();
|
||||
}
|
||||
{
|
||||
fv = cw.visitField(ACC_PRIVATE, FIELDPREFIX + "_bsonConvert", bsonConvertDesc, null, null);
|
||||
av0 = fv.visitAnnotation("Ljavax/annotation/Resource;", true);
|
||||
@@ -1043,6 +1219,18 @@ public abstract class Sncp {
|
||||
av0.visitEnd();
|
||||
fv.visitEnd();
|
||||
}
|
||||
{
|
||||
fv = cw.visitField(ACC_PRIVATE, FIELDPREFIX + "_sncpGroup", stringDesc, null, null);
|
||||
fv.visitEnd();
|
||||
}
|
||||
{
|
||||
fv = cw.visitField(ACC_PRIVATE, FIELDPREFIX + "_groups", "Ljava/util/Set;", "Ljava/util/Set<Ljava/lang/String;>;", null);
|
||||
fv.visitEnd();
|
||||
}
|
||||
{
|
||||
fv = cw.visitField(ACC_PRIVATE, FIELDPREFIX + "_conf", anyValueDesc, null, null);
|
||||
fv.visitEnd();
|
||||
}
|
||||
{
|
||||
fv = cw.visitField(ACC_PRIVATE, FIELDPREFIX + "_transport", transportDesc, null, null);
|
||||
fv.visitEnd();
|
||||
@@ -1055,11 +1243,19 @@ public abstract class Sncp {
|
||||
fv = cw.visitField(ACC_PRIVATE, FIELDPREFIX + "_selfstring", "Ljava/lang/String;", null, null);
|
||||
fv.visitEnd();
|
||||
}
|
||||
{//静态构造函数
|
||||
mv = new AsmMethodVisitor(cw.visitMethod(ACC_STATIC, "<clinit>", "()V", null, null));
|
||||
mv.visitLdcInsn(Type.getType(Type.getDescriptor(serviceTypeOrImplClass)));
|
||||
mv.visitFieldInsn(PUTSTATIC, newDynName, FIELDPREFIX + "_service_type", "Ljava/lang/Class;");
|
||||
mv.visitInsn(RETURN);
|
||||
mv.visitMaxs(1, 0);
|
||||
mv.visitEnd();
|
||||
}
|
||||
{ //构造函数
|
||||
mv = new AsmMethodVisitor(cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null));
|
||||
//mv.setDebug(true);
|
||||
mv.visitVarInsn(ALOAD, 0);
|
||||
mv.visitMethodInsn(INVOKESPECIAL, serviceClass.isInterface() ? "java/lang/Object" : supDynName, "<init>", "()V", false);
|
||||
mv.visitMethodInsn(INVOKESPECIAL, serviceTypeOrImplClass.isInterface() ? "java/lang/Object" : supDynName, "<init>", "()V", false);
|
||||
mv.visitInsn(RETURN);
|
||||
mv.visitMaxs(1, 1);
|
||||
mv.visitEnd();
|
||||
@@ -1095,7 +1291,7 @@ public abstract class Sncp {
|
||||
mv.visitEnd();
|
||||
}
|
||||
int i = -1;
|
||||
for (final SncpAction entry : SncpClient.getSncpActions(realed ? createLocalServiceClass(name, serviceClass) : serviceClass)) {
|
||||
for (final SncpAction entry : SncpClient.getSncpActions(realed ? createLocalServiceClass(name, serviceTypeOrImplClass) : serviceTypeOrImplClass)) {
|
||||
final int index = ++i;
|
||||
final java.lang.reflect.Method method = entry.method;
|
||||
{
|
||||
@@ -1204,13 +1400,32 @@ public abstract class Sncp {
|
||||
}.loadClass(newDynName.replace('/', '.'), bytes);
|
||||
try {
|
||||
T rs = (T) newClazz.newInstance();
|
||||
Field c = newClazz.getDeclaredField(FIELDPREFIX + "_client");
|
||||
c.setAccessible(true);
|
||||
SncpClient client = new SncpClient(name, serviceClass, rs, executor, true, realed ? createLocalServiceClass(name, serviceClass) : serviceClass, clientAddress);
|
||||
c.set(rs, client);
|
||||
Field t = newClazz.getDeclaredField(FIELDPREFIX + "_transport");
|
||||
t.setAccessible(true);
|
||||
t.set(rs, transport);
|
||||
SncpClient client = new SncpClient(name, serviceTypeOrImplClass, rs, executor, true, realed ? createLocalServiceClass(name, serviceTypeOrImplClass) : serviceTypeOrImplClass, clientAddress);
|
||||
{
|
||||
Field c = newClazz.getDeclaredField(FIELDPREFIX + "_client");
|
||||
c.setAccessible(true);
|
||||
c.set(rs, client);
|
||||
}
|
||||
{
|
||||
Field c = newClazz.getDeclaredField(FIELDPREFIX + "_conf");
|
||||
c.setAccessible(true);
|
||||
c.set(rs, conf);
|
||||
}
|
||||
{
|
||||
Field c = newClazz.getDeclaredField(FIELDPREFIX + "_sncpGroup");
|
||||
c.setAccessible(true);
|
||||
c.set(rs, sncpGroup);
|
||||
}
|
||||
{
|
||||
Field c = newClazz.getDeclaredField(FIELDPREFIX + "_groups");
|
||||
c.setAccessible(true);
|
||||
c.set(rs, groups);
|
||||
}
|
||||
{
|
||||
Field t = newClazz.getDeclaredField(FIELDPREFIX + "_transport");
|
||||
t.setAccessible(true);
|
||||
t.set(rs, transport);
|
||||
}
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(newClazz.getName()).append("{name = '").append(name);
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
*/
|
||||
package org.redkale.net.sncp;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.logging.Level;
|
||||
import jdk.internal.org.objectweb.asm.*;
|
||||
import static jdk.internal.org.objectweb.asm.Opcodes.*;
|
||||
@@ -31,6 +32,10 @@ public interface SncpAsyncHandler<V, A> extends AsyncHandler<V, A> {
|
||||
|
||||
public void sncp_setParams(Object... params);
|
||||
|
||||
public void sncp_setFuture(CompletableFuture future);
|
||||
|
||||
public CompletableFuture sncp_getFuture();
|
||||
|
||||
static class Factory {
|
||||
|
||||
/**
|
||||
@@ -45,6 +50,8 @@ public interface SncpAsyncHandler<V, A> extends AsyncHandler<V, A> {
|
||||
*
|
||||
* private SncpAsyncHandler sncphandler;
|
||||
*
|
||||
* private CompletableFuture sncpfuture;
|
||||
*
|
||||
* @java.beans.ConstructorProperties({"sncphandler"})
|
||||
* public XXXAsyncHandler_DyncSncpAsyncHandler_4323(SncpAsyncHandler sncphandler) {
|
||||
* super();
|
||||
@@ -70,6 +77,16 @@ public interface SncpAsyncHandler<V, A> extends AsyncHandler<V, A> {
|
||||
* public void sncp_setParams(Object... params) {
|
||||
* sncphandler.sncp_setParams(params);
|
||||
* }
|
||||
*
|
||||
* @Override
|
||||
* public void sncp_setFuture(CompletableFuture future) {
|
||||
* this.sncpfuture = future;
|
||||
* }
|
||||
*
|
||||
* @Override
|
||||
* public CompletableFuture sncp_getFuture() {
|
||||
* return this.sncpfuture;
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* </pre></blockquote>
|
||||
@@ -82,22 +99,27 @@ public interface SncpAsyncHandler<V, A> extends AsyncHandler<V, A> {
|
||||
//-------------------------------------------------------------
|
||||
final boolean handlerinterface = handlerClass.isInterface();
|
||||
final String handlerClassName = handlerClass.getName().replace('.', '/');
|
||||
final String sncyHandlerName = SncpAsyncHandler.class.getName().replace('.', '/');
|
||||
final String sncyHandlerDesc = Type.getDescriptor(SncpAsyncHandler.class);
|
||||
final String sncpHandlerName = SncpAsyncHandler.class.getName().replace('.', '/');
|
||||
final String sncpHandlerDesc = Type.getDescriptor(SncpAsyncHandler.class);
|
||||
final String sncpFutureDesc = Type.getDescriptor(CompletableFuture.class);
|
||||
final String newDynName = handlerClass.getName().replace('.', '/') + "_Dync" + SncpAsyncHandler.class.getSimpleName() + "_" + (System.currentTimeMillis() % 10000);
|
||||
|
||||
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
|
||||
FieldVisitor fv;
|
||||
AsmMethodVisitor mv;
|
||||
AnnotationVisitor av0;
|
||||
cw.visit(V1_8, ACC_PUBLIC + ACC_SUPER, newDynName, null, handlerinterface ? "java/lang/Object" : handlerClassName, handlerinterface ? new String[]{handlerClassName, sncyHandlerName} : new String[]{sncyHandlerName});
|
||||
cw.visit(V1_8, ACC_PUBLIC + ACC_SUPER, newDynName, null, handlerinterface ? "java/lang/Object" : handlerClassName, handlerinterface ? new String[]{handlerClassName, sncpHandlerName} : new String[]{sncpHandlerName});
|
||||
|
||||
{ //handler 属性
|
||||
fv = cw.visitField(ACC_PRIVATE, "sncphandler", sncyHandlerDesc, null, null);
|
||||
fv = cw.visitField(ACC_PRIVATE, "sncphandler", sncpHandlerDesc, null, null);
|
||||
fv.visitEnd();
|
||||
}
|
||||
{ //future 属性
|
||||
fv = cw.visitField(ACC_PRIVATE, "sncpfuture", sncpFutureDesc, null, null);
|
||||
fv.visitEnd();
|
||||
}
|
||||
{//构造方法
|
||||
mv = new AsmMethodVisitor(cw.visitMethod(ACC_PUBLIC, "<init>", "(" + sncyHandlerDesc + ")V", null, null));
|
||||
mv = new AsmMethodVisitor(cw.visitMethod(ACC_PUBLIC, "<init>", "(" + sncpHandlerDesc + ")V", null, null));
|
||||
//mv.setDebug(true);
|
||||
{
|
||||
av0 = mv.visitAnnotation("Ljava/beans/ConstructorProperties;", true);
|
||||
@@ -112,7 +134,7 @@ public interface SncpAsyncHandler<V, A> extends AsyncHandler<V, A> {
|
||||
mv.visitMethodInsn(INVOKESPECIAL, handlerinterface ? "java/lang/Object" : handlerClassName, "<init>", "()V", false);
|
||||
mv.visitVarInsn(ALOAD, 0);
|
||||
mv.visitVarInsn(ALOAD, 1);
|
||||
mv.visitFieldInsn(PUTFIELD, newDynName, "sncphandler", sncyHandlerDesc);
|
||||
mv.visitFieldInsn(PUTFIELD, newDynName, "sncphandler", sncpHandlerDesc);
|
||||
mv.visitInsn(RETURN);
|
||||
mv.visitMaxs(2, 2);
|
||||
mv.visitEnd();
|
||||
@@ -122,20 +144,20 @@ public interface SncpAsyncHandler<V, A> extends AsyncHandler<V, A> {
|
||||
if ("completed".equals(method.getName()) && method.getParameterCount() == 2) {
|
||||
mv = new AsmMethodVisitor(cw.visitMethod(ACC_PUBLIC, "completed", Type.getMethodDescriptor(method), null, null));
|
||||
mv.visitVarInsn(ALOAD, 0);
|
||||
mv.visitFieldInsn(GETFIELD, newDynName, "sncphandler", sncyHandlerDesc);
|
||||
mv.visitFieldInsn(GETFIELD, newDynName, "sncphandler", sncpHandlerDesc);
|
||||
mv.visitVarInsn(ALOAD, 1);
|
||||
mv.visitVarInsn(ALOAD, 2);
|
||||
mv.visitMethodInsn(INVOKEINTERFACE, sncyHandlerName, "completed", "(Ljava/lang/Object;Ljava/lang/Object;)V", true);
|
||||
mv.visitMethodInsn(INVOKEINTERFACE, sncpHandlerName, "completed", "(Ljava/lang/Object;Ljava/lang/Object;)V", true);
|
||||
mv.visitInsn(RETURN);
|
||||
mv.visitMaxs(3, 3);
|
||||
mv.visitEnd();
|
||||
} else if ("failed".equals(method.getName()) && method.getParameterCount() == 2) {
|
||||
mv = new AsmMethodVisitor(cw.visitMethod(ACC_PUBLIC, "failed", Type.getMethodDescriptor(method), null, null));
|
||||
mv.visitVarInsn(ALOAD, 0);
|
||||
mv.visitFieldInsn(GETFIELD, newDynName, "sncphandler", sncyHandlerDesc);
|
||||
mv.visitFieldInsn(GETFIELD, newDynName, "sncphandler", sncpHandlerDesc);
|
||||
mv.visitVarInsn(ALOAD, 1);
|
||||
mv.visitVarInsn(ALOAD, 2);
|
||||
mv.visitMethodInsn(INVOKEINTERFACE, sncyHandlerName, "failed", "(Ljava/lang/Throwable;Ljava/lang/Object;)V", true);
|
||||
mv.visitMethodInsn(INVOKEINTERFACE, sncpHandlerName, "failed", "(Ljava/lang/Throwable;Ljava/lang/Object;)V", true);
|
||||
mv.visitInsn(RETURN);
|
||||
mv.visitMaxs(3, 3);
|
||||
mv.visitEnd();
|
||||
@@ -171,8 +193,8 @@ public interface SncpAsyncHandler<V, A> extends AsyncHandler<V, A> {
|
||||
{ // sncp_getParams
|
||||
mv = new AsmMethodVisitor(cw.visitMethod(ACC_PUBLIC, "sncp_getParams", "()[Ljava/lang/Object;", null, null));
|
||||
mv.visitVarInsn(ALOAD, 0);
|
||||
mv.visitFieldInsn(GETFIELD, newDynName, "sncphandler", sncyHandlerDesc);
|
||||
mv.visitMethodInsn(INVOKEINTERFACE, sncyHandlerName, "sncp_getParams", "()[Ljava/lang/Object;", true);
|
||||
mv.visitFieldInsn(GETFIELD, newDynName, "sncphandler", sncpHandlerDesc);
|
||||
mv.visitMethodInsn(INVOKEINTERFACE, sncpHandlerName, "sncp_getParams", "()[Ljava/lang/Object;", true);
|
||||
mv.visitInsn(ARETURN);
|
||||
mv.visitMaxs(1, 1);
|
||||
mv.visitEnd();
|
||||
@@ -180,13 +202,30 @@ public interface SncpAsyncHandler<V, A> extends AsyncHandler<V, A> {
|
||||
{ // sncp_setParams
|
||||
mv = new AsmMethodVisitor(cw.visitMethod(ACC_PUBLIC + ACC_VARARGS, "sncp_setParams", "([Ljava/lang/Object;)V", null, null));
|
||||
mv.visitVarInsn(ALOAD, 0);
|
||||
mv.visitFieldInsn(GETFIELD, newDynName, "sncphandler", sncyHandlerDesc);
|
||||
mv.visitFieldInsn(GETFIELD, newDynName, "sncphandler", sncpHandlerDesc);
|
||||
mv.visitVarInsn(ALOAD, 1);
|
||||
mv.visitMethodInsn(INVOKEINTERFACE, sncyHandlerName, "sncp_setParams", "([Ljava/lang/Object;)V", true);
|
||||
mv.visitMethodInsn(INVOKEINTERFACE, sncpHandlerName, "sncp_setParams", "([Ljava/lang/Object;)V", true);
|
||||
mv.visitInsn(RETURN);
|
||||
mv.visitMaxs(2, 2);
|
||||
mv.visitEnd();
|
||||
}
|
||||
{ // sncp_setFuture
|
||||
mv = new AsmMethodVisitor(cw.visitMethod(ACC_PUBLIC, "sncp_setFuture", "(" + sncpFutureDesc + ")V", null, null));
|
||||
mv.visitVarInsn(ALOAD, 0);
|
||||
mv.visitVarInsn(ALOAD, 1);
|
||||
mv.visitFieldInsn(PUTFIELD, newDynName, "sncpfuture", sncpFutureDesc);
|
||||
mv.visitInsn(RETURN);
|
||||
mv.visitMaxs(2, 2);
|
||||
mv.visitEnd();
|
||||
}
|
||||
{ // sncp_getFuture
|
||||
mv = new AsmMethodVisitor(cw.visitMethod(ACC_PUBLIC, "sncp_getFuture", "()" + sncpFutureDesc, null, null));
|
||||
mv.visitVarInsn(ALOAD, 0);
|
||||
mv.visitFieldInsn(GETFIELD, newDynName, "sncpfuture", sncpFutureDesc);
|
||||
mv.visitInsn(ARETURN);
|
||||
mv.visitMaxs(1, 1);
|
||||
mv.visitEnd();
|
||||
}
|
||||
cw.visitEnd();
|
||||
byte[] bytes = cw.toByteArray();
|
||||
Class<SncpAsyncHandler> newHandlerClazz = (Class<SncpAsyncHandler>) new ClassLoader(handlerClass.getClassLoader()) {
|
||||
@@ -214,6 +253,8 @@ public interface SncpAsyncHandler<V, A> extends AsyncHandler<V, A> {
|
||||
|
||||
protected SncpResponse response;
|
||||
|
||||
protected CompletableFuture future;
|
||||
|
||||
public DefaultSncpAsyncHandler(SncpServletAction action, BsonReader in, BsonWriter out, SncpRequest request, SncpResponse response) {
|
||||
this.action = action;
|
||||
this.in = in;
|
||||
@@ -252,5 +293,15 @@ public interface SncpAsyncHandler<V, A> extends AsyncHandler<V, A> {
|
||||
this.params = params;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sncp_setFuture(CompletableFuture future) {
|
||||
this.future = future;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture sncp_getFuture() {
|
||||
return this.future;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,6 +53,10 @@ public final class SncpClient {
|
||||
|
||||
protected final int addressSourceParamIndex;
|
||||
|
||||
protected final boolean boolReturnTypeFuture; // 返回结果类型是否为 CompletableFuture
|
||||
|
||||
protected final Creator<? extends CompletableFuture> futureCreator;
|
||||
|
||||
public SncpAction(final Class clazz, Method method, DLong actionid) {
|
||||
this.actionid = actionid == null ? Sncp.hash(method) : actionid;
|
||||
Type rt = method.getGenericReturnType();
|
||||
@@ -61,6 +65,8 @@ public final class SncpClient {
|
||||
if (tv.getBounds().length == 1) rt = tv.getBounds()[0];
|
||||
}
|
||||
this.resultTypes = rt == void.class ? null : rt;
|
||||
this.boolReturnTypeFuture = CompletableFuture.class.isAssignableFrom(method.getReturnType());
|
||||
this.futureCreator = boolReturnTypeFuture ? Creator.create((Class<? extends CompletableFuture>) method.getReturnType()) : null;
|
||||
this.paramTypes = method.getGenericParameterTypes();
|
||||
this.paramClass = method.getParameterTypes();
|
||||
this.method = method;
|
||||
@@ -75,6 +81,9 @@ public final class SncpClient {
|
||||
Class<?>[] params = method.getParameterTypes();
|
||||
for (int i = 0; i < params.length; i++) {
|
||||
if (AsyncHandler.class.isAssignableFrom(params[i])) {
|
||||
if (boolReturnTypeFuture) {
|
||||
throw new RuntimeException(method + " have both AsyncHandler and CompletableFuture");
|
||||
}
|
||||
if (handlerFuncIndex >= 0) {
|
||||
throw new RuntimeException(method + " have more than one AsyncHandler type parameter");
|
||||
}
|
||||
@@ -153,7 +162,7 @@ public final class SncpClient {
|
||||
|
||||
protected final Consumer<Runnable> executor;
|
||||
|
||||
public <T extends Service> SncpClient(final String serviceName, final Class<T> serviceType, final T service, final Consumer<Runnable> executor,
|
||||
public <T extends Service> SncpClient(final String serviceName, final Class<T> serviceTypeOrImplClass, final T service, final Consumer<Runnable> executor,
|
||||
final boolean remote, final Class serviceClass, final InetSocketAddress clientAddress) {
|
||||
this.remote = remote;
|
||||
this.executor = executor;
|
||||
@@ -161,7 +170,10 @@ public final class SncpClient {
|
||||
this.serviceversion = 0;
|
||||
this.clientAddress = clientAddress;
|
||||
this.name = serviceName;
|
||||
this.serviceid = Sncp.hash(serviceType.getName() + ':' + serviceName);
|
||||
Class tn = serviceTypeOrImplClass;
|
||||
ResourceType rt = (ResourceType) tn.getAnnotation(ResourceType.class);
|
||||
if (rt != null && rt.value().length > 0) tn = rt.value()[0];
|
||||
this.serviceid = Sncp.hash(tn.getName() + ':' + serviceName);
|
||||
final List<SncpAction> methodens = new ArrayList<>();
|
||||
//------------------------------------------------------------------------------
|
||||
for (java.lang.reflect.Method method : parseMethod(serviceClass)) {
|
||||
@@ -248,6 +260,7 @@ public final class SncpClient {
|
||||
}
|
||||
|
||||
public void remoteSameGroup(final BsonConvert bsonConvert, final JsonConvert jsonConvert, Transport transport, final int index, final Object... params) {
|
||||
if (transport == null) return;
|
||||
final SncpAction action = actions[index];
|
||||
if (action.handlerFuncParamIndex >= 0) params[action.handlerFuncParamIndex] = null; //不能让远程调用handler,因为之前本地方法已经调用过了
|
||||
for (InetSocketAddress addr : transport.getRemoteAddresses()) {
|
||||
@@ -256,6 +269,7 @@ public final class SncpClient {
|
||||
}
|
||||
|
||||
public void asyncRemoteSameGroup(final BsonConvert bsonConvert, final JsonConvert jsonConvert, Transport transport, final int index, final Object... params) {
|
||||
if (transport == null) return;
|
||||
if (executor != null) {
|
||||
executor.accept(() -> {
|
||||
remoteSameGroup(bsonConvert, jsonConvert, transport, index, params);
|
||||
@@ -290,9 +304,32 @@ public final class SncpClient {
|
||||
final SncpAction action = actions[index];
|
||||
final AsyncHandler handlerFunc = action.handlerFuncParamIndex >= 0 ? (AsyncHandler) params[action.handlerFuncParamIndex] : null;
|
||||
if (action.handlerFuncParamIndex >= 0) params[action.handlerFuncParamIndex] = null;
|
||||
SncpFuture<byte[]> future = remote0(handlerFunc, bsonConvert, jsonConvert, transport, null, action, params);
|
||||
if (handlerFunc != null) return null;
|
||||
final BsonReader reader = bsonConvert.pollBsonReader();
|
||||
CompletableFuture<byte[]> future = remote0(handlerFunc, bsonConvert, jsonConvert, transport, null, action, params);
|
||||
if (action.boolReturnTypeFuture) {
|
||||
CompletableFuture result = action.futureCreator.create();
|
||||
future.whenComplete((v, e) -> {
|
||||
try {
|
||||
if (e != null) {
|
||||
result.completeExceptionally(e);
|
||||
} else {
|
||||
reader.setBytes(v);
|
||||
byte i;
|
||||
while ((i = reader.readByte()) != 0) {
|
||||
final Attribute attr = action.paramAttrs[i];
|
||||
attr.set(params[i - 1], bsonConvert.convertFrom(attr.type(), reader));
|
||||
}
|
||||
Object rs = bsonConvert.convertFrom(Object.class, reader);
|
||||
|
||||
result.complete(rs);
|
||||
}
|
||||
} finally {
|
||||
bsonConvert.offerBsonReader(reader);
|
||||
}
|
||||
}); //需要获取 Executor
|
||||
return (T) result;
|
||||
}
|
||||
if (handlerFunc != null) return null;
|
||||
try {
|
||||
reader.setBytes(future.get(5, TimeUnit.SECONDS));
|
||||
byte i;
|
||||
@@ -317,7 +354,7 @@ public final class SncpClient {
|
||||
}
|
||||
}
|
||||
|
||||
private SncpFuture<byte[]> remote0(final AsyncHandler handler, final BsonConvert bsonConvert, final JsonConvert jsonConvert, final Transport transport, final SocketAddress addr0, final SncpAction action, final Object... params) {
|
||||
private CompletableFuture<byte[]> remote0(final AsyncHandler handler, final BsonConvert bsonConvert, final JsonConvert jsonConvert, final Transport transport, final SocketAddress addr0, final SncpAction action, final Object... params) {
|
||||
if ("rest".equalsIgnoreCase(transport.getSubprotocol())) {
|
||||
return remoteRest0(handler, jsonConvert, transport, addr0, action, params);
|
||||
}
|
||||
@@ -325,17 +362,17 @@ public final class SncpClient {
|
||||
}
|
||||
|
||||
//尚未实现
|
||||
private SncpFuture<byte[]> remoteRest0(final AsyncHandler handler, final JsonConvert jsonConvert, final Transport transport, final SocketAddress addr0, final SncpAction action, final Object... params) {
|
||||
private CompletableFuture<byte[]> remoteRest0(final AsyncHandler handler, final JsonConvert jsonConvert, final Transport transport, final SocketAddress addr0, final SncpAction action, final Object... params) {
|
||||
return null;
|
||||
}
|
||||
|
||||
private SncpFuture<byte[]> remoteSncp0(final AsyncHandler handler, final BsonConvert bsonConvert, final Transport transport, final SocketAddress addr0, final SncpAction action, final Object... params) {
|
||||
Type[] myparamtypes = action.paramTypes;
|
||||
Class[] myparamclass = action.paramClass;
|
||||
private CompletableFuture<byte[]> remoteSncp0(final AsyncHandler handler, final BsonConvert bsonConvert, final Transport transport, final SocketAddress addr0, final SncpAction action, final Object... params) {
|
||||
final Type[] myparamtypes = action.paramTypes;
|
||||
final Class[] myparamclass = action.paramClass;
|
||||
if (action.addressSourceParamIndex >= 0) params[action.addressSourceParamIndex] = this.clientAddress;
|
||||
final BsonWriter writer = bsonConvert.pollBsonWriter(transport.getBufferSupplier()); // 将head写入
|
||||
writer.writeTo(DEFAULT_HEADER);
|
||||
for (int i = 0; i < params.length; i++) {
|
||||
for (int i = 0; i < params.length; i++) { //params 可能包含: 3 个 boolean
|
||||
bsonConvert.convertTo(writer, AsyncHandler.class.isAssignableFrom(myparamclass[i]) ? AsyncHandler.class : myparamtypes[i], params[i]);
|
||||
}
|
||||
final int reqBodyLength = writer.count() - HEADER_SIZE; //body总长度
|
||||
@@ -351,7 +388,7 @@ public final class SncpClient {
|
||||
fillHeader(sendBuffers[0], seqid, actionid, reqBodyLength);
|
||||
|
||||
final ByteBuffer buffer = transport.pollBuffer();
|
||||
final SncpFuture<byte[]> future = new SncpFuture(false);
|
||||
final CompletableFuture<byte[]> future = new CompletableFuture();
|
||||
conn.write(sendBuffers, sendBuffers, new CompletionHandler<Integer, ByteBuffer[]>() {
|
||||
|
||||
@Override
|
||||
@@ -385,7 +422,7 @@ public final class SncpClient {
|
||||
@Override
|
||||
public void completed(Integer count, Void attachment2) {
|
||||
if (count < 1 && buffer.remaining() == buffer.limit()) { //没有数据可读
|
||||
future.set(new RuntimeException(action.method + " sncp[" + conn.getRemoteAddress() + "] remote no response data"));
|
||||
future.completeExceptionally(new RuntimeException(action.method + " sncp[" + conn.getRemoteAddress() + "] remote no response data"));
|
||||
transport.offerBuffer(buffer);
|
||||
transport.offerConnection(true, conn);
|
||||
return;
|
||||
@@ -430,7 +467,7 @@ public final class SncpClient {
|
||||
}
|
||||
|
||||
public void success() {
|
||||
future.set(this.body);
|
||||
future.complete(this.body);
|
||||
transport.offerBuffer(buffer);
|
||||
transport.offerConnection(false, conn);
|
||||
if (handler != null) {
|
||||
@@ -456,7 +493,7 @@ public final class SncpClient {
|
||||
@Override
|
||||
public void failed(Throwable exc, Void attachment2) {
|
||||
logger.log(Level.SEVERE, action.method + " sncp (params: " + convert.convertTo(params) + ") remote read exec failed", exc);
|
||||
future.set(new RuntimeException(action.method + " sncp remote exec failed"));
|
||||
future.completeExceptionally(new RuntimeException(action.method + " sncp remote exec failed"));
|
||||
transport.offerBuffer(buffer);
|
||||
transport.offerConnection(true, conn);
|
||||
if (handler != null) {
|
||||
@@ -508,91 +545,4 @@ public final class SncpClient {
|
||||
buffer.position(currentpos);
|
||||
}
|
||||
|
||||
protected static final class SncpFuture<T> implements Future<T> {
|
||||
|
||||
private volatile boolean done;
|
||||
|
||||
private T result;
|
||||
|
||||
private RuntimeException ex;
|
||||
|
||||
private final boolean rest;
|
||||
|
||||
public SncpFuture(boolean rest) {
|
||||
this.rest = rest;
|
||||
}
|
||||
|
||||
public SncpFuture(boolean rest, T result) {
|
||||
this.rest = rest;
|
||||
this.result = result;
|
||||
this.done = true;
|
||||
}
|
||||
|
||||
public boolean isRest() {
|
||||
return this.rest;
|
||||
}
|
||||
|
||||
public void set(T result) {
|
||||
this.result = result;
|
||||
this.done = true;
|
||||
synchronized (this) {
|
||||
notifyAll();
|
||||
}
|
||||
}
|
||||
|
||||
public void set(RuntimeException ex) {
|
||||
this.ex = ex;
|
||||
this.done = true;
|
||||
synchronized (this) {
|
||||
notifyAll();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean cancel(boolean mayInterruptIfRunning) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCancelled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDone() {
|
||||
return done;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T get() throws InterruptedException, ExecutionException {
|
||||
if (done) {
|
||||
if (ex != null) throw ex;
|
||||
return result;
|
||||
}
|
||||
synchronized (this) {
|
||||
if (!done) wait(10_000);
|
||||
}
|
||||
if (done) {
|
||||
if (ex != null) throw ex;
|
||||
return result;
|
||||
}
|
||||
throw new InterruptedException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
|
||||
if (done) {
|
||||
if (ex != null) throw ex;
|
||||
return result;
|
||||
}
|
||||
synchronized (this) {
|
||||
if (!done) wait(unit.toMillis(timeout));
|
||||
}
|
||||
if (done) {
|
||||
if (ex != null) throw ex;
|
||||
return result;
|
||||
}
|
||||
throw new TimeoutException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import java.lang.annotation.*;
|
||||
import java.lang.reflect.*;
|
||||
import java.nio.*;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.*;
|
||||
import java.util.logging.*;
|
||||
import javax.annotation.*;
|
||||
@@ -113,7 +114,7 @@ public final class SncpDynServlet extends SncpServlet {
|
||||
if (bufferSupplier == null) {
|
||||
bufferSupplier = request.getContext().getBufferSupplier();
|
||||
}
|
||||
SncpServletAction action = actions.get(request.getActionid());
|
||||
final SncpServletAction action = actions.get(request.getActionid());
|
||||
//if (finest) logger.log(Level.FINEST, "sncpdyn.execute: " + request + ", " + (action == null ? "null" : action.method));
|
||||
if (action == null) {
|
||||
response.finish(SncpResponse.RETCODE_ILLACTIONID, null); //无效actionid
|
||||
@@ -134,6 +135,8 @@ public final class SncpDynServlet extends SncpServlet {
|
||||
}
|
||||
handler = creator.create(new DefaultSncpAsyncHandler(action, in, out, request, response));
|
||||
}
|
||||
} else if (action.boolReturnTypeFuture) {
|
||||
handler = new DefaultSncpAsyncHandler(action, in, out, request, response);
|
||||
}
|
||||
in.setBytes(request.getBody());
|
||||
action.action(in, out, handler);
|
||||
@@ -141,6 +144,26 @@ public final class SncpDynServlet extends SncpServlet {
|
||||
response.finish(0, out);
|
||||
action.convert.offerBsonReader(in);
|
||||
action.convert.offerBsonWriter(out);
|
||||
} else if (action.boolReturnTypeFuture) {
|
||||
CompletableFuture future = handler.sncp_getFuture();
|
||||
if (future == null) {
|
||||
action._callParameter(out, handler.sncp_getParams());
|
||||
action.convert.convertTo(out, Object.class, null);
|
||||
} else {
|
||||
Object[] sncpParams = handler.sncp_getParams();
|
||||
future.whenComplete((v, e) -> {
|
||||
if (e != null) {
|
||||
response.getContext().getLogger().log(Level.INFO, "sncp CompleteAsync error(" + request + ")", e);
|
||||
response.finish(SncpResponse.RETCODE_THROWEXCEPTION, null);
|
||||
return;
|
||||
}
|
||||
action._callParameter(out, sncpParams);
|
||||
action.convert.convertTo(out, Object.class, v);
|
||||
response.finish(0, out);
|
||||
action.convert.offerBsonReader(in);
|
||||
action.convert.offerBsonWriter(out);
|
||||
});
|
||||
}
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
response.getContext().getLogger().log(Level.INFO, "sncp execute error(" + request + ")", t);
|
||||
@@ -164,10 +187,13 @@ public final class SncpDynServlet extends SncpServlet {
|
||||
|
||||
protected int handlerFuncParamIndex = -1; //handlerFuncParamIndex>=0表示存在AsyncHandler参数
|
||||
|
||||
protected boolean boolReturnTypeFuture = false; // 返回结果类型是否为 CompletableFuture
|
||||
|
||||
protected Class handlerFuncParamClass; //AsyncHandler参数的类型
|
||||
|
||||
public abstract void action(final BsonReader in, final BsonWriter out, final SncpAsyncHandler handler) throws Throwable;
|
||||
|
||||
//只有同步方法才调用 (没有AsyncHandler、CompletableFuture)
|
||||
public final void _callParameter(final BsonWriter out, final Object... params) {
|
||||
if (paramAttrs != null) {
|
||||
for (int i = 1; i < paramAttrs.length; i++) {
|
||||
@@ -193,6 +219,10 @@ public final class SncpDynServlet extends SncpServlet {
|
||||
*
|
||||
* public void update(long show, short v2, AsyncHandler<Boolean, TestBean> handler, TestBean bean, String name, int id) {
|
||||
* }
|
||||
*
|
||||
* public CompletableFuture<String> changeName(TestBean bean, String name, int id) {
|
||||
* return null;
|
||||
* }
|
||||
* }
|
||||
*
|
||||
*
|
||||
@@ -245,6 +275,22 @@ public final class SncpDynServlet extends SncpServlet {
|
||||
* }
|
||||
* }
|
||||
*
|
||||
*
|
||||
* class DynActionTestService_changeName extends SncpServletAction {
|
||||
*
|
||||
* public TestService service;
|
||||
*
|
||||
* @Override
|
||||
* public void action(final BsonReader in, final BsonWriter out, final SncpAsyncHandler handler) throws Throwable {
|
||||
* TestBean arg1 = convert.convertFrom(paramTypes[1], in);
|
||||
* String arg2 = convert.convertFrom(paramTypes[2], in);
|
||||
* int arg3 = convert.convertFrom(paramTypes[3], in);
|
||||
* handler.sncp_setParams(arg1, arg2, arg3);
|
||||
* CompletableFuture future = service.changeName(arg1, arg2, arg3);
|
||||
* handler.sncp_setFuture(future);
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* </pre></blockquote>
|
||||
*
|
||||
* @param service Service
|
||||
@@ -264,6 +310,7 @@ public final class SncpDynServlet extends SncpServlet {
|
||||
final String convertReaderDesc = Type.getDescriptor(BsonReader.class);
|
||||
final String convertWriterDesc = Type.getDescriptor(BsonWriter.class);
|
||||
final String serviceDesc = Type.getDescriptor(serviceClass);
|
||||
final boolean boolReturnTypeFuture = CompletableFuture.class.isAssignableFrom(method.getReturnType());
|
||||
String newDynName = serviceName.substring(0, serviceName.lastIndexOf('/') + 1)
|
||||
+ "DynAction" + serviceClass.getSimpleName() + "_" + method.getName() + "_" + actionid;
|
||||
while (true) {
|
||||
@@ -312,8 +359,11 @@ public final class SncpDynServlet extends SncpServlet {
|
||||
int store = 4; //action的参数个数+1
|
||||
final Class[] paramClasses = method.getParameterTypes();
|
||||
int[][] codes = new int[paramClasses.length][2];
|
||||
for (int i = 0; i < paramClasses.length; i++) { //参数
|
||||
for (int i = 0; i < paramClasses.length; i++) { //反序列化方法的每个参数
|
||||
if (AsyncHandler.class.isAssignableFrom(paramClasses[i])) {
|
||||
if (boolReturnTypeFuture) {
|
||||
throw new RuntimeException(method + " have both AsyncHandler and CompletableFuture");
|
||||
}
|
||||
if (handlerFuncIndex >= 0) {
|
||||
throw new RuntimeException(method + " have more than one AsyncHandler type parameter");
|
||||
}
|
||||
@@ -386,7 +436,7 @@ public final class SncpDynServlet extends SncpServlet {
|
||||
intconst++;
|
||||
store++;
|
||||
}
|
||||
if (handlerFuncIndex >= 0) { //调用SncpAsyncHandler.setParams(Object... params)
|
||||
if (boolReturnTypeFuture || handlerFuncIndex >= 0) { //调用SncpAsyncHandler.setParams(Object... params)
|
||||
mv.visitVarInsn(ALOAD, 3);
|
||||
if (paramClasses.length > 5) {
|
||||
mv.visitIntInsn(BIPUSH, paramClasses.length);
|
||||
@@ -444,8 +494,13 @@ public final class SncpDynServlet extends SncpServlet {
|
||||
}
|
||||
}
|
||||
mv.visitVarInsn(ASTORE, store); //11
|
||||
if (boolReturnTypeFuture) {
|
||||
mv.visitVarInsn(ALOAD, 3);
|
||||
mv.visitVarInsn(ALOAD, store);
|
||||
mv.visitMethodInsn(INVOKEINTERFACE, handlerName, "sncp_setFuture", "(Ljava/util/concurrent/CompletableFuture;)V", true);
|
||||
}
|
||||
}
|
||||
if (handlerFuncIndex < 0) {
|
||||
if (!boolReturnTypeFuture && handlerFuncIndex < 0) { //同步方法
|
||||
//------------------------- _callParameter 方法 --------------------------------
|
||||
mv.visitVarInsn(ALOAD, 0);
|
||||
mv.visitVarInsn(ALOAD, 2);
|
||||
@@ -486,10 +541,10 @@ public final class SncpDynServlet extends SncpServlet {
|
||||
}
|
||||
//-------------------------直接返回 或者 调用convertTo方法 --------------------------------
|
||||
int maxStack = codes.length > 0 ? codes[codes.length - 1][1] : 1;
|
||||
if (returnClass == void.class) { //返回
|
||||
if (boolReturnTypeFuture || returnClass == void.class) { //返回
|
||||
mv.visitInsn(RETURN);
|
||||
maxStack = 8;
|
||||
} else {
|
||||
} else { //同步方法调用
|
||||
mv.visitVarInsn(ALOAD, 0);
|
||||
mv.visitFieldInsn(GETFIELD, newDynName, "convert", Type.getDescriptor(BsonConvert.class));
|
||||
mv.visitVarInsn(ALOAD, 2);
|
||||
@@ -528,6 +583,7 @@ public final class SncpDynServlet extends SncpServlet {
|
||||
instance.paramTypes = types;
|
||||
instance.handlerFuncParamIndex = handlerFuncIndex;
|
||||
instance.handlerFuncParamClass = handlerFuncClass;
|
||||
instance.boolReturnTypeFuture = boolReturnTypeFuture;
|
||||
|
||||
org.redkale.util.Attribute[] atts = new org.redkale.util.Attribute[ptypes.length + 1];
|
||||
Annotation[][] anns = method.getParameterAnnotations();
|
||||
|
||||
@@ -38,15 +38,15 @@ public final class SncpServer extends Server<DLong, SncpContext, SncpRequest, Sn
|
||||
super.init(config);
|
||||
}
|
||||
|
||||
public void addSncpServlet(ServiceWrapper entry) {
|
||||
for (Class type : entry.getTypes()) {
|
||||
SncpDynServlet sds = new SncpDynServlet(BsonFactory.root().getConvert(), entry.getName(), type, entry.getService());
|
||||
this.prepare.addServlet(sds, null, entry.getConf());
|
||||
public void addSncpServlet(Service sncpService) {
|
||||
for (Class type : Sncp.getResourceTypes(sncpService)) {
|
||||
SncpDynServlet sds = new SncpDynServlet(BsonFactory.root().getConvert(), Sncp.getResourceName(sncpService), type, sncpService);
|
||||
this.prepare.addServlet(sds, null, Sncp.getConf(sncpService));
|
||||
}
|
||||
}
|
||||
|
||||
public <T extends Service> void addSncpServlet(Class<T> serviceType, String name, T service, AnyValue conf) {
|
||||
SncpDynServlet sds = new SncpDynServlet(BsonFactory.root().getConvert(), name, serviceType, service);
|
||||
public <T extends Service> void addSncpServlet(Class<T> serviceTypeClass, String name, T service, AnyValue conf) {
|
||||
SncpDynServlet sds = new SncpDynServlet(BsonFactory.root().getConvert(), name, serviceTypeClass, service);
|
||||
this.prepare.addServlet(sds, null, conf);
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
package org.redkale.net.sncp;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.*;
|
||||
import org.redkale.net.*;
|
||||
import org.redkale.util.*;
|
||||
|
||||
@@ -20,6 +21,14 @@ public abstract class SncpServlet extends Servlet<SncpContext, SncpRequest, Sncp
|
||||
|
||||
public abstract DLong getServiceid();
|
||||
|
||||
protected ExecutorService getExecutor() {
|
||||
Thread thread = Thread.currentThread();
|
||||
if (thread instanceof WorkThread) {
|
||||
return ((WorkThread) thread).getExecutor();
|
||||
}
|
||||
return ForkJoinPool.commonPool();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean equals(Object obj) {
|
||||
if (!(obj instanceof SncpServlet)) return false;
|
||||
|
||||
33
src/org/redkale/service/AbstractService.java
Normal file
33
src/org/redkale/service/AbstractService.java
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.service;
|
||||
|
||||
import java.util.concurrent.*;
|
||||
import org.redkale.net.WorkThread;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
public abstract class AbstractService implements Service {
|
||||
|
||||
protected void runAsync(Runnable runner) {
|
||||
Thread thread = Thread.currentThread();
|
||||
if (thread instanceof WorkThread) {
|
||||
((WorkThread) thread).runAsync(runner);
|
||||
} else {
|
||||
ForkJoinPool.commonPool().execute(runner);
|
||||
}
|
||||
}
|
||||
|
||||
protected ExecutorService getExecutor() {
|
||||
Thread thread = Thread.currentThread();
|
||||
if (thread instanceof WorkThread) {
|
||||
return ((WorkThread) thread).getExecutor();
|
||||
}
|
||||
return ForkJoinPool.commonPool();
|
||||
}
|
||||
}
|
||||
@@ -1,719 +0,0 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.service;
|
||||
|
||||
import java.io.*;
|
||||
import java.sql.*;
|
||||
import java.util.*;
|
||||
import java.util.function.*;
|
||||
import javax.annotation.*;
|
||||
import org.redkale.source.*;
|
||||
import org.redkale.util.*;
|
||||
|
||||
/**
|
||||
* DataSource对应的Service类, 该类主要特点是将所有含FilterBean参数的方法重载成FilterNode对应的方法。
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
@AutoLoad(false)
|
||||
@ResourceType({DataSourceService.class, DataSource.class})
|
||||
public class DataSourceService implements DataSource, Service, AutoCloseable {
|
||||
|
||||
@Resource(name = "$")
|
||||
private DataSource source;
|
||||
|
||||
@Override
|
||||
public <T> void insert(@RpcCall(DataCallArrayAttribute.class) T... values) {
|
||||
source.insert(values);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void insert(final AsyncHandler<Void, T[]> handler, @RpcAttachment @RpcCall(DataCallArrayAttribute.class) final T... values) {
|
||||
source.insert(handler, values);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> int delete(T... values) {
|
||||
return source.delete(values);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void delete(final AsyncHandler<Integer, T[]> handler, @RpcAttachment final T... values) {
|
||||
source.delete(handler, values);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> int delete(final Class<T> clazz, final Serializable... ids) {
|
||||
return source.delete(clazz, ids);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void delete(final AsyncHandler<Integer, Serializable[]> handler, final Class<T> clazz, @RpcAttachment final Serializable... ids) {
|
||||
source.delete(handler, clazz, ids);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> int delete(final Class<T> clazz, FilterNode node) {
|
||||
return source.delete(clazz, node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void delete(final AsyncHandler<Integer, FilterNode> handler, final Class<T> clazz, @RpcAttachment final FilterNode node) {
|
||||
source.delete(handler, clazz, node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> int delete(final Class<T> clazz, final Flipper flipper, FilterNode node) {
|
||||
return source.delete(clazz, flipper, node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void delete(final AsyncHandler<Integer, FilterNode> handler, final Class<T> clazz, final Flipper flipper, @RpcAttachment FilterNode node) {
|
||||
source.delete(handler, clazz, flipper, node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> int update(T... values) {
|
||||
return source.update(values);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void update(final AsyncHandler<Integer, T[]> handler, @RpcAttachment final T... values) {
|
||||
source.update(handler, values);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> int updateColumn(final Class<T> clazz, final Serializable id, final String column, final Serializable value) {
|
||||
return source.updateColumn(clazz, id, column, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void updateColumn(final AsyncHandler<Integer, Serializable> handler, final Class<T> clazz, @RpcAttachment final Serializable id, final String column, final Serializable value) {
|
||||
source.updateColumn(handler, clazz, id, column, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> int updateColumn(final Class<T> clazz, final String column, final Serializable value, final FilterNode node) {
|
||||
return source.updateColumn(clazz, column, value, node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void updateColumn(final AsyncHandler<Integer, FilterNode> handler, final Class<T> clazz, final String column, final Serializable value, @RpcAttachment final FilterNode node) {
|
||||
source.updateColumn(handler, clazz, column, value, node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> int updateColumn(final Class<T> clazz, final Serializable id, final ColumnValue... values) {
|
||||
return source.updateColumn(clazz, id, values);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void updateColumn(final AsyncHandler<Integer, Serializable> handler, final Class<T> clazz, @RpcAttachment final Serializable id, final ColumnValue... values) {
|
||||
source.updateColumn(handler, clazz, id, values);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> int updateColumn(final Class<T> clazz, final FilterNode node, final ColumnValue... values) {
|
||||
return source.updateColumn(clazz, node, values);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void updateColumn(final AsyncHandler<Integer, FilterNode> handler, final Class<T> clazz, @RpcAttachment final FilterNode node, final ColumnValue... values) {
|
||||
source.updateColumn(handler, clazz, node, values);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> int updateColumn(final Class<T> clazz, final FilterNode node, final Flipper flipper, final ColumnValue... values) {
|
||||
return source.updateColumn(clazz, node, flipper, values);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void updateColumn(final AsyncHandler<Integer, FilterNode> handler, final Class<T> clazz, @RpcAttachment final FilterNode node, final Flipper flipper, final ColumnValue... values) {
|
||||
source.updateColumn(handler, clazz, node, flipper, values);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> int updateColumn(T bean, final String... columns) {
|
||||
return source.updateColumn(bean, columns);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void updateColumn(final AsyncHandler<Integer, T> handler, @RpcAttachment final T bean, final String... columns) {
|
||||
source.updateColumn(handler, bean, columns);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> int updateColumn(T bean, final FilterNode node, final String... columns) {
|
||||
return source.updateColumn(bean, node, columns);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void updateColumn(final AsyncHandler<Integer, FilterNode> handler, final T bean, @RpcAttachment final FilterNode node, final String... columns) {
|
||||
source.updateColumn(handler, bean, node, columns);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> int updateColumn(T bean, final SelectColumn selects) {
|
||||
return source.updateColumn(bean, selects);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void updateColumn(final AsyncHandler<Integer, T> handler, @RpcAttachment final T bean, final SelectColumn selects) {
|
||||
source.updateColumn(handler, bean, selects);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> int updateColumn(T bean, final FilterNode node, final SelectColumn selects) {
|
||||
return source.updateColumn(bean, node, selects);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void updateColumn(final AsyncHandler<Integer, FilterNode> handler, final T bean, @RpcAttachment final FilterNode node, final SelectColumn selects) {
|
||||
source.updateColumn(handler, bean, node, selects);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Number getNumberResult(final Class entityClass, FilterFunc func, final String column) {
|
||||
return source.getNumberResult(entityClass, func, column);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getNumberResult(final AsyncHandler<Number, String> handler, final Class entityClass, final FilterFunc func, @RpcAttachment final String column) {
|
||||
source.getNumberResult(handler, entityClass, func, column);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Number getNumberResult(final Class entityClass, FilterFunc func, final String column, FilterBean bean) {
|
||||
return getNumberResult(entityClass, func, column, FilterNodeBean.createFilterNode(bean));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <B extends FilterBean> void getNumberResult(final AsyncHandler<Number, B> handler, final Class entityClass, final FilterFunc func, final String column, @RpcAttachment final B bean) {
|
||||
source.getNumberResult(handler, entityClass, func, column, bean);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Number getNumberResult(final Class entityClass, FilterFunc func, final String column, FilterNode node) {
|
||||
return source.getNumberResult(entityClass, func, column, node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getNumberResult(final AsyncHandler<Number, FilterNode> handler, final Class entityClass, final FilterFunc func, final String column, @RpcAttachment final FilterNode node) {
|
||||
source.getNumberResult(handler, entityClass, func, column, node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Number getNumberResult(final Class entityClass, FilterFunc func, final Number defVal, final String column) {
|
||||
return source.getNumberResult(entityClass, func, defVal, column);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getNumberResult(final AsyncHandler<Number, String> handler, final Class entityClass, final FilterFunc func, final Number defVal, @RpcAttachment final String column) {
|
||||
source.getNumberResult(handler, entityClass, func, defVal, column);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Number getNumberResult(final Class entityClass, FilterFunc func, final Number defVal, final String column, FilterBean bean) {
|
||||
return getNumberResult(entityClass, func, defVal, column, FilterNodeBean.createFilterNode(bean));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getNumberResult(final AsyncHandler<Number, String> handler, final Class entityClass, final FilterFunc func, final Number defVal, @RpcAttachment final String column, final FilterBean bean) {
|
||||
source.getNumberResult(handler, entityClass, func, defVal, column, bean);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Number getNumberResult(final Class entityClass, FilterFunc func, final Number defVal, final String column, FilterNode node) {
|
||||
return source.getNumberResult(entityClass, func, defVal, column, node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getNumberResult(final AsyncHandler<Number, String> handler, final Class entityClass, final FilterFunc func, final Number defVal, @RpcAttachment final String column, final FilterNode node) {
|
||||
source.getNumberResult(handler, entityClass, func, defVal, column, node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <N extends Number> Map<String, N> getNumberMap(final Class entityClass, final FilterFuncColumn... columns) {
|
||||
return source.getNumberMap(entityClass, columns);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <N extends Number> void getNumberMap(final AsyncHandler<Map<String, N>, FilterFuncColumn[]> handler, final Class entityClass, @RpcAttachment final FilterFuncColumn... columns) {
|
||||
source.getNumberMap(handler, entityClass, columns);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <N extends Number> Map<String, N> getNumberMap(final Class entityClass, final FilterBean bean, final FilterFuncColumn... columns) {
|
||||
return source.getNumberMap(entityClass, bean, columns);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <N extends Number, B extends FilterBean> void getNumberMap(final AsyncHandler<Map<String, N>, B> handler, final Class entityClass, @RpcAttachment final B bean, final FilterFuncColumn... columns) {
|
||||
source.getNumberMap(handler, entityClass, bean, columns);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <N extends Number> Map<String, N> getNumberMap(final Class entityClass, final FilterNode node, final FilterFuncColumn... columns) {
|
||||
return source.getNumberMap(entityClass, node, columns);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <N extends Number> void getNumberMap(final AsyncHandler<Map<String, N>, FilterNode> handler, final Class entityClass, @RpcAttachment final FilterNode node, final FilterFuncColumn... columns) {
|
||||
source.getNumberMap(handler, entityClass, node, columns);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T, K extends Serializable, N extends Number> Map<K, N> queryColumnMap(final Class<T> entityClass, final String keyColumn, FilterFunc func, final String funcColumn) {
|
||||
return source.queryColumnMap(entityClass, keyColumn, func, funcColumn);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T, K extends Serializable, N extends Number> void queryColumnMap(final AsyncHandler<Map<K, N>, String> handler, final Class<T> entityClass, @RpcAttachment final String keyColumn, final FilterFunc func, final String funcColumn) {
|
||||
source.queryColumnMap(handler, entityClass, keyColumn, func, funcColumn);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final <T, K extends Serializable, N extends Number> Map<K, N> queryColumnMap(final Class<T> entityClass, final String keyColumn, FilterFunc func, final String funcColumn, FilterBean bean) {
|
||||
return queryColumnMap(entityClass, keyColumn, func, funcColumn, FilterNodeBean.createFilterNode(bean));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T, K extends Serializable, N extends Number> void queryColumnMap(final AsyncHandler<Map<K, N>, String> handler, final Class<T> entityClass, @RpcAttachment final String keyColumn, final FilterFunc func, final String funcColumn, final FilterBean bean) {
|
||||
source.queryColumnMap(handler, entityClass, keyColumn, func, funcColumn, bean);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T, K extends Serializable, N extends Number> Map<K, N> queryColumnMap(final Class<T> entityClass, final String keyColumn, FilterFunc func, final String funcColumn, FilterNode node) {
|
||||
return source.queryColumnMap(entityClass, keyColumn, func, funcColumn, node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T, K extends Serializable, N extends Number> void queryColumnMap(final AsyncHandler<Map<K, N>, String> handler, final Class<T> entityClass, @RpcAttachment final String keyColumn, final FilterFunc func, final String funcColumn, final FilterNode node) {
|
||||
source.queryColumnMap(handler, entityClass, keyColumn, func, funcColumn, node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T find(final Class<T> clazz, final Serializable pk) {
|
||||
return source.find(clazz, pk);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void find(final AsyncHandler<T, Serializable> handler, final Class<T> clazz, @RpcAttachment final Serializable pk) {
|
||||
source.find(handler, clazz, pk);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T find(final Class<T> clazz, SelectColumn selects, final Serializable pk) {
|
||||
return source.find(clazz, selects, pk);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void find(final AsyncHandler<T, Serializable> handler, final Class<T> clazz, SelectColumn selects, @RpcAttachment final Serializable pk) {
|
||||
source.find(handler, clazz, selects, pk);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T find(final Class<T> clazz, final String column, final Serializable key) {
|
||||
return source.find(clazz, column, key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void find(final AsyncHandler<T, Serializable> handler, final Class<T> clazz, final String column, @RpcAttachment final Serializable key) {
|
||||
source.find(handler, clazz, column, key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final <T> T find(final Class<T> clazz, FilterBean bean) {
|
||||
return find(clazz, FilterNodeBean.createFilterNode(bean));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T, B extends FilterBean> void find(final AsyncHandler<T, B> handler, final Class<T> clazz, @RpcAttachment final B bean) {
|
||||
source.find(handler, clazz, bean);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T find(final Class<T> clazz, FilterNode node) {
|
||||
return source.find(clazz, node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void find(final AsyncHandler<T, FilterNode> handler, final Class<T> clazz, @RpcAttachment final FilterNode node) {
|
||||
source.find(handler, clazz, node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final <T> T find(final Class<T> clazz, final SelectColumn selects, FilterBean bean) {
|
||||
return find(clazz, selects, FilterNodeBean.createFilterNode(bean));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T, B extends FilterBean> void find(final AsyncHandler<T, B> handler, final Class<T> clazz, final SelectColumn selects, @RpcAttachment final B bean) {
|
||||
source.find(handler, clazz, selects, bean);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T find(final Class<T> clazz, final SelectColumn selects, final FilterNode node) {
|
||||
return source.find(clazz, selects, node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void find(final AsyncHandler<T, FilterNode> handler, final Class<T> clazz, final SelectColumn selects, @RpcAttachment final FilterNode node) {
|
||||
source.find(handler, clazz, selects, node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> Serializable findColumn(final Class<T> clazz, final String column, final Serializable pk) {
|
||||
return source.findColumn(clazz, column, pk);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void findColumn(final AsyncHandler<Serializable, Serializable> handler, final Class<T> clazz, final String column, @RpcAttachment final Serializable pk) {
|
||||
source.findColumn(handler, clazz, column, pk);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> Serializable findColumn(final Class<T> clazz, final String column, final FilterBean bean) {
|
||||
return source.findColumn(clazz, column, bean);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T, B extends FilterBean> void findColumn(final AsyncHandler<Serializable, B> handler, final Class<T> clazz, final String column, @RpcAttachment final B bean) {
|
||||
source.findColumn(handler, clazz, column, bean);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> Serializable findColumn(final Class<T> clazz, final String column, final FilterNode node) {
|
||||
return source.findColumn(clazz, column, node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void findColumn(final AsyncHandler<Serializable, FilterNode> handler, final Class<T> clazz, final String column, @RpcAttachment final FilterNode node) {
|
||||
source.findColumn(handler, clazz, column, node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> Serializable findColumn(final Class<T> clazz, final String column, final Serializable defValue, final Serializable pk) {
|
||||
return source.findColumn(clazz, column, defValue, pk);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void findColumn(final AsyncHandler<Serializable, Serializable> handler, final Class<T> clazz, final String column, final Serializable defValue, @RpcAttachment final Serializable pk) {
|
||||
source.findColumn(handler, clazz, column, defValue, pk);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> Serializable findColumn(final Class<T> clazz, final String column, final Serializable defValue, final FilterBean bean) {
|
||||
return source.findColumn(clazz, column, defValue, bean);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T, B extends FilterBean> void findColumn(final AsyncHandler<Serializable, B> handler, final Class<T> clazz, final String column, final Serializable defValue, @RpcAttachment final B bean) {
|
||||
source.findColumn(handler, clazz, column, defValue, bean);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> Serializable findColumn(final Class<T> clazz, final String column, final Serializable defValue, final FilterNode node) {
|
||||
return source.findColumn(clazz, column, defValue, node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void findColumn(final AsyncHandler<Serializable, FilterNode> handler, final Class<T> clazz, final String column, final Serializable defValue, @RpcAttachment final FilterNode node) {
|
||||
source.findColumn(handler, clazz, column, defValue, node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> boolean exists(final Class<T> clazz, final Serializable pk) {
|
||||
return source.exists(clazz, pk);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void exists(final AsyncHandler<Boolean, Serializable> handler, final Class<T> clazz, @RpcAttachment final Serializable pk) {
|
||||
source.exists(handler, clazz, pk);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final <T> boolean exists(final Class<T> clazz, FilterBean bean) {
|
||||
return exists(clazz, FilterNodeBean.createFilterNode(bean));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T, B extends FilterBean> void exists(final AsyncHandler<Boolean, B> handler, final Class<T> clazz, @RpcAttachment final B bean) {
|
||||
source.exists(handler, clazz, bean);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> boolean exists(final Class<T> clazz, FilterNode node) {
|
||||
return source.exists(clazz, node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void exists(final AsyncHandler<Boolean, FilterNode> handler, final Class<T> clazz, @RpcAttachment final FilterNode node) {
|
||||
source.exists(handler, clazz, node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T, V extends Serializable> HashSet<V> queryColumnSet(String selectedColumn, Class<T> clazz, final String column, final Serializable key) {
|
||||
return source.queryColumnSet(selectedColumn, clazz, column, key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T, V extends Serializable> void queryColumnSet(final AsyncHandler<HashSet<V>, String> handler, final String selectedColumn, final Class<T> clazz, @RpcAttachment final String column, final Serializable key) {
|
||||
source.queryColumnSet(handler, selectedColumn, clazz, column, key);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public final <T, V extends Serializable> HashSet<V> queryColumnSet(String selectedColumn, Class<T> clazz, FilterBean bean) {
|
||||
return queryColumnSet(selectedColumn, clazz, FilterNodeBean.createFilterNode(bean));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T, V extends Serializable, B extends FilterBean> void queryColumnSet(final AsyncHandler<HashSet<V>, B> handler, final String selectedColumn, final Class<T> clazz, @RpcAttachment final B bean) {
|
||||
source.queryColumnSet(handler, selectedColumn, clazz, bean);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T, V extends Serializable> HashSet<V> queryColumnSet(String selectedColumn, Class<T> clazz, FilterNode node) {
|
||||
return source.queryColumnSet(selectedColumn, clazz, node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T, V extends Serializable> void queryColumnSet(final AsyncHandler<HashSet<V>, FilterNode> handler, final String selectedColumn, final Class<T> clazz, @RpcAttachment final FilterNode node) {
|
||||
source.queryColumnSet(handler, selectedColumn, clazz, node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T, V extends Serializable> List<V> queryColumnList(String selectedColumn, Class<T> clazz, final String column, final Serializable key) {
|
||||
return source.queryColumnList(selectedColumn, clazz, column, key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T, V extends Serializable> void queryColumnList(final AsyncHandler<List<V>, Serializable> handler, final String selectedColumn, final Class<T> clazz, final String column, @RpcAttachment final Serializable key) {
|
||||
source.queryColumnList(handler, selectedColumn, clazz, column, key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final <T, V extends Serializable> List<V> queryColumnList(String selectedColumn, Class<T> clazz, FilterBean bean) {
|
||||
return queryColumnList(selectedColumn, clazz, FilterNodeBean.createFilterNode(bean));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T, V extends Serializable, B extends FilterBean> void queryColumnList(final AsyncHandler<List<V>, B> handler, String selectedColumn, Class<T> clazz, @RpcAttachment final B bean) {
|
||||
source.queryColumnList(handler, selectedColumn, clazz, bean);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T, V extends Serializable> List<V> queryColumnList(String selectedColumn, Class<T> clazz, FilterNode node) {
|
||||
return source.queryColumnList(selectedColumn, clazz, node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T, V extends Serializable> void queryColumnList(final AsyncHandler<List<V>, FilterNode> handler, final String selectedColumn, final Class<T> clazz, @RpcAttachment final FilterNode node) {
|
||||
source.queryColumnList(handler, selectedColumn, clazz, node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final <T, V extends Serializable> List<V> queryColumnList(String selectedColumn, Class<T> clazz, Flipper flipper, FilterBean bean) {
|
||||
return queryColumnList(selectedColumn, clazz, flipper, FilterNodeBean.createFilterNode(bean));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T, V extends Serializable, B extends FilterBean> void queryColumnList(final AsyncHandler<List<V>, B> handler, String selectedColumn, Class<T> clazz, Flipper flipper, @RpcAttachment final B bean) {
|
||||
source.queryColumnList(handler, selectedColumn, clazz, flipper, bean);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T, V extends Serializable> List<V> queryColumnList(String selectedColumn, Class<T> clazz, Flipper flipper, FilterNode node) {
|
||||
return source.queryColumnList(selectedColumn, clazz, flipper, node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T, V extends Serializable> void queryColumnList(final AsyncHandler<List<V>, FilterNode> handler, final String selectedColumn, final Class<T> clazz, Flipper flipper, @RpcAttachment final FilterNode node) {
|
||||
source.queryColumnList(handler, selectedColumn, clazz, flipper, node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final <T, V extends Serializable> Sheet<V> queryColumnSheet(String selectedColumn, Class<T> clazz, Flipper flipper, FilterBean bean) {
|
||||
return queryColumnSheet(selectedColumn, clazz, flipper, FilterNodeBean.createFilterNode(bean));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T, V extends Serializable, B extends FilterBean> void queryColumnSheet(final AsyncHandler<Sheet<V>, B> handler, String selectedColumn, Class<T> clazz, Flipper flipper, @RpcAttachment B bean) {
|
||||
source.queryColumnSheet(handler, selectedColumn, clazz, flipper, bean);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T, V extends Serializable> Sheet<V> queryColumnSheet(String selectedColumn, Class<T> clazz, Flipper flipper, FilterNode node) {
|
||||
return source.queryColumnSheet(selectedColumn, clazz, flipper, node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T, V extends Serializable> void queryColumnSheet(final AsyncHandler<Sheet<V>, FilterNode> handler, final String selectedColumn, final Class<T> clazz, final Flipper flipper, @RpcAttachment final FilterNode node) {
|
||||
source.queryColumnSheet(handler, selectedColumn, clazz, flipper, node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> List<T> queryList(final Class<T> clazz, final String column, final Serializable key) {
|
||||
return source.queryList(clazz, column, key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void queryList(final AsyncHandler<List<T>, Serializable> handler, final Class<T> clazz, final String column, @RpcAttachment final Serializable key) {
|
||||
source.queryList(handler, clazz, column, key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final <T> List<T> queryList(final Class<T> clazz, final FilterBean bean) {
|
||||
return queryList(clazz, FilterNodeBean.createFilterNode(bean));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T, B extends FilterBean> void queryList(final AsyncHandler<List<T>, B> handler, final Class<T> clazz, @RpcAttachment final B bean) {
|
||||
source.queryList(handler, clazz, bean);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> List<T> queryList(final Class<T> clazz, final FilterNode node) {
|
||||
return source.queryList(clazz, node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void queryList(final AsyncHandler<List<T>, FilterNode> handler, final Class<T> clazz, @RpcAttachment final FilterNode node) {
|
||||
source.queryList(handler, clazz, node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final <T> List<T> queryList(final Class<T> clazz, final SelectColumn selects, final FilterBean bean) {
|
||||
return queryList(clazz, FilterNodeBean.createFilterNode(bean));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T, B extends FilterBean> void queryList(final AsyncHandler<List<T>, B> handler, final Class<T> clazz, final SelectColumn selects, @RpcAttachment final B bean) {
|
||||
source.queryList(handler, clazz, selects, bean);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> List<T> queryList(final Class<T> clazz, final SelectColumn selects, final FilterNode node) {
|
||||
return source.queryList(clazz, selects, node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void queryList(final AsyncHandler<List<T>, FilterNode> handler, final Class<T> clazz, final SelectColumn selects, @RpcAttachment final FilterNode node) {
|
||||
source.queryList(handler, clazz, selects, node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> List<T> queryList(final Class<T> clazz, final Flipper flipper, final String column, final Serializable key) {
|
||||
return source.queryList(clazz, flipper, column, key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void queryList(final AsyncHandler<List<T>, Serializable> handler, final Class<T> clazz, final Flipper flipper, final String column, @RpcAttachment final Serializable key) {
|
||||
source.queryList(handler, clazz, flipper, column, key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final <T> List<T> queryList(final Class<T> clazz, final Flipper flipper, final FilterBean bean) {
|
||||
return queryList(clazz, flipper, FilterNodeBean.createFilterNode(bean));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T, B extends FilterBean> void queryList(final AsyncHandler<List<T>, B> handler, final Class<T> clazz, final Flipper flipper, @RpcAttachment final B bean) {
|
||||
source.queryList(handler, clazz, flipper, bean);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> List<T> queryList(final Class<T> clazz, final Flipper flipper, final FilterNode node) {
|
||||
return source.queryList(clazz, flipper, node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void queryList(final AsyncHandler<List<T>, FilterNode> handler, final Class<T> clazz, final Flipper flipper, @RpcAttachment final FilterNode node) {
|
||||
source.queryList(handler, clazz, flipper, node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final <T> List<T> queryList(final Class<T> clazz, final SelectColumn selects, final Flipper flipper, final FilterBean bean) {
|
||||
return queryList(clazz, selects, flipper, FilterNodeBean.createFilterNode(bean));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T, B extends FilterBean> void queryList(final AsyncHandler<List<T>, B> handler, final Class<T> clazz, final SelectColumn selects, final Flipper flipper, @RpcAttachment final B bean) {
|
||||
source.queryList(handler, clazz, selects, flipper, bean);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> List<T> queryList(final Class<T> clazz, final SelectColumn selects, final Flipper flipper, final FilterNode node) {
|
||||
return source.queryList(clazz, selects, flipper, node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void queryList(final AsyncHandler<List<T>, FilterNode> handler, final Class<T> clazz, final SelectColumn selects, final Flipper flipper, @RpcAttachment final FilterNode node) {
|
||||
source.queryList(handler, clazz, selects, flipper, node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final <T> Sheet<T> querySheet(final Class<T> clazz, final Flipper flipper, final FilterBean bean) {
|
||||
return querySheet(clazz, flipper, FilterNodeBean.createFilterNode(bean));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T, B extends FilterBean> void querySheet(final AsyncHandler<Sheet<T>, B> handler, final Class<T> clazz, final Flipper flipper, @RpcAttachment final B bean) {
|
||||
source.querySheet(handler, clazz, flipper, bean);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> Sheet<T> querySheet(final Class<T> clazz, final Flipper flipper, final FilterNode node) {
|
||||
return source.querySheet(clazz, flipper, node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void querySheet(final AsyncHandler<Sheet<T>, FilterNode> handler, final Class<T> clazz, final Flipper flipper, @RpcAttachment final FilterNode node) {
|
||||
source.querySheet(handler, clazz, flipper, node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final <T> Sheet<T> querySheet(final Class<T> clazz, final SelectColumn selects, final Flipper flipper, final FilterBean bean) {
|
||||
return querySheet(clazz, selects, flipper, FilterNodeBean.createFilterNode(bean));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T, B extends FilterBean> void querySheet(final AsyncHandler<Sheet<T>, B> handler, final Class<T> clazz, final SelectColumn selects, final Flipper flipper, @RpcAttachment final B bean) {
|
||||
source.querySheet(handler, clazz, selects, flipper, bean);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> Sheet<T> querySheet(final Class<T> clazz, final SelectColumn selects, final Flipper flipper, final FilterNode node) {
|
||||
return source.querySheet(clazz, selects, flipper, node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void querySheet(final AsyncHandler<Sheet<T>, FilterNode> handler, final Class<T> clazz, final SelectColumn selects, final Flipper flipper, @RpcAttachment final FilterNode node) {
|
||||
source.querySheet(handler, clazz, selects, flipper, node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws Exception {
|
||||
source.getClass().getMethod("close").invoke(source);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void directQuery(String sql, Consumer<ResultSet> consumer) {
|
||||
source.directQuery(sql, consumer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int[] directExecute(String... sqls) {
|
||||
return source.directExecute(sqls);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -49,7 +49,7 @@ public class WebSocketNodeService extends WebSocketNode implements Service {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int sendMessage(@RpcTargetAddress InetSocketAddress addr, Serializable groupid, boolean recent, Serializable message, boolean last) {
|
||||
public int sendMessage(@RpcTargetAddress InetSocketAddress addr, Serializable groupid, boolean recent, Object message, boolean last) {
|
||||
final Set<String> engineids = localNodes.get(groupid);
|
||||
if (engineids == null || engineids.isEmpty()) return RETCODE_GROUP_EMPTY;
|
||||
int code = RETCODE_GROUP_EMPTY;
|
||||
|
||||
@@ -3,23 +3,24 @@
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.service;
|
||||
package org.redkale.source;
|
||||
|
||||
import java.beans.*;
|
||||
import java.beans.ConstructorProperties;
|
||||
import java.io.*;
|
||||
import java.lang.reflect.*;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.function.*;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.logging.*;
|
||||
import javax.annotation.*;
|
||||
import org.redkale.convert.*;
|
||||
import javax.annotation.Resource;
|
||||
import org.redkale.convert.ConvertColumn;
|
||||
import org.redkale.convert.json.*;
|
||||
import org.redkale.net.sncp.*;
|
||||
import org.redkale.source.*;
|
||||
import org.redkale.net.sncp.Sncp;
|
||||
import org.redkale.service.*;
|
||||
import org.redkale.util.*;
|
||||
|
||||
/**
|
||||
* CacheSource的默认实现--内存缓存
|
||||
*
|
||||
* @param <K> key类型
|
||||
* @param <V> value类型
|
||||
@@ -28,9 +29,10 @@ import org.redkale.util.*;
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
@LocalService
|
||||
@AutoLoad(false)
|
||||
@ResourceType({CacheSourceService.class, CacheSource.class})
|
||||
public class CacheSourceService<K extends Serializable, V extends Object> implements CacheSource<K, V>, Service, AutoCloseable {
|
||||
@ResourceType({CacheSource.class})
|
||||
public class CacheMemorySource<K extends Serializable, V extends Object> extends AbstractService implements CacheSource<K, V>, Service, AutoCloseable, Resourcable {
|
||||
|
||||
@Resource(name = "APP_HOME")
|
||||
private File home;
|
||||
@@ -56,10 +58,10 @@ public class CacheSourceService<K extends Serializable, V extends Object> implem
|
||||
|
||||
protected final ConcurrentHashMap<K, CacheEntry<K, ?>> container = new ConcurrentHashMap<>();
|
||||
|
||||
public CacheSourceService() {
|
||||
public CacheMemorySource() {
|
||||
}
|
||||
|
||||
public final CacheSourceService setStoreType(Class keyType, Class valueType) {
|
||||
public final CacheMemorySource setStoreType(Class keyType, Class valueType) {
|
||||
this.keyType = keyType;
|
||||
this.objValueType = valueType;
|
||||
this.setValueType = TypeToken.createParameterizedType(null, CopyOnWriteArraySet.class, valueType);
|
||||
@@ -74,7 +76,7 @@ public class CacheSourceService<K extends Serializable, V extends Object> implem
|
||||
|
||||
@Override
|
||||
public void init(AnyValue conf) {
|
||||
final CacheSourceService self = this;
|
||||
final CacheMemorySource self = this;
|
||||
AnyValue prop = conf == null ? null : conf.getAnyValue("property");
|
||||
if (keyType == null && prop != null) {
|
||||
String storeKeyStr = prop.getValue("key-type");
|
||||
@@ -116,7 +118,7 @@ public class CacheSourceService<K extends Serializable, V extends Object> implem
|
||||
if (expireHandler != null && entry != null) expireHandler.accept(entry);
|
||||
}
|
||||
}, 10, 10, TimeUnit.SECONDS);
|
||||
logger.finest(self.getClass().getSimpleName() + ":" + self.name() + " start schedule expire executor");
|
||||
logger.finest(self.getClass().getSimpleName() + ":" + self.resourceName() + " start schedule expire executor");
|
||||
}
|
||||
if (Sncp.isRemote(self)) return;
|
||||
|
||||
@@ -125,7 +127,7 @@ public class CacheSourceService<K extends Serializable, V extends Object> implem
|
||||
// TODO
|
||||
if (!this.needStore) return;
|
||||
try {
|
||||
File store = new File(home, "cache/" + name());
|
||||
File store = new File(home, "cache/" + resourceName());
|
||||
if (!store.isFile() || !store.canRead()) return;
|
||||
LineNumberReader reader = new LineNumberReader(new FileReader(store));
|
||||
if (this.keyType == null) this.keyType = Serializable.class;
|
||||
@@ -148,7 +150,7 @@ public class CacheSourceService<K extends Serializable, V extends Object> implem
|
||||
reader.close();
|
||||
store.delete();
|
||||
} catch (Exception e) {
|
||||
logger.log(Level.SEVERE, CacheSource.class.getSimpleName() + "(" + name() + ") load store file error ", e);
|
||||
logger.log(Level.SEVERE, CacheSource.class.getSimpleName() + "(" + resourceName() + ") load store file error ", e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -157,8 +159,10 @@ public class CacheSourceService<K extends Serializable, V extends Object> implem
|
||||
destroy(null);
|
||||
}
|
||||
|
||||
public String name() {
|
||||
return this.getClass().getAnnotation(Resource.class).name();
|
||||
@Override
|
||||
public String resourceName() {
|
||||
Resource res = this.getClass().getAnnotation(Resource.class);
|
||||
return res == null ? null : res.name();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -166,7 +170,7 @@ public class CacheSourceService<K extends Serializable, V extends Object> implem
|
||||
if (scheduler != null) scheduler.shutdownNow();
|
||||
if (!this.needStore || Sncp.isRemote(this) || container.isEmpty()) return;
|
||||
try {
|
||||
File store = new File(home, "cache/" + name());
|
||||
File store = new File(home, "cache/" + resourceName());
|
||||
store.getParentFile().mkdirs();
|
||||
PrintStream stream = new PrintStream(store, "UTF-8");
|
||||
final Type storeObjType = TypeToken.createParameterizedType(null, CacheEntry.class, keyType, objValueType);
|
||||
@@ -179,7 +183,7 @@ public class CacheSourceService<K extends Serializable, V extends Object> implem
|
||||
container.clear();
|
||||
stream.close();
|
||||
} catch (Exception e) {
|
||||
logger.log(Level.SEVERE, CacheSource.class.getSimpleName() + "(" + name() + ") store to file error ", e);
|
||||
logger.log(Level.SEVERE, CacheSource.class.getSimpleName() + "(" + resourceName() + ") store to file error ", e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -192,9 +196,20 @@ public class CacheSourceService<K extends Serializable, V extends Object> implem
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exists(final AsyncHandler<Boolean, K> handler, @RpcAttachment final K key) {
|
||||
boolean rs = exists(key);
|
||||
if (handler != null) handler.completed(rs, key);
|
||||
public CompletableFuture<Boolean> existsAsync(final K key) {
|
||||
return CompletableFuture.supplyAsync(() -> exists(key), getExecutor());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void existsAsync(final AsyncHandler<Boolean, K> handler, @RpcAttachment final K key) {
|
||||
super.runAsync(() -> {
|
||||
try {
|
||||
boolean rs = exists(key);
|
||||
if (handler != null) handler.completed(rs, key);
|
||||
} catch (Throwable t) {
|
||||
if (handler != null) handler.failed(t, key);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -208,9 +223,20 @@ public class CacheSourceService<K extends Serializable, V extends Object> implem
|
||||
}
|
||||
|
||||
@Override
|
||||
public void get(final AsyncHandler<V, K> handler, @RpcAttachment final K key) {
|
||||
V rs = get(key);
|
||||
if (handler != null) handler.completed(rs, key);
|
||||
public CompletableFuture<V> getAsync(final K key) {
|
||||
return CompletableFuture.supplyAsync(() -> get(key), getExecutor());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getAsync(final AsyncHandler<V, K> handler, @RpcAttachment final K key) {
|
||||
super.runAsync(() -> {
|
||||
try {
|
||||
V rs = get(key);
|
||||
if (handler != null) handler.completed(rs, key);
|
||||
} catch (Throwable t) {
|
||||
if (handler != null) handler.failed(t, key);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -227,9 +253,20 @@ public class CacheSourceService<K extends Serializable, V extends Object> implem
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getAndRefresh(final AsyncHandler<V, K> handler, @RpcAttachment final K key, final int expireSeconds) {
|
||||
V rs = getAndRefresh(key, expireSeconds);
|
||||
if (handler != null) handler.completed(rs, key);
|
||||
public CompletableFuture<V> getAndRefreshAsync(final K key, final int expireSeconds) {
|
||||
return CompletableFuture.supplyAsync(() -> getAndRefresh(key, expireSeconds), getExecutor());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getAndRefreshAsync(final AsyncHandler<V, K> handler, @RpcAttachment final K key, final int expireSeconds) {
|
||||
super.runAsync(() -> {
|
||||
try {
|
||||
V rs = getAndRefresh(key, expireSeconds);
|
||||
if (handler != null) handler.completed(rs, key);
|
||||
} catch (Throwable t) {
|
||||
if (handler != null) handler.failed(t, key);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -243,9 +280,20 @@ public class CacheSourceService<K extends Serializable, V extends Object> implem
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refresh(final AsyncHandler<Void, K> handler, @RpcAttachment final K key, final int expireSeconds) {
|
||||
refresh(key, expireSeconds);
|
||||
if (handler != null) handler.completed(null, key);
|
||||
public CompletableFuture<Void> refreshAsync(final K key, final int expireSeconds) {
|
||||
return CompletableFuture.runAsync(() -> refresh(key, expireSeconds), getExecutor());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refreshAsync(final AsyncHandler<Void, K> handler, @RpcAttachment final K key, final int expireSeconds) {
|
||||
super.runAsync(() -> {
|
||||
try {
|
||||
refresh(key, expireSeconds);
|
||||
if (handler != null) handler.completed(null, key);
|
||||
} catch (Throwable t) {
|
||||
if (handler != null) handler.failed(t, key);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -264,9 +312,20 @@ public class CacheSourceService<K extends Serializable, V extends Object> implem
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(final AsyncHandler<Void, K> handler, @RpcAttachment final K key, final V value) {
|
||||
set(key, value);
|
||||
if (handler != null) handler.completed(null, key);
|
||||
public CompletableFuture<Void> setAsync(K key, V value) {
|
||||
return CompletableFuture.runAsync(() -> set(key, value), getExecutor());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAsync(final AsyncHandler<Void, K> handler, @RpcAttachment final K key, final V value) {
|
||||
super.runAsync(() -> {
|
||||
try {
|
||||
set(key, value);
|
||||
if (handler != null) handler.completed(null, key);
|
||||
} catch (Throwable t) {
|
||||
if (handler != null) handler.failed(t, key);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -285,9 +344,20 @@ public class CacheSourceService<K extends Serializable, V extends Object> implem
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(final AsyncHandler<Void, K> handler, final int expireSeconds, @RpcAttachment final K key, final V value) {
|
||||
set(expireSeconds, key, value);
|
||||
if (handler != null) handler.completed(null, key);
|
||||
public CompletableFuture<Void> setAsync(int expireSeconds, K key, V value) {
|
||||
return CompletableFuture.runAsync(() -> set(expireSeconds, key, value), getExecutor());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAsync(final AsyncHandler<Void, K> handler, final int expireSeconds, @RpcAttachment final K key, final V value) {
|
||||
super.runAsync(() -> {
|
||||
try {
|
||||
set(expireSeconds, key, value);
|
||||
if (handler != null) handler.completed(null, key);
|
||||
} catch (Throwable t) {
|
||||
if (handler != null) handler.failed(t, key);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -300,9 +370,20 @@ public class CacheSourceService<K extends Serializable, V extends Object> implem
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setExpireSeconds(final AsyncHandler<Void, K> handler, @RpcAttachment final K key, final int expireSeconds) {
|
||||
setExpireSeconds(key, expireSeconds);
|
||||
if (handler != null) handler.completed(null, key);
|
||||
public CompletableFuture<Void> setExpireSecondsAsync(final K key, final int expireSeconds) {
|
||||
return CompletableFuture.runAsync(() -> setExpireSeconds(key, expireSeconds), getExecutor());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setExpireSecondsAsync(final AsyncHandler<Void, K> handler, @RpcAttachment final K key, final int expireSeconds) {
|
||||
super.runAsync(() -> {
|
||||
try {
|
||||
setExpireSeconds(key, expireSeconds);
|
||||
if (handler != null) handler.completed(null, key);
|
||||
} catch (Throwable t) {
|
||||
if (handler != null) handler.failed(t, key);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -313,9 +394,20 @@ public class CacheSourceService<K extends Serializable, V extends Object> implem
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(final AsyncHandler<Void, K> handler, @RpcAttachment final K key) {
|
||||
remove(key);
|
||||
if (handler != null) handler.completed(null, key);
|
||||
public CompletableFuture<Void> removeAsync(final K key) {
|
||||
return CompletableFuture.runAsync(() -> remove(key), getExecutor());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeAsync(final AsyncHandler<Void, K> handler, @RpcAttachment final K key) {
|
||||
super.runAsync(() -> {
|
||||
try {
|
||||
remove(key);
|
||||
if (handler != null) handler.completed(null, key);
|
||||
} catch (Throwable t) {
|
||||
if (handler != null) handler.failed(t, key);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -324,9 +416,20 @@ public class CacheSourceService<K extends Serializable, V extends Object> implem
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getCollection(final AsyncHandler<Collection<V>, K> handler, @RpcAttachment final K key) {
|
||||
Collection<V> rs = getCollection(key);
|
||||
if (handler != null) handler.completed(rs, key);
|
||||
public CompletableFuture<Collection<V>> getCollectionAsync(final K key) {
|
||||
return CompletableFuture.supplyAsync(() -> getCollection(key), getExecutor());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getCollectionAsync(final AsyncHandler<Collection<V>, K> handler, @RpcAttachment final K key) {
|
||||
super.runAsync(() -> {
|
||||
try {
|
||||
Collection<V> rs = getCollection(key);
|
||||
if (handler != null) handler.completed(rs, key);
|
||||
} catch (Throwable t) {
|
||||
if (handler != null) handler.failed(t, key);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -335,9 +438,20 @@ public class CacheSourceService<K extends Serializable, V extends Object> implem
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getCollectionAndRefresh(final AsyncHandler<Collection<V>, K> handler, @RpcAttachment final K key, final int expireSeconds) {
|
||||
Collection<V> rs = getCollectionAndRefresh(key, expireSeconds);
|
||||
if (handler != null) handler.completed(rs, key);
|
||||
public CompletableFuture<Collection<V>> getCollectionAndRefreshAsync(final K key, final int expireSeconds) {
|
||||
return CompletableFuture.supplyAsync(() -> getCollectionAndRefresh(key, expireSeconds), getExecutor());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getCollectionAndRefreshAsync(final AsyncHandler<Collection<V>, K> handler, @RpcAttachment final K key, final int expireSeconds) {
|
||||
super.runAsync(() -> {
|
||||
try {
|
||||
Collection<V> rs = getCollectionAndRefresh(key, expireSeconds);
|
||||
if (handler != null) handler.completed(rs, key);
|
||||
} catch (Throwable t) {
|
||||
if (handler != null) handler.failed(t, key);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -357,9 +471,20 @@ public class CacheSourceService<K extends Serializable, V extends Object> implem
|
||||
}
|
||||
|
||||
@Override
|
||||
public void appendListItem(final AsyncHandler<Void, K> handler, @RpcAttachment final K key, final V value) {
|
||||
appendListItem(key, value);
|
||||
if (handler != null) handler.completed(null, key);
|
||||
public CompletableFuture<Void> appendListItemAsync(final K key, final V value) {
|
||||
return CompletableFuture.runAsync(() -> appendListItem(key, value), getExecutor());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void appendListItemAsync(final AsyncHandler<Void, K> handler, @RpcAttachment final K key, final V value) {
|
||||
super.runAsync(() -> {
|
||||
try {
|
||||
appendListItem(key, value);
|
||||
if (handler != null) handler.completed(null, key);
|
||||
} catch (Throwable t) {
|
||||
if (handler != null) handler.failed(t, key);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -372,9 +497,20 @@ public class CacheSourceService<K extends Serializable, V extends Object> implem
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeListItem(final AsyncHandler<Void, K> handler, @RpcAttachment final K key, final V value) {
|
||||
removeListItem(key, value);
|
||||
if (handler != null) handler.completed(null, key);
|
||||
public CompletableFuture<Void> removeListItemAsync(final K key, final V value) {
|
||||
return CompletableFuture.runAsync(() -> removeListItem(key, value), getExecutor());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeListItemAsync(final AsyncHandler<Void, K> handler, @RpcAttachment final K key, final V value) {
|
||||
super.runAsync(() -> {
|
||||
try {
|
||||
removeListItem(key, value);
|
||||
if (handler != null) handler.completed(null, key);
|
||||
} catch (Throwable t) {
|
||||
if (handler != null) handler.failed(t, key);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -394,9 +530,20 @@ public class CacheSourceService<K extends Serializable, V extends Object> implem
|
||||
}
|
||||
|
||||
@Override
|
||||
public void appendSetItem(final AsyncHandler<Void, K> handler, @RpcAttachment final K key, final V value) {
|
||||
appendSetItem(key, value);
|
||||
if (handler != null) handler.completed(null, key);
|
||||
public CompletableFuture<Void> appendSetItemAsync(final K key, final V value) {
|
||||
return CompletableFuture.runAsync(() -> appendSetItem(key, value), getExecutor());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void appendSetItemAsync(final AsyncHandler<Void, K> handler, @RpcAttachment final K key, final V value) {
|
||||
super.runAsync(() -> {
|
||||
try {
|
||||
appendSetItem(key, value);
|
||||
if (handler != null) handler.completed(null, key);
|
||||
} catch (Throwable t) {
|
||||
if (handler != null) handler.failed(t, key);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -409,9 +556,20 @@ public class CacheSourceService<K extends Serializable, V extends Object> implem
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeSetItem(final AsyncHandler<Void, K> handler, @RpcAttachment final K key, final V value) {
|
||||
removeSetItem(key, value);
|
||||
if (handler != null) handler.completed(null, key);
|
||||
public CompletableFuture<Void> removeSetItemAsync(final K key, final V value) {
|
||||
return CompletableFuture.runAsync(() -> removeSetItem(key, value), getExecutor());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeSetItemAsync(final AsyncHandler<Void, K> handler, @RpcAttachment final K key, final V value) {
|
||||
super.runAsync(() -> {
|
||||
try {
|
||||
removeSetItem(key, value);
|
||||
if (handler != null) handler.completed(null, key);
|
||||
} catch (Throwable t) {
|
||||
if (handler != null) handler.failed(t, key);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static enum CacheEntryType {
|
||||
@@ -7,6 +7,7 @@ package org.redkale.source;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import org.redkale.util.*;
|
||||
|
||||
/**
|
||||
@@ -52,36 +53,84 @@ public interface CacheSource<K extends Serializable, V extends Object> {
|
||||
|
||||
public void removeSetItem(final K key, final V value);
|
||||
|
||||
//----------------------异步版---------------------------------
|
||||
public void exists(final AsyncHandler<Boolean, K> handler, final K key);
|
||||
//---------------------- CompletableFuture 异步版 ---------------------------------
|
||||
public CompletableFuture<Boolean> existsAsync(final K key);
|
||||
|
||||
public void get(final AsyncHandler<V, K> handler, final K key);
|
||||
public CompletableFuture<V> getAsync(final K key);
|
||||
|
||||
public void getAndRefresh(final AsyncHandler<V, K> handler, final K key, final int expireSeconds);
|
||||
public CompletableFuture<V> getAndRefreshAsync(final K key, final int expireSeconds);
|
||||
|
||||
public void refresh(final AsyncHandler<Void, K> handler, final K key, final int expireSeconds);
|
||||
public CompletableFuture<Void> refreshAsync(final K key, final int expireSeconds);
|
||||
|
||||
public void set(final AsyncHandler<Void, K> handler, final K key, final V value);
|
||||
public CompletableFuture<Void> setAsync(final K key, final V value);
|
||||
|
||||
public void set(final AsyncHandler<Void, K> handler, final int expireSeconds, final K key, final V value);
|
||||
public CompletableFuture<Void> setAsync(final int expireSeconds, final K key, final V value);
|
||||
|
||||
public void setExpireSeconds(final AsyncHandler<Void, K> handler, final K key, final int expireSeconds);
|
||||
public CompletableFuture<Void> setExpireSecondsAsync(final K key, final int expireSeconds);
|
||||
|
||||
public void remove(final AsyncHandler<Void, K> handler, final K key);
|
||||
public CompletableFuture<Void> removeAsync(final K key);
|
||||
|
||||
public void getCollection(final AsyncHandler<Collection<V>, K> handler, final K key);
|
||||
public CompletableFuture<Collection<V>> getCollectionAsync(final K key);
|
||||
|
||||
public void getCollectionAndRefresh(final AsyncHandler<Collection<V>, K> handler, final K key, final int expireSeconds);
|
||||
public CompletableFuture<Collection<V>> getCollectionAndRefreshAsync(final K key, final int expireSeconds);
|
||||
|
||||
public void appendListItem(final AsyncHandler<Void, K> handler, final K key, final V value);
|
||||
public CompletableFuture<Void> appendListItemAsync(final K key, final V value);
|
||||
|
||||
public void removeListItem(final AsyncHandler<Void, K> handler, final K key, final V value);
|
||||
public CompletableFuture<Void> removeListItemAsync(final K key, final V value);
|
||||
|
||||
public void appendSetItem(final AsyncHandler<Void, K> handler, final K key, final V value);
|
||||
public CompletableFuture<Void> appendSetItemAsync(final K key, final V value);
|
||||
|
||||
public void removeSetItem(final AsyncHandler<Void, K> handler, final K key, final V value);
|
||||
public CompletableFuture<Void> removeSetItemAsync(final K key, final V value);
|
||||
|
||||
default void isOpen(final AsyncHandler<Boolean, Void> handler) {
|
||||
default CompletableFuture<Boolean> isOpenAsync() {
|
||||
return CompletableFuture.completedFuture(true);
|
||||
}
|
||||
|
||||
//---------------------- AsyncHandler 异步版 ---------------------------------
|
||||
@Deprecated
|
||||
public void existsAsync(final AsyncHandler<Boolean, K> handler, final K key);
|
||||
|
||||
@Deprecated
|
||||
public void getAsync(final AsyncHandler<V, K> handler, final K key);
|
||||
|
||||
@Deprecated
|
||||
public void getAndRefreshAsync(final AsyncHandler<V, K> handler, final K key, final int expireSeconds);
|
||||
|
||||
@Deprecated
|
||||
public void refreshAsync(final AsyncHandler<Void, K> handler, final K key, final int expireSeconds);
|
||||
|
||||
@Deprecated
|
||||
public void setAsync(final AsyncHandler<Void, K> handler, final K key, final V value);
|
||||
|
||||
@Deprecated
|
||||
public void setAsync(final AsyncHandler<Void, K> handler, final int expireSeconds, final K key, final V value);
|
||||
|
||||
@Deprecated
|
||||
public void setExpireSecondsAsync(final AsyncHandler<Void, K> handler, final K key, final int expireSeconds);
|
||||
|
||||
@Deprecated
|
||||
public void removeAsync(final AsyncHandler<Void, K> handler, final K key);
|
||||
|
||||
@Deprecated
|
||||
public void getCollectionAsync(final AsyncHandler<Collection<V>, K> handler, final K key);
|
||||
|
||||
@Deprecated
|
||||
public void getCollectionAndRefreshAsync(final AsyncHandler<Collection<V>, K> handler, final K key, final int expireSeconds);
|
||||
|
||||
@Deprecated
|
||||
public void appendListItemAsync(final AsyncHandler<Void, K> handler, final K key, final V value);
|
||||
|
||||
@Deprecated
|
||||
public void removeListItemAsync(final AsyncHandler<Void, K> handler, final K key, final V value);
|
||||
|
||||
@Deprecated
|
||||
public void appendSetItemAsync(final AsyncHandler<Void, K> handler, final K key, final V value);
|
||||
|
||||
@Deprecated
|
||||
public void removeSetItemAsync(final AsyncHandler<Void, K> handler, final K key, final V value);
|
||||
|
||||
@Deprecated
|
||||
default void isOpenAsync(final AsyncHandler<Boolean, Void> handler) {
|
||||
if (handler != null) handler.completed(Boolean.TRUE, null);
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -264,6 +264,7 @@ public final class EntityInfo<T> {
|
||||
attributeMap.put(fieldname, attr);
|
||||
}
|
||||
} while ((cltmp = cltmp.getSuperclass()) != Object.class);
|
||||
if (idAttr0 == null) throw new RuntimeException(type.getName() + " have no primary column by @javax.persistence.Id");
|
||||
this.primary = idAttr0;
|
||||
this.aliasmap = aliasmap0;
|
||||
this.attributes = attributeMap.values().toArray(new Attribute[attributeMap.size()]);
|
||||
|
||||
@@ -55,7 +55,7 @@ public interface AsyncHandler<V, A> extends CompletionHandler<V, A> {
|
||||
*
|
||||
* @return AsyncHandler
|
||||
*/
|
||||
public static <A> AsyncHandler<Void, A> createNoResultHandler(final Consumer<A> success, final BiConsumer<Throwable, A> fail) {
|
||||
public static <A> AsyncHandler<Void, A> create(final Consumer<A> success, final BiConsumer<Throwable, A> fail) {
|
||||
return new AsyncHandler<Void, A>() {
|
||||
@Override
|
||||
public void completed(Void result, A attachment) {
|
||||
@@ -78,7 +78,7 @@ public interface AsyncHandler<V, A> extends CompletionHandler<V, A> {
|
||||
*
|
||||
* @return AsyncHandler
|
||||
*/
|
||||
public static <V> AsyncHandler<V, Void> createNoAttachHandler(final Consumer<V> success, final Consumer<Throwable> fail) {
|
||||
public static <V> AsyncHandler<V, Void> create(final Consumer<V> success, final Consumer<Throwable> fail) {
|
||||
return new AsyncHandler<V, Void>() {
|
||||
@Override
|
||||
public void completed(V result, Void attachment) {
|
||||
|
||||
@@ -15,6 +15,9 @@ import java.util.regex.Pattern;
|
||||
import javax.annotation.Resource;
|
||||
|
||||
/**
|
||||
*
|
||||
* 依赖注入功能主类 <br>
|
||||
*
|
||||
* 如果@Resource(name = "$") 表示资源name采用所属对象的name <br>
|
||||
* 如果没有@Resource 则会取对象的getResourceName()方法值(若存在)
|
||||
* <blockquote><pre>
|
||||
@@ -59,7 +62,7 @@ public final class ResourceFactory {
|
||||
}
|
||||
|
||||
public void checkName(String name) {
|
||||
if (name == null || (!name.isEmpty() && !name.matches("^[a-zA-Z0-9_\\-\\.\\[\\]\\(\\)]+$"))) {
|
||||
if (name == null || (!name.isEmpty() && !name.matches("^[a-zA-Z0-9_;\\-\\.\\[\\]\\(\\)]+$"))) {
|
||||
throw new IllegalArgumentException("Resource.name(" + name + ") contains illegal character, must be (a-z,A-Z,0-9,_,.,(,),-,[,])");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import java.lang.reflect.*;
|
||||
import java.net.*;
|
||||
import java.nio.*;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.BiConsumer;
|
||||
import org.redkale.convert.json.*;
|
||||
import org.redkale.net.http.*;
|
||||
@@ -60,10 +61,10 @@ public interface HttpResponseDesc {
|
||||
|
||||
//异步输出指定内容
|
||||
public <A> void sendBody(ByteBuffer buffer, A attachment, AsyncHandler<Integer, A> handler);
|
||||
|
||||
|
||||
//创建AsyncHandler实例,将非字符串对象以JSON格式输出,字符串以文本输出
|
||||
public AsyncHandler createAsyncHandler();
|
||||
|
||||
|
||||
//关闭HTTP连接,如果是keep-alive则不强制关闭
|
||||
public void finish();
|
||||
|
||||
@@ -91,6 +92,15 @@ public interface HttpResponseDesc {
|
||||
//将RetResult对象以JSON格式输出
|
||||
public void finishJson(final JsonConvert convert, final org.redkale.service.RetResult ret);
|
||||
|
||||
//将CompletableFuture的结果对象以JSON格式输出
|
||||
public void finishJson(final CompletableFuture future);
|
||||
|
||||
//将CompletableFuture的结果对象以JSON格式输出
|
||||
public void finishJson(final JsonConvert convert, final CompletableFuture future);
|
||||
|
||||
//将CompletableFuture的结果对象以JSON格式输出
|
||||
public void finishJson(final JsonConvert convert, final Type type, final CompletableFuture future);
|
||||
|
||||
//将指定字符串以响应结果输出
|
||||
public void finish(String obj);
|
||||
|
||||
|
||||
@@ -87,7 +87,7 @@ public class HelloService implements Service {
|
||||
//异步查询单个
|
||||
@RestMapping(name = "asyncfind")
|
||||
public void findHello(AsyncHandler handler, @RestParam(name = "#") int id) { //通过 /pipes/hello/find/1234、/pipes/hello/jsfind/1234 查询对象
|
||||
if (source != null) source.find(handler, HelloEntity.class, id);
|
||||
if (source != null) source.findAsync(handler, HelloEntity.class, id);
|
||||
HelloEntity rs = new HelloEntity();
|
||||
rs.setHelloname("Hello名称");
|
||||
if (handler != null) handler.completed(rs, null);
|
||||
|
||||
@@ -41,29 +41,29 @@ public class ABMainService implements Service {
|
||||
factory.register(JsonConvert.root());
|
||||
factory.register(BsonConvert.root());
|
||||
//------------------------ 初始化 CService ------------------------------------
|
||||
CService cservice = Sncp.createLocalService("", null, ResourceFactory.root(), CService.class, new InetSocketAddress("127.0.0.1", 5577), null, null);
|
||||
CService cservice = Sncp.createLocalService("", null, ResourceFactory.root(), CService.class, new InetSocketAddress("127.0.0.1", 5577), "", new HashSet<>(), (AnyValue) null, null, null);
|
||||
SncpServer cserver = new SncpServer();
|
||||
cserver.getLogger().setLevel(Level.WARNING);
|
||||
cserver.addSncpServlet(new ServiceWrapper(cservice, "", "", new HashSet<>(), null));
|
||||
cserver.addSncpServlet(cservice);
|
||||
cserver.init(DefaultAnyValue.create("port", 5577));
|
||||
cserver.start();
|
||||
|
||||
//------------------------ 初始化 BCService ------------------------------------
|
||||
final Transport bctransport = new Transport("", WatchFactory.root(), "", newBufferPool(), newChannelGroup(), null, Utility.ofSet(new InetSocketAddress("127.0.0.1", 5577)));
|
||||
BCService bcservice = Sncp.createLocalService("", null, ResourceFactory.root(), BCService.class, new InetSocketAddress("127.0.0.1", 5588), bctransport, null);
|
||||
CService remoteCService = Sncp.createRemoteService("", null, CService.class, new InetSocketAddress("127.0.0.1", 5588), bctransport);
|
||||
BCService bcservice = Sncp.createLocalService("", null, ResourceFactory.root(), BCService.class, new InetSocketAddress("127.0.0.1", 5588), "", new HashSet<>(), (AnyValue) null, bctransport, null);
|
||||
CService remoteCService = Sncp.createRemoteService("", null, CService.class, new InetSocketAddress("127.0.0.1", 5588), "", new HashSet<>(), (AnyValue) null, bctransport);
|
||||
factory.inject(remoteCService);
|
||||
factory.register("", remoteCService);
|
||||
SncpServer bcserver = new SncpServer();
|
||||
bcserver.getLogger().setLevel(Level.WARNING);
|
||||
bcserver.addSncpServlet(new ServiceWrapper(bcservice, "", "", new HashSet<>(), null));
|
||||
bcserver.addSncpServlet(bcservice);
|
||||
bcserver.init(DefaultAnyValue.create("port", 5588));
|
||||
bcserver.start();
|
||||
|
||||
//------------------------ 初始化 ABMainService ------------------------------------
|
||||
final Transport abtransport = new Transport("", WatchFactory.root(), "", newBufferPool(), newChannelGroup(), null, Utility.ofSet(new InetSocketAddress("127.0.0.1", 5588)));
|
||||
ABMainService service = Sncp.createLocalService("", null, ResourceFactory.root(), ABMainService.class, new InetSocketAddress("127.0.0.1", 5599), bctransport, null);
|
||||
BCService remoteBCService = Sncp.createRemoteService("", null, BCService.class, new InetSocketAddress("127.0.0.1", 5599), abtransport);
|
||||
ABMainService service = Sncp.createLocalService("", null, ResourceFactory.root(), ABMainService.class, new InetSocketAddress("127.0.0.1", 5599), "", new HashSet<>(), (AnyValue) null, bctransport, null);
|
||||
BCService remoteBCService = Sncp.createRemoteService("", null, BCService.class, new InetSocketAddress("127.0.0.1", 5599), "", new HashSet<>(), (AnyValue) null, abtransport);
|
||||
factory.inject(remoteBCService);
|
||||
factory.register("", remoteBCService);
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
*/
|
||||
package org.redkale.test.service;
|
||||
|
||||
import java.util.HashSet;
|
||||
import org.redkale.net.sncp.*;
|
||||
import org.redkale.service.Service;
|
||||
import org.redkale.util.*;
|
||||
@@ -26,7 +25,7 @@ public class TestService implements Service {
|
||||
|
||||
public static void main(String[] args) throws Throwable {
|
||||
SncpServer cserver = new SncpServer();
|
||||
cserver.addSncpServlet(new ServiceWrapper(new TestService(), "", "", new HashSet<>(), null));
|
||||
cserver.addSncpServlet(new TestService());
|
||||
cserver.init(AnyValue.DefaultAnyValue.create("port", 5577));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ public class SncpTest {
|
||||
if (port2 > 0) set.add(new InetSocketAddress(myhost, port2));
|
||||
//String name, WatchFactory, ObjectPool<ByteBuffer>, AsynchronousChannelGroup, InetSocketAddress clientAddress, Collection<InetSocketAddress>
|
||||
final Transport transport = new Transport("", WatchFactory.root(), "", newBufferPool(), newChannelGroup(), null, set);
|
||||
final SncpTestService service = Sncp.createRemoteService(serviceName, null, SncpTestService.class, null, transport);
|
||||
final SncpTestIService service = Sncp.createSimpleRemoteService(serviceName, SncpTestIService.class, addr, transport);
|
||||
ResourceFactory.root().inject(service);
|
||||
|
||||
// SncpTestBean bean = new SncpTestBean();
|
||||
@@ -132,6 +132,13 @@ public class SncpTest {
|
||||
}.start();
|
||||
}
|
||||
cld.await();
|
||||
final CountDownLatch cld2 = new CountDownLatch(1);
|
||||
final CompletableFuture<String> future = service.queryResultAsync(callbean);
|
||||
future.whenComplete((v, e) -> {
|
||||
cld2.countDown();
|
||||
System.out.println("异步执行完毕: " + v + ", 异常为: " + e);
|
||||
});
|
||||
cld2.await();
|
||||
System.out.println("---全部运行完毕---");
|
||||
System.exit(0);
|
||||
}
|
||||
@@ -152,9 +159,9 @@ public class SncpTest {
|
||||
if (port2 > 0) set.add(new InetSocketAddress(myhost, port2));
|
||||
//String name, WatchFactory, ObjectPool<ByteBuffer>, AsynchronousChannelGroup, InetSocketAddress clientAddress, Collection<InetSocketAddress>
|
||||
final Transport transport = new Transport("", WatchFactory.root(), "", newBufferPool(), newChannelGroup(), null, set);
|
||||
SncpTestService service = Sncp.createLocalService("", null, ResourceFactory.root(), SncpTestService.class, addr, transport, null);
|
||||
SncpTestIService service = Sncp.createSimpleLocalService("", SncpTestServiceImpl.class, addr, transport);
|
||||
ResourceFactory.root().inject(service);
|
||||
server.addSncpServlet(new ServiceWrapper(service, "", "", new HashSet<>(), null));
|
||||
server.addSncpServlet(service);
|
||||
System.out.println(service);
|
||||
AnyValue.DefaultAnyValue conf = new AnyValue.DefaultAnyValue();
|
||||
conf.addValue("host", "0.0.0.0");
|
||||
@@ -186,8 +193,8 @@ public class SncpTest {
|
||||
set.add(new InetSocketAddress(myhost, port));
|
||||
//String name, WatchFactory, ObjectPool<ByteBuffer>, AsynchronousChannelGroup, InetSocketAddress clientAddress, Collection<InetSocketAddress>
|
||||
final Transport transport = new Transport("", WatchFactory.root(), "", newBufferPool(), newChannelGroup(), null, set);
|
||||
Service service = Sncp.createLocalService("", null, ResourceFactory.root(), SncpTestService.class, addr, transport, null);
|
||||
server.addSncpServlet(new ServiceWrapper(service, "", "", new HashSet<>(), null));
|
||||
Service service = Sncp.createSimpleLocalService("", SncpTestServiceImpl.class, addr, transport);
|
||||
server.addSncpServlet(service);
|
||||
AnyValue.DefaultAnyValue conf = new AnyValue.DefaultAnyValue();
|
||||
conf.addValue("host", "0.0.0.0");
|
||||
conf.addValue("port", "" + port2);
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
*/
|
||||
package org.redkale.test.sncp;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import org.redkale.service.*;
|
||||
import org.redkale.source.DataCallArrayAttribute;
|
||||
|
||||
@@ -16,7 +17,9 @@ public interface SncpTestIService extends Service {
|
||||
|
||||
public String queryResult(SncpTestBean bean);
|
||||
|
||||
public CompletableFuture<String> queryResultAsync(SncpTestBean bean);
|
||||
|
||||
public void insert(@RpcCall(DataCallArrayAttribute.class) SncpTestBean... beans);
|
||||
|
||||
public String updateBean(@RpcCall(SncpTestService.CallAttribute.class) SncpTestBean bean);
|
||||
public String updateBean(@RpcCall(SncpTestServiceImpl.CallAttribute.class) SncpTestBean bean);
|
||||
}
|
||||
|
||||
@@ -7,6 +7,8 @@ package org.redkale.test.sncp;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.HashSet;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import org.redkale.net.sncp.*;
|
||||
import org.redkale.service.*;
|
||||
import org.redkale.source.DataCallArrayAttribute;
|
||||
@@ -16,8 +18,27 @@ import org.redkale.util.*;
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
@ResourceType({SncpTestIService.class, SncpTestService.class})
|
||||
public class SncpTestService implements SncpTestIService {
|
||||
@ResourceType({SncpTestIService.class})
|
||||
public class SncpTestServiceImpl implements SncpTestIService {
|
||||
|
||||
@Override
|
||||
public CompletableFuture<String> queryResultAsync(SncpTestBean bean) {
|
||||
final CompletableFuture<String> future = new CompletableFuture<>();
|
||||
new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
System.out.println(Thread.currentThread().getName() + " 运行了异步方法-----------queryResultAsync方法");
|
||||
future.complete("异步result: " + bean);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
return future;
|
||||
|
||||
}
|
||||
|
||||
public static class CallAttribute implements Attribute<SncpTestBean, Long> {
|
||||
|
||||
@@ -50,12 +71,14 @@ public class SncpTestService implements SncpTestIService {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void insert(@RpcCall(DataCallArrayAttribute.class) SncpTestBean... beans) {
|
||||
for (SncpTestBean bean : beans) {
|
||||
bean.setId(System.currentTimeMillis());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String queryResult(SncpTestBean bean) {
|
||||
System.out.println(Thread.currentThread().getName() + " 运行了queryResult方法");
|
||||
return "result: " + bean;
|
||||
@@ -67,6 +90,7 @@ public class SncpTestService implements SncpTestIService {
|
||||
}
|
||||
|
||||
@RpcMultiRun
|
||||
@Override
|
||||
public String updateBean(@RpcCall(CallAttribute.class) SncpTestBean bean) {
|
||||
bean.setId(System.currentTimeMillis());
|
||||
System.out.println(Thread.currentThread().getName() + " 运行了updateBean方法");
|
||||
@@ -74,7 +98,7 @@ public class SncpTestService implements SncpTestIService {
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
Service service = Sncp.createLocalService("", null, ResourceFactory.root(), SncpTestService.class, new InetSocketAddress("127.0.0.1", 7070), null, null);
|
||||
Service service = Sncp.createLocalService("", null, ResourceFactory.root(), SncpTestServiceImpl.class, new InetSocketAddress("127.0.0.1", 7070), "", new HashSet<>(), (AnyValue) null, null, null);
|
||||
for (Method method : service.getClass().getDeclaredMethods()) {
|
||||
System.out.println(method);
|
||||
}
|
||||
@@ -83,7 +107,7 @@ public class SncpTestService implements SncpTestIService {
|
||||
System.out.println(method);
|
||||
}
|
||||
System.out.println("-----------------------------------");
|
||||
service = Sncp.createRemoteService("", null, SncpTestService.class, new InetSocketAddress("127.0.0.1", 7070), null);
|
||||
service = Sncp.createSimpleRemoteService("", SncpTestServiceImpl.class, new InetSocketAddress("127.0.0.1", 7070), null);
|
||||
for (Method method : service.getClass().getDeclaredMethods()) {
|
||||
System.out.println(method);
|
||||
}
|
||||
@@ -92,7 +116,7 @@ public class SncpTestService implements SncpTestIService {
|
||||
System.out.println(method);
|
||||
}
|
||||
System.out.println("-----------------------------------");
|
||||
service = Sncp.createRemoteService("", null, SncpTestIService.class, new InetSocketAddress("127.0.0.1", 7070), null);
|
||||
service = Sncp.createSimpleRemoteService("", SncpTestIService.class, new InetSocketAddress("127.0.0.1", 7070), null);
|
||||
for (Method method : service.getClass().getDeclaredMethods()) {
|
||||
System.out.println(method);
|
||||
}
|
||||
@@ -5,7 +5,10 @@
|
||||
*/
|
||||
package org.redkale.test.source;
|
||||
|
||||
import org.redkale.source.FilterBean;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.*;
|
||||
import java.util.function.BiFunction;
|
||||
import org.redkale.source.*;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -14,7 +17,25 @@ import org.redkale.source.FilterBean;
|
||||
public class LoginTestBean implements FilterBean {
|
||||
|
||||
private String sessionid;
|
||||
|
||||
|
||||
private int sid;
|
||||
public static void main(String[] args) throws Throwable {
|
||||
LoginTestBean bean = new LoginTestBean();
|
||||
bean.setSessionid("xxx");
|
||||
bean.setSid(23333);
|
||||
BiFunction<DataSource, Class, List> fullloader = (s, z) -> new ArrayList();
|
||||
Method method = EntityInfo.class.getDeclaredMethod("load", Class.class, boolean.class, Properties.class,
|
||||
DataSource.class, BiFunction.class);
|
||||
method.setAccessible(true);
|
||||
final EntityInfo<CacheTestBean> info = (EntityInfo<CacheTestBean>) method.invoke(null, CacheTestBean.class, true, new Properties(), null, fullloader);
|
||||
EntityCache<CacheTestBean> cache = new EntityCache(info, null);
|
||||
FilterNode node = FilterNodeBean.createFilterNode(bean);
|
||||
System.out.println("cache = " + cache + ", node = " + node);
|
||||
Method pre = FilterNode.class.getDeclaredMethod("createPredicate", EntityCache.class);
|
||||
pre.setAccessible(true);
|
||||
//为null是因为CacheTestBean 没有sid和sessionid这两个字段
|
||||
System.out.println(pre.invoke(node,cache));
|
||||
}
|
||||
public String getSessionid() {
|
||||
return sessionid;
|
||||
}
|
||||
@@ -23,4 +44,12 @@ public class LoginTestBean implements FilterBean {
|
||||
this.sessionid = sessionid;
|
||||
}
|
||||
|
||||
public int getSid() {
|
||||
return sid;
|
||||
}
|
||||
|
||||
public void setSid(int sid) {
|
||||
this.sid = sid;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user