This commit is contained in:
Redkale
2018-01-29 21:26:35 +08:00
parent 9f4f459ea8
commit a71f1a17dd
8 changed files with 78 additions and 72 deletions

View File

@@ -233,11 +233,11 @@
</response> </response>
<!-- <!--
【节点在<server>中唯一】 【节点在<server>中唯一】
当Server为HTTP协议时template-engine才有效. 指定模板引擎的实现类, 没有配置则无法使用HttpTemplate功能 当Server为HTTP协议时render才有效. 指定输出引擎的实现类
value: 模板引擎的实现类, 必须是org.redkale.net.http.HttpTemplateEngine的子类 value: 输出引擎的实现类, 必须是org.redkale.net.http.HttpRender的子类
--> -->
<template-engine value="org.redkalex.htel.XXXHttpTemplateEngine"> <render value="org.redkalex.htel.HttpTemplateRender">
</template-engine> </render>
<!-- <!--
【节点在<server>中唯一】 【节点在<server>中唯一】
当Server为HTTP协议时ResourceServlet才有效. 默认存在一个有默认属性的resource-servlet节点 当Server为HTTP协议时ResourceServlet才有效. 默认存在一个有默认属性的resource-servlet节点

View File

@@ -205,8 +205,10 @@ public class NodeHttpServer extends NodeServer {
loadRestServlet(webSocketFilter, restConf, restedObjects, sb); loadRestServlet(webSocketFilter, restConf, restedObjects, sb);
} }
} }
resourceFactory.inject(this.httpServer.getTemplateEngine(), this);
resourceFactory.inject(this.httpServer.getPrepareServlet(), this); resourceFactory.inject(this.httpServer.getPrepareServlet(), this);
for (HttpRender render : this.httpServer.getHttpRenders()) {
resourceFactory.inject(render, this);
}
if (sb != null && sb.length() > 0) logger.log(Level.INFO, sb.toString().trim()); if (sb != null && sb.length() > 0) logger.log(Level.INFO, sb.toString().trim());
} }

View File

@@ -31,8 +31,6 @@ public class HttpContext extends Context {
protected final ConcurrentHashMap<Class, Creator> asyncHandlerCreators = new ConcurrentHashMap<>(); protected final ConcurrentHashMap<Class, Creator> asyncHandlerCreators = new ConcurrentHashMap<>();
protected HttpTemplateEngine templateEngine;
public HttpContext(long serverStartTime, Logger logger, ThreadPoolExecutor executor, int bufferCapacity, ObjectPool<ByteBuffer> bufferPool, public HttpContext(long serverStartTime, Logger logger, ThreadPoolExecutor executor, int bufferCapacity, ObjectPool<ByteBuffer> bufferPool,
ObjectPool<Response> responsePool, int maxbody, Charset charset, InetSocketAddress address, PrepareServlet prepare, ObjectPool<Response> responsePool, int maxbody, Charset charset, InetSocketAddress address, PrepareServlet prepare,
int readTimeoutSecond, int writeTimeoutSecond) { int readTimeoutSecond, int writeTimeoutSecond) {
@@ -42,14 +40,6 @@ public class HttpContext extends Context {
random.setSeed(Math.abs(System.nanoTime())); random.setSeed(Math.abs(System.nanoTime()));
} }
protected void setTemplateEngine(HttpTemplateEngine engine) {
this.templateEngine = engine;
}
public HttpTemplateEngine getTemplateEngine() {
return templateEngine;
}
protected String createSessionid() { protected String createSessionid() {
byte[] bytes = new byte[16]; byte[] bytes = new byte[16];
random.nextBytes(bytes); random.nextBytes(bytes);

View File

@@ -31,8 +31,6 @@ public class HttpPrepareServlet extends PrepareServlet<String, HttpContext, Http
protected HttpServlet resourceHttpServlet = new HttpResourceServlet(); protected HttpServlet resourceHttpServlet = new HttpResourceServlet();
protected HttpTemplateEngine templateEngine = null;
protected MappingEntry[] regArray = null; //regArray 包含 regWsArray protected MappingEntry[] regArray = null; //regArray 包含 regWsArray
protected MappingEntry[] regWsArray = null; protected MappingEntry[] regWsArray = null;
@@ -47,6 +45,8 @@ public class HttpPrepareServlet extends PrepareServlet<String, HttpContext, Http
private BiPredicate<String, String>[] forbidURIPredicates; //禁用的URL的Predicate, 必须与 forbidURIMaps 保持一致 private BiPredicate<String, String>[] forbidURIPredicates; //禁用的URL的Predicate, 必须与 forbidURIMaps 保持一致
final List<HttpRender> renders = new ArrayList<>();
private List<HttpServlet> removeHttpServlet(final Predicate<MappingEntry> predicateEntry, final Predicate<Map.Entry<String, WebSocketServlet>> predicateFilter) { private List<HttpServlet> removeHttpServlet(final Predicate<MappingEntry> predicateEntry, final Predicate<Map.Entry<String, WebSocketServlet>> predicateFilter) {
List<HttpServlet> servlets = new ArrayList<>(); List<HttpServlet> servlets = new ArrayList<>();
synchronized (allMapStrings) { synchronized (allMapStrings) {
@@ -233,18 +233,22 @@ public class HttpPrepareServlet extends PrepareServlet<String, HttpContext, Http
this.resourceHttpServlet.init(context, resConfig); this.resourceHttpServlet.init(context, resConfig);
} }
{ //设置TemplateEngine { //设置TemplateEngine
AnyValue engineConfig = config.getAnyValue("template-engine"); AnyValue[] renderConfigs = config.getAnyValues("render");
if (engineConfig != null) { if (renderConfigs != null) {
String engineType = engineConfig.getValue("value"); for (AnyValue renderConfig : renderConfigs) {
try { String renderType = renderConfig.getValue("value");
this.templateEngine = (HttpTemplateEngine) Thread.currentThread().getContextClassLoader().loadClass(engineType).newInstance(); try {
this.templateEngine.init(context, engineConfig); HttpRender render = (HttpRender) Thread.currentThread().getContextClassLoader().loadClass(renderType).newInstance();
} catch (Throwable e) { for (HttpRender one : renders) {
logger.log(Level.WARNING, "init HttpTemplateEngine(" + engineType + ") error", e); if (one.getType().equals(render.getType())) throw new RuntimeException("HttpRender(" + renderType + ") repeat");
}
renders.add(render);
} catch (Throwable e) {
logger.log(Level.WARNING, "init HttpRender(" + renderType + ") error", e);
}
} }
Collections.sort(renders, (o1, o2) -> o1.getType().isAssignableFrom(o2.getType()) ? 1 : -1);
} }
//设置给Context
context.setTemplateEngine(this.templateEngine);
} }
} }
@@ -391,14 +395,6 @@ public class HttpPrepareServlet extends PrepareServlet<String, HttpContext, Http
return this.resourceHttpServlet; return this.resourceHttpServlet;
} }
public void setTemplateEngine(final HttpTemplateEngine engine) {
this.templateEngine = engine;
}
public HttpTemplateEngine getTemplateEngine() {
return this.templateEngine;
}
@Override @Override
public void destroy(HttpContext context, AnyValue config) { public void destroy(HttpContext context, AnyValue config) {
super.destroy(context, config); //必须要执行 super.destroy(context, config); //必须要执行

View File

@@ -8,17 +8,20 @@ package org.redkale.net.http;
import org.redkale.util.AnyValue; import org.redkale.util.AnyValue;
/** /**
* HTTP模板引擎的基类 * HTTP输出引擎的基类
* *
* <p> * <p>
* 详情见: https://redkale.org * 详情见: https://redkale.org
* *
* @author zhangjx * @author zhangjx
* @param <T> 泛型
*/ */
public interface HttpTemplateEngine { public interface HttpRender<T> {
default void init(HttpContext context, AnyValue config) { default void init(HttpContext context, AnyValue config) {
} }
public void renderTo(HttpRequest request, HttpResponse response, HttpScope scope); public <V extends T> void renderTo(HttpRequest request, HttpResponse response, V scope);
public Class<T> getType();
} }

View File

@@ -122,17 +122,26 @@ public class HttpResponse extends Response<HttpContext, HttpRequest> {
private final HttpCookie defcookie; private final HttpCookie defcookie;
private final List<HttpRender> renders;
private final boolean hasRender;
private final HttpRender onlyoneHttpRender;
public static ObjectPool<Response> createPool(AtomicLong creatCounter, AtomicLong cycleCounter, int max, Creator<Response> creator) { public static ObjectPool<Response> createPool(AtomicLong creatCounter, AtomicLong cycleCounter, int max, Creator<Response> creator) {
return new ObjectPool<>(creatCounter, cycleCounter, max, creator, (x) -> ((HttpResponse) x).prepare(), (x) -> ((HttpResponse) x).recycle()); return new ObjectPool<>(creatCounter, cycleCounter, max, creator, (x) -> ((HttpResponse) x).prepare(), (x) -> ((HttpResponse) x).recycle());
} }
public HttpResponse(HttpContext context, HttpRequest request, String[][] defaultAddHeaders, String[][] defaultSetHeaders, public HttpResponse(HttpContext context, HttpRequest request, String[][] defaultAddHeaders, String[][] defaultSetHeaders,
HttpCookie defcookie, boolean autoOptions) { HttpCookie defcookie, boolean autoOptions, List< HttpRender> renders) {
super(context, request); super(context, request);
this.defaultAddHeaders = defaultAddHeaders; this.defaultAddHeaders = defaultAddHeaders;
this.defaultSetHeaders = defaultSetHeaders; this.defaultSetHeaders = defaultSetHeaders;
this.defcookie = defcookie; this.defcookie = defcookie;
this.autoOptions = autoOptions; this.autoOptions = autoOptions;
this.renders = renders;
this.hasRender = renders != null && !renders.isEmpty();
this.onlyoneHttpRender = renders != null && renders.size() == 1 ? renders.get(0) : null;
} }
@Override @Override
@@ -467,18 +476,24 @@ public class HttpResponse extends Response<HttpContext, HttpRequest> {
} else { } else {
finish(convert, result.getResult()); finish(convert, result.getResult());
} }
} else if (obj instanceof HttpScope) {
HttpScope scope = (HttpScope) obj;
if (this.recycleListener != null) this.output = obj;
this.contentType = "text/html; charset=utf-8";
HttpTemplateEngine templateEngine = context.getTemplateEngine();
if (templateEngine == null) {
context.getLogger().log(Level.WARNING, "HttpServlet not found HttpTemplateEngine. request = " + getRequest() + ", scope = " + scope);
finish(500, null);
} else {
templateEngine.renderTo(this.request, this, scope);
}
} else { } else {
if (hasRender) {
if (onlyoneHttpRender != null) {
if (onlyoneHttpRender.getType().isAssignableFrom(obj.getClass())) {
onlyoneHttpRender.renderTo(this.request, this, obj);
return;
}
} else {
Class objt = obj.getClass();
for (HttpRender render : this.renders) {
if (render.getType().isAssignableFrom(objt)) {
render.renderTo(this.request, this, obj);
return;
}
}
}
}
if (convert instanceof TextConvert) this.contentType = "text/plain; charset=utf-8"; if (convert instanceof TextConvert) this.contentType = "text/plain; charset=utf-8";
if (this.recycleListener != null) this.output = obj; if (this.recycleListener != null) this.output = obj;
if (obj instanceof org.redkale.service.RetResult) { if (obj instanceof org.redkale.service.RetResult) {

View File

@@ -1,7 +1,7 @@
/* /*
* To change this license header, choose License Headers in Project Properties. * To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates * To change this referid file, choose Tools | Templates
* and open the template in the editor. * and open the referid in the editor.
*/ */
package org.redkale.net.http; package org.redkale.net.http;
@@ -17,18 +17,18 @@ import org.redkale.convert.json.JsonConvert;
* HttpServlet调用: <br> * HttpServlet调用: <br>
* <pre> * <pre>
* &#064;HttpMapping(url = "/hello.html", auth = false) * &#064;HttpMapping(url = "/hello.html", auth = false)
* public void hello(HttpRequest req, HttpResponse resp) throws IOException { public void hello(HttpRequest req, HttpResponse resp) throws IOException {
* resp.finish(HttpScope.template("/hello.html").attr("content", "哈哈")); resp.finish(HttpScope.refer("/hello.html").attr("content", "哈哈"));
* } }
* </pre> </pre>
* <p> * <p>
* RestService调用: <br> * RestService调用: <br>
* <pre> * <pre>
* &#064;RestMapping(name = "hello.html", auth = false) * &#064;RestMapping(name = "hello.html", auth = false)
* public HttpScope hello() { public HttpScope hello() {
* return HttpScope.template("hello.html").attr("content", "哈哈"); return HttpScope.refer("hello.html").attr("content", "哈哈");
* } }
* </pre> </pre>
* *
* 详情见: https://redkale.org * 详情见: https://redkale.org
* *
@@ -36,13 +36,13 @@ import org.redkale.convert.json.JsonConvert;
*/ */
public class HttpScope { public class HttpScope {
protected String template; protected String referid;
protected Map<String, Object> attributes; protected Map<String, Object> attributes;
public static HttpScope template(String template) { public static HttpScope refer(String template) {
HttpScope rs = new HttpScope(); HttpScope rs = new HttpScope();
rs.setTemplate(template); rs.setReferid(template);
return rs; return rs;
} }
@@ -74,12 +74,12 @@ public class HttpScope {
this.attributes.forEach(action); this.attributes.forEach(action);
} }
public String getTemplate() { public String getReferid() {
return template; return referid;
} }
public void setTemplate(String template) { public void setReferid(String referid) {
this.template = template; this.referid = referid;
} }
public Map<String, Object> getAttributes() { public Map<String, Object> getAttributes() {

View File

@@ -48,12 +48,12 @@ public class HttpServer extends Server<String, HttpContext, HttpRequest, HttpRes
} }
/** /**
* 获取HttpTemplateEngine * 获取HttpRender列表
* *
* @return HttpTemplateEngine * @return HttpRender列表
*/ */
public HttpTemplateEngine getTemplateEngine() { public List<HttpRender> getHttpRenders() {
return (HttpTemplateEngine) ((HttpPrepareServlet) this.prepare).templateEngine; return ((HttpPrepareServlet) this.prepare).renders;
} }
/** /**
@@ -370,7 +370,7 @@ public class HttpServer extends Server<String, HttpContext, HttpRequest, HttpRes
ObjectPool<Response> responsePool = HttpResponse.createPool(createResponseCounter, cycleResponseCounter, this.responsePoolSize, null); ObjectPool<Response> responsePool = HttpResponse.createPool(createResponseCounter, cycleResponseCounter, this.responsePoolSize, null);
HttpContext httpcontext = new HttpContext(this.serverStartTime, this.logger, executor, rcapacity, bufferPool, responsePool, HttpContext httpcontext = new HttpContext(this.serverStartTime, this.logger, executor, rcapacity, bufferPool, responsePool,
this.maxbody, this.charset, this.address, this.prepare, this.readTimeoutSecond, this.writeTimeoutSecond); this.maxbody, this.charset, this.address, this.prepare, this.readTimeoutSecond, this.writeTimeoutSecond);
responsePool.setCreator((Object... params) -> new HttpResponse(httpcontext, new HttpRequest(httpcontext, addrHeader), addHeaders, setHeaders, defCookie, options)); responsePool.setCreator((Object... params) -> new HttpResponse(httpcontext, new HttpRequest(httpcontext, addrHeader), addHeaders, setHeaders, defCookie, options, ((HttpPrepareServlet) prepare).renders));
return httpcontext; return httpcontext;
} }