問題:Filter是什麼,它能做什麼?
1.從兩個方面來解析Filter是什麼?
1.功能 可以幫助我們對請求與響應操作進行過濾。
2.技術 Sun公司定義的一個接口,javax.servlet.Filter
2.Filter能完成什麼操作?
常用示例:
1.通用編碼過濾器.
2.粗粒度的權限控制(url級別)
3.過濾一些敏感字
Filter創建步驟:
1.創建一個類實現javax.servlet.Filter接口。
2.重寫Filter接口中三個方法 init doFilter destroy.
3.在web.xml文件中配置Filter
爲什麼在web.xml文件中配置Filter?
1.Filter也是一個資源,也要被服務器加載,所以要在web.xml文件中配置.
2.我們在web.xml文件中配置Filter的另一個目的是用來設置Filter攔截什麼資源。
實例:需求:網站登錄的時候當用戶勾選自動登錄選框之後,當用戶再來登錄,自動登錄進網站。
準備:簡單的模擬如下頁面:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title></title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
</head>
<body>
<h3>這裏是最美網</h3>
<c:if test="${ not empty existUser}">
<h2>歡迎您:${existUser.nickname }</h2>
</c:if>
<c:if test="${empty existUser }">
<a href="${pageContext.request.contextPath }/login.jsp">請登錄</a>
</c:if>
<h3>新聞標題</h3>
<h2>大閱兵</h2>
</body>
</html>
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title></title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
</head>
<body>
<form action="${pageContext.request.contextPath }/login" method="post">
<p style="color:red">${msg }</p>
用戶名:<input type="text" id="username" name = "username"><br>
密碼:<input type="password" id="password" name="password"><br>
<input type="checkbox" name="autologin" value="auto_ok">自動登錄<br>
<button type="submit" value="登錄">登錄</button>
</form>
</body>
</html>
過濾器:
public class myFilter implements Filter {
public void destroy() {
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
/**
* 從session中獲取existUser
* 如果不爲空,說明已經登錄並且沒有關閉瀏覽器,放行
* 如果爲空說明沒有登錄,獲取指定名稱的cookie
* *如果找不到該cookie說明用戶沒有開啓自動登錄功能 ,放行
* *如果不爲空,從cookie中拿到用戶名和密碼從數據庫中查詢
* *如果查不到 ,則用戶名或密碼改變了,不處理 放行
* *如果查到了放到session中,放行
*
*/
//從session中獲取用戶existUser
HttpServletRequest req =(HttpServletRequest) request ;
HttpSession session = req.getSession();
User existUser =(User) session.getAttribute("existUser");
if (existUser!=null) {
chain.doFilter(req, response);
}else {
//爲空,說明沒有登錄
//獲取指定cookie
//獲取保存cookie的數組
Cookie []cookies = req.getCookies();
Cookie cookie =MyCookieUtile.findCookieByName(cookies, "autologin");
//判斷cookie是否爲空
if (cookie==null) {
chain.doFilter(req, response);
}else{
//獲取cookie的value值
String value = cookie.getValue();
String username = value.split(":")[0];
String password = value.split(":")[1];
//拿到cookie中的用戶名和密碼去數據庫中查
UserDao dao = new UserDao();
try {
User user = dao.checkUser(username, password);
if (user==null) {
chain.doFilter(req, response);
}else{
//說明成功,自動登錄
session.setAttribute("existUser",user);
//放行
chain.doFilter(req, response);
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public void init(FilterConfig filterConfig) throws ServletException {
}
}
public class MyCookieUtile {
/**
* 通過傳入的cookie名稱從傳入的cookie數組中查找cookie
* 如果數組爲空,則沒有找到返回爲null
* 如果不爲空,找到返回cookie
* @param cookies
* @param cookiename
* @return
*/
public static Cookie findCookieByName(Cookie []cookies,String cookiename){
if (cookies==null) {
return null;
}else{
for (Cookie cookie : cookies) {
//獲取cookie的名稱和傳入的名稱對比
if (cookiename.equals(cookie.getName()) ) {
//相同則返回
return cookie;
}
}
return null;
}
}
}
servlet:
public class LoginServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
/**
* 接收參數
* 根據用戶名和密碼查詢數據庫
* 如果成功,返回到content頁
* 如果不成功,返回登錄頁繼續登錄
*/
//解決中文亂碼問題
request.setCharacterEncoding("UTF-8");
String username = request.getParameter("username");
String password = request.getParameter("password");
//調用dao層查詢
UserDao dao = new UserDao();
try {
User existUser = dao.checkUser( username, password);
if (existUser==null) {
request.setAttribute("msg", "用戶名或密碼錯誤");
request.getRequestDispatcher("/login.jsp").forward(request, response);
}else{
//登錄成功
//回寫cookie
String autologin = request.getParameter("autologin");
if ("auto_ok".equals(autologin)) {
String value = username+":"+password;
Cookie cookie = new Cookie("autologin", value);
//設置有效時間
cookie.setMaxAge(60*60);
//設置有效路徑
cookie.setPath("/");
//回寫到客戶端
response.addCookie(cookie);
}
request.getSession().setAttribute("existUser", existUser);
//重定向到content頁面
response.sendRedirect(request.getContextPath()+"/content.jsp");
}
} catch (SQLException e) {
e.printStackTrace();
}
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doGet(request, response);
}
}
最後在配置文件中web.xml文件中配置filter。這樣當用戶勾選了自動登錄,關閉瀏覽器之後,再次訪問即可自動登錄進網站。
在我們創建一個Filter時,要重寫接口中的方法,有一個方法doFilter,它就是用於攔截操作的方法。在配置Filter時,可以指定攔截什麼資源,當瀏覽器訪問這個資源時,Filter的doFilter方法就會執行攔截操作。
我們如果在Filter中,它的doFilter方法執行了,代表攔截操作開始了,如果想要讓其可以繼續向下訪問資源,就需要通過doFilter方法的第三個參數FilterChain類型,調用它的doFilter方法,完成向下執行操作。
總結:
1.在Filter中具體的攔截操作是由doFilter方法執行的。 如果要想訪問資源,需要chain.doFilter()放行.
2.攔截什麼資源是由web.xml文件中配置的Filter確定的。