當前位置:
首頁 > 知識 > 深入 Spring Boot :實現對 Fat Jar jsp 的支持

深入 Spring Boot :實現對 Fat Jar jsp 的支持

(點擊

上方公眾號

,可快速關注)




來源:Hengyunabc ,


hengyunabc.github.io/spring-boot-fat-jar-jsp-sample/




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-和-1-4-版本的區別




原來的結構之下,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




總結






  • spring boot改變了打包結構,導致tomcat沒有辦法掃描到fat jar里的/BOOT-INF/classes



  • 通過一個StaticResourceConfigurer把fat jar里的/BOOT-INF/classes加到tomcat的ResourceSet來解決問題




【關於投稿】




如果大家有原創好文投稿,請直接給公號發送留言。




① 留言格式:


【投稿】+《 文章標題》+ 文章鏈接

② 示例:


【投稿】《不要自稱是程序員,我十多年的 IT 職場總結》:http://blog.jobbole.com/94148/

③ 最後請附上您的個人簡介哈~






看完本文有收穫?請轉發分享給更多人


關注「ImportNew」,提升Java技能


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 ImportNew 的精彩文章:

TAG:ImportNew |