Spring boot restrictions on jsp support
For the support of jsp, Spring Boot only supports the packaging method of war, and does not support fat jar. Refer to the official document: https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-developing-web-applications.html#boot-features-jsp-limitations
Here, spring boot officially says it is a problem with tomcat, but it is actually caused by spring boot itself changing the packaging format. Refer to previous articles: http://www.VeVB.COM/article/141479.htm
Under the original structure, tomcat can scan resources under the META-INF/resources directory in the fat jar. After adding BOOT-INF/classes , tomcat cannot scan.
So how to solve this problem? Here is a solution to achieve support for the JSP of spring boot fat jar/exploded directory.
Personalize tomcat and add BOOT-INF/classes to tomcat's ResourceSet
In tomcat, all scanned resources will be placed in the so-called ResourceSet . For example, META-INF/resources of the application jar package in the servlet 3 specification is a ResourceSet .
Now we need to find a way to add the BOOT-INF/classes directory of the fat jar that is struck by spring boot to ResourceSet .
Next, by implementing the LifecycleListener interface of tomcat, obtain the URL of BOOT-INF/classes in the Lifecycle.CONFIGURE_START_EVENT event, and then add this URL to the 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"); } }}In order to make spring boot embedded tomcat load this StaticResourceConfigurer, an EmbeddedServletContainerCustomizer configuration is also required:
@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)); } }); } } }; }}In this way, spring boot can support jsp resources in fat jar.
demo address: https://github.com/hengyunabc/spring-boot-fat-jar-jsp-sample
Summarize
BOOT-INF/classes in fat jar/BOOT-INF/classes in the fat jar StaticResourceConfigurer ResourceSet of tomcatThe above is all the content of this article. I hope it will be helpful to everyone's learning and I hope everyone will support Wulin.com more.