org.noear.solon.view.velocity.VelocityRender Maven / Gradle / Ivy
package org.noear.solon.view.velocity;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.exception.ResourceNotFoundException;
import org.apache.velocity.runtime.RuntimeInstance;
import org.apache.velocity.runtime.directive.Directive;
import org.noear.solon.Solon;
import org.noear.solon.Utils;
import org.noear.solon.core.event.EventBus;
import org.noear.solon.core.handle.ModelAndView;
import org.noear.solon.core.handle.Render;
import org.noear.solon.core.handle.Context;
import org.noear.solon.ext.SupplierEx;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.URI;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
public class VelocityRender implements Render {
private static VelocityRender _global;
public static VelocityRender global() {
if (_global == null) {
_global = new VelocityRender();
}
return _global;
}
private RuntimeInstance provider;
private RuntimeInstance provider_debug;
private Map _sharedVariable = new HashMap<>();
private String _baseUri = "/WEB-INF/view/";
//不要要入参,方便后面多视图混用
//
public VelocityRender() {
String baseUri = Solon.cfg().get("slon.mvc.view.prefix");
if (Utils.isEmpty(baseUri) == false) {
_baseUri = baseUri;
}
if (Solon.cfg().isDebugMode()) {
forDebug();
forRelease();
} else {
forRelease();
}
engineInit(provider);
engineInit(provider_debug);
Solon.global().onSharedAdd((k, v) -> {
putVariable(k, v);
});
}
private void engineInit(RuntimeInstance ve) {
if(ve == null){
return;
}
ve.setProperty(Velocity.ENCODING_DEFAULT, getEncoding());
ve.setProperty(Velocity.INPUT_ENCODING, getEncoding());
Solon.cfg().forEach((k, v) -> {
String key = k.toString();
if (key.startsWith("velocity")) {
ve.setProperty(key, v);
}
});
ve.init();
}
private void forDebug() {
if (provider_debug != null) {
return;
}
//添加调试模式
URL rooturi = Utils.getResource("/");
if(rooturi == null){
return;
}
provider_debug = new RuntimeInstance();
String rootdir = rooturi.toString().replace("target/classes/", "");
File dir = null;
if (rootdir.startsWith("file:")) {
String dir_str = rootdir + "src/main/resources" + _baseUri;
dir = new File(URI.create(dir_str));
if (!dir.exists()) {
dir_str = rootdir + "src/main/webapp" + _baseUri;
dir = new File(URI.create(dir_str));
}
}
try {
if (dir != null && dir.exists()) {
provider_debug.setProperty(Velocity.FILE_RESOURCE_LOADER_PATH, dir.getAbsolutePath() + File.separatorChar);
} else {
//如果没有找到文件,则使用发行模式
//
forRelease();
}
} catch (Exception ex) {
EventBus.push(ex);
}
}
private void forRelease() {
if (provider != null) {
return;
}
provider = new RuntimeInstance();
String root_path = Utils.getResource(_baseUri).getPath();
provider.setProperty(Velocity.FILE_RESOURCE_LOADER_CACHE, true);
provider.setProperty(Velocity.FILE_RESOURCE_LOADER_PATH, root_path);
}
/**
* 添加共享指令(自定义标签)
* */
public void putDirective(T obj) {
provider.addDirective(obj);
if (provider_debug != null) {
provider_debug.addDirective(obj);
}
}
/**
* 添加共享变量
* */
public void putVariable(String key, Object obj) {
_sharedVariable.put(key, obj);
}
public String getEncoding() {
return "utf-8";
}
@Override
public void render(Object obj, Context ctx) throws Throwable {
if (obj == null) {
return;
}
if (obj instanceof ModelAndView) {
render_mav((ModelAndView) obj, ctx, () -> ctx.outputStream());
} else {
ctx.output(obj.toString());
}
}
@Override
public String renderAndReturn(Object obj, Context ctx) throws Throwable {
if (obj == null) {
return null;
}
if (obj instanceof ModelAndView) {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
render_mav((ModelAndView) obj, ctx, () -> outputStream);
return outputStream.toString();
} else {
return obj.toString();
}
}
public void render_mav(ModelAndView mv, Context ctx, SupplierEx outputStream) throws Throwable {
if (ctx.contentTypeNew() == null) {
ctx.contentType("text/html;charset=utf-8");
}
if (XPluginImp.output_meta) {
ctx.headerSet("solon.view", "VelocityRender");
}
String view = mv.view();
//取得velocity的模版
Template template = null;
if (provider_debug != null) {
try {
template = provider_debug.getTemplate(view, getEncoding());
} catch (ResourceNotFoundException ex) {
//忽略此异常
}
}
if (template == null) {
template = provider.getTemplate(view, getEncoding());
}
// 取得velocity的上下文context
VelocityContext vc = new VelocityContext(mv.model());
_sharedVariable.forEach((k, v) -> vc.put(k, v));
// 输出流
PrintWriter writer = new PrintWriter(outputStream.get());
// 转换输出
template.merge(vc, writer);
writer.flush();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy