import java.io.StringReader;
java.io.StringWriter 가져오기;
java.util.* 가져오기;
java.util.regex.* 가져오기;
/*******************************************
* jsp, html 코드 압축 , 모든 공백 및 개행 문자 제거
* @author bearrui(ak-47)
* @version 0.1
* @date 2010-5-13
********* *** *********************************/
public class HtmlCompressor {
private static String tempPreBlock = "%%%HTMLCOMPRESS~PRE&&&";
비공개 정적 문자열 tempTextAreaBlock = "%%%HTMLCOMPRESS~TEXTAREA&&&";
private static String tempScriptBlock = "%%%HTMLCOMPRESS~SCRIPT&&&";
private static String tempStyleBlock = "%%%HTMLCOMPRESS~STYLE&&&";
private static String tempJspBlock = "%%%HTMLCOMPRESS~JSP&&&";
비공개 정적 패턴 commentPattern = Pattern.compile("", Pattern.DOTALL | Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
비공개 정적 패턴 itsPattern = Pattern.compile(">\s ?<", Pattern.DOTALL | Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
비공개 정적 패턴 prePattern = Pattern.compile("
]*?>.*?
", Pattern.DOTALL | Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
비공개 정적 패턴 taPattern = Pattern.compile("
", Pattern.DOTALL | Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
비공개 정적 패턴 jspPattern = Pattern.compile("<%([^-@][\w\W]*?)%>", Pattern.DOTALL | Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
// <스크립트>
비공개 정적 패턴 scriptPattern = Pattern.compile("(?:", Pattern.DOTALL | Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
비공개 정적 패턴 stylePattern = Pattern.compile("", Pattern.DOTALL | Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
// 单行注释,
private static Pattern signleCommentPattern = Pattern.compile("//.*");
// 字符串匹配
private static Pattern stringPattern = Pattern.compile("("[^"\n]*?"|'[^'\n]*?')");
// 트리밍 작업 공간
private static Pattern TrimPattern = Pattern.compile("\n\s*",Pattern.MULTILINE);
private static Pattern TrimPattern2 = Pattern.compile("\s*\ r",Pattern.MULTILINE);
// 多行注释
private static Pattern multiCommentPattern = Pattern.compile("/\*.*?\*/", Pattern.DOTALL | Pattern.CASE_INSENSITIVE | Pattern. MULTILINE);
private static String tempSingleCommentBlock = "%%%HTMLCOMPRESS~SINGLECOMMENT&&&" // //位符
private static String tempMulitCommentBlock1 = "%%%HTMLCOMPRESS~MULITCOMMENT1&&&" // /*符
private static String tempMulitCommentBlock2 = "%%%HTMLCOMPRESS~MULITCOMMENT2&&&" // */·位符
public static String 압축(String html)에서 예외 발생 {
if(html == null || html.length() == 0) {
return html;
List
preBlocks = new ArrayList(); 배열목록()
목록 scriptBlocks = new ArrayList();
목록 styleBlocks = new ArrayList();
목록 jspBlocks = new ArrayList();
문자열 결과 = html;
//인라인 자바 코드 유지
Matcher jspMatcher = jspPattern.matcher(result);
while(jspMatcher.find()) {
jspBlocks.add(jspMatcher.group(0));
}
결과 = jspMatcher.replaceAll(tempJspBlock);
//PRE 태그 유지
Matcher preMatcher = prePattern.matcher(result);
while(preMatcher.find()) {
preBlocks.add(preMatcher.group(0));
}
결과 = preMatcher.replaceAll(tempPreBlock);
//TEXTAREA 태그 유지
Matcher taMatcher = taPattern.matcher(result);
while(taMatcher.find()) {
taBlocks.add(taMatcher.group(0));
}
결과 = taMatcher.replaceAll(tempTextAreaBlock);
//SCRIPT 태그 유지
Matcher scriptMatcher = scriptPattern.matcher(result);
while(scriptMatcher.find()) {
scriptBlocks.add(scriptMatcher.group(0));
}
결과 = scriptMatcher.replaceAll(tempScriptBlock);
// 인라인 CSS를 처리하지 않음
Matcher styleMatcher = stylePattern.matcher(result);
while(styleMatcher.find()) {
styleBlocks.add(styleMatcher.group(0));
}
결과 = styleMatcher.replaceAll(tempStyleBlock);
//순수 HTML 처리
result = processHtml(result);
//보존된 블록 처리
result = processPreBlocks(result, preBlocks);
결과 = processTextareaBlocks(결과, taBlocks);
결과 = processScriptBlocks(결과, scriptBlocks);
결과 = processStyleBlocks(결과, styleBlocks);
결과 = processJspBlocks(결과, jspBlocks);
preBlocks = taBlocks = scriptBlocks = styleBlocks = jspBlocks = null;
결과 반환.trim();
}
private static String processHtml(String html) {
String result = html;
//댓글 제거
// if(removeComments) {
result = commentPattern.matcher(result).replaceAll("");
// }
//태그 간 공백 제거
// if(removeIntertagSpaces) {
result = itsPattern.matcher(result).replaceAll("><");
// }
//여러 공백 문자 제거
// if(removeMultiSpaces) {
result = result.replaceAll("\s{2,}"," ");
// }
결과 반환;
}
private static String processJspBlocks(String html, List 블록){
String result = html;
for(int i = 0; i blocks.set(i,compressJsp(blocks.get(i)));
}
//보존된 블록을 다시 넣기
while(result.contains(tempJspBlock)) {
result = result.replaceFirst(tempJspBlock, Matcher.quoteReplacement(blocks.remove(0)));
}
결과 반환;
}
비공개 정적 문자열 processPreBlocks(String html, List 블록)에서 예외 발생 {
String result = html;
//보존된 블록을 다시 넣기
while(result.contains(tempPreBlock)) {
result = result.replaceFirst(tempPreBlock, Matcher.quoteReplacement(blocks.remove(0)));
}
결과 반환;
}
비공개 정적 문자열 processTextareaBlocks(String html, List 블록)에서 예외 발생 {
String result = html;
//보존된 블록을 다시 넣기
while(result.contains(tempTextAreaBlock)) {
result = result.replaceFirst(tempTextAreaBlock, Matcher.quoteReplacement(blocks.remove(0)));
}
결과 반환;
}
비공개 정적 문자열 processScriptBlocks(String html, List 블록)에서 예외 발생 {
String result = html;
// if(compressJavaScript) {
for(int i = 0; i blocks.set(i,compressJavaScript(blocks.get(i)) );
}
// }
//보존된 블록을 다시 넣기
while(result.contains(tempScriptBlock)) {
result = result.replaceFirst(tempScriptBlock, Matcher.quoteReplacement(blocks.remove) (0)));
}
결과 반환;
}
비공개 정적 문자열 processStyleBlocks(String html, List 블록)에서 예외 발생 {
String result = html;
// if(compressCss) {
for(int i = 0; i blocks.set(i,compressCssStyles(blocks.get(i)) );
}
// }
//보존된 블록을 다시 넣기
while(result.contains(tempStyleBlock)) {
result = result.replaceFirst(tempStyleBlock, Matcher.quoteReplacement(blocks.remove) (0)));
}
결과 반환;
}
private static String 압축Jsp(String source) {
//블록이 비어 있지 않은지 확인
Matcher jspMatcher = jspPattern.matcher(source);
if(jspMatcher.find()) {
String result = 압축JspJs(jspMatcher.group(1));
return (new StringBuilder(source.substring(0, jspMatcher.start(1))).append(result).append(source.substring(jspMatcher.end(1)))).toString();
} else {
반환 소스;
}
}
private static String 압축JavaScript(String source) {
//블록이 비어 있지 않은지 확인
Matcher scriptMatcher = scriptPattern.matcher(source);
if(scriptMatcher.find()) {
String result = 압축JspJs(scriptMatcher.group(1));
return (new StringBuilder(source.substring(0, scriptMatcher.start(1))).append(result).append(source.substring(scriptMatcher.end(1)))).toString();
} else {
반환 소스;
}
}
private static String 압축CssStyles(String source) {
//블록이 비어 있지 않은지 확인
Matcher styleMatcher = stylePattern.matcher(source);
if(styleMatcher.find()) {
// 去掉注释,换行
String result= multiCommentPattern.matcher(styleMatcher.group(1)).replaceAll("");
결과 = TrimPattern.matcher(result).replaceAll("");
결과 = TrimPattern2.matcher(result).replaceAll("");
return (new StringBuilder(source.substring(0, styleMatcher.start(1))).append(result).append(source.substring(styleMatcher.end(1)))).toString();
} else {
반환 소스;
}
}
private static String extractJspJs(String source){
String result = source;
// 문자열에 주석이 나타날 수 있으므로 문자열의 특수 문자를 먼저 제거해야 합니다
Matcher stringMatcher = stringPattern. matcher(result);
while(stringMatcher.find()){
String tmpStr = stringMatcher.group(0)
if(tmpStr.indexOf("//") != -1 || tmpStr.indexOf("/*") != -1 || tmpStr.indexOf("*/") != -1){
String blockStr = tmpStr.replaceAll("//" , tempSingleCommentBlock).replaceAll( "/\*", tempMulitCommentBlock1)
.replaceAll("\*/", tempMulitCommentBlock2);
result = result.replace(tmpStr, blockStr)
}
}
// 주석 제거
result = signleCommentPattern.matcher(result).replaceAll("");
result = multiCommentPattern.matcher(result).replaceAll("")
result = TrimPattern2 .matcher(result) .replaceAll("");
result = TrimPattern.matcher(result).replaceAll(" ");
// 대체된 문자열 복원
result = result.replaceAll( tempSingleCommentBlock, "//") .replaceAll(tempMulitCommentBlock1, "/*")
.replaceAll(tempMulitCommentBlock2, "*/");
return result;
}
}