【spring】通过GZIP压缩提高网络传输效率(可以实现任何资源的gzip压缩、包括AJAX)

gzip是http协议中使用的一种加密算法,客户端向web服务器端发出了请求后,通常情况下服务器端会将页面文件和其他资源,返回到客户端,客户端加载后渲染呈现,这种情况文件一般都比较大,如果开启Gzip ,那么服务器端响应后,会将页面,JS,CSS等文本文件或者其他文件通过高压缩算法将其压缩,然后传输到客户端,由客户端的浏览器负责解压缩与呈现。通常能节省40%以上的流量(一般都有60%左右),一些PHP,JSP文件也能够进行压缩。

1、通过WEB服务器打开GZIP压缩服务

目前大多数主流WEB中间件都支持GZIP压缩、下面以Tomcat 为例进行说明:

找到Tomcat 目录下的conf下的server.xml,并找到如下信息

      <Connector port = "8080" maxHttpHeaderSize = "8192" maxThreads = "150" minSpareThreads = "25"
              maxSpareThreads = "75" enableLookups = "false" redirectPort = "8443" acceptCount = "100"
              connectionTimeout = "20000" disableUploadTimeout = "true"

将它改成如下的形式(其实在上面代码的下面已经有了,将他们打开而已。):

      <Connector port="8080" maxHttpHeaderSize="8192" maxThreads="150" minSpareThreads="25"
             maxSpareThreads="75" enableLookups="false" redirectPort="8443" acceptCount="100"
             connectionTimeout="20000" disableUploadTimeout="true"
             compression="on" compressionMinSize="2048" noCompressionUserAgents="gozilla, traviata"
             compressableMimeType="text/html,text/xml" >

这样,就能够对html和xml进行压缩了,如果要压缩css 和 js,那么需要将

compressableMimeType=”text/html,text/xml”加入css和js:

           <Connector port="8080" ......... compressableMimeType="text/html,text/xml,text/css,text/javascript" >

一般文本类型的静态文件可以通过这种方式压缩后传输、提高传输效率。

已压缩过的静态文件(如图片)进行gzip压缩后大小基本无变化、所以一般不进行压缩。

2、通过过滤器实现gzip压缩

  1. package com.tyyd.framework.web;
  2. import java.io.IOException;
  3. import javax.servlet.Filter;
  4. import javax.servlet.FilterChain;
  5. import javax.servlet.FilterConfig;
  6. import javax.servlet.ServletException;
  7. import javax.servlet.ServletOutputStream;
  8. import javax.servlet.ServletRequest;
  9. import javax.servlet.ServletResponse;
  10. import javax.servlet.http.HttpServletRequest;
  11. import javax.servlet.http.HttpServletResponse;
  12. import org.apache.commons.io.FilenameUtils;
  13. import org.apache.commons.lang.StringUtils;
  14. import com.tyyd.framework.core.AcwsInfo;
  15. import com.tyyd.framework.core.AcwsMonitorLog;
  16. import com.tyyd.framework.core.BufferedResponse;
  17. import com.tyyd.framework.core.util.ZipUtil;
  18. /**
  19. * HTTP访问过滤器
  20. */
  21. public class PageVisitFilter2 implements Filter {
  22. @Override
  23. public void init(FilterConfig filterConfig) throws ServletException {
  24. }
  25. @Override
  26. public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
  27. //性能监控
  28. long startTime = System.currentTimeMillis();
  29. HttpServletRequest request = (HttpServletRequest)req;
  30. HttpServletResponse response = (HttpServletResponse)res;
  31. String uri = request.getRequestURI();
  32. String ext = FilenameUtils.getExtension(uri);
  33. try{
  34. response.setHeader("Pragma", "No-cache");
  35. response.setHeader("Cache-Control", "no-cache");
  36. response.setDateHeader("Expires", -1);
  37. request.setCharacterEncoding("UTF-8");
  38. response.setCharacterEncoding("UTF-8");
  39. response.setHeader("renderer", "webkit");
  40. response.setHeader("viewport", "width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0 user-scalable=no");
  41. if(isGZipEncoding(request)){
  42. //需要过滤的扩展名:.htm,.html,.jsp,.js,.ajax,.css
  43. String gzippPattern=",.htm,.html,.jsp,.js,.ajax,.css,";
  44. if(StringUtils.indexOf(gzippPattern, ",."+ext+",")!=-1){
  45. BufferedResponse gzipResponse = new BufferedResponse(response);
  46. chain.doFilter(request, gzipResponse);
  47. byte[] srcData = gzipResponse.getResponseData();
  48. byte[] outData = null;
  49. if(srcData.length > 512){
  50. byte[] gzipData = ZipUtil.toGzipBytes(srcData);
  51. response.addHeader("Content-Encoding", "gzip");
  52. response.setContentLength(gzipData.length);
  53. outData = gzipData;
  54. } else {
  55. outData = srcData;
  56. }
  57. ServletOutputStream output = response.getOutputStream();
  58. output.write(outData);
  59. output.flush();
  60. } else {
  61. chain.doFilter(request, response);
  62. }
  63. return;
  64. }
  65. chain.doFilter(request, response);
  66. }catch(Exception e){
  67. }finally{
  68. AcwsMonitorLog.warnHttpVisit(startTime, request);
  69. }
  70. }
  71. @Override
  72. public void destroy() {
  73. }
  74. /**
  75. * 判断浏览器是否支持GZIP
  76. * @param request
  77. * @return
  78. */
  79. private boolean isGZipEncoding(HttpServletRequest request){
  80. boolean flag=false;
  81. String encoding=request.getHeader("Accept-Encoding");
  82. if(encoding.indexOf("gzip")!=-1){
  83. flag=true;
  84. }
  85. return flag;
  86. }
  87. }
  1. package com.tyyd.framework.core;
  2. import java.io.IOException;
  3. import java.io.OutputStreamWriter;
  4. import java.io.PrintWriter;
  5. import javax.servlet.ServletOutputStream;
  6. import javax.servlet.http.HttpServletResponse;
  7. import javax.servlet.http.HttpServletResponseWrapper;
  8. public class BufferedResponse extends HttpServletResponseWrapper {
  9. public static final int OT_NONE = 0, OT_WRITER = 1, OT_STREAM = 2;
  10. private BufferedOutputStream outputStream = null;
  11. private PrintWriter writer = null;
  12. private int outputType = OT_NONE;
  13. public BufferedResponse(HttpServletResponse response) {
  14. super(response);
  15. outputStream = new BufferedOutputStream();
  16. }
  17. public PrintWriter getWriter() throws IOException {
  18. if (outputType == OT_STREAM)
  19. throw new IllegalStateException();
  20. else if (outputType == OT_WRITER)
  21. return writer;
  22. else {
  23. outputType = OT_WRITER;
  24. writer = new PrintWriter(new OutputStreamWriter(outputStream,
  25. getCharacterEncoding()), true);
  26. return writer;
  27. }
  28. }
  29. public ServletOutputStream getOutputStream() throws IOException {
  30. if (outputType == OT_WRITER)
  31. throw new IllegalStateException();
  32. else if (outputType == OT_STREAM)
  33. return outputStream;
  34. else {
  35. outputType = OT_STREAM;
  36. return outputStream;
  37. }
  38. }
  39. public void flushBuffer() throws IOException {
  40. try{writer.flush();}catch(Exception e){}
  41. try{outputStream.flush();}catch(Exception e){}
  42. }
  43. public void reset() {
  44. outputType = OT_NONE;
  45. outputStream.reset();
  46. }
  47. public byte[] getResponseData() throws IOException {
  48. flushBuffer();
  49. return outputStream.toByteArray();
  50. }
  51. }
  1. /**
  2. * 版权所有:
  3. * 项目名称:框架
  4. * 创建者: Wangdf
  5. * 创建日期: 2015-2-27
  6. * 文件说明: AJAX 缓存输出流
  7. */
  8. package com.tyyd.framework.core;
  9. import java.io.ByteArrayOutputStream;
  10. import java.io.IOException;
  11. import javax.servlet.ServletOutputStream;
  12. public class BufferedOutputStream extends ServletOutputStream {
  13. private ByteArrayOutputStream outputStream = null;
  14. public BufferedOutputStream(){
  15. outputStream = new ByteArrayOutputStream(1024);
  16. }
  17. /**
  18. * Writes the specified byte to this output stream. The general
  19. * contract for <code>write</code> is that one byte is written
  20. * to the output stream. The byte to be written is the eight
  21. * low-order bits of the argument <code>b</code>. The 24
  22. * high-order bits of <code>b</code> are ignored.
  23. * <p>
  24. * Subclasses of <code>OutputStream</code> must provide an
  25. * implementation for this method.
  26. *
  27. * @param      b   the <code>byte</code>.
  28. * @exception  IOException  if an I/O error occurs. In particular,
  29. *             an <code>IOException</code> may be thrown if the
  30. *             output stream has been closed.
  31. */
  32. public void write(int b) throws IOException {
  33. outputStream.write(b);
  34. }
  35. /**
  36. * Writes <code>b.length</code> bytes from the specified byte array
  37. * to this output stream. The general contract for <code>write(b)</code>
  38. * is that it should have exactly the same effect as the call
  39. * <code>write(b, 0, b.length)</code>.
  40. *
  41. * @param      b   the data.
  42. * @exception  IOException  if an I/O error occurs.
  43. * @see        java.io.OutputStream#write(byte[], int, int)
  44. */
  45. public void write(byte b[]) throws IOException {
  46. outputStream.write(b);
  47. }
  48. /**
  49. * Writes <code>len</code> bytes from the specified byte array
  50. * starting at offset <code>off</code> to this output stream.
  51. * The general contract for <code>write(b, off, len)</code> is that
  52. * some of the bytes in the array <code>b</code> are written to the
  53. * output stream in order; element <code>b[off]</code> is the first
  54. * byte written and <code>b[off+len-1]</code> is the last byte written
  55. * by this operation.
  56. * <p>
  57. * The <code>write</code> method of <code>OutputStream</code> calls
  58. * the write method of one argument on each of the bytes to be
  59. * written out. Subclasses are encouraged to override this method and
  60. * provide a more efficient implementation.
  61. * <p>
  62. * If <code>b</code> is <code>null</code>, a
  63. * <code>NullPointerException</code> is thrown.
  64. * <p>
  65. * If <code>off</code> is negative, or <code>len</code> is negative, or
  66. * <code>off+len</code> is greater than the length of the array
  67. * <code>b</code>, then an <tt>IndexOutOfBoundsException</tt> is thrown.
  68. *
  69. * @param      b     the data.
  70. * @param      off   the start offset in the data.
  71. * @param      len   the number of bytes to write.
  72. * @exception  IOException  if an I/O error occurs. In particular,
  73. *             an <code>IOException</code> is thrown if the output
  74. *             stream is closed.
  75. */
  76. public void write(byte b[], int off, int len) throws IOException {
  77. outputStream.write(b, off, len);
  78. }
  79. /**
  80. * Writes a <code>String</code> to the client,
  81. * without a carriage return-line feed (CRLF)
  82. * character at the end.
  83. *
  84. *
  85. * @param s         the <code>String</code> to send to the client
  86. *
  87. * @exception IOException   if an input or output exception occurred
  88. *
  89. */
  90. public void print(String s) throws IOException {
  91. print(s, "UTF-8");
  92. }
  93. public void print(String s, String charsetName) throws IOException {
  94. /*
  95. * 解决中文乱码问题
  96. */
  97. outputStream.write(s.getBytes(charsetName));
  98. }
  99. /**
  100. * Writes a <code>boolean</code> value to the client,
  101. * with no carriage return-line feed (CRLF)
  102. * character at the end.
  103. *
  104. * @param b         the <code>boolean</code> value
  105. *              to send to the client
  106. *
  107. * @exception IOException   if an input or output exception occurred
  108. *
  109. */
  110. public void print(boolean b) throws IOException {
  111. print(b?"true":"false");
  112. }
  113. /**
  114. * Writes a character to the client,
  115. * with no carriage return-line feed (CRLF)
  116. * at the end.
  117. *
  118. * @param c         the character to send to the client
  119. *
  120. * @exception IOException   if an input or output exception occurred
  121. *
  122. */
  123. public void print(char c) throws IOException {
  124. print(String.valueOf(c));
  125. }
  126. /**
  127. *
  128. * Writes an int to the client,
  129. * with no carriage return-line feed (CRLF)
  130. * at the end.
  131. *
  132. * @param i         the int to send to the client
  133. *
  134. * @exception IOException   if an input or output exception occurred
  135. *
  136. */
  137. public void print(int i) throws IOException {
  138. print(String.valueOf(i));
  139. }
  140. /**
  141. *
  142. * Writes a <code>long</code> value to the client,
  143. * with no carriage return-line feed (CRLF) at the end.
  144. *
  145. * @param l         the <code>long</code> value
  146. *              to send to the client
  147. *
  148. * @exception IOException   if an input or output exception
  149. *              occurred
  150. *
  151. */
  152. public void print(long l) throws IOException {
  153. print(String.valueOf(l));
  154. }
  155. /**
  156. *
  157. * Writes a <code>float</code> value to the client,
  158. * with no carriage return-line feed (CRLF) at the end.
  159. *
  160. * @param f         the <code>float</code> value
  161. *              to send to the client
  162. *
  163. * @exception IOException   if an input or output exception occurred
  164. *
  165. *
  166. */
  167. public void print(float f) throws IOException {
  168. print(String.valueOf(f));
  169. }
  170. /**
  171. *
  172. * Writes a <code>double</code> value to the client,
  173. * with no carriage return-line feed (CRLF) at the end.
  174. *
  175. * @param d         the <code>double</code> value
  176. *              to send to the client
  177. *
  178. * @exception IOException   if an input or output exception occurred
  179. *
  180. */
  181. public void print(double d) throws IOException {
  182. print(String.valueOf(d));
  183. }
  184. /**
  185. * Writes a carriage return-line feed (CRLF)
  186. * to the client.
  187. *
  188. *
  189. *
  190. * @exception IOException   if an input or output exception occurred
  191. *
  192. */
  193. public void println() throws IOException {
  194. print("\r\n");
  195. }
  196. /**
  197. * Writes a <code>String</code> to the client,
  198. * followed by a carriage return-line feed (CRLF).
  199. *
  200. *
  201. * @param s         the <code>String</code> to write to the client
  202. *
  203. * @exception IOException   if an input or output exception occurred
  204. *
  205. */
  206. public void println(String s){
  207. println(s, "UTF-8");
  208. }
  209. public void println(String s, String charsetName){
  210. /*
  211. * 解决中文乱码问题
  212. */
  213. try {
  214. print(s,charsetName);
  215. println();
  216. } catch (IOException e) {
  217. throw new RuntimeException(e);
  218. }
  219. }
  220. /**
  221. *
  222. * Writes a <code>boolean</code> value to the client,
  223. * followed by a
  224. * carriage return-line feed (CRLF).
  225. *
  226. *
  227. * @param b         the <code>boolean</code> value
  228. *              to write to the client
  229. *
  230. * @exception IOException   if an input or output exception occurred
  231. *
  232. */
  233. public void println(boolean b) throws IOException {
  234. print(b);
  235. println();
  236. }
  237. /**
  238. *
  239. * Writes a character to the client, followed by a carriage
  240. * return-line feed (CRLF).
  241. *
  242. * @param c         the character to write to the client
  243. *
  244. * @exception IOException   if an input or output exception occurred
  245. *
  246. */
  247. public void println(char c) throws IOException {
  248. print(c);
  249. println();
  250. }
  251. /**
  252. *
  253. * Writes an int to the client, followed by a
  254. * carriage return-line feed (CRLF) character.
  255. *
  256. *
  257. * @param i         the int to write to the client
  258. *
  259. * @exception IOException   if an input or output exception occurred
  260. *
  261. */
  262. public void println(int i) throws IOException {
  263. print(i);
  264. println();
  265. }
  266. /**
  267. *
  268. * Writes a <code>long</code> value to the client, followed by a
  269. * carriage return-line feed (CRLF).
  270. *
  271. *
  272. * @param l         the <code>long</code> value to write to the client
  273. *
  274. * @exception IOException   if an input or output exception occurred
  275. *
  276. */
  277. public void println(long l) throws IOException {
  278. print(l);
  279. println();
  280. }
  281. /**
  282. *
  283. * Writes a <code>float</code> value to the client,
  284. * followed by a carriage return-line feed (CRLF).
  285. *
  286. * @param f         the <code>float</code> value
  287. *              to write to the client
  288. *
  289. *
  290. * @exception IOException   if an input or output exception
  291. *              occurred
  292. *
  293. */
  294. public void println(float f) throws IOException {
  295. print(f);
  296. println();
  297. }
  298. /**
  299. *
  300. * Writes a <code>double</code> value to the client,
  301. * followed by a carriage return-line feed (CRLF).
  302. *
  303. *
  304. * @param d         the <code>double</code> value
  305. *              to write to the client
  306. *
  307. * @exception IOException   if an input or output exception occurred
  308. *
  309. */
  310. public void println(double d) throws IOException {
  311. print(d);
  312. println();
  313. }
  314. /**
  315. * Flushes this output stream and forces any buffered output bytes
  316. * to be written out. The general contract of <code>flush</code> is
  317. * that calling it is an indication that, if any bytes previously
  318. * written have been buffered by the implementation of the output
  319. * stream, such bytes should immediately be written to their
  320. * intended destination.
  321. * <p>
  322. * If the intended destination of this stream is an abstraction provided by
  323. * the underlying operating system, for example a file, then flushing the
  324. * stream guarantees only that bytes previously written to the stream are
  325. * passed to the operating system for writing; it does not guarantee that
  326. * they are actually written to a physical device such as a disk drive.
  327. * <p>
  328. * The <code>flush</code> method of <code>OutputStream</code> does nothing.
  329. *
  330. * @exception  IOException  if an I/O error occurs.
  331. */
  332. public void flush() throws IOException {
  333. outputStream.flush();
  334. }
  335. /**
  336. * Closes this output stream and releases any system resources
  337. * associated with this stream. The general contract of <code>close</code>
  338. * is that it closes the output stream. A closed stream cannot perform
  339. * output operations and cannot be reopened.
  340. * <p>
  341. * The <code>close</code> method of <code>OutputStream</code> does nothing.
  342. *
  343. * @exception  IOException  if an I/O error occurs.
  344. */
  345. public void close() throws IOException {
  346. outputStream.close();
  347. }
  348. /**
  349. * Resets the <code>count</code> field of this byte array output
  350. * stream to zero, so that all currently accumulated output in the
  351. * output stream is discarded. The output stream can be used again,
  352. * reusing the already allocated buffer space.
  353. *
  354. * @see     java.io.ByteArrayInputStream#count
  355. */
  356. public void reset() {
  357. outputStream.reset();
  358. }
  359. public byte[] toByteArray() {
  360. return outputStream.toByteArray();
  361. }
  362. }

在web.xml中配置 PageVisitFilter,当我们访问应用中以.htm,.html,.jsp,.js,.ajax,.css结尾的资源的使用,服务器端就开启http gzip压缩,将压缩后的信息通过http 协议传递给浏览器.

  1. <filter>
  2. <filter-name>Page Visit Filter</filter-name>
  3. <filter-class>com.tyyd.framework.web.PageVisitFilter</filter-class>
  4. </filter>
  5. <filter-mapping>
  6. <filter-name>Page Visit Filter</filter-name>
  7. <url-pattern>/*</url-pattern>
  8. </filter-mapping>

3、AJAX也可以通过这种方式压缩

只需知道ajax请求的后缀添加到下面的代码中即可:

//需要过滤的扩展名:.htm,.html,.jsp,.js,.ajax,.css

String gzippPattern=",.htm,.html,.jsp,.js,.ajax,.css,";

GZIP压缩提高网络传输效率的更多相关文章

  1. 网页启用Gzip压缩 提高浏览速度

    启用Gzip压缩的好处 它的好处显而易见,提高网页浏览速度,无论是之前说的精简代码.压缩图片都不如启用Gzip来的实在.下图为启用Gzip后的效果. Gzip压缩效率非常高,通常可以达到70%的压缩率 ...

  2. 170306、wamp中的Apache开启gzip压缩提高网站的响应速度

    一个网站的响应速度决定该网站的人气和质量,所以wamp配置的服务器也需要支持giz压缩来提高网站的响应速度,如何开启wamp的gzip压缩呢,经过在网站查找资料结合自己服务器中的配置,现在将这个方法分 ...

  3. Nginx开启Gzip压缩提高页面加载速度

    本文转自http://www.veryhuo.com/a/view/51706.html,如有侵权,请及时联系转载人删除! 在实际运维中,为了提高web页面的访问加载速度,一般会把静态资源(比如js. ...

  4. Okhttp3请求网络开启Gzip压缩

    前沿 首先OkHttp3是支持Gzip解压缩的,不过我们要明白,它是支持我们在发起请求的时候自动加入header,Accept-Encoding: gzip,而我们的服务器返回的时候header中有C ...

  5. 聊聊HTTP gzip压缩与常见的Android网络框架

    版权声明: 欢迎转载,但请保留文章原始出处 作者:GavinCT 出处:http://www.cnblogs.com/ct2011/p/5835990.html 进入主题之前,我们先来看一下客户端与服 ...

  6. Nginx网络架构实战学习笔记(三):nginx gzip压缩提升网站速度、expires缓存提升网站负载、反向代理实现nginx+apache动静分离、nginx实现负载均衡

    文章目录 nginx gzip压缩提升网站速度 expires缓存提升网站负载 反向代理实现nginx+apache动静分离 nginx实现负载均衡 nginx gzip压缩提升网站速度 网页内容的压 ...

  7. 在windows、linux中开启nginx的Gzip压缩大大提高页面、图片加载速度<转>

    为了降低tomcat服务的压力,把页面上的图片采用windows版的nginx进行加载,由于有些图片比较大,加载特别的慢,所以在nginx中打开了gzip的压缩功能.加载图片的速度快了很多. 通过站长 ...

  8. Java Web 减少网络 IO、静态资源磁盘 IO 有效的办法--响应使用 GZIP( 压缩http请求与响应gzip压缩)

    (转载http://blog.csdn.net/hylclxy/article/details/7779662) 出于节约流量考虑, 客户端在向服务端发送request的时候对post数据进行gzip ...

  9. nginx优化:配置gzip压缩页面提高访问速度(nginx1.18.0)

    一,为什么nginx要使用gzip 1,压缩的作用: 页面使用gzip压缩之后, 页面大小可以压缩到原来的1/7左右, 传输速度和页面打开时间都可以大幅度提高, 有利于用户访问页面体验的提升 2,Ng ...

随机推荐

  1. 使用jQuery和CSS3实现一个数字时钟

    点击进入更详细教程及源码下载     在线演示 我们经常会在网站中看见一个时钟的效果.今天向大家分享一个使用jQuery和CSS3实现一个数字时钟教程. http://www.html5cn.org/ ...

  2. loadrunner录制的时候如何应对验证码的问题解决办法?

    对这个问题,我个人的看法是,基本上可以考虑从三个途径来解决该问题: 1.第一种方法,也是最容易想到的,在被测系统中暂时屏蔽验证功能,也就是说,临时修改应用,无论用户输入的是什么验证码,都认为是正确的. ...

  3. SpringMVC处理请求

    HttpServletBean HttpServletBean主要参与了创建工作,并没有涉及请求的处理. FrameworkServlet FrameworkServlet的service方法里添加了 ...

  4. mac下载的excel如果带有超链接,url被转义问题

    注释的代码是file开头的,这种链接在mac系统进行跳转url会转义 hyperlink 还有一种就是http这种就可以正常跳转了. String sLink = basePath + "/ ...

  5. The Tomcat connector configured to listen on port 8080 failed to start. The port may already be in use or the connector may be misconfigured

    springboot 8080端口被占用报错:The Tomcat connector configured to listen on port 8080 failed to start. The p ...

  6. 异常检测(anomaly detection)

    版权声明:本文为博主原创文章,转载或者引用请务必注明作者和出处,尊重原创,谢谢合作 https://blog.csdn.net/u012328159/article/details/51462942 ...

  7. 自定义mysql类用于快速执行数据库查询以及将查询结果转为json文件

    由于每次连接数据库进行查询比较麻烦,偶尔还需要将查询结果转为json格式的文件, 因此暂时定义一个mysql的类,将这些常用的方法进行封装,便于直接调用(代码如下,个人用,没写什么注释). 注:导入了 ...

  8. January 20th, 2018 Week 3rd Saturday

    We may encounter many defeats but we must not be defeated. 我们可能会失败很多次,但决不能被打败. As long as we are con ...

  9. 浅析Java中的23种设计模式

    前言 设计模式不论是在我们学习编程,还是在工作和面试过程中,都会涉及到的一个问题,所以了解和学习好设计模式,是我们每一位码农必须要具备的技能,对以后的发展和自己技能的提升都有好处. 什么是设计模式(D ...

  10. 字符串之StringBuffer 与 StringBuilder的对比

    StringBuilder 和 StringBuffer是高度类似的两个类 StringBuilder是StringBuffer的版本改写,下面从几个方面简单的对比下他们的区别 原文地址:[十四]基础 ...