mirror of
https://github.com/apache/struts.git
synced 2026-08-07 07:37:20 +00:00
Resolved WW-3467 - Improve performance for page rendering by refactoring freemarker cache
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@965050 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
@@ -82,9 +82,13 @@ public final class StrutsConstants {
|
||||
/** The org.apache.struts2.views.freemarker.FreemarkerManager implementation class */
|
||||
public static final String STRUTS_FREEMARKER_MANAGER_CLASSNAME = "struts.freemarker.manager.classname";
|
||||
|
||||
/** Cache Freemarker templates */
|
||||
@Deprecated
|
||||
/** Cache Freemarker templates, this cache is managed by struts2,instead of native freemarker cache,set STRUTS_FREEMARKER_MRU_MAX_STRONG_SIZE >0&&STRUTS_FREEMARKER_TEMPLATES_CACHE_UPDATE_DELAY>0*/
|
||||
public static final String STRUTS_FREEMARKER_TEMPLATES_CACHE = "struts.freemarker.templatesCache";
|
||||
|
||||
/** Update freemarker templates cache in seconds*/
|
||||
public static final String STRUTS_FREEMARKER_TEMPLATES_CACHE_UPDATE_DELAY = "struts.freemarker.templatesCache.updateDelay";
|
||||
|
||||
/** Cache model instances at BeanWrapper level */
|
||||
public static final String STRUTS_FREEMARKER_BEANWRAPPER_CACHE = "struts.freemarker.beanwrapperCache";
|
||||
|
||||
|
||||
+2
-61
@@ -23,16 +23,14 @@ package org.apache.struts2.components.template;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
import java.util.Map;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.struts2.ServletActionContext;
|
||||
import org.apache.struts2.StrutsConstants;
|
||||
import org.apache.struts2.views.freemarker.FreemarkerManager;
|
||||
|
||||
import com.opensymphony.xwork2.ActionContext;
|
||||
@@ -54,10 +52,6 @@ public class FreemarkerTemplateEngine extends BaseTemplateEngine {
|
||||
static Class bodyContent = null;
|
||||
protected FreemarkerManager freemarkerManager;
|
||||
|
||||
protected final Map<String, freemarker.template.Template> templates = new ConcurrentHashMap<String, freemarker.template.Template>();
|
||||
protected final Set<String> missingTemplates = new CopyOnWriteArraySet<String>();
|
||||
protected boolean freemarkerCaching = false;
|
||||
|
||||
static {
|
||||
try {
|
||||
bodyContent = ClassLoaderUtil.loadClass("javax.servlet.jsp.tagext.BodyContent",
|
||||
@@ -97,24 +91,6 @@ public class FreemarkerTemplateEngine extends BaseTemplateEngine {
|
||||
Exception exception = null;
|
||||
for (Template t : templates) {
|
||||
templateName = getFinalTemplateName(t);
|
||||
if (freemarkerCaching) {
|
||||
if (!isTemplateMissing(templateName)) {
|
||||
try {
|
||||
template = findInCache(templateName); // look in cache first
|
||||
if (template == null) {
|
||||
// try to load, and if it works, stop at the first one
|
||||
template = config.getTemplate(templateName);
|
||||
addToCache(templateName, template);
|
||||
}
|
||||
break;
|
||||
} catch (IOException e) {
|
||||
addToMissingTemplateCache(templateName);
|
||||
if (exception == null) {
|
||||
exception = e;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
// try to load, and if it works, stop at the first one
|
||||
template = config.getTemplate(templateName);
|
||||
@@ -129,7 +105,6 @@ public class FreemarkerTemplateEngine extends BaseTemplateEngine {
|
||||
exception = e;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (template == null) {
|
||||
@@ -189,39 +164,5 @@ public class FreemarkerTemplateEngine extends BaseTemplateEngine {
|
||||
return "ftl";
|
||||
}
|
||||
|
||||
protected void addToMissingTemplateCache(String templateName) {
|
||||
missingTemplates.add(templateName);
|
||||
}
|
||||
|
||||
protected boolean isTemplateMissing(String templateName) {
|
||||
return missingTemplates.contains(templateName);
|
||||
}
|
||||
|
||||
protected void addToCache(String templateName,
|
||||
freemarker.template.Template template) {
|
||||
templates.put(templateName, template);
|
||||
}
|
||||
|
||||
protected freemarker.template.Template findInCache(String templateName) {
|
||||
return templates.get(templateName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables or disables Struts caching of Freemarker templates. By default disabled.
|
||||
* Set struts.freemarker.templatesCache=true to enable cache
|
||||
* @param cacheTemplates "true" if the template engine should cache freemarker template
|
||||
* internally
|
||||
*/
|
||||
@Inject(StrutsConstants.STRUTS_FREEMARKER_TEMPLATES_CACHE)
|
||||
public void setCacheTemplates(String cacheTemplates) {
|
||||
freemarkerCaching = "true".equals(cacheTemplates);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the templates and missing templates cache
|
||||
*/
|
||||
public void clearTemplatesCache() {
|
||||
templates.clear();
|
||||
missingTemplates.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,6 @@ import java.util.StringTokenizer;
|
||||
|
||||
import org.apache.struts2.StrutsConstants;
|
||||
import org.apache.struts2.components.UrlRenderer;
|
||||
import org.apache.struts2.dispatcher.DefaultStaticContentLoader;
|
||||
import org.apache.struts2.dispatcher.StaticContentLoader;
|
||||
import org.apache.struts2.dispatcher.mapper.ActionMapper;
|
||||
import org.apache.struts2.dispatcher.multipart.MultiPartRequest;
|
||||
@@ -222,6 +221,7 @@ public class BeanSelectionProvider implements ConfigurationProvider {
|
||||
props.setProperty(StrutsConstants.STRUTS_I18N_RELOAD, "true");
|
||||
props.setProperty(StrutsConstants.STRUTS_CONFIGURATION_XML_RELOAD, "true");
|
||||
props.setProperty(StrutsConstants.STRUTS_FREEMARKER_TEMPLATES_CACHE, "false");
|
||||
props.setProperty(StrutsConstants.STRUTS_FREEMARKER_TEMPLATES_CACHE_UPDATE_DELAY, "0");
|
||||
// Convert struts properties into ones that xwork expects
|
||||
props.setProperty("devMode", "true");
|
||||
} else {
|
||||
|
||||
@@ -50,14 +50,12 @@ import freemarker.cache.FileTemplateLoader;
|
||||
import freemarker.cache.MultiTemplateLoader;
|
||||
import freemarker.cache.TemplateLoader;
|
||||
import freemarker.cache.WebappTemplateLoader;
|
||||
import freemarker.ext.beans.BeansWrapper;
|
||||
import freemarker.ext.jsp.TaglibFactory;
|
||||
import freemarker.ext.servlet.HttpRequestHashModel;
|
||||
import freemarker.ext.servlet.HttpRequestParametersHashModel;
|
||||
import freemarker.ext.servlet.HttpSessionHashModel;
|
||||
import freemarker.ext.servlet.ServletContextHashModel;
|
||||
import freemarker.template.*;
|
||||
import freemarker.core.Configurable;
|
||||
import freemarker.template.utility.StringUtil;
|
||||
|
||||
|
||||
@@ -117,7 +115,6 @@ public class FreemarkerManager {
|
||||
// Note these names start with dot, so they're essentially invisible from a freemarker script.
|
||||
private static final String ATTR_REQUEST_MODEL = ".freemarker.Request";
|
||||
private static final String ATTR_REQUEST_PARAMETERS_MODEL = ".freemarker.RequestParameters";
|
||||
private static final String ATTR_SESSION_MODEL = ".freemarker.Session";
|
||||
private static final String ATTR_APPLICATION_MODEL = ".freemarker.Application";
|
||||
private static final String ATTR_JSP_TAGLIBS_MODEL = ".freemarker.JspTaglibs";
|
||||
|
||||
@@ -169,6 +166,7 @@ public class FreemarkerManager {
|
||||
protected boolean altMapWrapper;
|
||||
protected boolean cacheBeanWrapper;
|
||||
protected int mruMaxStrongSize;
|
||||
protected String templateUpdateDelay;
|
||||
protected Map<String,TagLibrary> tagLibraries;
|
||||
|
||||
@Inject(StrutsConstants.STRUTS_I18N_ENCODING)
|
||||
@@ -191,6 +189,11 @@ public class FreemarkerManager {
|
||||
mruMaxStrongSize = Integer.parseInt(size);
|
||||
}
|
||||
|
||||
@Inject(value = StrutsConstants.STRUTS_FREEMARKER_TEMPLATES_CACHE_UPDATE_DELAY, required = false)
|
||||
public void setTemplateUpdateDelay(String delay) {
|
||||
templateUpdateDelay = delay;
|
||||
}
|
||||
|
||||
@Inject
|
||||
public void setContainer(Container container) {
|
||||
Map<String,TagLibrary> map = new HashMap<String,TagLibrary>();
|
||||
@@ -229,7 +232,7 @@ public class FreemarkerManager {
|
||||
return contentType;
|
||||
}
|
||||
|
||||
public synchronized freemarker.template.Configuration getConfiguration(ServletContext servletContext) {
|
||||
public synchronized Configuration getConfiguration(ServletContext servletContext) {
|
||||
if (config == null) {
|
||||
try {
|
||||
init(servletContext);
|
||||
@@ -287,15 +290,17 @@ public class FreemarkerManager {
|
||||
*
|
||||
* @param servletContext
|
||||
*/
|
||||
protected freemarker.template.Configuration createConfiguration(ServletContext servletContext) throws TemplateException {
|
||||
freemarker.template.Configuration configuration = new freemarker.template.Configuration();
|
||||
protected Configuration createConfiguration(ServletContext servletContext) throws TemplateException {
|
||||
Configuration configuration = new Configuration();
|
||||
|
||||
configuration.setTemplateExceptionHandler(TemplateExceptionHandler.HTML_DEBUG_HANDLER);
|
||||
|
||||
if (mruMaxStrongSize > 0) {
|
||||
configuration.setSetting(freemarker.template.Configuration.CACHE_STORAGE_KEY, "strong:" + mruMaxStrongSize);
|
||||
configuration.setSetting(Configuration.CACHE_STORAGE_KEY, "strong:" + mruMaxStrongSize);
|
||||
}
|
||||
if (templateUpdateDelay != null) {
|
||||
configuration.setSetting(Configuration.TEMPLATE_UPDATE_DELAY_KEY, templateUpdateDelay);
|
||||
}
|
||||
|
||||
if (encoding != null) {
|
||||
configuration.setDefaultEncoding(encoding);
|
||||
}
|
||||
@@ -333,17 +338,8 @@ public class FreemarkerManager {
|
||||
|
||||
// Create hash model wrapper for session
|
||||
HttpSession session = request.getSession(false);
|
||||
HttpSessionHashModel sessionModel;
|
||||
if (session != null) {
|
||||
sessionModel = (HttpSessionHashModel) session.getAttribute(ATTR_SESSION_MODEL);
|
||||
if (sessionModel == null) {
|
||||
sessionModel = new HttpSessionHashModel(session, wrapper);
|
||||
session.setAttribute(ATTR_SESSION_MODEL, sessionModel);
|
||||
}
|
||||
model.put(KEY_SESSION, new HttpSessionHashModel(session, wrapper));
|
||||
} else {
|
||||
// no session means no attributes ???
|
||||
// model.put(KEY_SESSION_MODEL, new SimpleHash());
|
||||
}
|
||||
|
||||
// Create hash model wrapper for the request attributes
|
||||
@@ -525,19 +521,4 @@ public class FreemarkerManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If the parameter "nocache" was set to true, generate a set of headers
|
||||
* that will advise the HTTP client not to cache the returned page.
|
||||
*/
|
||||
private void setBrowserCachingPolicy(HttpServletResponse res) {
|
||||
if (nocache) {
|
||||
// HTTP/1.1 + IE extensions
|
||||
res.setHeader("Cache-Control", "no-store, no-cache, must-revalidate, "
|
||||
+ "post-check=0, pre-check=0");
|
||||
// HTTP/1.0
|
||||
res.setHeader("Pragma", "no-cache");
|
||||
// Last resort for those that ignore all of the above
|
||||
res.setHeader("Expires", EXPIRATION_DATE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user