# Filter
## 概念
Filter 的基本功能是对 Servlet 容器调用 Servlet 的过程进行拦截,从而在 Servlet 进行响应处理的前后实现一些特殊的功能。
在 Servlet API 中定义了三个接口类来开供开发人员编写 Filter 程序:Filter, FilterChain, FilterConfig
Filter 程序是一个实现了 Filter 接口的 Java 类,与 Servlet 程序相似,它由 Servlet 容器进行调用和执行
Filter 程序需要在 web.xml 文件中进行注册和设置它所能拦截的资源:Filter 程序可以拦截 Jsp, Servlet, 静态图片文件和静态 html 文件
***
### 创建一个HelloWorldFilter
创建一个test.jsp
创建一个继承Filter的类
~~~
package com.neusoft.web.fiter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class HelloWorldFilter implements Filter{
@Override
public void destroy() {
// TODO Auto-generated method stub
System.out.println("destroy");
}
@Override
public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2)
throws IOException, ServletException {
// TODO Auto-generated method stub
System.out.println("doFilter");
}
@Override
public void init(FilterConfig arg0) throws ServletException {
// TODO Auto-generated method stub
System.out.println("init");
}
}
~~~
web.xml配置Filter
~~~
<filter>
<filter-name>helloworldFilter</filter-name>
<filter-class>com.neusoft.web.fiter.HelloWorldFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>helloworldFilter</filter-name>
<url-pattern>/20180125/test.jsp</url-pattern>
</filter-mapping>
~~~
运行jsp,发现init()被调用后(创建Filter对象后立即被调用,且只被调用一次),doFilter()被调用,所以init()与Servlet的init()基本功能一样,都是初始化用的,而doFilter()与Servlet当中的service()功能基本一样,而FilterConfig与ServletConfig基本一样,封装着配置信息;destory()释放当前Filter所占用的资源的方法,在Filter被销毁之前调用,且只能调用一次
而上述例子当中,发现页面中的内容并没有出现,是因为Filter将请求拦截下来了,想要对拦截进行放行,需要调用FilterChain的doFilter方法
~~~
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
// TODO Auto-generated method stub
System.out.println("doFilter");
chain.doFilter(request, response);
}
~~~
### Filter链
~~~
<filter>
<filter-name>helloworldFilter</filter-name>
<filter-class>com.neusoft.web.fiter.HelloWorldFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>helloworldFilter</filter-name>
<url-pattern>/20180125/test.jsp</url-pattern>
</filter-mapping>
<filter>
<filter-name>secondFilter</filter-name>
<filter-class>com.neusoft.web.fiter.SecondFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>secondFilter</filter-name>
<url-pattern>/20180125/test.jsp</url-pattern>
</filter-mapping>
~~~
多个Filter在一起形成一个Filter链,而拦截的顺序与filter-mapping的前后有关
思考:多个Filter代码的顺序
~~~
package com.neusoft.web.fiter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class HelloWorldFilter implements Filter{
@Override
public void destroy() {
// TODO Auto-generated method stub
System.out.println("destroy");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
// TODO Auto-generated method stub
System.out.println("1.doFilter");
chain.doFilter(request, response);
System.out.println("2.doFilter");
}
@Override
public void init(FilterConfig arg0) throws ServletException {
// TODO Auto-generated method stub
System.out.println("init");
}
}
~~~
~~~
package com.neusoft.web.fiter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class SecondFilter implements Filter{
@Override
public void destroy() {
// TODO Auto-generated method stub
System.out.println("destroy2");
}
@Override
public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2)
throws IOException, ServletException {
// TODO Auto-generated method stub
System.out.println("3.doFilter2");
arg2.doFilter(arg0, arg1);
System.out.println("4.doFilter2");
}
@Override
public void init(FilterConfig arg0) throws ServletException {
// TODO Auto-generated method stub
System.out.println("init2");
}
}
~~~
~~~
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>Test Page</h1>
<% System.out.println("5.test"); %>
</body>
</html>
~~~
***
课堂练习--1
![](https://box.kancloud.cn/7ce6f7a537f33c3b95041d24b4101e95_962x656.png)
***
#### dispatcher
< dispatcher >指定过滤器所拦截的资源被 Servlet 容器调用的方式,可以是REQUEST,INCLUDE,FORWARD和ERROR之一,默认REQUEST. 可以设置多个<dispatcher> 子元素用来指定 Filter 对资源的多种调用方式进行拦截。在filter-mapping中配置。
**REQUEST**:当用户直接访问页面时,Web容器将会调用过滤器。如果目标资源是通过RequestDispatcher的include()或forward()方法访问时,那么该过滤器就不会被调用。
INCLUDE:如果目标资源是通过RequestDispatcher的include()方法访问时,那么该过滤器将被调用。除此之外,该过滤器不会被调用。
**FORWARD**:如果目标资源是通过RequestDispatcher的forward()方法访问时,那么该过滤器将被调用,除此之外,该过滤器不会被调用。
ERROR:如果目标资源是通过声明式异常处理机制调用时,那么该过滤器将被调用。除此之外,过滤器不会被调用。
***
### 典型应用1--字符编码的过滤器
在每个页面上都写request.setCharacterEncoding()很麻烦,写个过滤器
one.jsp
~~~
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="two.jsp" method="post">
username:<input type="text" name="username">
<input type="submit" value="Submit">
</form>
</body>
</html>
~~~
two.jsp
~~~
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
Hello:${ param.username }
</body>
</html>
~~~
web.xml
~~~
<context-param>
<param-name>encode</param-name>
<param-value>UTF-8</param-value>
</context-param>
~~~
EncodingFilter
~~~
package com.neusoft.web.fiter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
/**
* Servlet Filter implementation class EncodingFilter
*/
@WebFilter("/*")
public class EncodingFilter implements Filter {
public void destroy() {
// TODO Auto-generated method stub
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
String encode = fConfig.getServletContext().getInitParameter("encode");
request.setCharacterEncoding(encode);
chain.doFilter(request, response);
}
private FilterConfig fConfig;
public void init(FilterConfig fConfig) throws ServletException {
this.fConfig = fConfig;
}
}
~~~
***
### 典型应用2--检测用户是否登录的过滤器
list.jsp
~~~
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>List Page</h1>
<a href="a.jsp">AAA</a>
<br><br>
<a href="b.jsp">BBB</a>
<br><br>
<a href="c.jsp">CCC</a>
<br><br>
<a href="d.jsp">DDD</a>
<br><br>
<a href="e.jsp">EEE</a>
<br><br>
</body>
</html>
~~~
a.jsp,b.jsp,c.jsp,d.jsp,e.jsp
~~~
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>BBB Page</h1>
<a href="list.jsp">Return...</a>
</body>
</html>
~~~
doLogin.jsp
~~~
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<%
// 1.获取用户的登录信息
String username = request.getParameter("username");
// 2.若登录信息完整,则把登录信息放到HttpSession里
if(username != null && !username.trim().equals("")){
session.setAttribute(application.getInitParameter("userSessionKey"), username);
// 3.重定向到list.jsp
response.sendRedirect("list.jsp");
}else{
response.sendRedirect("login.jsp");
}
%>
</body>
</html>
~~~
login.jsp
~~~
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="doLogin.jsp" method="post">
userName:<input type="text" name="username">
<input type="submit" value="Submit">
</form>
</body>
</html>
~~~
web.xml
~~~
<!-- 不要拦截的资源 -->
<context-param>
<param-name>noCheckPage</param-name>
<param-value>/login/a.jsp,/login/doLogin.jsp,/login/list.jsp,/login/login.jsp</param-value>
</context-param>
<!-- 拦截后重定向到的页面 -->
<context-param>
<param-name>redirectPage</param-name>
<param-value>/login/login.jsp</param-value>
</context-param>
<!-- 用户信息放入到session中的键名 -->
<context-param>
<param-name>userSessionKey</param-name>
<param-value>USERSESSIONKEY</param-value>
</context-param>
~~~
CheckLoginFilter
~~~
package com.neusoft.web.fiter;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet Filter implementation class CheckLoginFilter
*/
@WebFilter("/login/*")
public class CheckLoginFilter extends HttpFilter {
private String sessionKey;
private String redirectUrl;
private String noCheckPage;
@Override
public void init() {
ServletContext servletContext = getFilterConfig().getServletContext();
sessionKey = servletContext.getInitParameter("userSessionKey");
redirectUrl = servletContext.getInitParameter("redirectPage");
// /login/a.jsp,/login/doLogin.jsp,/login/list.jsp,/login/login.jsp
noCheckPage = servletContext.getInitParameter("noCheckPage");
}
@Override
public void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws IOException, ServletException {
// 1.获取请求的serlvetPath
String servletPath = request.getServletPath();
// 2.检查获取到的是否为不需要检查中的一个,若是,则放行,return
List<String> urls = Arrays.asList(noCheckPage.split(","));
if(urls.contains(servletPath)) {
filterChain.doFilter(request, response);
return;
}
// 3.检查是否有登录者,即检查sessionKey是否存在,若不存在,则重定向redirectUrl
Object user = request.getSession().getAttribute(sessionKey);
if(user == null) {
response.sendRedirect(request.getContextPath()+redirectUrl);
return;
}
// 4.若存在,放行,允许访问
filterChain.doFilter(request, response);
}
}
~~~
HttpFilter
~~~
package com.neusoft.web.fiter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class HttpFilter implements Filter{
@Override
public void destroy() {
}
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain filterChain)
throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest)req;
HttpServletResponse response = (HttpServletResponse)res;
doFilter(request,response,filterChain);
}
public void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws IOException, ServletException {
filterChain.doFilter(request, response);
}
private FilterConfig filterConfig;
public FilterConfig getFilterConfig() {
return filterConfig;
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
this.filterConfig = filterConfig;
init();
}
public void init(){
}
}
~~~
***
### Filter小结
(1)简介
Filter是JavaWEB的一个重要组件,可以对发送到Servlet的请求进行拦截,并对响应也进行拦截
Filter是实现了Filter接口的Java类
Filter需要在web.xml文件中进行配置和映射(注解)
(2)在web.xml中如何配置
~~~
<filter>
<filter-name>helloworldFilter</filter-name>
<filter-class>com.neusoft.web.fiter.HelloWorldFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>helloworldFilter</filter-name>
<url-pattern>/20180125/test.jsp</url-pattern>
</filter-mapping>
~~~
配置与Servlet的配置很相似,url-pattern映射的路径是可以拦截的资源,也就是通过哪些url能够访问到该Filter
***
- 第一章 配置和安装Tomcat
- 第二章 Servlet(一)
- 第三章 Servlet(二)
- 练习 一 . Servlet配置级获取初始化参数
- 第四章 JSP(一)
- 第五章 JSP(二)
- 第六章 MVC设计模式
- 第七章 Cookie
- 第八章 Session
- 练习 二 . 简易版购物车
- 第九章 EL表达式
- 第十章 JSTL
- 第十一章 过滤器
- 第十二章 监听器
- 第十三章 文件的上传与下载
- 复习总结
- 如何手动启动Tomcat
- 如何修改Tomcat端口号
- 如何在web.xml中配置Servlet
- Servlet生命周期
- load-on-startup参数
- Servlet映射路径
- POST和GET的区别
- JSP中9个隐式对象及功能
- 请求转发及请求重定向的区别
- JSP指令有哪些
- 简述对MVC设计模式的理解
- 简述Cookie机制
- 简述Session机制
- HttpSession的生命周期
- Cookie和Session有什么区别
- 简述创建过滤器步骤
- 过滤器经典案例--统一编码字符集
- getParameter与getAttribute的区别
- JSP页面中可以包含哪些元素
- web应用中,是如何跟踪用户的
- InteliJ创建web项目