过滤器(Filter)应用:全站压缩----Gzip网页压缩输出

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zuosixiaonengshou/article/details/53638136

Filter应用-7

实现压缩的输出流。
现在的网络,流量就是钱。所以,如果能在很少的流量的情况下,查看相同的数据内容,那何乐而不为呢?
实现方案:
用户在调用response.getOutputStream()时让获取自己的输出流对像, 我们将信息写到事先准备好的缓存当中。
当用户书写完毕,我们再调用自己提供的方法,获取缓存中的数据流
然后接着对数据进行压缩,在过虑器中,将信息返回给用户,从而实现数据的压缩。
 
那么如何用户调用response.getWriter进行输出时,我们怎么办呢?
能不能也对jsp所有输出进行压缩呢?
可以处理中文乱码问题吗?

配置只对部分和.jsp压缩,其他的不压缩,

            还应配置对.js.css压缩

    但决不能配置对所有请求都压缩,因为如果用户请求的是下载,那不但不能压缩,反而会让

    服务器因内存益处而崩溃。

 

canGzipWeb

在学习的过程中,分成三段,先是字节流压缩,然后是字符流压缩,最后是二者都可以压缩。

主页index.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core"	prefix="c" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>过滤器应用之全站压缩</title>
  </head>
  
  <body>
   <h1>过滤器应用之全站压缩</h1>
   <a href="<c:url value='/FirstServlet' />">请求第一个servlet----网页压缩的基本原理</a><br/>
   <a href="<c:url value='/OutputStream/SecondServlet' />">请求第二个servlet----用过滤器压缩输出字节流数据</a><br/>
   <a href="<c:url value='/Write/ThirdServlet' />">请求第三个个servlet----用过滤器压缩输出字符流数据</a><br/>
  </body>
</html>

 

FirstServlet.java  这里主要是知道压缩的基本原理,是在servlet直接压缩,没有经过过滤器压缩的

package cn.hncu.servlets;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.zip.GZIPOutputStream;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/*
 * 数据压缩的基本原理:
 * 1.源数据
 * 2.ByteArrayOutputStream字节数据流
 * 3.GZIPOutputStream字节压缩流
 * new GZIPOutputStream时把ByteArrayOutputStream放进去,然后GZIPOutputStream写数据,即写到字节数组中,然后字节数组再输出来
 */
public class FirstServlet extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doPost(request, response);
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		response.setContentType("text/html;charset=utf-8");
		
		String str="hncu湖南城院hncu湖南城院hncu湖南城院hncu湖南城院hncu湖南城院hncu湖南城院hncu湖南城院hncu湖南城院";
		System.out.println("before1:"+str.getBytes("utf-8").length);
		System.out.println("before2:"+str.getBytes().length);
		
		//压缩输出:把源数据通过GZIPOutputStream压缩到ByteArrayOutputStream中
		ByteArrayOutputStream baout=new ByteArrayOutputStream();
		GZIPOutputStream gzip=new GZIPOutputStream(baout);
		gzip.write(str.getBytes("utf-8"));
		gzip.close();
		
		//从baout中内存流中把压缩后的数据取出来,然后输出到客户端
		byte[] dest=baout.toByteArray();
		System.out.println("after:"+dest.length);
		
		//在输出之前要告诉客户端数据是gzip格式
		response.setHeader("Content-Encoding", "gzip");
		response.setContentLength(dest.length);
		response.getOutputStream().write(dest);
	}
}


字节压缩:

GzipFilter1.java

package cn.hncu.filter;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.zip.GZIPOutputStream;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;

public class GzipFilter1 implements Filter{

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		//把增强的resp放进去,放行到后台(在后台把数据写到baout中)
		MyResponse resp=new MyResponse((HttpServletResponse) response);
		
		chain.doFilter(request, resp);//放行,到后台去写数据
		
		//回来的时候拦住,从增强版的resp中把baout(源数据)压缩并用原response输出到客户端
		ByteArrayOutputStream baout=resp.getBaout();
		byte srcBytes[]=baout.toByteArray();//源字节数据
		System.out.println("过滤器中:"+srcBytes.length);
		
		ByteArrayOutputStream baout2=new ByteArrayOutputStream();
		GZIPOutputStream gzip=new GZIPOutputStream(baout2);
		gzip.write(srcBytes);
		gzip.close();//注意:此处一定要关流
		byte[] destBytes=baout2.toByteArray();
		System.out.println("压缩之后的数据长度:"+destBytes.length);
		
		//输出之前告诉客户端我们是gzip格式
		HttpServletResponse httpResp=(HttpServletResponse) response;
		httpResp.setHeader("Content-Encoding", "gzip");
		httpResp.setContentLength(destBytes.length);
		response.getOutputStream().write(destBytes);
	}

	@Override
	public void destroy() {
	}

}
class MyResponse extends HttpServletResponseWrapper{
	private ByteArrayOutputStream baout;
	public MyResponse(HttpServletResponse response) {
		super(response);
		baout=new ByteArrayOutputStream();
	}

	@Override
	public ServletOutputStream getOutputStream() throws IOException {
		return new MyOutputStream(baout);
	}
	public ByteArrayOutputStream getBaout(){
		return baout;
	}
	
}
class MyOutputStream extends ServletOutputStream{
	private ByteArrayOutputStream baout;
	public MyOutputStream(ByteArrayOutputStream baout) {
		this.baout=baout;
	}

	@Override
	public void write(int b) throws IOException {
		baout.write(b);//把数据写到baout中了
	}
	
}


 

SecondServlet.java

package cn.hncu.servlets;

import java.io.IOException;
import java.io.OutputStream;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class SecondServlet extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doPost(request, response);
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		response.setContentType("text/html;charset=utf-8");
		
		String str="";
		for(int i=0;i<=1024;i++){
			str+=i;
		}
		System.out.println("原数据大小:"+str.getBytes("utf-8").length);
		OutputStream out=response.getOutputStream();
		out.write(str.getBytes("utf-8"));//注:虽然MyEclipse环境设置的是utf-8编码,但本句str.getBytes()仍以gbk方式编码---应该是Tomcat中的JVM采用的方式
	}

}


 

字符压缩:

GzipFilter2.java

package cn.hncu.filter;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.zip.GZIPOutputStream;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;

public class GzipFilter2 implements Filter{

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		//把增强的resp放进去,放行到后台(在后台把数据写到baout中)
		MyResponse2 resp=new MyResponse2((HttpServletResponse) response);
		
		chain.doFilter(request, resp);//放行,到后台去写数据
		
		//回来的时候拦住,从增强版的resp中把baout(源数据)压缩并用原response输出到客户端
		ByteArrayOutputStream baout=resp.getBaout();
		byte srcBytes[]=baout.toByteArray();//源字节数据
		System.out.println("过滤器中:"+srcBytes.length);
		
		ByteArrayOutputStream baout2=new ByteArrayOutputStream();
		GZIPOutputStream gzip=new GZIPOutputStream(baout2);
		gzip.write(srcBytes);
		gzip.close();//注意:此处一定要关流
		byte[] destBytes=baout2.toByteArray();
		System.out.println("压缩之后的数据长度:"+destBytes.length);
		
		//输出之前告诉客户端我们是gzip格式
		HttpServletResponse httpResp=(HttpServletResponse) response;
		httpResp.setHeader("Content-Encoding", "gzip");
		httpResp.setContentLength(destBytes.length);
		response.getOutputStream().write(destBytes);
	}

	@Override
	public void destroy() {
	}

}
class MyResponse2 extends HttpServletResponseWrapper{
	private ByteArrayOutputStream baout;
	public MyResponse2(HttpServletResponse response) {
		super(response);
		baout=new ByteArrayOutputStream();
	}
	@Override
	public PrintWriter getWriter() throws IOException {
		return new PrintWriter(new OutputStreamWriter(baout, "utf-8"));
	}
	public ByteArrayOutputStream getBaout(){
		return baout;
	}
}


ThirdServlet.java

package cn.hncu.servlets;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class ThirdServlet extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doPost(request, response);
	}
	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		response.setContentType("text/html;charset=utf-8");
		
		StringBuilder sb=new StringBuilder();
		String str="";
		for(int i=0;i<1024;i++){
			sb.append(i+"你好");
		}
		str=sb.toString();
		System.out.println("压缩前数据长度:"+str.getBytes("utf-8").length);
		System.out.println("压缩前数据长度:"+str.getBytes().length);
		PrintWriter pw=response.getWriter();
		pw.println(str);
		pw.close();//关流
	}

}


 

完整版本的二者都可以压缩:

GzipFilter.java

package cn.hncu.filter;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.zip.GZIPOutputStream;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;

public class GzipFilter implements Filter{

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		MyHttpServletResponse resp=new MyHttpServletResponse((HttpServletResponse) response);
		
		chain.doFilter(request, resp);
		
		ByteArrayOutputStream baout=resp.getBaout();
		byte[] srcBytes=baout.toByteArray();
		System.out.println("srcBytes的长度:"+srcBytes.length);
		ByteArrayOutputStream baout2=new ByteArrayOutputStream();
		GZIPOutputStream gzip=new GZIPOutputStream(baout2);
		gzip.write(srcBytes);
		gzip.close();
		
		byte[] destBytes=baout2.toByteArray();
		HttpServletResponse httpResp=(HttpServletResponse) response;
		httpResp.setHeader("Content-Encoding", "gzip");
		httpResp.setContentLength(destBytes.length);
		httpResp.getOutputStream().write(destBytes);
	}

	@Override
	public void destroy() {
	}

}
class MyHttpServletResponse extends HttpServletResponseWrapper{
	private ByteArrayOutputStream baout;
	public MyHttpServletResponse(HttpServletResponse response) {
		super(response);
		baout=new ByteArrayOutputStream();
	}
	@Override
	public ServletOutputStream getOutputStream() throws IOException {
		return new MyOutputStream3(baout);
	}
	PrintWriter pw=null;
	@Override
	public PrintWriter getWriter() throws IOException {
		pw=new PrintWriter(new OutputStreamWriter(baout, "utf-8"),true);
		return pw;
	}
	public ByteArrayOutputStream getBaout(){
		if(pw!=null){
			pw.close();
		}
		return baout;
	}
}
class MyOutputStream3 extends ServletOutputStream{
	private ByteArrayOutputStream baout;
	public MyOutputStream3(ByteArrayOutputStream baout) {
		this.baout=baout;
	}

	@Override
	public void write(int b) throws IOException {
		baout.write(b);
	}
	
}


web.xml的配置

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" 
	xmlns="http://java.sun.com/xml/ns/javaee" 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
	http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
  <display-name></display-name>
  <filter>
  	<filter-name>GzipFilter1</filter-name>
  	<filter-class>cn.hncu.filter.GzipFilter1</filter-class>
  </filter>
  <filter>
  	<filter-name>GzipFilter2</filter-name>
  	<filter-class>cn.hncu.filter.GzipFilter2</filter-class>
  </filter>
  <filter>
  	<filter-name>GzipFilter</filter-name>
  	<filter-class>cn.hncu.filter.GzipFilter</filter-class>
  </filter>
  <servlet>
    <servlet-name>FirstServlet</servlet-name>
    <servlet-class>cn.hncu.servlets.FirstServlet</servlet-class>
  </servlet>
  <servlet>
    <servlet-name>SecondServlet</servlet-name>
    <servlet-class>cn.hncu.servlets.SecondServlet</servlet-class>
  </servlet>
  <servlet>
    <servlet-name>ThirdServlet</servlet-name>
    <servlet-class>cn.hncu.servlets.ThirdServlet</servlet-class>
  </servlet>


	<!-- 
	<filter-mapping>
		<filter-name>GzipFilter1</filter-name>
		<url-pattern>/OutputStream/*</url-pattern>
	</filter-mapping>
	<filter-mapping>
		<filter-name>GzipFilter2</filter-name>
		<url-pattern>/Write/*</url-pattern>
	</filter-mapping>
	 -->
	
	<filter-mapping>
		<filter-name>GzipFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>
  <servlet-mapping>
    <servlet-name>FirstServlet</servlet-name>
    <url-pattern>/FirstServlet</url-pattern>
  </servlet-mapping>
  <servlet-mapping>
    <servlet-name>SecondServlet</servlet-name>
    <url-pattern>/OutputStream/SecondServlet</url-pattern>
  </servlet-mapping>
  <servlet-mapping>
    <servlet-name>ThirdServlet</servlet-name>
    <url-pattern>/Write/ThirdServlet</url-pattern>
  </servlet-mapping>	
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
</web-app>


注意:字符流在读写时,一定要关流!

全站压缩后的网页是不影响正常访问的,区别就是,流量减少了,速度提高了。在访问的过程中,是难以察觉的。


阅读更多
换一批

没有更多推荐了,返回首页