grails的七个filter
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>
此处过滤器分发合法的url
第一步获取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()); } }
第三步判断是否在非过滤的数据中
if (uriExclusionCache.isUriExcluded(uri)) {
processFilterChain(request, response, filterChain);
return;
uriExclusionCache是一个缓存
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