前一章讲到页面静态化当中freeMarker标签的使用,这一章我们使用spring mvc结合freeMarker处理大型网站页面静态化.
第一步:引入除spring mvc 所需的jar包(之前系列的文章讲过,大家可以看之前的文章),还需要引入freemarker-xxx.jar commons-logging-xxx.jar
第二步:扩展FreeMarkerView,使我们可以控制是否生成静态页面以及生成的静态页面存放的位置.
- packagegd.hz;
- importjava.io.BufferedWriter;
- importjava.io.File;
- importjava.io.FileOutputStream;
- importjava.io.IOException;
- importjava.io.OutputStreamWriter;
- importjava.io.Writer;
- importjava.util.Locale;
- importjava.util.Map;
- importjavax.servlet.ServletException;
- importjavax.servlet.http.HttpServletRequest;
- importjavax.servlet.http.HttpServletResponse;
- importorg.springframework.web.servlet.support.RequestContextUtils;
- importorg.springframework.web.servlet.view.freemarker.FreeMarkerView;
- importfreemarker.template.SimpleHash;
- importfreemarker.template.Template;
- importfreemarker.template.TemplateException;
- publicclassExFreeMarkerViewextendsFreeMarkerView{
- @Override
- protectedvoiddoRender(Map<String,Object>model,
- HttpServletRequestrequest,HttpServletResponseresponse)
- throwsException{
- exposeModelAsRequestAttributes(model,request);
- SimpleHashfmModel=buildTemplateModel(model,request,response);
- if(logger.isDebugEnabled()){
- logger.debug("RenderingFreeMarkertemplate["+getUrl()+"]inFreeMarkerView'"+getBeanName()+"'");
- }
- Localelocale=RequestContextUtils.getLocale(request);
- /*
- *在这里我们默认生成静态文件,当ModelAndView有指定STATIC_HTML=false时,就不会输出HTML文件
- *例如:ModelAndViewmodelAndView=newModelAndView("htmlTest");
- *modelAndView.addObject("STATICHTML",false);
- */
- if(Boolean.FALSE.equals(model.get("STATIC_HTML"))){
- processTemplate(getTemplate(locale),fmModel,response);
- }else{
- createHTML(getTemplate(locale),fmModel,request,response);
- }
- }
- publicvoidcreateHTML(Templatetemplate,SimpleHashmodel,HttpServletRequestrequest,
- HttpServletResponseresponse)throwsIOException,TemplateException,ServletException{
- //站点根目录的绝对路径
- StringbasePath=request.getSession().getServletContext().getRealPath("/");
- StringrequestHTML=this.getRequestHTML(request);
- //静态页面绝对路径
- StringhtmlPath=basePath+requestHTML;
- FilehtmlFile=newFile(htmlPath);
- if(!htmlFile.getParentFile().exists()){
- htmlFile.getParentFile().mkdirs();
- }
- /**
- *如果静态页面已经存在,就不再创建静态页面.
- */
- if(!htmlFile.exists()){
- htmlFile.createNewFile();
- Writerout=newBufferedWriter(newOutputStreamWriter(newFileOutputStream(htmlFile),"UTF-8"));
- //处理模版
- template.process(model,out);
- out.flush();
- out.close();
- }
- /*将请求转发到生成的htm文件*/
- request.getRequestDispatcher(requestHTML).forward(request,response);
- }
- /**
- *计算要生成的静态文件相对路径.
- */
- privateStringgetRequestHTML(HttpServletRequestrequest){
- //web应用名称,部署在ROOT目录时为空
- StringcontextPath=request.getContextPath();
- //web应用/目录/文件.do
- StringrequestURI=request.getRequestURI();
- //basePath里面已经有了web应用名称,所以直接把它replace掉,以免重复
- requestURI=requestURI.replaceFirst(contextPath,"");
- //将.do改为.htm,稍后将请求转发到此htm文件
- requestURI=requestURI.substring(0,requestURI.indexOf("."))+".htm";
- returnrequestURI;
- }
- }
这里我们取出STATIC_HTML的值,当为false是就不生成静态页面.
而getRequestHTML()方法是生成静态页面的相对路径,这里我们可以灵活处理,可以决定静态页面的存放路径.
第三步:配置spring mvc配置文件,这里我的文件名为springmvc.xml
- <?xmlversion="1.0"encoding="UTF-8"?>
- <beansxmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:p="http://www.springframework.org/schema/p"
- xmlns:context="http://www.springframework.org/schema/context"
- xmlns:mvc="http://www.springframework.org/schema/mvc"
- xsi:schemaLocation="
- http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
- http://www.springframework.org/schema/context
- http://www.springframework.org/schema/context/spring-context-3.0.xsd
- http://www.springframework.org/schema/mvc
- http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
- <!--开启注解扫描功能-->
- <context:component-scanbase-package="gd.hz.controller"></context:component-scan>
- <!--将上面两个注解和并-->
- <mvc:annotation-driven/>
- <!--freemarker页面解析器-->
- <beanid="viewResolver"
- class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
- <propertyname="suffix"value=".ftl"></property>
- <propertyname="contentType"value="text/html;charset=UTF-8"/>
- <!--<propertyname="viewClass"value="org.springframework.web.servlet.view.freemarker.FreeMarkerView"/>-->
- <!--将Spring的FreeMarkerView改成我们扩展的View-->
- <propertyname="viewClass"value="gd.hz.ExFreeMarkerView"/>
- <propertyname="exposeRequestAttributes"value="true"/>
- <propertyname="exposeSessionAttributes"value="true"/>
- <propertyname="exposeSpringMacroHelpers"value="true"/>
- </bean>
- <beanid="fmXmlEscape"class="freemarker.template.utility.XmlEscape"/>
- <!--配置Freemarker-->
- <beanid="freemarkerConfigurer"
- class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
- <!--模版页面存放的位置-->
- <propertyname="templateLoaderPath"value="/ftl/"></property>
- <propertyname="freemarkerVariables">
- <map>
- <entrykey="xml_escape"value-ref="fmXmlEscape"/>
- </map>
- </property>
- <propertyname="freemarkerSettings">
- <props>
- <propkey="template_update_delay">10</prop>
- <propkey="defaultEncoding">UTF-8</prop>
- </props>
- </property>
- </bean>
- <!--下面要声明在模版后面-->
- <bean
- class="org.springframework.web.servlet.view.InternalResourceViewResolver">
- <!--JSP页面存放的位置-->
- <propertyname="prefix"value="/jsp/"/>
- <propertyname="suffix"value=".jsp"/>
- </bean>
- </beans>
这里页面额外说明的是,如果我们想一个网站有使用freeMarker和jsp时,也可以在配置文件中声明如:
- <bean
- class="org.springframework.web.servlet.view.InternalResourceViewResolver">
- <!--JSP页面存放的位置-->
- <propertyname="prefix"value="/jsp/"/>
- <propertyname="suffix"value=".jsp"/>
- </bean>
这句话要声明在使用freeMarker配置下面,这样当处sping 找不到相关页面模板时就会找相关名称的jsp页面.另外还需要声明使用我们扩展的ExFreeMarkerView.
第四步:创建测试页:
模板页:
- <!DOCTYPEhtmlPUBLIC"-//W3C//DTDHTML4.01Transitional//EN""http://www.w3.org/TR/html4/loose.dtd">
- <html>
- <head>
- <metahttp-equiv="Content-Type"content="text/html;charset=UTF-8">
- <title></title>
- </head>
- <body>
- ${content}
- </body>
- </html>
JSP页面:
- <%@pagelanguage="java"contentType="text/html;charset=UTF-8"
- pageEncoding="UTF-8"%>
- <!DOCTYPEhtmlPUBLIC"-//W3C//DTDHTML4.01Transitional//EN""http://www.w3.org/TR/html4/loose.dtd">
- <html>
- <head>
- <metahttp-equiv="Content-Type"content="text/html;charset=UTF-8">
- <title></title>
- </head>
- <body>
- 我是从jsp过来的.${content}
- </body>
- </html
第五步:Controller
- packagegd.hz.controller;
- importorg.springframework.stereotype.Controller;
- importorg.springframework.web.bind.annotation.RequestMapping;
- importorg.springframework.web.servlet.ModelAndView;
- @Controller("indexController")
- publicclassIndexController{
- @RequestMapping("index")
- publicModelAndViewindex(){
- ModelAndViewmodelAndView=newModelAndView("index");
- modelAndView.addObject("content","网站标题");
- //当设置false时不生成静态页面
- modelAndView.addObject("STATIC_HTML",false);
- returnmodelAndView;
- }
- @RequestMapping("html/index")
- publicModelAndViewhtmlIndex(){
- ModelAndViewmodelAndView=newModelAndView("index");
- //默认是生成静态页面的
- modelAndView.addObject("content","网站标题");
- returnmodelAndView;
- }
- //jsp测试
- @RequestMapping("jsp/index")
- publicModelAndViewjspindex(){
- ModelAndViewmodelAndView=newModelAndView("test");
- modelAndView.addObject("content","网站标题");
- returnmodelAndView;
- }
- }
首先看一下第一个请求,这里我们声明STATIC_HTML=false,不生成静态页面.第二个请求,我们生成的静态页面,根据ExFreeMarkerView中的定义,会跳转到静态页面.
第三个请求,因为没有test.ftl,这样spring 会去找test.jsp页面,所发请求会到test.jsp.
经过上面的三种方法,我们使用在进行大型网站开发时,可以灵活运用,可以在页面的某些数据变化少的地方进行部分页面静态化.也可以根据需求,只请求JSP页面.