过滤器应用案例分析

简介: ----------------------------------------------------------------------------------------------[版权申明:本文系作者原创,转载请注明出处] 文章出处:http://blog.csdn.net/sdksdk0/article/details/52077359作者:朱培      ID:sdksdk0  
----------------------------------------------------------------------------------------------
[版权申明:本文系作者原创,转载请注明出处
文章出处: 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




目录
相关文章
|
安全 网络安全 数据库
“小红书基于零信任的数据安全落地实践”演讲实录
11月,为期两天的FCIS 2023网络安全创新大会(以下简称:“FCIS 2023大会”)在上海张江科学会堂圆满落幕。来自全球的数十位网络安全人物、企业安全负责人、技术大拿、研究学者等发表主题演讲,累计线下参会观众突破6000人次。 在主论坛E-Tech企业安全实践分享中,亿格云行业标杆客户「小红书安全技术负责人、首席数据官」周达发表了“基于零信任的数据安全建设实践”的主题演讲。分别从办公场景下的数据安全挑战、小红书全链路零信任体系和安全思考与展望三方面详细阐述。
|
12月前
|
存储 搜索推荐 数据挖掘
数据库的应用
数据库在众多领域发挥着重要作用。在企业管理中,它助力客户关系、人力资源和财务管理,提升决策科学性和效率;金融领域中,银行系统、证券交易和保险行业依托数据库保障交易安全、投资决策及风险管理;医疗行业则通过电子病历管理和数据分析提高诊疗准确性并优化资源配置;电子商务运用数据库实现商品、订单管理和用户行为分析,增强购物体验;教育领域中,数据库支持学生信息、教学资源管理和教育数据分析,促进家校沟通与教学质量提升;科学研究方面,数据库促进数据共享、科研项目管理和深入数据分析,加速科学进步。
552 3
|
Prometheus Kubernetes Cloud Native
Kruise Rollout:灵活可插拔的渐进式发布框架
Kruise Rollout 是 OpenKruise 社区开源的渐进式交付框架。Kruise Rollout 支持配合流量和实例灰度的金丝雀发布、蓝绿发布、A/B Testing 发布,以及发布过程能够基于 Prometheus Metrics 指标自动化分批与暂停,并提供旁路的无感对接、兼容已有的多种工作负载(Deployment、CloneSet、DaemonSet)。近期也在《2022 开放原子全球开源峰会》上面做了主题分享,以下是主要内容。
Kruise Rollout:灵活可插拔的渐进式发布框架
|
3天前
|
SpringCloudAlibaba 负载均衡 Dubbo
微服务架构下Feign和Dubbo的性能大比拼,到底鹿死谁手?
本文对比分析了SpringCloudAlibaba框架下Feign与Dubbo的服务调用性能及差异。Feign基于HTTP协议,使用简单,适合轻量级微服务架构;Dubbo采用RPC通信,性能更优,支持丰富的服务治理功能。通过实际测试,Dubbo在调用性能、负载均衡和服务发现方面表现更出色。两者各有适用场景,可根据项目需求灵活选择。
347 123
微服务架构下Feign和Dubbo的性能大比拼,到底鹿死谁手?
|
2天前
|
Java 数据库 数据安全/隐私保护
Spring 微服务和多租户:处理多个客户端
本文介绍了如何在 Spring Boot 微服务架构中实现多租户。多租户允许单个应用实例为多个客户提供独立服务,尤其适用于 SaaS 应用。文章探讨了多租户的类型、优势与挑战,并详细说明了如何通过 Spring Boot 的灵活配置实现租户隔离、动态租户管理及数据源路由,同时确保数据安全与系统可扩展性。结合微服务的优势,开发者可以构建高效、可维护的多租户系统。
180 127
|
5天前
|
人工智能 JavaScript 测试技术
Qwen3-Coder入门教程|10分钟搞定安装配置
Qwen3-Coder 挑战赛简介:无论你是编程小白还是办公达人,都能通过本教程快速上手 Qwen-Code CLI,利用 AI 轻松实现代码编写、文档处理等任务。内容涵盖 API 配置、CLI 安装及多种实用案例,助你提升效率,体验智能编码的乐趣。
481 106
|
2天前
|
Web App开发 前端开发 API
在折叠屏应用中,如何处理不同屏幕尺寸和设备类型的样式兼容性?
在折叠屏应用中,如何处理不同屏幕尺寸和设备类型的样式兼容性?
214 124