なぜ起源、ルールに合致する研究インターセプタは適用されません
@Configuration("admimWebConfig")
public class WebConfiguration implements WebMvcConfigurer {
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(getServiceAuthRestInterceptor()).
addPathPatterns(getIncludePathPatterns());
}
}
見つけることができ、インターセプタは内部登録に注入されます
public InterceptorRegistration addInterceptor(HandlerInterceptor interceptor) {
InterceptorRegistration registration = new InterceptorRegistration(interceptor);
this.registrations.add(registration);
return registration;
}
アイデアによって、あなたは、この方法だけで使用されている登録を見ることができます
protected List<Object> getInterceptors() {
return this.registrations.stream()
.sorted(INTERCEPTOR_ORDER_COMPARATOR)
.map(InterceptorRegistration::getInterceptor)
.collect(Collectors.toList());
}
そして、この方法はWebMvcConfigurationSupportここで呼び出され
、この変数を使用することがあり、このクラスのメンテナンスインターセプタ変数が、見つかったアイデアインターセプタによってのみ、次のメソッドを返すために、
protected final Object[] getInterceptors() {
if (this.interceptors == null) {
InterceptorRegistry registry = new InterceptorRegistry();
addInterceptors(registry);
registry.addInterceptor(new ConversionServiceExposingInterceptor(mvcConversionService()));
registry.addInterceptor(new ResourceUrlProviderExposingInterceptor(mvcResourceUrlProvider()));
this.interceptors = registry.getInterceptors();
}
return this.interceptors.toArray();
}
上記の方法は、このメソッドの呼び出しWebMvcConfigurationSupportです
@Bean
public RequestMappingHandlerMapping requestMappingHandlerMapping() {
RequestMappingHandlerMapping mapping = createRequestMappingHandlerMapping();
mapping.setOrder(0);
// 可以看到,是RequestMappingHandlerMapping的setInterceptors的拦截
//器调用了,也就是说,RequestMappingHandlerMapping维护了所有的拦截器
// 维护在interceptors这个变量中
mapping.setInterceptors(getInterceptors());
...
return mapping;
}
Spring MVCのソースコード解析は、それは、インターセプタを呼び出すためにアップすると以前は、doDispatchのメソッドDispatchServletに呼ばれています
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
...
// 找到能处理这个请求的handlerMapping
// 这里找到的handlerMapping,已经初始化过了所有的拦截器
// 这里通过handlermapping,获取HandlerExecutionChain,这里会过滤掉不匹配的拦截器
mappedHandler = getHandler(processedRequest);
...
// 这里会调用拦截器
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
...
}
インターセプタ・メソッドの呼び出しを参照してください。
すでにインターセプタをフィルタリングされ、かつインターセプターフィルタをマッチしていないここでインターセプタ変数のHandlerExecutionを発見したデバッグを
この変数は、それの終わりにインターセプタを割り当てられていますか?そして、アイデアが開発中のデバッグプロセスは、有効な値に割り当てられない場所インタセプタはありません、最後にHandlerExecutionインターセプタの値は来る方法ですか?
それは非常に奇妙だった、となぜですか?それはそれのどこ値はありますか?
その後、ヘッド建設HandlerExecutionコードを通じて、私たちはその後、オフヨーヨーが値を変更する値ではなく、直接の割り当てを変更するメソッドを追加し、インターセプタはコレクションです、あなたがリターンしてこのコレクションに取得することができ、事を見落としが見つかります
boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
HandlerInterceptor[] interceptors = getInterceptors();
if (!ObjectUtils.isEmpty(interceptors)) {
for (int i = 0; i < interceptors.length; i++) {
HandlerInterceptor interceptor = interceptors[i];
if (!interceptor.preHandle(request, response, this.handler)) {
triggerAfterCompletion(request, response, null);
return false;
}
this.interceptorIndex = i;
}
}
return true;
}
public HandlerInterceptor[] getInterceptors() {
if (this.interceptors == null && this.interceptorList != null) {
this.interceptors = this.interceptorList.toArray(new HandlerInterceptor[this.interceptorList.size()]);
}
return this.interceptors;
}
それはインターセプタを除外、コード行であります
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
if (this.handlerMappings != null) {
for (HandlerMapping hm : this.handlerMappings) {
if (logger.isTraceEnabled()) {
logger.trace(
"Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName() + "'");
}
//这行代码
HandlerExecutionChain handler = hm.getHandler(request);
if (handler != null) {
return handler;
}
}
}
return null;
}
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
Object handler = getHandlerInternal(request);
if (handler == null) {
handler = getDefaultHandler();
}
if (handler == null) {
return null;
}
// Bean name or resolved handler?
if (handler instanceof String) {
String handlerName = (String) handler;
handler = obtainApplicationContext().getBean(handlerName);
}
// 这行代码
HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
if (CorsUtils.isCorsRequest(request)) {
CorsConfiguration globalConfig = this.globalCorsConfigSource.getCorsConfiguration(request);
CorsConfiguration handlerConfig = getCorsConfiguration(handler, request);
CorsConfiguration config = (globalConfig != null ? globalConfig.combine(handlerConfig) : handlerConfig);
executionChain = getCorsHandlerExecutionChain(request, executionChain, config);
}
return executionChain;
}
最後に、ここで除外され、ここに配置することインターセプタと一致していません
protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ?
(HandlerExecutionChain) handler : new HandlerExecutionChain(handler));
// 这是我们请求的路径
String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);
for (HandlerInterceptor interceptor : this.adaptedInterceptors) {
if (interceptor instanceof MappedInterceptor) {
MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor;
// 这里进行匹配
if (mappedInterceptor.matches(lookupPath, this.pathMatcher)) {
chain.addInterceptor(mappedInterceptor.getInterceptor());
}
}
else {
chain.addInterceptor(interceptor);
}
}
return chain;
}
フィルタリングされたフィルタがどのように見て
、直接このインターセプタを追加しない、つまり、除外(excludeUrlで、で、excludeUrl濾過により、まず、ありますが、多くの人がそれを見つけるだろうし、excludeUrlに追加無効ましたこれはなぜでしょうか?コードの下を見て)
、その後includeUrlに従ってフィルタリング、includeUrlが空である、つまり、このフィルタを追加し、そのノーカスタムincludeUrl、インターセプタすべての場合。
includeUrlが空でない場合は、インターセプトをマッチング
public boolean matches(String lookupPath, PathMatcher pathMatcher) {
PathMatcher pathMatcherToUse = (this.pathMatcher != null ? this.pathMatcher : pathMatcher);
if (!ObjectUtils.isEmpty(this.excludePatterns)) {
for (String pattern : this.excludePatterns) {
if (pathMatcherToUse.match(pattern, lookupPath)) {
return false;
}
}
}
if (ObjectUtils.isEmpty(this.includePatterns)) {
return true;
}
for (String pattern : this.includePatterns) {
if (pathMatcherToUse.match(pattern, lookupPath)) {
return true;
}
}
return false;
}
これは、特定の一致コードである:AntPathMatcherクラス、すなわちAUTパターンマッチング、詳細なマッチングAUTの方法は、多くの百度があります。
コードの最初の行で批判的な視線
protected boolean doMatch(String pattern, String path, boolean fullMatch,
@Nullable Map<String, String> uriTemplateVariables) {
// pathSeparator路径分割符是“/”,path如果以“/”分割,而pathSeparator不以“/”分
//割,则直接返回false。也就是说,如果访问swagger-ui.html页面,这里的path
//是/swagger-ui.html,而不管配置的excludeUrl是:**swagger.html还是
//*swagger.html,都将返回false,匹配不到
if (path.startsWith(this.pathSeparator) != pattern.startsWith(this.pathSeparator)) {
return false;
}
...
return true;
}
だから、AntPathMatcherパターンは、それが何であるかに一致しますか?
アリのルールに一致するように使用AntPathMatcher名前は、私たちが見て、参照してください。
文字のワイルドカードの説明
?1文字にマッチします
*試合ゼロ以上の文字(除く/ディレクトリの区切り)
*ゼロ以上のディレクトリとディレクトリにマッチします
いくつかの例を参照してください:
/swagger.htmlに一致/*swagger.html、*は0以上まあ
/ / Swagger.html /swagger.html **もゼロ以上のディレクトリまあ一致する
/ / * ** /webjars/springfox-swagger-ui/images/favicon-32x32.png整合性多層一致するディレクトリを.pngをします複数の文字にマッチします
?COM /トンst.jsp -試合:COM /なtest.jsp、COM / tast.jsp、COM / txst.jsp
COM / .jspファイル-マッチング:COMのすべての.jspファイルフォルダの下の
COM / /test.jsp -マッチング:すべての.jspファイルの下のcomフォルダとサブフォルダ、
ORG / springframework / / .jspファイル-試合:ORG / springframeworkすべての.jspファイルの下のフォルダとサブフォルダ
ORG / ** /サーブレット/ bla.jsp -試合:ORG / springframework /サーブレット/ bla.jsp 、ORG / springframework /テスト/サーブレット/ bla.jsp、ORG /サーブレット/ bla.jsp
あなたは試験例を書くことができます。
public static void main(String[] args) {
pathMatcher.setCachePatterns(true);
pathMatcher.setCaseSensitive(true);
pathMatcher.setTrimTokens(true);
pathMatcher.setPathSeparator("/");
Assert.assertTrue(pathMatcher.match("/**/*swagger.html", "/swagger.html"));
Assert.assertTrue(pathMatcher.match("/**/*.png", "/webjars/springfox-swagger-ui/images/favicon-32x32.png"));
Assert.assertTrue(pathMatcher.match("a*", "ab"));
Assert.assertTrue(pathMatcher.match("a*/**/a", "ab/asdsa/a"));
Assert.assertTrue(pathMatcher.match("a*/**/a", "ab/asdsa/asdasd/a"));
Assert.assertTrue(pathMatcher.match("*", "a"));
Assert.assertTrue(pathMatcher.match("*/*", "a/a"));
}
ます。https://www.jianshu.com/p/ce3e93670fc8で再現