过滤器应用案例分析

----------------------------------------------------------------------------------------------
[版权申明:本文系作者原创,转载请注明出处] 
文章出处:http://blog.csdn.net/sdksdk0/article/details/52077359
作者:朱培      ID:sdksdk0      邮箱: zhupei@tianfang1314.cn   

--------------------------------------------------------------------------------------------

本文主要分享的内容是通过使用过滤器解决全站乱码、Html过滤、脏话过滤、Gzip压缩过滤等主要内容,是一个切实解决网站实际问题的一套方案。

一、过滤器简介

Filter,对web服务器管理的所有web资源对请求和响应对象进行拦截。例如实现URL级别的权限访问控制、过滤敏感信息。

下面来看一下过滤器的执行过程和生命周期

生命周期

初始化:当应用被加载时,由服务器调用默认的构造方法,并接着调用初始化方法。
doFilter:一直伴随着应用程序而存在,用户每次访问被过滤的资源,都会调用doFilter方法。
销毁:应用被卸载的时候。

执行过程

1、在javaweb服务器:服务器启动时加载应用,加载应用的配置文件web.xml,实例化过滤器并初始化。
2、浏览器请求index.jsp。
3、创建request和response,经过过滤器,调用request,response,FilterChain。
4、通过FilterChain()处理。

开发步骤

1、写一个类,继承Filter接口
2、配置web.xml。指定需要过滤的资源

    <!-- 定义过滤器 -->
	<filter>
		<filter-name>Demo1</filter-name>
		<filter-class>cn.tf.filter.Demo1</filter-class>
	</filter>

	<!-- 映射要过滤的资源 -->
	<filter-mapping>
		<filter-name>Demo1</filter-name>
		<url-pattern>/index.jsp</url-pattern>
	</filter-mapping>

二、全站乱码

我们以前对于网站乱码的问题大多数是直接在servlet中rerquest.setCharacterEncoder("UTF-8")这样来解决,但是对于多个servlet重复也的话就非常不好了,及其不方便,所以我们可以使用一个过滤器来对整站的编码进行设置。

新建一个类SetCharacterEncodingFilter,使其继承Filter接口。然后实现其3个生命周期方法init()、doFilter()、destroy(),当然,我们需要对其doFilter方法进行操作了。在这里面设置编码就可以了

public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {

		String encoding = filterConfig.getInitParameter("encoding");
		if(encoding==null)
			encoding = "UTF-8";

		request.setCharacterEncoding(encoding);//解决POST请求参数编码
		response.setCharacterEncoding(encoding);//更改响应字符流使用的编码
		response.setContentType("text/html;charset="+encoding);//更改响应字符流使用的编码,还能告知浏览器用什么编码进行显示
		chain.doFilter(request, response);
	}

使用chain.doFilter释放拦截。
然后我们就到web.xml中去配置一个这个过滤器。这个找到你直接的类路径就可以了,/*是通配符,表示全站过滤,如果你只想要过滤某一种类型的文件,只需要修改相应的<url-pattern>就可以了,例如是想要jsp的格式改变,就改成*.jsp即可。

<filter>
	  	<filter-name>SetCharacterEncodingFilter</filter-name>
	  	<filter-class>cn.tf.filter.SetCharacterEncodingFilter</filter-class>
	  </filter>
	  <filter-mapping>
	  	<filter-name>SetCharacterEncodingFilter</filter-name>
	  	<url-pattern>/*</url-pattern>
	  </filter-mapping>

三、Html过滤

对于一个网站来说,进行html过滤是非常有必要的,因为在执行某些操作的时候,很有看通过html文件对你的网站注入html进行攻击,一方面防止攻击,一方面使用户体验度更好,所以我们常常需要进行html标签过滤。

首先新建一个类HtmlFilter,使其继承Filter接口,在doFilter中进行操作。

public void doFilter(ServletRequest req, ServletResponse resp,
			FilterChain chain) throws IOException, ServletException {
		HttpServletRequest request;
		HttpServletResponse response;

		try {
			request=(HttpServletRequest) req;
			response=(HttpServletResponse) resp;
		} catch (Exception e) {
			throw new RuntimeException(e);
		}

		HttpServletRequest hrequest=new HtmlHttpServletRequest(request);
		chain.doFilter(hrequest,response);

	}

这里我们把HtmlHttpServletRequest写出来

class HtmlHttpServletRequest extends HttpServletRequestWrapper{

	public HtmlHttpServletRequest(HttpServletRequest request) {
		super(request);

	}

	@Override
	public String getParameter(String name) {

		String value=super.getParameter(name);
		if(value==null)
			return null;
		value=filter(value);
		return value;
	}

	private String filter(String message) {
		 if (message == null)
	            return (null);

	        char content[] = new char[message.length()];
	        message.getChars(0, message.length(), content, 0);
	        StringBuilder result = new StringBuilder(content.length + 50);
	        for (int i = 0; i < content.length; i++) {
	            switch (content[i]) {
	            case '<':
	                result.append("<");
	                break;
	            case '>':
	                result.append(">");
	                break;
	            case '&':
	                result.append("&");
	                break;
	            case '"':
	                result.append(""");
	                break;
	            default:
	                result.append(content[i]);
	            }
	        }
	        return (result.toString());
	}
	}

同样的,我们需要在web.xml中进行配置

 <!-- 过滤html -->
	 <filter>
	 <filter-name>HtmlFilter</filter-name>
	  	<filter-class>cn.tf.filterHtml.HtmlFilter</filter-class>
	  </filter>
	  <filter-mapping>
	  	<filter-name>HtmlFilter</filter-name>
	  	<url-pattern>/*</url-pattern>
	  </filter-mapping>

处理前效果:

处理后:

四、脏话过滤

对于脏话过滤在一些论坛网站等都是非常常见的功能,实现这个功能的方法非常多,你可以直接用js来做判断也是可以,这里我介绍的是另一种方法,就是通过过滤器来对脏话进行过滤,把脏话都替换为*号。

同样的,新建一个类DirtyWordsFilter.java,实现其Filter接口。

public void doFilter(ServletRequest req, ServletResponse resp,
			FilterChain chain) throws IOException, ServletException {
		HttpServletRequest request;
		HttpServletResponse response;

		try {
			request=(HttpServletRequest) req;
			response=(HttpServletResponse) resp;
		} catch (Exception e) {
			throw new RuntimeException(e);
		}

		DWHttpServletRequest  dwrequest=new DWHttpServletRequest(request) ;
		chain.doFilter(dwrequest, response);
	}

在这里对脏话进行处理。

class DWHttpServletRequest extends HttpServletRequestWrapper{

		private String[] strs={"傻逼","人妖","他妈的"};

		public DWHttpServletRequest(HttpServletRequest request) {
			super(request);

		}

		@Override
		public String getParameter(String name) {
			String value=super.getParameter(name);
			if(value==null)
				return null;

			for(String s:strs){
				value=value.replace(s, "**");
			}
			return value;
		}

	}

处理前效果:

处理后效果:

五、Gzip压缩

在网站数据传输的时候,我们通常为了节省流量,加快传输速度等原因,通常需要把文件进行压缩,不但是用户请求的页面,例如当用户访问你的index.html页面的时候,从你的服务器传输到用户的客户端,如果直接传输整个人html页面是很耗资源的(当然是对于大量用户访问),所以我们需要把页面压缩之后再传输,这个我们就可以通过过滤器来实现了。

新建GzipFilter.java,使其继承Filter接口。

 

public void doFilter(ServletRequest req, ServletResponse resp,
			FilterChain chain) throws IOException, ServletException {
		HttpServletRequest request;
		HttpServletResponse response;

		try {
			request=(HttpServletRequest) req;
			response=(HttpServletResponse) resp;
		} catch (Exception e) {
			throw new RuntimeException(e);
		}

		MyHttpServletResponse  mresponse=new MyHttpServletResponse(response);
		chain.doFilter(request, mresponse);

		//获取原始数据
		byte b[] = mresponse.getOldData();
		System.out.println("压缩前:"+b.length);
		//GZIP压缩
		ByteArrayOutputStream out = new ByteArrayOutputStream();//内存字节缓存输出流
		GZIPOutputStream gout = new GZIPOutputStream(out);
		gout.write(b);
		gout.close();//压缩后的数据写到了ByteArrayOutputStream中了

		b = out.toByteArray();//取出压缩后的数据
		System.out.println("压缩后:"+b.length);
		//告知客户端正文的压缩方式:gzip
		response.setHeader("Content-Encoding", "gzip");
		response.setContentLength(b.length);//响应消息头,告知客户端正文的长度
		response.getOutputStream().write(b);
	}

对字符流、字节流进行处理。

class MyHttpServletResponse  extends HttpServletResponseWrapper{

		private ByteArrayOutputStream baos=new ByteArrayOutputStream();
		private PrintWriter pw = null;
		public MyHttpServletResponse(HttpServletResponse response) {
			super(response);

		}

		//截获数据:字符流
		public PrintWriter getWriter() throws IOException {
			pw = new PrintWriter(new OutputStreamWriter(baos, super.getCharacterEncoding()));
			return pw;
		}

		//截获数据:字节流
		public ServletOutputStream getOutputStream() throws IOException {
			return new MyServletOutputStream(baos);
		}

		//返回截取的数据
		public byte[] getOldData(){
			try {
				if(pw!=null){
					pw.close();
				}
				baos.flush();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

			return baos.toByteArray();
		}

	}

		class MyServletOutputStream extends ServletOutputStream{

			private ByteArrayOutputStream  baos;

			public MyServletOutputStream(ByteArrayOutputStream baos){
				this.baos=baos;
			}

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

			}

		}

当然,我们同样要在web.xml中配置。这里的话我们不需要全部过滤,只需要过滤jsp、html、js、css类型的即可。

<!-- GZIP压缩 -->
 <filter>
	 <filter-name>GzipFilter</filter-name>
	  	<filter-class>cn.tf.filterHtml.GzipFilter</filter-class>
	  </filter>
	  <filter-mapping>
	  	<filter-name>GzipFilter</filter-name>
	  	<url-pattern>*.jsp</url-pattern>
	  </filter-mapping>
	  	  <filter-mapping>
	  	<filter-name>GzipFilter</filter-name>
	  	<url-pattern>*.html</url-pattern>
	  </filter-mapping>
	  	  <filter-mapping>
	  	<filter-name>GzipFilter</filter-name>
	  	<url-pattern>*.js</url-pattern>
	  </filter-mapping>
	  	  <filter-mapping>
	  	<filter-name>GzipFilter</filter-name>
	  	<url-pattern>*.css</url-pattern>
	  </filter-mapping>

在servlet中使用:

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

		String data="你们好啊fyufbdljsbcjlksdnckdnjkdhjfbjcnjdjkdsnkklqispkxlndkehlfehihiohfdidsisildnckdnilfiefilefkkdhwgflkfnioufhyoinckdnckllhdefwvvewfefrvb54eqgdfbfdbgsfngfnhggfns";
		PrintWriter out = response.getWriter();
		out.write(data);
	}

使用Gzip压缩我们需要注意的是,数据量如果太小了的话,压缩之后会变更大了,数据量至少应该在150个字节以上的再压缩,否则会适得其反。

总结:本文主要是通过四个常用的案例来说明了Filter过滤器的使用,都是一些非常简单易用的知识。对于一名合格的开发者来说,这些知识都是必须要掌握的。共勉!欢迎关注!

源码下载:https://github.com/sdksdk0/FilterDemo

时间: 2025-01-20 21:59:50

过滤器应用案例分析的相关文章

案例分析:如何将免费社区转化为成功的商业模式

社区 Nisan Gabbay注:非常高兴本周的案例分析出自Startup Review的读者Kempton Lam. Kempton是一位管理咨询师,专于创业指导,您可以查看Kempton的背景及博客.Kempton采用了和我相同的案例分析流程,作为编辑,我的工作是确保其与Startup Review保持格式上的一致.如果你有意成为Startup Review的嘉宾作者,请与我联系. 为什么研究这个案例 iStockphoto既是一个摄影师社区,也是一个高质低价的庞大图片库.到2006年10月

Digg&amp;nbsp;案例分析:为什么技术人群是重要的用户

一直觉得Digg是我错过的了一个Web2.0应用,想去研究研究一下,感谢丁丁提供的译文! Digg 案例分析:为什么技术人群是重要的用户原文作者:Nisan Gabbay***:雷声大雨点大原文链接:Digg Case Study: Why techies are an important audience原文发表时间:2006年10月15日 为什么做这个案例分析从2004年12月面世至今,Digg已经成为Web2.0的成功典型.Digg是一个提供新闻内容的网站,它一反传统的层层审核的编辑制度.

广场舞案例分析深入思考二:别样冲突

前面对于Robin广场舞案例从我个人的角度作了深入思考,可能都是一些基础的技巧,但是运用到全面的SEO工作当中还是相当不错的一些技巧,尤其是对没有形成体系的朋友显得尤为重要.最近在不少群里面见到有些朋友认为SEO很简单,个人还是有点担忧,因为SEO真的不是那么简单,而且要真正的学好SEO,这里指的不仅仅是执行的SEO,而是要真正要建立良好的SEO知识结构体系和SEO全局观的SEO. 当然,这两个问题并不是今天我要跟大家谈的想法,后面如果有机会可以跟大家多探讨探讨.今天我要跟大家交流的依然是关于广

案例分析:老张的搬家公司(4)

<老张的搬家公司>第三篇中,我觉得老张很难应用百度凤巢来推广自己的业务,主要原因在于竞争成本.对此,天岸提出了不同看法. 天岸提出的第一点:"除去营销因素之外,有没有考虑到运营因素呢?也许这些出高价的搬家公司的利润很高呢(价格高,相对成本低)?那么理所当然的,点击成本和折算后的转化成本(如果他们有计算的话)对于他们来说是没有多少影响的.本身竞争优势的缺陷也是限制老张们使用更好的营销方法的因素之一吧." 因为这个问题非常好,所以我又舍不得在直接回复了,还是拉出来再成一篇. 老

案例分析:在谈网络公司关键词提升方案

之前荣超帮助朋友分析了一个站点案例分析:一套网络公司网站排名方案那时候好像是5.8号分析的网站,到现在5.16号已经过了8天,早上的时候发现百度昨晚有更新,然后我在去看排名的时候发现排名有部分不错,但是还是没有挺近首页,那么荣超今天在继续看看这个站点吧 首先我们先开关注一下在8天中排名情况吧: 我们可以看到经过改进网站排名已经出现在百度前100位了,之前是没有一个排名在前100名的,但是现在的排名根本对于根本没有任何作用,毕竟别人搜索不会到后面去看你的站点,所以这次我们主要做的就是如何提高排名,

实战案例分析 一个月指数500排名第一

之前就看见了许多实战案例分析的例子,但大多还是一些理论,并没有细节到每一个动作与步骤.今天,我的站刚好上线一个月.今天关键词排名一跃升为第一.看似偶然的事,实是必然.今天和大家分析新站真正快速排名的奥秘,希望其中有某一些改动,某一些细节可以让大家灵感一现,找到自己网站的优化之道. 这个站域名注册时间是6月28日,7月22号上线,迄今为止刚好1个月时间.凤凰古城,指数是5000-6000.凤凰古城住宿,指数500+.其中的热门度不用我说,大家搜索一下便知.当今天打开电脑时,看到网站已经排名第一,说

水杯SEO:百度快照标题显示不正常的案例分析

百度快照标题显示不正常的案例分析,今天水杯在昨天发现水杯SEO博客也出现了百度快照标题显示不正常,这次不同的是,水杯SEO博客只上线了一个星期,虽然百度收录只收录了网站首页,但是快照在上线当天就更新了,刚开始的快照是8-5号,接下来第二次更新快照星期三晚上8-10号,现在的快照是昨天晚上的8-11号,但是快照更新了,网站标题显示却不正常,这个问题相信也有朋友遇到过,现在水杯来和大家一起分析解决这个问题. 在之前的<案例分析:网站百度快照被删除的原因>中,我们发现电脑知识网的情况也是这样,快照隔

实战案例分析网站排名之第一章

这篇<实战案例分析网站排名之第一章>主要是为了和大家一起分析排在百度搜索结果第一位的网站情况,以实例的方式让大家的分析思路更清晰,现在大部分SEO培训教学中所灌输的潜意识都是以内容为皇.外链为王的理论知识,很多SEO导师都是建议网站应该发布原创内容,可有几个网站能够每天都坚持更新原创内容呢?而网站外部链接也是如此,导师都是建议发布高质量的外部链接,可高质量的外部链接怎么可能那么容易就获得呢?那究竟"内容垃圾"."外部链接质量低"的网站能不能获得良好的排名

百度快速排名之案例分析

百度快速排名之案例分析-(一个医药网站的百度30天优化案例分析)网站名称香草醇.阿魏酸.高哌嗪.酚磺乙胺.羟苯磺酸钙-苏州布莱恩斯国际 :网站域名:http://www.szbles.com 网站在10月份接到优化的任务,11月中旬已经有词香草醇已经到第一名了.大家可以在百度上查的到. 先来分析一下关键词:香草醇百度收录(找到相关结果约2,070,000个)也就是说百度数据在200多万条.应该来说优化的难度不是很大.百度指数查不到关键词的指数可以说是很少人会查这样的词,换句话说只有专业的人士才会