JavaWeb中過濾器Filter的用法詳解
過濾器Filter
過濾器通常對(duì)一些web資源進(jìn)行攔截,做完一些處理器再交給下一個(gè)過濾器處理,直到所有的過濾器處理器,再調(diào)用servlet實(shí)例的service方法進(jìn)行處理。過濾器可以對(duì)request進(jìn)行處理也可以對(duì)response進(jìn)行處理。
處理順序

如果過濾器鏈順序如上圖所示,那么對(duì)request請(qǐng)求的處理順序?yàn)?、2、3,對(duì)response響應(yīng)的處理順序?yàn)?、2、1.
使用場(chǎng)景
用戶權(quán)限驗(yàn)證
防止亂碼統(tǒng)一對(duì)請(qǐng)求和響應(yīng)設(shè)置編碼
對(duì)響應(yīng)數(shù)據(jù)壓縮等等
自定義過濾器
實(shí)現(xiàn)接口 Filter
public interface Filter {
// 由web容器調(diào)用在filter實(shí)例化后調(diào)用一次,可以用來配置filter的初始信息等
public void init(FilterConfig filterConfig) throws ServletException;
// 執(zhí)行該過濾器邏輯,由ApplicationFilterChain過濾器鏈統(tǒng)一調(diào)用
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException;
// 有web容器調(diào)用進(jìn)行銷毀
public void destroy();
}寫一個(gè)簡(jiǎn)單的過濾器,當(dāng)用戶已登錄或者請(qǐng)求的頁(yè)面是首頁(yè)時(shí)不進(jìn)行過濾攔截繼續(xù)請(qǐng)求下一個(gè)過濾器,否則跳轉(zhuǎn)回首頁(yè)進(jìn)行登錄??梢钥吹浇oLoginFilter類加了WebFilter注解,表明過濾器的名稱、作用的servlet以及需要攔截的請(qǐng)求路徑表達(dá)式,后續(xù)會(huì)將這個(gè)過濾器注冊(cè)添加到web容器的過濾器鏈中。
@Slf4j(topic = "e")
@WebFilter(filterName = "loginFilter", servletNames = "dispatcher", urlPatterns = "*")
public class LoginFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
log.info("LoginFilter init");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
log.info("LoginFilter doFilter");
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
// 判斷用戶是否登錄
HttpSession session = req.getSession();
String uri = req.getRequestURI();
log.info("requestUri:" + uri);
// 已經(jīng)登錄 | 首頁(yè) | 登錄接口不攔截,其他情況重定向回首頁(yè)
if (LoginUtil.isLogin(session.getAttribute("username"))) {
log.info("用戶已登錄");
chain.doFilter(req, res);
} else if (uri.equals(req.getContextPath() + "/") || uri.contains("login")) {
log.info("請(qǐng)求首頁(yè)/登錄接口");
chain.doFilter(req, res);
} else {
log.info("未登錄請(qǐng)求轉(zhuǎn)發(fā)到登錄頁(yè)");
RequestDispatcher requestDispatcher = req.getRequestDispatcher("/");
requestDispatcher.forward(req, res);
}
}
@Override
public void destroy() {
}
}當(dāng)然也可以在web.xml文件中配置此過濾器同使用注解是相同的效果,如下:
<filter>
<filter-name>LoginFilter</filter-name>
<filter-class>com.monian.study.filter.LoginFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>LoginFilter</filter-name>
<servlet-name>dispatcher</servlet-name>
<url-pattern>*</url-pattern>
</filter-mapping>請(qǐng)求接口日志如下

源碼分析
FilterDef
這個(gè)類定義了過濾器的名稱、全限定名、初始化參數(shù)等信息,有了這些信息web容器就可以實(shí)例化這個(gè)過濾器并進(jìn)行一些初始化的配置操作,用來生成后續(xù)的ApplicationFilterConfig對(duì)象
?public class FilterDef implements Serializable {
private static final long serialVersionUID = 1L;
private static final StringManager sm =
StringManager.getManager(Constants.PACKAGE_NAME);
// ------------------------------------------------------------- Properties
/**
* The description of this filter.
*/
private String description = null;
public String getDescription() {
return this.description;
}
public void setDescription(String description) {
this.description = description;
}
/**
* The display name of this filter.
*/
private String displayName = null;
public String getDisplayName() {
return this.displayName;
}
public void setDisplayName(String displayName) {
this.displayName = displayName;
}
/**
* The filter instance associated with this definition
*/
private transient Filter filter = null;
public Filter getFilter() {
return filter;
}
public void setFilter(Filter filter) {
this.filter = filter;
}
/**
* The fully qualified name of the Java class that implements this filter.
*/
private String filterClass = null;
public String getFilterClass() {
return this.filterClass;
}
public void setFilterClass(String filterClass) {
this.filterClass = filterClass;
}
/**
* The name of this filter, which must be unique among the filters
* defined for a particular web application.
*/
private String filterName = null;
public String getFilterName() {
return this.filterName;
}
public void setFilterName(String filterName) {
if (filterName == null || filterName.equals("")) {
throw new IllegalArgumentException(
sm.getString("filterDef.invalidFilterName", filterName));
}
this.filterName = filterName;
}
/**
* The large icon associated with this filter.
*/
private String largeIcon = null;
public String getLargeIcon() {
return this.largeIcon;
}
public void setLargeIcon(String largeIcon) {
this.largeIcon = largeIcon;
}
/**
* The set of initialization parameters for this filter, keyed by
* parameter name.
*/
private final Map<String, String> parameters = new HashMap<>();
public Map<String, String> getParameterMap() {
return this.parameters;
}
/**
* The small icon associated with this filter.
*/
private String smallIcon = null;
public String getSmallIcon() {
return this.smallIcon;
}
public void setSmallIcon(String smallIcon) {
this.smallIcon = smallIcon;
}
private String asyncSupported = null;
public String getAsyncSupported() {
return asyncSupported;
}
public void setAsyncSupported(String asyncSupported) {
this.asyncSupported = asyncSupported;
}
// --------------------------------------------------------- Public Methods
/**
* Add an initialization parameter to the set of parameters associated
* with this filter.
*
* @param name The initialization parameter name
* @param value The initialization parameter value
*/
public void addInitParameter(String name, String value) {
if (parameters.containsKey(name)) {
// The spec does not define this but the TCK expects the first
// definition to take precedence
return;
}
parameters.put(name, value);
}
/**
* Render a String representation of this object.
*/
@Override
public String toString() {
StringBuilder sb = new StringBuilder("FilterDef[");
sb.append("filterName=");
sb.append(this.filterName);
sb.append(", filterClass=");
sb.append(this.filterClass);
sb.append("]");
return sb.toString();
}
}FilterMap
這個(gè)類主要定義了過濾器的名稱、作用的serlvet、攔截的路徑以及調(diào)度類型等信息,主要用來作為判斷過濾器是否能應(yīng)用在request上。
?public class FilterMap extends XmlEncodingBase implements Serializable {
// ------------------------------------------------------------- Properties
private static final long serialVersionUID = 1L;
/**
* The name of this filter to be executed when this mapping matches
* a particular request.
*/
public static final int ERROR = 1;
public static final int FORWARD = 2;
public static final int INCLUDE = 4;
public static final int REQUEST = 8;
public static final int ASYNC = 16;
// represents nothing having been set. This will be seen
// as equal to a REQUEST
private static final int NOT_SET = 0;
private int dispatcherMapping = NOT_SET;
private String filterName = null;
public String getFilterName() {
return this.filterName;
}
public void setFilterName(String filterName) {
this.filterName = filterName;
}
// 過濾器作用的servlet的名稱
private String[] servletNames = new String[0];
public String[] getServletNames() {
if (matchAllServletNames) {
return new String[] {};
} else {
return this.servletNames;
}
}
public void addServletName(String servletName) {
if ("*".equals(servletName)) {
this.matchAllServletNames = true;
} else {
String[] results = new String[servletNames.length + 1];
System.arraycopy(servletNames, 0, results, 0, servletNames.length);
results[servletNames.length] = servletName;
servletNames = results;
}
}
/**
* The flag that indicates this mapping will match all url-patterns
*/
private boolean matchAllUrlPatterns = false;
public boolean getMatchAllUrlPatterns() {
return matchAllUrlPatterns;
}
/**
* The flag that indicates this mapping will match all servlet-names
*/
private boolean matchAllServletNames = false;
public boolean getMatchAllServletNames() {
return matchAllServletNames;
}
/**
* 過濾器作用攔截的路徑
*/
private String[] urlPatterns = new String[0];
public String[] getURLPatterns() {
if (matchAllUrlPatterns) {
return new String[] {};
} else {
return this.urlPatterns;
}
}
public void addURLPattern(String urlPattern) {
addURLPatternDecoded(UDecoder.URLDecode(urlPattern, getCharset()));
}
public void addURLPatternDecoded(String urlPattern) {
if ("*".equals(urlPattern)) {
this.matchAllUrlPatterns = true;
} else {
String[] results = new String[urlPatterns.length + 1];
System.arraycopy(urlPatterns, 0, results, 0, urlPatterns.length);
results[urlPatterns.length] = UDecoder.URLDecode(urlPattern);
urlPatterns = results;
}
}
/**
* This method will be used to set the current state of the FilterMap
* representing the state of when filters should be applied.
* @param dispatcherString the dispatcher type which should
* match this filter
*/
public void setDispatcher(String dispatcherString) {
String dispatcher = dispatcherString.toUpperCase(Locale.ENGLISH);
if (dispatcher.equals(DispatcherType.FORWARD.name())) {
// apply FORWARD to the global dispatcherMapping.
dispatcherMapping |= FORWARD;
} else if (dispatcher.equals(DispatcherType.INCLUDE.name())) {
// apply INCLUDE to the global dispatcherMapping.
dispatcherMapping |= INCLUDE;
} else if (dispatcher.equals(DispatcherType.REQUEST.name())) {
// apply REQUEST to the global dispatcherMapping.
dispatcherMapping |= REQUEST;
} else if (dispatcher.equals(DispatcherType.ERROR.name())) {
// apply ERROR to the global dispatcherMapping.
dispatcherMapping |= ERROR;
} else if (dispatcher.equals(DispatcherType.ASYNC.name())) {
// apply ERROR to the global dispatcherMapping.
dispatcherMapping |= ASYNC;
}
}
public int getDispatcherMapping() {
// per the SRV.6.2.5 absence of any dispatcher elements is
// equivalent to a REQUEST value
if (dispatcherMapping == NOT_SET) return REQUEST;
return dispatcherMapping;
}
public String[] getDispatcherNames() {
ArrayList<String> result = new ArrayList<>();
if ((dispatcherMapping & FORWARD) != 0) {
result.add(DispatcherType.FORWARD.name());
}
if ((dispatcherMapping & INCLUDE) != 0) {
result.add(DispatcherType.INCLUDE.name());
}
if ((dispatcherMapping & REQUEST) != 0) {
result.add(DispatcherType.REQUEST.name());
}
if ((dispatcherMapping & ERROR) != 0) {
result.add(DispatcherType.ERROR.name());
}
if ((dispatcherMapping & ASYNC) != 0) {
result.add(DispatcherType.ASYNC.name());
}
return result.toArray(new String[result.size()]);
}
// --------------------------------------------------------- Public Methods
/**
* Render a String representation of this object.
*/
@Override
public String toString() {
StringBuilder sb = new StringBuilder("FilterMap[");
sb.append("filterName=");
sb.append(this.filterName);
for (int i = 0; i < servletNames.length; i++) {
sb.append(", servletName=");
sb.append(servletNames[i]);
}
for (int i = 0; i < urlPatterns.length; i++) {
sb.append(", urlPattern=");
sb.append(urlPatterns[i]);
}
sb.append("]");
return sb.toString();
}
}初始化過濾器
org.apache.catalina.core.StandardContext#filterStart
? /**
* Configure and initialize the set of filters for this Context.
* 為此上下文配置和初始化過濾器
* @return <code>true</code> if all filter initialization completed
* successfully, or <code>false</code> otherwise.
*/
public boolean filterStart() {
if (getLogger().isDebugEnabled()) {
getLogger().debug("Starting filters");
}
// Instantiate and record a FilterConfig for each defined filter
boolean ok = true;
synchronized (filterConfigs) {
filterConfigs.clear();
// 遍歷過濾器定義
for (Entry<String,FilterDef> entry : filterDefs.entrySet()) {
String name = entry.getKey();
if (getLogger().isDebugEnabled()) {
getLogger().debug(" Starting filter '" + name + "'");
}
try {
// 實(shí)例化應(yīng)用過濾器配置
ApplicationFilterConfig filterConfig =
new ApplicationFilterConfig(this, entry.getValue());
filterConfigs.put(name, filterConfig);
} catch (Throwable t) {
t = ExceptionUtils.unwrapInvocationTargetException(t);
ExceptionUtils.handleThrowable(t);
getLogger().error(sm.getString(
"standardContext.filterStart", name), t);
ok = false;
}
}
}
return ok;
}通過構(gòu)建ApplicationFilterConfig主要是實(shí)例化filter,以及初始化init(只會(huì)調(diào)用一次),并且該類實(shí)現(xiàn)了FilterConfig接口,可以通過ApplicationFilterConfig實(shí)例獲取過濾器的名稱、全限定名以及配置的一些初始化參數(shù)信息。
public final class ApplicationFilterConfig implements FilterConfig, Serializable {
private static final long serialVersionUID = 1L;
static final StringManager sm =
StringManager.getManager(Constants.Package);
private transient Log log = LogFactory.getLog(ApplicationFilterConfig.class); // must not be static
/**
* Empty String collection to serve as the basis for empty enumerations.
*/
private static final List<String> emptyString = Collections.emptyList();
// ----------------------------------------------------------- Constructors
// 構(gòu)造方法
ApplicationFilterConfig(Context context, FilterDef filterDef)
throws ClassCastException, ClassNotFoundException, IllegalAccessException,
InstantiationException, ServletException, InvocationTargetException, NamingException,
IllegalArgumentException, NoSuchMethodException, SecurityException {
super();
this.context = context;
this.filterDef = filterDef;
// 過濾器初始化
if (filterDef.getFilter() == null) {
getFilter();
} else {
this.filter = filterDef.getFilter();
getInstanceManager().newInstance(filter);
initFilter();
}
}
// ----------------------------------------------------- Instance Variables
/**
* The Context with which we are associated.
*/
private final transient Context context;
/**
* The application Filter we are configured for.
*/
private transient Filter filter = null;
/**
* The <code>FilterDef</code> that defines our associated Filter.
*/
private final FilterDef filterDef;
/**
* the InstanceManager used to create and destroy filter instances.
*/
private transient InstanceManager instanceManager;
/**
* JMX registration name
*/
private ObjectName oname;
// --------------------------------------------------- FilterConfig Methods
/**
* Return the name of the filter we are configuring.
*/
@Override
public String getFilterName() {
return filterDef.getFilterName();
}
/**
* @return The class of the filter we are configuring.
*/
public String getFilterClass() {
return filterDef.getFilterClass();
}
/**
* Return a <code>String</code> containing the value of the named
* initialization parameter, or <code>null</code> if the parameter
* does not exist.
*
* @param name Name of the requested initialization parameter
*/
@Override
public String getInitParameter(String name) {
Map<String,String> map = filterDef.getParameterMap();
if (map == null) {
return null;
}
return map.get(name);
}
/**
* Return an <code>Enumeration</code> of the names of the initialization
* parameters for this Filter.
*/
@Override
public Enumeration<String> getInitParameterNames() {
Map<String,String> map = filterDef.getParameterMap();
if (map == null) {
return Collections.enumeration(emptyString);
}
return Collections.enumeration(map.keySet());
}
/**
* Return the ServletContext of our associated web application.
*/
@Override
public ServletContext getServletContext() {
return this.context.getServletContext();
}
/**
* Return a String representation of this object.
*/
@Override
public String toString() {
StringBuilder sb = new StringBuilder("ApplicationFilterConfig[");
sb.append("name=");
sb.append(filterDef.getFilterName());
sb.append(", filterClass=");
sb.append(filterDef.getFilterClass());
sb.append("]");
return sb.toString();
}
// --------------------------------------------------------- Public Methods
public Map<String, String> getFilterInitParameterMap() {
return Collections.unmodifiableMap(filterDef.getParameterMap());
}
// -------------------------------------------------------- Package Methods
Filter getFilter() throws ClassCastException, ClassNotFoundException, IllegalAccessException,
InstantiationException, ServletException, InvocationTargetException, NamingException,
IllegalArgumentException, NoSuchMethodException, SecurityException {
// Return the existing filter instance, if any
if (this.filter != null)
return this.filter;
// 根據(jù)過濾器的全限定名通過反射實(shí)例化
String filterClass = filterDef.getFilterClass();
this.filter = (Filter) getInstanceManager().newInstance(filterClass);
// 初始化過濾器
initFilter();
return this.filter;
}
// 調(diào)用過濾器的init()方法,我們自定義的過濾器該init方法也由我們自定義
private void initFilter() throws ServletException {
if (context instanceof StandardContext &&
context.getSwallowOutput()) {
try {
SystemLogHandler.startCapture();
filter.init(this);
} finally {
String capturedlog = SystemLogHandler.stopCapture();
if (capturedlog != null && capturedlog.length() > 0) {
getServletContext().log(capturedlog);
}
}
} else {
filter.init(this);
}
// Expose filter via JMX
registerJMX();
}
/**
* Return the filter definition we are configured for.
*/
FilterDef getFilterDef() {
return this.filterDef;
}
private InstanceManager getInstanceManager() {
if (instanceManager == null) {
if (context instanceof StandardContext) {
instanceManager = ((StandardContext)context).getInstanceManager();
} else {
instanceManager = new DefaultInstanceManager(null,
new HashMap<String, Map<String, String>>(),
context,
getClass().getClassLoader());
}
}
return instanceManager;
}
}創(chuàng)建過濾器鏈 ApplicationFilterChain
web容器會(huì)為request創(chuàng)建過濾器鏈,并且經(jīng)過過濾器鏈中每個(gè)過濾器的處理后才會(huì)繼續(xù)執(zhí)行到servlet
org.apache.catalina.core.ApplicationFilterFactory#createFilterChain
?public static ApplicationFilterChain createFilterChain(ServletRequest request,
Wrapper wrapper, Servlet servlet) {
// If there is no servlet to execute, return null
if (servlet == null)
return null;
// 創(chuàng)建并初始化一個(gè)攔截器對(duì)象
ApplicationFilterChain filterChain = null;
if (request instanceof Request) {
Request req = (Request) request;
if (Globals.IS_SECURITY_ENABLED) {
// Security: Do not recycle
filterChain = new ApplicationFilterChain();
} else {
// 從請(qǐng)求中取,復(fù)用過濾器鏈
filterChain = (ApplicationFilterChain) req.getFilterChain();
if (filterChain == null) {
filterChain = new ApplicationFilterChain();
req.setFilterChain(filterChain);
}
}
} else {
// Request dispatcher in use
filterChain = new ApplicationFilterChain();
}
// 設(shè)置servlet
filterChain.setServlet(servlet);
// 是否支持異步
filterChain.setServletSupportsAsync(wrapper.isAsyncSupported());
// 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
// 未設(shè)置過濾器直接返回
if ((filterMaps == null) || (filterMaps.length == 0))
return filterChain;
// Acquire the information we will need to match filter mappings
// 從request獲取dispatcher以匹配 (REQUEST)
DispatcherType dispatcher =
(DispatcherType) request.getAttribute(Globals.DISPATCHER_TYPE_ATTR);
// 獲取請(qǐng)求路徑
String requestPath = null;
Object attribute = request.getAttribute(Globals.DISPATCHER_REQUEST_PATH_ATTR);
if (attribute != null){
requestPath = attribute.toString();
}
// 獲取servlet名稱
String servletName = wrapper.getName();
// Add the relevant path-mapped filters to this filter chain
// 過濾器鏈中添加路徑匹配的過濾器
for (int i = 0; i < filterMaps.length; i++) {
// 先匹配dispatcher類型,默認(rèn)是REQUEST
if (!matchDispatcher(filterMaps[i] ,dispatcher)) {
continue;
}
// 再匹配請(qǐng)求路徑
if (!matchFiltersURL(filterMaps[i], requestPath))
continue;
ApplicationFilterConfig filterConfig = (ApplicationFilterConfig)
context.findFilterConfig(filterMaps[i].getFilterName());
if (filterConfig == null) {
// FIXME - log configuration problem
continue;
}
// 添加到過濾器鏈中
filterChain.addFilter(filterConfig);
}
// Add filters that match on servlet name second
// 在根據(jù)servlet名稱匹配過濾器添加到過濾器鏈中
for (int i = 0; i < filterMaps.length; i++) {
if (!matchDispatcher(filterMaps[i] ,dispatcher)) {
continue;
}
if (!matchFiltersServlet(filterMaps[i], servletName))
continue;
ApplicationFilterConfig filterConfig = (ApplicationFilterConfig)
context.findFilterConfig(filterMaps[i].getFilterName());
if (filterConfig == null) {
// FIXME - log configuration problem
continue;
}
filterChain.addFilter(filterConfig);
}
// Return the completed filter chain
// 返回完整的過濾器鏈對(duì)象
return filterChain;
}執(zhí)行過濾器鏈
ApplicationFilterChain執(zhí)行過濾器方法
?public final class ApplicationFilterChain implements FilterChain {
// Used to enforce requirements of SRV.8.2 / SRV.14.2.5.1
private static final ThreadLocal<ServletRequest> lastServicedRequest;
private static final ThreadLocal<ServletResponse> lastServicedResponse;
static {
if (ApplicationDispatcher.WRAP_SAME_OBJECT) {
lastServicedRequest = new ThreadLocal<>();
lastServicedResponse = new ThreadLocal<>();
} else {
lastServicedRequest = null;
lastServicedResponse = null;
}
}
// -------------------------------------------------------------- Constants
public static final int INCREMENT = 10;
// ----------------------------------------------------- Instance Variables
/**
* Filters.
*/
private ApplicationFilterConfig[] filters = new ApplicationFilterConfig[0];
/**
* The int which is used to maintain the current position
* in the filter chain.
*/
private int pos = 0;
/**
* The int which gives the current number of filters in the chain.
*/
private int n = 0;
/**
* The servlet instance to be executed by this chain.
*/
private Servlet servlet = null;
/**
* Does the associated servlet instance support async processing?
*/
private boolean servletSupportsAsync = false;
/**
* The string manager for our package.
*/
private static final StringManager sm =
StringManager.getManager(Constants.Package);
/**
* Static class array used when the SecurityManager is turned on and
* <code>doFilter</code> is invoked.
*/
private static final Class<?>[] classType = new Class[]{
ServletRequest.class, ServletResponse.class, FilterChain.class};
/**
* Static class array used when the SecurityManager is turned on and
* <code>service</code> is invoked.
*/
private static final Class<?>[] classTypeUsedInService = new Class[]{
ServletRequest.class, ServletResponse.class};
// ---------------------------------------------------- FilterChain Methods
/**
* Invoke the next filter in this chain, passing the specified request
* and response. If there are no more filters in this chain, invoke
* the <code>service()</code> method of the servlet itself.
*
* @param request The servlet request we are processing
* @param response The servlet response we are creating
*
* @exception IOException if an input/output error occurs
* @exception ServletException if a servlet exception occurs
*/
// 執(zhí)行過濾器
@Override
public void doFilter(ServletRequest request, ServletResponse response)
throws IOException, ServletException {
if( Globals.IS_SECURITY_ENABLED ) {
final ServletRequest req = request;
final ServletResponse res = response;
try {
java.security.AccessController.doPrivileged(
new java.security.PrivilegedExceptionAction<Void>() {
@Override
public Void run()
throws ServletException, IOException {
internalDoFilter(req,res);
return null;
}
}
);
} catch( PrivilegedActionException pe) {
Exception e = pe.getException();
if (e instanceof ServletException)
throw (ServletException) e;
else if (e instanceof IOException)
throw (IOException) e;
else if (e instanceof RuntimeException)
throw (RuntimeException) e;
else
throw new ServletException(e.getMessage(), e);
}
} else {
internalDoFilter(request,response);
}
}
private void internalDoFilter(ServletRequest request,
ServletResponse response)
throws IOException, ServletException {
// Call the next filter if there is one
// pos表示當(dāng)前正在使用的過濾器在過濾器數(shù)組filters中的序號(hào),每執(zhí)行一次加1
// n表示過濾器數(shù)目
if (pos < n) {
ApplicationFilterConfig filterConfig = filters[pos++];
try {
Filter filter = filterConfig.getFilter();
if (request.isAsyncSupported() && "false".equalsIgnoreCase(
filterConfig.getFilterDef().getAsyncSupported())) {
request.setAttribute(Globals.ASYNC_SUPPORTED_ATTR, Boolean.FALSE);
}
if( Globals.IS_SECURITY_ENABLED ) {
final ServletRequest req = request;
final ServletResponse res = response;
Principal principal =
((HttpServletRequest) req).getUserPrincipal();
Object[] args = new Object[]{req, res, this};
SecurityUtil.doAsPrivilege ("doFilter", filter, classType, args, principal);
} else {
// 調(diào)用doFilter執(zhí)行過濾器的方法
filter.doFilter(request, response, this);
}
} catch (IOException | ServletException | RuntimeException e) {
throw e;
} catch (Throwable e) {
e = ExceptionUtils.unwrapInvocationTargetException(e);
ExceptionUtils.handleThrowable(e);
throw new ServletException(sm.getString("filterChain.filter"), e);
}
return;
}
// We fell off the end of the chain -- call the servlet instance
// 當(dāng)所有過濾器執(zhí)行完后,調(diào)用servlet的service()方法
try {
if (ApplicationDispatcher.WRAP_SAME_OBJECT) {
lastServicedRequest.set(request);
lastServicedResponse.set(response);
}
if (request.isAsyncSupported() && !servletSupportsAsync) {
request.setAttribute(Globals.ASYNC_SUPPORTED_ATTR,
Boolean.FALSE);
}
// Use potentially wrapped request from this point
if ((request instanceof HttpServletRequest) &&
(response instanceof HttpServletResponse) &&
Globals.IS_SECURITY_ENABLED ) {
final ServletRequest req = request;
final ServletResponse res = response;
Principal principal =
((HttpServletRequest) req).getUserPrincipal();
Object[] args = new Object[]{req, res};
SecurityUtil.doAsPrivilege("service",
servlet,
classTypeUsedInService,
args,
principal);
} else {
servlet.service(request, response);
}
} catch (IOException | ServletException | RuntimeException e) {
throw e;
} catch (Throwable e) {
e = ExceptionUtils.unwrapInvocationTargetException(e);
ExceptionUtils.handleThrowable(e);
throw new ServletException(sm.getString("filterChain.servlet"), e);
} finally {
if (ApplicationDispatcher.WRAP_SAME_OBJECT) {
lastServicedRequest.set(null);
lastServicedResponse.set(null);
}
}
}
/**
* The last request passed to a servlet for servicing from the current
* thread.
*
* @return The last request to be serviced.
*/
public static ServletRequest getLastServicedRequest() {
return lastServicedRequest.get();
}
/**
* The last response passed to a servlet for servicing from the current
* thread.
*
* @return The last response to be serviced.
*/
public static ServletResponse getLastServicedResponse() {
return lastServicedResponse.get();
}
// -------------------------------------------------------- Package Methods
/**
* Add a filter to the set of filters that will be executed in this chain.
*
* @param filterConfig The FilterConfig for the servlet to be executed
*/
// 添加過濾器配置信息到過濾器鏈
void addFilter(ApplicationFilterConfig filterConfig) {
// Prevent the same filter being added multiple times
for(ApplicationFilterConfig filter:filters)
if(filter==filterConfig)
return;
if (n == filters.length) {
ApplicationFilterConfig[] newFilters =
new ApplicationFilterConfig[n + INCREMENT];
System.arraycopy(filters, 0, newFilters, 0, n);
filters = newFilters;
}
filters[n++] = filterConfig;
}
/**
* Release references to the filters and wrapper executed by this chain.
*/
void release() {
for (int i = 0; i < n; i++) {
filters[i] = null;
}
n = 0;
pos = 0;
servlet = null;
servletSupportsAsync = false;
}
/**
* Prepare for reuse of the filters and wrapper executed by this chain.
*/
void reuse() {
pos = 0;
}
/**
* Set the servlet that will be executed at the end of this chain.
*
* @param servlet The Wrapper for the servlet to be executed
*/
void setServlet(Servlet servlet) {
this.servlet = servlet;
}
void setServletSupportsAsync(boolean servletSupportsAsync) {
this.servletSupportsAsync = servletSupportsAsync;
}
/**
* Identifies the Filters, if any, in this FilterChain that do not support
* async.
*
* @param result The Set to which the fully qualified class names of each
* Filter in this FilterChain that does not support async will
* be added
*/
public void findNonAsyncFilters(Set<String> result) {
for (int i = 0; i < n ; i++) {
ApplicationFilterConfig filter = filters[i];
if ("false".equalsIgnoreCase(filter.getFilterDef().getAsyncSupported())) {
result.add(filter.getFilterClass());
}
}
}
}到此這篇關(guān)于JavaWeb中過濾器Filter的用法詳解的文章就介紹到這了,更多相關(guān)JavaWeb過濾器Filter內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot之HandlerInterceptor攔截器的使用詳解
這篇文章主要介紹了SpringBoot之HandlerInterceptor攔截器的使用詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-10-10
Java利用redis zset實(shí)現(xiàn)延時(shí)任務(wù)詳解
zset作為redis的有序集合數(shù)據(jù)結(jié)構(gòu)存在,排序的依據(jù)就是score。本文就將利用zset score這個(gè)排序的這個(gè)特性,來實(shí)現(xiàn)延時(shí)任務(wù),感興趣的可以了解一下2022-08-08
Springbootadmin與security沖突問題及解決
這篇文章主要介紹了Springbootadmin與security沖突問題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-08-08
解析Apache Dubbo的SPI實(shí)現(xiàn)機(jī)制
SPI全稱為Service Provider Interface,對(duì)應(yīng)中文為服務(wù)發(fā)現(xiàn)機(jī)制。SPI類似一種可插拔機(jī)制,首先需要定義一個(gè)接口或一個(gè)約定,然后不同的場(chǎng)景可以對(duì)其進(jìn)行實(shí)現(xiàn),調(diào)用方在使用的時(shí)候無需過多關(guān)注具體的實(shí)現(xiàn)細(xì)節(jié)2021-06-06
SpringBoot整合Shiro實(shí)現(xiàn)權(quán)限控制的代碼實(shí)現(xiàn)
Apache Shiro是一個(gè)強(qiáng)大且易用的Java安全框架,執(zhí)行身份驗(yàn)證、授權(quán)、密碼和會(huì)話管理,今天通過本文給大家介紹SpringBoot整合Shiro實(shí)現(xiàn)權(quán)限控制的方法,感興趣的朋友一起看看吧2021-07-07
Mybatis不啟動(dòng)項(xiàng)目直接測(cè)試Mapper的實(shí)現(xiàn)方法
在項(xiàng)目開發(fā)中,測(cè)試單個(gè)Mybatis Mapper方法通常需要啟動(dòng)整個(gè)SpringBoot項(xiàng)目,消耗大量時(shí)間,本文介紹通過Main方法和Mybatis配置類,快速測(cè)試Mapper功能,無需啟動(dòng)整個(gè)項(xiàng)目,這方法使用AnnotationConfigApplicationContext容器2024-09-09

