java EE js css 加载及版本集中管理器
2016-03-03 17:41
579 查看
网站中大部分js css有重复的引用代码,生产环境中需要对新的js css版本做更新,此管理器实现了
1. js css 引用统一配置
2. 可方便地更新版本号
3. 引用路径支持相对路径、单一绝对路径、多域名绝对路径、是否使用.min格式
一、自定义控件
二、jsp引用js配置文件
三、 jsp引用css配置文件
四、jsp中加入相关代码
五、效果
1. js css 引用统一配置
2. 可方便地更新版本号
3. 引用路径支持相对路径、单一绝对路径、多域名绝对路径、是否使用.min格式
一、自定义控件
public class JavascriptLoader extends BodyTagSupport { private static final long serialVersionUID = 1L; /** * 控件参数1:用于匹配xxxLoader.xml中的定义 */ private String pageName; /** * 控件参数2:用于指定处理类型:js css */ private String fileType = "js"; // 以下变量会有变化,用于适用css js不同的处理类型 begin private String loaderXmlPathDef = "/WEB-INF/JavascriptLoader.xml";// xxxLoader.xml具体文件名 private String urlAttr = "src"; private String fullUrl1 = "<script type='text/javascript' src=\"{1}/{0}\"></script>"; private String fullUrl2 = "<script type='text/javascript' src=\"{0}{1}\"></script>"; private String fullUrl3 = "<script type='text/javascript' src=\"{1}/{0}\"></script>"; private String fullUrl4 = "<script type='text/javascript' src=\"{0}\"></script>"; private String jsRoot = "/" + fileType;// js文件所属目录,开头加/ private String minFileRoot = fileType + "/min";// js压缩后文件所属目录,开头不加/ private String minFileName = "{0}_min_{1}." + fileType;// outputType=3时生成压缩文件名 private String minFileString = "{0}/{1}/{2}_min_{3}." + fileType;// outputType=3时生成压缩文件完整路径,存放在minFileRoot对应目录下 private String tempFileString = "{0}/{1}/{2}_temp_{3}." + fileType;// outputType=3时生成临时合并文件文件格式,存放在minFileRoot对应目录下 private String deletedFilePattern = "{0}_min_\\d+." + fileType;// 需清除的旧的合并压缩文件的匹配正则表达式 private String commonEle = "script"; // end public JavascriptLoader() { } /** * 当前是否JS处理模式 * * @return */ private boolean forJS() { return (fileType == null || fileType.length() == 0 || fileType .equals( "js")); } @Override public int doEndTag() throws JspException { return super.doEndTag(); } @Override public int doStartTag() throws JspException { // 如果fileType为空,则默认当前为JS输出模式,否则为CSS输出模式 if (!forJS()) { loaderXmlPathDef = "/WEB-INF/CSSLoader.xml"; urlAttr = "href"; fullUrl1 = "<link href=\"{1}/{0}\" rel='stylesheet' type='text/css' />"; fullUrl2 = "<link href=\"{0}{1}\" rel='stylesheet' type='text/css' />"; fullUrl3 = "<link href=\"{1}/{0}\" rel='stylesheet' type='text/css' />"; fullUrl4 = "<link href=\"{0}\" rel='stylesheet' type='text/css' />"; jsRoot = "/" + fileType; minFileRoot = fileType + "/min"; minFileName = "{0}_min_{1}." + fileType; minFileString = "{0}/{1}/{2}_min_{3}." + fileType; tempFileString = "{0}/{1}/{2}_temp_{3}." + fileType; deletedFilePattern = "{0}_min_\\d+." + fileType; commonEle = "link"; } // web根目录的资源管理器路径 String dirPath = this.pageContext.getServletContext().getRealPath("/"); // web根目录的站点根路径 String urlPath = this.pageContext.getServletContext().getContextPath(); // 配置文件位置 String loaderXmlPath = dirPath + loaderXmlPathDef;// getClass().getClassLoader().getResource("JavascriptLoader.xml").getPath(); // 读取web.xml中的MergeAndCompress,判断是否所有资源按outputType=1的形式输出 String mergeAndCompress = this.pageContext.getServletContext() .getInitParameter("MergeAndCompress"); String useMinJsCss = this.pageContext.getServletContext() .getInitParameter("UseMinJsCss"); // 配置文件读取,所有CSS JS各一个文件 Document doc = LoaderTagSupport.getMessage(loaderXmlPath, fileType); Element root = XmlParser.getRootNode(doc); // 读取common节点 java.util.List<Element> commonList = XmlParser.getChildElements(root, "common/" + commonEle); Map<String, CommonScript> commonMap = new HashMap<String, CommonScript>(); if (commonList != null) { for (Element common : commonList) { Attribute outputTypeAttr = XmlParser.getAttribute(common, "outputType"); String name = XmlParser.getAttribute(common, "name").getText(); commonMap.put( name, new CommonScript(name, XmlParser.getAttribute(common, urlAttr).getText(), outputTypeAttr == null ? null : outputTypeAttr .getText())); } } // 读取server节点 java.util.List<Element> serverEleList = XmlParser.getChildElements( root, "servers/server"); List<String> serverList = new ArrayList<String>(); if (serverEleList != null) { for (Element server : serverEleList) { serverList.add(server.getText()); } } // 读配置文件对应page节点 Element page =(Element) XmlParser.getSingleNode(root, "page[@name='" + pageName + "']"); // page节点的所有子集,对于JS对于script节点,对于css对于link节点 List<Element> srcriptList =null; if(page!=null) srcriptList = XmlParser.getChildList(page); else { srcriptList=new ArrayList<Element>(); } // 判断outputType,根据outputType存入不同集合 List<String> outTypeList1 = new ArrayList<String>(); List<String> outTypeList2 = new ArrayList<String>(); List<String> outTypeList3 = new ArrayList<String>(); //加入group公共组,开始 //由于group功能是后期加入的,不想对javascriptloader.xml做大修改,所以暂时只对cssloader.xml有效 if(!forJS()){ Element groups = XmlParser.getChild(root,"groups"); List<Element> groupList = XmlParser.getChildList(groups); @SuppressWarnings("unchecked") //取出page的groupid org.dom4j.Attribute groupid = XmlParser.getAttribute(page, "groupid"); if(groups!=null && groupList.size() >0 ){ //未配置groupid,使用默认group或第一个group if(groupid==null ){ Element defaultEle = (Element) XmlParser.getSingleNode(groups,"group[@default='true']"); if(defaultEle==null ) defaultEle = groupList.get(0); srcriptList.addAll(0,XmlParser.getChildList(defaultEle)); } else{ //已配置groupid,则找到对应group加入到scriptlist Element groupEle = (Element) XmlParser.getSingleNode(groups,"group[@id='"+ groupid.getText() +"']"); if(groupEle!=null) srcriptList.addAll(0,XmlParser.getChildList(groupEle)); } } } //加入group公共组,结束 // 当前page的所有script for (Element script : srcriptList) { org.dom4j.Attribute outputType = XmlParser.getAttribute(script, "outputType"); String curOutputType = outputType==null?null:outputType.getText(); // 判断script是否存在ref org.dom4j.Attribute ref = XmlParser.getAttribute(script, "ref"); // 存在ref String src; if (ref != null) { CommonScript commonScript = commonMap.get(ref.getText()); src = commonScript.getSrc(); if(curOutputType==null && commonScript.getOutputType()!=null) curOutputType = commonScript.getOutputType(); } else { src = XmlParser.getAttribute(script, urlAttr).getText(); } if(!StringHelp.IsNullOrEmpty(useMinJsCss) && useMinJsCss.equals("true") && !StringHelp.IsNullOrEmpty(src) && !src.startsWith("http") && !src.contains(".min")){ src = src.replace("."+fileType, ".min."+fileType ); } // 按照xml的outputtype指定输出,用于生产环境 if (mergeAndCompress.equals("true")) { // 如果未指定outputtype,则默认outputtype=2 if (curOutputType == null) { outTypeList2.add(src); } else { switch (curOutputType) { case "1": outTypeList1.add(src); break; case "2": outTypeList2.add(src); break; case "3": outTypeList3.add(src); break; } } } else { // 不按照xml指定的outputtype输出,而是全部原样输出,用于测试环境 outTypeList1.add(src); } } // outputType=1的处理,原样输出 for (String src : outTypeList1) { // Long lastModified = LoaderTagSupport.getLastModified(src); if (src == null) continue; String scriptString = src.startsWith("http") ? MessageFormat .format(fullUrl4, src) : MessageFormat.format(fullUrl1, src, urlPath); try { this.pageContext.getOut().println(scriptString); } catch (IOException e) { e.printStackTrace(); } } // outputType=2的处理,每个js随机服务器地址输出 for (String src : outTypeList2) { // Long lastModified = LoaderTagSupport.getLastModified(src); String scriptString = MessageFormat.format(fullUrl2, LoaderTagSupport.RandomJSAbsoluteUrl(serverList), src); try { this.pageContext.getOut().println(scriptString); } catch (IOException e) { e.printStackTrace(); } } // outputType=3的处理 基本没用过,略 return super.doStartTag(); } /** * 指定页面代号以获取相关配置 * * @return */ public String getPageName() { return pageName; } public void setPageName(String pageName) { this.pageName = pageName; } public String getFileType() { return fileType; } public void setFileType(String fileType) { this.fileType = fileType; } }
二、jsp引用js配置文件
<?xml version="1.0" encoding="UTF-8"?> <root> <!-- 定义随机地址列表,也可删除,只有 MergeAndCompress=true 且 outputType=2时才会起作用 --> <servers> <server>http://js1.domain.com/</server> <server>http://js2.domain.com/</server> <server>http://js3.domain.com/</server> </servers> <common> <script src="js/JsRender.js" name="jsrender"></script> <script src="js/jquery-1.10.2.min.js" name="jquery"></script> <script src="js/jquery.validate.1.14.001.js" name="jqvalidate"></script> <script src="js/selectArea.js?v=0004" name="selectArea"></script> <script src="js/mobileBUGFix.mini.js" name="mobilebf"></script> <script src="js/jquery.blockUI.js" name="blockui"></script> </common> <!-- 注意, 不指定 outputType,则等效于 outputType=2,所以一般都不需指定 --> <page name="demo_beginform"> <script ref="jquery"></script> <script ref="jqvalidate"></script> <script ref="jsrender"></script> <script src="js/selectArea.js?v=0003"></script> <script ref="mobilebf"></script> <script src="js/qst.js"></script> <script src="js/uploadImg.js"></script> <script ref="blockui"></script> </page> <page name="test"> <script ref="jquery"></script> <script ref="jsrender"></script> <script src="js/selectArea.js?v=20160105"></script> <script ref="jweixin"></script> <script ref="wxsdk"></script> </page> <!-- 测试 end --> </root>
三、 jsp引用css配置文件
<?xml version="1.0" encoding="UTF-8"?> <root> <servers> <server>http://css1.domain.com/</server> <server>http://css2.domain.com/</server> <server>http://css3.domain.com/</server> </servers> <common> <link href="css/citycss.css?v=0015" name="citycss" /> <link href="css/base.css?v=0015" type="text/css" name="mt_base" /> </common> <!-- 会默认为每个jsp添加的css引用,默认为page加载第一个或default="true"的group 。可以在 page 节点指定 groupid="1"匹配对应group,或指定 groupid="none"不加载group,未匹配page节点的jsp页,也会加载 group[@default="true"] --> <groups> <group default="true" id="1"> <link ref="mt_base" /> <link ref="citycss" /> </group> </groups> <page name="test"> <link href="css/wap_indexokwei.css?v=20160105" /> </page> </root>
四、jsp中加入相关代码
<custom:JsLoaderTag pageName="beginform"></custom:JsLoaderTag>
<custom:JsLoaderTag pageName="beginform" fileType="css"></custom:JsLoaderTag>
五、效果
相关文章推荐
- css样式分类
- CSS3动画属性animation的基本用法
- css display visibility
- CSS----引入方式和常用属性
- 前端性能优化--合理使用CSS Sprites和内联图片
- HTML 样式
- 一些css技巧
- CSS选择器详解
- HTML和CSS <h1> --2-- <h1>
- 使用css3伪元素实现遮罩效果
- css 如何让背景图片拉伸填充避免重复显示
- css3 perspective与translateZ变换
- 礼拜四log~CSS背景设置技巧和java框架某些问题的解决方法
- 谷歌CSS风格规范
- css-selectors
- css自定义开关(一个圆里有一个x)
- 发觉前一个项目需求很好玩的两个CSS animation
- CSS3 Animation
- css3(border-radius)边框圆角详解
- [积累]推荐给大家的CSS书写规范、顺序