利用Struts2生成静态页面其实很灵活,很强大,尤其是利用Struts2对Freemarker较好的支持,充分利用Freemarker的模板功能来生成静态页面。
基本思路为:利用Struts2对自定义result type的支持,自定义能够生成静态页面的result type,结合模板引擎Freemarker可以实现大批量静态页面的生成。
参看org.apache.struts2.views.freemarker.FreemarkerResult的代码实现,自定义了自己的生成静态页面的result type。此种方案不单纯用于生成静态页面,其实也可以用于生成诸如wml、xhtml等内容,具体可以参考Struts2缺省提供的各种result type的实现。
1、com.mobilesoft.esales.webapp.action.FreemarkerResult
package com.mobilesoft.esales.webapp.action;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.Locale;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts2.ServletActionContext;
import org.apache.struts2.dispatcher.StrutsResultSupport;
import org.apache.struts2.views.freemarker.FreemarkerManager;
import org.apache.struts2.views.util.ResourceUtil;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.LocaleProvider;
import com.opensymphony.xwork2.inject.Inject;
import com.opensymphony.xwork2.util.ValueStack;
import freemarker.template.Configuration;
import freemarker.template.ObjectWrapper;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import freemarker.template.TemplateModel;
import freemarker.template.TemplateModelException;
public class FreemarkerResult extends StrutsResultSupport {
private static final long serialVersionUID = -3778230771704661631L;
protected ActionInvocation invocation;
protected Configuration configuration;
protected ObjectWrapper wrapper;
protected FreemarkerManager freemarkerManager;
private Writer writer;
protected String location;
private String pContentType = “text/html”;
protected String fileName; // 要生成的静态页面名称
protected String filePath; // 要生成的静态页面的路径
protected String staticTemplate; // 用于生成静态页面Freemarker模板的路径
public FreemarkerResult() {
super();
}
public FreemarkerResult(String location) {
super(location);
}
@Inject
public void setFreemarkerManager(FreemarkerManager mgr) {
this.freemarkerManager = mgr;
}
public void setContentType(String aContentType) {
pContentType = aContentType;
}
public String getContentType() {
return pContentType;
}
public void doExecute(String location, ActionInvocation invocation)
throws IOException, TemplateException {
this.location = location;
this.invocation = invocation;
this.configuration = getConfiguration();
this.wrapper = getObjectWrapper();
this.fileName = (String) conditionalParse(fileName, invocation);
this.staticTemplate = (String) conditionalParse(staticTemplate, invocation);
this.filePath = ((String) conditionalParse(filePath, invocation)) == null ? “”
: ((String) conditionalParse(filePath, invocation));
if (!location.startsWith(”/”)) {
ActionContext ctx = invocation.getInvocationContext();
HttpServletRequest req = (HttpServletRequest) ctx
.get(ServletActionContext.HTTP_REQUEST);
String base = ResourceUtil.getResourceBase(req);
location = base + “/” + location;
}
//生成html页面的模板类
Template template = configuration.getTemplate(location, deduceLocale());
// 生成静态页面的的模板类
Template staticTemplate = configuration.getTemplate(this.staticTemplate,
deduceLocale());
TemplateModel model = createModel();
String path = ServletActionContext.getServletContext().getRealPath(
filePath)
+ File.separator;
Writer out = new BufferedWriter(new OutputStreamWriter(
new FileOutputStream(path + fileName)));
if (preTemplateProcess(template, model)) {
try {
staticTemplate.process(model, out);
template.process(model, getWriter());
} finally {
postTemplateProcess(template, model);
postTemplateProcess(staticTemplate, model);
}
}
}
protected Configuration getConfiguration() throws TemplateException {
return freemarkerManager.getConfiguration(ServletActionContext
.getServletContext());
}
protected ObjectWrapper getObjectWrapper() {
return configuration.getObjectWrapper();
}
public void setWriter(Writer writer) {
this.writer = writer;
}
protected Writer getWriter() throws IOException {
if (writer != null) {
return writer;
}
return ServletActionContext.getResponse().getWriter();
}
protected TemplateModel createModel() throws TemplateModelException {
ServletContext servletContext = ServletActionContext
.getServletContext();
HttpServletRequest request = ServletActionContext.getRequest();
HttpServletResponse response = ServletActionContext.getResponse();
ValueStack stack = ServletActionContext.getContext().getValueStack();
Object action = null;
if (invocation != null)
action = invocation.getAction(); // Added for NullPointException
return freemarkerManager.buildTemplateModel(stack, action,
servletContext, request, response, wrapper);
}
protected Locale deduceLocale() {
if (invocation.getAction() instanceof LocaleProvider) {
return ((LocaleProvider) invocation.getAction()).getLocale();
} else {
return configuration.getLocale();
}
}
protected void postTemplateProcess(Template template, TemplateModel data)
throws IOException {
}
protected boolean preTemplateProcess(Template template, TemplateModel model)
throws IOException {
Object attrContentType = template.getCustomAttribute(”content_type”);
if (attrContentType != null) {
ServletActionContext.getResponse().setContentType(
attrContentType.toString());
} else {
String contentType = getContentType();
if (contentType == null) {
contentType = “text/html”;
}
String encoding = template.getEncoding();
if (encoding != null) {
contentType = contentType + “; charset=” + encoding;
}
ServletActionContext.getResponse().setContentType(contentType);
}
return true;
}
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public String getFilePath() {
return filePath;
}
public void setFilePath(String filePath) {
this.filePath = filePath;
}
public String getStaticTemplate() {
return staticTemplate;
}
public void setStaticTemplate(String staticTemplate) {
this.staticTemplate = staticTemplate;
}
}
2、struts.xml
<action name=”staticViewAction” class=”com.mobilesoft.esales.webapp.action.StaticViewtAction”>
<result name=”success” type=”staticview”>
<param name=”location”>test/freemarkertest.ftl</param>
<param name=”contentType”>text/html</param>
<param name=”fileName”>${filename}</param>
<param name=”staticTemplate”>test/freemarkertest.ftl</param>
<param name=”filePath”>static</param>
</result>
</action>
基本思路为:利用Struts2对自定义result type的支持,自定义能够生成静态页面的result type,结合模板引擎Freemarker可以实现大批量静态页面的生成。
参看org.apache.struts2.views.freemarker.FreemarkerResult的代码实现,自定义了自己的生成静态页面的result type。此种方案不单纯用于生成静态页面,其实也可以用于生成诸如wml、xhtml等内容,具体可以参考Struts2缺省提供的各种result type的实现。
1、com.mobilesoft.esales.webapp.action.FreemarkerResult
package com.mobilesoft.esales.webapp.action;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.Locale;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts2.ServletActionContext;
import org.apache.struts2.dispatcher.StrutsResultSupport;
import org.apache.struts2.views.freemarker.FreemarkerManager;
import org.apache.struts2.views.util.ResourceUtil;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.LocaleProvider;
import com.opensymphony.xwork2.inject.Inject;
import com.opensymphony.xwork2.util.ValueStack;
import freemarker.template.Configuration;
import freemarker.template.ObjectWrapper;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import freemarker.template.TemplateModel;
import freemarker.template.TemplateModelException;
public class FreemarkerResult extends StrutsResultSupport {
private static final long serialVersionUID = -3778230771704661631L;
protected ActionInvocation invocation;
protected Configuration configuration;
protected ObjectWrapper wrapper;
protected FreemarkerManager freemarkerManager;
private Writer writer;
protected String location;
private String pContentType = “text/html”;
protected String fileName; // 要生成的静态页面名称
protected String filePath; // 要生成的静态页面的路径
protected String staticTemplate; // 用于生成静态页面Freemarker模板的路径
public FreemarkerResult() {
super();
}
public FreemarkerResult(String location) {
super(location);
}
@Inject
public void setFreemarkerManager(FreemarkerManager mgr) {
this.freemarkerManager = mgr;
}
public void setContentType(String aContentType) {
pContentType = aContentType;
}
public String getContentType() {
return pContentType;
}
public void doExecute(String location, ActionInvocation invocation)
throws IOException, TemplateException {
this.location = location;
this.invocation = invocation;
this.configuration = getConfiguration();
this.wrapper = getObjectWrapper();
this.fileName = (String) conditionalParse(fileName, invocation);
this.staticTemplate = (String) conditionalParse(staticTemplate, invocation);
this.filePath = ((String) conditionalParse(filePath, invocation)) == null ? “”
: ((String) conditionalParse(filePath, invocation));
if (!location.startsWith(”/”)) {
ActionContext ctx = invocation.getInvocationContext();
HttpServletRequest req = (HttpServletRequest) ctx
.get(ServletActionContext.HTTP_REQUEST);
String base = ResourceUtil.getResourceBase(req);
location = base + “/” + location;
}
//生成html页面的模板类
Template template = configuration.getTemplate(location, deduceLocale());
// 生成静态页面的的模板类
Template staticTemplate = configuration.getTemplate(this.staticTemplate,
deduceLocale());
TemplateModel model = createModel();
String path = ServletActionContext.getServletContext().getRealPath(
filePath)
+ File.separator;
Writer out = new BufferedWriter(new OutputStreamWriter(
new FileOutputStream(path + fileName)));
if (preTemplateProcess(template, model)) {
try {
staticTemplate.process(model, out);
template.process(model, getWriter());
} finally {
postTemplateProcess(template, model);
postTemplateProcess(staticTemplate, model);
}
}
}
protected Configuration getConfiguration() throws TemplateException {
return freemarkerManager.getConfiguration(ServletActionContext
.getServletContext());
}
protected ObjectWrapper getObjectWrapper() {
return configuration.getObjectWrapper();
}
public void setWriter(Writer writer) {
this.writer = writer;
}
protected Writer getWriter() throws IOException {
if (writer != null) {
return writer;
}
return ServletActionContext.getResponse().getWriter();
}
protected TemplateModel createModel() throws TemplateModelException {
ServletContext servletContext = ServletActionContext
.getServletContext();
HttpServletRequest request = ServletActionContext.getRequest();
HttpServletResponse response = ServletActionContext.getResponse();
ValueStack stack = ServletActionContext.getContext().getValueStack();
Object action = null;
if (invocation != null)
action = invocation.getAction(); // Added for NullPointException
return freemarkerManager.buildTemplateModel(stack, action,
servletContext, request, response, wrapper);
}
protected Locale deduceLocale() {
if (invocation.getAction() instanceof LocaleProvider) {
return ((LocaleProvider) invocation.getAction()).getLocale();
} else {
return configuration.getLocale();
}
}
protected void postTemplateProcess(Template template, TemplateModel data)
throws IOException {
}
protected boolean preTemplateProcess(Template template, TemplateModel model)
throws IOException {
Object attrContentType = template.getCustomAttribute(”content_type”);
if (attrContentType != null) {
ServletActionContext.getResponse().setContentType(
attrContentType.toString());
} else {
String contentType = getContentType();
if (contentType == null) {
contentType = “text/html”;
}
String encoding = template.getEncoding();
if (encoding != null) {
contentType = contentType + “; charset=” + encoding;
}
ServletActionContext.getResponse().setContentType(contentType);
}
return true;
}
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public String getFilePath() {
return filePath;
}
public void setFilePath(String filePath) {
this.filePath = filePath;
}
public String getStaticTemplate() {
return staticTemplate;
}
public void setStaticTemplate(String staticTemplate) {
this.staticTemplate = staticTemplate;
}
}
2、struts.xml
<action name=”staticViewAction” class=”com.mobilesoft.esales.webapp.action.StaticViewtAction”>
<result name=”success” type=”staticview”>
<param name=”location”>test/freemarkertest.ftl</param>
<param name=”contentType”>text/html</param>
<param name=”fileName”>${filename}</param>
<param name=”staticTemplate”>test/freemarkertest.ftl</param>
<param name=”filePath”>static</param>
</result>
</action>