过滤器Filter
1、 现有问题
在以往的Servlet中,有冗余的代码,多个Servlet都有重复的代码
比如编码格式设置
登录信息认证
2、 概念
过滤器(Filter)是处于客户端与服务器目标资源之间的一道过滤技术。
过滤器 |
---|
3、 过滤器作用
执行顺序在Servlet之前,客户端发送请求时,会先经过Filter,再到达目标Servlet中;响应时,会根据执行流程再次反向执行Filter
可以解决多个Servlet共性代码的冗余问题(例如:乱码处理、登录验证)
4、 编写过滤器
Servlet API中提供了一个
Filter接口
,开发人员编写一个Java类实现了这个接口
即可,这个Java类称之为过滤器(Filter)
编写Java类实现Filter接口
在
doFilter方法
中编写拦截逻辑设置拦截路径@WebFilter("path"),path写法
/* 拦截所有请求路径
/a 拦截指定的/a请求
*.do 拦截指定的后缀请求
也可以写对多个 {"/a","/b"}
5、 过滤器链和优先级
5.1 过滤器链
客户端对服务器请求之后,服务器调用Servlet之前会执行一组过滤器(多个过滤器),那么这组过滤器就称为一条过滤器链。
每个过滤器实现某个特定的功能,当第一个Filter的doFilter方法被调用时,Web服务器会创建一个代表Filter链的FilterChain对象传递给该方法。在doFilter方法中,开发人员如果调用了FilterChain对象的doFilter方法,则Web服务器会检查FilterChain对象中是否还有filter,如果有,则调用第2个filter,如果没有,则调用目标资源。
过滤器链 |
---|
5.2 过滤器优先级
在一个Web应用中,可以开发编写多个Filter,这些Filter组合起来称之为一个Filter链。 优先级:
如果为注解的话,是按照类全名称的字符串顺序决定作用顺序
6、 过滤器应用1:全局编码
以前: 在每个servlet为了防止乱码,在进行操作之前,都先设置请求和响应的编码格式.
现在: 使用拦截器,对所有请求拦截器,设置编码,然后放行
@WebFilter("/*")
public class EncodingFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException { }
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
// 设置编码格式
request.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
// 放行
chain.doFilter(request,response);
}
@Override
public void destroy() { }
}
7、 过滤器应用2: 身份认证拦截器
以前: 在web项目中,在每个Servlet中都要对身份进行认证
现在: 使用拦截器,将身份过滤的代码前置到拦截器,对每个请求先身份认证
@WebFilter("/*")
// @WebFilter("/hw/*")
// @WebFilter("*.do")
public class LoginFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException { }
/**
* 对请求的身份进行认证
* 请求中获得session,且session中有登录时存入的数据,说明登录成功,放行
* 请求中获得session,但是session中没有数据,说明没有登录,重定向到登录页
*/
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
// 获取session
HttpServletRequest req = (HttpServletRequest) request;
HttpSession session = req.getSession( );
String requestURI = req.getRequestURI( );
/**
* 因为是拦截所有 /*
* 所以要放行 静态资源以及第一次登录的请求
*/
if(requestURI.contains("login")) {
// 放行
chain.doFilter(request, response);
} else {
// 从session获得数据
String username = (String) session.getAttribute("username");
// 判断
if (username != null){
// 放行
chain.doFilter(request, response);
} else {
HttpServletResponse resp = (HttpServletResponse) response;
resp.sendRedirect("/index.jsp");
}
}
}
@Override
public void destroy() { }
}