日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

SpringMVC源码阅读:过滤器

發(fā)布時(shí)間:2025/7/14 66 豆豆
生活随笔 收集整理的這篇文章主要介紹了 SpringMVC源码阅读:过滤器 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

SpringMVC源碼閱讀:過(guò)濾器

目錄

  • 1.前言
  • 2.源碼分析
  • 3.自定義過(guò)濾器
    • 3.1 自定義過(guò)濾器繼承OncePerRequestFilter
    • 3.2 自定義過(guò)濾器實(shí)現(xiàn)Filter接口
  • 4.過(guò)濾器(Filter)和攔截器(Interceptor)的區(qū)別
    • 4.1 過(guò)濾器:
    • 4.2 攔截器:
  • 5.總結(jié):
  • 6.參考

?

正文

回到頂部

1.前言

SpringMVC是目前J2EE平臺(tái)的主流Web框架,不熟悉的園友可以看SpringMVC源碼閱讀入門,它交代了SpringMVC的基礎(chǔ)知識(shí)和源碼閱讀的技巧

本文將通過(guò)源碼(基于Spring4.3.7)分析,弄清楚SpringMVC過(guò)濾器是如何執(zhí)行的,并自定義過(guò)濾器,分清楚過(guò)濾器和攔截器的區(qū)別

回到頂部

2.源碼分析

web.xml配置

<filter><!--過(guò)濾器名稱--><filter-name>Set Character Encoding</filter-name><!--過(guò)濾器處理類--><filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class><!--初始化參數(shù)--><init-param><param-name>encoding</param-name><param-value>UTF-8</param-value></init-param><init-param><param-name>forceEncoding</param-name><param-value>true</param-value></init-param></filter><filter-mapping><filter-name>Set Character Encoding</filter-name><!--攔截路徑--><url-pattern>/*</url-pattern></filter-mapping>

打開(kāi)CharacterEncoding類,該類為request設(shè)置字符編碼,打開(kāi)類繼承圖

CharacterEncodingFilter重寫父類OncePerRequestFilter的doFilterInterval方法

forceRequestEncoding為True

188行獲取編碼

191行為request設(shè)置編碼

194行為response設(shè)置編碼

197行調(diào)用FilterChain

打開(kāi)CharcterEncodingFilter的父類OncePerRequestFilter,OncePerRequestFilter保證請(qǐng)求分發(fā)執(zhí)行一次Filter

CharcterEncodingFilter實(shí)現(xiàn)Filter接口的doFilter方法,打開(kāi)之

96行獲取屬性,該屬性表明這個(gè)方法是否被過(guò)濾

98行hasAlreadyFilteredAttribute表明這個(gè)方法是否被過(guò)濾;skipDispatch方法判斷是否跳過(guò)分發(fā);shouldNotFilter方法默認(rèn)返回False,被子類重寫,然而,CharacterEncodingFilter類并未重寫,ForwardedHeaderFilter重寫該方法,暫時(shí)不看

101行直接調(diào)用FilterChain的doFilter方法,FilterChain部分

98行的上述條件都不滿足,則進(jìn)入105行,為request設(shè)置“已過(guò)濾”標(biāo)識(shí)

107行調(diào)用子類CharacterEncodingFilter的doFilterInterval方法

繼續(xù)深入,打開(kāi)OncePerRequestFilter類的父類GenericFilterBean類

重點(diǎn)看init方法,該方法啟動(dòng)服務(wù)才會(huì)進(jìn)入,主要負(fù)責(zé)獲取web.xml里配置的參數(shù)

?

180行獲取FilterConfig

filterClass和filterName是我們?cè)趙eb.xml配置的屬性

184行獲取<init-param>里屬性

?

185行聲明BeanWrapper,一個(gè)通用的JavaBean接口,封裝了setget方法,在SpringMVC源碼閱讀:屬性編輯器、數(shù)據(jù)綁定我已經(jīng)講過(guò)

186行聲明資源加載器,加載classpath和文件系統(tǒng)

189行給屬性設(shè)置True

199行initFilterBean方法被子類重寫,用于補(bǔ)充初始化方法,OncePerRequestFilter未重寫,我們暫時(shí)不看

回到頂部

3.自定義過(guò)濾器

現(xiàn)在Web項(xiàng)目基本都是前后端分離的,不可避免地要解決跨域問(wèn)題。看Filter接口繼承圖,發(fā)現(xiàn)CorsFilter可以處理跨域,但是并不方便

什么是跨域?

前端地址和后臺(tái)地址的

IP一致,端口不一致

IP不一致,端口不一致

IP不一致,端口一致

都屬于跨域范疇

前端代碼如下

<!DOCTYPE html> <html><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><title></title><!-- <link rel="stylesheet" href=""> --><style></style> </head><body><script></script><script type="text/javascript" src="jquery-3.1.1.min.js"></script><script type="text/javascript">$.ajax({url: "http://localhost:8080/springmvcdemo/employee/detail/8",data: {},success: function (data) {console.log(html)},dataType: "json"});</script></body></html>

將前端代碼地址設(shè)置為http://localhost:1234,VSCode可以做,不贅述。后臺(tái)代碼地址http://localhost:8080,因?yàn)槎丝诓灰恢?#xff0c;形成了跨域,不做跨域處理,直接訪問(wèn)有如下效果

現(xiàn)在我們來(lái)自定義過(guò)濾器解決跨域問(wèn)題

3.1 自定義過(guò)濾器繼承OncePerRequestFilter

web.xml

<filter><!--過(guò)濾器名稱--><filter-name>CorsFilter</filter-name><!--過(guò)濾器處理類--><filter-class>org.format.demo.custom.ExtendedCorsFilter</filter-class></filter><filter-mapping><filter-name>CorsFilter</filter-name><!--攔截路徑--><url-pattern>/*</url-pattern></filter-mapping>

ExtendedCorsFilter.java,重寫doFilterInterval方法

public class ExtendedCorsFilter extends OncePerRequestFilter{@Overrideprotected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {response.addHeader("Access-Control-Allow-Origin", "*");response.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");response.addHeader("Access-Control-Allow-Headers", "Content-Type");filterChain.doFilter(request,response);}}

此時(shí)再運(yùn)行前端代碼,已經(jīng)成功請(qǐng)求到結(jié)果

Headers設(shè)置成功

3.2 自定義過(guò)濾器實(shí)現(xiàn)Filter接口

web.xml配置如下

<filter><!--過(guò)濾器名稱--><filter-name>CorsFilter</filter-name><!--過(guò)濾器處理類--><filter-class>org.format.demo.custom.ImplementedCorsFilter</filter-class><!--初始化參數(shù)--><init-param><param-name>allowedOrigins</param-name><param-value>*</param-value></init-param><init-param><param-name>allowedMethods</param-name><param-value>*</param-value></init-param><init-param><param-name>allowedHeaders</param-name><param-value>*</param-value></init-param></filter>

?

ImplementedCorsFilter.java

public class ImplementedCorsFilter implements Filter{//允許的請(qǐng)求域private String allowedOrigins;//允許的請(qǐng)求方法private String allowedMethods;//允許的請(qǐng)求頭private String allowedHeaders;@Overridepublic void init(FilterConfig filterConfig) throws ServletException {this.allowedOrigins = filterConfig.getInitParameter("allowedOrigins");this.allowedMethods = filterConfig.getInitParameter("allowedMethods");this.allowedHeaders = filterConfig.getInitParameter("allowedHeaders");}@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {HttpServletResponse rsp = (HttpServletResponse) response;rsp.setHeader("Access-Control-Allow-Origin", allowedOrigins);rsp.setHeader("Access-Control-Allow-Methods", allowedMethods);rsp.setHeader("Access-Control-Allow-Headers", allowedHeaders);chain.doFilter(request, response);}@Overridepublic void destroy() {} }

相比繼承OncePerRequestFilter方法,實(shí)現(xiàn)Filter接口可以通過(guò)重寫init方法獲取web.xml屬性值,效果一致

回到頂部

4.過(guò)濾器(Filter)和攔截器(Interceptor)的區(qū)別

我在SpringMVC源碼閱讀:攔截器詳細(xì)講解了SpringMVC攔截器的工作原理

過(guò)濾器先于攔截器執(zhí)行,后于攔截器執(zhí)行結(jié)束

4.1 過(guò)濾器:

  依賴于servlet容器。在實(shí)現(xiàn)上基于函數(shù)回調(diào),可以對(duì)幾乎所有請(qǐng)求進(jìn)行過(guò)濾,但是缺點(diǎn)是一個(gè)過(guò)濾器實(shí)例只能在容器初始化時(shí)調(diào)用一次。使用過(guò)濾器的目的是用來(lái)做一些過(guò)濾操作,獲取我們想要獲取的數(shù)據(jù).

  比如:在過(guò)濾器中修改字符編碼;在過(guò)濾器中修改HttpServletRequest的一些參數(shù),包括:過(guò)濾低俗文字、危險(xiǎn)字符等

4.2 攔截器:

  依賴于web框架,在SpringMVC中就是依賴于SpringMVC框架。在實(shí)現(xiàn)上基于Java的反射機(jī)制,屬于面向切面編程(AOP)的一種運(yùn)用。由于攔截器是基于Web框架的調(diào)用。

  因此可以使用spring的依賴注入(DI)進(jìn)行一些業(yè)務(wù)操作,同時(shí)一個(gè)攔截器實(shí)例在一個(gè)controller生命周期之內(nèi)可以多次調(diào)用。但是缺點(diǎn)是只能對(duì)controller請(qǐng)求進(jìn)行攔截,對(duì)其他的一些比如直接訪問(wèn)靜態(tài)資源的請(qǐng)求則沒(méi)辦法進(jìn)行攔截處理。

總結(jié):業(yè)務(wù)中盡量使用基于方法的攔截器,在進(jìn)行一些需要統(tǒng)一處理的業(yè)務(wù)可以使用基于Servlet的過(guò)濾器

回到頂部

5.總結(jié):

Filter接口用來(lái)執(zhí)行過(guò)濾任務(wù)

CompositeFilter實(shí)現(xiàn)filter,用到了組合設(shè)計(jì)模式

抽象類GenericFilterBean實(shí)現(xiàn)Filter接口,負(fù)責(zé)解析web.xml的Filter的init-param中參數(shù),是所有過(guò)濾器的父類。init方法解析web.xml的參數(shù)

抽象類OncePerRequestFilter繼承GenericFilterBean,doFilter方法根據(jù)hasAlreadyFilteredAttribute判斷是否執(zhí)行過(guò)濾

CharacterEncodingFilter重寫父類OncePerRequestFilter的doFilterInterval方法,調(diào)用FilterChain的doDilter方法執(zhí)行過(guò)濾邏輯

其他過(guò)濾器園友可以自行查看,不再贅述,demo源碼

回到頂部

6.參考

https://docs.spring.io/spring/docs/4.3.7.RELEASE/spring-framework-reference/htmlsingle/#beans-beans-conversion

https://docs.spring.io/spring/docs/current/javadoc-api/

https://github.com/spring-projects/spring-framework

文中難免有不足,歡迎指正

原文地址https://www.cnblogs.com/Java-Starter/p/10444617.html

總結(jié)

以上是生活随笔為你收集整理的SpringMVC源码阅读:过滤器的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。