国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

過(guò)濾器入門看這一篇就夠了

yy13818512006 / 3337人閱讀

摘要:我們很容易發(fā)現(xiàn),過(guò)濾器可以比喻成一張濾網(wǎng)。這究竟是怎么回事啊我們可以這樣理解過(guò)濾器不單單只有一個(gè),那么我們?cè)趺垂芾磉@些過(guò)濾器呢在中就使用了鏈?zhǔn)浇Y(jié)構(gòu)。第一種方式在文件中配置用于注冊(cè)過(guò)濾器用于為過(guò)濾器指定一個(gè)名字,該元素的內(nèi)容不能為空。

什么是過(guò)濾器

過(guò)濾器是Servlet的高級(jí)特性之一,也別把它想得那么高深,只不過(guò)是實(shí)現(xiàn)Filter接口的Java類罷了!

首先,我們來(lái)看看過(guò)濾器究竟Web容器的哪處:

從上面的圖我們可以發(fā)現(xiàn),當(dāng)瀏覽器發(fā)送請(qǐng)求給服務(wù)器的時(shí)候,先執(zhí)行過(guò)濾器,然后才訪問(wèn)Web的資源。服務(wù)器響應(yīng)Response,從Web資源抵達(dá)瀏覽器之前,也會(huì)途徑過(guò)濾器。。

我們很容易發(fā)現(xiàn),過(guò)濾器可以比喻成一張濾網(wǎng)。我們想想現(xiàn)實(shí)中的濾網(wǎng)可以做什么:在泡茶的時(shí)候,過(guò)濾掉茶葉。那濾網(wǎng)是怎么過(guò)濾茶葉的呢?規(guī)定大小的網(wǎng)孔,只要網(wǎng)孔比茶葉小,就可以實(shí)現(xiàn)過(guò)濾了!

引申在Web容器中,過(guò)濾器可以做:過(guò)濾一些敏感的字符串【規(guī)定不能出現(xiàn)敏感字符串】、避免中文亂碼【規(guī)定Web資源都使用UTF-8編碼】、權(quán)限驗(yàn)證【規(guī)定只有帶Session或Cookie的瀏覽器,才能訪問(wèn)web資源】等等等,過(guò)濾器的作用非常大,只要發(fā)揮想象就可以有意想不到的效果

也就是說(shuō):當(dāng)需要限制用戶訪問(wèn)某些資源時(shí)、在處理請(qǐng)求時(shí)提前處理某些資源、服務(wù)器響應(yīng)的內(nèi)容對(duì)其進(jìn)行處理再返回、我們就是用過(guò)濾器來(lái)完成的!

為什么需要用到過(guò)濾器

直接舉例子來(lái)說(shuō)明吧:

沒(méi)有過(guò)濾器解決中文亂碼問(wèn)題

如果我沒(méi)有用到過(guò)濾器:瀏覽器通過(guò)http請(qǐng)求發(fā)送數(shù)據(jù)給Servlet,如果存在中文,就必須指定編碼,否則就會(huì)亂碼!

jsp頁(yè)面提交中文數(shù)據(jù)給Servlet處理

Servlet沒(méi)有指定編碼的情況下,獲取得到的是亂碼

Servlet中如何解決中文亂碼問(wèn)題,我的其他博文中有:http://blog.csdn.net/hon_3y/article/details/54632004

也就是說(shuō):如果我每次接受客戶端帶過(guò)來(lái)的中文數(shù)據(jù),在Serlvet中都要設(shè)定編碼。這樣代碼的重復(fù)率太高了!!!!

有過(guò)濾器解決中文亂碼問(wèn)題

有過(guò)濾器的情況就不一樣了:只要我在過(guò)濾器中指定了編碼,可以使全站的Web資源都是使用該編碼,并且重用性是非常理想的!

過(guò)濾器 API

只要Java類實(shí)現(xiàn)了Filter接口就可以稱為過(guò)濾器!Filter接口的方法也十分簡(jiǎn)單:

其中init()和destory()方法就不用多說(shuō)了,他倆跟Servlet是一樣的。只有在Web服務(wù)器加載和銷毀的時(shí)候被執(zhí)行,只會(huì)被執(zhí)行一次!

值得注意的是doFilter()方法,它有三個(gè)參數(shù)(ServletRequest,ServletResponse,FilterChain),從前兩個(gè)參數(shù)我們可以發(fā)現(xiàn):過(guò)濾器可以完成任何協(xié)議的過(guò)濾操作

那FilterChain是什么東西呢?我們看看:

FilterChain是一個(gè)接口,里面又定義了doFilter()方法。這究竟是怎么回事啊??????

我們可以這樣理解:過(guò)濾器不單單只有一個(gè),那么我們?cè)趺垂芾磉@些過(guò)濾器呢?在Java中就使用了鏈?zhǔn)浇Y(jié)構(gòu)把所有的過(guò)濾器都放在FilterChain里邊,如果符合條件,就執(zhí)行下一個(gè)過(guò)濾器(如果沒(méi)有過(guò)濾器了,就執(zhí)行目標(biāo)資源)

上面的話好像有點(diǎn)拗口,我們可以想象生活的例子:現(xiàn)在我想在茶杯上能過(guò)濾出石頭和茶葉出來(lái)。石頭在一層,茶葉在一層。所以茶杯的過(guò)濾裝置應(yīng)該有兩層濾網(wǎng)。這個(gè)過(guò)濾裝置就是FilterChain,過(guò)濾石頭的濾網(wǎng)和過(guò)濾茶葉的濾網(wǎng)就是Filter。在石頭濾網(wǎng)中,茶葉是屬于下一層的,就把茶葉放行,讓茶葉的濾網(wǎng)過(guò)濾茶葉。過(guò)濾完茶葉了,剩下的就是茶(茶就可以比喻成我們的目標(biāo)資源)

快速入門 寫一個(gè)簡(jiǎn)單的過(guò)濾器

實(shí)現(xiàn)Filter接口的Java類就被稱作為過(guò)濾器

    public class FilterDemo1 implements Filter {
        public void destroy() {
        }
    
        public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
    
            //執(zhí)行這一句,說(shuō)明放行(讓下一個(gè)過(guò)濾器執(zhí)行,如果沒(méi)有過(guò)濾器了,就執(zhí)行執(zhí)行目標(biāo)資源)
            chain.doFilter(req, resp);
        }
    
        public void init(FilterConfig config) throws ServletException {
            
        }
    }
filter部署

過(guò)濾器和Servlet是一樣的,需要部署到Web服務(wù)器上的。

第一種方式:在web.xml文件中配置 filter

用于注冊(cè)過(guò)濾器

    
              FilterDemo1
             FilterDemo1
             
             word_file    
             /WEB-INF/word.txt
             
    

用于為過(guò)濾器指定一個(gè)名字,該元素的內(nèi)容不能為空。

元素用于指定過(guò)濾器的完整的限定類名

元素用于為過(guò)濾器指定初始化參數(shù),它的子元素指定參數(shù)的名字,指定參數(shù)的值。在過(guò)濾器中,可以使用FilterConfig接口對(duì)象來(lái)訪問(wèn)初始化參數(shù)

filter-mapping

元素用于設(shè)置一個(gè)Filter 所負(fù)責(zé)攔截的資源

一個(gè)Filter攔截的資源可通過(guò)兩種方式來(lái)指定:Servlet 名稱和資源訪問(wèn)的請(qǐng)求路徑


    
        FilterDemo1
        /*
    

子元素用于設(shè)置filter的注冊(cè)名稱。該值必須是在元素中聲明過(guò)的過(guò)濾器的名字

設(shè)置 filter 所攔截的請(qǐng)求路徑(過(guò)濾器關(guān)聯(lián)的URL樣式)

指定過(guò)濾器所攔截的Servlet名稱

指定過(guò)濾器所攔截的資源被 Servlet 容器調(diào)用的方式,可以是REQUEST,INCLUDE,FORWARD和ERROR之一,默認(rèn)REQUEST。用戶可以設(shè)置多個(gè) 子元素用來(lái)指定 Filter 對(duì)資源的多種調(diào)用方式進(jìn)行攔截。

dispatcher

子元素可以設(shè)置的值及其意義:

REQUEST:當(dāng)用戶直接訪問(wèn)頁(yè)面時(shí),Web容器將會(huì)調(diào)用過(guò)濾器。如果目標(biāo)資源是通過(guò)RequestDispatcher的include()或forward()方法訪問(wèn)時(shí),那么該過(guò)濾器就不會(huì)被調(diào)用。

INCLUDE:如果目標(biāo)資源是通過(guò)RequestDispatcher的include()方法訪問(wèn)時(shí),那么該過(guò)濾器將被調(diào)用。除此之外,該過(guò)濾器不會(huì)被調(diào)用。

FORWARD:如果目標(biāo)資源是通過(guò)RequestDispatcher的forward()方法訪問(wèn)時(shí),那么該過(guò)濾器將被調(diào)用,除此之外,該過(guò)濾器不會(huì)被調(diào)用。

ERROR:如果目標(biāo)資源是通過(guò)聲明式異常處理機(jī)制調(diào)用時(shí),那么該過(guò)濾器將被調(diào)用。除此之外,過(guò)濾器不會(huì)被調(diào)用。

第二種方式:通過(guò)注解配置

    @WebFilter(filterName = "FilterDemo1",urlPatterns = "/*")

上面的配置是“/*”,所有的Web資源都需要途徑過(guò)濾器

如果想要部分的Web資源進(jìn)行過(guò)濾器過(guò)濾則需要指定Web資源的名稱即可!

過(guò)濾器的執(zhí)行順序

上面已經(jīng)說(shuō)過(guò)了,過(guò)濾器的doFilter()方法是極其重要的,FilterChain接口是代表著所有的Filter,F(xiàn)ilterChain中的doFilter()方法決定著是否放行下一個(gè)過(guò)濾器執(zhí)行(如果沒(méi)有過(guò)濾器了,就執(zhí)行目標(biāo)資源)

測(cè)試一

首先在過(guò)濾器的doFilter()中輸出一句話,并且調(diào)用chain對(duì)象的doFilter()方法

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {

        System.out.println("我是過(guò)濾器1");

        //執(zhí)行這一句,說(shuō)明放行(讓下一個(gè)過(guò)濾器執(zhí)行,或者執(zhí)行目標(biāo)資源)
        chain.doFilter(req, resp);
    }

我們來(lái)訪問(wèn)一下test.jsp頁(yè)面:

我們發(fā)現(xiàn)test.jsp(我們的目標(biāo)資源)成功訪問(wèn)到了,并且在服務(wù)器上也打印了字符串!

測(cè)試二

我們來(lái)試試把chain.doFilter(req, resp);這段代碼注釋了看看!

test.jsp頁(yè)面并沒(méi)有任何的輸出(也就是說(shuō),并沒(méi)有訪問(wèn)到j(luò)sp頁(yè)面)。

測(cè)試三

直接看下面的代碼。我們已經(jīng)知道了”準(zhǔn)備放行“會(huì)被打印在控制臺(tái)上和test.jsp頁(yè)面也能被訪問(wèn)得到,但“放行完成“會(huì)不會(huì)打印在控制臺(tái)上呢?

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {

        System.out.println("準(zhǔn)備放行");

        //執(zhí)行這一句,說(shuō)明放行(讓下一個(gè)過(guò)濾器執(zhí)行,或者執(zhí)行目標(biāo)資源)
        chain.doFilter(req, resp);

        System.out.println("放行完成");
    }

答案也非常簡(jiǎn)單,肯定會(huì)打印在控制臺(tái)上的。我們來(lái)看看:

注意,它的完整流程順序是這樣的:客戶端發(fā)送http請(qǐng)求到Web服務(wù)器上,Web服務(wù)器執(zhí)行過(guò)濾器,執(zhí)行到”準(zhǔn)備放行“時(shí),就把字符串輸出到控制臺(tái)上,接著執(zhí)行doFilter()方法,Web服務(wù)器發(fā)現(xiàn)沒(méi)有過(guò)濾器了,就執(zhí)行目標(biāo)資源(也就是test.jsp)。目標(biāo)資源執(zhí)行完后,回到過(guò)濾器上,繼續(xù)執(zhí)行代碼,然后輸出”放行完成“

測(cè)試四

我們?cè)俣嗉右粋€(gè)過(guò)濾器,看看執(zhí)行順序。

過(guò)濾器1

        System.out.println("過(guò)濾器1開(kāi)始執(zhí)行");

        //執(zhí)行這一句,說(shuō)明放行(讓下一個(gè)過(guò)濾器執(zhí)行,或者執(zhí)行目標(biāo)資源)
        chain.doFilter(req, resp);

        System.out.println("過(guò)濾器1開(kāi)始完畢");

過(guò)濾器2

        System.out.println("過(guò)濾器2開(kāi)始執(zhí)行");
        chain.doFilter(req, resp);
        System.out.println("過(guò)濾器2開(kāi)始完畢");

Servlet


        System.out.println("我是Servlet1");

當(dāng)我們?cè)L問(wèn)Servlet1的時(shí)候,看看控制臺(tái)會(huì)出現(xiàn)什么:

執(zhí)行順序是這樣的:先執(zhí)行FilterDemo1,放行,執(zhí)行FilterDemo2,放行,執(zhí)行Servlet1,Servlet1執(zhí)行完回到FilterDemo2上,F(xiàn)ilterDemo2執(zhí)行完畢后,回到FilterDemo1上

注意:過(guò)濾器之間的執(zhí)行順序看在web.xml文件中mapping的先后順序的,如果放在前面就先執(zhí)行,放在后面就后執(zhí)行!如果是通過(guò)注解的方式配置,就比較urlPatterns的字符串優(yōu)先級(jí)

Filter簡(jiǎn)單應(yīng)用

filter的三種典型應(yīng)用:

1、可以在filter中根據(jù)條件決定是否調(diào)用chain.doFilter(request, response)方法,即是否讓目標(biāo)資源執(zhí)行

2、在讓目標(biāo)資源執(zhí)行之前,可以對(duì)requestresponse作預(yù)處理,再讓目標(biāo)資源執(zhí)行

3、在目標(biāo)資源執(zhí)行之后,可以捕獲目標(biāo)資源的執(zhí)行結(jié)果,從而實(shí)現(xiàn)一些特殊的功能

禁止瀏覽器緩存所有動(dòng)態(tài)頁(yè)面
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {

        //讓W(xué)eb資源不緩存,很簡(jiǎn)單,設(shè)置http中response的請(qǐng)求頭即可了!

        //我們使用的是http協(xié)議,ServletResponse并沒(méi)有能夠設(shè)置請(qǐng)求頭的方法,所以要強(qiáng)轉(zhuǎn)成HttpServletRequest

        //一般我們寫Filter都會(huì)把他倆強(qiáng)轉(zhuǎn)成Http類型的
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;

        response.setDateHeader("Expires", -1);
        response.setHeader("Cache-Control", "no-cache");
        response.setHeader("Pragma", "no-cache");

        //放行目標(biāo)資源的response已經(jīng)設(shè)置成不緩存的了
        chain.doFilter(request, response);
    }

沒(méi)有過(guò)濾之前,響應(yīng)頭是這樣的:

過(guò)濾之后,響應(yīng)頭是這樣的:

實(shí)現(xiàn)自動(dòng)登陸 開(kāi)發(fā)實(shí)體、集合模擬數(shù)據(jù)庫(kù)、Dao

實(shí)體:


    private String username ;
    private String password;


    public User() {
    }

    public User(String username, String password) {
        this.username = username;
        this.password = password;
    }

    //各種setter和getter

集合模擬數(shù)據(jù)庫(kù)

    public class UserDB {
    
        private static List users = new ArrayList<>();
    
    
    
        static {
            users.add(new User("aaa", "123"));
            users.add(new User("bbb", "123"));
            users.add(new User("ccc", "123"));
        }
    
        public static List getUsers() {
            return users;
        }
    
        public static void setUsers(List users) {
            UserDB.users = users;
        }
    }

開(kāi)發(fā)dao

    public User find(String username, String password) {

        List userList = UserDB.getUsers();

        //遍歷List集合,看看有沒(méi)有對(duì)應(yīng)的username和password
        for (User user : userList) {
            if (user.getUsername().equals(username) && user.getPassword().equals(password)) {
                return user;
            }
        }
        return null;
    }

登陸界面

用戶名
密碼
10分鐘 30分鐘 1小時(shí)
處理登陸的Servlet
        //得到客戶端發(fā)送過(guò)來(lái)的數(shù)據(jù)
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        
        UserDao userDao = new UserDao();
        User user = userDao.find(username, password);

        if (user == null) {
            request.setAttribute("message", "用戶名或密碼是錯(cuò)的!");
            request.getRequestDispatcher("/message.jsp").forward(request, response);
        }

        //如果不是為空,那么在session中保存一個(gè)屬性
        request.getSession().setAttribute("user", user);
        request.setAttribute("message", "恭喜你,已經(jīng)登陸了!");
        
        //如果想要用戶關(guān)閉了瀏覽器,還能登陸,就必須要用到Cookie技術(shù)了
        Cookie cookie = new Cookie("autoLogin", user.getUsername() + "." + user.getPassword());

        //設(shè)置Cookie的最大聲明周期為用戶指定的
        cookie.setMaxAge(Integer.parseInt(request.getParameter("time")) * 60);
        
        //把Cookie返回給瀏覽器
        response.addCookie(cookie);
        
        //跳轉(zhuǎn)到提示頁(yè)面
        request.getRequestDispatcher("/message.jsp").forward(request, response);
過(guò)濾器
        HttpServletResponse response = (HttpServletResponse) resp;
        HttpServletRequest request = (HttpServletRequest) req;

        //如果用戶沒(méi)有關(guān)閉瀏覽器,就不需要Cookie做拼接登陸了
        if (request.getSession().getAttribute("user") != null) {
            chain.doFilter(request, response);
            return;
        }

        //用戶關(guān)閉了瀏覽器,session的值就獲取不到了。所以要通過(guò)Cookie來(lái)自動(dòng)登陸
        Cookie[] cookies = request.getCookies();
        String value = null;
        for (int i = 0; cookies != null && i < cookies.length; i++) {
            if (cookies[i].getName().equals("autoLogin")) {
                value = cookies[i].getValue();
            }
        }

        //得到Cookie的用戶名和密碼
        if (value != null) {

            String username = value.split(".")[0];
            String password = value.split(".")[1];

            UserDao userDao = new UserDao();
            User user = userDao.find(username, password);

            if (user != null) {
                request.getSession().setAttribute("user", user);
            }
        }
        
        chain.doFilter(request, response);

效果:

改良

我們直接把用戶名和密碼都放在了Cookie中,這是明文的。懂點(diǎn)編程的人就會(huì)知道你的賬號(hào)了。

于是乎,我們要對(duì)密碼進(jìn)行加密!

        Cookie cookie = new Cookie("autoLogin", user.getUsername() + "." + md5.md5(user.getPassword()));

在過(guò)濾器中,加密后的密碼就不是數(shù)據(jù)庫(kù)中的密碼的。所以,我們得在Dao添加一個(gè)功能【根據(jù)用戶名,找到用戶】

    public User find(String username) {
        List userList = UserDB.getUsers();

        //遍歷List集合,看看有沒(méi)有對(duì)應(yīng)的username和password
        for (User user : userList) {
            if (user.getUsername().equals(username)) {
                return user;
            }
        }

        return null;
    }

在過(guò)濾器中,比較Cookie帶過(guò)來(lái)的md5密碼和在數(shù)據(jù)庫(kù)中獲得的密碼(也經(jīng)過(guò)md5)是否相同

        //得到Cookie的用戶名和密碼
        if (value != null) {

            String username = value.split(".")[0];
            String password = value.split(".")[1];

            //在Cookie拿到的密碼是md5加密過(guò)的,不能直接與數(shù)據(jù)庫(kù)中的密碼比較
            UserDao userDao = new UserDao();
            User user = userDao.find(username);

            //通過(guò)用戶名獲得用戶信息,得到用戶的密碼,用戶的密碼也md5一把

            String dbPassword = md5.md5(user.getPassword());
            //如果兩個(gè)密碼匹配了,就是正確的密碼了
            if (password.equals(dbPassword)) {
                request.getSession().setAttribute("user", user);
            }

        }
如果文章有錯(cuò)的地方歡迎指正,大家互相交流。習(xí)慣在微信看技術(shù)文章的同學(xué),可以關(guān)注微信公眾號(hào):Java3y

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/70947.html

相關(guān)文章

  • JSON入門看這一篇夠了

    摘要:采用完全獨(dú)立于任何程序語(yǔ)言的文本格式,使成為理想的數(shù)據(jù)交換語(yǔ)言為什么需要提到,我們就應(yīng)該和來(lái)進(jìn)行對(duì)比。也是一種存儲(chǔ)和交換文本信息的手段。那么好在哪里呢比更小更快,更易解析。使用的時(shí)候,也支持將轉(zhuǎn)成但是,我們不一定使用框架來(lái)做開(kāi)發(fā)呀。 什么是JSON JSON:JavaScript Object Notation 【JavaScript 對(duì)象表示法】 JSON 是存儲(chǔ)和交換文本信息的語(yǔ)法...

    gplane 評(píng)論0 收藏0
  • Scrapy詳解 爬蟲框架入門看這一篇夠了

    摘要:目錄前言架構(gòu)安裝第一個(gè)爬蟲爬取有道翻譯創(chuàng)建項(xiàng)目創(chuàng)建創(chuàng)建解析運(yùn)行爬蟲爬取單詞釋義下載單詞語(yǔ)音文件前言學(xué)習(xí)有一段時(shí)間了,當(dāng)時(shí)想要獲取一下百度漢字的解析,又不想一個(gè)個(gè)漢字去搜,復(fù)制粘貼太費(fèi)勁,考慮到爬蟲的便利性,這篇文章是介紹一個(gè)爬蟲框架, 目錄 前言 架構(gòu) 安裝 第一個(gè)爬蟲:爬取有道翻譯 創(chuàng)建項(xiàng)目 創(chuàng)建Item 創(chuàng)建Spider 解析 運(yùn)行爬蟲-爬取單詞釋義 下載單詞語(yǔ)音文件 ...

    lordharrd 評(píng)論0 收藏0
  • Python字符串的格式化,看這一篇夠了

    摘要:相信很多人在格式化字符串的時(shí)候都用的語(yǔ)法,提出一種更先進(jìn)的格式化方法并成為的標(biāo)準(zhǔn)用來(lái)替換舊的格式化語(yǔ)法,從開(kāi)始已經(jīng)實(shí)現(xiàn)了這一方法其它解釋器未考證。 showImg(https://segmentfault.com/img/remote/1460000018650325); 相信很多人在格式化字符串的時(shí)候都用%s % v的語(yǔ)法,PEP 3101 提出一種更先進(jìn)的格式化方法 str.for...

    BDEEFE 評(píng)論0 收藏0
  • Java3y文章目錄導(dǎo)航

    摘要:前言由于寫的文章已經(jīng)是有點(diǎn)多了,為了自己和大家的檢索方便,于是我就做了這么一個(gè)博客導(dǎo)航。 前言 由于寫的文章已經(jīng)是有點(diǎn)多了,為了自己和大家的檢索方便,于是我就做了這么一個(gè)博客導(dǎo)航。 由于更新比較頻繁,因此隔一段時(shí)間才會(huì)更新目錄導(dǎo)航哦~想要獲取最新原創(chuàng)的技術(shù)文章歡迎關(guān)注我的公眾號(hào):Java3y Java3y文章目錄導(dǎo)航 Java基礎(chǔ) 泛型就這么簡(jiǎn)單 注解就這么簡(jiǎn)單 Druid數(shù)據(jù)庫(kù)連接池...

    KevinYan 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<