Filter可以認為是一種Servlet的加強版,有如下作用:
- 在HttpServletRequest到達Servlet之前將其攔截
- 檢查或修改HttpServletRequest頭和數據
- 在HttpServletResponse到達客戶端之前將其攔截
- 檢查或修改HttpServletResponse頭和數據
創建Filter######
實現看java.servlet.Filter接口,該接口定義了3個方法
- void init(FilterConfig config):完成Filter初始化
- void destory() :Filter銷毀前回收資源
- void doFilter(ServletRequest request, ServletResponse response, FilterChain chain): 實現過濾功能,即對每個請求和響應增加的額外處理
例如下面這個日志Filter,它攔截所有用戶請求并輸出日志
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
@WebFilter(filterName = "log", urlPatterns = "/*")
public class LogFilter implements Filter{
//FilterConfig可用于訪問Filter的配置信息
private FilterConfig config;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
this.config = config;
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//對用戶請求進行預處理
//獲取ServletContext對象 ,用于記錄日志
ServletContext context = this.config.getServletContext();
long before = System.currentTimeMillis();
System.out.println("開始過濾...");
//將請求轉換成HttpServletRequest請求
HttpServletRequest hrequest = (HttpServletRequest)servletRequest;
//輸出提示信息
System.out.println("Filter截取請求的地址:" + hrequest.getServletPath());
//將請求放行到目的地址
filterChain.doFilter(servletRequest,servletResponse);
//對服務器響應做后處理
long after = System.currentTimeMillis();
System.out.println("過濾結束。");
System.out.println("請求被定位到" + hrequest.getRequestURI() + " 花費時間 " + (after - before));
}
@Override
public void destroy() {
this.config = null;
}
}
在執行chain.doFilter()之前的對用戶請求進行預處理,執行chain.doFilter()之后就是對服務器響應進行后處理,chain.doFilter()是分水嶺。
配置Filter######
與Servlet類似,Filter既可以通過@WebFilter注釋配置,也可以在web.xml中配置
Filter的實際應用######
doFilter()通常是從多個Servlet的service()方法中提取相同代碼,提高代碼復用性。
下面的Filter將設置request的編碼字符集(避免每個JSP和Servlet都要設置一次),并驗證用戶是否登錄,否則跳轉到登錄頁
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.annotation.WebInitParam;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.io.IOException;
/**
* 1.設置request編碼的字符集,避免每個JSP和Servlet都要設置
* 2.驗證用戶是否登錄,如果沒有登錄,則跳轉到登錄頁面
*/
@WebFilter(filterName = "aythorrity", urlPatterns = {"/*"}, initParams = {
@WebInitParam(name="encoding", value="GBK"),
@WebInitParam(name="loginPage", value="/login.jsp"),
@WebInitParam(name="proLogin", value="/proLogin.jsp")})
public class AuthorityFilter implements Filter{
//FilterConfig可用于訪問Filter的配置信息
private FilterConfig config;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
this.config = config;
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//獲取配置參數
String encoding = config.getInitParameter("encoding");
String loginPage = config.getInitParameter("loginPage");
String proLogin = config.getInitParameter("proLogin");
//設置request編碼的字符集
servletRequest.setCharacterEncoding(encoding);
HttpServletRequest httpServletRequest = (HttpServletRequest)servletRequest;
HttpSession session = httpServletRequest.getSession(true);
//獲取客戶請求的頁面
String requestPath = httpServletRequest.getServletPath();
//如果session范圍的user為null,則表示未登錄
//如果用戶請求的既不是登錄頁面,也不是處理登錄的頁面
if (session.getAttribute("user") == null && !requestPath.endsWith(loginPage) && !requestPath.endsWith(proLogin)){
//forward到登錄頁面
servletRequest.setAttribute("tip","還未登陸");
servletRequest.getRequestDispatcher(loginPage).forward(servletRequest,servletResponse);
}
//放行請求
else {
filterChain.doFilter(servletRequest,servletResponse);
}
}
@Override
public void destroy() {
this.config = null;
}
}