在进行日常网页开发的时候,不可避免的会用到CharacterEncodingFilter,此拦截器用于解决网页开发中的编码问题。
在SpringBoot开发中HttpEncodingAutoConfiguration就成为不得不学的一个自动配置类
配置类声明
打开该自动配置类可以看到该类上加的注解
1 2 3 4 5 6 7 8 9 10 11 12
| @Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties(HttpProperties.class)
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
@ConditionalOnClass(CharacterEncodingFilter.class)
@ConditionalOnProperty(prefix = "spring.http.encoding", value = "enabled", matchIfMissing = true) public class HttpEncodingAutoConfiguration { }
|
然后就可以看到以下代码
1 2 3 4 5 6 7 8 9 10 11 12 13
| @Bean
@ConditionalOnMissingBean public CharacterEncodingFilter characterEncodingFilter() { CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter(); filter.setEncoding(this.properties.getCharset().name()); filter.setForceRequestEncoding(this.properties.shouldForce(Type.REQUEST)); filter.setForceResponseEncoding(this.properties.shouldForce(Type.RESPONSE)); return filter; }
|
想必有人跟我一样会想到,我们在进行Spring开发时,在web.xml中有这么一段配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| //filter声明 <filter> <filter-name>encodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <async-supported>true</async-supported> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> </filter> //指定拦截器拦截请求地址 <filter-mapping> <filter-name>encodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
|
如果是我们自定义的Filter,可以手动指定拦截请求url(在另一篇文章中有介绍如何自定义),那SpringBoot中这些是如何指定的呢?
配置类如何生效
接着往下看
首先在项目启动时从启动类入口,很容易找到以下一段代码(为了方便删除了部分代码)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public ConfigurableApplicationContext run(String... args) { StopWatch stopWatch = new StopWatch(); stopWatch.start(); ConfigurableApplicationContext context = null; Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>(); configureHeadlessProperty(); SpringApplicationRunListeners listeners = getRunListeners(args); listeners.starting(); context = createApplicationContext(); refreshContext(context); afterRefresh(context, applicationArguments); stopWatch.stop();
return context; }
|
接着往下能看到以下代码
1 2 3 4 5 6
| protected void refresh(ApplicationContext applicationContext) { Assert.isInstanceOf(AbstractApplicationContext.class, applicationContext); ((AbstractApplicationContext) applicationContext).refresh(); }
|
即以下代码
1 2 3 4 5 6 7 8 9 10 11
| @Override public final void refresh() throws BeansException, IllegalStateException { try { super.refresh(); } catch (RuntimeException ex) { stopAndReleaseWebServer(); throw ex; } }
|
最终执行代码 部分加了中文注释,其他的暂时没细看就没加—AbstractApplicationContext
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { prepareRefresh(); ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
prepareBeanFactory(beanFactory);
try {
onRefresh();
registerListeners(); } } }
|
这是进入ServletWebServerApplicationContext
看到这段代码,马上就接近真相了
此源码为了容易理解 我稍加修改
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| protected void onRefresh() { super.onRefresh(); try { createWebServer(); WebServer webServer = this.webServer; ServletContext servletContext = getServletContext(); if (webServer == null && servletContext == null) { ServletWebServerFactory factory = getWebServerFactory(); this.webServer = factory.getWebServer(getSelfInitializer()); } else if (servletContext != null) { try { getSelfInitializer().onStartup(servletContext); } catch (ServletException ex) { throw new ApplicationContextException("Cannot initialize servlet context", ex); } } --------------------------------------------------------------------- } catch (Throwable ex) { throw new ApplicationContextException("Unable to start web server", ex); } }
|
就是这个方法getSelfInitializer,接着会看到这段代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
| private org.springframework.boot.web.servlet.ServletContextInitializer getSelfInitializer() { return this::selfInitialize; }
private void selfInitialize(ServletContext servletContext) throws ServletException { prepareWebApplicationContext(servletContext); registerApplicationScope(servletContext); WebApplicationContextUtils.registerEnvironmentBeans(getBeanFactory(), servletContext); for (ServletContextInitializer beans : getServletContextInitializerBeans()) { beans.onStartup(servletContext); } }
protected Collection<ServletContextInitializer> getServletContextInitializerBeans() { return new ServletContextInitializerBeans(getBeanFactory()); }
public ServletContextInitializerBeans(ListableBeanFactory beanFactory, Class<? extends ServletContextInitializer>... initializerTypes) { this.initializers = new LinkedMultiValueMap<>(); this.initializerTypes = (initializerTypes.length != 0) ? Arrays.asList(initializerTypes) : Collections.singletonList(ServletContextInitializer.class); addServletContextInitializerBeans(beanFactory); addAdaptableBeans(beanFactory); List<ServletContextInitializer> sortedInitializers = this.initializers.values().stream() .flatMap((value) -> value.stream().sorted(AnnotationAwareOrderComparator.INSTANCE)) .collect(Collectors.toList()); this.sortedList = Collections.unmodifiableList(sortedInitializers); logMappings(this.initializers); }
private void addServletContextInitializerBeans(ListableBeanFactory beanFactory) { for (Class<? extends ServletContextInitializer> initializerType : this.initializerTypes) { for (Entry<String, ? extends ServletContextInitializer> initializerBean : getOrderedBeansOfType(beanFactory, initializerType)) { addServletContextInitializerBean(initializerBean.getKey(), initializerBean.getValue(), beanFactory); } } }
protected void addAdaptableBeans(ListableBeanFactory beanFactory) { MultipartConfigElement multipartConfig = getMultipartConfig(beanFactory); addAsRegistrationBean(beanFactory, Servlet.class, new ServletRegistrationBeanAdapter(multipartConfig)); private static final String[] DEFAULT_URL_MAPPINGS = { "/*" }; addAsRegistrationBean(beanFactory, Filter.class, new FilterRegistrationBeanAdapter()); for (Class<?> listenerType : ServletListenerRegistrationBean.getSupportedTypes()) { addAsRegistrationBean(beanFactory, EventListener.class, (Class<EventListener>) listenerType, new ServletListenerRegistrationBeanAdapter()); } }
|
至此 结束。