Filter&Listener11_Filter1
Filter:过滤器
1. 概念
* 生活中的过滤器:净水器,空气净化器,土匪
* web中的过滤器:当访问服务器的资源时,过滤器可以将请求拦截下来,完成一些特殊的功能。
* 过滤器的作用:一般用于完成通用的操作。如:登录验证、统一编码处理、敏感字符过滤...
2. 快速入门
a. 步骤:
1. 定义一个类,实现接口Filter
2. 复写方法
3. 配置拦截路径
1. web.xml
2. 注解
更改Filter模板:File-Settings-Editor-File and Code Templates-Other-Web-Java code templates-Filer Annotated Class.java,在这儿更改一下Filter类的脚本,新建的时候就能一键填充部分内容。
b. 代码:
注解配置拦截路径
@WebFilter("/*") //访问所有资源之前都会执行该过滤器
@WebFilter("/demo.jsp") //访问demo.jsp之前会执行该过滤器
package cn.itcast.web.filter; import javax.servlet.*; import javax.servlet.annotation.WebFilter; import java.io.IOException; /** * 过滤器快速入门程序 */ @WebFilter("/*")//访问所有资源之前都会执行该过滤器 public class FilterDemo1 implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { System.out.println("filterDemo1被执行了..."); //放行 filterChain.doFilter(servletRequest,servletResponse); } @Override public void destroy() { } }
index.jsp
<%-- Created by IntelliJ IDEA. User: ajing Date: 2022/2/28 Time: 21:16 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>$Title$</title> </head> <body> index.jsp... </body> </html>
如果不写filterChain.doFilter(servletRequest,servletResponse);那么浏览器访问http://localhost/day11/index.jsp,idea控制台输出:filterDemo1被执行了...,但是浏览器未输出index.jsp...,因为被拦截了;
写了filterChain.doFilter(servletRequest,servletResponse);那么浏览器访问http://localhost/day11/index.jsp时,idea控制台会输出:filterDemo1被执行了...,同时浏览器会输出index.jsp...
3. web.xml配置拦截路径
web包中新建路径WEB-INF,WEB-INF下新建web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1"> <filter> <filter-name>demo2</filter-name> <filter-class>cn.itcast.web.filter.FilterDemo2</filter-class> </filter> <filter-mapping> <filter-name>demo2</filter-name> <url-pattern>/*</url-pattern> <!-- 拦截路径 --> </filter-mapping> </web-app>
package cn.itcast.web.filter; import javax.servlet.*; import javax.servlet.annotation.WebFilter; import java.io.IOException; /** * 过滤器快速入门程序 */ public class FilterDemo2 implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { System.out.println("filterDemo2被执行了..."); //放行 filterChain.doFilter(servletRequest,servletResponse); } @Override public void destroy() { } }
浏览器访问http://localhost/day11/index.jsp,检查idea控制台输出:filterDemo2被执行了...,同时浏览器展示:index.jsp。
4. 过滤器执行流程
a. 执行过滤器
b. 执行放行后的资源
c. 回来执行过滤器放行代码下边的代码
package cn.itcast.web.filter; import javax.servlet.*; import javax.servlet.annotation.WebFilter; import java.io.IOException; @WebFilter("/*") public class FilterDemo3 implements Filter { public void destroy() { } public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException { //对request对象请求消息增强 System.out.println("filterDemo3执行了..."); //放行 chain.doFilter(req, resp); //对response对象的响应消息增强 System.out.println("filterDemo3回来了..."); } public void init(FilterConfig config) throws ServletException { } }
index.jsp
<%-- Created by IntelliJ IDEA. User: ajing Date: 2022/2/28 Time: 21:16 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>$Title$</title> </head> <body> index.jsp... <% System.out.println("index.jsp......"); %> </body> </html>
浏览器访问http://localhost/day11/index.jsp,检查浏览器输出:index.jsp...,同时idea控制台输出结果:
可以看出来执行顺序,先执行打印filterDemo3执行了...,然后执行放行,去执行index.jsp,输出到浏览器及idea控制台,执行完后执行放行下方的代码,打印:filterDemo3回来了...
5. 过滤器生命周期方法
a. init:在服务器启动后,会创建Filter对象,然后调用init方法。只执行一次。用于加载资源
b. doFilter:每一次请求被拦截资源时,会执行。执行多次
c. destroy:在服务器关闭后,Filter对象被销毁。如果服务器是正常关闭,则会执行destroy方法。只执行一次。用于释放资源
package cn.itcast.web.filter; import javax.servlet.*; import javax.servlet.annotation.WebFilter; import java.io.IOException; @WebFilter("/*") public class FilterDemo4 implements Filter { /** * 每一次请求被拦截资源时,会执行。执行多次 * @param req * @param resp * @param chain * @throws ServletException * @throws IOException */ public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException { System.out.println("doFilter..."); chain.doFilter(req, resp); } /** * 在服务器启动后,会创建Filter对象,然后调用init方法。只执行一次。用于加载资源 * @param config * @throws ServletException */ public void init(FilterConfig config) throws ServletException { System.out.println("init..."); } /** * 在服务器关闭后,Filter对象被销毁。如果服务器是正常关闭,则会执行destroy方法。只执行一次。用于释放资源 */ public void destroy() { System.out.println("destroy..."); } }
tomcat启动成功后,检查idea控制台输出:init...。
浏览器访问http://localhost/day11/index.jsp,检查输出doFilter...,再请求一次http://localhost/day11/index.jsp,继续输出doFilter...。
tomcat关闭服务后,检查idea控制台输出:destroy...
6. 过滤器配置详解
a. 拦截路径配置:
1. 具体资源路径: /index.jsp 只有访问index.jsp资源时,过滤器才会被执行。访问其他资源不会执行过滤器
2. 拦截目录: /user/* 访问/user下的所有资源时,过滤器都会被执行
3. 后缀名拦截: *.jsp 访问所有后缀名为jsp资源时,过滤器都会被执行
4. 拦截所有资源:/* 访问所有资源时,过滤器都会被执行
package cn.itcast.web.filter; import javax.servlet.*; import javax.servlet.annotation.WebFilter; import java.io.IOException; @WebFilter("/index.jsp") public class FilterDemo5 implements Filter { public void destroy() { } public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException { System.out.println("filterDemo5..."); chain.doFilter(req, resp); } public void init(FilterConfig config) throws ServletException { } }
浏览器访问http://localhost/day11/index.jsp,idea控制台会输出:filterDemo5...,访问http://localhost/day11/hello.jsp,过滤器不会被执行,idea控制台不会输出内容。
package cn.itcast.web.filter; import javax.servlet.*; import javax.servlet.annotation.WebFilter; import java.io.IOException; @WebFilter("/user/*") public class FilterDemo5 implements Filter { public void destroy() { } public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException { System.out.println("filterDemo5..."); chain.doFilter(req, resp); } public void init(FilterConfig config) throws ServletException { } }
package cn.itcast.web.servlet; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @WebServlet("/user/findAllServlet") public class ServletDemo1 extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("findAllServlet..."); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } }
package cn.itcast.web.servlet; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @WebServlet("/user/updateServlet") public class ServletDemo2 extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("updateServlet..."); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } }
浏览器访问http://localhost/day11/user/findAllServlet,检查idea控制台输出:filterDemo5...及findAllServlet...。浏览器访问http://localhost/day11/user/updateServlet,检查idea控制台输出filterDemo5...及updateServlet...。访问http://localhost/day11/index.jsp,检查idea控制台不会输出:filterDemo5...
package cn.itcast.web.filter; import javax.servlet.*; import javax.servlet.annotation.WebFilter; import java.io.IOException; @WebFilter("*.jsp") public class FilterDemo5 implements Filter { public void destroy() { } public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException { System.out.println("filterDemo5..."); chain.doFilter(req, resp); } public void init(FilterConfig config) throws ServletException { } }
浏览器访问http://localhost/day11/index.jsp,idea控制台会输出:filterDemo5...。访问http://localhost/day11/user/findAllServlet,过滤器不会被执行,idea控制台不会输出内容。
b. 拦截方式配置:资源被访问的方式
注解配置:
* 设置dispatcherTypes属性(数组)
1. REQUEST:默认值。浏览器直接请求资源
2. FORWARD:转发访问资源
3. INCLUDE:包含访问资源
4. ERROR:错误跳转资源
5. ASYNC:异步访问资源
web.xml配置
设置<dispatcher></dispatcher>标签即可
取值同上面5个,如:<dispatcher>REQUEST</dispatcher>
package cn.itcast.web.filter; import javax.servlet.*; import javax.servlet.annotation.WebFilter; import java.io.IOException; //浏览器直接请求资源时,该过滤器会被执行 @WebFilter(value = "/index.jsp",dispatcherTypes = DispatcherType.REQUEST) public class FilterDemo6 implements Filter { public void destroy() { } public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException { System.out.println("filterDemo6..."); chain.doFilter(req, resp); } public void init(FilterConfig config) throws ServletException { } }
package cn.itcast.web.servlet; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @WebServlet("/user/updateServlet") public class ServletDemo2 extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("updateServlet..."); //转发到index.jsp request.getRequestDispatcher("/index.jsp").forward(request,response); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } }
浏览器直接访问http://localhost/day11/index.jsp,idea控制台会输出:filterDemo6...。
浏览器访问http://localhost/day11/user/updateServlet,idea控制台不会输出内容。
package cn.itcast.web.filter; import javax.servlet.*; import javax.servlet.annotation.WebFilter; import java.io.IOException; //只有转发访问index.jsp时,该过滤器才会被执行 @WebFilter(value = "/index.jsp",dispatcherTypes = DispatcherType.FORWARD) public class FilterDemo6 implements Filter { public void destroy() { } public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException { System.out.println("filterDemo6..."); chain.doFilter(req, resp); } public void init(FilterConfig config) throws ServletException { } }
浏览器访问http://localhost/day11/user/updateServlet,idea控制台会输出:filterDemo6...。
浏览器访问http://localhost/day11/index.jsp,idea控制台不会输出内容。
package cn.itcast.web.filter; import javax.servlet.*; import javax.servlet.annotation.WebFilter; import java.io.IOException; //浏览器直接请求index.jsp或者转发访问index.jsp时,该过滤器都会被执行 @WebFilter(value = "/index.jsp",dispatcherTypes = {DispatcherType.REQUEST,DispatcherType.FORWARD}) public class FilterDemo6 implements Filter { public void destroy() { } public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException { System.out.println("filterDemo6..."); chain.doFilter(req, resp); } public void init(FilterConfig config) throws ServletException { } }
浏览器直接访问http://localhost/day11/index.jsp,idea控制台会输出:filterDemo6...。
浏览器访问http://localhost/day11/user/updateServlet,idea控制台会输出:filterDemo6...。
package cn.itcast.web.filter; import javax.servlet.*; import javax.servlet.annotation.WebFilter; import java.io.IOException; @WebFilter(value = "/*",dispatcherTypes = {DispatcherType.REQUEST,DispatcherType.FORWARD}) public class FilterDemo6 implements Filter { public void destroy() { } public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException { System.out.println("filterDemo6..."); chain.doFilter(req, resp); } public void init(FilterConfig config) throws ServletException { } }
浏览器直接访问http://localhost/day11/index.jsp,idea控制台会输出:filterDemo6...。
浏览器访问http://localhost/day11/user/updateServlet,idea控制台输出结果:
6. 过滤器链(配置多个过滤器)
a. 执行顺序:如果有两个过滤器:过滤器1和过滤器2
1. 过滤器1
2. 过滤器2
3. 资源执行
4. 过滤器2
5. 过滤器1
b. 过滤器先后顺序问题:
1. 注解配置:按照类名的字符串比较规则比较,值小的先执行
* 如: AFilter 和 BFilter,AFilter就先执行了。
2. web.xml配置: <filter-mapping>谁定义在上边,谁先执行
package cn.itcast.web.filter; import javax.servlet.*; import javax.servlet.annotation.WebFilter; import java.io.IOException; @WebFilter("/*") public class FilterDemo7 implements Filter { public void destroy() { } public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException { System.out.println("filterDemo7执行了。。。"); chain.doFilter(req, resp); System.out.println("filterDemo7回来了。。。"); } public void init(FilterConfig config) throws ServletException { } }
package cn.itcast.web.filter; import javax.servlet.*; import javax.servlet.annotation.WebFilter; import java.io.IOException; @WebFilter("/*") public class FilterDemo8 implements Filter { public void destroy() { } public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException { System.out.println("filterDemo8执行了。。。"); chain.doFilter(req, resp); System.out.println("filterDemo8回来了。。。"); } public void init(FilterConfig config) throws ServletException { } }
浏览器访问http://localhost/day11/index.jsp,检查idea控制台输出结果(7比8小所以FilterDemo7先执行):
7. 案例:登录验证
需求:
1. 访问day10_case案例的资源。验证其是否登录
2. 如果登录了,则直接放行。
3. 如果没有登录,则跳转到登录页面,提示"您尚未登录,请先登录"。
分析:
代码:
login.jsp
<%--
Created by IntelliJ IDEA.
User: ajing
Date: 2022/2/26
Time: 20:42
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>login</title>
<script>
window.onload = function(){
document.getElementById("img").onclick = function () {
this.src="/day10/checkCodeServlet?time="+ new Date().getTime();
}
}
</script>
<style>
div{
color: red;
}
</style>
</head>
<body>
<form action="/day10/loginServlet" method="post">
<table>
<tr>
<td>用户名</td>
<td><input type="text" name="username"></td>
</tr>
<tr>
<td>密码</td>
<td><input type="text" name="password"></td>
</tr>
<tr>
<td>验证码</td>
<td><input type="text" name="checkCode"></td>
</tr>
<tr>
<td colspan="2"><img id="img" src="/day10/checkCodeServlet"></td>
</tr>
<tr>
<td colspan="2"><input type="submit" value="登录"></td>
</tr>
</table>
</form>
<div><%=request.getAttribute("cc_error") == null ? "":request.getAttribute("cc_error")%></div>
<div><%=request.getAttribute("login_error") == null ? "" : request.getAttribute("login_error")%></div>
</body>
</html>
package cn.itcast.servlet;
import cn.itcast.dao.UserDao;
import cn.itcast.domain.User;
import org.apache.commons.beanutils.BeanUtils;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;
@WebServlet("/loginServlet")
public class LoginServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1. 设置request编码
request.setCharacterEncoding("utf-8");
//2. 获取参数Map
Map<String, String[]> map = request.getParameterMap();
//3. 创建User对象
User loginUser = new User();
UserDao dao = new UserDao();
try {
BeanUtils.populate(loginUser,map);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
//3. 先获取生产的验证码
HttpSession session = request.getSession();
String checkCode_session = (String) session.getAttribute("checkCode_session");
//删除session中存储的验证码
session.removeAttribute("checkCode_session");
//3.先判断验证码是否正确
if(checkCode_session != null && checkCode_session.equalsIgnoreCase(map.get("checkCode")[0])){
//忽略大小写比较
//验证码正确
//判断用户名和密码是否一致
//4. 调用UserDao的login方法
User user = dao.login(loginUser);
if(user != null){
//登录成功
//存储信息:用户信息
session.setAttribute("user",user.getUsername());
//重定向到success.jsp
response.sendRedirect(request.getContextPath()+"/success.jsp");
}else {
//登录失败
//存储提示信息到request
request.setAttribute("login_error","用户名或密码错误");
//转发到登录页面
request.getRequestDispatcher("/login.jsp").forward(request,response);
}
}else{
//验证码不一致
//存储提示信息到request
request.setAttribute("cc_error","验证码错误");
//转发到登录页面
request.getRequestDispatcher("/login.jsp").forward(request,response);
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
success.jsp
<%--
Created by IntelliJ IDEA.
User: ajing
Date: 2022/2/26
Time: 21:15
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1><%=request.getSession().getAttribute("user")%>,欢迎您</h1>
</body>
</html>
package cn.itcast.filter;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
/**
* 登录验证的过滤器
*/
@WebFilter("/*")
public class LoginFilter implements Filter {
public void destroy() {
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
//0. 强制转换
HttpServletRequest request = (HttpServletRequest) req;
//1. 获取资源请求路径
String uri = request.getRequestURI();
//2.判断是否包含登录相关的资源路径,要注意排除掉css/js/图片/验证码等资源
if(uri.contains("/login.jsp")|| uri.contains("/loginServlet")|| uri.contains("/css")|| uri.contains("/js")|| uri.contains("/fonts")|| uri.contains("/checkCodeServlet")){
//包含,用户想登陆。放行
chain.doFilter(req, resp);
}else{
//不包含,需要验证用户是否登录
//3.从获取session中获取user
Object user = request.getSession().getAttribute("user");
if(user!=null){
//登录了,放行
chain.doFilter(req, resp);
}else{
//没有登录,跳转登录页面
request.setAttribute("login_error","您尚未登录,请先登录");
request.getRequestDispatcher("/login.jsp").forward(request,resp);
}
}
}
public void init(FilterConfig config) throws ServletException {
}
}