一、概念
Filter:过滤器,JavaWeb三大组件(Servlet,Filter,Listener)之一。作用是把对资源的请求拦截下来,从而实现一些特殊的功能。一般完成一些通用的操作,比如:权限控制、统一编码处理、敏感字符处理等。
二、快速使用
上面提到Filter是JavaWeb的三大组件之一,那么可想而知其使用过程与Servlet开发是极其相似的。即实现固定接口Filter,覆盖相关方法doFilter,注解配置路径@WebFilter三步即可。
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
@WebFilter("/*")
public class FilterDemo 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("filter demo...");
// 一定要有这一行,表示处理完请求后,放行,会请求到目标资源
filterChain.doFilter(servletRequest, servletResponse);
// 请求完目标资源后,将回到此处
// todo
}
@Override
public void destroy() {
}
}
三、执行流程
请求会在到达Servlet之前与响应离开Servlet之后进行拦截和过滤处理,而分界点就是上面代码片段中的filterChain.doFilter(req, resp)方法。总结:执行放行前逻辑-放行-访问目标资源-执行放行后逻辑。因此,我们常常在该方法之前对请求参数做处理,在该方法之后对响应做处理。
四、过滤器链
如果有多个过滤器,则会形成一个过滤器链,执行流程如下所示:
如果是注解配置的Filter,优先级会按照名称自然排序
五、登录小案例
在一个系统中,我们不允许未登录状态下去访问一些资源,如果拦截器发现是未登录状态时,则不允许访问目标资源,自动跳转到登录页面。
(1)先准备一个用于登录的页面,需要填写用户名与密码,我们把信息提交到/login的servlet中
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Tomcat</title>
</head>
<body>
<h1>hello tomcat</h1>
<form action="/javaweb/login" method="post">
<input type="text" name="username">
<input type="password" name="password">
<input type="submit">
</form>
</body>
</html>
(2)在登录的servlet中,我们完成用户名与密码的验证,并利用session将登录状态设置为已登录,并跳转到hello.jsp页面中
import com.byhuang.mvc.mapper.UserMapper;
import com.byhuang.mvc.util.SqlSessionFactoryUtil;
import com.byhuang.pojo.User;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
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.util.Objects;
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
HttpSession session = req.getSession();
String username = (String) req.getParameter("username");
String password = (String) req.getParameter("password");
SqlSessionFactory sqlSessionFactory = SqlSessionFactoryUtil.getSqlSessionFactory();
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user = mapper.getUserByName(username);
System.out.println(user);
if (Objects.nonNull(user) && password.equals(user.getPassword())) {
session.setAttribute("is_login", true);
}
req.getRequestDispatcher("/hello.jsp").forward(req, resp);
}
}
(3)我们在拦截器中设置,要访问hello.jsp页面会被拦截,必须先校验session域中的登录状态,校验不通过则转到登录页面a.html中
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.Objects;
@WebFilter("/hello.jsp")
public class LoginFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
HttpSession session = httpServletRequest.getSession();
System.out.println(session.getId());
Object isLogin = session.getAttribute("is_login");
if (Objects.isNull(isLogin) || !(boolean) isLogin) {
httpServletRequest.getRequestDispatcher("/a.html").forward(servletRequest, servletResponse);
}
filterChain.doFilter(servletRequest, servletResponse);
System.out.println("request back...");
}
@Override
public void destroy() {
}
}
(4)测试:我们直接访问hello.jsp时,会重定向到a.html页面要求先登录。在登录后,我们可以打开一个新的浏览器tab页,可以直接访问hello.jsp页面。
以上便是我们对Filter的介绍,请读者关注下一篇关于Listener的介绍,届时我们将完成对Java Web三大组件的介绍。