最近分享代码较少,正好在优化最代码关于返回的html代码的压缩上有些相关经验分享下。
【参考:http://www.zuidaima.com/share/2633847241772032.htm】
之前研究的是通过freemarker的原生macro实现的:
1
<@compress single_line=true>
2
<html>
3
freemarker template技术
4
</html>
5
</@compress>
但因为最代码目前已经有几十个template文件,一个个加的话太费时费力了,另外如果不是freemarker技术的话就不能使用这个机制了,感觉java应该有这种技术来实现压缩的功能,于是想到了Filter
HtmlFilter.java
001
package com.zuidaima.filter;
002
003
import java.io.ByteArrayOutputStream;
004
import java.io.IOException;
005
import java.io.PrintWriter;
006
import java.util.ArrayList;
007
import java.util.List;
008
import java.util.regex.Matcher;
009
import java.util.regex.Pattern;
010
011
import javax.servlet.Filter;
012
import javax.servlet.FilterChain;
013
import javax.servlet.FilterConfig;
014
import javax.servlet.ServletException;
015
import javax.servlet.ServletOutputStream;
016
import javax.servlet.ServletRequest;
017
import javax.servlet.ServletResponse;
018
import javax.servlet.http.HttpServletRequest;
019
import javax.servlet.http.HttpServletResponse;
020
import javax.servlet.http.HttpServletResponseWrapper;
021
022
/**
023
*@author www.zuidaima.com
024
**/
025
public class HtmlFilter implements Filter {
026
027
public static final String codePatternStr = "(<|<)p-re[\\w\\W]*?[\\w\\W]*?/p-re[\\w\\W]*?(>|>)";
028
public static final Pattern codePattern = Pattern.compile(codePatternStr,
029
Pattern.CASE_INSENSITIVE);
030
031
private FilterConfig filterConfig = null;
032
033
class CodeFragment {
034
035
private String left;
036
private String fragment;
037
private String right;
038
039
public CodeFragment(String left, String fragment, String right) {
040
this.left = left;
041
this.fragment = fragment;
042
this.right = right;
043
}
044
045
public String getLeft() {
046
return left;
047
}
048
049
public void setLeft(String left) {
050
this.left = left;
051
}
052
053
public String getFragment() {
054
return fragment;
055
}
056
057
public void setFragment(String fragment) {
058
this.fragment = fragment;
059
}
060
061
public String getRight() {
062
return right;
063
}
064
065
public void setRight(String right) {
066
this.right = right;
067
}
068
}
069
070
private static class ByteArrayServletStream extends ServletOutputStream {
071
ByteArrayOutputStream baos;
072
073
ByteArrayServletStream(ByteArrayOutputStream baos) {
074
this.baos = baos;
075
}
076
077
public void write(int param) throws IOException {
078
baos.write(param);
079
}
080
}
081
082
private static class ByteArrayPrintWriter {
083
084
private ByteArrayOutputStream baos = new ByteArrayOutputStream();
085
086
private PrintWriter pw = new PrintWriter(baos);
087
088
private ServletOutputStream sos = new ByteArrayServletStream(baos);
089
090
public PrintWriter getWriter() {
091
return pw;
092
}
093
094
public ServletOutputStream getStream() {
095
return sos;
096
}
097
098
byte[] toByteArray() {
099
return baos.toByteArray();
100
}
101
}
102
103
public class CharResponseWrapper extends HttpServletResponseWrapper {
104
private ByteArrayPrintWriter output;
105
private boolean usingWriter;
106
107
public CharResponseWrapper(HttpServletResponse response) {
108
super(response);
109
usingWriter = false;
110
output = new ByteArrayPrintWriter();
111
}
112
113
public byte[] getByteArray() {
114
return output.toByteArray();
115
}
116
117
@Override
118
public ServletOutputStream getOutputStream() throws IOException {
119
// will error out, if in use
120
if (usingWriter) {
121
super.getOutputStream();
122
}
123
usingWriter = true;
124
return output.getStream();
125
}
126
127
@Override
128
public PrintWriter getWriter() throws IOException {
129
// will error out, if in use
130
if (usingWriter) {
131
super.getWriter();
132
}
133
usingWriter = true;
134
return output.getWriter();
135
}
136
137
public String toString() {
138
return output.toString();
139
}
140
}
141
142
public void doFilter(ServletRequest request, ServletResponse response,
143
FilterChain chain) throws IOException, ServletException {
144
HttpServletRequest _request = (HttpServletRequest) request;
145
if (_request.getRequestURI().indexOf("update") != -1
146
|| _request.getRequestURI().indexOf("create") != -1) {
147
chain.doFilter(request, response);
148
return;
149
}
150
CharResponseWrapper wrappedResponse = new CharResponseWrapper(
151
(HttpServletResponse) response);
152
chain.doFilter(request, wrappedResponse);
153
byte[] bytes = wrappedResponse.getByteArray();
154
155
String contentType = wrappedResponse.getContentType();
156
if (contentType != null && contentType.matches(".*?(html|json).*?")) {
157
String out = new String(bytes);
158
Matcher matcher = codePattern.matcher(out);
159
List<CodeFragment> codeFragments = new ArrayList<CodeFragment>();
160
while (matcher.find()) {
161
String fragment = matcher.group(0);
162
String left = matcher.group(1);
163
String right = matcher.group(2);
164
CodeFragment codeFragment = new CodeFragment(left, fragment,
165
right);
166
codeFragments.add(codeFragment);
167
// 占位符<pr-e>idx</pr-e>
168
out = out.replace(fragment, left + "p-re" + right
169
+ codeFragments.size() + left + "/p-re" + right);
170
}
171
out = out.replaceAll("[\r\n]", "").replaceAll(">\\s*?<", "><")
172
.trim();
173
// 还原占位符
174
for (int i = 0; i < codeFragments.size(); i++) {
175
CodeFragment codeFragment = codeFragments.get(i);
176
String fragment = codeFragment.getFragment();
177
String left = codeFragment.getLeft();
178
String right = codeFragment.getRight();
179
out = out.replace(left + "p-re" + right + (i + 1) + left
180
+ "/p-re" + right, fragment);
181
}
182
response.getOutputStream().write(out.getBytes());
183
} else {
184
response.getOutputStream().write(bytes);
185
}
186
}
187
188
@Override
189
public void init(FilterConfig filterConfig) throws ServletException {
190
this.filterConfig = filterConfig;
191
}
192
193
@Override
194
public void destroy() {
195
filterConfig = null;
196
}
197
}
刚上线的新鲜代码分享,相信对牛牛们会有所帮助吧。
注意:
1.创建和编辑类的操作不做压缩,因为访问量不大
2.<pre></pre>内部的代码不做处理
3.只对content type为html和json做的做处理
压缩前和压缩后的html代码大小对比如下图
java servlet对html网页压缩后返回的过滤器代码实现
压缩前源码
java servlet对html网页压缩后返回的过滤器代码实现
压缩后源码
java servlet对html网页压缩后返回的过滤器代码实现
另外对seo的影响可能不会很大,毕竟没有改变html结构。
【参考:http://www.zuidaima.com/share/2633847241772032.htm】
之前研究的是通过freemarker的原生macro实现的:
1
<@compress single_line=true>
2
<html>
3
freemarker template技术
4
</html>
5
</@compress>
但因为最代码目前已经有几十个template文件,一个个加的话太费时费力了,另外如果不是freemarker技术的话就不能使用这个机制了,感觉java应该有这种技术来实现压缩的功能,于是想到了Filter
HtmlFilter.java
001
package com.zuidaima.filter;
002
003
import java.io.ByteArrayOutputStream;
004
import java.io.IOException;
005
import java.io.PrintWriter;
006
import java.util.ArrayList;
007
import java.util.List;
008
import java.util.regex.Matcher;
009
import java.util.regex.Pattern;
010
011
import javax.servlet.Filter;
012
import javax.servlet.FilterChain;
013
import javax.servlet.FilterConfig;
014
import javax.servlet.ServletException;
015
import javax.servlet.ServletOutputStream;
016
import javax.servlet.ServletRequest;
017
import javax.servlet.ServletResponse;
018
import javax.servlet.http.HttpServletRequest;
019
import javax.servlet.http.HttpServletResponse;
020
import javax.servlet.http.HttpServletResponseWrapper;
021
022
/**
023
*@author www.zuidaima.com
024
**/
025
public class HtmlFilter implements Filter {
026
027
public static final String codePatternStr = "(<|<)p-re[\\w\\W]*?[\\w\\W]*?/p-re[\\w\\W]*?(>|>)";
028
public static final Pattern codePattern = Pattern.compile(codePatternStr,
029
Pattern.CASE_INSENSITIVE);
030
031
private FilterConfig filterConfig = null;
032
033
class CodeFragment {
034
035
private String left;
036
private String fragment;
037
private String right;
038
039
public CodeFragment(String left, String fragment, String right) {
040
this.left = left;
041
this.fragment = fragment;
042
this.right = right;
043
}
044
045
public String getLeft() {
046
return left;
047
}
048
049
public void setLeft(String left) {
050
this.left = left;
051
}
052
053
public String getFragment() {
054
return fragment;
055
}
056
057
public void setFragment(String fragment) {
058
this.fragment = fragment;
059
}
060
061
public String getRight() {
062
return right;
063
}
064
065
public void setRight(String right) {
066
this.right = right;
067
}
068
}
069
070
private static class ByteArrayServletStream extends ServletOutputStream {
071
ByteArrayOutputStream baos;
072
073
ByteArrayServletStream(ByteArrayOutputStream baos) {
074
this.baos = baos;
075
}
076
077
public void write(int param) throws IOException {
078
baos.write(param);
079
}
080
}
081
082
private static class ByteArrayPrintWriter {
083
084
private ByteArrayOutputStream baos = new ByteArrayOutputStream();
085
086
private PrintWriter pw = new PrintWriter(baos);
087
088
private ServletOutputStream sos = new ByteArrayServletStream(baos);
089
090
public PrintWriter getWriter() {
091
return pw;
092
}
093
094
public ServletOutputStream getStream() {
095
return sos;
096
}
097
098
byte[] toByteArray() {
099
return baos.toByteArray();
100
}
101
}
102
103
public class CharResponseWrapper extends HttpServletResponseWrapper {
104
private ByteArrayPrintWriter output;
105
private boolean usingWriter;
106
107
public CharResponseWrapper(HttpServletResponse response) {
108
super(response);
109
usingWriter = false;
110
output = new ByteArrayPrintWriter();
111
}
112
113
public byte[] getByteArray() {
114
return output.toByteArray();
115
}
116
117
@Override
118
public ServletOutputStream getOutputStream() throws IOException {
119
// will error out, if in use
120
if (usingWriter) {
121
super.getOutputStream();
122
}
123
usingWriter = true;
124
return output.getStream();
125
}
126
127
@Override
128
public PrintWriter getWriter() throws IOException {
129
// will error out, if in use
130
if (usingWriter) {
131
super.getWriter();
132
}
133
usingWriter = true;
134
return output.getWriter();
135
}
136
137
public String toString() {
138
return output.toString();
139
}
140
}
141
142
public void doFilter(ServletRequest request, ServletResponse response,
143
FilterChain chain) throws IOException, ServletException {
144
HttpServletRequest _request = (HttpServletRequest) request;
145
if (_request.getRequestURI().indexOf("update") != -1
146
|| _request.getRequestURI().indexOf("create") != -1) {
147
chain.doFilter(request, response);
148
return;
149
}
150
CharResponseWrapper wrappedResponse = new CharResponseWrapper(
151
(HttpServletResponse) response);
152
chain.doFilter(request, wrappedResponse);
153
byte[] bytes = wrappedResponse.getByteArray();
154
155
String contentType = wrappedResponse.getContentType();
156
if (contentType != null && contentType.matches(".*?(html|json).*?")) {
157
String out = new String(bytes);
158
Matcher matcher = codePattern.matcher(out);
159
List<CodeFragment> codeFragments = new ArrayList<CodeFragment>();
160
while (matcher.find()) {
161
String fragment = matcher.group(0);
162
String left = matcher.group(1);
163
String right = matcher.group(2);
164
CodeFragment codeFragment = new CodeFragment(left, fragment,
165
right);
166
codeFragments.add(codeFragment);
167
// 占位符<pr-e>idx</pr-e>
168
out = out.replace(fragment, left + "p-re" + right
169
+ codeFragments.size() + left + "/p-re" + right);
170
}
171
out = out.replaceAll("[\r\n]", "").replaceAll(">\\s*?<", "><")
172
.trim();
173
// 还原占位符
174
for (int i = 0; i < codeFragments.size(); i++) {
175
CodeFragment codeFragment = codeFragments.get(i);
176
String fragment = codeFragment.getFragment();
177
String left = codeFragment.getLeft();
178
String right = codeFragment.getRight();
179
out = out.replace(left + "p-re" + right + (i + 1) + left
180
+ "/p-re" + right, fragment);
181
}
182
response.getOutputStream().write(out.getBytes());
183
} else {
184
response.getOutputStream().write(bytes);
185
}
186
}
187
188
@Override
189
public void init(FilterConfig filterConfig) throws ServletException {
190
this.filterConfig = filterConfig;
191
}
192
193
@Override
194
public void destroy() {
195
filterConfig = null;
196
}
197
}
刚上线的新鲜代码分享,相信对牛牛们会有所帮助吧。
注意:
1.创建和编辑类的操作不做压缩,因为访问量不大
2.<pre></pre>内部的代码不做处理
3.只对content type为html和json做的做处理
压缩前和压缩后的html代码大小对比如下图
java servlet对html网页压缩后返回的过滤器代码实现
压缩前源码
java servlet对html网页压缩后返回的过滤器代码实现
压缩后源码
java servlet对html网页压缩后返回的过滤器代码实现
另外对seo的影响可能不会很大,毕竟没有改变html结构。