Filter过滤器
概述
1. 什么是Filter过滤器
Filter过滤器是JavaEE的一个接口,是JavaWeb的三大组件之一(三大组件分别是:Servlet程序、Listener监听器、Filter过滤器),它的作用就是拦截请求,过滤响应
拦截请求常见的应用场景有:
- 权限检查
- 日志操作
- 事务管理
...
2. 如何创建一个Filter过滤器
要求:在web工程下,有一个admin目录,这个目录下的资源必须要求用户登录之后才能访问
目前阶段用户登录之后信息会保存在Session域中,所以判断用户是否登录,只需检查Session域中有没有用户信息即可
Filter代码示例:
/**
* doFilter():处理请求,拦截响应,可以做权限检查
* @param servletRequest
* @param servletResponse
* @param filterChain
* @throws IOException
* @throws ServletException
*/
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpSession session = request.getSession();
Object user = session.getAttribute("user");
if(user == null){
servletRequest.getRequestDispatcher("/login.jsp").forward(servletRequest,servletResponse);
}else{
//使程序继续访问目标资源
filterChain.doFilter(servletRequest,servletResponse);
}
}
web.xml中的配置:
<filter>
<filter-name>AdminFilter</filter-name>
<filter-class>com.th1024.filter.AdminFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>AdminFilter</filter-name>
<!--
/ 表示请求地址为:http://ip:port/工程路径/ 映射到IDEA web目录
/admin/* 表示拦截请求地址为:http://ip:port/工程路径/admin/*
-->
<url-pattern>/admin/*</url-pattern>
</filter-mapping>
Filter过滤器在请求到达服务器之后会先将请求拦截,并根据业务要求检查相应的权限,有权限即放行,无权限则不允许访问或跳转至某个页面
3. Filter过滤器的创建步骤
- 编写一个类实现Filter接口
- 实现执行过滤操作的方法doFilter()
- 在web.xml中配置Filter的拦截路径
完整的用户登录
登录表单:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
登录页面<br/>
<form action="http://localhost:8080/10_filter/loginServlet" method="get">
用户名:<input type="text" name="username"/><br/>
密 码:<input type="password" name="password"/><br/>
<input type="submit"/>
</form>
</body>
</html>
Servlet程序:
public class LoginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=UTF-8");
String username = req.getParameter("username");
String password = req.getParameter("password");
if("th1024".equals(username) && "123456".equals(password)){
req.getSession().setAttribute("user",username);
resp.getWriter().write("登录成功");
}else{
resp.sendRedirect(req.getContextPath() + "/login.jsp");
}
}
}
4. Filter过滤器的生命周期
在Filter过滤器中包含几个方法
-
构造器方法
-
init()初始化方法
第1、2步在web工程启动的时候执行(创建Filter过滤器)
-
doFilter()方法
第3步每次拦截到请求都会执行
-
destroy()方法
第4步在web工程停止的时候执行(销毁FIlter过滤器)
FilterConfig类
FilterConfig类是Filter过滤器的配置文件类,服务器在创建Filter过滤器对象时,也会同时创建一个FilterConfig类的对象,包含了Filter配置文件的信息
Java代码:
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("2.Filter 的init(FilterConfig filterConfig)初始化");
// 1、获取Filter 的名称filter-name 的内容
System.out.println("filter-name 的值是:" + filterConfig.getFilterName());
// 2、获取在web.xml 中配置的init-param 初始化参数
System.out.println("初始化参数username 的值是:" + filterConfig.getInitParameter("username"));
System.out.println("初始化参数url 的值是:" + filterConfig.getInitParameter("url"));
// 3、获取ServletContext 对象
System.out.println(filterConfig.getServletContext());
}
web.xml的配置:
<!--filter 标签用于配置一个Filter 过滤器-->
<filter>
<!--给filter 起一个别名-->
<filter-name>AdminFilter</filter-name>
<!--配置filter 的全类名-->
<filter-class>com.atguigu.filter.AdminFilter</filter-class>
<init-param>
<param-name>username</param-name>
<param-value>root</param-value>
</init-param>
<init-param>
<param-name>url</param-name>
<param-value>jdbc:mysql://localhost3306/test</param-value>
</init-param>
</filter>
FilterChain过滤器链
FilterChain过滤器链可以链式执行Filter过滤器的doFilter()方法
doFilter():
- 执行下一个Filter过滤器的doFilter()方法(有下一个Filter)
- 访问目标资源(没有下一个Filter)
执行顺序:按照在web.xml中配置Filter的先后顺序来执行
特点:
- 所有Filter过滤器和目标资源默认都执行在同一个线程中
- 多个Filter过滤器共同执行的时候,共用一个Request对象
Filter1:
public class Filter1 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("Filter1前置代码");
filterChain.doFilter(servletRequest,servletResponse);
System.out.println("Filter1后置代码");
}
@Override
public void destroy() {
}
}
Filter2:
public class Filter2 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("Filter2前置代码");
filterChain.doFilter(servletRequest,servletResponse);
System.out.println("Filter2后置代码");
}
@Override
public void destroy() {
}
}
web.xml中的配置:
<filter>
<filter-name>filter1</filter-name>
<filter-class>com.th1024.filter.Filter1</filter-class>
</filter>
<filter>
<filter-name>filter2</filter-name>
<filter-class>com.th1024.filter.Filter2</filter-class>
</filter>
<filter-mapping>
<filter-name>filter1</filter-name>
<url-pattern>/target.jsp</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>filter2</filter-name>
<url-pattern>/target.jsp</url-pattern>
</filter-mapping>
输出结果:
Filter1前置代码
Filter2前置代码
Filter2后置代码
Filter1后置代码
Filter过滤器的拦截路径
-
精确匹配
<url-pattern>/target.jsp</url-pattern>
表示请求地址必须为:http://ip:port/工程路径/target.jsp
-
目录匹配
<url-pattern>/admin/*</url-pattern>
表示请求地址必须为:http://ip:port/工程路径/admin/*
-
后缀名匹配
<url-pattern>*.html</url-pattern>
表示请求地址必须以.html结尾才会被拦截
Filter过滤器拦截请求与请求访问的资源是否存在没有关系
浙公网安备 33010602011771号