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

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自己改变了打包格式引起的。参考之前的文章://www.jb51.net/article/141479.htm

原来的结构之下,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

总结

  1. spring boot改变了打包结构,导致tomcat没有办法扫描到fat jar里的/BOOT-INF/classes
  2. 通过一个StaticResourceConfigurer把fat jar里的/BOOT-INF/classes加到tomcat的ResourceSet来解决问题

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Spring boot 跳转到jsp页面的实现方法

    本人正在学习Spring boot,搜索了很多关于Spring boot 跳转到jsp页面的实现方法介绍,下面我来记录一下,有需要了解的朋友可参考.希望此文章对各位有所帮助. @Controller注解 1.application.properties文件中配置 # 配置jsp文件的位置,默认位置为:src/main/webapp spring.mvc.view.prefix=/pages/ # 配置jsp文件的后缀 spring.mvc.view.suffix=.jsp 2.Controlle

  • SpringBoot创建JSP登录页面功能实例代码

    添加JSP配置 1.pom.xml添加jsp解析引擎 <dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-jasper</artifactId> <scope>provided</scope> </dependency> <dependency> <groupId>javax.s

  • JSP spring boot / cloud 使用filter防止XSS

    JSP spring boot / cloud 使用filter防止XSS 一.前言 XSS(跨站脚本攻击) 跨站脚本攻击(Cross Site Scripting),为不和层叠样式表(Cascading Style Sheets, CSS)的缩写混淆,故将跨站脚本攻击缩写为XSS.恶意攻击者往Web页面里插入恶意Script代码,当用户浏览该页之时,嵌入其中Web里面的Script代码会被执行,从而达到恶意攻击用户的目的. 二.思路 基于filter拦截,将特殊字符替换为html转意字符 (如

  • 详解SpringBoot 添加对JSP的支持(附常见坑点)

    序言: SpringBoot默认不支持JSP,如果想在项目中使用,需要进行相关初始化工作.为了方便大家更好的开发,本案例可直接作为JSP开发的脚手架工程 SpringBoot+War+JSP . 常见问题: 1.修改JSP需重启才能生效: 在生产环境中,SpringBoot重新编译JSP可能会导致较大的性能损失,并且很难追查到问题根源,所以在最新的版本中,官方已经默认关闭此功能,详见JspServlet类的初始化参数.那么,如何解决这个问题呢?推荐两个解决办法:1.使用devtools 2. 添

  • SpringBoot项目如何访问jsp页面的示例代码

    最近在接支付项目,从官方下了个及时到款的demo,想在springBoot项目中运行起来,发现访问jsp的时候直接会访问到jsp页面的源文件. 如何在springBoot项目中访问到jsp页面? 1.添加pom依赖 首先在原来的pom文件基础上加上这两个配置 <!-- tomcat 的支持.--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring

  • spring boot实战之使用JSP的示例

    前后端分离的架构有其优势,但具体情况具体分析,并不是任何时候使用前后端分离架构都是合适的.我最近就体会到其中的坑,因为部门属性的问题,前端项目占比较低,所以公司前端基本上都是新手,结果就是后端接口完成了一个多月,前端还在加班加点的赶.前后端人员的能力和人数与工作量是匹配的,前后端都能hold住时建议使用前后端分离架构,如果前端能力有限或人员较少,那就最好不要采用,这样才能保证项目进度可控. Spring Boot并不建议使用JSP,但是可能有习惯和人员知识面的限制,还是希望使用jsp,则可以根据

  • JSP 开发之Spring Boot 动态创建Bean

    JSP 开发之Spring Boot 动态创建Bean 1.通过注解@Import导入方式创建 a.新建MyImportBeanDefinitionRegistrar注册中心 Java代码 import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.GenericBeanDefinition; import org

  • 详解SpringBoot集成jsp(附源码)+遇到的坑

    本文介绍了SpringBoot集成jsp(附源码)+遇到的坑 ,分享给大家 1.大体步骤 (1)创建Maven web project: (2)在pom.xml文件添加依赖: (3)配置application.properties支持jsp (4)编写测试Controller (5)编写JSP页面 (6)编写启动类App.java 2.新建SpringInitialzr 3.pom文件 <dependencies> <dependency> <groupId>org.s

  • Spring boot 添加jsp支持配置详解

    spring boot添加对jsp的支持,以下是pom.xml文件的配置 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v

  • 详解Spring Boot 添加JSP支持

    大体步骤: (1)创建Maven web project: (2)在pom.xml文件添加依赖: (3)配置application.properties支持jsp (4)编写测试Controller (5)编写JSP页面 (6)编写启动类Application.Java 1,FreeMarker 2,Groovy 3,Thymeleaf (spring 官网使用这个) 4,Velocity 5,JSP (貌似Spring Boot官方不推荐,STS创建的项目会在src/main/resource

随机推荐