Spring-boot UTF-8 resources
java, spring, spring-boot, utf-8
Solution
The Tomcat `DefaultServlet` is enabled by default, but only as a fallback, and I think static resources in the main `ServletContext` root will be handled by Spring's `DispatcherServlet` (with a vanilla Boot app anyway). In the embedded case (like in the guide you quoted) you can add mime mappings explicitly in an initializer callback, e.g.
@Configuration
@EnableAutoConfiguration
public class SampleWebStaticApplication implements EmbeddedServletContainerCustomizer {
@Override
public void customize(ConfigurableEmbeddedServletContainerFactory factory) {
MimeMappings mappings = new MimeMappings(MimeMappings.DEFAULT);
mappings.add("html", "text/html;charset=utf-8");
factory.setMimeMappings(mappings );
}
public static void main(String[] args) throws Exception {
SpringApplication.run(SampleWebStaticApplication.class, args);
}
}
If you need more control you can probably do something at the resource handler level.
Problem
I'm using spring-boot (I'm following this tutorial), the current code is here. My application is configured via `@EnableAutoConfiguration`, so I don't have `web.xml`, or other configuration files. The application has a default handler for `/**`, files from `projectRoot/src/main/webapp/` are served, but unfortunately with `Content-Type: text/html;charset=ISO-8859-1`. I'd like to serve (`html` files) with `UTF-8` charset. The static files are served by spring too, as far as I know: after launching the application, the following line apprears in the log: `Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]` (github.com/spring-projects/spring-boot/blob/master/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/WebMvcAutoConfiguration.java#L182, sorry, I cannot post more than 2 links) Putting `<meta charset="utf-8" />` or `<meta http-equiv="Content-Type: text/html;charset=utf-8" />` into the served `html` file has no effect. How can I serve `*.html` files with `UTF-8` charset? The debug log is the following: ``` . ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v0.5.0.M6) 2013-11-24 00:48:41.327 INFO 15786 --- [ main] hello.Application : Starting Application on ubuntu with PID 15786 (/home/lennon/bme/szoftarch/szoftarch-2013-osz/build/libs/gs-rest-service-0.1.0.jar started by lennon) 2013-11-24 00:48:41.331 DEBUG 15786 --- [ main] o.s.boot.SpringApplication : Loading source class hello.Application 2013-11-24 00:48:41.380 INFO 15786 --- [ main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@7455ffcd: startup date [Sun Nov 24 00:48:41 CET 2013]; root of context hierarchy 2013-11-24 00:48:41.385 DEBUG 15786 --- [ main] ationConfigEmbeddedWebApplicationContext : Bean factory for org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@7455ffcd: org.springframework.beans.factory.support.DefaultListableBeanFactory@54cb8484: defining beans [org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,application]; root of factory hierarchy 2013-11-24 00:48:42.179 DEBUG 15786 --- [ main] ationConfigEmbeddedWebApplicationContext : Using MessageSource [org.springframework.context.support.ResourceBundleMessageSource: basenames=[messages]] 2013-11-24 00:48:42.182 DEBUG 15786 --- [ main] ationConfigEmbeddedWebApplicationContext : Unable to locate ApplicationEventMulticaster with name 'applicationEventMulticaster': using default [org.springframework.context.event.SimpleApplicationEventMulticaster@5d36368] 2013-11-24 00:48:42.518 DEBUG 15786 --- [ main] .t.TomcatEmbeddedServletContainerFactory : Code archive: /home/lennon/bme/szoftarch/szoftarch-2013-osz/build/libs/gs-rest-service-0.1.0.jar 2013-11-24 00:48:42.518 DEBUG 15786 --- [ main] .t.TomcatEmbeddedServletContainerFactory : Code archive: /home/lennon/bme/szoftarch/szoftarch-2013-osz/build/libs/gs-rest-service-0.1.0.jar 2013-11-24 00:48:42.518 DEBUG 15786 --- [ main] .t.TomcatEmbeddedServletContainerFactory : Document root: /home/lennon/bme/szoftarch/szoftarch-2013-osz/src/main/webapp 2013-11-24 00:48:42.904 INFO 15786 --- [ main] o.apache.catalina.core.StandardService : Starting service Tomcat 2013-11-24 00:48:42.905 INFO 15786 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet Engine: Apache Tomcat/7.0.42 2013-11-24 00:48:43.006 INFO 15786 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext 2013-11-24 00:48:43.007 INFO 15786 --- [ost-startStop-1] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 1630 ms 2013-11-24 00:48:43.259 INFO 15786 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring FrameworkServlet 'dispatcherServlet' 2013-11-24 00:48:43.260 INFO 15786 --- [ost-startStop-1] o.s.web.servlet.DispatcherServlet : FrameworkServlet 'dispatcherServlet': initialization started 2013-11-24 00:48:43.428 INFO 15786 --- [ost-startStop-1] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/**/favicon.ico] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler] 2013-11-24 00:48:43.717 INFO 15786 --- [ost-startStop-1] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/greeting],methods=[],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public hello.Greeting hello.GreetingController.greeting(java.lang.String) 2013-11-24 00:48:43.725 INFO 15786 --- [ost-startStop-1] o.s.w.s.c.a.WebMvcConfigurerAdapter : Adding welcome page: jndi:/localhost/index.html 2013-11-24 00:48:43.732 INFO 15786 --- [ost-startStop-1] o.s.w.s.handler.SimpleUrlHandlerMapping : Root mapping to handler of type [class org.springframework.web.servlet.mvc.ParameterizableViewController] 2013-11-24 00:48:43.811 INFO 15786 --- [ost-startStop-1] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler] 2013-11-24 00:48:43.812 INFO 15786 --- [ost-startStop-1] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler] 2013-11-24 00:48:44.489 INFO 15786 --- [ost-startStop-1] o.s.web.servlet.DispatcherServlet : FrameworkServlet 'dispatcherServlet': initialization completed in 1229 ms 2013-11-24 00:48:44.641 DEBUG 15786 --- [ main] ationConfigEmbeddedWebApplicationContext : Unable to locate LifecycleProcessor with name 'lifecycleProcessor': using default [org.springframework.context.support.DefaultLifecycleProcessor@10d6fc05] 2013-11-24 00:48:44.644 DEBUG 15786 --- [ main] nitializer$AutoConfigurationReportLogger : ========================= AUTO-CONFIGURATION REPORT ========================= Positive matches: ----------------- MessageSourceAutoConfiguration - @ConditionalOnMissingBean (types: org.springframework.context.MessageSource; SearchStrategy: all) found no beans (OnBeanCondition) PropertyPlaceholderAutoConfiguration#propertySourcesPlaceholderConfigurer - @ConditionalOnMissingBean (types: org.springframework.context.support.PropertySourcesPlaceholderConfigurer; SearchStrategy: current) found no beans (OnBeanCondition) DispatcherServletAutoConfiguration - found web application StandardServletEnvironment (OnWebApplicationCondition) - @ConditionalOnClass classes found: org.springframework.web.servlet.DispatcherServlet (OnClassCondition) - found web application StandardServletEnvironment (OnWebApplicationCondition) - @ConditionalOnClass classes found: org.springframework.web.servlet.DispatcherServlet (OnClassCondition) - @ConditionalOnBean (types: org.springframework.boot.context.embedded.EmbeddedServletContainerFactory; SearchStrategy: all) found the following [tomcatEmbeddedServletContainerFactory] (OnBeanCondition) DispatcherServletAutoConfiguration#dispatcherServlet - no DispatcherServlet found (DispatcherServletAutoConfiguration.DefaultDispatcherServletCondition) EmbeddedServletContainerAutoConfiguration - found web application StandardServletEnvironment (OnWebApplicationCondition) - found web application StandardServletEnvironment (OnWebApplicationCondition) EmbeddedServletContainerAutoConfiguration.EmbeddedTomcat - @ConditionalOnClass classes found: javax.servlet.Servlet,org.apache.catalina.startup.Tomcat (OnClassCondition) - @ConditionalOnClass classes found: javax.servlet.Servlet,org.apache.catalina.startup.Tomcat (OnClassCondition) - @ConditionalOnMissingBean (types: org.springframework.boot.context.embedded.EmbeddedServletContainerFactory; SearchStrategy: current) found no beans (OnBeanCondition) ServerPropertiesAutoConfiguration#serverProperties - @ConditionalOnMissingBean (types: org.springframework.boot.context.embedded.properties.ServerProperties; SearchStrategy: all) found no beans (OnBeanCondition) WebMvcAutoConfiguration - found web application StandardServletEnvironment (OnWebApplicationCondition) - @ConditionalOnClass classes found: javax.servlet.Servlet,org.springframework.web.servlet.DispatcherServlet,org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter (OnClassCondition) - found web application StandardServletEnvironment (OnWebApplicationCondition) - @ConditionalOnClass classes found: javax.servlet.Servlet,org.springframework.web.servlet.DispatcherServlet,org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter (OnClassCondition) - @ConditionalOnMissingBean (types: org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport; SearchStrategy: all) found no beans (OnBeanCondition) WebMvcAutoConfiguration#hiddenHttpMethodFilter - @ConditionalOnMissingBean (types: org.springframework.web.filter.HiddenHttpMethodFilter; SearchStrategy: all) found no beans (OnBeanCondition) WebMvcAutoConfiguration.WebMvcAutoConfigurationAdapter#defaultViewResolver - @ConditionalOnMissingBean (types: org.springframework.web.servlet.view.InternalResourceViewResolver; SearchStrategy: all) found no beans (OnBeanCondition) Negative matches: ----------------- RabbitAutoConfiguration - required @ConditionalOnClass classes not found: org.springframework.amqp.rabbit.core.RabbitTemplate,com.rabbitmq.client.Channel (OnClassCondition) AopAutoConfiguration - required @ConditionalOnClass classes not found: org.aspectj.lang.annotation.Aspect,org.aspectj.lang.reflect.Advice (OnClassCondition) BatchAutoConfiguration - required @ConditionalOnClass classes not found: org.springframework.batch.core.launch.JobLauncher (OnClassCondition) JpaRepositoriesAutoConfiguration - required @ConditionalOnClass classes not found: org.springframework.data.jpa.repository.JpaRepository (OnClassCondition) MongoRepositoriesAutoConfiguration - required @ConditionalOnClass classes not found: com.mongodb.Mongo,org.springframework.data.mongodb.repository.MongoRepository (OnClassCondition) DataSourceAutoConfiguration - required @ConditionalOnClass classes not found: org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType (OnClassCondition) DataSourceTransactionManagerAutoConfiguration - required @ConditionalOnClass classes not found: org.springframework.jdbc.core.JdbcTemplate,org.springframework.transaction.PlatformTransactionManager (OnClassCondition) JmsTemplateAutoConfiguration - required @ConditionalOnClass classes not found: org.springframework.jms.core.JmsTemplate,javax.jms.ConnectionFactory (OnClassCondition) DeviceResolverAutoConfiguration - required @ConditionalOnClass classes not found: org.springframework.mobile.device.DeviceResolverHandlerInterceptor,org.springframework.mobile.device.DeviceHandlerMethodArgumentResolver (OnClassCondition) HibernateJpaAutoConfiguration - required @ConditionalOnClass classes not found: org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean,org.springframework.transaction.annotation.EnableTransactionManagement,javax.persistence.EntityManager,org.hibernate.ejb.HibernateEntityManager (OnClassCondition) ReactorAutoConfiguration - required @ConditionalOnClass classes not found: reactor.spring.context.config.EnableReactor (OnClassCondition) ThymeleafAutoConfiguration - required @ConditionalOnClass classes not found: org.thymeleaf.spring3.SpringTemplateEngine (OnClassCondition) EmbeddedServletContainerAutoConfiguration.EmbeddedJetty - required @ConditionalOnClass classes not found: org.eclipse.jetty.server.Server,org.eclipse.jetty.util.Loader (OnClassCondition) MultipartAutoConfiguration - @ConditionalOnClass classes found: javax.servlet.Servlet,org.springframework.web.multipart.support.StandardServletMultipartResolver (OnClassCondition) - @ConditionalOnClass classes found: javax.servlet.Servlet,org.springframework.web.multipart.support.StandardServletMultipartResolver (OnClassCondition) - @ConditionalOnBean (types: javax.servlet.MultipartConfigElement; SearchStrategy: all) found no beans (OnBeanCondition) WebMvcAutoConfiguration.WebMvcAutoConfigurationAdapter#beanNameViewResolver - @ConditionalOnBean (types: org.springframework.web.servlet.View; SearchStrategy: all) found no beans (OnBeanCondition) WebMvcAutoConfiguration.WebMvcAutoConfigurationAdapter#viewResolver - @ConditionalOnBean (types: org.springframework.web.servlet.View; SearchStrategy: all) found no beans (OnBeanCondition) WebSocketAutoConfiguration - required @ConditionalOnClass classes not found: org.springframework.web.socket.WebSocketHandler (OnClassCondition) 2013-11-24 00:48:44.650 INFO 15786 --- [ main] hello.Application : Started Application in 4.125 seconds ```