文章目录
Filter简介
-
filter是服务器端组件,它可以截取客户端和web资源之间的请求和响应消息而过滤不同内容。那具体怎么过滤呢,filter在java中的体现其实是一个接口,我们只需要定义这个接口的实现类,然后实现接口中的过滤方法,在方法中写过滤条件即可·。
-
当服务器收到特定的请求后,会先将请求交给过滤器,我们则可以实现filter接口,实现接口中的过滤方法,在方法中对请求信息进行读取修改等操作,然后将请求信息再发送给目标资源。目标资源作出响应后,服务器会再次将响应转交给过滤器,在过滤器中同样可以对响应信息做这些操作,然后再将响应发送给浏览器。
-
在一个WEB应用中可以部署多个过滤器,多个过滤器就组成了一个过滤器链,请求和响应必须在经过多个过滤器后才能到达目标资源。
为什么要使用过滤器
前面说了过滤器可以截取客户端和web资源之间的请求和响应消息,然后进行一些过滤(如:敏感词过滤)或对请求响应设置编码等操作。
其实这些也都可以在Servlet中实现,像设置编码与敏感词过滤等。但是在Servlet中操作就有一个问题了,像每请求一个资源都要在对应Servlet中解决编码问题或敏感词过滤,这样就要写很多重复的代码,而使用过滤器就可以解决这个问题了。
Filter的简单使用
web3.0以上版本,使用注解配置filter
- 创建一个类实现过滤器接口
- 注解配置过滤器拦截的请求路径(urlPatterns = “/*”)
- 在doFilter方法中书写过滤任务
- FilterChain.doFilter方法放行当前请求
@WebFilter(filterName = "FilterTest",urlPatterns = "/*")
public class FilterTest implements Filter {
public void init(FilterConfig config) throws ServletException {
System.out.print("过滤器初始化");
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
System.out.print("每次请求的路径符合 过滤器配置的路径 与 过滤器拦截请求方式 ,都会执行过滤器的doFilter方法");
//放行当前请求
chain.doFilter(req, resp);
}
public void destroy() {
System.out.println("执行过滤器的desotory方法(服务器停止的时候销毁过滤器)");
}
}
web3.0以前版本,使用web.xml配置filter
- 创建一个类实现过滤器接口
public class FilterTest implements Filter {
public void init(FilterConfig config) throws ServletException {
System.out.print("过滤器初始化");
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
System.out.print("每次请求的路径符合 过滤器配置的路径 与 过滤器拦截请求方式 ,都会执行过滤器的doFilter方法");
//放行当前请求
chain.doFilter(req, resp);
}
public void destroy() {
System.out.println("执行过滤器的desotory方法(服务器停止的时候销毁过滤器)");
}
}
- 在web.xml里面配置过滤器,配置方法与servlet基本一样。
基本配置
<filter>
<filter-name>FilterTest</filter-name>
<filter-class>mycode.FilterTest</filter-class>
</filter>
<filter-mapping>
<filter-name>FilterTest</filter-name>
<url-pattern>/*</url-pattern> </filter-mapping>
更多完整配置:
<!--配置Demo01的过滤器-->
<filter>
<!--过滤器的名称,相当于注解里的filterName属性-->
<filter-name>FilterTest</filter-name>
<!--过滤器的全限定类名-->
<filter-class>mycode.FilterTest</filter-class>
<!--初始化参数,相当于注解里的initParams属性-->
<init-param>
<param-name>aa</param-name>
<param-value>AA</param-value>
</init-param>
</filter>
<!--配置过滤器的映射信息(拦截信息)-->
<filter-mapping>
<!--过滤器名称,要给哪个过滤器配置拦截的信息-->
<filter-name>FilterTest</filter-name>
<!--配置过滤器的拦截范围(可配置多个),相当于注解里的urlPatterns属性-->
<url-pattern>*.jsp</url-pattern>
<!--配置过滤器的拦截方式(可配置多个),相当于注解里的dispatcherTypes属性-->
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
扩展:Filter的执行顺序
注解配置的过滤器执行:由过滤器类的全限定类名的排序决定的。
web.xml配置的过滤器执行顺序:按照在web.xml文件中servlet-mapping的顺序决定的,如果顺序越靠前越先被调用。
Filter的配置
虽然根据版本不同配置方式也不同,但是这两种配置的方式,参数属性是一样的,这里以注解配置的方法来说明Filter的配置。
@WebFilter(filterName="FilterTest", urlPatterns="/*", initParams={@WebInitParam(name="参数名",value="参数值")}, dispatcherTypes=DispatcherType.REQUEST)
public class FilterTest implements Filter {
public void init(FilterConfig config) throws ServletException {
System.out.print("过滤器初始化");
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
//放行当前请求
chain.doFilter(req, resp);
}
public void destroy() {
System.out.println("执行过滤器的desotory方法(服务器停止的时候销毁过滤器)");
}
}
主要配置:
urlPatterns
说明:配置过滤器的拦截范围,只要客户端请求的资源在过滤器的拦截范围里,过滤器就会拦截这次请求
语法:
- 完全匹配的方式:
urlPatterns="/target"
,表示只拦截对/target的请求,其它任意请求都不拦截 - 目录匹配的方式:以/开头, 以*结尾
urlPatterns="/*"
:表示拦截对所有资源的请求
urlPatterns="/admin/*"
:表示拦截对/admin/下的任意资源的请求 - 扩展名匹配的方式:以*开头,以扩展名结尾
urlPatterns="*.jsp"
:表示拦截对.jsp资源的请求
dispatcherTypes
说明:配置拦截不同的请求方式。过滤器默认的拦截方式DispatcherType.REQUEST
,只能拦截浏览器对服务器的之间访问,这种请求方式可以说是客户端的请求(有直接访问或重定向)。而服务器资源之间使用转发的方式需要拦截的话。要配置DispatcherType.FORWARD
,这样请求转发的请求就会拦截了。
分类:
要拦截客户端的请求(直接访问或重定向): DispatcherType.REQUEST
要拦截请求转发的请求:DispatcherType.FORWARD
注: 两种拦截方式可以共存,写法
@WebFilter(dispatcherTypes = {DispatcherType.FORWARD,DispatcherType.REQUEST},urlPatterns = "/*")
从配置的角度看过滤器会拦截请求的前提条件
过滤器拦截请求前提条件:在过滤器拦截范围里,并且符合过滤器拦截的请求方式。
Filter相关API及Filter的生命周期
@WebFilter(filterName = "FilterTest",urlPatterns = "/*")
public class FilterTest implements Filter {
/* 参数FilterConfig:过滤器的配置信息对象 */
public void init(FilterConfig config) throws ServletException {
System.out.print("过滤器初始化");
}
/* 参数ServletReqeuset:代表http请求的request对象,通常强转成HttpServletRequest再使用 参数ServletResponse:代表http响应的response对象,通常强转成HttpServletResponse再使用 参数FilterChain:过滤器链对象,维护了能够拦截本次请求的所有过滤器的队列。作用:放行请求到下一个过滤器;如果下一个过滤器不存在,请求会到达目标资源 */
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
System.out.print("每次请求的路径符合 过滤器配置的路径 与 过滤器拦截请求方式 ,都会执行过滤器的doFilter方法");
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
//放行当前请求
chain.doFilter(req, resp);
}
public void destroy() {
System.out.println("执行过滤器的desotory方法(服务器停止的时候销毁过滤器)");
}
}
/* Filter的生命周期 创建:服务器启动时创建,创建时执行init方法,方法执行一次 销毁:服务器关闭时销毁,销毁时执行destory方法,方法执行一次 拦截到请求执行的方法:doFilter方法 */
相关接口
Filter接口,编写Filter需要实现该接口
- init()方法用于初始化Filter
- doFilter()作用和service()方法类似,这里是过滤请求和响应的主要方法。
- destroy()用于在Filter对象被销毁前做一些收尾工作。如:释放资源等。
FilterConfig对象在服务器调用init()方法时传递进来,是过滤器的配置信息对象。作用:
- getFilterName() 获取Filter的名字
- getServletContext() 获取ServletContext对象(掌握)
- getInitParameter() 获取Filter的初始化参数
- getInitParameterNames() 获取所有初始化参数的名字
FilterChain对象是在doFilter()方法被调用时作为参数传递进来的。
- doFilter()方法用于调用Filter链上的下一个过滤器,如果当前过滤器为最后一个过滤器则将请求发送到目标资源。
Filter的使用场景
- Filter的使用场景:敏感词过滤
- 统一设置编码
@WebFilter("/*")//该项目下的所有请求和响应都会经过该过滤器统一解决乱码
public class EncodingFilter implements Filter {
public void destroy() {
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
//统一解决乱码问题
//解决响应的中文乱码
response.setContentType("text/html;charset=utf-8");
//解决请求的中文乱码:post方式
if ("POST".equalsIgnoreCase(request.getMethod())) {
request.setCharacterEncoding("utf-8");
}
//放行请求
chain.doFilter(request, response);
}
public void init(FilterConfig config) throws ServletException {
}
}
- 自动登录
- 登录权限检查