grails的七個filterjava
1 charEncodingFilter
org.springframework.web.filter.DelegatingFilterProxy
2 hiddenHttpMethod
org.codehaus.groovy.grails.web.filters.HiddenHttpMethodFilter
<dispatcher>FORWARD</dispatcher>
<dispatcher>REQUEST</dispatcher>
3 AssetPipelineFilter
asset.pipeline.AssetPipelineFilter
<url-pattern>/assets/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
4 grailsWebRequest
org.codehaus.groovy.grails.web.servlet.mvc.GrailsWebRequestFilter
<dispatcher>FORWARD</dispatcher>
<dispatcher>REQUEST</dispatcher>
<dispatcher>ERROR</dispatcher>
5 urlMapping
org.codehaus.groovy.grails.web.mapping.filter.UrlMappingsFilter
<url-pattern>/*</url-pattern>
<dispatcher>FORWARD</dispatcher>
<dispatcher>REQUEST</dispatcher>web
此處過濾器分發合法的urlspring
第一步獲取uri: String uri = urlHelper.getPathWithinApplication(request);緩存
第二步判斷是否合法併發
// not index request, no controllers, and no URL mappings for views, so it's not a Grails request if (!"/".equals(uri) && isGrailsAppWithoutControllersAndRegexMappings()) { processFilterChain(request, response, filterChain); return; } //查找不須要過濾緩存中是否有包含但錢的uil包含則放行 if (uriExclusionCache.isUriExcluded(uri)) { processFilterChain(request, response, filterChain); return; } GrailsWebRequest webRequest = (GrailsWebRequest)request. getAttribute(GrailsApplicationAttributes.WEB_REQUEST); HttpServletRequest currentRequest = webRequest.getCurrentRequest(); String version = findRequestedVersion(webRequest); //找到相應的MappingIfon UrlMappingInfo[] urlInfos = urlMappingsHolder.matchAll(uri, currentRequest.getMethod(), version != null ? version : UrlMapping.ANY_VERSION); WrappedResponseHolder.setWrappedResponse(response);boolean dispatched = false; try { //過濾相應的MappingInfo for (UrlMappingInfo info : urlInfos) { if (info != null) { Object redirectInfo = info.getRedirectInfo(); 處理redirect if(redirectInfo != null) { final Map redirectArgs; if(redirectInfo instanceof Map) { redirectArgs = (Map) redirectInfo; } else { redirectArgs = CollectionUtils.newMap("uri", redirectInfo); } GrailsParameterMap params = webRequest.getParams(); redirectArgs.put("params", params); ResponseRedirector redirector = new ResponseRedirector(linkGenerator); redirector.redirect(redirectArgs); dispatched = true; break; } // GRAILS-3369: The configure() will modify the // parameter map attached to the web request. So, // we need to clear it each time and restore the // original request parameters. webRequest.resetParams(); //將MappingInfo中的參數傳遞到requet中(forword作準備) try { info.configure(webRequest); UrlConverter urlConverterToUse = urlConverter; GrailsApplication grailsApplicationToUse = application; GrailsClass controller = UrlMappingUtils.passControllerForUrlMappingInfoInRequest(webRequest, info, urlConverterToUse, grailsApplicationToUse); if(controller == null && info.getViewName()==null && info.getURI()==null) continue; } catch (Exception e) { if (e instanceof MultipartException) { reapplySitemesh(request); throw ((MultipartException)e); } LOG.error("Error when matching URL mapping [" + info + "]:" + e.getMessage(), e); continue; } dispatched = true; if (!WAR_DEPLOYED) { checkDevelopmentReloadingState(request); } request = checkMultipart(request); String nameOfview = info.getViewName(); //轉發request if (nameOfview == null || nameOfview.endsWith(GSP_SUFFIX) || nameOfview.endsWith(JSP_SUFFIX)) { if (info.isParsingRequest()) { webRequest.informParameterCreationListeners(); } String forwardUrl = UrlMappingUtils.forwardRequestForUrlMappingInfo(request, response, info); if (LOG.isDebugEnabled()) { LOG.debug("Matched URI [" + uri + "] to URL mapping [" + info + "], forwarding to [" + forwardUrl + "] with response [" + response.getClass() + "]"); } } else { if (!renderViewForUrlMappingInfo(request, response, info, nameOfview)) { dispatched = false; } } break; } } } finally { WrappedResponseHolder.setWrappedResponse(null); } //沒有轉發則返回錯誤 if (!dispatched) { Set<HttpMethod> allowedHttpMethods = allowHeaderForWrongHttpMethod ? allowedMethods(urlMappingsHolder, uri) : Collections.EMPTY_SET; if(allowedHttpMethods.isEmpty()) { if (LOG.isDebugEnabled()) { LOG.debug("No match found, processing remaining filter chain."); } processFilterChain(request, response, filterChain); } else { response.addHeader(HttpHeaders.ALLOW, DefaultGroovyMethods.join(allowedHttpMethods, ",")); response.sendError(HttpStatus.METHOD_NOT_ALLOWED.value()); } } if (!dispatched) { Set<HttpMethod> allowedHttpMethods = allowHeaderForWrongHttpMethod ? allowedMethods(urlMappingsHolder, uri) : Collections.EMPTY_SET; if(allowedHttpMethods.isEmpty()) { if (LOG.isDebugEnabled()) { LOG.debug("No match found, processing remaining filter chain."); } processFilterChain(request, response, filterChain); } else { response.addHeader(HttpHeaders.ALLOW, DefaultGroovyMethods.join(allowedHttpMethods, ",")); response.sendError(HttpStatus.METHOD_NOT_ALLOWED.value()); } }
第三步判斷是否在非過濾的數據中mvc
if (uriExclusionCache.isUriExcluded(uri)) {
processFilterChain(request, response, filterChain);
return;
uriExclusionCache是一個緩存app
static class UriExclusionCache { int maxWeightedCacheCapacity = 50000; //ConcurrentLinkedHashMap是谷歌的一個支持併發的LinkedHashMap Map<String, Boolean> exclusionCache = new ConcurrentLinkedHashMap.Builder<String, Boolean>().maximumWeightedCapacity(maxWeightedCacheCapacity).weigher(new EntryWeigher<String, Boolean>() { @Override public int weightOf(String key, Boolean value) { return key.length(); } }).build(); private UrlMappingsHolder holder; UriExclusionCache(UrlMappingsHolder holder) { this.holder = holder; } boolean isUriExcluded(String uri) { //判斷緩存中是否存在該uri Boolean isExcluded = exclusionCache.get(uri); if(isExcluded == null) { //判斷本地的holder中是否有該緩存 isExcluded = UrlMappingsFilter.isUriExcluded(holder, uri); if(!Environment.isDevelopmentMode()) { exclusionCache.put(uri, isExcluded); } } return isExcluded; } } //判斷本地的holder中是否有該緩存 public static boolean isUriExcluded(UrlMappingsHolder holder, String uri) { boolean isExcluded = false; @SuppressWarnings("unchecked") List<String> excludePatterns = holder.getExcludePatterns(); if (excludePatterns != null && excludePatterns.size() > 0) { for (String excludePattern : excludePatterns) { int wildcardLen = 0; if (excludePattern.endsWith("**")) { wildcardLen = 2; } else if (excludePattern.endsWith("*")) { wildcardLen = 1; } if (wildcardLen > 0) { excludePattern = excludePattern.substring(0,excludePattern.length() - wildcardLen); } if ((wildcardLen==0 && uri.equals(excludePattern)) || (wildcardLen > 0 && uri.startsWith(excludePattern))) { isExcluded = true; break; } } } return isExcluded; }
6 grailsCacheFilter
ide