Filter(过滤器)、Listener(监听器)

一: 过滤器: 可以把"不和谐"的东西给过滤掉

01.过滤器概述

生活中的过滤器:带有过滤功能的净水器,滤纸,香烟的过滤嘴,测试,丈母娘.

程序中的过滤器:JAVA中最小的程序单元是类,程序中的过滤器就是一个特殊的类
		
			  Servelt/Filter是Web的一个组件.
Web中过滤器的作用(简单理解为:过滤器处在客户端和服务端资源之间):

		过滤器可以对所有的请求或者响应做拦截操作.
	
		1:以常规的方式调用资源(Servelt/JSP);
		
		2:利用修改过的请求信息调用资源;
		
		3:调用资源之后,但在响应到客户端之前,对响应做出修改;
		
		4:阻止当前资源调用,代之转带其他资源.

02.过滤器的应用

过滤器在开发中的应用:

	1):可以对请求中的字符做编码.
	
	2):登录验证过滤器.
	
	3):敏感字(非法文字)过滤.

	4):MVC框架中的前端控制器(处理所有请求共同操作,再分发)
在开发中两个常用的思想:

	1):DRY原则: Don't Repeat Yourself.
			
		开发中拒绝代码重复,(重复会带来巨大的维护成本)
	
	2):责任分离原则:各自做各自最擅长的事情.

03:开发和使用Filter

Servlet开发:
	
		1:自定义一个类(XxxServlet),实现于javax.servlet.Servlet接口.
		
		2:实现Servelt接口中的方法(init(初始化方法),service(处理请求))
		
		3:告诉Tomcat来帮我们管理该Servlet程序(1:使用web.xml做配置,2:WebServlet("/资源名")).
		
		<servlet>
				<servlet-name>Servlet的别名</servlet-name>
				<servlet-class>自定义Servelt的全限定名</servlet-class>
		</servlet>
		<servlet-mapping>
				<servlet-name>Servlet的别名</servlet-name>
				<url-pattern>/资源名</url-pattern>
		</servlet-mapping>
			
		注意:此时的url-pattern的文本内容是外界访问Servelt的资源名称.
Filter开发:
	
		1:自定义一个类(XxxFilter),实现于javax.servlet.Filter接口.
		
		2:实现Filter接口中的方法(init(初始化方法),doFilter(处理请求))
		
		3:告诉Tomcat来帮我们管理该Filter程序(1:使用web.xml做配置,2:WebFilter("/资源名")).
		
		<filter>
				<filter-name>Filter的别名</filter-name>
				<filter-class>自定义Filter的全限定名</filter-class>
		</filter>
		<filter-mapping>
				<filter-name>Filter的别名</filter-name>
				<url-pattern>/资源名</url-pattern>
		</filter-mapping>
			
		注意:此时的url-pattern的文本内容是Filter对哪一些资源做过滤操作.
			
			如:   /hello.jsp           :说明当前Filter只会对/hello.jsp做拦截/过滤.
				  /employee            :说明当前Filter只会对/enployee资源做过滤.
				  /system/*            :说明当前Filter只会对以/system/作为前缀的资源路径做拦截.
filterChain(过滤器链):多个过滤器按照一定的顺序,排列起来.

拦截器栈:
--------------------------------------------------------
程序中存在多个过滤器的时候,过滤器的先后执行顺序由谁来决定.		

	在WEB.xml中:配置的<fiter-mapping>的先后顺序来决定.

过滤器的的先后执行顺序示意图
过滤器的的先后执行顺序示意图

04.Filter的细节

过滤器的映射细节:

1):filter中的url-pattern的文本内容是Filter对哪一些资源做过滤操作.
	
		:	    /hello.jsp           :说明当前Filter只会对/hello.jsp做拦截/过滤.
				/employee            :说明当前Filter只会对/enployee资源做过滤.
				/system/*            :说明当前Filter只会对以/system/作为前缀的资源路径做拦截.
				/*                   :说明对所有的资源做过滤.
				/*.do                :对所有以 .do 结尾的资源做拦截
2):Filter的dispatcher(表示对哪些动作作过滤).

		<filter-mapping>
			<filter-name>FilterDemo1</filter-name>
			<url-pattern>/*</url-pattern>
			<url-pattern>/x1</url-pattern>
			<!-- 只对请求做拦截(默认) -->
			<dispatcher>REQUEST</dispatcher>
			<!-- 增加对请求转发做拦截 -->
			<dispatcher>FORWARD</dispatcher>
			<!-- 增加请求包含做拦截 -->
			<dispatcher>INCLUDE</dispatcher>
			<!-- 增加跳转到错误页面做拦截 -->
			<dispatcher>ERROR</dispatcher>
	</filter-mapping>
	
	<error-page>
			<error-code>404</error-code>
			<location>/404.jsp</location>
	</error-page>			

05.请求编码过滤器CharacterEncodingFilter

Servelt只管 1:获取 2:调用 3:跳转 就行,设置编码交给Filter就行, DRY原则 跟 责任分离原则!
	//字符编码过滤器
	public class CharacterEncodingFilter implements Filter{
	
		private String encoding;	
		
		private Boolean forceEncoding = false;
		
		public void init(FilterConfig config) throws ServletException {
			this.encoding = config.getInitParameter("encoding");
			forceEncoding = Boolean.valueOf(config.getInitParameter("force"));
		}
	
		public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
				throws IOException, ServletException {
			//类型
			HttpServletRequest req = (HttpServletRequest) request;
			HttpServletResponse resp = (HttpServletResponse) response;
			//设置编码
			//1:应用中没有编码,并且我自己设置了编码.
			//2:应用中已经存在编码了但是依然要使用我自己设置的编码:强制使用
			if(haslength(encoding) && (req.getCharacterEncoding() == null || forceEncoding)){
				req.setCharacterEncoding(encoding);
			}
			chain.doFilter(req, resp);
		}
	
		public void destroy() {
			
		}
		
		private boolean haslength(String str){
			return str!=null && !"".equals(str.trim());
		}
	}

XML配置文件

	<filter>
			<filter-name>CharacterEncodingFilter</filter-name>
			<filter-class>com._520it._02_characterencoding.CharacterEncodingFilter</filter-class>
			<!-- 设置编码 -->
			<init-param>
				<param-name>encoding</param-name>
				<param-value>UTF-8</param-value>
			</init-param>
			<!-- 是否强制使用该编码  -->
			<init-param>
				<param-name>force</param-name>
				<param-value>true</param-value>
			</init-param>
	</filter>
	<filter-mapping>
			<filter-name>CharacterEncodingFilter</filter-name>
			<url-pattern>/*</url-pattern>
	</filter-mapping>

06.登陆检查过滤器

登录检查的流程图:
登录检查的流程图

检查登录过滤器

	//登录检查过滤器
	public class CheckLoginFilter implements Filter{
		
		private String[] unCheckUris = {"/login.jsp","/login"};
		
		public void init(FilterConfig filterConfig) throws ServletException {
		}
		public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
				throws IOException, ServletException {
			HttpServletRequest req = (HttpServletRequest) request;
			HttpServletResponse resp = (HttpServletResponse) response;
			Object user = req.getSession().getAttribute("USER_IN_SESSION");
			//当前正在过滤的资源
			String requestURI = req.getRequestURI();
			if(!Arrays.asList(unCheckUris).contains(requestURI)){
				if(user == null){//没有登录
					resp.sendRedirect("login.jsp");
					return ;
				}
			}
			chain.doFilter(req, resp);
		}
		public void destroy() {
		}
	}

从登录界面跳转到的Servlet中

	@WebServlet("/login")
	public class LoginServelt extends HttpServlet{
	
		private static final long serialVersionUID = 1L;
		
		protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
			String username = req.getParameter("username");
			//把登录信息存储到session中
			req.getSession().setAttribute("USER_IN_SESSION",username);
			resp.sendRedirect("/welcome.jsp");
		}
	}

login.jsp登录界面

	<form action="/login" method="post">
		账号:<input type="text" name="username" required/><br/>
		密码:<input type="text" name="password"/><br/>
			<input type="submit" value="登录"/>
	</form>

welcom.jsp

	${sessionScope.USER_IN_SESSION}
	<hr/>
	<a href="function1.jsp">功能1</a><br/>
	<a href="function2.jsp">功能2</a><br/>
	<a href="function3.jsp">功能3</a><br/>

Filter的配置文件

	<filter>
		<filter-name>CheckLoginFilter</filter-name>
		<filter-class>com._520it.checklogin.CheckLoginFilter</filter-class>
		<init-param>
				<param-name>unCheckUris</param-name>
				<!-- 以后这样做 对需要检查的放到/system/中来 -->
				<param-value>/system/*</param-value>
		</init-param>
	</filter>
	<filter-mapping>
		<filter-name>CheckLoginFilter</filter-name>
		<url-pattern>/*</url-pattern>	
	</filter-mapping>

07.敏感字过滤

		利用装饰设计模式,给Request.getParameter赋予敏感字过滤功能

流程示意图:
流程示意图

给Filter中的request赋予过滤字符的功能

	public class MessageRequestWapper extends HttpServletRequestWrapper{
		public MessageRequestWapper(HttpServletRequest request) {
			super(request);
		}
		//覆盖getParameter方法,使之支持敏感字过滤
		public String getParameter(String name){
			//如果参数名为title或content
			if("title".equals(name) || "content".equals(name)){
				//返回过滤之后的title和content
				FilterUtil.filter(super.getParameter(name)); //FilterUtils就是过滤的代码,现在先知道就行
			}
			return super.getParameter(name);
		}
	}

过滤器(filter)使用

	@WebFilter("/*")
	public class MessageFilter implements Filter{
		public void init(FilterConfig filterConfig) throws ServletException {
		}
		public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
				throws IOException, ServletException {
			//把不具有处理敏感字的请求对象换成可以处理敏感字的请求对象.
			HttpServletRequest req = (HttpServletRequest) request;
			HttpServletRequest requestWapper = new MessageRequestWapper(req);
			//放行
			chain.doFilter(requestWapper, response);
		}
		public void destroy() {
		}
	}

二: Listener(监听器)

Web的另一大组件:Listener(监听器).

Web中的监听器,主要用于监听作用域对象的创建,监听作用域对象属性的添加/删除/替换:

		1):监听作用域对象的创建和销毁.
			
			ServletRequestListener:监听请求对象的创建和销毁.
		
			HttpSessionListener:监听会话对象(session)	的创建和销毁
		
			ServletContextListener:监听应用的创建和销毁.
			
		2):监听作用域对象的属性的添加/删除/替换.
			
			ServletRequestAttributeListener: 监听request作用域中属性的添加/删除/替换.
				
			HttpSessionAttributeListener: 监听session作用域中属性的添加/删除/替换.
				
			ServletContextAttributeListener: 监听application作用域中属性的添加/删除/替换.
	
		Web中的监听器组件,没有初始化参数配置如果要解决监听器中的硬编码,只能使用全局的初始化参数.
	//监听系统(应用)的启动和销毁
	public class ContextLoaderListener implements ServletContextListener{
	
		public void contextInitialized(ServletContextEvent sce) {
			System.out.println("Web系统启动了.....");
		}
	
		public void contextDestroyed(ServletContextEvent sce) {
			System.out.println("Web系统销毁了.....");
		}
	}
	@WebListener
	public class HttpSessionListenerDemo implements HttpSessionListener{
	
		public void sessionCreated(HttpSessionEvent se) {
			System.out.println("会话开始了");
		}
	
		public void sessionDestroyed(HttpSessionEvent se) {
			System.out.println("会话结束了");
		}
	}
	@WebListener
	public class HttpSessionAttributeListenerDemo implements HttpSessionAttributeListener{
	
		public void attributeAdded(HttpSessionBindingEvent se) {
			System.out.println("属性添加"+se.getName()+","+se.getValue());
		}
		public void attributeRemoved(HttpSessionBindingEvent se) {
			System.out.println("属性删除"+se.getName()+","+se.getValue());
		}
		public void attributeReplaced(HttpSessionBindingEvent se) {
			System.out.println("属性替换"+se.getName()+","+se.getValue()+","+se.getSession().getAttribute(se.getName()));
		}
	}
预习,精通Struts2的hello开发:
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值