sprig mvc+freemarker模板页面静态化

来源:互联网 发布:windows会员计划 编辑:程序博客网 时间:2024/06/07 02:42

本篇文章重点介绍freemarker模板页面静态化在spring mvc框架中的运用,其中模板放在redis缓存中


1、配置文件

代码如下

<bean id="freemarkerConfig" class="com.wu.wuji.front.base.MyFreemarkerConfig"><property name="templateLoaderPath" value="/WEB-INF/views/" /><property name="freemarkerSettings"><props><prop key="template_update_delay">0</prop><prop key="default_encoding">UTF-8</prop><prop key="number_format">0.##########</prop><prop key="datetime_format">yyyy-MM-dd HH:mm:ss</prop><prop key="classic_compatible">true</prop><prop key="template_exception_handler">ignore</prop><prop key="auto_import">/ftl/spring.ftl as s</prop></props></property><property name="freemarkerVariables"><map><entry key="content" value-ref="contentDirective" /></map></property></bean>


2、MyFreemarkerConfig

注入 RedisTemplateLoader 

public class MyFreemarkerConfig extends FreeMarkerConfigurer{        @Autowired(required=false)    private RedisTemplateLoader templateLoader;    /**     * TODO 配置自定义templateLoader.     * @see org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer     *      #postProcessTemplateLoaders(java.util.List)     */    @Override    public void postProcessTemplateLoaders(List<TemplateLoader> templateLoaders) {        if(templateLoader!=null){            templateLoaders.add(templateLoader);        }        super.postProcessTemplateLoaders(templateLoaders);    }}

这里需要注意的是freemarker加载模板类是multiTemplateLoder,里面默认包含FileTemplateLoader,即加载配置文件中auto_import的templateLoader.我们需要自定义一个tempalteLoader加载模板文件,即RedisTemplateLoader


3、RedisTemplateLoader

@Servicepublic class RedisTemplateLoader implements TemplateLoader {        private static final Logger LOG = LoggerFactory.getLogger(RedisTemplateLoader.class);        @Autowired    IContentFacade contentFacade;        private String[] ignoreLocales = { "_zh_CN", "_zh", "_en_US", "_en" };        @Override    public Object findTemplateSource(String name) throws IOException {        for (String ignore : ignoreLocales) {            if (name.indexOf(ignore) != -1) {                LOG.debug("templete ignore: {}", name);                return null;            }        }        return new RedisTemplateSource(Constants.TEMPLATE_ROOT_PATH+"/"+name);    }    @Override    public long getLastModified(Object templateSource) {        return System.currentTimeMillis();    }    @Override    public Reader getReader(Object templateSource, String encoding) throws IOException {        return new StringReader(((RedisTemplateSource) templateSource).source());    }    @Override    public void closeTemplateSource(Object templateSource) throws IOException {    }    /**     * redis缓存模板源     * @作者 0200759     * @创建时间 2017年9月15日 下午3:21:51     * @修改备注     */    private static class RedisTemplateSource {        private final String name;                RedisTemplateSource(String name) {            if (name == null) {                throw new IllegalArgumentException("name == null");            }            this.name = name;        }        /**         * @作者 0200759         * @创建时间 2017年9月15日 下午3:22:27         * @TODO 从获缓存取模板内容         * @return         */        public String source() {            return  CacheUtils.get(Constants.TEMPLATE_INFO, name);        }        /** (non-Javadoc)         * @see java.lang.Object#equals(java.lang.Object)         * @author 0200759 2017年9月15日         * @param obj         * @return         */        public boolean equals(Object obj) {            if (obj instanceof RedisTemplateSource) {                return name.equals(((RedisTemplateSource) obj).name);            }            return false;        }        /** (non-Javadoc)         * @see java.lang.Object#hashCode()         * @author 0200759 2017年9月15日         * @return         */        public int hashCode() {            return name.hashCode();        }    }}

freemarker模板加载默认会在文件名称后面带上ignoreLocales中的字符串,即文件名locale化(后缀名称可在配置文件自定义配置),freemarker会根据controller返回的ModelAndView中的url+后缀,如"content/add"+"_zh_CN",先循环遍历url,每一次遍历在multiTemplateLoader中循环遍历每一个tempalteLoader,寻找当前tempalteLoader是否存在此模板文件,如果存在,则返回,否则去掉url后缀中"_CN"字段进入下一次循环,直到后缀去完为止。而templateaLoaderPath下的文件在FileTemplateLoader中都会带上后缀,我们自定义加载的模板文件不加后缀。
ignoreLocales就是用来区分文件从FileTemplateLoader还是我们自定义的RedisTemplateLoader加载。这里怎么将模板文件存到缓存就不介绍了。


4、Controller

  @RequestMapping("/news")    public ModelAndView toIndex() {        ModelAndView mv = new ModelAndView("content/add");        return mv;    }

注意这里mv中的url必须和redis缓存中模板文件名一致