diff --git a/spring-core/src/main/java/org/springframework/core/log/LogDelegateFactory.java b/spring-core/src/main/java/org/springframework/core/log/LogDelegateFactory.java index 6097a7f53e..a672f2f6a3 100644 --- a/spring-core/src/main/java/org/springframework/core/log/LogDelegateFactory.java +++ b/spring-core/src/main/java/org/springframework/core/log/LogDelegateFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2021 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -63,15 +63,28 @@ public final class LogDelegateFactory { } /** - * Create a "hidden" logger whose name is intentionally prefixed with "_" - * because its output is either too verbose or otherwise deemed as optional - * or unnecessary to see at any log level by default under the normal package - * based log hierarchy. + * Create a "hidden" logger with a category name prefixed with "_", thus + * precluding it from being enabled together with other log categories from + * the same package. This is useful for specialized output that is either + * too verbose or otherwise optional or unnecessary to see all the time. * @param clazz the class for which to create a logger - * @return a logger for the hidden category ("_" + fully-qualified class name) + * @return a Log with the category {@code "_" + fully-qualified class name} */ public static Log getHiddenLog(Class clazz) { - return LogFactory.getLog("_" + clazz.getName()); + return getHiddenLog(clazz.getName()); + } + + /** + * Create a "hidden" logger with a category name prefixed with "_", thus + * precluding it from being enabled together with other log categories from + * the same package. This is useful for specialized output that is either + * too verbose or otherwise optional or unnecessary to see all the time. + * @param category the log category to use + * @return a Log with the category {@code "_" + category} + * @since 5.3.5 + */ + public static Log getHiddenLog(String category) { + return LogFactory.getLog("_" + category); } } diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/support/RouterFunctionMapping.java b/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/support/RouterFunctionMapping.java index 5d25ee817e..e9f78b2956 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/support/RouterFunctionMapping.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/support/RouterFunctionMapping.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -128,12 +128,15 @@ public class RouterFunctionMapping extends AbstractHandlerMapping implements Ini } private void logRouterFunctions(List> routerFunctions) { - if (logger.isDebugEnabled()) { + if (mappingsLogger.isDebugEnabled()) { + routerFunctions.forEach(function -> mappingsLogger.debug("Mapped " + function)); + } + else if (logger.isDebugEnabled()) { int total = routerFunctions.size(); String message = total + " RouterFunction(s) in " + formatMappingName(); if (logger.isTraceEnabled()) { if (total > 0) { - routerFunctions.forEach(routerFunction -> logger.trace("Mapped " + routerFunction)); + routerFunctions.forEach(function -> logger.trace("Mapped " + function)); } else { logger.trace(message); diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/handler/AbstractHandlerMapping.java b/spring-webflux/src/main/java/org/springframework/web/reactive/handler/AbstractHandlerMapping.java index 4fea378fe9..9176b731aa 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/handler/AbstractHandlerMapping.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/handler/AbstractHandlerMapping.java @@ -18,11 +18,13 @@ package org.springframework.web.reactive.handler; import java.util.Map; +import org.apache.commons.logging.Log; import reactor.core.publisher.Mono; import org.springframework.beans.factory.BeanNameAware; import org.springframework.context.support.ApplicationObjectSupport; import org.springframework.core.Ordered; +import org.springframework.core.log.LogDelegateFactory; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.lang.Nullable; import org.springframework.util.Assert; @@ -51,6 +53,10 @@ public abstract class AbstractHandlerMapping extends ApplicationObjectSupport private static final WebHandler NO_OP_HANDLER = exchange -> Mono.empty(); + /** Dedicated "hidden" logger for request mappings. */ + protected final Log mappingsLogger = + LogDelegateFactory.getHiddenLog(HandlerMapping.class.getName() + ".Mappings"); + private final PathPatternParser patternParser; diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/handler/SimpleUrlHandlerMapping.java b/spring-webflux/src/main/java/org/springframework/web/reactive/handler/SimpleUrlHandlerMapping.java index 430681f85b..966b316455 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/handler/SimpleUrlHandlerMapping.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/handler/SimpleUrlHandlerMapping.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2021 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -158,9 +158,16 @@ public class SimpleUrlHandlerMapping extends AbstractUrlHandlerMapping { } registerHandler(url, handler); } - if (logger.isDebugEnabled()) { - logger.debug("Patterns " + getHandlerMap().keySet() + " in " + formatMappingName()); - } + logMappings(); + } + } + + private void logMappings() { + if (mappingsLogger.isDebugEnabled()) { + mappingsLogger.debug(formatMappingName() + " " + getHandlerMap()); + } + else if (logger.isDebugEnabled()) { + logger.debug("Patterns " + getHandlerMap().keySet() + " in " + formatMappingName()); } } diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/resource/ResourceWebHandler.java b/spring-webflux/src/main/java/org/springframework/web/reactive/resource/ResourceWebHandler.java index 8b58e163fb..be4edf688c 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/resource/ResourceWebHandler.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/resource/ResourceWebHandler.java @@ -619,7 +619,9 @@ public class ResourceWebHandler implements WebHandler, InitializingBean { return this.locationValues.stream().collect(Collectors.joining("\", \"", "[\"", "\"]")); } else if (!this.locations.isEmpty()) { - return "[" + this.locations + "]"; + return "[" + this.locations.toString() + .replaceAll("class path resource", "Classpath") + .replaceAll("ServletContext resource", "ServletContext") + "]"; } return Collections.emptyList(); } diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/AbstractHandlerMethodMapping.java b/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/AbstractHandlerMethodMapping.java index e5a8e98ff1..d28af9d89f 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/AbstractHandlerMethodMapping.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/AbstractHandlerMethodMapping.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -211,6 +211,9 @@ public abstract class AbstractHandlerMethodMapping extends AbstractHandlerMap if (logger.isTraceEnabled()) { logger.trace(formatMappings(userType, methods)); } + else if (mappingsLogger.isDebugEnabled()) { + mappingsLogger.debug(formatMappings(userType, methods)); + } methods.forEach((method, mapping) -> { Method invocableMethod = AopUtils.selectInvocableMethod(method, userType); registerHandlerMethod(handler, invocableMethod, mapping); diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/function/support/RouterFunctionMapping.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/function/support/RouterFunctionMapping.java index 040679b595..ebaae4460d 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/function/support/RouterFunctionMapping.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/function/support/RouterFunctionMapping.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -153,14 +153,31 @@ public class RouterFunctionMapping extends AbstractHandlerMapping implements Ini (this.detectHandlerFunctionsInAncestorContexts ? BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, RouterFunction.class) : applicationContext.getBeansOfType(RouterFunction.class)); - List routerFunctions = new ArrayList<>(beans.values()); - if (!CollectionUtils.isEmpty(routerFunctions) && logger.isInfoEnabled()) { - routerFunctions.forEach(routerFunction -> logger.info("Mapped " + routerFunction)); + this.routerFunction = routerFunctions.stream().reduce(RouterFunction::andOther).orElse(null); + logRouterFunctions(routerFunctions); + } + + @SuppressWarnings("rawtypes") + private void logRouterFunctions(List routerFunctions) { + if (mappingsLogger.isDebugEnabled()) { + routerFunctions.forEach(function -> mappingsLogger.debug("Mapped " + function)); + } + else if (logger.isDebugEnabled()) { + int total = routerFunctions.size(); + String message = total + " RouterFunction(s) in " + formatMappingName(); + if (logger.isTraceEnabled()) { + if (total > 0) { + routerFunctions.forEach(function -> logger.trace("Mapped " + function)); + } + else { + logger.trace(message); + } + } + else if (total > 0) { + logger.debug(message); + } } - this.routerFunction = routerFunctions.stream() - .reduce(RouterFunction::andOther) - .orElse(null); } /** diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractDetectingUrlHandlerMapping.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractDetectingUrlHandlerMapping.java index a254fff84d..a5f70384fb 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractDetectingUrlHandlerMapping.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractDetectingUrlHandlerMapping.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2021 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -82,7 +82,10 @@ public abstract class AbstractDetectingUrlHandlerMapping extends AbstractUrlHand } } - if ((logger.isDebugEnabled() && !getHandlerMap().isEmpty()) || logger.isTraceEnabled()) { + if (mappingsLogger.isDebugEnabled()) { + mappingsLogger.debug(formatMappingName() + " " + getHandlerMap()); + } + else if ((logger.isDebugEnabled() && !getHandlerMap().isEmpty()) || logger.isTraceEnabled()) { logger.debug("Detected " + getHandlerMap().size() + " mappings in " + formatMappingName()); } } diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractHandlerMapping.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractHandlerMapping.java index a749d2f99a..30cc87453e 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractHandlerMapping.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractHandlerMapping.java @@ -26,10 +26,13 @@ import javax.servlet.DispatcherType; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.apache.commons.logging.Log; + import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanFactoryUtils; import org.springframework.beans.factory.BeanNameAware; import org.springframework.core.Ordered; +import org.springframework.core.log.LogDelegateFactory; import org.springframework.http.server.RequestPath; import org.springframework.lang.Nullable; import org.springframework.util.AntPathMatcher; @@ -75,6 +78,11 @@ import org.springframework.web.util.pattern.PathPatternParser; public abstract class AbstractHandlerMapping extends WebApplicationObjectSupport implements HandlerMapping, Ordered, BeanNameAware { + /** Dedicated "hidden" logger for request mappings. */ + protected final Log mappingsLogger = + LogDelegateFactory.getHiddenLog(HandlerMapping.class.getName() + ".Mappings"); + + @Nullable private Object defaultHandler; @@ -358,7 +366,7 @@ public abstract class AbstractHandlerMapping extends WebApplicationObjectSupport } protected String formatMappingName() { - return this.beanName != null ? "'" + this.beanName + "'" : ""; + return this.beanName != null ? "'" + this.beanName + "'" : getClass().getName(); } diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractHandlerMethodMapping.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractHandlerMethodMapping.java index e346db9f53..e0ca4380b3 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractHandlerMethodMapping.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractHandlerMethodMapping.java @@ -290,6 +290,9 @@ public abstract class AbstractHandlerMethodMapping extends AbstractHandlerMap if (logger.isTraceEnabled()) { logger.trace(formatMappings(userType, methods)); } + else if (mappingsLogger.isDebugEnabled()) { + mappingsLogger.debug(formatMappings(userType, methods)); + } methods.forEach((method, mapping) -> { Method invocableMethod = AopUtils.selectInvocableMethod(method, userType); registerHandlerMethod(handler, invocableMethod, mapping); diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractUrlHandlerMapping.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractUrlHandlerMapping.java index 589c3aecd5..2f7be313ca 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractUrlHandlerMapping.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractUrlHandlerMapping.java @@ -206,7 +206,7 @@ public abstract class AbstractUrlHandlerMapping extends AbstractHandlerMapping i if (matches.size() > 1) { matches.sort(PathPattern.SPECIFICITY_COMPARATOR); if (logger.isTraceEnabled()) { - logger.debug("Matching patterns " + matches); + logger.trace("Matching patterns " + matches); } } PathPattern pattern = matches.get(0); diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/SimpleUrlHandlerMapping.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/SimpleUrlHandlerMapping.java index b39b46ecb6..8e37bbf337 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/SimpleUrlHandlerMapping.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/SimpleUrlHandlerMapping.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2021 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -161,17 +161,31 @@ public class SimpleUrlHandlerMapping extends AbstractUrlHandlerMapping { } registerHandler(url, handler); }); - if (logger.isDebugEnabled()) { - List patterns = new ArrayList<>(); - if (getRootHandler() != null) { - patterns.add("/"); - } - if (getDefaultHandler() != null) { - patterns.add("/**"); - } - patterns.addAll(getHandlerMap().keySet()); - logger.debug("Patterns " + patterns + " in " + formatMappingName()); + logMappings(); + } + } + + private void logMappings() { + if (mappingsLogger.isDebugEnabled()) { + Map map = new LinkedHashMap<>(getHandlerMap()); + if (getRootHandler() != null) { + map.put("/", getRootHandler()); } + if (getDefaultHandler() != null) { + map.put("/**", getDefaultHandler()); + } + mappingsLogger.debug(formatMappingName() + " " + map); + } + else if (logger.isDebugEnabled()) { + List patterns = new ArrayList<>(); + if (getRootHandler() != null) { + patterns.add("/"); + } + if (getDefaultHandler() != null) { + patterns.add("/**"); + } + patterns.addAll(getHandlerMap().keySet()); + logger.debug("Patterns " + patterns + " in " + formatMappingName()); } } diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/resource/ResourceHttpRequestHandler.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/resource/ResourceHttpRequestHandler.java index 260b443863..ed49cf3cd2 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/resource/ResourceHttpRequestHandler.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/resource/ResourceHttpRequestHandler.java @@ -800,6 +800,10 @@ public class ResourceHttpRequestHandler extends WebContentGenerator @Override public String toString() { - return "ResourceHttpRequestHandler " + getLocations(); + return "ResourceHttpRequestHandler " + + getLocations().toString() + .replaceAll("class path resource", "Classpath") + .replaceAll("ServletContext resource", "ServletContext"); } + }