This commit is contained in:
Redkale
2017-05-23 23:14:30 +08:00
parent 804e0e27e7
commit 713fdefb56
4 changed files with 148 additions and 57 deletions

View File

@@ -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>
<!--

View File

@@ -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) {

View File

@@ -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());
}
}

View File

@@ -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