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本身改变了打包名目引起的。参考之前的文章:http://hengyunabc.github.io/spring-boot-classloader/#spring-boot-1-3-%E5%92%8C-1-4-%E7%89%88%E6%9C%AC%E7%9A%84%E5%8C%BA%E5%88%AB
本来的布局之下,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来办理问题