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


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

    <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

    <!--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,在这里对原类进行扩展

    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;
        }
    }

     

    测试结果如下:

  • 相关阅读:
    JS检测浏览器Adobe Reader插件
    Java Filter防止sql注入攻击
    log4j的基本配置参数
    Log4j.properties配置详解
    使用Spring进行统一日志管理 + 统一异常管理
    springMVC获取request和response
    深入浅出Mybatis-分页
    PROPAGATION_REQUIRED事务管理
    Java String类型数据的字节长度
    构建高并发高可用的电商平台架构实践
  • 原文地址:https://www.cnblogs.com/lxl57610/p/7043619.html
Copyright © 2020-2023  润新知