spring boot 對於jsp支持的限制
對於jsp的支持,Spring Boot官方只支持了war的打包方式,不支持fat jar。參考官方文檔: https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-developing-web-applications.html#boot-features-jsp-limitations
這裡spring boot官方說是tomcat的問題,實際上是spring boot自己改變了打包格式引起的。參考之前的文章://www.VeVB.COm/article/141479.htm
原來的結構之下,tomcat是可以掃描到fat jar裡的META-INF/resources目錄下面的資源的。在增加了BOOT-INF/classes之後,則tomcat掃描不到了。
那麼怎麼解決這個問題呢?下面給出一種方案,來實現對spring boot fat jar/exploded directory的jsp的支持。
個性化配置tomcat,把BOOT-INF/classes 加入tomcat的ResourceSet
在tomcat裡,所有掃描到的資源都會放到所謂的ResourceSet裡。比如servlet 3規範裡的應用jar包的META-INF/resources就是一個ResourceSet 。
現在需要想辦法把spring boot打出來的fat jar的BOOT-INF/classes目錄加到ResourceSet裡。
下面通過實現tomcat的LifecycleListener接口,在Lifecycle.CONFIGURE_START_EVENT事件裡,獲取到BOOT-INF/classes的URL,再把這個URL加入到WebResourceSet裡。
/** * Add main class fat jar/exploded directory into tomcat ResourceSet. * * @author hengyunabc 2017-07-29 * */public class StaticResourceConfigurer implements LifecycleListener { private final Context context; StaticResourceConfigurer(Context context) { this.context = context; } @Override public void lifecycleEvent(LifecycleEvent event) { if (event.getType().equals(Lifecycle.CONFIGURE_START_EVENT)) { URL location = this.getClass().getProtectionDomain().getCodeSource().getLocation(); if (ResourceUtils.isFileURL(location)) { // when run as exploded directory String rootFile = location.getFile(); if (rootFile.endsWith("/BOOT-INF/classes/")) { rootFile = rootFile.substring(0, rootFile.length() - "/BOOT-INF/classes/".length() + 1); } if (!new File(rootFile, "META-INF" + File.separator + "resources").isDirectory()) { return; } try { location = new File(rootFile).toURI().toURL(); } catch (MalformedURLException e) { throw new IllegalStateException("Can not add tomcat resources", e); } } String locationStr = location.toString(); if (locationStr.endsWith("/BOOT-INF/classes!/")) { // when run as fat jar locationStr = locationStr.substring(0, locationStr.length() - "/BOOT-INF/classes!/".length() + 1); try { location = new URL(locationStr); } catch (MalformedURLException e) { throw new IllegalStateException("Can not add tomcat resources", e); } } this.context.getResources().createWebResourceSet(ResourceSetType.RESOURCE_JAR, "/", location, "/META-INF/resources"); } }}為了讓spring boot embedded tomcat加載這個StaticResourceConfigurer,還需要一個EmbeddedServletContainerCustomizer的配置:
@Configuration@ConditionalOnProperty(name = "tomcat.staticResourceCustomizer.enabled", matchIfMissing = true)public class TomcatConfiguration { @Bean public EmbeddedServletContainerCustomizer staticResourceCustomizer() { return new EmbeddedServletContainerCustomizer() { @Override public void customize(ConfigurableEmbeddedServletContainer container) { if (container instanceof TomcatEmbeddedServletContainerFactory) { ((TomcatEmbeddedServletContainerFactory) container) .addContextCustomizers(new TomcatContextCustomizer() { @Override public void customize(Context context) { context.addLifecycleListener(new StaticResourceConfigurer(context)); } }); } } }; }}這樣子的話,spring boot就可以支持fat jar裡的jsp資源了。
demo地址: https://github.com/hengyunabc/spring-boot-fat-jar-jsp-sample
總結
BOOT-INF/classesStaticResourceConfigurer把fat jar裡的/BOOT-INF/classes加到tomcat的ResourceSet來解決問題以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持武林網。