模板部分:
TemplateFactory 抽象类:单类
//通过给定路径返回一个模板, 经典的抽象工厂模式 public Template loadTemplate(String path) throws Exception
两个子类:JspTemplateFactory 和VelocityTemplateFactory
VelocityTemplateFactory类:
初始化:
public void init(Config config) {
String webAppPath = config.getServletContext().getRealPath("/");
if (webAppPath==null) {
String err = "Cannot get web application path. Are you deploy the application as a .war file?";
log.warn(err);
throw new ExceptionInInitializerError(err);
}
if (!webAppPath.endsWith("/") && !webAppPath.endsWith("\\"))
webAppPath = webAppPath + File.separator;
log.info("Detect web application path: " + webAppPath);
log.info("init VelocityTemplateFactory...");
rtInstance = new RuntimeInstance();
// read property file:
//读取velocity的配置文件
Properties props = readProperties(webAppPath + "/WEB-INF/velocity.properties");
checkProperty(props);
Set<?> keys = props.keySet();
for(Object key : keys) {
if(key instanceof String) {
Object value = props.get(key);
rtInstance.addProperty((String)key, value);
}
}
try {
if(rtInstance.getProperty(RuntimeConstants.FILE_RESOURCE_LOADER_PATH)==null) {
rtInstance.setProperty(RuntimeConstants.FILE_RESOURCE_LOADER_PATH, webAppPath);
log.info("Using web application context path as velocity template root path: " + webAppPath);
}
else {
log.info("Velocity property \"" + RuntimeConstants.FILE_RESOURCE_LOADER_PATH + "\" has been specified in \"/WEB-INF/velocity.properties\".");
log.info("To using web application context path, remove property \"" + RuntimeConstants.FILE_RESOURCE_LOADER_PATH + "\" from configuration file.");
}
//初始化
rtInstance.init();
afterVelocityEngineInit(rtInstance);
}
catch(Exception e) {
log.error("VelocityTemplateFactory init failed.", e);
throw new ExceptionInInitializerError(e);
}
}
创建模板:
public Template loadTemplate(String path) throws Exception {
if (log.isDebugEnabled())
log.debug("Load Velocity template '" + path + "'.");
return new VelocityTemplate(
rtInstance.getTemplate(path, inputEncoding),
null,
outputEncoding
);
}
再看模板部分:
Template接口:
//使用模板引擎渲染
voidrender(HttpServletRequest request, HttpServletResponse response,Map<String, Object> model) throwsException;
JspTemplate模板:
public void render(HttpServletRequest request, HttpServletResponse response, Map<String, Object> model) throws Exception {
Set<String> keys = model.keySet();
//向request中写入数据
for (String key : keys) {
request.setAttribute(key, model.get(key));
}
//用当前的模板路径(jsp)得到一个Dispatcher, 然后跳转(forward)到这个页面上
//NOTES:
//使用forward的时候浏览器不知道它所请求的具体资源来源,所以地址栏不会变;
//使用redirect,服务端根据逻辑,发送一个状态码,告诉浏览器重新去请求那个地址.所以地址栏显示的是新的URL。
request.getRequestDispatcher(path).forward(request, response);
}
VelocityTemplate模板:
public void render(HttpServletRequest request, HttpServletResponse response, Map<String, Object> model) throws Exception {
StringBuilder sb = new StringBuilder(64);
sb.append(contentType==null ? "text/html" : contentType)
.append(";charset=")
.append(encoding==null ? "UTF-8" : encoding);
//设置头部信息
response.setContentType(sb.toString());
response.setCharacterEncoding(encoding==null ? "UTF-8" : encoding);
// init context:
Context context = new VelocityContext(model);
afterContextPrepared(context);
// render: 获取渲染writer
VelocityWriter vw = new VelocityWriter(response.getWriter());
try {
//merge数据
template.merge(context, vw);
vw.flush();
}
finally {
vw.recycle(null);
}
}
至此,模板部分也完了.很简单.
浙公网安备 33010602011771号