JavaWeb Filter

1. 過濾器概述

1.1. 什麼是過濾器

Filter譯爲過濾器,是JavaWeb的三大組件之一,用於在Servlet以外對Request或者Response進行修改。對於Web應用程序來講,過濾器是一個駐留在服務器端的Web組件,它能夠截取客戶端和服務器端之間的請求與響應信息。html

1.2. 發展歷史

因爲Servlet規範是開放的,藉助於公衆與開源社區的力量,Servlet規範愈來愈科學,功能也愈來愈強大。2000年,Sun公司在Servlet2.3規範中添加了Filter功能,並在Servlet2.4中對Filter進行了細節上的補充。目前主流版本爲Servlet2.5Filterjava

1.3. 運行原理

Servlet是服務器端用於處理客戶端的請求與響應的,而Filter就是介於客戶端與服務器端攔截客戶端的請求或服務器端的響應,並對其修改或過濾。具體實現流程以下:web

當客戶端向服務器端發送一個請求時,若是有對應的過濾器進行攔截,過濾器能夠改變請求的內容、或者從新設置請求協議的相關信息等,而後再將請求發送給服務器端的Servlet進行處理。當Servlet對客戶端作出響應時,過濾器一樣能夠進行攔截,將響應內容進行修改或者從新設置後,再響應給客戶端瀏覽器。在上述過程當中,客戶端與服務器端並不須要知道過濾器的存在。api

在一個Web應用程序中,能夠部署多個過濾器進行攔截,這些過濾器組成了一個過濾器鏈。過濾器鏈中的每一個過濾器負責特定的操做和任務,客戶端的請求在這些過濾器之間傳遞,直到服務器端的Servlet。具體執行流程以下:瀏覽器

1.4. 第一個過濾器

Servlet API中提供了一個Filter接口,實現過濾器只須要實現該接口便可。如下是Filter接口的API緩存

Method Summary服務器

voidcookie

destroy() 
Called by the web container to indicate to a filter that it is being taken out of service.session

voidapp

doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 
The doFilter method of the Filter is called by the container each time a request/response pair is passed through the chain due to a client request for a resource at the end of the chain.

void

init(FilterConfig filterConfig) 
Called by the web container to indicate to a filter that it is being placed into service.

實現過濾器的具體步驟以下:

  • 建立一個Java類,並實現Filter接口,重寫該接口的方法。
public class MyFitler implements Filter {
    /**
     * init()方法用於Filter的初始化
     */
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("執行了Filter的init()方法...");
    }
    /**
     * doFilter()方法用於Filter的攔截
     */
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
        System.out.println("執行了Filter的doFilter()方法...");
    }
    /**
     * destory()方法用於Filter的銷燬
     */
    public void destroy() {
        System.out.println("執行了Filter的destroy()方法...");
    }
}
  • Web工程的web.xml文件中配置過濾器。
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" 
    xmlns="http://java.sun.com/xml/ns/javaee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
    http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
  <!-- 配置過濾器 -->
  <filter>
      <!-- 配置過濾器的名稱 -->
      <filter-name>MyFitler</filter-name>
      <!-- 配置對應過濾器類的完整路徑 -->
      <filter-class>app.java.fitler.MyFitler</filter-class>
  </filter>
  <!-- 配置過濾器的攔截路徑 -->
  <filter-mapping>
      <!-- 配置過濾器的名稱 -->
      <filter-name>MyFitler</filter-name>
      <!-- 配置過濾器的攔截的路徑 -->
      <url-pattern>/*</url-pattern>
  </filter-mapping>
</web-app>
  • 建立Web動態資源Servlet
public class HelloServlet extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html");
        PrintWriter out = response.getWriter();
        out.println("<h1>Hello Servlet.</h1>");
        out.flush();
        out.close();
    }
    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }
}
  • Web工程的web.xml文件中配置Servlet
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" 
    xmlns="http://java.sun.com/xml/ns/javaee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
    http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
  <servlet>
    <servlet-name>HelloServlet</servlet-name>
    <servlet-class>app.java.servlet.HelloServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>HelloServlet</servlet-name>
    <url-pattern>/hello</url-pattern>
  </servlet-mapping>
</web-app>
  • 建立Web工程的靜態資源JSP頁面。
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>hello.jsp</title>
    <meta http-equiv="pragma" content="no-cache">
    <meta http-equiv="cache-control" content="no-cache">
    <meta http-equiv="expires" content="0">    
  </head>
  <body>
    <h1>Hello JSP.</h1>
  </body>
</html>
  • 發佈Web工程並訪問,不管是訪問動態資源Servlet仍是靜態資源JSP,過濾器都會攔截,並執行過濾器的doFilter()方法。
  • 這時訪問的Servlet或者JSP並無被執行,緣由是過濾器只進行了攔截,並無將請求發送到對應的Servlet或者JSP。在過濾器的doFilter()方法中執行FilterChain對象的doFilter()方法將進行放行。
public class MyFitler implements Filter {
    /**
     * init()方法用於Filter的初始化
     */
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("執行了Filter的init()方法...");
    }
    /**
     * doFilter()方法用於Filter的攔截
     */
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
        System.out.println("執行了Filter的doFilter()方法...");
        chain.doFilter(request, response);
    }
    /**
     * destory()方法用於Filter的銷燬
     */
    public void destroy() {
        System.out.println("執行了Filter的destroy()方法...");
    }
}

2. 深刻過濾器

2.1. 生命週期

Servlet API提供的Filter接口中含有三個方法,分別爲init()doFilter()destroy()方法。該三個方式就是Filter的生命週期方法。

  • Filter的構造函數
  • Tomcat服務器啓動時執行。
  • Filter的生命週期中只執行一次。
  • init(FilterConfig)方法
    • Tomcat服務器啓動時執行。
    • Filter的生命週期中只執行一次。
    • 用於Filter的初始化工做。
  • doFilter(ServletRequest, ServletResponse, FilterChain)方法
    • 在每次攔截時執行。
    • Filter的生命週期中只執行屢次。
    • 用於Filter的攔截處理工做。
  • destroy()方法
    • Tomcat服務器關閉時執行。
    • Filter的生命週期中只執行一次。
    • 用於Filter的銷燬工做。

2.2. 過濾器鏈

在一個Web應用程序中,能夠部署多個過濾器進行攔截,這些過濾器組成了一個過濾器鏈。完成過濾器鏈的功能,具體步驟以下:

  • 建立一個Java類,並實現Filter接口,重寫該接口的方法。
public class MyFitler1 implements Filter {
    /**
     * init()方法用於Filter的初始化
     */
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("執行了Filter1的init()方法...");
    }
    /**
     * doFilter()方法用於Filter的攔截
     */
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
        System.out.println("執行了Filter1的doFilter()方法...");
    }
    /**
     * destory()方法用於Filter的銷燬
     */
    public void destroy() {
        System.out.println("執行了Filter1的destroy()方法...");
    }
}
  • 再建立一個Java類,並實現Filter接口,重寫該接口的方法。
public class MyFilter2 implements Filter {
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("執行了Filter2的init()方法...");
    }
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
        System.out.println("執行了Filter2的doFilter()方法...");
    }
    public void destroy() {
        System.out.println("執行了Filter2的destroy()方法...");
    }
}
  • Web工程的web.xml文件中配置過濾器。
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" 
    xmlns="http://java.sun.com/xml/ns/javaee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
    http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
  <!-- 配置過濾器 -->
  <filter>
      <!-- 配置過濾器的名稱 -->
      <filter-name>MyFitler</filter-name>
      <!-- 配置對應過濾器類的完整路徑 -->
      <filter-class>app.java.fitler.MyFitler</filter-class>
  </filter>
  <!-- 配置過濾器的攔截路徑 -->
  <filter-mapping>
      <!-- 配置過濾器的名稱 -->
      <filter-name>MyFitler</filter-name>
      <!-- 配置過濾器的攔截的路徑 -->
      <url-pattern>/*</url-pattern>
  </filter-mapping>
  <filter>
      <filter-name>MyFitler2</filter-name>
      <filter-class>app.java.fitler.MyFilter2</filter-class>
  </filter>
  <filter-mapping>
      <filter-name>MyFitler2</filter-name>
      <url-pattern>/*</url-pattern>
  </filter-mapping>
</web-app>

須要注意的是,FilterChaindoFilter()方法執行時,若是隻有一個過濾器的話,執行該方法會將請求發送給服務器端的動態或靜態資源。若是是過濾器鏈的話,只有在執行過濾器鏈的最後一個過濾器的FilterChaindoFilter()方法時,纔會將請求發送給服務器端的動態或靜態資源。若是不是在過濾器鏈的最後一個過濾器的FilterChaindoFilter()方法時,將請求發送給下一個過濾器進行攔截。

在過濾器鏈中的過濾器執行的前後順序是按照Web工程的web.xml文件配置過濾器的前後順序被執行。

2.3. FilterConfig

在過濾器接口的init()方法中提供了FilterConfig參數,經過該參數能夠獲取web.xml配置過濾器的參數內容,或者獲取ServletContext對象等。FilterConfig API內容以下:

Method Summary

String

getFilterName() 
Returns the filter-name of this filter as defined in the deployment descriptor.

String

getInitParameter(String name) 
Returns a String containing the value of the named initialization parameter, or null if the parameter does not exist.

Enumeration

getInitParameterNames() 
Returns the names of the filter's initialization parameters as an Enumeration of String objects, or an empty Enumeration if the filter has no initialization parameters.

ServletContext

getServletContext() 
Returns a reference to the ServletContext in which the caller is executing.

具體使用方式以下:

  • 建立一個Java類,並實現Filter接口,重寫該接口的方法。
public class MyFitler implements Filter {
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("執行了Filter的init()方法...");
    }
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
        System.out.println("執行了Filter的doFilter()方法...");
    }
    public void destroy() {
        System.out.println("執行了Filter的destroy()方法...");
    }
}
  • Web工程的web.xml文件中配置過濾器,而且設置初始化參數內容。
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" 
    xmlns="http://java.sun.com/xml/ns/javaee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
    http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
  <filter>
      <filter-name>MyFitler</filter-name>
      <filter-class>app.java.fitler.MyFitler</filter-class>
      <init-param>
          <param-name>longestory</param-name>
          <param-value>http://www.baidu.com.com</param-value>
      </init-param>
  </filter>
  <filter-mapping>
      <filter-name>MyFitler</filter-name>
      <url-pattern>/*</url-pattern>
  </filter-mapping>
</web-app>
  • 在過濾器的init()方法中獲取配置文件的初始化參數。
public class MyFitler implements Filter {
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("執行了Filter的init()方法...");
System.out.println(filterConfig.getInitParameter("longestory"));
    }
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
        System.out.println("執行了Filter的doFilter()方法...");
    }
    public void destroy() {
        System.out.println("執行了Filter的destroy()方法...");
    }
}

須要注意的是,經過getInitParameter()方法獲取的初始化參數是私有參數。只有當前過濾器才能獲取到,而其餘過濾器並不能訪問。若是配置全局初始化參數,可使用<context-param>來配置,並使用ServletContext對象獲取。

2.4. Filter映射配置

過濾器須要配置在web.xml中才能生效。一個過濾器須要配置<filter><filter-mapping>標籤,例如以下:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" 
    xmlns="http://java.sun.com/xml/ns/javaee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
    http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
  <!-- 配置過濾器 -->
  <filter>
      <!-- 配置過濾器的名稱 -->
      <filter-name>MyFitler</filter-name>
      <!-- 配置對應過濾器類的完整路徑 -->
      <filter-class>app.java.fitler.MyFitler</filter-class>
  </filter>
  <!-- 配置過濾器的攔截路徑 -->
  <filter-mapping>
      <!-- 配置過濾器的名稱 -->
      <filter-name>MyFitler</filter-name>
      <!-- 配置過濾器的攔截的路徑 -->
      <url-pattern>/*</url-pattern>
  </filter-mapping>
</web-app>

<filter>配置過濾器的名稱,實現類以及初始化參數。<filter-mapping>配置當前過濾器攔截的路徑。<filter-mapping>中的<url-pattern>標籤用於配置當前過濾器攔截的路徑,配置方式與Servlet<url-pattern>配置方式相似,共有三種方式:

  • 徹底匹配
  • 目錄匹配
  • 擴展名匹配

若是須要攔截的是Servlet的話,有兩種方式配置攔截路徑:

  • 使用<url-pattern>標籤:<url-pattern>/hello</url-pattern>
  • 使用<servlet-name>標籤:<servlet-name>HelloServlet</servlet-name>

<dispatcher>標籤配置到達Servlet的方法,有四種取值:REQUESTFORWARDINCLUDEERROR。能夠同時配置多個<dispatcher>標籤,若是沒有配置<dispatcher>標籤,默認爲REQUEST。這四種取值的區別以下:

  • REQUEST:表示僅當直接請求Servlet時才生效。
  • FORWARD:表示僅當某Servlet經過FORWARD到該Servlet時才生效。
  • INCLUDEJSP中能夠經過<jsp:include>標籤請求某Servlet或調用RequestDispatcherinclude()方法請求某Servlet,僅這種狀況下有效。
  • ERRORJSP中能夠經過<%@ page errorPage=」error.jsp」>標籤指定錯誤處理頁面,僅這種狀況下有效。

<url-pattern>標籤與<dispatcher>標籤的關係是「且」的關係。只有知足<url-pattern>標籤的條件,且知足<dispatcher>標籤的條件時,當前過濾器才能生效。

3. 過濾器案例

3.1. 全站亂碼案例

中文亂碼問題一直都是Web應用開發的問題,想要解決整個Web應用程序的中文亂碼問題,能夠以下操做:

  • 建立一個Java類繼承於HttpServletRequestWrapper類,用於重寫HttpServletRequest,解決GET方式的中文亂碼問題。
public class MyRequest extends HttpServletRequestWrapper {
    public MyRequest(HttpServletRequest request) {
        super(request);
    }
    @Override
    public String getParameter(String name) {
        String value = super.getParameter(name);
        if (getMethod().equalsIgnoreCase("GET")) {
            try {
                value = new String(value.getBytes("ISO-8859-1"),"utf-8");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        }
        return value;
    }
}
  • 建立一個過濾器用於解決整個Web應用程序的中文亂碼問題。
public class EncodingFilter implements Filter {
    public void init(FilterConfig filterConfig) throws ServletException {}
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
        request.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=utf-8");
        MyRequest req = new MyRequest((HttpServletRequest)request);
        chain.doFilter(req, response);
    }
    public void destroy() {}
}
  • 配置Web工程的web.xml文件。
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" 
    xmlns="http://java.sun.com/xml/ns/javaee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
    http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
  <filter>
      <filter-name>EncodingFilter</filter-name>
      <filter-class>app.java.demo4.EncodingFilter</filter-class>
  </filter>
  <filter-mapping>
      <filter-name>EncodingFilter</filter-name>
      <url-pattern>/*</url-pattern>
  </filter-mapping>
</web-app>
  • 建立一個JSP頁面用於中文亂碼問題的測試。
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>My JSP 'login.jsp' starting page</title>
  </head>
  <body>
    <form id="userinfo" action="encoding" method="post">
        用戶名:<input type="text" name="username"><br>
        密碼:<input type="password" name="password"><br>
        <input type="submit" value="登陸">
    </form>
    <a href="/encoding?username=張無忌">GET方式的中文亂碼問題</a>
  </body>
</html>
  • 建立一個Servlet用於測試中文亂碼問題。
public class EncodingServlet extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String username = request.getParameter("username");
        response.getWriter().println("<h1>username : "+username+"</h1>");
    }
    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }
}
  • 配置Web工程的web.xml文件。
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" 
    xmlns="http://java.sun.com/xml/ns/javaee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
    http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
  <servlet>
    <servlet-name>EncodingServlet</servlet-name>
    <servlet-class>app.java.servlet.EncodingServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>EncodingServlet</servlet-name>
    <url-pattern>/encoding</url-pattern>
  </servlet-mapping>
</web-app>

3.2. 自動登陸案例

所謂自動登陸就是當用戶第一次登陸後,而且選擇「自動登陸」選項,用戶從第二次訪問開始,用戶都無需再登陸,完成直接登陸的功能。具體實現步驟以下:

  • 建立一個JSP頁面用於用戶登陸功能。
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>My JSP 'login.jsp' starting page</title>
  </head>
  <body>
    <h3 style="color:red;">${msg }</h3>
    <form id="userinfo" action="login" method="post">
        用戶名:<input type="text" name="username"><br>
        密碼:<input type="password" name="password"><br>
        <input type="checkbox" name="autologin" value="true">自動登陸<br>
        <input type="submit" value="登陸">
    </form>
  </body>
</html>
  • 建立一個JavaBean用於封裝用戶信息。
public class User {
    private String username;
    private String password;
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
}
  • 建立一個Servlet用於處理用戶登陸邏輯。
public class LoginServlet extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }
    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        if("admin".equals(username)&&"admin".equals(password)){
            User user = new User();
            user.setUsername(username);
            user.setPassword(password);
            
            HttpSession session = request.getSession();
            session.setAttribute("user", user);
            
            if("true".equals(request.getParameter("autologin"))){
                Cookie cookie = new Cookie("autologin", username+"#"+password);
                cookie.setPath("/");
                cookie.setMaxAge(60 * 60 * 24 * 90);
                response.addCookie(cookie);
            }
            response.sendRedirect("index.jsp");
            return;
        }else{
            request.setAttribute("msg", "用戶名或密碼錯誤,請從新輸入.");
            request.getRequestDispatcher("login.jsp").forward(request, response);
            return;
        }
    }
}
  • 配置Web工程的web.xml文件。
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" 
    xmlns="http://java.sun.com/xml/ns/javaee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
    http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
  <servlet>
    <servlet-name>LoginServlet</servlet-name>
    <servlet-class>app.java.servlet.LoginServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>LoginServlet</servlet-name>
    <url-pattern>/login</url-pattern>
  </servlet-mapping>
</web-app>
  • 建立一個JSP頁面用於顯示主頁面,顯示用戶登陸信息。
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>My JSP 'index.jsp' starting page</title>
  </head>
  <body>
    <c:if test="${empty user }">
        <h1>您還未登陸,請去<a href="login.jsp">登陸</a></h1>
    </c:if>
    <c:if test="${not empty user }">
        <h1>歡迎您,${user.username }</h1>
    </c:if>
  </body>
</html>
  • 建立一個過濾器用於完成自動登陸功能。
public class AutoLoginFilter implements Filter {
    public void init(FilterConfig filterConfig) throws ServletException {}
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest)request;
        // 判斷用戶是否選擇手動登陸
        if(req.getSession().getAttribute("user") != null){
            // 已經登陸
            chain.doFilter(request, response);
            return;
        }else{
            // 沒有登陸,查找是否含有自動登陸Cookie
            Cookie autoLoginCookie = findCookie(req.getCookies(), "autologin");
            if (autoLoginCookie == null){
                // 沒有自動登陸信息
                chain.doFilter(request, response);
                return;
            }else{
                // 存在自動登陸信息
                String username = autoLoginCookie.getValue().split("#")[0];
                String password = autoLoginCookie.getValue().split("#")[1];
                if (!"admin".equals(username)||!"admin".equals(password)) {
                    // 自動登陸信息有問題
                    chain.doFilter(request, response);
                }else{
                    // 完成自動登陸功能
                    User user = new User();
                    user.setUsername(username);
                    user.setPassword(password);
                    req.getSession().setAttribute("user", user);
                    chain.doFilter(request, response);
                    return;
                }
            }
        }
    }
    public Cookie findCookie(Cookie[] cookies, String name) {
        if (cookies == null) {
            return null;
        } else {
            for (Cookie cookie : cookies) {
                if (cookie.getName().equals(name)) {
                    return cookie;
                }
            }
            return null;
        }
    }
    public void destroy() {}
}
  • 配置Web工程的web.xml文件。
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" 
    xmlns="http://java.sun.com/xml/ns/javaee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
    http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
  <filter>
      <filter-name>AutoLoginFilter</filter-name>
      <filter-class>app.java.demo2.AutoLoginFilter</filter-class>
  </filter>
  <filter-mapping>
      <filter-name>AutoLoginFilter</filter-name>
      <url-pattern>/index.jsp</url-pattern>
  </filter-mapping>
</web-app>

3.3. 權限控制案例

通常狀況下,Web應用程序不能容許全部用戶能夠訪問全部功能。換句話講,不一樣的用戶具備訪問不一樣功能的權限。因此,須要完成權限控制功能,具體操做以下:

  • 建立JavaBean用於封裝用戶信息(包含權限信息)。
public class User {
    private String username;
    private String password;
    private String role;
    public String getRole() {
        return role;
    }
    public void setRole(String role) {
        this.role = role;
    }
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
}
  • 建立Web應用程序的主頁面,用於用戶功能的顯示。
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>My JSP 'index.jsp' starting page</title>
  </head>
  <body>
    <c:if test="${empty user }">
        <h1>您還未登陸,請去<a href="login.jsp">登陸</a></h1>
    </c:if>
    <c:if test="${not empty user }">
        <h1>歡迎您,${user.username }</h1>
        <h1><a href="user/userlist.jsp">用戶操做功能列表</a></h1>
        <h1><a href="admin/adminlist.jsp">管理員操做功能列表</a></h1>
    </c:if>
  </body>
</html>
  • 建立用戶能夠訪問的功能列表頁面。
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>My JSP 'userlist.jsp' starting page</title>
  </head>
  <body>
    <h1>這裏是用戶操做的功能列表!</h1>
  </body>
</html>
  • 建立管理員能夠訪問的功能列表頁面。
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>My JSP 'adminlist.jsp' starting page</title>
  </head>
  <body>
    <h1>這裏是管理員操做的功能列表!</h1>
  </body>
</html>
  • 建立一個過濾器用於完成權限控制功能。
public class AuthoFilter implements Filter {
    private FilterConfig config;
    private Map<String, String> map = new HashMap<String, String>();
    public void init(FilterConfig filterConfig) throws ServletException {
        this.config = filterConfig;
    }
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
        Enumeration names = config.getInitParameterNames();
        while (names.hasMoreElements()) {
            String name = (String) names.nextElement();
            String value = config.getInitParameter(name);
            map.put(value, name);
        }
        HttpServletRequest req = (HttpServletRequest) request;
        String path = req.getRequestURI().substring(req.getContextPath().length());
        for (String needPath : map.keySet()) {
            if (path.startsWith(needPath)) {
                String needRole = map.get(needPath);
                User user = (User) req.getSession().getAttribute("user");
                if (user == null) {
                    req.getRequestDispatcher("login.jsp").forward(request, response);
                    return;
                }else {
                    String role = user.getRole();
                    if (needRole.equals(role)) {
                        chain.doFilter(request, response);
                        return;
                    }else {
                        throw new RuntimeException("權限不足,沒法訪問!");
                    }
                }
            }
        }
        chain.doFilter(request, response);
    }
    public void destroy() {}
}
  • 配置Web工程的web.xml文件。
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" 
    xmlns="http://java.sun.com/xml/ns/javaee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
    http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
  <filter>
      <filter-name>AuthoFilter</filter-name>
      <filter-class>app.java.demo3.AuthoFilter</filter-class>
      <init-param>
          <param-name>user</param-name>
          <param-value>/user</param-value>
      </init-param>
      <init-param>
          <param-name>admin</param-name>
          <param-value>/admin</param-value>
      </init-param>
  </filter>
  <filter-mapping>
      <filter-name>AuthoFilter</filter-name>
      <url-pattern>/*</url-pattern>
  </filter-mapping>
</web-app>

3.4. 禁用緩存案例

以前完成過禁止瀏覽器緩存功能,使用的是響應協議頭中的三個內容,以下:

Expires: -1

禁用瀏覽器緩存(考慮不一樣瀏覽器兼容性,存在三個字段)

Cache-Control: no-cache

Pragma: no-cache

在服務器端Servlet代碼以下:

//設置響應頭信息,禁止瀏覽器緩存.
response.setHeader("Cache-Control", "no-cache");
response.setHeader("Pragma", "no-cache");
response.setDateHeader("Expires", -1);

但這種方式只能適用於一個JSP頁面,而一個Web應用程序中可能包含多個JSP頁面。若是想要整個Web應用程序的全部JSP頁面都禁止緩存,須要使用過濾器功能來完成,具體操做以下:

  • 建立一個過濾器類,實現Filter接口,並重寫全部方法。
public class NoCacheFilter implements Filter {
    public void init(FilterConfig filterConfig) throws ServletException {}
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
        //1 將ServletResponse強轉爲HttpServletResponse
        HttpServletResponse res = (HttpServletResponse)response;
        //2 禁止瀏覽器緩存功能
        res.setHeader("Cache-Control", "no-cache");
        res.setHeader("Pragma", "no-cache");
        res.setDateHeader("Expires", -1);
        //3 過濾器放行
        chain.doFilter(request, response);
    }
    public void destroy() {}
}
  • 配置Web工程中的web.xml文件。
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" 
    xmlns="http://java.sun.com/xml/ns/javaee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
    http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
  <filter>
      <filter-name>NoCacheFilter</filter-name>
      <filter-class>app.java.demo1.NoCacheFilter</filter-class>
  </filter>
  <filter-mapping>
      <filter-name>NoCacheFilter</filter-name>
      <url-pattern>*.jsp</url-pattern>
  </filter-mapping>
</web-app>
相關文章
相關標籤/搜索