26、Filter一些常見應(yīng)用(2)(JavaEE筆記)

一、統(tǒng)一全站字符編碼

通過配置參數(shù)encoding指明使用何種字符編碼,以處理html form請(qǐng)求參數(shù)的中文問題。
CharacterEncodingFilter.java

package cn.itcast.web.filter;
//解決全站亂碼
import java.io.IOException;
import java.nio.charset.Charset;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

public class CharacterEncodingFilter implements Filter {
    
    private FilterConfig FilterConfig = null;
    private String defaultCharset = "UTF-8";
    
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        this.FilterConfig = filterConfig;

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
        String charset = FilterConfig.getInitParameter("charset");
        if(charset == null){
            //如果為空,則表示沒有配置編碼,使用默認(rèn)的編碼
            charset = defaultCharset;   
        }
        request.setCharacterEncoding(charset);//這樣設(shè)置只對(duì)post方式有效
        response.setCharacterEncoding(charset);
        response.setContentType("text/html;charset=" + charset);
        
        chain.doFilter(request, response);

    }

    @Override
    public void destroy() {
    }
}

配置:web.xml

    <filter>
        <filter-name>CharacterEncodingFilter</filter-name>
        <filter-class>cn.itcast.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>charset</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
      </filter>
    <filter-mapping>
        <filter-name>CharacterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
      </filter-mapping> 

二、禁止瀏覽器緩存所有動(dòng)態(tài)頁面的過濾器

  • 有3個(gè)http響應(yīng)頭字段都可以禁止瀏覽器緩存當(dāng)前頁面,它們?cè)赟ervlet中的示例代碼如下:
response.setDateHeader("Expires",-1);
response.setHeader("Cache-Control","no-cache");
response.setHeader("Prama","no-cache");

并不是所有的瀏覽器都能完全支持上面的三個(gè)響應(yīng)頭,因此最好是同時(shí)使用上面的三個(gè)響應(yīng)頭。

  • Expires數(shù)據(jù)頭:值為GMT時(shí)間值,為-1指瀏覽器不要緩存頁面
  • Cache-Control響應(yīng)頭有兩個(gè)常用值:
  • No-cache:瀏覽器不要緩存當(dāng)前頁面
  • Max-age:xxx指瀏覽器緩存頁面xxx秒

示例:
NoCacheFilter.java

public void doFilter(ServletRequest req, ServletResponse resp,
            FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;
        response.setDateHeader("Expires", -1);
        response.setHeader("cache-control", "no-cache");
        response.setHeader("Pragma", "no-cache");
        
        chain.doFilter(request, response);
    }

配置:

<filter>
    <filter-name>NoCacheFilter</filter-name>
    <filter-class>cn.itcast.web.filter.NoCacheFilter</filter-class>
  </filter>
  
  <filter-mapping>
    <filter-name>NoCacheFilter</filter-name>
    <servlet-name>*.jsp</servlet-name>
  </filter-mapping>

說明:這里我們不讓jsp進(jìn)行緩存,所以配置的是*.jsp。還有,要注意首先要將請(qǐng)求和響應(yīng)對(duì)象進(jìn)行轉(zhuǎn)換。

三、控制瀏覽器緩存頁面中的靜態(tài)資源的過濾器

頁面中的有些資源是很長(zhǎng)時(shí)間不變的,比如一些圖片或是一些js和css文件,我們可以通過緩存這些資源以提高服務(wù)器的性能。

ExpiresFilter.java

package cn.itcast.web.filter;
//控制緩存
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;

public class ExpiresFilter implements Filter {

    private FilterConfig filterConfig = null;
    
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        this.filterConfig = filterConfig;
    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse resp,
            FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;
        //1.獲取用戶想訪問的資源
        String uri = request.getRequestURI();
        
        //2.得到用戶想訪問的資源的后綴名
        String ext = uri.substring(uri.lastIndexOf(".") + 1);
        
        //3.得到資源需要緩存的時(shí)間
        String time = filterConfig.getInitParameter(ext);
        if(time != null){
            long t = Long.parseLong(time)*3600*1000;
            response.setDateHeader("expires", System.currentTimeMillis() + t);//注意:這里一定要是一個(gè)long型時(shí)間值
            
        }
        chain.doFilter(request, response);
    }

    @Override
    public void destroy() {
    }
}

配置

  <filter>
        <filter-name>ExpiresFilter</filter-name>
        <filter-class>cn.itcast.web.filter.ExpiresFilter</filter-class>
        <init-param>
            <param-name>css</param-name>
            <param-value>4</param-value>
        </init-param>
        <init-param>
            <param-name>jpg</param-name>
            <param-value>4</param-value>
        </init-param>
        <init-param>
            <param-name>js</param-name>
            <param-value>4</param-value>
        </init-param>
     </filter>
      <filter-mapping><!--一個(gè)filter對(duì)應(yīng)多個(gè)filter-mapping-->
        <filter-name>ExpiresFilter</filter-name>
        <url-pattern>*.jpg</url-pattern>
      </filter-mapping>
      <filter-mapping>
        <filter-name>ExpiresFilter</filter-name>
        <url-pattern>*.css</url-pattern>
      </filter-mapping>
      <filter-mapping>
        <filter-name>ExpiresFilter</filter-name>
        <url-pattern>*.js</url-pattern>
      </filter-mapping>

說明:從上面的例子中可以看到我們可以精確配置一些靜態(tài)資源緩存活的時(shí)間。如果想看到效果,在試驗(yàn)的時(shí)候可以先在IE瀏覽器中清除緩存,Internet選項(xiàng)-->刪除(將最上面的保留收藏夾網(wǎng)站…的勾去掉)-->刪除,然后設(shè)置-查看文件可以看到目錄中的緩存內(nèi)容,對(duì)于我們想要緩存的內(nèi)容我們可以查看其有效時(shí)間是否和我們?cè)O(shè)置的一樣。

四、保護(hù)執(zhí)行敏感操作servlet

在實(shí)際開發(fā)中我們經(jīng)常把一些執(zhí)行敏感操作的Servlet映射到一些特殊目錄中,并用Filter把這些特殊目錄保護(hù)起來,限制只能擁有相應(yīng)的訪問權(quán)限的用戶才能訪問這些目錄下的資源。從而在我們系統(tǒng)中實(shí)現(xiàn)一種URL級(jí)別的權(quán)限功能。

要求:為使Filter具有通用性,F(xiàn)ilter保護(hù)的資源和相應(yīng)的訪問權(quán)限通過Filter參數(shù)的形式予以配置。(以后會(huì)講到,這里提一下)

五、實(shí)現(xiàn)用戶自動(dòng)登錄的過濾器

  • 在用戶登錄成功后,發(fā)送一個(gè)名稱為user的cookie給客戶端,cookie的值為用戶名和md5加密后的密碼。

  • 編寫一個(gè)AutoLoginFilter,這個(gè)Filter檢查用戶是否帶有名稱為user的cookie來,如果有,則調(diào)用dao查詢cookie的用戶名和密碼是否和數(shù)據(jù)庫中的匹配,匹配則向session中存入user對(duì)象(即用戶登錄標(biāo)記),以實(shí)現(xiàn)程序完成自動(dòng)登錄。

過濾器:AutoLoginFilter.java

package cn.itcast.web.filter;
import java.io.IOException;
import java.net.CookieStore;
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.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import cn.itcast.dao.UserDao;
import cn.itcast.domain.User;
import cn.itcast.utils.WebUtils;

public class AutoLoginFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse resp,
            FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;
        
        if(request.getSession().getAttribute("user") != null){//表示已經(jīng)登錄了
            chain.doFilter(request, response);
            return;
        }
        
        //1.得到用戶帶來的autologin的cookie
        String value =null;
        Cookie cookies[] = request.getCookies();
        for(int i = 0; cookies != null && i < cookies.length; i++){
            if(cookies[i].getName().equals("autologin")){
                value = cookies[i].getValue();
            }
        }
        //2.得到cookie中的用戶名和密碼
        if(value != null){
            String username = value.split("\\.")[0];
            String password = value.split("\\.")[1];
            
            //3.調(diào)用dao獲取用戶對(duì)應(yīng)的密碼
            UserDao dao = new UserDao();
            User user = dao.find(username);
            String dbpassword = user.getPassword();
            
            //4.檢查用戶帶過來的md5密碼和數(shù)據(jù)庫中的密碼是否匹配,如果匹配則自動(dòng)登錄
            if(password.equals(WebUtils.md5(dbpassword))){
                request.getSession().setAttribute("user", user);
            }   
        }
        
        chain.doFilter(request, response);  
    }

    @Override
    public void destroy() {
    }
}

說明:程序中可以看到我們會(huì)在cookie中存入一個(gè)名為autologin的標(biāo)記,其值是用戶名和使用md5加密的密碼,使用點(diǎn)號(hào)分隔。

配置:

<filter>
    <filter-name>AutoLoginFilter</filter-name>
    <filter-class>cn.itcast.web.filter.AutoLoginFilter</filter-class>
</filter> 
<filter-mapping>
    <filter-name>AutoLoginFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

處理登錄業(yè)務(wù)的servlet:LoginServlet.java

package cn.itcast.web.servlet;
import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import sun.misc.BASE64Encoder;
import cn.itcast.dao.UserDao;
import cn.itcast.domain.User;
import cn.itcast.utils.WebUtils;

public class LoginServlet extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        UserDao dao = new UserDao();
        User user = dao.find(username, password);
        if(user == null){
            request.setAttribute("message", "用戶名或密碼不對(duì)?。?);
            request.getRequestDispatcher("/message.jsp").forward(request, response);
            return ;
        }
        request.getSession().setAttribute("user", user);//對(duì)session作一個(gè)標(biāo)記
        request.setAttribute("message", "登錄成功?。?!");
        
        //發(fā)送自動(dòng)登錄的cookie
        sendAutoLoginCookie(request,response,user);
        request.getRequestDispatcher("/message.jsp").forward(request, response);
    }

    private void sendAutoLoginCookie(HttpServletRequest request, HttpServletResponse response, User user) {
        
        int logintime = Integer.parseInt(request.getParameter("logintime"));//得到時(shí)間值
        Cookie cookie = new Cookie("autologin", user.getUsername() + "." + WebUtils.md5(user.getPassword()));//使用點(diǎn)號(hào)進(jìn)行分割,而BASE64中是沒有點(diǎn)號(hào)的
        cookie.setMaxAge(logintime);//設(shè)置cookie的有效時(shí)間
        cookie.setPath("/day18");//設(shè)置cookie的有效路徑,即day18的所有cookie
        
        response.addCookie(cookie);
    }
    
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }
}

dao層:UserDao.java

package cn.itcast.dao;
import java.util.List;
import cn.itcast.db.MyDb;
import cn.itcast.domain.User;

public class UserDao {
    
    public User find(String username, String password){
        
        List<User> list = MyDb.getAll();
        for(User user : list){
            if(user.getUsername().equals(username) && user.getPassword().equals(password)){
                return user;
            }
        }
    
        return null;
    }
    
    public User find(String username){
        List<User> list = MyDb.getAll();
        for(User user : list){
            if(user.getUsername().equals(username)){
                return user;
            }
        }
        return null;
    }
}

模擬一個(gè)數(shù)據(jù)庫:MyDb.java

package cn.itcast.db;
import java.util.ArrayList;
import java.util.List;
import cn.itcast.domain.User;

public class MyDb {
    private static List list = new ArrayList();
    
    static {
        list.add(new User("aaa","111"));
        list.add(new User("bbb","222"));
        list.add(new User("ccc","333"));
    }
    public static List getAll(){
        return list;
    }
}

實(shí)體類:User.java

package cn.itcast.domain;
public class User {
    private String username ;
    private String password ;
    
    public User() {
    }
    public User(String username, String password) {
        super();
        this.username = username;
        this.password = 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;
    }
}

工具類:WebUtils.java

package cn.itcast.utils;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import sun.misc.BASE64Encoder;

public class WebUtils {
    public static String md5(String message){
        
        try {
            MessageDigest md = MessageDigest.getInstance("md5");
            byte result[] = md.digest(message.getBytes());
            
            BASE64Encoder encoder = new BASE64Encoder();
            return encoder.encode(result);
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }   
    }
}

界面:login.jsp

<form action="${pageContext.request.contextPath }/servlet/LoginServlet" method="post">
        用戶名:<input type="text" name="username"><br/>
        密碼:<input type="password" name="password"><br/>
        有效期:
            <input type="radio" name="logintime" value="3600">1小時(shí)
            <input type="radio" name="logintime" value="${10*60}">10分鐘
            <input type="radio" name="logintime" value="${5*60}">5分鐘
            <br/>
        <input type="submit" value="登錄">
    </form>

index.jsp

歡迎你:${user.username }登錄

全局消息顯示頁面:message.jsp

${message}

說明:

  • 試驗(yàn)的時(shí)候我們先訪問login.jsp進(jìn)行登錄,此時(shí)請(qǐng)求經(jīng)過filter時(shí)沒有經(jīng)過任何處理就直接到達(dá)了servlet,servlet將提交過的用戶名和密碼和數(shù)據(jù)庫中數(shù)據(jù)進(jìn)行對(duì)比,如果有此用戶則將此用戶存入session,就表示此用戶已經(jīng)登錄了。

  • 然后再訪問index.jsp,此時(shí)經(jīng)過filter的時(shí)候filter發(fā)現(xiàn)session中已經(jīng)有此用戶,則直接提交給servlet。

  • 上面是在一次會(huì)話中進(jìn)行的試驗(yàn),此時(shí)我們將瀏覽器關(guān)閉,再次訪問index.jsp,此時(shí)請(qǐng)求經(jīng)過過濾器時(shí),過濾器會(huì)發(fā)現(xiàn)cookie中存在一個(gè)autologin的標(biāo)記,則讓此用戶自動(dòng)登錄。這是因?yàn)橛脩舻谝淮蔚卿浀臅r(shí)候我們的servlet會(huì)向cookie中存入一個(gè)autologin的標(biāo)記,只要我們下次登錄在我們?cè)O(shè)置的緩存保存時(shí)間之內(nèi)就會(huì)自動(dòng)登錄。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 本文包括:1、Filter簡(jiǎn)介2、Filter是如何實(shí)現(xiàn)攔截的?3、Filter開發(fā)入門4、Filter的生命周期...
    廖少少閱讀 7,512評(píng)論 3 56
  • 從三月份找實(shí)習(xí)到現(xiàn)在,面了一些公司,掛了不少,但最終還是拿到小米、百度、阿里、京東、新浪、CVTE、樂視家的研發(fā)崗...
    時(shí)芥藍(lán)閱讀 42,787評(píng)論 11 349
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,534評(píng)論 19 139
  • 這部分主要是與Java Web和Web Service相關(guān)的面試題。 96、闡述Servlet和CGI的區(qū)別? 答...
    雜貨鋪老板閱讀 1,501評(píng)論 0 10
  • 盛夏的午后,喝了點(diǎn)酒,我又精分了。一個(gè)人打開酷我,自唱自嗨。當(dāng)大腦中感性的小人打敗了理性的小人的時(shí)候,我變開始犯病...
    王家小易閱讀 433評(píng)論 0 1

友情鏈接更多精彩內(nèi)容