@Configuration
public class DebugConfig {
@Autowired
private ServletWebServerApplicationContext servletWebServerApplicationContext;
@PostConstruct
public void listServletFilters() {
Map<String, ? extends FilterRegistration> filterRegistrations = servletWebServerApplicationContext.getServletContext().getFilterRegistrations();
for (Map.Entry<String, ? extends FilterRegistration> entry : filterRegistrations.entrySet()) {
System.out.println("Filter name: " + entry.getKey() + ", Filter class: " + entry.getValue().getClassName());
}
}
}
Spring Boot를 이용해 애플리케이션을 실행하면 다음과 같은 기본 필터를 볼 수 있다.
- OrderedRequestContextFilter
- WsFilter
- OrderedCharacterEncodingFilter
- OrderedFormContentFilter
public class OrderedRequestContextFilter extends RequestContextFilter implements OrderedFilter { }
public class RequestContextFilter extends OncePerRequestFilter {
...
public void setThreadContextInheritable(boolean threadContextInheritable) {
this.threadContextInheritable = threadContextInheritable;
}
protected void doFilterInternal(
HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
ServletRequestAttributes attributes = new ServletRequestAttributes(request, response);
initContextHolders(request, attributes);
try {
filterChain.doFilter(request, response);
}
finally {
resetContextHolders();
if (logger.isTraceEnabled()) {
logger.trace("Cleared thread-bound request context: " + request);
}
attributes.requestCompleted();
}
}
private void initContextHolders(HttpServletRequest request, ServletRequestAttributes requestAttributes) {
LocaleContextHolder.setLocale(request.getLocale(), this.threadContextInheritable);
RequestContextHolder.setRequestAttributes(requestAttributes, this.threadContextInheritable);
if (logger.isTraceEnabled()) {
logger.trace("Bound request context to thread: " + request);
}
}
...
}
public class InheritableThreadLocal<T> extends ThreadLocal<T> {
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
// This filter only needs to handle WebSocket upgrade requests
if (!sc.areEndpointsRegistered() || !UpgradeUtil.isWebSocketUpgradeRequest(request, response)) {
chain.doFilter(request, response);
return;
}
// HTTP request with an upgrade header for WebSocket present
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse resp = (HttpServletResponse) response;
// Check to see if this WebSocket implementation has a matching mapping
String path;
String pathInfo = req.getPathInfo();
if (pathInfo == null) {
path = req.getServletPath();
} else {
path = req.getServletPath() + pathInfo;
}
WsMappingResult mappingResult = sc.findMapping(path);
if (mappingResult == null) {
// No endpoint registered for the requested path. Let the
// application handle it (it might redirect or forward for example)
chain.doFilter(request, response);
return;
}
UpgradeUtil.doUpgrade(sc, req, resp, mappingResult.getConfig(), mappingResult.getPathParams());
}
}
public class WsFilter extends GenericFilter {
...
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
// This filter only needs to handle WebSocket upgrade requests
if (!sc.areEndpointsRegistered() || !UpgradeUtil.isWebSocketUpgradeRequest(request, response)) {
chain.doFilter(request, response);
return;
}
// HTTP request with an upgrade header for WebSocket present
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse resp = (HttpServletResponse) response;
// Check to see if this WebSocket implementation has a matching mapping
String path;
String pathInfo = req.getPathInfo();
if (pathInfo == null) {
path = req.getServletPath();
} else {
path = req.getServletPath() + pathInfo;
}
WsMappingResult mappingResult = sc.findMapping(path);
if (mappingResult == null) {
// No endpoint registered for the requested path. Let the
// application handle it (it might redirect or forward for example)
chain.doFilter(request, response);
return;
}
UpgradeUtil.doUpgrade(sc, req, resp, mappingResult.getConfig(), mappingResult.getPathParams());
}
}
public class OrderedCharacterEncodingFilter extends CharacterEncodingFilter implements OrderedFilter { }
public class CharacterEncodingFilter extends OncePerRequestFilter {
...
@Override
protected void doFilterInternal(
HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
String encoding = getEncoding();
if (encoding != null) {
if (isForceRequestEncoding() || request.getCharacterEncoding() == null) {
request.setCharacterEncoding(encoding);
}
if (isForceResponseEncoding()) {
response.setCharacterEncoding(encoding);
}
}
filterChain.doFilter(request, response);
}
}
public class OrderedFormContentFilter extends FormContentFilter implements OrderedFilter {}
public class FormContentFilter extends OncePerRequestFilter {
public class FormContentFilter extends OncePerRequestFilter {
private static final List<String> HTTP_METHODS = Arrays.asList("PUT", "PATCH", "DELETE");
...
@Override
protected void doFilterInternal(
HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
MultiValueMap<String, String> params = parseIfNecessary(request);
if (!CollectionUtils.isEmpty(params)) {
filterChain.doFilter(new FormContentRequestWrapper(request, params), response);
}
else {
filterChain.doFilter(request, response);
}
}
}
private boolean shouldParse(HttpServletRequest request) {
String contentType = request.getContentType();
String method = request.getMethod();
if (StringUtils.hasLength(contentType) && HTTP_METHODS.contains(method)) {
try {
MediaType mediaType = MediaType.parseMediaType(contentType);
return MediaType.APPLICATION_FORM_URLENCODED.includes(mediaType);
}
catch (IllegalArgumentException ex) {
}
}
return false;
}
public class FilterChainProxy extends GenericFilterBean {
...
public FilterChainProxy(SecurityFilterChain chain) {
this(Arrays.asList(chain));
}
...
}
public class DelegatingFilterProxyRegistrationBean extends AbstractFilterRegistrationBean<DelegatingFilterProxy> implements ApplicationContextAware {}
public abstract class AbstractFilterRegistrationBean<T extends Filter> extends DynamicRegistrationBean<Dynamic> {}
public class DelegatingFilterProxy extends GenericFilterBean {]