Spring MVC + freemarker实现半自动静态化

这里对freemarker的代码进行了修改,效果:
1,请求.do的URL时直接生成对应的.htm文件,并将请求转发到该htm文件
2,自由控制某个页面是否需要静态化
原理:对org.springframework.web.servlet.view.freemarker.FreeMarkerView类进行扩展
第一步:在web.xml中将*.do请求交给SpringMVC

XML code

<servlet>

      <servlet-name>demo</servlet-name>

      <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

      <init-param>

          <param-name>contextConfigLocation</param-name>

          <param-value>/WEB-INF/demo-servlet.xml</param-value>

      </init-param>

      <load-on-startup>1</load-on-startup>

  </servlet>



  <servlet-mapping>

      <servlet-name>demo</servlet-name>

      <url-pattern>*.do</url-pattern>

  </servlet-mapping>

 

第二步:配置/WEB-INF/demo-servlet.xml

XML code

<!--freemarker页面解析器 -->

 <bean id="viewResolver"  class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">

        <property name="suffix" value=".ftl"></property>

        <property name="contentType" value="text/html;charset=UTF-8" />

       <!-- <property name="viewClass" value="org.springframework.web.servlet.view.freemarker.FreeMarkerView" /> -->

        <!-- 将Spring的FreeMarkerView改成我们扩展的View -->

        <property name="viewClass" value="com.myview.MyFreeMarkerView" />

        <property name="exposeRequestAttributes" value="true" />

        <property name="exposeSessionAttributes" value="true" />

        <property name="exposeSpringMacroHelpers" value="true" />

 </bean>

<bean id="fmXmlEscape" class="freemarker.template.utility.XmlEscape" />



<!--配置Freemarker -->

<bean id="freemarkerConfigurer"  class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">

        <property name="templateLoaderPath" value="/WEB-INF/freemarker/"></property>

        <property name="freemarkerVariables">

            <map>

                <entry key="xml_escape" value-ref="fmXmlEscape" />

            </map>

        </property>

        <property name="freemarkerSettings">

            <props>

                <prop key="template_update_delay">1</prop>

                <prop key="defaultEncoding">UTF-8</prop>

            </props>

        </property>

  </bean>

 

 

第三步:新建package,com.myview,新建一个MyFreeMarkerView,继承自org.springframework.web.servlet.view.freemarker.FreeMarkerView,在这里对原类进行扩展

Java code

package com.myview;



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 java.util.Map;



import javax.servlet.ServletException;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.support.RequestContextUtils;

import org.springframework.web.servlet.view.freemarker.FreeMarkerView;

import freemarker.template.SimpleHash;

import freemarker.template.Template;

import freemarker.template.TemplateException;



public class MyFreeMarkerView extends FreeMarkerView{

    @Override

    protected void doRender(Map<String, Object> model,

            HttpServletRequest request, HttpServletResponse response)

            throws Exception {

        // Expose model to JSP tags (as request attributes).

        exposeModelAsRequestAttributes(model, request);

        // Expose all standard FreeMarker hash models.

        SimpleHash fmModel = buildTemplateModel(model, request, response);



        if (logger.isDebugEnabled()) {

            logger.debug("Rendering FreeMarker template [" + getUrl() + "] in FreeMarkerView '" + getBeanName() + "'");

        }



        // Grab the locale-specific version of the template.

        Locale locale = RequestContextUtils.getLocale(request);       



        /*

         * 默认生成静态文件,除非在编写ModelAndView时指定CREATE_HTML = false,

         * 这样对静态文件生成的粒度控制更细一点

         * 例如:ModelAndView mav = new ModelAndView("search");

         *       mav.addObject("CREATE_HTML", false);

         */

        if(Boolean.FALSE.equals(model.get("CREATE_HTML"))){

            processTemplate(getTemplate(locale), fmModel, response);

        }else{

            createHTML(getTemplate(locale), fmModel, request, response);

        }

    }



    public void createHTML(Template template, SimpleHash model,HttpServletRequest request,

            HttpServletResponse response) throws IOException, TemplateException, ServletException {

            //站点根目录的绝对路径

            String basePath = request.getSession().getServletContext().getRealPath("/");

            String requestHTML = this.getRequestHTML(request);

            //静态页面绝对路径

            String htmlPath = basePath + requestHTML;         

            File htmlFile = new File(htmlPath);

            if(!htmlFile.getParentFile().exists()){

                htmlFile.getParentFile().mkdirs();

            }

            if(!htmlFile.exists()){

                htmlFile.createNewFile();

            }

            Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(htmlFile), "UTF-8"));

            //处理模版 

            template.process(model, out);

            out.flush();

            out.close();

            /*将请求转发到生成的htm文件*/        request.getRequestDispatcher(requestHTML).forward(request, response);



    }



    /**

     * 计算要生成的静态文件相对路径

     * 因为大家在调试的时候一般在Tomcat的webapps下面新建站点目录的,

     * 但在实际应用时直接布署到ROOT目录里面,这里要保证路径的一致性。

     * @param request HttpServletRequest

     * @return /目录/*.htm

     */

     private String getRequestHTML(HttpServletRequest request){

        //web应用名称,部署在ROOT目录时为空

        String contextPath = request.getContextPath();

        //web应用/目录/文件.do

        String requestURI = request.getRequestURI();

        //basePath里面已经有了web应用名称,所以直接把它replace掉,以免重复

        requestURI = requestURI.replaceFirst(contextPath, "");

        //将.do改为.htm,稍后将请求转发到此htm文件

        requestURI = requestURI.substring(0, requestURI.indexOf(".")) + ".htm";

        return requestURI;

     }



}

 

到这里就基本完成了。
一个Controller类的例子:

Java code

import org.springframework.stereotype.Controller;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RequestParam;

import org.springframework.web.servlet.ModelAndView;



@Controller

public class IndexController {

    @RequestMapping("/index.do")

    public ModelAndView index(){

        ModelAndView mav = new ModelAndView("index");

        mav.addObject("title", "网站标题");

        mav.addObject("origin", "freemarker");

        //在这里可以控制不生成静态htm

        mav.addObject("CREATE_HTML", false);

        return mav;

    }



    @RequestMapping("/abc/index.do")

    public ModelAndView abcindex(){

        ModelAndView mav = new ModelAndView("index");

        mav.addObject("origin", "html");

        //默认生成htm文件

        mav.addObject("title", "网站标题");

        return mav;

    }

}

测试结果如下:

Spring MVC + freemarker实现半自动静态化

Spring MVC + freemarker实现半自动静态化

源码下载地址http://vdisk.weibo.com/s/kmkCC 

 

 

 

 

你可能感兴趣的:(freemarker)