• 使用Freemarker 实现JSP页面的静态化


    使用Freemarker 静态化网页

    一、原理

     Freemarker 生成静态页面,首先需要使用自己定义的模板页面,这个模板页面可以是最最普通的html,也可以是嵌套freemarker中的 取值表达式, 标签或者自定义标签等等,然后后台读取这个模板页面,解析其中的标签完成相对应的操作, 然后采用键值对的方式传递参数替换模板中的的取值表达式,做完之后 根据配置的路径生成一个新的html页面, 以达到静态化访问的目的。

    二、Freemaker提供的标签

    Freemarker提供了很多有用 常用的标签,具体可以分为三个部分:Freemarker标签都是类似Html标签,不同的是它是为了与HTML标记区分,用#开始。例如<#标签名称>;${value} 表示输出变量名的内容 ;注释:包含在<#---->(而不是<!---->)之间;

    三、Freemaker实现网页静态化DEMO

    Freemarker是一种基于模板的、用来生成输出文本的通用工具,所以我们必须要定制符合自己业务的模板出来,然后生成的我们得html页面

    这个例子中我们会Freemarker生成一个html文件 包括html的头部和尾部,以及body,这三个部分会分别对应三个模板文件:

    Body.ftl
    
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">  
    
    <html>  
    
      <head>  
    
        <title>用户列表</title>  
    
          
    
        <meta http-equiv="pragma" content="no-cache">  
    
        <meta http-equiv="cache-control" content="no-cache">  
    
        <meta http-equiv="expires" content="0">      
    
        <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">  
    
        <meta http-equiv="description" content="This is my page">  
    
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />  
    
        <!--  
    
        <link rel="stylesheet" type="text/css" href="styles.css">  
    
        -->  
    
       
    
      </head>  
    
        
    
      <body>  
    
      <#include "header.ftl" parse=true encoding="utf-8">  
    
      <hr/>  
    
      <a href="#">用户列表</a><br/>  
    
      <table border="1">  
    
        <tr>  
    
            <td>用户名</td>  
    
            <td>年龄</td>  
    
            <td>生日</td>  
    
            <td>id</td>  
    
            <td>操作</td>  
    
        </tr>  
    
        <#list users as user>  
    
            <tr>  
    
                <td>${user.name}</td>  
    
                <td>${user.age}</td>  
    
                <td>  
    
                ${user.birthday?string("yyyy-MM-dd HH:mm:ss")}  
    
                </td>  
    
                <td>${user.id}</td>  
    
                <td><a href="http://localhost:8082/JspToHtml/DelUser.do?id=${user.id}">删除</a></td>  
    
            </tr>  
    
        </#list>  
    
          
    
      </table>  
    
    <hr/>  
    
      <#include "footer.ftl" parse=true encoding="utf-8">  
    
      </body>  
    
    </html>  
    
    Footer.ftl
    
    ${f.des}<br/> 
    
    Header.ftl
    
    company:${h.companyName}<br/>  
    
    address:${h.address}<br/>  
    
    它们对于的实体类分别是:
    
    User.java
    
    package com.cys.jsptohtml.schema;
    
     
    
    import java.util.Date;  
    
     
    
    public class User {  
    
          
    
        private Integer id;  
    
      
    
        private String name ;  
    
          
    
        private int age;  
    
          
    
        private Date birthday;  
    
      
    
        public String getName() {  
    
            return name;  
    
        }  
    
      
    
        public void setName(String name) {  
    
            this.name = name;  
    
        }  
    
      
    
        public int getAge() {  
    
            return age;  
    
        }  
    
      
    
        public void setAge(int age) {  
    
            this.age = age;  
    
        }  
    
      
    
        public Date getBirthday() {  
    
            return birthday;  
    
        }  
    
      
    
        public void setBirthday(Date birthday) {  
    
            this.birthday = birthday;  
    
        }  
    
      
    
          
    
        public Integer getId() {  
    
            return id;  
    
        }  
    
      
    
        public void setId(Integer id) {  
    
            this.id = id;  
    
        }  
    
      
    
        public User(Integer id,String name, int age, Date birthday) {  
    
            super();  
    
            this.name = name;  
    
            this.age = age;  
    
            this.birthday = birthday;  
    
            this.id = id;  
    
        }  
    
      
    
        public User() {  
    
            super();  
    
        }  
    
          
    
          
    
    }  
    
    Header.java
    
    package com.cys.jsptohtml.schema;
    
     
    
     
    
    public class Header {  
    
      
    
        private String companyName;  
    
          
    
        private String address;  
    
      
    
        public String getCompanyName() {  
    
            return companyName;  
    
        }  
    
      
    
        public void setCompanyName(String companyName) {  
    
            this.companyName = companyName;  
    
        }  
    
      
    
        public String getAddress() {  
    
            return address;  
    
        }  
    
      
    
        public void setAddress(String address) {  
    
            this.address = address;  
    
        }        
    
    }  
    
    Footer.java
    
    package com.cys.jsptohtml.schema;
    
     
    
     
    
    public class Header {  
    
      
    
        private String companyName;  
    
          
    
        private String address;  
    
      
    
        public String getCompanyName() {  
    
            return companyName;  
    
        }  
    
      
    
        public void setCompanyName(String companyName) {  
    
            this.companyName = companyName;  
    
        }  
    
      
    
        public String getAddress() {  
    
            return address;  
    
        }  
    
      
    
        public void setAddress(String address) {  
    
            this.address = address;  
    
        }   
    
    }  
    
    对应的Service有(在Service中模仿了数据库操作):
    
    UserService.java:
    
    package com.cys.jsptohtml.service;
    
     
    
    import java.util.ArrayList;
    
    import java.util.Date;
    
    import java.util.List;
    
     
    
    import com.cys.jsptohtml.schema.User;
    
     
    
    public class UserService {  
    
      
    
        private static List<User> users = new ArrayList<User>();  
    
          
    
        static{  
    
            for(int i=0;i<10;i++){  
    
                User u = new User(i,"cys"+i,i+10,new Date());  
    
                users.add(u);  
    
            }  
    
        }  
    
          
    
        public static List<User> getUsers(){  
    
            return users;  
    
        }  
    
          
    
        public static void delete(int index){  
    
            for(int i=0 ;i<users.size();i++){  
    
                User u = users.get(i);  
    
                if(u.getId()==index){  
    
                    users.remove(u);  
    
                    //users.remove(index);  
    
                }  
    
            }  
    
        }  
    
    }   
    
    HeaderService.java
    
    package com.cys.jsptohtml.service;
    
     
    
    import com.cys.jsptohtml.schema.Header;
    
     
    
    public class HeaderService {  
    
      
    
        private static Header h = new Header();  
    
          
    
        static{  
    
            h.setAddress("中关村东路");  
    
            h.setCompanyName("中科软");  
    
        }  
    
          
    
        public static void update(String address,String companyName){  
    
            h.setAddress(address);  
    
            h.setCompanyName(companyName);  
    
        }  
    
          
    
        public static Header getHeader(){  
    
            return h;  
    
        }  
    
    }  
    
    FooterService.java
    
    package com.cys.jsptohtml.service;
    
     
    
    import com.cys.jsptohtml.schema.Footer;
    
     
    
     
    
     
    
    public class FooterService {  
    
      
    
        private static Footer f = new Footer();  
    
        static{  
    
            f.setDes("这是底部");  
    
        }  
    
          
    
        public static void update(String des){  
    
            f.setDes(des);  
    
        }  
    
          
    
        public static Footer gerFooter(){  
    
            return f;  
    
        }  
    
    }  
    
    Servlet操作:
    
    DelUser.java
    
    package com.cys.jsptohtml.servlet;
    
     
    
    import java.io.File;
    
    import java.io.FileOutputStream;
    
    import java.io.FilenameFilter;
    
    import java.io.IOException;
    
    import java.io.OutputStreamWriter;
    
    import java.io.Writer;
    
    import java.util.UUID;
    
     
    
    import javax.servlet.ServletException;
    
    import javax.servlet.http.HttpServlet;
    
    import javax.servlet.http.HttpServletRequest;
    
    import javax.servlet.http.HttpServletResponse;
    
     
    
    import com.cys.jsptohtml.service.UserService;
    
    import com.cys.jsptohtml.util.ProcessClient;
    
      
    
    /** 
    
     * @author cys 
    
     **/  
    
    @SuppressWarnings("serial")
    
    public class DelUser extends HttpServlet {  
    
      
    
          
    
        public void doGet(HttpServletRequest request, HttpServletResponse response)  
    
                throws ServletException, IOException {  
    
                this.doPost(request, response);  
    
        }  
    
      
    
        //删除用户  
    
        public void doPost(HttpServletRequest request, HttpServletResponse response)  
    
                throws ServletException, IOException {  
    
             System.out.println("Del dopost");
    
            String id = request.getParameter("id");  
    
            UserService.delete(Integer.valueOf(id));  
    
              
    
            //生成html的位置  
    
            String dirPath = request.getSession().getServletContext().getRealPath("/templateDir/html");  
    
            //文件名字  
    
            String indexFileName = "index.html";  
    
              
    
            //删除原来的文件  
    
            delOldHtml(dirPath,indexFileName);  
    
              
    
            //防止浏览器缓存,用于重新生成新的html  
    
            UUID uuid = UUID.randomUUID();  
    
            Writer out = new OutputStreamWriter(new FileOutputStream(dirPath+"/"+uuid+indexFileName),"UTF-8");  
    
            ProcessClient.processBody(out, "body.ftl");
    
            response.sendRedirect("templateDir/html/"+uuid+"index.html");  
    
        }  
    
          
    
        /** 
    
         * 删除原来的html文件 
    
         * @param htmlDir 
    
         * @param htmlName 
    
         */  
    
        private void delOldHtml(String htmlDir,String htmlName){  
    
            File path = new File(htmlDir);  
    
            String[] indexfileList = path.list(new FilenameFilter(){
    
     
    
    public boolean accept(File dir, String name) {
    
    return name.endsWith(".html");
    
    }
    
            
    
            });  
    
            if(indexfileList.length>0){  
    
                for(String f:indexfileList){  
    
                    File delf = new File(htmlDir+"/"+f);  
    
                    delf.delete();  
    
                }  
    
            }  
    
        }  
    
      
    
    }
    
    JspToHtmlServlet.java
    
    package com.cys.jsptohtml.servlet;
    
     
    
    import java.io.File;
    
    import java.io.FileOutputStream;
    
    import java.io.FilenameFilter;
    
    import java.io.IOException;
    
    import java.io.OutputStreamWriter;
    
    import java.io.Writer;
    
     
    
    import javax.servlet.ServletException;
    
    import javax.servlet.http.HttpServlet;
    
    import javax.servlet.http.HttpServletRequest;
    
    import javax.servlet.http.HttpServletResponse;
    
     
    
    import com.cys.jsptohtml.util.ProcessClient;
    
     
    
    public class JspToHtmlServlet extends HttpServlet{
    
     
    
    private static final long serialVersionUID = 1L;
    
     
    
    public JspToHtmlServlet() {  
    
            super();  
    
        }  
    
     
    
        public void doGet(HttpServletRequest request,HttpServletResponse response)  
    
                throws ServletException, IOException {  
    
         System.out.println("doget");
    
            this.doPost(request, response);  
    
        }  
    
      
    
          
    
    public void doPost(HttpServletRequest request, 
    
    HttpServletResponse response)  
    
                throws ServletException, IOException {  
    
         System.out.println("doPost");
    
            // html生成之后存放的路径
    
            String dirPath = request.getSession().getServletContext().getRealPath("/templateDir/html");  
    
            File path = new File(dirPath);  
    
            // 生成的文件的名字
    
            String indexFileName = "index.html";  
    
            /**
    
     * 判断是否已经存在该html文件,存在了就直接访问html ,不存在生成html文件
    
     */  
    
            String[] indexfileList = path.list(new FilenameFilter(){
    
     
    
    public boolean accept(File dir, String name) {
    
    return name.endsWith(".html");
    
    }
    
            });
    
            System.out.println(indexfileList);
    
            if(indexfileList.length<=0){  
    
                Writer out = new OutputStreamWriter(new FileOutputStream(dirPath+"/"+indexFileName),"UTF-8"); 
    
                // 生成html文件
    
                ProcessClient.processBody(out,"body.ftl");  
    
                request.getRequestDispatcher("/templateDir/html/index.html").forward(request, response);   
    
            }else{  
    
                request.getRequestDispatcher("/templateDir/html/"+indexfileList[0]).forward(request, response);   
    
            }  
    
     
    
     
    
    }
    
    }
    
    Login.java(该类用于测试环境,与静态化无关)
    
    package com.cys.jsptohtml.servlet;
    
     
    
    import java.io.IOException;
    
     
    
    import javax.servlet.ServletException;
    
    import javax.servlet.http.HttpServlet;
    
    import javax.servlet.http.HttpServletRequest;
    
    import javax.servlet.http.HttpServletResponse;
    
     
    
    public class Login extends HttpServlet{
    
        private static final long serialVersionUID = 7474850489594438527L;  
    
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
            doPost(request, response);
    
        }
    
     
    
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
            request.setCharacterEncoding("UTF-8");  
    
            response.setContentType("text/html;charset=utf-8");
    
            
    
            String action = request.getParameter("action");  
    
            if("login_input".equals(action)) {  
    
                request.getRequestDispatcher("login.jsp").forward(request , response);  
    
            } else if("login".equals(action)) {  
    
                String name = request.getParameter("name");  
    
                String password = request.getParameter("password");  
    
                  
    
                System.out.println("name->" + name + ",password->" + password);
    
            }
    
        }
    
     
    
    }
    
    Jsp页面:
    
    Index.jsp
    
    <%@ page language="java" contentType="text/html; charset=UTF-8"
    
        pageEncoding="UTF-8"%>
    
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    
    <html>
    
    <head>
    
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    
    <title>Insert title here</title>
    
    </head>
    
    <body>
    
        <p>用Maven创建web项目,测试Servlet</p>
    
        <a href="demo?action=login_input">登录(demo?action=login_input)</a>
    
        <a href="index?action=login_input">静态化</a>
    
    </body>
    
    </html>
    
    Login.jsp
    
    <%@ page language="java" contentType="text/html; charset=UTF-8"
    
        pageEncoding="UTF-8"%>
    
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    
    <html>
    
    <head>
    
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    
    <title>Insert title here</title>
    
    </head>
    
    <body>
    
        <form action="demo?action=login" method="post">  
    
            Name:<input type="text" name="name" />  
    
            Password:<input type="password" name="password" />  
    
                  
    
            <input type="submit" value="登录" />  
    
        </form>  
    
    </body>
    
    </html>
    
    Web.xml
    
    <?xml version="1.0" encoding="UTF-8"?>
    
    <web-app xmlns:javaee="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
    
      <javaee:display-name>Archetype Created Web Application</javaee:display-name>
    
      <servlet>
    
        <javaee:description></javaee:description>
    
        <javaee:display-name>ServletDemo</javaee:display-name>
    
        <servlet-name>ServletDemo</servlet-name>
    
        <servlet-class>com.cys.jsptohtml.servlet.Login</servlet-class>
    
      </servlet>
    
      <servlet-mapping>
    
        <servlet-name>ServletDemo</servlet-name>
    
        <url-pattern>/demo</url-pattern>
    
      </servlet-mapping>
    
      
    
      <servlet>  
    
       <servlet-name>Index</servlet-name>  
    
       <servlet-class>com.cys.jsptohtml.servlet.JspToHtmlServlet</servlet-class>  
    
       <load-on-startup>3</load-on-startup>
    
     </servlet>  
    
      
    
     <servlet-mapping>  
    
       <servlet-name>Index</servlet-name>  
    
       <url-pattern>/index</url-pattern>  
    
     </servlet-mapping> 
    
     
    
      <servlet>  
    
       <servlet-name>DelUser</servlet-name>  
    
       <servlet-class>com.cys.jsptohtml.servlet.DelUser</servlet-class>  
    
       <load-on-startup>3</load-on-startup>
    
     </servlet>  
    
      
    
     <servlet-mapping>  
    
       <servlet-name>DelUser</servlet-name>  
    
       <url-pattern>/DelUser.do</url-pattern>  
    
     </servlet-mapping> 
    
    </web-app>
    
    Util类:
    
    FreeMarkertUtil .java
    
    package com.cys.jsptohtml.util;
    
    import java.io.IOException;
    
    import java.io.Writer;
    
    import java.util.Map;
    
     
    
    import freemarker.template.Configuration;
    
    import freemarker.template.Template;
    
    import freemarker.template.TemplateException;
    
     
    
    public class FreeMarkertUtil {
    
     
    
    public Template getTemplate(String name) {
    
            try {
    
                // 通过Freemaker的Configuration读取相应的ftl
    
                Configuration cfg = new Configuration();
    
                // 设定去哪里读取相应的ftl模板文件
    
                cfg.setClassForTemplateLoading(this.getClass(), "ftl");
    
                // 在模板文件目录中找到名称为name的文件
    
                Template temp = cfg.getTemplate(name);
    
                System.out.println(temp.getName());
    
                return temp;
    
            } catch (IOException e) {
    
                e.printStackTrace();
    
            }
    
            return null;
    
        }
    
        /** 
    
         * @param templateName 模板名字 
    
         * @param root 模板根 用于在模板内输出结果集 
    
         * @param out 输出对象 具体输出到哪里 
    
         */  
    
        public  void processTemplate(Template template,Map<?,?> root, Writer out){  
    
            try{  
    
             System.out.println("processTemplate");
    
                template.process(root, out);   
    
                out.flush();     
    
            } catch (IOException e) {  
    
                e.printStackTrace();  
    
            } catch (TemplateException e) {  
    
                e.printStackTrace();  
    
            }finally{  
    
                 try {  
    
                    out.close();  
    
                    out=null;  
    
                } catch (IOException e) {  
    
                    e.printStackTrace();  
    
                }  
    
            }  
    
        }  
    
    }
    
    在该类中加载模板的方式有多种:
    
    void setDirectoryForTemplateLoading(File dir);// 根据全路径加载
    void setClassForTemplateLoading(Class cl, String prefix);//根据类的路径加载,prefix为模板前缀
    
    void setServletContextForTemplateLoading(Object servletContext, String path); //根据web上下文
    
    从多地址加载模板
    
    import freemarker.cache.*; // 模板加载器在这个包下  
    
    ...  
    
    FileTemplateLoader ftl1 = new FileTemplateLoader(new File("/tmp/templates"));  
    
    FileTemplateLoader ftl2 = new FileTemplateLoader(new File("/usr/data/templates"));  
    
    ClassTemplateLoader ctl = new ClassTemplateLoader(getClass(),"");  
    
    TemplateLoader[] loaders = new TemplateLoader[] { ftl1, ftl2,ctl };  
    
    MultiTemplateLoader mtl = new MultiTemplateLoader(loaders);  
    
    cfg.setTemplateLoader(mtl);  
    
    现在,FreeMarker 将会尝试从/tmp/templates 目录加载模板,如果在这个目录下没有发现请求的模板,它就会继续尝试从/usr/data/templates 目录下加载,如果还是没有发现请求的模板,那么它就会使用类加载器来加载模板。
    
     
    
    ProcessClient .java
    
     
    
    package com.cys.jsptohtml.util;
    
     
    
    import java.io.Writer;
    
    import java.util.HashMap;
    
    import java.util.List;
    
    import java.util.Map;
    
     
    
    import com.cys.jsptohtml.schema.Footer;
    
    import com.cys.jsptohtml.schema.Header;
    
    import com.cys.jsptohtml.schema.User;
    
    import com.cys.jsptohtml.service.FooterService;
    
    import com.cys.jsptohtml.service.HeaderService;
    
    import com.cys.jsptohtml.service.UserService;
    
     
    
    import freemarker.template.Template;
    
      
    
     
    
      
    
    /** 
    
     * @author cys  
    
     **/  
    
    public class ProcessClient {  
    
     
    
        private static Map<String,Object> root = new HashMap<String,Object>();  
    
      
    
        /** 
    
         * 调用FreeMarkertUtil.java 
    
         * FreeMarkertUtil.processTemplate("body.ftl", root, out); 
    
         * 来生成html文件 
    
         * @param out 
    
         */  
    
        public static void processBody(Writer out,String filename){  
    
            Header h = HeaderService.getHeader();  
    
            root.put("h", h);  
    
            Footer f = FooterService.gerFooter();  
    
            root.put("f", f);  
    
            List<User> users = UserService.getUsers();  
    
            root.put("users", users);
    
            FreeMarkertUtil freeMarkertUtil = new FreeMarkertUtil();
    
            Template template = freeMarkertUtil.getTemplate(filename);
    
            freeMarkertUtil.processTemplate(template, root, out);
    
        }  
    
    }
    
     
    
    Pom.xml(对应的jar包,以及插件):
    
     
    
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    
      xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    
      <modelVersion>4.0.0</modelVersion>
    
      <groupId>com.cys</groupId>
    
      <artifactId>JspToHtml</artifactId>
    
      <packaging>war</packaging>
    
      <version>0.0.1-SNAPSHOT</version>
    
      <name>JspToHtml Maven Webapp</name>
    
      <url>http://maven.apache.org</url>
    
      <dependencies>
    
        <dependency>
    
          <groupId>junit</groupId>
    
          <artifactId>junit</artifactId>
    
          <version>3.8.1</version>
    
          <scope>test</scope>
    
        </dependency>
    
       <dependency>    
    
         <groupId>javax.servlet</groupId>    
    
         <artifactId>servlet-api</artifactId>    
    
         <version>2.5</version>    
    
         <scope>provided</scope>    
    
        </dependency>
    
        <dependency>
    
        <groupId>javax.servlet.jsp</groupId>
    
        <artifactId>jsp-api</artifactId>
    
        <version>2.1</version>
    
        <scope>provided</scope>
    
    </dependency>
    
    <dependency>
    
      <groupId>org.freemarker</groupId>
    
      <artifactId>freemarker</artifactId>
    
      <version>2.3.23</version>
    
    </dependency>
    
      </dependencies>
    
       <build>
    
        <finalName>codingdream</finalName>
    
        <plugins>
    
          <plugin>
    
    <groupId>org.codehaus.mojo</groupId>
    
    <artifactId>tomcat-maven-plugin</artifactId>
    
    <version>1.1</version>
    
    <configuration>
    
        <path></path>
    
        <port>8082</port>
    
        <uriEncoding>UTF-8</uriEncoding>
    
        <url>http://localhost:8087/codingdream</url>
    
        <server>tomcat6</server>
    
    </configuration>
    
    </plugin>
    
        </plugins>
    
      </build>
    
    </project>

    四、运行结果

     

     maven相关问题请参考:http://www.cnblogs.com/caoyusongnet/p/5150882.html

    参考:http://freemarker.incubator.apache.org/

      http://blog.csdn.net/ajun_studio/article/details/6932185/

       

  • 相关阅读:
    javascript中优雅的处理async和await异常
    CSS旋转动画和动画的拼接
    我这个人有哪些优点,有哪些缺点
    electron内监控目标网站cookie的变化,查找指定的cookie
    监控ckeditor内容变化,删除编辑器内图片,ueditor同样适用
    大型政务应用或企业应用平台建设漫谈【一】
    javascript中的闭包、函数的toString方法
    在【用户、角色、权限】模块中如何查询不拥有某角色的用户
    javascript中bind绑定接收者与函数柯里化
    centos安装mongodb 4.x及配置用户名密码(官方推荐的方式)
  • 原文地址:https://www.cnblogs.com/caoyusongnet/p/5150850.html
Copyright © 2020-2023  润新知