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

View File

@@ -205,8 +205,10 @@ public class NodeHttpServer extends NodeServer {
loadRestServlet(webSocketFilter, restConf, restedObjects, sb);
}
}
resourceFactory.inject(this.httpServer.getTemplateEngine(), 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());
}

View File

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

View File

@@ -31,8 +31,6 @@ public class HttpPrepareServlet extends PrepareServlet<String, HttpContext, Http
protected HttpServlet resourceHttpServlet = new HttpResourceServlet();
protected HttpTemplateEngine templateEngine = null;
protected MappingEntry[] regArray = null; //regArray 包含 regWsArray
protected MappingEntry[] regWsArray = null;
@@ -47,6 +45,8 @@ public class HttpPrepareServlet extends PrepareServlet<String, HttpContext, Http
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) {
List<HttpServlet> servlets = new ArrayList<>();
synchronized (allMapStrings) {
@@ -233,18 +233,22 @@ public class HttpPrepareServlet extends PrepareServlet<String, HttpContext, Http
this.resourceHttpServlet.init(context, resConfig);
}
{ //设置TemplateEngine
AnyValue engineConfig = config.getAnyValue("template-engine");
if (engineConfig != null) {
String engineType = engineConfig.getValue("value");
try {
this.templateEngine = (HttpTemplateEngine) Thread.currentThread().getContextClassLoader().loadClass(engineType).newInstance();
this.templateEngine.init(context, engineConfig);
} catch (Throwable e) {
logger.log(Level.WARNING, "init HttpTemplateEngine(" + engineType + ") error", e);
AnyValue[] renderConfigs = config.getAnyValues("render");
if (renderConfigs != null) {
for (AnyValue renderConfig : renderConfigs) {
String renderType = renderConfig.getValue("value");
try {
HttpRender render = (HttpRender) Thread.currentThread().getContextClassLoader().loadClass(renderType).newInstance();
for (HttpRender one : renders) {
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;
}
public void setTemplateEngine(final HttpTemplateEngine engine) {
this.templateEngine = engine;
}
public HttpTemplateEngine getTemplateEngine() {
return this.templateEngine;
}
@Override
public void destroy(HttpContext context, AnyValue config) {
super.destroy(context, config); //必须要执行

View File

@@ -8,17 +8,20 @@ package org.redkale.net.http;
import org.redkale.util.AnyValue;
/**
* HTTP模板引擎的基类
* HTTP输出引擎的基类
*
* <p>
* 详情见: https://redkale.org
*
* @author zhangjx
* @param <T> 泛型
*/
public interface HttpTemplateEngine {
public interface HttpRender<T> {
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 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) {
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,
HttpCookie defcookie, boolean autoOptions) {
HttpCookie defcookie, boolean autoOptions, List< HttpRender> renders) {
super(context, request);
this.defaultAddHeaders = defaultAddHeaders;
this.defaultSetHeaders = defaultSetHeaders;
this.defcookie = defcookie;
this.autoOptions = autoOptions;
this.renders = renders;
this.hasRender = renders != null && !renders.isEmpty();
this.onlyoneHttpRender = renders != null && renders.size() == 1 ? renders.get(0) : null;
}
@Override
@@ -467,18 +476,24 @@ public class HttpResponse extends Response<HttpContext, HttpRequest> {
} else {
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 {
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 (this.recycleListener != null) this.output = obj;
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 template file, choose Tools | Templates
* and open the template in the editor.
* To change this referid file, choose Tools | Templates
* and open the referid in the editor.
*/
package org.redkale.net.http;
@@ -17,18 +17,18 @@ import org.redkale.convert.json.JsonConvert;
* HttpServlet调用: <br>
* <pre>
* &#064;HttpMapping(url = "/hello.html", auth = false)
* public void hello(HttpRequest req, HttpResponse resp) throws IOException {
* resp.finish(HttpScope.template("/hello.html").attr("content", "哈哈"));
* }
* </pre>
public void hello(HttpRequest req, HttpResponse resp) throws IOException {
resp.finish(HttpScope.refer("/hello.html").attr("content", "哈哈"));
}
</pre>
* <p>
* RestService调用: <br>
* <pre>
* &#064;RestMapping(name = "hello.html", auth = false)
* public HttpScope hello() {
* return HttpScope.template("hello.html").attr("content", "哈哈");
* }
* </pre>
public HttpScope hello() {
return HttpScope.refer("hello.html").attr("content", "哈哈");
}
</pre>
*
* 详情见: https://redkale.org
*
@@ -36,13 +36,13 @@ import org.redkale.convert.json.JsonConvert;
*/
public class HttpScope {
protected String template;
protected String referid;
protected Map<String, Object> attributes;
public static HttpScope template(String template) {
public static HttpScope refer(String template) {
HttpScope rs = new HttpScope();
rs.setTemplate(template);
rs.setReferid(template);
return rs;
}
@@ -74,12 +74,12 @@ public class HttpScope {
this.attributes.forEach(action);
}
public String getTemplate() {
return template;
public String getReferid() {
return referid;
}
public void setTemplate(String template) {
this.template = template;
public void setReferid(String referid) {
this.referid = referid;
}
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() {
return (HttpTemplateEngine) ((HttpPrepareServlet) this.prepare).templateEngine;
public List<HttpRender> getHttpRenders() {
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);
HttpContext httpcontext = new HttpContext(this.serverStartTime, this.logger, executor, rcapacity, bufferPool, responsePool,
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;
}