深入Spring Boot实现对Fat Jar jsp的支持
spring boot 对于jsp支持的限制
对于jsp的支持,spring boot官方只支持了war的打包方式,不支持fat jar。参考官方文档:
这里spring boot官方说是tomcat的问题,实际上是spring boot自己改变了打包格式引起的。参考之前的文章:
原来的结构之下,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地址:
总结
- spring boot改变了打包结构,导致tomcat没有办法扫描到fat jar里的/
boot-inf/classes
- 通过一个
staticresourceconfigurer
把fat jar里的/boot-inf/classes
加到tomcat的resourceset
来解决问题
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。