在 How Tomcat Works(十四) 中,本人并沒(méi)有對(duì)javax.servlet.Filter及javax.servlet.FilterChain做詳細(xì)的描述,本文在這里做一下補(bǔ)充
FilterChain接口只有一個(gè)方法,方法聲明如下:
public void doFilter ( ServletRequest request, ServletResponse response ) throws IOException, ServletException;
在tomcat中,org.apache.catalina.core.ApplicationFilterChain類實(shí)現(xiàn)了該接口
ApplicationFilterChain類采用一個(gè)私有成員變量private ArrayList filters = new ArrayList()保存ApplicationFilterConfig對(duì)象的集合,ApplicationFilterConfig類實(shí)現(xiàn)了javax.servlet.FilterConfig接口,封裝了對(duì)Filter實(shí)例的管理
下面是向ArrayList filters集合添加ApplicationFilterConfig實(shí)例
void
addFilter(ApplicationFilterConfig filterConfig) {
this
.filters.add(filterConfig);
}
setServlet()方法用于向ApplicationFilterChain對(duì)象設(shè)置當(dāng)前的servlet實(shí)例
void
setServlet(Servlet servlet) {
this
.servlet =
servlet;
}
在ApplicationFilterChain類的實(shí)現(xiàn)FilterChain接口方法doFilter()中,調(diào)用了其私有方法internalDoFilter(),下面是該方法的具體實(shí)現(xiàn)
private
void
internalDoFilter(ServletRequest request, ServletResponse response)
throws
IOException, ServletException {
//
Construct an iterator the first time this method is called
if
(
this
.iterator ==
null
)
this
.iterator =
filters.iterator();
//
Call the next filter if there is one
if
(
this
.iterator.hasNext()) {
ApplicationFilterConfig filterConfig
=
(ApplicationFilterConfig) iterator.next();
Filter filter
=
null
;
try
{
filter
=
filterConfig.getFilter();
support.fireInstanceEvent(InstanceEvent.BEFORE_FILTER_EVENT,
filter, request, response);
filter.doFilter(request, response,
this
);
support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT,
filter, request, response);
}
catch
(IOException e) {
if
(filter !=
null
)
support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT,
filter, request, response, e);
throw
e;
}
catch
(ServletException e) {
if
(filter !=
null
)
support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT,
filter, request, response, e);
throw
e;
}
catch
(RuntimeException e) {
if
(filter !=
null
)
support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT,
filter, request, response, e);
throw
e;
}
catch
(Throwable e) {
if
(filter !=
null
)
support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT,
filter, request, response, e);
throw
new
ServletException
(sm.getString(
"filterChain.filter"
), e);
}
return
;
}
//
We fell off the end of the chain -- call the servlet instance
try
{
support.fireInstanceEvent(InstanceEvent.BEFORE_SERVICE_EVENT,
servlet, request, response);
if
((request
instanceof
HttpServletRequest) &&
(response
instanceof
HttpServletResponse)) {
servlet.service((HttpServletRequest) request,
(HttpServletResponse) response);
}
else
{
servlet.service(request, response);
}
support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT,
servlet, request, response);
}
catch
(IOException e) {
support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT,
servlet, request, response, e);
throw
e;
}
catch
(ServletException e) {
support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT,
servlet, request, response, e);
throw
e;
}
catch
(RuntimeException e) {
support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT,
servlet, request, response, e);
throw
e;
}
catch
(Throwable e) {
support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT,
servlet, request, response, e);
throw
new
ServletException
(sm.getString(
"filterChain.servlet"
), e);
}
}
在調(diào)用了filter.doFilter(request, response, this)方法之后,繼續(xù)執(zhí)行servlet的service()方法
這里的this是ApplicationFilterChain對(duì)象自身,在我們編寫的Filter實(shí)現(xiàn)類里面同在在執(zhí)行完我們實(shí)現(xiàn)的過(guò)濾方法之后會(huì)繼續(xù)調(diào)用FilterChain對(duì)象的void doFilter(ServletRequest request, ServletResponse response)方法,我們自定義的過(guò)濾器通常會(huì)這樣實(shí)現(xiàn):
class
SampleFilter
implements
Filter {
........
public
void
doFilter(ServletRequest request, ServletResponse response,FilterChain chain)
throws
IOException, ServletException {
//
do something
.....
//
request, response傳遞給下一個(gè)過(guò)濾器進(jìn)行過(guò)濾
chain.doFilter(request, response);
}
}
ApplicationFilterConfig類實(shí)現(xiàn)了javax.servlet.FilterConfig接口,代表一個(gè)Filter容器,F(xiàn)ilterConfig接口定義如下:
public
interface
FilterConfig {
public
String getFilterName();
public
ServletContext getServletContext();
public
String getInitParameter(String name);
public
Enumeration getInitParameterNames();
}
可以通過(guò)傳入org.apache.catalina.Context對(duì)象和FilterDef對(duì)象(FilterDef對(duì)象用于對(duì)過(guò)濾器類的定義,包括過(guò)濾器類名、相關(guān)參數(shù)等)傳給其構(gòu)造函數(shù)構(gòu)造一個(gè)ApplicationFilterConfig對(duì)象:
public
ApplicationFilterConfig(Context context, FilterDef filterDef)
throws
ClassCastException, ClassNotFoundException,
IllegalAccessException, InstantiationException,
ServletException {
super
();
this
.context =
context;
setFilterDef(filterDef);
}
ApplicationFilterConfig類的getFilter()方法返回一個(gè)javax.servlet.Filter對(duì)象,該方法負(fù)責(zé)載入并實(shí)例化一個(gè)過(guò)濾器類
Filter getFilter()
throws
ClassCastException, ClassNotFoundException,
IllegalAccessException, InstantiationException, ServletException {
//
Return the existing filter instance, if any
if
(
this
.filter !=
null
)
return
(
this
.filter);
//
Identify the class loader we will be using
String filterClass =
filterDef.getFilterClass();
ClassLoader classLoader
=
null
;
if
(filterClass.startsWith("org.apache.catalina."
))
classLoader
=
this
.getClass().getClassLoader();
else
classLoader
=
context.getLoader().getClassLoader();
ClassLoader oldCtxClassLoader
=
Thread.currentThread().getContextClassLoader();
//
Instantiate a new instance of this filter and return it
Class clazz =
classLoader.loadClass(filterClass);
this
.filter =
(Filter) clazz.newInstance();
filter.init(
this
);
return
(
this
.filter);
}
現(xiàn)在,也許我們更容易理解StandardWrapperValve類中創(chuàng)建過(guò)濾器鏈createFilterChain()方法了
private
ApplicationFilterChain createFilterChain(Request request,
Servlet servlet) {
//
If there is no servlet to execute, return null
if
(servlet ==
null
)
return
(
null
);
//
Create and initialize a filter chain object
ApplicationFilterChain filterChain =
new
ApplicationFilterChain();
filterChain.setServlet(servlet);
StandardWrapper wrapper
=
(StandardWrapper) getContainer();
filterChain.setSupport(wrapper.getInstanceSupport());
//
Acquire the filter mappings for this Context
StandardContext context =
(StandardContext) wrapper.getParent();
FilterMap filterMaps[]
=
context.findFilterMaps();
//
If there are no filter mappings, we are done
if
((filterMaps ==
null
) || (filterMaps.length == 0
))
return
(filterChain);
//
if (debug >= 1)
//
log("createFilterChain: Processing " + filterMaps.length +
//
" filter map entries");
//
Acquire the information we will need to match filter mappings
String requestPath =
null
;
if
(request
instanceof
HttpRequest) {
HttpServletRequest hreq
=
(HttpServletRequest) request.getRequest();
String contextPath
=
hreq.getContextPath();
if
(contextPath ==
null
)
contextPath
= ""
;
String requestURI
=
((HttpRequest) request).getDecodedRequestURI();
if
(requestURI.length() >=
contextPath.length())
requestPath
=
requestURI.substring(contextPath.length());
}
String servletName
=
wrapper.getName();
//
if (debug >= 1) {
//
log(" requestPath=" + requestPath);
//
log(" servletName=" + servletName);
//
}
int
n = 0
;
//
Add the relevant path-mapped filters to this filter chain
for
(
int
i = 0; i < filterMaps.length; i++
) {
//
if (debug >= 2)
//
log(" Checking path-mapped filter '" +
//
filterMaps[i] + "'");
if
(!
matchFiltersURL(filterMaps[i], requestPath))
continue
;
ApplicationFilterConfig filterConfig
=
(ApplicationFilterConfig)
context.findFilterConfig(filterMaps[i].getFilterName());
if
(filterConfig ==
null
) {
//
if (debug >= 2)
//
log(" Missing path-mapped filter '" +
//
filterMaps[i] + "'");
;
//
FIXME - log configuration problem
continue
;
}
//
if (debug >= 2)
//
log(" Adding path-mapped filter '" +
//
filterConfig.getFilterName() + "'");
filterChain.addFilter(filterConfig);
n
++
;
}
//
Add filters that match on servlet name second
for
(
int
i = 0; i < filterMaps.length; i++
) {
//
if (debug >= 2)
//
log(" Checking servlet-mapped filter '" +
//
filterMaps[i] + "'");
if
(!
matchFiltersServlet(filterMaps[i], servletName))
continue
;
ApplicationFilterConfig filterConfig
=
(ApplicationFilterConfig)
context.findFilterConfig(filterMaps[i].getFilterName());
if
(filterConfig ==
null
) {
//
if (debug >= 2)
//
log(" Missing servlet-mapped filter '" +
//
filterMaps[i] + "'");
;
//
FIXME - log configuration problem
continue
;
}
//
if (debug >= 2)
//
log(" Adding servlet-mapped filter '" +
//
filterMaps[i] + "'");
filterChain.addFilter(filterConfig);
n
++
;
}
//
Return the completed filter chain
//
if (debug >= 2)
//
log(" Returning chain with " + n + " filters");
return
(filterChain);
}
---------------------------------------------------------------------------?
本系列How Tomcat Works系本人原創(chuàng)?
轉(zhuǎn)載請(qǐng)注明出處 博客園 刺猬的溫馴?
本人郵箱: ? chenying998179 # 163.com ( #改為@ )
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061
微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元

