(1). 概述
在前面分析了,cas只是简单的创建了一个ClientInfo对象与线程绑定,我们这一篇继续往下分析,在这小篇,主要分析:ThreadContextMDCServletFilter.
(2). 看下ThreadContextMDCServletFilter是在什么时机初始化的
@Configuration(value = "casLoggingConfiguration", proxyBeanMethods = false)
@EnableConfigurationProperties(CasConfigurationProperties.class)
public class CasLoggingConfiguration {
// CasCookieConfiguration配置中:
// TicketGrantingCookieRetrievingCookieGenerator
@Autowired
@Qualifier("ticketGrantingTicketCookieGenerator")
private ObjectProvider<CasCookieBuilder> ticketGrantingTicketCookieGenerator;
// CasCoreTicketsConfiguration配置中:
// DefaultTicketRegistrySupport
@Autowired
@Qualifier("defaultTicketRegistrySupport")
private ObjectProvider<TicketRegistrySupport> ticketRegistrySupport;
// 1. 创建Filter:ThreadContextMDCServletFilter
// cas.logging.mdc-enabled=true
@ConditionalOnBean(value = TicketRegistry.class)
@ConditionalOnProperty(prefix = "cas.logging", name = "mdc-enabled", havingValue = "true", matchIfMissing = true)
@Bean
public FilterRegistrationBean threadContextMDCServletFilter() {
// 2. 创建ThreadContextMDCServletFilter
val filter = new ThreadContextMDCServletFilter(ticketRegistrySupport.getObject(), this.ticketGrantingTicketCookieGenerator.getObject());
// 3. 构建参数
val initParams = new HashMap<String, String>();
val bean = new FilterRegistrationBean<ThreadContextMDCServletFilter>();
bean.setFilter(filter);
bean.setUrlPatterns(CollectionUtils.wrap("/*"));
bean.setInitParameters(initParams);
bean.setName("threadContextMDCServletFilter");
bean.setOrder(Ordered.HIGHEST_PRECEDENCE + 1);
return bean;
} // end threadContextMDCServletFilter
}
(3). ThreadContextMDCServletFilter
package org.apereo.cas.logging.web;
// ***********************************************************************
// ... ...
// ***********************************************************************
import org.slf4j.MDC;
// ... ...
public class ThreadContextMDCServletFilter implements Filter {
//
private final TicketRegistrySupport ticketRegistrySupport;
private final CasCookieBuilder ticketGrantingTicketCookieGenerator;
private static void addContextAttribute(final String attributeName, final Object value) {
val result = Optional.ofNullable(value).map(Object::toString).orElse(null);
if (StringUtils.isNotBlank(result)) {
// ***********************************************************************
// 传递变量到MDC是,可以通过配置日志格式化,打印这些信息
// ***********************************************************************
MDC.put(attributeName, result);
}
}
@Override
public void init(final FilterConfig filterConfig) {
}
@Override
public void doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse,
final FilterChain filterChain) throws IOException, ServletException {
try {
val request = (HttpServletRequest) servletRequest;
addContextAttribute("remoteAddress", request.getRemoteAddr());
addContextAttribute("remoteUser", request.getRemoteUser());
addContextAttribute("serverName", request.getServerName());
addContextAttribute("serverPort", String.valueOf(request.getServerPort()));
addContextAttribute("locale", request.getLocale().getDisplayName());
addContextAttribute("contentType", request.getContentType());
addContextAttribute("contextPath", request.getContextPath());
addContextAttribute("localAddress", request.getLocalAddr());
addContextAttribute("localPort", String.valueOf(request.getLocalPort()));
addContextAttribute("remotePort", String.valueOf(request.getRemotePort()));
addContextAttribute("pathInfo", request.getPathInfo());
addContextAttribute("protocol", request.getProtocol());
addContextAttribute("authType", request.getAuthType());
addContextAttribute("method", request.getMethod());
addContextAttribute("queryString", request.getQueryString());
addContextAttribute("requestUri", request.getRequestURI());
addContextAttribute("scheme", request.getScheme());
addContextAttribute("timezone", TimeZone.getDefault().getDisplayName());
val params = request.getParameterMap();
params.keySet()
.stream()
.filter(k -> !k.equalsIgnoreCase("password"))
.forEach(k -> {
val values = params.get(k);
addContextAttribute(k, Arrays.toString(values));
});
Collections.list(request.getAttributeNames()).forEach(a -> addContextAttribute(a, request.getAttribute(a)));
val requestHeaderNames = request.getHeaderNames();
if (requestHeaderNames != null) {
Collections.list(requestHeaderNames).forEach(h -> addContextAttribute(h, request.getHeader(h)));
}
val cookieValue = this.ticketGrantingTicketCookieGenerator.retrieveCookieValue(request);
if (StringUtils.isNotBlank(cookieValue)) {
val p = this.ticketRegistrySupport.getAuthenticatedPrincipalFrom(cookieValue);
if (p != null) {
addContextAttribute("principal", p.getId());
}
}
filterChain.doFilter(servletRequest, servletResponse);
} finally {
// ***********************************************************************
// 清空上下文
// ***********************************************************************
MDC.clear();
}
}
/**
* Does nothing.
*/
@Override
public void destroy() {
}
}
(4). 总结
ThreadContextMDCServletFilter的职责比较简单,配置一些变量到MDC中,可供我们通过配置日志格式时使用.