.Net转Java自学之路—基础巩固篇三十一(Listener、Filter)
监听器:
监听三大组件:Servlet、Listener、Filter。
三大组件都需要在web.xml中进行配置。Listener中由二个感知监听器不需要配置。
Listener:
特性:
1、是一个接口,内容自定义来实现。
2、需要注册。在web.xml中进行配置
3、监听器的方法,会在特殊事件发生时被调用。
监听器监听的是事件源。
JavaWeb中的监听器:
JavaWeb中监听的事件源为三大域:ServletContext、HttpSession、ServletRequest
三大域同有俩种监听方式:
生命周期监听:
ServletContextListener、HttpSessionListener、ServletRequestListener 他们有俩个方法。一个在服务器启动时调用,一个在服务器关闭时调用。
//ServletContext: void contextInitialized(ServletContextEvent se){}//创建ServletContext时 void contextDestroyed(ServletContextEvent se){}//销毁ServletContext时 //HttpSession: void sessionCreated(HttpSessionEvent se){}//创建session时 void sessionDestroyed(HttpSessionEvent se){}//销毁session时。 //ServletRequest: void requestInitialized(ServletRequestEvent se){}//创建ServletRequest时 void requestDestroyed(ServletRequestEvent se){}//销毁ServletRequest时
属性监听:
ServletContextAttributeListener、HttpSessionAttributeListener、ServletRequestAttributeListener它们都有三个方法,一个在添加属性时调用,一个在替换属性时调用,最后一个在移除属性时调用。
//ServletContext: void attributeAdded(ServletContextAttributeEvent event){}//添加属性时 void attributeReplaced(ServletContextAttributeEvent event){}//替换属性时 void attributeRemoved(ServletContextAttributeEvent event){}//移除属性时 //HttpSession: void attributeAdded(HttpSessionBindingEvent event){}//添加属性时 void attributeReplaced(HttpSessionBindingEvent event){}//替换属性时 void attributeRemoved(HttpSessionBindingEvent event){}//移除属性时 //ServletRequest: void attributeAdded(ServletRequestAttributeEvent event){}//添加属性时 void attributeReplaced(ServletRequestAttributeEvent event){}//替换属性时 void attributeRemoved(ServletRequestAttributeEvent event){}//移除属性时
书写监听器时,必须实现某个监听器接口,并在web.xml中配置。
事件对象:
//ServletContextEvent: ServletContext getServletContext(); //ServletContextAttributeEvent: ServletContext getServletContext(); String getName();//获取属性名 Object getValue();//获取属性值 //HttpSessionEvent: HttpSession getSession(); //HttpSessionBindingEvent: HttpSession getSession(); String getName();//获取属性名 Object getValue();//获取属性值 //ServletRequestEvent: ServletRequest getServletRequest(); ServletContext getServletContext(); //ServletRequestAttributeEvent: ServletRequest getServletRequest(); String getName();//获取属性名 Object getValue();//获取属性值
web.xml配置
<listener> <listener-class></listener-class> </listener>
感知监听:
它是用来添加到JavaBean上,而不是添加到三大域上。都与HttpSession相关。这俩个监听器都不需要在web.xml中配置注册。
Filter:过滤器
它会在一组资源的前面执行。它可以让请求达到目标资源,也可以终止请求。也就是说 过滤器有拦截请求的能力。
特性:
Filter是单例的;与Servlet一样。
书写过滤器时必须实现Filter接口;并在web.xml中进行配置注册。
生命周期:
init(FilterConfig);//创建后马上执行进行初始化操作。在服务器启动时就创建 destory();//销毁前执行。在服务器关闭时销毁。 doFilter(ServletRequest,ServletResponse,FilterChain);//每次过滤时都会执行
web.xml配置
<filter> <filter-name>xxx</filter-name> <filter-class>cn.filter.xxx</filter-class> </filter> <filter-mapping> <filter-name>xxx</filter-name> <url-pattern>/*</url-pattern><!--所有都拦截--> </filter-mapping>
在<filter-mapping>中可以指定要拦截的Servlet。可以指定多个Servlet:<servlet-name></servlet-name>
FilterConfig:
与ServletConfig相似。
getInitParameter();//获取初始化参数 getFilterName();//获取过滤器名称 getServletContext();//获取application
FilterChain:
doFilter(ServletRequest,ServletResponse);//放行。就相当于调用了目标Servlet的service()方法。
多过滤器:
FilterChain的doFilter()方法:执行目标资源,或执行下一个过滤器。若没下一个过滤器,那么执行的时目标资源;若有下一个过滤器,那么就性值下一个过滤器。
过滤器的四种拦截方式:在filter-mapping中进行配置
1、拦截请求 DISPATCHER:
<dispatcher>REQUEST</dispatcher> <!--默认拦截方式-->
2、拦截转发 FORWARD:
<dispatcher>FORWARD</dispatcher>
3、拦截包含 INCLUDE:
<dispatcher>INCLUDE</dispatcher>
4、拦截错误 ERROR:
<dispatcher>ERROR</dispatcher>
多个过滤器的执行顺序:
<filter-mapping>的配置顺序决定了过滤器的执行顺序。
实例:分IP统计访问次数
//1、Listener 在服务器启动时创建Map,保存到ServletContext中 public class AListener implements ServletContextListener{ public void contextInitialized(ServletContextEvent event){ Map<String,Integer> map=new LinkedHashMap<String,Integer>(); ServletContext application=event.getServletContext(); application.setAttribute("map",map); } } //2、从application中获取Map,从request中得到当前客户端的IP进行统计工作,结果保存到Map中。 public class AFilter implements Filter{ Private FilterConfig config; public void init(FilterConfig config) throws ServletException{ this.config=config; } public void destroy(){ } public void doFilter(ServletRequest request,ServletResponse response,FilterChain chain) throws IOException,ServletException { ServletContext sc=config.getServletContext(); Map<String,Integer> map=(Map<String,Integet>) sc.getAttribute("map"); String strIP=request.getRemoteAddr(); if(map.containsKey(strIP)){ int count=map.get(strIP); map.put(strIP,count+1); }else{ map.put(strIP,1); } app.setAttribute("map",map); chain.doFilter(request,response);//放行 } } //3、JSP页面forEach展示 items="${applicationScope.map}" var="entry" ${entry.key}、${entry.key}
实例:过滤器解决全站字符乱码(POST和GET中文编码问题)
//在Servlet的doGet()、doPost()中只需要处理response的请求的编码问题 response.setContentType("text/html;charset-utf-8"); //1、过滤器 public class EncodingFilter implements Filter{ public void doFilter(ServletRequest request,ServletResponse response,FilterChain chain) throws IOException,ServletException{ //处理POST请求编码问题 request.setCharacterEncoding("utf-8"); //处理GET请求编码问题。用装饰者模式,需要一个request装饰类 HttpServletRequest req=(HttpServletRequest)request; if(req.getMethod().equals("GET")){ EncodingRequest er=new EncodingRequest(req); chain.doFilter(er,response); } chain.doFilter(request,response); } } /* * 2、request装饰类:需要实现HttpServletRequest或继承HttpServletRequestWrapper * HttpServletRequestWrapper:是将除去getParameter()方法外的所有方法都实现了,就是将“一切拜托你”实现了。 */ public class EncodingRequest extends HttpServletRequestWrapper{ private HttpServletRequest req; public EncodingRequest(HttpServletRequest request){ super(request); this.req=request; } public String getParameter(String name){ String value=req.getParameter(name); try{ value=new String(value.getBytes("iso-8859-1"),"utf-8"); }catch(UnsupportedEncodingException ex){ throw new RuntimeException(ex); } return value; } }