├── .classpath ├── .gitignore ├── .project ├── .settings ├── .jsdtscope ├── org.eclipse.jdt.core.prefs ├── org.eclipse.m2e.core.prefs ├── org.eclipse.wst.common.component ├── org.eclipse.wst.common.project.facet.core.xml ├── org.eclipse.wst.jsdt.ui.superType.container ├── org.eclipse.wst.jsdt.ui.superType.name └── org.eclipse.wst.validation.prefs ├── README.md ├── pom.xml └── src └── main ├── java ├── com │ └── zhangguo │ │ └── springmvc71 │ │ ├── Services │ │ └── ArticleService.java │ │ ├── actions │ │ └── News.java │ │ ├── demo │ │ └── HelloWorld.java │ │ └── entities │ │ └── Article.java └── templates │ ├── news.ftl │ ├── newsList.ftl │ └── product.ftl └── webapp ├── META-INF └── MANIFEST.MF ├── WEB-INF └── web.xml └── index.jsp /.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | SpringMVC71 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.wst.jsdt.core.javascriptValidator 10 | 11 | 12 | 13 | 14 | org.eclipse.jdt.core.javabuilder 15 | 16 | 17 | 18 | 19 | org.eclipse.wst.common.project.facet.core.builder 20 | 21 | 22 | 23 | 24 | org.eclipse.m2e.core.maven2Builder 25 | 26 | 27 | 28 | 29 | org.eclipse.wst.validation.validationbuilder 30 | 31 | 32 | 33 | 34 | 35 | org.eclipse.jem.workbench.JavaEMFNature 36 | org.eclipse.wst.common.modulecore.ModuleCoreNature 37 | org.eclipse.jdt.core.javanature 38 | org.eclipse.m2e.core.maven2Nature 39 | org.eclipse.wst.common.project.facet.core.nature 40 | org.eclipse.wst.jsdt.core.jsNature 41 | 42 | 43 | -------------------------------------------------------------------------------- /.settings/.jsdtscope: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled 3 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7 4 | org.eclipse.jdt.core.compiler.compliance=1.7 5 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error 6 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error 7 | org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning 8 | org.eclipse.jdt.core.compiler.source=1.7 9 | -------------------------------------------------------------------------------- /.settings/org.eclipse.m2e.core.prefs: -------------------------------------------------------------------------------- 1 | activeProfiles= 2 | eclipse.preferences.version=1 3 | resolveWorkspaceProjects=true 4 | version=1 5 | -------------------------------------------------------------------------------- /.settings/org.eclipse.wst.common.component: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.settings/org.eclipse.wst.common.project.facet.core.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.settings/org.eclipse.wst.jsdt.ui.superType.container: -------------------------------------------------------------------------------- 1 | org.eclipse.wst.jsdt.launching.baseBrowserLibrary -------------------------------------------------------------------------------- /.settings/org.eclipse.wst.jsdt.ui.superType.name: -------------------------------------------------------------------------------- 1 | Window -------------------------------------------------------------------------------- /.settings/org.eclipse.wst.validation.prefs: -------------------------------------------------------------------------------- 1 | disabled=06target 2 | eclipse.preferences.version=1 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Spring_MVC_071 2 | 3 | 4 | Spring MVC 学习总结(七)——FreeMarker模板引擎与动态页面静态化 5 | 6 | 7 | 8 | http://www.cnblogs.com/best/p/5681511.html 9 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | com.zhangguo 5 | SpringMVC71 6 | 0.0.1-SNAPSHOT 7 | war 8 | 9 | 10 | 11 | org.freemarker 12 | freemarker-gae 13 | 2.3.25-incubating 14 | 15 | 16 | 17 | javax.servlet 18 | javax.servlet-api 19 | 3.0.1 20 | provided 21 | 22 | 23 | 24 | javax.servlet.jsp 25 | jsp-api 26 | 2.1 27 | provided 28 | 29 | 30 | -------------------------------------------------------------------------------- /src/main/java/com/zhangguo/springmvc71/Services/ArticleService.java: -------------------------------------------------------------------------------- 1 | package com.zhangguo.springmvc71.Services; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import com.zhangguo.springmvc71.entities.Article; 6 | 7 | /** 8 | * 文章业务类(模拟) 9 | * 10 | */ 11 | public class ArticleService { 12 | private static List
articles; 13 | 14 | static { 15 | articles = new ArrayList
(); 16 | articles.add(new Article(20160701, "不明真相的美国人被UFO惊呆了 其实是长征7号","据美国《洛杉矶时报》报道,当地时间周三晚(北京时间周四),在美国中西部的犹他州、内华达州、加利福利亚州,数千人被划过夜空的神秘火球吓到")); 17 | articles.add(new Article(20160702, "法国巴黎圣母院为教堂恐袭案遇害神父举行大弥撒", "而据美国战略司令部证实,其实这是中国长征七号火箭重新进入大气层,刚好经过加利福利亚附近。")); 18 | articles.add(new Article(20160703, "日东京知事候选人小池百合子回击石原:浓妆可以", "然而昨晚的美国人民可不明真相,有些人甚至怀疑这些火球是飞机解体,还有些人猜测是流星雨。")); 19 | articles.add(new Article(20160704, "日资慰安妇基金在首尔成立 韩国示威者闯入抗议","美国战略司令部发言人表示,到目前为止还没有任何受损报告,他说类似物体通常在大气中就会消失,这也解释了为何出现一道道光痕,这一切都并未造成什么威胁。")); 20 | articles.add(new Article(20160705, "中日关系正处十字路口日应寻求减少与华冲突","中国长征七号火箭6月25日在海南文昌航天发射中心首次发射,并成功升空进入轨道。有学者指出长征七号第二级火箭一直在地球低轨运行,一个月后重新进入大气层。")); 21 | } 22 | 23 | /** 24 | * 所有的文章 25 | */ 26 | public List
getArticles() { 27 | return articles; 28 | } 29 | 30 | /* 31 | * 获得文章通过文章编号 32 | */ 33 | public Article getArticle(int id) { 34 | for (Article article : articles) { 35 | if (article.getId() == id) { 36 | return article; 37 | } 38 | } 39 | return null; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/com/zhangguo/springmvc71/actions/News.java: -------------------------------------------------------------------------------- 1 | package com.zhangguo.springmvc71.actions; 2 | 3 | import java.io.File; 4 | import java.io.FileOutputStream; 5 | import java.io.IOException; 6 | import java.io.OutputStreamWriter; 7 | import java.io.Writer; 8 | import java.util.HashMap; 9 | import java.util.List; 10 | import java.util.Map; 11 | import javax.servlet.ServletException; 12 | import javax.servlet.annotation.WebServlet; 13 | import javax.servlet.http.HttpServlet; 14 | import javax.servlet.http.HttpServletRequest; 15 | import javax.servlet.http.HttpServletResponse; 16 | import com.zhangguo.springmvc71.Services.ArticleService; 17 | import com.zhangguo.springmvc71.entities.Article; 18 | import freemarker.template.Configuration; 19 | import freemarker.template.Template; 20 | import freemarker.template.TemplateException; 21 | 22 | /** 23 | *新闻列表 24 | */ 25 | @WebServlet("/News") 26 | public class News extends HttpServlet { 27 | private static final long serialVersionUID = 1L; 28 | 29 | ArticleService articleService=new ArticleService(); 30 | protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException{ 31 | //设置编码格式与MIME类型 32 | response.setContentType("text/html; charset=UTF-8"); 33 | 34 | //首页新闻列表路径 35 | String indexPath=request.getServletContext().getRealPath("/index.html"); 36 | 37 | //文件是否存在 38 | File file=new File(indexPath); 39 | if(!file.exists()){ 40 | //如果新闻列表不存在,生成新闻列表 41 | 42 | //创建一个freemarker.template.Configuration实例,它是存储 FreeMarker 应用级设置的核心部分 43 | //指定版本号 44 | Configuration cfg=new Configuration(Configuration.VERSION_2_3_22); 45 | //获得模板文件路径 46 | String templatePath=this.getClass().getClassLoader().getResource("/templates").getPath(); 47 | //设置模板目录 48 | cfg.setDirectoryForTemplateLoading(new File(templatePath)); 49 | //设置默认编码格式 50 | cfg.setDefaultEncoding("UTF-8"); 51 | 52 | //数据 53 | Map articleData = new HashMap<>(); 54 | List
articles=articleService.getArticles(); 55 | articleData.put("articles", articles); 56 | 57 | //从设置的目录中获得模板 58 | Template template = cfg.getTemplate("newsList.ftl"); 59 | 60 | //合并模板和数据模型 61 | try { 62 | //将数据与模板渲染的结果写入文件中 63 | Writer writer=new OutputStreamWriter(new FileOutputStream(file), "UTF-8"); 64 | template.process(articleData, writer); 65 | writer.flush(); 66 | 67 | articleData.clear(); 68 | template = cfg.getTemplate("news.ftl"); 69 | //生成单个新闻文件 70 | for (Article article : articles) { 71 | articleData.put("article", article); 72 | //单个新闻文件 73 | file=new File(request.getServletContext().getRealPath("/news/"+article.getId()+".html")); 74 | //文件输出流写入器 75 | writer=new OutputStreamWriter(new FileOutputStream(file), "UTF-8"); 76 | //将模板+数据生成的结果写入文件中,得到一个静态文件 77 | template.process(articleData, writer); 78 | writer.flush(); 79 | } 80 | writer.close(); 81 | } catch (TemplateException e) { 82 | e.printStackTrace(); 83 | } 84 | } 85 | //如果新闻单页下存在,生成新闻单页 86 | request.getRequestDispatcher("index.html").forward(request, response); 87 | } 88 | 89 | protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 90 | doGet(request, response); 91 | } 92 | 93 | } 94 | -------------------------------------------------------------------------------- /src/main/java/com/zhangguo/springmvc71/demo/HelloWorld.java: -------------------------------------------------------------------------------- 1 | package com.zhangguo.springmvc71.demo; 2 | 3 | import java.io.File; 4 | import java.io.IOException; 5 | import java.io.OutputStreamWriter; 6 | import java.io.Writer; 7 | import java.util.HashMap; 8 | import java.util.Map; 9 | 10 | import freemarker.template.Configuration; 11 | import freemarker.template.Template; 12 | 13 | public class HelloWorld { 14 | 15 | public static void main(String[] args) throws Exception { 16 | 17 | //创建一个freemarker.template.Configuration实例,它是存储 FreeMarker 应用级设置的核心部分 18 | //指定版本号 19 | Configuration cfg=new Configuration(Configuration.VERSION_2_3_22); 20 | //设置模板目录 21 | cfg.setDirectoryForTemplateLoading(new File("src/main/java/templates")); 22 | //设置默认编码格式 23 | cfg.setDefaultEncoding("UTF-8"); 24 | 25 | //数据 26 | Map product = new HashMap<>(); 27 | product.put("name", "Huwei P8"); 28 | product.put("price", "3985.7"); 29 | product.put("users", new String[]{"Tom","Jack","Rose"}); 30 | product.put("book","struts2,freemarker"); 31 | 32 | //从设置的目录中获得模板 33 | Template temp = cfg.getTemplate("product.ftl"); 34 | 35 | //合并模板和数据模型 36 | Writer out = new OutputStreamWriter(System.out); 37 | temp.process(product, out); 38 | 39 | //关闭 40 | out.flush(); 41 | out.close(); 42 | 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/com/zhangguo/springmvc71/entities/Article.java: -------------------------------------------------------------------------------- 1 | package com.zhangguo.springmvc71.entities; 2 | 3 | /** 4 | * 文章 5 | * 6 | */ 7 | public class Article { 8 | /* 9 | * 编号 10 | */ 11 | private int id; 12 | /* 13 | * 标题 14 | */ 15 | private String title; 16 | /* 17 | * 内容 18 | */ 19 | private String content; 20 | 21 | public Article() { 22 | } 23 | 24 | public Article(int id, String title, String content) { 25 | super(); 26 | this.id = id; 27 | this.title = title; 28 | this.content = content; 29 | } 30 | 31 | public int getId() { 32 | return id; 33 | } 34 | 35 | public void setId(int id) { 36 | this.id = id; 37 | } 38 | 39 | public String getTitle() { 40 | return title; 41 | } 42 | 43 | public void setTitle(String title) { 44 | this.title = title; 45 | } 46 | 47 | public String getContent() { 48 | return content; 49 | } 50 | 51 | public void setContent(String content) { 52 | this.content = content; 53 | } 54 | 55 | @Override 56 | public String toString() { 57 | return "Article [id=" + id + ", title=" + title + ", content=" + content + "]"; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/templates/news.ftl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ${article.title} 6 | 7 | 8 |
9 |

${article.title}

10 |

11 | ${article.content} 12 |

13 |
14 | 21 | 22 | -------------------------------------------------------------------------------- /src/main/java/templates/newsList.ftl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 新闻焦点 6 | 7 | 8 |
9 |

新闻焦点

10 | <#setting number_format="#"> 11 | 18 |
19 | 34 | 35 | -------------------------------------------------------------------------------- /src/main/java/templates/product.ftl: -------------------------------------------------------------------------------- 1 | ----------产品详细---------- 2 | 产品名称:${name} 3 | 产品价格:${price} 4 | 设计作者:<#list users as user> ${user} 5 | ------------------------------ 6 | 7 | <#assign test="Tom & Jerry"> 8 | ${test?html} 9 | ${test?upper_case?html} 10 | 11 | ${tom!"tom is missed"} 12 | <#if !jack??>jack is missed 13 | 14 | <#assign age=23> 15 | <#if (age>60)>老年人 16 | <#elseif (age>40)>中年人 17 | <#elseif (age>20)>青年人 18 | <#else> 少年人 19 | 20 | 21 | 22 | <#assign level=1> 23 | <#switch level> 24 | <#case 1>A级<#break> 25 | <#case 2>B级<#break> 26 | <#case 3>C级<#break> 27 | <#default>未知级别 28 | 29 | 30 | <#list ["星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期天"] as week> 31 | ${week_index + 1}.${week}<#if week_has_next>, 32 | <#if week="星期四"><#break> 33 | 34 | 35 | <#assign weeks> 36 | <#list ["星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期天"] as n> 37 | ${n} 38 | 39 | 40 | ${weeks} 41 | 42 | <#macro book> //定义一个自定义指令 43 | j2ee 44 | 45 | <@book /> //使用刚才定义的指令 46 | 47 | <#macro book booklist> //定义一个自定义指令booklist是参数 48 | <#list booklist as book> 49 | ${book} 50 | 51 | 52 | <@book booklist=["spring","j2ee"] /> //使用刚刚定义的指令 53 | 54 | 55 | <#macro book> 56 | <#nested 1> 57 | <#nested 2> 58 | <#nested 3> 59 | 60 | <@book ;index> ${index} .图书 61 | 62 | 63 | <#macro repeat count> 64 | <#list 1..count as x> 65 | <#nested x, x/2, x==count> 66 | 67 | 68 | 69 | <@repeat count=4 ;c,halfc,last> 70 | ${c}. ${halfc}<#if last> Last! 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /src/main/webapp/META-INF/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Class-Path: 3 | 4 | -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/web.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | index.html 8 | index.jsp 9 | 10 | -------------------------------------------------------------------------------- /src/main/webapp/index.jsp: -------------------------------------------------------------------------------- 1 | <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> 2 | --------------------------------------------------------------------------------