package com.qxueyou.scc.base.util;
|
|
import java.io.BufferedReader;
|
import java.io.BufferedWriter;
|
import java.io.File;
|
import java.io.FileInputStream;
|
import java.io.FileOutputStream;
|
import java.io.IOException;
|
import java.io.InputStream;
|
import java.io.InputStreamReader;
|
import java.io.OutputStream;
|
import java.io.OutputStreamWriter;
|
import java.security.MessageDigest;
|
import java.text.SimpleDateFormat;
|
import java.util.ArrayList;
|
import java.util.Date;
|
import java.util.HashMap;
|
import java.util.Iterator;
|
import java.util.List;
|
import java.util.Map;
|
import java.util.regex.Pattern;
|
|
import org.apache.commons.lang3.StringUtils;
|
|
/**
|
* 前三个属性根据实际存储位置设置
|
* @author ody.yuan
|
*
|
*/
|
public class MyJsCssVersionUtils {
|
|
/** web工程的发布路径 */
|
private static String webContent = "qxueyou";
|
|
/** web工程中web文件夹的绝对路径 D:\project\workspace_web\versioncontroller0\web\js\qxueyou.js */
|
/** web工程中web文件夹的绝对路径 D:\project\workspaceStkkk\qxueyou_web\web\js\qxueyou.js */
|
private static String webFileAbsolutePath = "C:" + File.separator + "workspace" + File.separator + "qxueyou_web";
|
|
/** 扫描js、css、html文件的文件夹绝对路径,固定设置为web目录 */
|
private static String fileScanDirec = "C:" + File.separator + "workspace" + File.separator + "qxueyou_web";
|
|
/** 匹配html中引入js文件 */
|
private static Pattern scriptImportPattrrn = Pattern.compile("<script(.*)src(.*)</script>");
|
|
/** 匹配html中引入css文件 */
|
private static Pattern cssImportPattrrn = Pattern.compile("<link(.*)href(.*)rel(.*)>");
|
|
private static char hexDigits[]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
|
|
|
/**
|
* 得到处理过的文件路径为key,文件md5值为value的map
|
* @param filePath 文件路径
|
* @param fileExtension 文件类型
|
* @param map map
|
*/
|
private static void getFileMD5Map(String filePath,String fileExtension,Map<String,String> map,String version){
|
readFile(filePath,fileExtension,map,version);
|
}
|
|
/**
|
* 得到路径下的所需文件和文件的md5值
|
* @param filePath
|
* @param fileExtension
|
* @param map
|
*/
|
private static void readFile(String filePath,String fileExtension,Map<String,String> map,String version){
|
|
File file = new File(filePath);
|
if(file.isFile()){
|
String fiePath = file.getAbsolutePath();
|
//符合指定类型
|
if(fiePath.endsWith(fileExtension)){
|
generateMap(file,fileExtension,map,version);
|
}
|
}else if(file.isDirectory()){
|
String[] fileList = file.list();
|
for(String name : fileList){
|
readFile(filePath + File.separator + name,fileExtension,map,version);
|
}
|
}
|
}
|
|
/**
|
* 得到一个文件的map
|
* @param file
|
* @param map
|
*/
|
private static void generateMap(File file, String fileExtension, Map<String,String> map,String version){
|
//TODO 缩短md5值
|
String strKey = file.getAbsolutePath();
|
strKey = strKey.replace(webFileAbsolutePath, File.separator + webContent);
|
strKey = strKey.replace("\\", "/");
|
String strValue = getMD5(file);
|
if(StringUtils.isNotBlank(strValue)){
|
strValue = version;
|
}
|
map.put(strKey, strValue);
|
|
}
|
|
/**
|
* 对文件全文生成MD5摘要
|
*
|
* @param file
|
* 要加密的文件
|
* @return MD5摘要码
|
*/
|
public static String getMD5(File file) {
|
FileInputStream fis = null;
|
try {
|
MessageDigest md = MessageDigest.getInstance("MD5");
|
fis = new FileInputStream(file);
|
byte[] buffer = new byte[2048];
|
int length = -1;
|
//暂时不用
|
//long s = System.currentTimeMillis();
|
while ((length = fis.read(buffer)) != -1) {
|
md.update(buffer, 0, length);
|
}
|
byte[] b = md.digest();
|
return byteToHexString(b);
|
// 16位加密
|
// return buf.toString().substring(8, 24);
|
} catch (Exception ex) {
|
ex.printStackTrace();
|
return null;
|
} finally {
|
try {
|
fis.close();
|
} catch (IOException ex) {
|
ex.printStackTrace();
|
}
|
}
|
}
|
|
/**
|
* 把byte[]数组转换成十六进制字符串表示形式
|
* @param tmp 要转换的byte[]
|
* @return 十六进制字符串表示形式
|
*/
|
private static String byteToHexString(byte[] tmp) {
|
|
String s;
|
// 用字节表示就是 16 个字节
|
char str[] = new char[16 * 2]; // 每个字节用 16 进制表示的话,使用两个字符,
|
// 所以表示成 16 进制需要 32 个字符
|
int k = 0; // 表示转换结果中对应的字符位置
|
for (int i = 0; i < 16; i++) { // 从第一个字节开始,对 MD5 的每一个字节
|
// 转换成 16 进制字符的转换
|
byte byte0 = tmp[i]; // 取第 i 个字节
|
str[k++] = hexDigits[byte0 >>> 4 & 0xf]; // 取字节中高 4 位的数字转换,
|
// >>> 为逻辑右移,将符号位一起右移
|
str[k++] = hexDigits[byte0 & 0xf]; // 取字节中低 4 位的数字转换
|
}
|
s = new String(str); // 换后的结果转换为字符串
|
return s;
|
}
|
|
/**
|
*
|
* @param filePath
|
* @param fileExtension
|
* @param map
|
*/
|
private static void getHtml(String filePath,String fileExtension,Map<String,String> map){
|
readHtmlFile(fileScanDirec,".ftl",map);
|
}
|
|
/**
|
* 得到路径下的所需文件和文件的md5值
|
* @param filePath
|
* @param fileExtension
|
* @param map
|
*/
|
private static void readHtmlFile(String filePath,String fileExtension,Map<String,String> map){
|
|
File file = new File(filePath);
|
if(file.isFile()){
|
String fiePath = file.getAbsolutePath();
|
//符合指定类型
|
if(fiePath.endsWith(fileExtension)){
|
addVersion(file,map);
|
}
|
}else if(file.isDirectory()){
|
String[] fileList = file.list();
|
for(String name : fileList){
|
readHtmlFile(filePath + File.separator + name,fileExtension,map);
|
}
|
}
|
}
|
|
/**
|
* 得到一个文件的map
|
* @param file
|
* @param map
|
*/
|
private static void addVersion(File file,Map<String,String> map){
|
//TODO 缩短md5值
|
InputStream is = null;
|
OutputStream os = null;
|
List<String> contentList = new ArrayList<String>();
|
|
// 读文件
|
try {
|
//指定utf-8格式
|
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(file), "utf-8"));
|
String line = null;
|
|
while ((line = br.readLine()) != null) {
|
//TODO version 传null值
|
String modLine = getModLine(line, null,map);
|
if (modLine != null) {
|
//System.out.println(modLine);
|
line = modLine;
|
}
|
line = line + "\r\n";
|
contentList.add(line);
|
}
|
// 关闭流
|
br.close();
|
} catch (Exception e) {
|
System.out.println("读文件失败:" + file.getAbsolutePath());
|
e.printStackTrace();
|
} finally {
|
if (null != is) {
|
try {
|
is.close();
|
} catch (Exception e) {
|
e.printStackTrace();
|
}
|
}
|
|
}
|
// 写文件
|
try {
|
//指定utf8格式
|
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file),"utf-8"));
|
|
for (Iterator<String> it = contentList.iterator(); it.hasNext();) {
|
String line = it.next();
|
bw.write(line);
|
}
|
// 更新到文件
|
bw.flush();
|
// 关闭流
|
bw.close();
|
} catch (Exception e) {
|
System.out.println("写文件失败:" + file.getAbsolutePath());
|
e.printStackTrace();
|
} finally {
|
if (null != os) {
|
try {
|
os.close();
|
} catch (Exception e) {
|
e.printStackTrace();
|
}
|
}
|
}
|
}
|
|
/**
|
*
|
* 查找文件需要的版本号的js 与css 行
|
* @param line 行字符
|
* @param version 默认版本
|
* @param map md5 map
|
* @return
|
*/
|
private static String getModLine(String line, String version, Map<String, String> map) {
|
|
//匹配html引入js文件 eg:<script type="text/javascript" src="/qxueyou/web/js/qxueyou.js"></script>
|
if (scriptImportPattrrn.matcher(line).find()) {
|
//以引号分隔,以/开始
|
String md5Version = null;
|
String strLine[] = line.split("\"");
|
for(String str:strLine){
|
if(null != md5Version){
|
break;
|
}
|
if(str.startsWith("/")){
|
//如果已有版本号,按?分隔,取第一个
|
if(str.lastIndexOf("?version") != -1){
|
str = str.substring(0, str.lastIndexOf("?version"));
|
}
|
md5Version = map.get(str);
|
}
|
}
|
|
int pos = line.lastIndexOf(".js");
|
if(null != md5Version){
|
String modLine = line.substring(0, pos) + ".js?version=" + md5Version+ "\"></script>";
|
return modLine;
|
}
|
|
//匹配html引入css文件 eg:<link href="/qxueyou/web/css/bootstrap.min.css" rel="stylesheet">
|
} else if (cssImportPattrrn.matcher(line).find()) {
|
|
//以引号分隔,以/开始
|
String md5Version = null;
|
String strLine[] = line.split("\"");
|
for(String str:strLine){
|
if(null != md5Version){
|
break;
|
}
|
if(str.startsWith("/")){
|
//如果已有版本号,按?分隔,取第一个
|
if(str.lastIndexOf("?version") != -1){
|
str = str.substring(0, str.lastIndexOf("?version"));
|
}
|
md5Version = map.get(str);
|
}
|
}
|
|
int pos = line.lastIndexOf(".css");
|
if(null != md5Version){
|
String modLine = line.substring(0, pos) + ".css?version=" + md5Version+ "\" rel=\"stylesheet\">";
|
return modLine;
|
}
|
|
}
|
|
return line;
|
}
|
|
/**
|
*
|
* @param args
|
*/
|
public static void main(String[] args) {
|
|
Date date = new Date();
|
SimpleDateFormat df = new SimpleDateFormat("yyyyMMddhhmmss");
|
String version = df.format(date);
|
|
Map<String,String> objMap = new HashMap<String,String>();
|
//添加js文件
|
getFileMD5Map(fileScanDirec,".js",objMap,version);
|
//添加CSS文件
|
getFileMD5Map(fileScanDirec,".css",objMap,version);
|
|
//循环html文件,修改其中的css和js引入路径
|
getHtml(fileScanDirec,".ftl",objMap);
|
|
System.out.println("successful");
|
|
}
|
|
}
|