定义:过滤器是一个服务端的软件,它可以截取用户端的请求与响应信息,并对这些信息进行过滤。
工作原理:用户发送请求——>过滤器将用户请求发送至web资源——>资源响应发送至过滤器——>过滤器将web资源的响应发送给用户
过滤器的生命周期:
1. 实例化配
置Web.xml,启动时自动加载,只会实例化一次
2. 初始化
执行init()方法,也只执行一次
3. 过滤
doFilter(),执行N次,每次请求都会执行过滤方法
4. 销毁
destroy(),web容器关闭的时候执行
intit():
过滤器的初始化方法,web容器创建过滤器实例后调用这个方法,可以读取web.xml文件中过滤器的参数;
doFilter():
这个方法完成实际的过滤操作,当用户请求访问与过滤器关联的url时,web容器将先调用doFilter方法,FilterChain参数可以调用chain.doFilter,将请求传给下一个过滤器,或利用转发或重定向转发到其他资源。
destory():
web容器在销毁过滤器前调用,释放过滤器占用的资源(多数情况用不到)
问题?
1. 过滤器能否改变用户请求的Web资源,也就是能否改变用户请求的路径? 可以
2. 过滤器能否直接返回数据,能不能直接处理用户请求? 不可以
3. 多个过滤器如何实现?
4. 多个过滤器对应同一个用户路径的执行顺序如何?
过滤器链,按照web.xml中过滤器定义的先后顺序组装成一条链。
web.xml文件配置
过滤器的分类
1. request 用户直接访问页面时
2. forward .getRequestDispatcher().forward时调用
3. include .getRequestDispatcher().include时调用
4. error 通过声明式异常处理机制调用时,调用
默认request级别
通常转发更快一些,性能更好一些
- ASYNC 支持异步处理(servlet3.0)
@webfilter注解,将一个类声明为过滤器,该注解将会在部署时被容器处理,容器将根据具体的属性配置将相应的类部署为过滤器。
@webfilter(servletNames=”…”,filterName=”…”)
@webFilter常用属性
过滤器在实际项目中的应用场景 - 对用户请求进行统一认证
- 编码转换
- 对用户发送的数据进行过滤替换
- 转换图像格式
- 对响应的内容进行压缩
登陆案例代码片段
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>登陆案例</title>
</head>
<body>
<form action="servlet/LoginServlet"
method="post">
用户名: <input type="text" name="username"> 密码: <input
type="password" name="password"> <input type="submit"
value="提交">
</form>
</body>
</html>
public class LoginServlet extends HttpServlet
{
/**
*
*/
private static final long serialVersionUID = 8756299071983197411L;
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String username = req.getParameter("username");
String pwd = req.getParameter("password");
System.out.println(username);
if ("admin".equals(username) && "11111".equals(pwd)) {
//校验通过
HttpSession session = req.getSession();
session.setAttribute("username", username);
resp.sendRedirect(req.getContextPath() + "/success.html");
}
else {
//校验失败
resp.sendRedirect(req.getContextPath() + "/fail.html");
}
}
}
public class LoginFilter implements Filter
{
private FilterConfig config;
@Override
public void destroy() {
}
@Override
public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2)
throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) arg0;
HttpServletResponse response = (HttpServletResponse) arg1;
HttpSession session = request.getSession();
String nologinPaths = config.getInitParameter("nologinfilter");
request.setCharacterEncoding(config.getInitParameter("encoding"));//设置字符集
if (nologinPaths != null) {
String[] paths = nologinPaths.split(";");
for (int i = 0; i < paths.length; i++) {
if (paths[i] == null || "".equals(paths[i])) {
continue;
}
if (request.getRequestURI().indexOf(paths[i]) != -1) {
arg2.doFilter(arg0, arg1);
return;
}
}
}
//登陆页面不可能存在session,直接放行
if (request.getRequestURI().indexOf("login.html") != -1) {
arg2.doFilter(arg0, arg1);
return;//不 return的话,还是会继续往下执行,报错:Cannot call sendRedirect() after the response has been committed
}
if (session.getAttribute("username") == null || "".equals(session.getAttribute("username"))) {
response.sendRedirect("login.html");
}
else {
arg2.doFilter(arg0, arg1);
}
}
@Override
public void init(FilterConfig arg0) throws ServletException {
config = arg0;
}
}