This commit is contained in:
@@ -63,10 +63,10 @@
|
||||
<!--
|
||||
全局的数据源设置, 可以是CacheSource、DataSource, JDBC的DataSource通常通过persistence.xml配置,此处多用于CacheSource的配置
|
||||
name: 资源名,用于依赖注入。
|
||||
type:类名,必须是CacheSource或DataSource的子类,且必须实现Service接口。
|
||||
value:类名,必须是CacheSource或DataSource的子类,且必须实现Service接口。
|
||||
xxx: 其他属性与子节点通过Service.init方法传入的AnyValue获取。
|
||||
-->
|
||||
<source name="redis" type="org.redkalex.cache.RedisCacheSource" xxx="16">
|
||||
<source name="redis" value="org.redkalex.cache.RedisCacheSource" xxx="16">
|
||||
<node addr="127.0.0.1" port="7070"/>
|
||||
</source>
|
||||
|
||||
@@ -144,20 +144,46 @@
|
||||
</service>
|
||||
</services>
|
||||
|
||||
<!--
|
||||
加载所有的Filter服务;
|
||||
autoload="true" 默认值.
|
||||
autoload="false" 需要显著的指定Filter类
|
||||
includes: 当autoload="true", 拉取类名与includes中的正则表达式匹配的类, 多个正则表达式用分号;隔开
|
||||
excludes: 当autoload="true", 排除类名与excludes中的正则表达式匹配的类, 多个正则表达式用分号;隔开
|
||||
-->
|
||||
<filters autoload="true" includes="" excludes="">
|
||||
|
||||
<!-- 显著加载指定的Filter类 -->
|
||||
<filter value="com.xxx.XXX1Filter"/>
|
||||
|
||||
<!-- 给Filter增加配置属性 -->
|
||||
<filter value="com.xxx.XXX12Filter">
|
||||
<!-- property节点值在 public void init(AnyValue conf) 方法中可以通过 AnyValue properties = conf.getAnyValue("properties");获取 -->
|
||||
<property name="xxxxxx" value="XXXXXXXX"/>
|
||||
<property name="xxxxxx" value="XXXXXXXX"/>
|
||||
</filter>
|
||||
</filters>
|
||||
|
||||
<!--
|
||||
REST的核心配置项
|
||||
当Server为HTTP协议时, rest节点才有效。存在[rest]节点则Server启动时会加载REST服务, 节点可以多个,(WATCH协议不需要设置,系统会自动生成)
|
||||
path: servlet的ContextPath前缀 默认为空
|
||||
base: REST服务的BaseServlet,必须是 org.redkale.net.http.HttpServlet 的子类,且子类必须标记@HttpUserType。
|
||||
autoload:默认值"true" 默认值. 加载当前server所能使用的Servce对象;
|
||||
includes:当autoload="true", 拉取类名与includes中的正则表达式匹配的类, 多个正则表达式用分号;隔开
|
||||
excludes:当autoload="true", 排除类名与excludes中的正则表达式匹配的类, 多个正则表达式用分号;隔开
|
||||
-->
|
||||
<rest base="org.redkale.net.http.HttpServlet" autoload="true" includes="" excludes="">
|
||||
<rest path="/pipes" base="org.redkale.net.http.HttpServlet" autoload="true" includes="" excludes="">
|
||||
<!--
|
||||
value: Service类名,列出的表示必须被加载的Service对象
|
||||
ignore: 是否忽略,设置为true则不会加载该Service对象,默认值为false
|
||||
-->
|
||||
<service value="com.xxx.XXXXService"/>
|
||||
<!--
|
||||
value: WebSocket类名,列出的表示必须被加载且标记为@RestWebSocket的WebSocket对象
|
||||
ignore: 是否忽略,设置为true则不会加载该RestWebSocket对象,默认值为false
|
||||
-->
|
||||
<websocket value="com.xxx.XXXXRestWebSocket"/>
|
||||
</rest>
|
||||
|
||||
<!--
|
||||
|
||||
@@ -66,6 +66,11 @@ public class NodeHttpServer extends NodeServer {
|
||||
return createClassFilter(null, WebServlet.class, HttpServlet.class, new Class[]{WatchServlet.class}, null, "servlets", "servlet");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ClassFilter createOtherClassFilter() {
|
||||
return createClassFilter(null, RestWebSocket.class, WebSocket.class, null, null, "rest", "websocket");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void loadService(ClassFilter serviceFilter) throws Exception {
|
||||
super.loadService(serviceFilter);
|
||||
@@ -74,12 +79,12 @@ public class NodeHttpServer extends NodeServer {
|
||||
|
||||
@Override
|
||||
protected void loadFilter(ClassFilter<? extends Filter> filterFilter) throws Exception {
|
||||
if (httpServer != null) loadHttpFilter(this.serverConf.getAnyValue("fliters"), filterFilter);
|
||||
if (httpServer != null) loadHttpFilter(this.serverConf.getAnyValue("filters"), filterFilter);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void loadServlet(ClassFilter<? extends Servlet> servletFilter) throws Exception {
|
||||
if (httpServer != null) loadHttpServlet(this.serverConf.getAnyValue("servlets"), servletFilter);
|
||||
protected void loadServlet(ClassFilter<? extends Servlet> servletFilter, ClassFilter otherFilter) throws Exception {
|
||||
if (httpServer != null) loadHttpServlet(servletFilter, otherFilter);
|
||||
}
|
||||
|
||||
private void initWebSocketService() {
|
||||
@@ -105,7 +110,7 @@ public class NodeHttpServer extends NodeServer {
|
||||
}, WebSocketNode.class);
|
||||
}
|
||||
|
||||
protected void loadHttpFilter(final AnyValue servletsConf, final ClassFilter<? extends Filter> classFilter) throws Exception {
|
||||
protected void loadHttpFilter(final AnyValue filtersConf, final ClassFilter<? extends Filter> classFilter) throws Exception {
|
||||
final StringBuilder sb = logger.isLoggable(Level.INFO) ? new StringBuilder() : null;
|
||||
final String threadName = "[" + Thread.currentThread().getName() + "] ";
|
||||
List<FilterEntry<? extends Filter>> list = new ArrayList(classFilter.getFilterEntrys());
|
||||
@@ -121,14 +126,15 @@ public class NodeHttpServer extends NodeServer {
|
||||
if (sb != null && sb.length() > 0) logger.log(Level.INFO, sb.toString());
|
||||
}
|
||||
|
||||
protected void loadHttpServlet(final AnyValue servletsConf, final ClassFilter<? extends Servlet> filter) throws Exception {
|
||||
protected void loadHttpServlet(final ClassFilter<? extends Servlet> servletFilter, ClassFilter<? extends WebSocket> webSocketFilter) throws Exception {
|
||||
final AnyValue servletsConf = this.serverConf.getAnyValue("servlets");
|
||||
final StringBuilder sb = logger.isLoggable(Level.INFO) ? new StringBuilder() : null;
|
||||
String prefix0 = servletsConf == null ? "" : servletsConf.getValue("path", "");
|
||||
if (!prefix0.isEmpty() && prefix0.charAt(prefix0.length() - 1) == '/') prefix0 = prefix0.substring(0, prefix0.length() - 1);
|
||||
if (!prefix0.isEmpty() && prefix0.charAt(0) != '/') prefix0 = '/' + prefix0;
|
||||
final String prefix = prefix0;
|
||||
final String threadName = "[" + Thread.currentThread().getName() + "] ";
|
||||
List<FilterEntry<? extends Servlet>> list = new ArrayList(filter.getFilterEntrys());
|
||||
List<FilterEntry<? extends Servlet>> list = new ArrayList(servletFilter.getFilterEntrys());
|
||||
list.sort((FilterEntry<? extends Servlet> o1, FilterEntry<? extends Servlet> o2) -> { //必须保证WebSocketServlet优先加载, 因为要确保其他的HttpServlet可以注入本地模式的WebSocketNode
|
||||
boolean ws1 = WebSocketServlet.class.isAssignableFrom(o1.getType());
|
||||
boolean ws2 = WebSocketServlet.class.isAssignableFrom(o2.getType());
|
||||
@@ -169,61 +175,115 @@ public class NodeHttpServer extends NodeServer {
|
||||
}
|
||||
}
|
||||
if (rest && serverConf != null) {
|
||||
final List<Object> restedObjects = new ArrayList<>();
|
||||
for (AnyValue restConf : serverConf.getAnyValues("rest")) {
|
||||
loadRestServlet(prefix, restConf, sb);
|
||||
loadRestServlet(webSocketFilter, restConf, restedObjects, sb);
|
||||
}
|
||||
}
|
||||
if (sb != null && sb.length() > 0) logger.log(Level.INFO, sb.toString());
|
||||
if (sb != null && sb.length() > 0) logger.log(Level.INFO, sb.toString().trim());
|
||||
}
|
||||
|
||||
protected void loadRestServlet(final String prefix, final AnyValue restConf, final StringBuilder sb) throws Exception {
|
||||
protected void loadRestServlet(final ClassFilter<? extends WebSocket> webSocketFilter, final AnyValue restConf, final List<Object> restedObjects, final StringBuilder sb) throws Exception {
|
||||
if (!rest) return;
|
||||
if (restConf == null) return; //不存在REST服务
|
||||
|
||||
String prefix0 = restConf.getValue("path", "");
|
||||
if (!prefix0.isEmpty() && prefix0.charAt(prefix0.length() - 1) == '/') prefix0 = prefix0.substring(0, prefix0.length() - 1);
|
||||
if (!prefix0.isEmpty() && prefix0.charAt(0) != '/') prefix0 = '/' + prefix0;
|
||||
final String prefix = prefix0;
|
||||
|
||||
final String threadName = "[" + Thread.currentThread().getName() + "] ";
|
||||
final List<AbstractMap.SimpleEntry<String, String[]>> ss = sb == null ? null : new ArrayList<>();
|
||||
|
||||
String userTypeStr = restConf.getValue("usertype");
|
||||
final Class userType = userTypeStr == null ? null : Class.forName(userTypeStr);
|
||||
final Class baseServletType = Class.forName(restConf.getValue("base", HttpServlet.class.getName()));
|
||||
|
||||
final boolean autoload = restConf.getBoolValue("autoload", true);
|
||||
{ //加载RestService
|
||||
String userTypeStr = restConf.getValue("usertype");
|
||||
final Class userType = userTypeStr == null ? null : Class.forName(userTypeStr);
|
||||
final Class baseServletType = Class.forName(restConf.getValue("base", HttpServlet.class.getName()));
|
||||
final Set<String> includeValues = new HashSet<>();
|
||||
final Set<String> excludeValues = new HashSet<>();
|
||||
for (AnyValue item : restConf.getAnyValues("service")) {
|
||||
if (item.getBoolValue("ignore", false)) {
|
||||
excludeValues.add(item.getValue("value", ""));
|
||||
} else {
|
||||
includeValues.add(item.getValue("value", ""));
|
||||
}
|
||||
}
|
||||
|
||||
final Set<String> includeValues = new HashSet<>();
|
||||
final Set<String> excludeValues = new HashSet<>();
|
||||
for (AnyValue item : restConf.getAnyValues("service")) {
|
||||
if (item.getBoolValue("ignore", false)) {
|
||||
excludeValues.add(item.getValue("value", ""));
|
||||
} else {
|
||||
includeValues.add(item.getValue("value", ""));
|
||||
final ClassFilter restFilter = ClassFilter.create(null, restConf.getValue("includes", ""), restConf.getValue("excludes", ""), includeValues, excludeValues);
|
||||
final boolean finest = logger.isLoggable(Level.FINEST);
|
||||
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;
|
||||
|
||||
final String stypename = stype.getName();
|
||||
if (!autoload && !includeValues.contains(stypename)) return;
|
||||
if (!restFilter.accept(stypename)) return;
|
||||
if (restedObjects.contains(service)) {
|
||||
logger.log(Level.WARNING, stype.getName() + " repeat create rest servlet, so ignore");
|
||||
return;
|
||||
}
|
||||
restedObjects.add(service); //避免重复创建Rest对象
|
||||
HttpServlet servlet = httpServer.addRestServlet(name, stype, service, userType, baseServletType, prefix, (AnyValue) null);
|
||||
if (servlet == null) return; //没有HttpMapping方法的HttpServlet调用Rest.createRestServlet就会返回null
|
||||
resourceFactory.inject(servlet, NodeHttpServer.this);
|
||||
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];
|
||||
}
|
||||
ss.add(new AbstractMap.SimpleEntry<>(servlet.getClass().getName(), mappings));
|
||||
}
|
||||
});
|
||||
}
|
||||
if (webSocketFilter != null) { //加载RestWebSocket
|
||||
final Set<String> includeValues = new HashSet<>();
|
||||
final Set<String> excludeValues = new HashSet<>();
|
||||
for (AnyValue item : restConf.getAnyValues("websocket")) {
|
||||
if (item.getBoolValue("ignore", false)) {
|
||||
excludeValues.add(item.getValue("value", ""));
|
||||
} else {
|
||||
includeValues.add(item.getValue("value", ""));
|
||||
}
|
||||
}
|
||||
|
||||
final ClassFilter restFilter = ClassFilter.create(null, restConf.getValue("includes", ""), restConf.getValue("excludes", ""), includeValues, excludeValues);
|
||||
final boolean finest = logger.isLoggable(Level.FINEST);
|
||||
|
||||
List<FilterEntry<? extends WebSocket>> list = new ArrayList(webSocketFilter.getFilterEntrys());
|
||||
for (FilterEntry<? extends WebSocket> en : list) {
|
||||
Class<WebSocket> clazz = (Class<WebSocket>) en.getType();
|
||||
if (Modifier.isAbstract(clazz.getModifiers())) continue;
|
||||
final Class<? extends WebSocket> stype = en.getType();
|
||||
RestWebSocket rs = stype.getAnnotation(RestWebSocket.class);
|
||||
if (rs == null || rs.ignore()) return;
|
||||
|
||||
final String stypename = stype.getName();
|
||||
if (!autoload && !includeValues.contains(stypename)) return;
|
||||
if (!restFilter.accept(stypename)) return;
|
||||
if (restedObjects.contains(stype)) {
|
||||
logger.log(Level.WARNING, stype.getName() + " repeat create rest websocket, so ignore");
|
||||
return;
|
||||
}
|
||||
restedObjects.add(stype); //避免重复创建Rest对象
|
||||
HttpServlet servlet = httpServer.addRestWebSocketServlet(stype, prefix, en.getProperty());
|
||||
if (servlet == null) return; //没有RestOnMessage方法的HttpServlet调用Rest.createRestWebSocketServlet就会返回null
|
||||
resourceFactory.inject(servlet, NodeHttpServer.this);
|
||||
if (finest) logger.finest(threadName + " " + stype.getName() + " create RestWebSocketServlet " + 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];
|
||||
}
|
||||
ss.add(new AbstractMap.SimpleEntry<>(servlet.getClass().getName(), mappings));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final ClassFilter restFilter = ClassFilter.create(null, restConf.getValue("includes", ""), restConf.getValue("excludes", ""), includeValues, excludeValues);
|
||||
final boolean finest = logger.isLoggable(Level.FINEST);
|
||||
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;
|
||||
|
||||
final String stypename = stype.getName();
|
||||
if (!autoload && !includeValues.contains(stypename)) return;
|
||||
if (!restFilter.accept(stypename)) return;
|
||||
|
||||
HttpServlet servlet = httpServer.addRestServlet(name, stype, service, userType, baseServletType, prefix, (AnyValue) null);
|
||||
if (servlet == null) return; //没有HttpMapping方法的HttpServlet调用Rest.createRestServlet就会返回null
|
||||
resourceFactory.inject(servlet, NodeHttpServer.this);
|
||||
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];
|
||||
}
|
||||
ss.add(new AbstractMap.SimpleEntry<>(servlet.getClass().getName(), mappings));
|
||||
}
|
||||
});
|
||||
//输出信息
|
||||
if (ss != null && sb != null) {
|
||||
if (ss != null && !ss.isEmpty() && 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) {
|
||||
|
||||
@@ -165,20 +165,21 @@ public abstract class NodeServer {
|
||||
ClassFilter<Service> serviceFilter = createServiceClassFilter();
|
||||
ClassFilter<Filter> filterFilter = createFilterClassFilter();
|
||||
ClassFilter<Servlet> servletFilter = createServletClassFilter();
|
||||
ClassFilter otherFilter = createOtherClassFilter();
|
||||
long s = System.currentTimeMillis();
|
||||
ClassFilter.Loader.load(application.getHome(), serverConf.getValue("excludelibs", "").split(";"), serviceFilter, filterFilter, servletFilter);
|
||||
ClassFilter.Loader.load(application.getHome(), serverConf.getValue("excludelibs", "").split(";"), serviceFilter, filterFilter, servletFilter, otherFilter);
|
||||
long e = System.currentTimeMillis() - s;
|
||||
logger.info(this.getClass().getSimpleName() + " load filter class in " + e + " ms");
|
||||
loadService(serviceFilter); //必须在servlet之前
|
||||
loadFilter(filterFilter);
|
||||
loadServlet(servletFilter);
|
||||
loadServlet(servletFilter, otherFilter);
|
||||
|
||||
if (this.interceptor != null) this.resourceFactory.inject(this.interceptor);
|
||||
}
|
||||
|
||||
protected abstract void loadFilter(ClassFilter<? extends Filter> filterFilter) throws Exception;
|
||||
|
||||
protected abstract void loadServlet(ClassFilter<? extends Servlet> servletFilter) throws Exception;
|
||||
protected abstract void loadServlet(ClassFilter<? extends Servlet> servletFilter, ClassFilter otherFilter) throws Exception;
|
||||
|
||||
private void initResource() {
|
||||
final NodeServer self = this;
|
||||
@@ -190,7 +191,7 @@ public abstract class NodeServer {
|
||||
if (resources != null) {
|
||||
for (AnyValue sourceConf : resources.getAnyValues("source")) {
|
||||
try {
|
||||
Class type = Class.forName(sourceConf.getValue("type"));
|
||||
Class type = Class.forName(sourceConf.getValue("value"));
|
||||
if (!Service.class.isAssignableFrom(type)) {
|
||||
logger.log(Level.SEVERE, "load application source resource, but not Service error: " + sourceConf);
|
||||
} else if (CacheSource.class.isAssignableFrom(type)) {
|
||||
@@ -510,6 +511,10 @@ public abstract class NodeServer {
|
||||
|
||||
protected abstract ClassFilter<Servlet> createServletClassFilter();
|
||||
|
||||
protected ClassFilter createOtherClassFilter() {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected ClassFilter<Service> createServiceClassFilter() {
|
||||
return createClassFilter(this.sncpGroup, null, Service.class, null, Annotation.class, "services", "service");
|
||||
}
|
||||
@@ -544,19 +549,19 @@ public abstract class NodeServer {
|
||||
prop.addValue("groups", sc);
|
||||
}
|
||||
ClassFilter filter = new ClassFilter(ref, inter, excludeSuperClasses, prop);
|
||||
for (AnyValue av : list.getAnyValues(property)) { // <service> 或 <servlet> 节点
|
||||
for (AnyValue av : list.getAnyValues(property)) { // <service>、<filter>、<servlet> 节点
|
||||
final AnyValue[] items = av.getAnyValues("property");
|
||||
if (av instanceof DefaultAnyValue && items.length > 0) { //存在 <property>节点
|
||||
DefaultAnyValue dav = DefaultAnyValue.create();
|
||||
final AnyValue.Entry<String>[] strings = av.getStringEntrys();
|
||||
if (strings != null) { //将<service>或<servlet>节点的属性值传给dav
|
||||
if (strings != null) { //将<service>、<filter>、<servlet>节点的属性值传给dav
|
||||
for (AnyValue.Entry<String> en : strings) {
|
||||
dav.addValue(en.name, en.getValue());
|
||||
}
|
||||
}
|
||||
final AnyValue.Entry<AnyValue>[] anys = av.getAnyEntrys();
|
||||
if (anys != null) {
|
||||
for (AnyValue.Entry<AnyValue> en : anys) { //将<service>或<servlet>节点的非property属性节点传给dav
|
||||
for (AnyValue.Entry<AnyValue> en : anys) { //将<service>、<filter>、<servlet>节点的非property属性节点传给dav
|
||||
if (!"property".equals(en.name)) dav.addValue(en.name, en.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,7 +102,7 @@ public class NodeSncpServer extends NodeServer {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void loadServlet(ClassFilter<? extends Servlet> servletFilter) throws Exception {
|
||||
protected void loadServlet(ClassFilter<? extends Servlet> servletFilter, ClassFilter otherFilter) throws Exception {
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user