一、简介
1、为什么需要拦截技术
这有点像我们小学数学中的提取公因式。把那些原本在每次请求或响应中都要重复做的事情,提取出来,统一在另外一个地方进行处理。
2、Filter的应用场景
编码过滤:统一编码。
敏感词过滤:对一些敏感的词用其他符号代替。
认证过滤:对用户请求进行统一的认证。
登录和审核过滤:对用户的访问请求进行记录和审核。
图像装换过滤:转换图像格式。
数据压缩过滤:对用户发生的数据进行压缩,从而减少传输量。
......
3、Filter的生命周期:
(1、)Filter的初始化
public void init(FilterConfig filterConfig)throws ServletException;//初始化
Filter的创建和销毁由web服务器负责。web应用程序启动时,web服务器将创建Filter的实例对象,并调用其init方法,读取web.xml配置,完成对象的初始化功能。Filter对象只会创建一次,init方法也只会执行一次。
(2、)执行拦截
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException;//拦截请求
这个方法完成实际的过滤操作。当客户请求访问与过滤器关联的URL的时候,Servlet过滤器将先执行doFilter方法。FilterChain参数用于访问后续过滤器。
(3、)Filter销毁
public void destroy();//销毁
Filter对象创建后会驻留在内存,当web应用移除或服务器停止时才被销毁。该方法在Filter的生命周期中仅执行一次。在这个方法中,可以释放过滤器使用的资源。
二、应用:
1、两个步骤:
1)新建一个java类,实现Filter接口,并实现其doFilter方法。
2)在web.xml文件中(或使用注解的方式),对编写的filter类进行注册,并设置它所能拦截的资源。
例:登录过滤器,只可以在地址栏输入登录网址,检测到没有登录则调到登录界面:
/**
*
*
* @Package: com.iflytek.controller
* @author: tingzhang
* @date: - - 上午 : :
*/
package com.iflytek.controller;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import com.iflytek.po.User;
/**
* @ClassName: LoginFilter
* @Description: 登录过滤器
* @author:tingzhnag7
* @date: 2018-3-11 下午1:42:24
*/
public class LoginFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
// TODO Auto-generated method stub
}
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
// 获得在下面代码中要用的request,response,session对象
HttpServletRequest servletRequest = (HttpServletRequest) request;
HttpServletResponse servletResponse = (HttpServletResponse) response;
HttpSession session = servletRequest.getSession();
// 获得用户请求的URI
String path = servletRequest.getRequestURI();
//System.out.println(path);
// 从session里取用户信息
User user = (User) session.getAttribute("user");
/*创建类Constants.java,里面写的是无需过滤的页面
for (int i = ; i < Constants.NoFilter_Pages.length; i++) {
if (path.indexOf(Constants.NoFilter_Pages[i]) > - ) {
chain.doFilter(servletRequest, servletResponse);
return;
}
}*/
// 登陆页面无需过滤
if(path.indexOf("/login") > -1 ) {
chain.doFilter(servletRequest, servletResponse);
return;
}
System.out.println("拦截器"+user);
// 判断如果没有取到员工信息,就跳转到登陆页面
if (user == null ) {
// 跳转到登陆页面
servletResponse.sendRedirect("../login/login");
} else {
// 已经登陆,继续此次请求
chain.doFilter(request, response);
}
}
@Override
public void destroy() {
// TODO Auto-generated method stub
}
}
在web.xml里注册一下就OK了:
<!-- 配置登陆过滤器 -->
<filter>
<filter-name>login</filter-name>
<filter-class>com.iflytek.controller.LoginFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>login</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
较全面的过滤器:
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* ajax请求session是否失效判断过滤器。
* <pre>
* 该过滤器只针对ajax请求,对于非ajax请求不执行任何逻辑操作。
* 如果是ajax请求,判断当前session是否失效,如果已经失效,则响应头增加session失效标识。
* </pre>
* @author chaofang3
*
*/
public class AjaxSessionFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse resp = (HttpServletResponse) response;
if (isAjaxRequest(req) && filterURI(req)) {
// 判断session是否失效
if (WebUtil.getCurrentUser(req) == null) {
resp.setHeader("sessionstatus", "timeout");
return;
}
}
chain.doFilter(request, response);
}
/**
* 当前请求是否为ajax异步请求。
* @param request 当前request
* @return 如果当前请求为ajax请求,返回true,否则返回false
*/
private boolean isAjaxRequest(HttpServletRequest request) {
return "XMLHttpRequest".equalsIgnoreCase(request
.getHeader("x-requested-with"));
}
/**
* 当前请求是否过滤请求。
* <pre>
* 如果为过滤请求,则判断ajax请求的session是否失效。
* 当前只有绑定操作是非过滤请求。
* </pre>
* @param request 当前request请求
* @return 如果是登录操作,则不是过滤URI,返回false,否则返回true
*/
private boolean filterURI(HttpServletRequest request) {
return !(request.getRequestURI().contains("ssoservice.jsp") || request.getRequestURI().contains("/login/") || request.getRequestURI().contains("/loginSuccess/") || request.getRequestURI().contains("/autoLogin/") || request.getRequestURI().contains("/reg/")|| request.getRequestURI().contains("/loginState/") || request.getRequestURI().contains("/getLoginFailTime/")
|| request.getRequestURI().contains("/stat/"));
}
@Override
public void destroy() {
}
}