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