# javaweb过滤器和监听器
# 原理

过滤器,监听器和servlet被称为javaweb的三大组件
作用:将请求拦截下来,对这个请求完成一些特殊的操作,比如验证用户是否登录,如果过滤器没有放行的话,请求会一直处于拦截状态
还可以为所有的请求设置编码,这样就不用对每一个请求都单独设置编码,可以节约时间
# 实现步骤
定义一个类,实现
Filter
接口,重写里面的三个方法@Override public void init (FilterConfig filterConfig) throws ServletException { //此方法是服务器放启动的时候,就会执行,并不是需要等访问资源时,才会执行 } @Override public void doFilter (ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { //只要浏览器发送一次请求,并且这个请求的路径是在过滤器的过滤范围类,只要有一次请求,就会执行一次 } @Override public void destroy () { //服务器被正常关闭时,执行,正常关闭才会执行 }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 配置拦截路径
# 使用注解进行配置
- 具体资源路径:
/index.jsp
只有访问index.jsp资源时,过滤器才会被执行 - 拦截目录:
/user/*
访问/user下的所有资源时,过滤器都会被执行 - 后缀名拦截:
*.jsp
访问所有后缀名为jsp资源时,过滤器都会被执行 - 拦截所有资源:
/*
访问所有资源时,过滤器都会被执行
使用:@WebFilter("/index.jsp")
例如这样进行配置
# 通过web.xml进行配置
<filter>
<filter-name>demon1</filter-name>
<filter-name>com.chu.filter.FilterDemon1</filter-name>
</filter>
<filter-mapping>
<filter-name>demon1</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
2
3
4
5
6
7
8
# 过滤器的执行流程
配置的过滤路径是/*
- 当我们浏览器发送请求的时候,会首先经过过滤器,会执行
filterChain.doFilter(servletRequest,servletResponse);
上部分的代码 - 如果过滤器中没有
filterChain.doFilter(servletRequest,servletResponse);
,那么请求会在此处进行拦截,服务器不会对返回任何的响应,因为响应是发生在这一串代码之后 - 执行
filterChain.doFilter(servletRequest,servletResponse);
,然后服务器像浏览器返回响应,浏览器接收到响应,并为此展示数据 - 当响应执行完毕之后,就会执行
filterChain.doFilter(servletRequest,servletResponse);
最后的代码块(响应代码块执行完毕
)
# 拦截方式配置
可以单独的为请求,转发,错误跳转资源,异步访问,包含资源进行单独的配置
- 使用注解进行配置(
设置DispatcherType的值
)
REQUEST:默认值。浏览器直接请求资源 FORWARD:转发访问资源 INCLUDE:包含访问资源 ERROR:错误跳转资源 ASYNC:异步访问资源
例如DispatcherType.REQUEST
这样配置,就是浏览器进行请求的时候,就会触发过滤器
DispatcherType.FORWARD
服务器进行请求转发时,才会触发过滤器
如果一个servlet
文件中,没有进行请求转发,那么不会触发过滤器DispatcherType.REQUEST
但是,如果配置了DispatcherType...
,没有配置过滤路径的话,那么也不会有任何的过滤效果,所以出了配置资源被访问的方式外,还需要配置过滤路径
@WebFilter(dispatcherTypes = DispatcherType.REQUEST,value = "/*")
web.xml
设置<dispatcher></dispatcher>
标签即可
# 过滤器链
有时候,单独的一个过滤器并不能满足我们的需求,这个时候,我们可以多创建几个过滤器进行组合使用,这个就是过滤器链
执行顺序
通过看图就可以发现,去的时候顺序是过滤器1,过滤器2
,但是回来的时候,最先经过的是过滤器2
,这和我们日常走路相似
所以执行顺序为
过滤器1
过滤器2
.......
过滤器2
过滤器1
那么如何判断谁是第一最先执行的过滤器?
- 如果使用注解进行过滤路径配置
那么是对过滤器的类名进行字符串的比较,字符串值小的,在前面先执行,反之,并不是过滤器的名字小的先执行
@WebFilter(filterName = "ab",value = "/*") filtername为过滤器名字,并不是这个小的就先执行
3小于0,所以FileterDemon04
的过滤器会先执行
使用
web.xml
进行配置<filter-mapping> <filter-name>demon1</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
1
2
3
4<filter-mapping>
谁在前面,谁先执行,因为如果有多个过滤器的话,那么我们就会配置多个<filter-mapping>
# 排除某个资源
有时候,并不是所有的资源进行访问的时候,我们都需要进行拦截,像js,css,还有验证码等等一些对于页面的展示非常重要的资源,我们不应该对其进行拦截,否则的话,就会发送页面非常丑的情况,因为js,css等等,已经被我们进行拦截了,
排除某个资源的方法
获取请求资源的路径
request.getRequestURI()
使用
String
中的某些方法进行路径的判断,判断是否包含某些资源
# Listenner
这是javaweb的三大组件之一
- 创建步骤
- 定义一个类,实现
ServletContextListener
接口
- 方法
@Override public void contextInitialized (ServletContextEvent sce) { ServletContext对象被创建的时候,执行此方法 只要服务器启动,就会创建ServletContext对象 那么就会执行这个方法 } @Override public void contextDestroyed (ServletContextEvent sce) { ServletContext对象被销毁时,执行此方法 }
1
2
3
4
5
6
7
8
9
10
也可以通过idea直接创建,
package com.chu.listenner; import javax.servlet.*; import javax.servlet.http.*; import javax.servlet.annotation.*; @WebListener public class ListenerDemon2 implements ServletContextListener, HttpSessionListener, HttpSessionAttributeListener { public ListenerDemon2 () { } @Override public void contextInitialized (ServletContextEvent sce) { /* This method is called when the servlet context is initialized(when the Web application is deployed). */ } @Override public void contextDestroyed (ServletContextEvent sce) { /* This method is called when the servlet Context is undeployed or Application Server shuts down. */ } @Override public void sessionCreated (HttpSessionEvent se) { /* Session is created. */ } @Override public void sessionDestroyed (HttpSessionEvent se) { /* Session is destroyed. */ } @Override public void attributeAdded (HttpSessionBindingEvent sbe) { /* This method is called when an attribute is added to a session. */ } @Override public void attributeRemoved (HttpSessionBindingEvent sbe) { /* This method is called when an attribute is removed from a session. */ } @Override public void attributeReplaced (HttpSessionBindingEvent sbe) { /* This method is called when an attribute is replaced in a session. */ } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48配置
web.xml
配置<listener> <listener-class>cn.itcast.web.listener.ContextLoaderListener</listener-class> </listener>
1
2
3
4使用注解
因为注解中什么也没有,所以直接写注解就行
public @interface WebListener { String value() default ""; }
使用监听器进行资源的加载
因为监听器在服务器启动的时候,就会被执行,所以可以用监听器对资源进行加载
步骤
通过
ServletContextEvent
对象获取ServletContext
对象通过
ServletContext.getInitParameter("chu")
获取web.xml
文件中配置的文件<context-param> <param-name>chu</param-name> <param-value>WEB-INF/classes/f.txt</param-value> </context-param>
1
2
3
4servletContext.getRealPath(chu)
获取此文件的真实路径,然后就可以使用IO流的知识....
在web.xml
中对资源文件进行配置的时候,可以多配置几个文件
String getInitParameter(String var1);
一定要保证var1
值在web.xml
中到的<context-param>
存在
@Override
public void contextInitialized (ServletContextEvent sce) {
//获取ServletContext对象
ServletContext servletContext = sce.getServletContext();
String chu = servletContext.getInitParameter("chu");
String realPath = servletContext.getRealPath(chu);
System.out.println(realPath);
}
2
3
4
5
6
7
8





