java-springmvc4+freemarker-实现layout布局页

来源:互联网 发布:linux qt5 usb热插拔 编辑:程序博客网 时间:2024/05/18 16:56
java-springmvc4+freemarker-实现layout布局页


使用 jsp 开发业务系统时,一般一个页面的js脚本针对当前页面的逻辑比较复杂无法公用,js 又常常更新。
客户端由于缓存问题,浏览器会缓存js到本地,不去下载最新的 js 文件(除非引用js时加版本号,如:order.js?v=1.0)


为了解决以上开发问题,可以将 js 写到 jsp 页面的下方,这样就可以每次加载页面时下载最新的 js 了。


但是,在开发时就不方便了。开发时经常需要看“html 结构”还要看“js 逻辑”,这时需要上下不停拖动jsp编辑器的滚动条。


为了解决上述问题:可以考虑在开发时,使 jsp 和 js 页面分离,再响应时将js文件合并到 jsp 中进行输出。


这样既保证了开发的时效和开发体验,也兼顾了客户端得不到最新js导致的各种问题。


下面,利用 maven + springmvc + freemarker 实现布局页,开发时将一个页面分割成三部分,使用时组合成一个页面输出:
1.layout 部分:只定义布局
2.js 部分:只定义当前页面使用的 js 脚本
3.body 部分:只定义页面中 body 标签内容的内容


约定:三部分必须有相同的前缀,如 order 页面,分为三部分时个文件的命名为:
1.layout 部分:orderLayout.ftl
2.js 部分:orderJs.js
3.body 部分:orderViewer.ftl


目标:实现两种 jsp 响应方式;
1.jsp(模板+数据)在请求时同时输出
2.只输出页面和js,数据使用 ajax 请求


前置:已经搭建好 springmvc + freemarker 项目,项目命名为 mavens-web


1.目录结构
1.1 后台代码目录
-demo
.+-mvc
..+-base
...|-PageController.java
..+-controllers
...|-HelloController.java


1.2 前端代码目录
-webapp
.+-views
..+-hello  //对应 controller 名
...+-js
....|-indexJs.js
....|-masterJs.js
...+-layout
....|-indexLayout.ftl
....|-masterLayout.ftl
...+-pub
....|-indexViewer.ftl
....|-masterViewer.ftl


2.controller 代码
2.1 控制器基类 PageController.java
package demo.mvc.base;import java.io.File;import java.util.Map;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.*;import freemarker.cache.*;/** **/public abstract class PageController {/** * 控制器名称,不包含“Controller”后缀 * @param controllerName */public PageController(String controllerName){ctrlName= controllerName.toLowerCase();}String ctrlName="";@Autowiredorg.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer _fmc;//static freemarker.cache.FileTemplateLoader _ftl = null;static String _templateLoaderPath=null;/** * 初始化 freemarker 模板地址 *  */boolean initTemplateLoaderPath() {if(_templateLoaderPath!=null)return true;gsPrintln("_fmc = {0}", _fmc==null?"null":_fmc.toString());//布局模板是否存在if(_fmc!=null){MultiTemplateLoader utll = (MultiTemplateLoader)_fmc.getConfiguration().getTemplateLoader();int n=utll.getTemplateLoaderCount();gsPrintln("TemplateLoaderCount="+n);TemplateLoader tl = null;File file = null;for(int i=0;i<n;i++) {tl= utll.getTemplateLoader(i);gsPrintln(tl.toString());//获取模板加载目录地址if(tl instanceof freemarker.cache.FileTemplateLoader){_templateLoaderPath = ((freemarker.cache.FileTemplateLoader)tl).getBaseDirectory().getAbsolutePath();}}}gsPrintln("freemark 模板地址:{0}", _templateLoaderPath);return _templateLoaderPath!=null;}/** * 判断模板是否存在 * @param filePath * @return */boolean IsExistsTemplate(String filePath){initTemplateLoaderPath();File file = new File(gsFormat("{0}/{1}", _templateLoaderPath,filePath));boolean exist = file.exists();gsPrintln("viewer[{1}]:{0}",file,exist);return exist;}/** * 公共视图解析器:controllerName/viewer/{file}/{prefix} * @param prefix * @param pars * @return */@RequestMapping("viewer/{prefix}")public String viewer(@PathVariable String prefix,Map<String, Object> pars){return freeMarkerViewResult(prefix, pars);//布局模板}/** * freemarker 布局视图解析 * @param prefix * @param pars * @return */public String freeMarkerViewResult(String prefix,Map<String, Object> pars){//布局模板String layout = gsFormat("{0}/layout/{1}Layout.ftl", ctrlName,prefix);//js内容String js = gsFormat("{0}/js/{1}Js.js", ctrlName,prefix);if(!IsExistsTemplate(js)){js="";//不存在时,地址赋值为空}//页模板String body = gsFormat("{0}/pub/{1}Viewer.ftl", ctrlName,prefix);//页面参数pars.put("body_file_path", body);pars.put("js_file_path", js);//优先使用布局页if(IsExistsTemplate(layout)){return layout.replaceAll("\\.ftl$", ""); //模板不需要后缀}return body.replaceAll("\\.ftl$", "");//模板不需要后缀}public static void gsPrintln(String msg, Object... args){System.out.println(gsFormat(msg,args));}/** * 字符串内容格式化输出,内部使用{0}\{1}\{2}...为参数占位符 * @param msg 格式化模板 * @param args 不固定参数 * @return */public static String gsFormat(String msg, Object... args){return java.text.MessageFormat.format(msg, args);}}




2.1 hello 控制器 HelloController.java
package demo.mvc.controllers;import java.util.ArrayList;import java.util.Date;import java.util.List;import java.util.Map;import org.springframework.mail.MailParseException;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import demo.models.hello.UserInfoModel;import demo.mvc.base.PageController;/** **/@Controller@RequestMapping("/hello")public class HelloController extends PageController {public HelloController(){super("Hello"); //将当前 controller 名传入,与 viewer 中的 hello 文件夹名对应}/** * 请求地址:项目名/hello/master * @return */@RequestMapping("master")public String freemarkerLayout(Map<String, Object> map){map.put("name", "张三");map.put("date", new Date());return this.freeMarkerViewResult("master", map);}}




3. js 文件
3.1 webapp/views/hello/js/indexJs.js
<script language="JavaScript">function init(){document.write("<div>这个是 indexJs.ftl 内容</div>");}init();</script>




3.2 webapp/views/hello/js/masterJs.js
<script language="JavaScript">function init(){document.write("<div>这个是 masterJs.ftl 内容</div>");}init();</script>




4. layout 布局文件
4.1 webapp/views/hello/layout/indexLayout.ftl
<!doctype html><html> <head>  <meta charset="UTF-8">  <meta name="Author" content="">  <meta name="Keywords" content="">  <meta name="Description" content="">  <title>index 布局页</title> </head> <body><#--body内容--><#include "${body_file_path}"> </body></html><#--js内容,不进行 ftl 解析;include 地址为空时,不抛出异常--><#include "${js_file_path}" parse=false ignore_missing=true>




4.2 webapp/views/hello/layout/masterLayout.ftl
<!doctype html><html> <head>  <meta charset="UTF-8">  <meta name="Author" content="">  <meta name="Keywords" content="">  <meta name="Description" content="">  <title>index 布局页</title> </head> <body><#--body内容--><#include "${body_file_path}"> </body></html><#--js内容,不进行 ftl 解析;include 地址为空时,不抛出异常--><#include "${js_file_path}" parse=false ignore_missing=true>




5. 页面 body 部分
5.1 webapp/views/hello/pub/indexViewer.ftl
<div>这个是 indexViewer.ftl 页面内容</div><#--模板+数据--><div></div>




5.2 views/hello/pub/masterViewer.ftl
<div>这个是 indexViewer.ftl 页面内容</div><#--模板+数据--><div></div>




6.部署到 tomcat 测试页面
6.1 jsp(模板+数据)在请求时同时输出
http://localhost:8080/mavens-web/hello/master
6.2 只输出页面和js,数据使用 ajax 请求(这种方式可以手动在tomcat添加页面,然后修改与之对应的前缀名即可访问到页面,这里index 即是前缀名)

http://localhost:8080/mavens-web/hello/viewer/index





0 0