深入Spring Boot:实现对Fat Jar jsp的支持

简介: spring boot 对于jsp支持的限制对于jsp的支持,Spring Boot官方只支持了war的打包方式,不支持fat jar。

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

总结

  • spring boot改变了打包结构,导致tomcat没有办法扫描到fat jar里的/BOOT-INF/classes
  • 通过一个StaticResourceConfigurer把fat jar里的/BOOT-INF/classes加到tomcat的ResourceSet来解决问题
相关文章
|
4月前
|
Java Spring
Spring boot 运行服务jar外配置配置文件方式总结
Spring boot 运行服务jar外配置配置文件方式总结
956 0
|
12天前
|
存储 运维 安全
Spring运维之boot项目多环境(yaml 多文件 proerties)及分组管理与开发控制
通过以上措施,可以保证Spring Boot项目的配置管理在专业水准上,并且易于维护和管理,符合搜索引擎收录标准。
24 2
|
1月前
|
SQL JSON Java
mybatis使用三:springboot整合mybatis,使用PageHelper 进行分页操作,并整合swagger2。使用正规的开发模式:定义统一的数据返回格式和请求模块
这篇文章介绍了如何在Spring Boot项目中整合MyBatis和PageHelper进行分页操作,并且集成Swagger2来生成API文档,同时定义了统一的数据返回格式和请求模块。
56 1
mybatis使用三:springboot整合mybatis,使用PageHelper 进行分页操作,并整合swagger2。使用正规的开发模式:定义统一的数据返回格式和请求模块
|
1月前
|
缓存 NoSQL Java
Springboot自定义注解+aop实现redis自动清除缓存功能
通过上述步骤,我们不仅实现了一个高度灵活的缓存管理机制,还保证了代码的整洁与可维护性。自定义注解与AOP的结合,让缓存清除逻辑与业务逻辑分离,便于未来的扩展和修改。这种设计模式非常适合需要频繁更新缓存的应用场景,大大提高了开发效率和系统的响应速度。
64 2
|
3月前
|
XML JSON Java
使用IDEA+Maven搭建整合一个Struts2+Spring4+Hibernate4项目,混合使用传统Xml与@注解,返回JSP视图或JSON数据,快来给你的SSH老项目翻新一下吧
本文介绍了如何使用IntelliJ IDEA和Maven搭建一个整合了Struts2、Spring4、Hibernate4的J2EE项目,并配置了项目目录结构、web.xml、welcome.jsp以及多个JSP页面,用于刷新和学习传统的SSH框架。
92 0
使用IDEA+Maven搭建整合一个Struts2+Spring4+Hibernate4项目,混合使用传统Xml与@注解,返回JSP视图或JSON数据,快来给你的SSH老项目翻新一下吧
|
3月前
|
前端开发 JavaScript Java
【Azure 应用服务】App Service For Windows 中如何设置代理实现前端静态文件和后端Java Spring Boot Jar包
【Azure 应用服务】App Service For Windows 中如何设置代理实现前端静态文件和后端Java Spring Boot Jar包
|
3月前
|
Java Spring
【Azure 应用服务】记一次Azure Spring Cloud 的部署错误 (az spring-cloud app deploy -g dev -s testdemo -n demo -p ./hellospring-0.0.1-SNAPSHOT.jar --->>> Failed to wait for deployment instances to be ready)
【Azure 应用服务】记一次Azure Spring Cloud 的部署错误 (az spring-cloud app deploy -g dev -s testdemo -n demo -p ./hellospring-0.0.1-SNAPSHOT.jar --->>> Failed to wait for deployment instances to be ready)
|
5月前
|
运维 Java 关系型数据库
Spring运维之boot项目bean属性的绑定读取与校验
Spring运维之boot项目bean属性的绑定读取与校验
54 2
|
5月前
|
存储 运维 Java
Spring运维之boot项目开发关键之日志操作以及用文件记录日志
Spring运维之boot项目开发关键之日志操作以及用文件记录日志
66 2
下一篇
无影云桌面