过滤器和监听器
一、过滤器
过滤器,顾名思义,就是用来过滤的,当需要限制用户访问某些资源时、在处理请求时提前处理某些资源、服务器响应的内容对其进行处理再返回、我们就是用过滤器来完成的!
如下,一个过滤器
public class Filterdemo implements Filter{
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
filterChain.doFilter(servletRequest,servletResponse);
}
@Override
public void destroy() {
}
}
开发步骤
1、实现Filter接口
2、重写doFilter方法
3、注册过滤器
Filter接口是Servlet下的接口,实现接口需要重写三个方法,初始化和销毁以及过滤器方法
doFilter方法有三个参数, servletRequest,servletResponse, FilterChain filterChain,
其中filterChain是传递到下一个过滤器的方法,如果没有过滤器,那么结束过滤
注册可以在web.xml中注册,注册顺序就是过滤顺序,也可以使用注解,注解控制不了顺序
这里有一个/Web002,主代码如下
PrintWriter writer = response.getWriter();
writer.println("<h1>你好</h1>");
writer.write("<h1>大家好</h1>");
代码没有设置响应头编码,所以访问后页面乱码
以下是两个过滤器
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
servletResponse.setContentType("text/html;charset=UTF-8");
System.out.println("第一个过滤器开始过滤。。。");
filterChain.doFilter(servletRequest,servletResponse);
System.out.println("第一个过滤器结束过滤。。。。");
}
第一个过滤器设置了响应编码,所以不会乱码啦,在两个打印中夹着一个传递过滤器
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
servletResponse.getWriter().println("<h1>过滤器呀。。。</h1>");
System.out.println("第二个过滤器开始过滤。。。");
filterChain.doFilter(servletRequest,servletResponse);
System.out.println("第二个过滤器结束过滤。。。。");
}
第二个过滤器中也向页面打印了一个h1标题,传递方法夹在打印中间
webxml中注册
<filter>
<filter-name>filterDemo1</filter-name>
<filter-class>Filterdemo</filter-class>
</filter>
<filter-mapping>
<filter-name>filterDemo1</filter-name>
<url-pattern>/Web002</url-pattern>
</filter-mapping>
<filter>
<filter-name>filterDemo2</filter-name>
<filter-class>Filterdemo2</filter-class>
</filter>
<filter-mapping>
<filter-name>filterDemo2</filter-name>
<url-pattern>/Web002</url-pattern>
</filter-mapping>
访问/Web002后,得到页面和控制台如下
第一个过滤器开始过滤。。。
第二个过滤器开始过滤。。。
第二个过滤器结束过滤。。。。
第一个过滤器结束过滤。。。。
可以看出过滤器执行顺序,第一个注册的先执行,遇到filterChain方法传递到第二个注册的,第二个过滤器无下一个传递目标,结束,第一个过滤器结束,第二个过滤器确实打印到了页面
二、监听器
监听器:事件源,事件,监听器三个要素
域对象是事件源,监听器监听着,当域对象发生变化时,触发相关方法
Listener 的作用是用于监听 web应用的创建和销毁,以及在其上attribute发生的变化。
以ServletContext为例
实现ServletContextListener接口,监听域对象的诞生与毁灭
public class ListenerContext implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
System.out.println("服务器开启,ServletContext监听器监听域对象初始化。。。");
}
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
System.out.println("服务器关闭,ServletContext监听器监听结束。。。。");
}
}
实现ServletContextAttributeListener,监听域对象中Attribute的诞生,毁灭,改变
public class ListenerContextAtt implements ServletContextAttributeListener {
@Override
public void attributeAdded(ServletContextAttributeEvent servletContextAttributeEvent) {
System.out.println("监听到:加入了属性。。");
}
@Override
public void attributeRemoved(ServletContextAttributeEvent servletContextAttributeEvent) {
System.out.println("监听到:移除了属性。。");
}
@Override
public void attributeReplaced(ServletContextAttributeEvent servletContextAttributeEvent) {
System.out.println("监听到:替换了属性。。");
}
}
在web.xml中注册这两个监听器
<listener>
<listener-class>ListenerContext</listener-class>
</listener>
<listener>
<listener-class>ListenerContextAtt</listener-class>
</listener>
过滤器那里Web002中继续添加下面这串代码
ServletContext servletContext = this.getServletContext();
servletContext.setAttribute("name","Tom");
System.out.println("加入域对象属性name:"+servletContext.getAttribute("name"));
servletContext.setAttribute("name","sally");
System.out.println("替换域对象属性name:"+servletContext.getAttribute("name"));
servletContext.removeAttribute("name");
System.out.println("移除了域对象。。。");
启动服务器,开始访问/Web002,然后关闭,在控制台下得到以下
Connected to server
服务器开启,ServletContext监听器监听域对象初始化。。。
[2019-05-22 11:40:25,297] Artifact Web002:war exploded: Artifact is deployed successfully
[2019-05-22 11:40:25,297] Artifact Web002:war exploded: Deploy took 585 milliseconds
22-May-2019 23:40:34.683 淇℃伅 [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deploying web application directory [F:\Tom\apache-tomcat-8.5.38-windows-x64\apache-tomcat-8.5.38\webapps\manager]
22-May-2019 23:40:34.792 淇℃伅 [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deployment of web application directory [F:\Tom\apache-tomcat-8.5.38-windows-x64\apache-tomcat-8.5.38\webapps\manager] has finished in [93] ms
第一个过滤器开始过滤。。。
第二个过滤器开始过滤。。。
监听到:加入了属性。。
加入域对象属性name:Tom
监听到:替换了属性。。
替换域对象属性name:sally
监听到:移除了属性。。
移除了域对象。。。
第二个过滤器结束过滤。。。。
第一个过滤器结束过滤。。。。
22-May-2019 23:52:52.926 淇℃伅 [main] org.apache.catalina.core.StandardServer.await A valid shutdown command was received via the shutdown port. Stopping the Server instance.
22-May-2019 23:52:52.926 淇℃伅 [main] org.apache.coyote.AbstractProtocol.pause Pausing ProtocolHandler ["http-nio-8080"]
22-May-2019 23:52:53.058 淇℃伅 [main] org.apache.coyote.AbstractProtocol.pause Pausing ProtocolHandler ["ajp-nio-8009"]
服务器关闭,ServletContext监听器监听结束。。。。
22-May-2019 23:52:53.175 淇℃伅 [main] org.apache.catalina.core.StandardService.stopInternal Stopping service [Catalina]
22-May-2019 23:52:53.206 淇℃伅 [main] org.apache.coyote.AbstractProtocol.stop Stopping ProtocolHandler ["http-nio-8080"]
22-May-2019 23:52:53.206 淇℃伅 [main] org.apache.coyote.AbstractProtocol.stop Stopping ProtocolHandler ["ajp-nio-8009"]
22-May-2019 23:52:53.206 淇℃伅 [main] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler ["http-nio-8080"]
22-May-2019 23:52:53.206 淇℃伅 [main] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler ["ajp-nio-8009"]
Disconnected from server