欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

JavaWeb三大組件之一的Filter詳解

 更新時(shí)間:2022年06月18日 10:33:25   作者:蘇瞳吶  
本篇文章主要介紹了JavaWeb三大組件之中的Filter過(guò)濾器詳解,實(shí)例分析了JavaWeb之Filter過(guò)濾器的使用技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下

1. 概念

Filter過(guò)濾器是JavaWeb的三大組件之一。三大組件:Servlet,Listener,F(xiàn)ilter

Filter過(guò)濾器是JavaEE的規(guī)范,即接口

作用:攔截請(qǐng)求,過(guò)濾響應(yīng)

攔截請(qǐng)求常見(jiàn)的應(yīng)用場(chǎng)景:

  • 權(quán)限檢查
  • 日記操作
  • 事務(wù)管理…

2. 基本使用

例子:要求在你的web工程下,有一個(gè)admin目錄,這個(gè)目錄下的所有資源(html,jpg,jsp等)都必須是用戶登錄之后才允許訪問(wèn)。

  • 根據(jù)之前我們學(xué)的,用戶登陸后我們把用戶信息保存到Session域中,所以我們判斷Session中是否包含有用戶信息即可,但這種方案只能用在jsp頁(yè)面中
  • 使用Filter,可以使用在任何資源上(Filter在獲取目標(biāo)資源前執(zhí)行)

使用:

寫(xiě)個(gè)類(lèi)去實(shí)現(xiàn)Filter接口

// 先寫(xiě)個(gè)類(lèi)去實(shí)現(xiàn)javax.servlet.Filter
public class AdminFilter implements Filter {
    // 這個(gè)方法重要,主要用于攔截請(qǐng)求??!(權(quán)限檢查)
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
                         FilterChain filterChain) throws IOException, ServletException 
    {
        HttpServletRequest req = (HttpServletRequest) servletRequest; // 要強(qiáng)轉(zhuǎn)一下,才能獲取Session
        HttpServletResponse resp = (HttpServletResponse) servletResponse;

        HttpSession session = req.getSession();  // 獲取Session
        Object user = session.getAttribute("user");
        if (user == null) {
            req.getRequestDispatcher("/login.jsp").forward(req, resp); //沒(méi)登錄轉(zhuǎn)發(fā)到登陸頁(yè)面
            return;
        } else {
            // 如果已經(jīng)登錄,如果有下一個(gè)Filter則進(jìn)入,沒(méi)有則放行,去訪問(wèn)用戶請(qǐng)求的資源!(沒(méi)有這行是不行的)
            filterChain.doFilter(req, resp); 
        }
    }
    // 下面兩個(gè)可以空實(shí)現(xiàn)
    @Override
    public void init(FilterConfig filterConfig) throws ServletException { }
    @Override
    public void destroy() { }
}

xml配置過(guò)濾器(和Servlet差不多)

<!-- 配置過(guò)濾器-->
<filter>
    <filter-name>AdminFilter</filter-name>  <!-- 給Filter起一個(gè)名稱(chēng)-->
    <filter-class>com.sutong.filter.AdminFilter</filter-class>  <!-- 全類(lèi)名-->
</filter>
<filter-mapping>
    <filter-name>AdminFilter</filter-name> <!-- 表示當(dāng)前的攔截路徑給哪個(gè)Filter使用-->
    <!-- 攔截路徑,斜杠表示到工程路徑,映射到web目錄,admin/* 表示admin目錄下全部資源-->
    <url-pattern>/admin/*</url-pattern> 
</filter-mapping>

3. 生命周期

Filter 的方法執(zhí)行順序:

  • 構(gòu)造器 方法
  • init() 初始化方法, 第一二步在web工程啟動(dòng)的時(shí)候已經(jīng)執(zhí)行(即Filter已經(jīng)創(chuàng)建)
  • doFilter(),每次攔截到請(qǐng)求就會(huì)執(zhí)行
  • destroy(),停止web的時(shí)候執(zhí)行

4. FilterConfig類(lèi)

FIlterConfig,F(xiàn)ilter過(guò)濾器的配置文件類(lèi),Tomcat每次創(chuàng)建的Filter的時(shí)候,會(huì)同時(shí)創(chuàng)建一個(gè)FilterConfig類(lèi)。

作用:獲取Filter過(guò)濾器的配置內(nèi)容

  • 獲取Filter的名稱(chēng),即配置文件中filter-name標(biāo)簽里面的內(nèi)容
  • 獲取Filter在web.xml中配置的init-param初始化參數(shù) (在filter標(biāo)簽里面配置初始化參數(shù),和Servlet一樣)
  • 獲取ServletContext對(duì)象
@Override
public void init(FilterConfig filterConfig) throws ServletException {
    String filterName = filterConfig.getFilterName(); // 1
    String value = filterConfig.getInitParameter("key1"); // 2
    ServletContext servletContext = filterConfig.getServletContext(); // 3
}

5. FilterChain類(lèi)

FilterChain 是過(guò)濾器鏈(多個(gè)過(guò)濾器一起工作)

filterChain.doFilter(req, resp) 該方法是作用:

  • 執(zhí)行下一個(gè)Filter(如果有)
  • 執(zhí)行目標(biāo)資源(沒(méi)有了Filter了)

如果驗(yàn)證通過(guò),執(zhí)行完目標(biāo)資源后會(huì)返回 doFilter 方法調(diào)用的地方,繼續(xù)執(zhí)行下面的代碼。

當(dāng)多個(gè)過(guò)濾器時(shí),攔截同一個(gè)文件/目錄時(shí),F(xiàn)ilter 配置文件的順序(即web.xml中的配置順序)決定了每 Filter 的執(zhí)行順序,配置在前先執(zhí)行。

當(dāng)多個(gè)過(guò)濾器的特點(diǎn):?

  • 所有的 Filter 和目標(biāo)資源默認(rèn)都執(zhí)行在同一個(gè)線程中
  • 多個(gè) Filter 共同執(zhí)行的時(shí)候他們都使用一個(gè) Request 對(duì)象

6. 攔截路徑

精確匹配

<url-pattern>/target.jsp</url-pattern> --> http://ip:port/工程路徑/target.jsp

目錄匹配

<url-pattern>/admin/*</url-pattern> -> http://ip:port/工程路徑/admin/*

后綴名匹配

<url-pattern>*.html</url-pattern> -> 表示要攔截的地址必須以 .html結(jié)尾

這個(gè)后綴名不一定是現(xiàn)有文件的后綴名,是個(gè)字符串就行 *.abc 也行。注意不是以斜杠開(kāi)頭

Filter只關(guān)系請(qǐng)求的地址是否匹配,不關(guān)心資源是否存在。

7. ThreadLocal+Filter管理事務(wù)

7.1 ThreadLocal

ThreadLocal是jdk1.2開(kāi)始的,作用:可以解決多線程的數(shù)據(jù)安全問(wèn)題

ThreadLocal可以給當(dāng)前線程關(guān)聯(lián)一個(gè)數(shù)據(jù)(可以是普通變量,對(duì)象,集合等)

(可以簡(jiǎn)單理解為,像Map一樣,當(dāng)前線程名為key,關(guān)聯(lián)的數(shù)據(jù)為value)

如果想要給當(dāng)前線程關(guān)聯(lián)多個(gè)數(shù)據(jù)則需要多個(gè)ThreadLocal實(shí)例,ThreadLocal實(shí)例一般都是 static 類(lèi)型,其中保存的數(shù)據(jù)在線程銷(xiāo)毀后由JVM虛擬機(jī)自動(dòng)釋放。

// Hashtable線程安全
public static Map<String, Object> map = new Hashtable<>(); 
// ThreadLocal泛型就是關(guān)聯(lián)數(shù)據(jù)的類(lèi)型,類(lèi)似:Map中V的類(lèi)型,K是當(dāng)前線程
// 只能關(guān)聯(lián)一個(gè)數(shù)據(jù),多個(gè)則需new多個(gè)
public static ThreadLocal<Object> threadLocal = new ThreadLocal<>(); 
// 使用
public void test() {
    map.put(Thread.currentThread().getName(), "Map存數(shù)據(jù)");
    threadLocal.set("ThreadLocal存數(shù)據(jù)");
    // 取數(shù)據(jù)
    Object obj1 = map.get(Thread.currentThread().getName());
    Object obj2 = threadLocal.get();
}

7.2 MySQL事務(wù)前提

我們?cè)赽ook項(xiàng)目的時(shí)候,如果生成訂單后發(fā)生錯(cuò)誤,則生成訂單成功而訂單詳情生成失敗,這是嚴(yán)重錯(cuò)誤的,所以我們要使用事務(wù)確保這些操作在一個(gè)事務(wù)內(nèi)。

而確保在一個(gè)事務(wù)的前期是 使用同一個(gè) Connection 連接對(duì)象! 這里就可以用 ThreadLocal 了,把Connection 存到ThreadLocal 中,確保多個(gè)Service使用的是同一個(gè)連接對(duì)象。

而使用 ThreadLocal 關(guān)聯(lián)數(shù)據(jù)要確保上面這些操作在一個(gè)線程中執(zhí)行! (經(jīng)過(guò)驗(yàn)證我們book中生成訂單操作都是在一個(gè)線程下的)

String orderId = null;
try {
    orderId = orderService.createOrder(cart, loginUser.getId());
    JdbcUtils.commitAndClose();    // 生成訂單,沒(méi)異常提交事務(wù)關(guān)閉連接
} catch (Exception e) {
	JdbcUtils.rollbackAndClose();  // 有異常回滾,關(guān)閉連接 !!
}
// 但這樣做每個(gè)xxxService.xxx() 都要進(jìn)行try catch,太麻煩了,可以使用Filter,看下面

7.3 Filter統(tǒng)一管理

使用Filter統(tǒng)一給所有的 Service 方法都加上 try-catch,來(lái)實(shí)現(xiàn)管理!!

所有的異常都要拋給 Filter,不要私自處理異常

TransactionFilter.java :

public class TransactionFilter implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, 
                         FilterChain filterChain) {
        try {
            // 下面這行相當(dāng)于調(diào)用xxxService.xxx()方法,
            // 所以我們對(duì)這行進(jìn)行try-catch就行了(即給所有的Servlet中的所以方法進(jìn)行了try-catch)
            filterChain.doFilter(servletRequest, servletResponse);
            JdbcUtils.commitAndClose();   // 沒(méi)異常提交事務(wù),關(guān)閉連接
        } catch (Exception e) {
            JdbcUtils.rollbackAndClose();  // 有異?;貪L,關(guān)閉連接
            e.printStackTrace();           // 可以不打印,打印可以讓我們開(kāi)到什么錯(cuò)誤
            throw new RuntimeException(e); // 再把錯(cuò)誤拋給Tomcat去顯示我們準(zhǔn)備的錯(cuò)誤頁(yè)面!!?。。。?
            // (如果有異常了,用戶頁(yè)面則會(huì)一頁(yè)空白,我們要給用戶一點(diǎn)友好的提示!可以交給Tomcat展示友好的錯(cuò)誤頁(yè)面信息)
        }
    }
    @Override
    public void init(FilterConfig filterConfig) throws ServletException { }
    @Override
    public void destroy() { }
}

web.xml

<filter>
    <filter-name>TransactionFilter</filter-name>
    <filter-class>com.sutong.filter.TransactionFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>TransactionFilter</filter-name>
    <url-pattern>/*</url-pattern>  <!-- /* 代表當(dāng)前工程的所有請(qǐng)求,相當(dāng)于對(duì)工程下的所有請(qǐng)求進(jìn)行了try-catch-->
</filter-mapping>

7.4 錯(cuò)誤信息展示

TransactionFilter.java

try {
    filterChain.doFilter(servletRequest, servletResponse);
    JdbcUtils.commitAndClose(); 
} catch (Exception e) {
    JdbcUtils.rollbackAndClose();       
    throw new RuntimeException(e); // 再把錯(cuò)誤拋給Tomcat去顯示我們準(zhǔn)備的錯(cuò)誤頁(yè)面!?。。。?!
    // (如果有異常了,用戶頁(yè)面則會(huì)一頁(yè)空白,我們要給用戶一點(diǎn)友好的提示!可以交給Tomcat展示友好的錯(cuò)誤頁(yè)面信息)
}

web.xml配置

<!-- error-page配置服務(wù)器出錯(cuò)后,自動(dòng)跳轉(zhuǎn)的頁(yè)面-->
<error-page>
    <error-code>500</error-code> <!-- 錯(cuò)誤類(lèi)型-->
    <location>/pages/error/error500.jsp</location> <!-- 要跳轉(zhuǎn)去的頁(yè)面路徑-->
</error-page>
<error-page>
    <error-code>404</error-code> 
    <location>/pages/error/error404.jsp</location> 
</error-page>

到此這篇關(guān)于JavaWeb三大組件之一的Filter詳解的文章就介紹到這了,更多相關(guān)JavaWeb Filter內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java Socket實(shí)現(xiàn)猜數(shù)字小游戲

    Java Socket實(shí)現(xiàn)猜數(shù)字小游戲

    這篇文章主要為大家詳細(xì)介紹了Java Socket實(shí)現(xiàn)猜數(shù)字小游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-09-09
  • Java String 拼接字符串原理詳解

    Java String 拼接字符串原理詳解

    在本篇文章里小編給大家分享的是關(guān)于Java String 拼接字符串原理詳解的相關(guān)資源內(nèi)容,有需要的朋友們可以跟著學(xué)習(xí)參考下。
    2020-02-02
  • Java中關(guān)于字符串的編碼方式

    Java中關(guān)于字符串的編碼方式

    這篇文章主要介紹了Java中關(guān)于字符串的編碼方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-06-06
  • 使用jekins自動(dòng)構(gòu)建部署java maven項(xiàng)目的方法步驟

    使用jekins自動(dòng)構(gòu)建部署java maven項(xiàng)目的方法步驟

    這篇文章主要介紹了使用jekins自動(dòng)構(gòu)建部署java maven項(xiàng)目的方法步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-01-01
  • Mybatis通過(guò)Spring完成代理類(lèi)注入的流程分析

    Mybatis通過(guò)Spring完成代理類(lèi)注入的流程分析

    這篇文章主要介紹了Mybatis通過(guò)Spring完成代理類(lèi)注入的流程分析,本文通過(guò)實(shí)例圖文相結(jié)合給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-08-08
  • java Date獲取年月日時(shí)分秒的實(shí)現(xiàn)方法

    java Date獲取年月日時(shí)分秒的實(shí)現(xiàn)方法

    下面小編就為大家?guī)?lái)一篇java Date獲取年月日時(shí)分秒的實(shí)現(xiàn)方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2016-06-06
  • Spring MVC利用Swagger2如何構(gòu)建動(dòng)態(tài)RESTful API詳解

    Spring MVC利用Swagger2如何構(gòu)建動(dòng)態(tài)RESTful API詳解

    這篇文章主要給大家介紹了關(guān)于在Spring MVC中利用Swagger2如何構(gòu)建動(dòng)態(tài)RESTful API的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。
    2017-10-10
  • 圖解Java經(jīng)典算法快速排序的原理與實(shí)現(xiàn)

    圖解Java經(jīng)典算法快速排序的原理與實(shí)現(xiàn)

    快速排序是基于二分的思想,對(duì)冒泡排序的一種改進(jìn)。主要思想是確立一個(gè)基數(shù),將小于基數(shù)的數(shù)放到基數(shù)左邊,大于基數(shù)的數(shù)字放到基數(shù)的右邊,然后在對(duì)這兩部分進(jìn)一步排序,從而實(shí)現(xiàn)對(duì)數(shù)組的排序
    2022-09-09
  • Java實(shí)現(xiàn)圖片對(duì)比功能

    Java實(shí)現(xiàn)圖片對(duì)比功能

    個(gè)人從來(lái)沒(méi)有研究過(guò)圖像學(xué),也沒(méi)看過(guò)什么論文或者相關(guān)文檔,寫(xiě)這個(gè)完全是靠google和百度,自己寫(xiě)了個(gè)實(shí)驗(yàn)了下,測(cè)試用例也少,估計(jì)有大BUG的存在,所以看的人權(quán)當(dāng)學(xué)習(xí)交流,切勿生產(chǎn)使用。
    2014-09-09
  • 淺談Mybatis SqlSession執(zhí)行流程

    淺談Mybatis SqlSession執(zhí)行流程

    本文主要介紹了淺談Mybatis SqlSession執(zhí)行流程,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-07-07

最新評(píng)論