SSM项目改造SpringBoot webapp目录外部化 jsp 404 问题

近期接手一个陈旧的项目基于SSM,SpringMVCSpringMybatis实现的管理项目,没使用依赖管理。

改造目标:SpringBoot + Maven,jar形式打包,非war形式,并且配置文件及webapp目录中的资源要外部化,通过maven-jar-plugin打包的jar为thin jar,jar包内不包含lib依赖及webapp。

改造后通过assembly打包目录结构如下:

SSM项目改造SpringBoot webapp目录外部化 jsp 404 问题_第1张图片

 改造后最大的问题就是webapp外部化jsp资源访问404问题:java -cp 形式启动,通过开启trace日志发现:

2020-08-19 10:43:18 [http-nio-8080-exec-3] DEBUG org.apache.jasper.servlet.JspServlet - JspEngine --> /WEB-INF/views/index.jsp
2020-08-19 10:43:18 [http-nio-8080-exec-3] DEBUG org.apache.jasper.servlet.JspServlet - 	     ServletPath: /WEB-INF/views/index.jsp
2020-08-19 10:43:18 [http-nio-8080-exec-3] DEBUG org.apache.jasper.servlet.JspServlet - 	        PathInfo: null
2020-08-19 10:43:18 [http-nio-8080-exec-3] DEBUG org.apache.jasper.servlet.JspServlet - 	        RealPath: /tmp/tomcat-docbase.11133512333430917306.8080/WEB-INF/views/index.jsp
2020-08-19 10:43:18 [http-nio-8080-exec-3] DEBUG org.apache.jasper.servlet.JspServlet - 	      RequestURI: /WEB-INF/views/index.jsp
2020-08-19 10:43:18 [http-nio-8080-exec-3] DEBUG org.apache.jasper.servlet.JspServlet - 	     QueryString: null

JspServlet 是tomcat-embed-jasper 中的jsp处理类,获取jsp文件是从tomcat的docBase目录,该目录通过debug发现,idea上是使用的本地src/main/webapp下的目录,服务器上是创建的临时目录,而临时目录并不存在webapp目录下的文件,所以访问后导致出现404问题。

debug主要涉及类及方法:


// TomcatEmbeddedServletContainerFactory prepareContext() getValidDocumentRoot() getDocumentRoot()
// AbstractConfigurableEmbeddedServletContainer documentRoot()
// 此方法获取的路径最终被用于docBase实际值
protected final File getValidDocumentRoot() {
		File file = getDocumentRoot();
		// If document root not explicitly set see if we are running from a war archive
		file = file != null ? file : getWarFileDocumentRoot();
		// If not a war archive maybe it is an exploded war
		file = file != null ? file : getExplodedWarFileDocumentRoot();
		// Or maybe there is a document root in a well-known location
		file = file != null ? file : getCommonDocumentRoot();
		if (file == null && this.logger.isDebugEnabled()) {
			this.logger
					.debug("None of the document roots " + Arrays.asList(COMMON_DOC_ROOTS)
							+ " point to a directory and will be ignored.");
		}
		else if (this.logger.isDebugEnabled()) {
			this.logger.debug("Document root: " + file);
		}
		return file;
}

通过spring文档,发现只有server.tomcat.basedir, 并没有地方设置docBase的具体配置,那么只有通过自定义TomcatEmbeddedServletContainerFactory来实现自定义的docBase地址,默认该类在EmbeddedServletContainerAutoConfiguration中实例化,只需要自定义该类覆盖默认配置bean即可。

    @Bean
    public TomcatEmbeddedServletContainerFactory tomcatEmbeddedServletContainerFactory() {
        TomcatEmbeddedServletContainerFactory factory = new TomcatEmbeddedServletContainerFactory();
        log.info("Tomcat Current DocumentRoot => {}", factory.getDocumentRoot());
        factory.addContextCustomizers(context -> {
            log.info("Tomcat Customizer DocBase => {}", context.getDocBase());
            //temp dir if docbase = tomcat-docbase
            // 如果是临时目录,则获取系统变量,设置docBase,系统变量在启动脚本启动时设置
            if (context.getDocBase() != null && context.getDocBase().contains("tomcat-docbase")) {
                String k = "external.webapp";
                String docBase = System.getProperty(k);
                if (docBase != null && docBase.trim().length() > 0) {
                    context.setDocBase(docBase);
                    log.info("Tomcat DocBase Reset => {}", docBase);
                }
            }
        });
        return factory;
    }

修改后再次部署:可以正常找到自定义目录下的jsp文件了

2020-08-19 13:44:40 [http-nio-8080-exec-1] DEBUG org.apache.jasper.servlet.JspServlet - JspEngine --> /WEB-INF/views/index.jsp
2020-08-19 13:44:40 [http-nio-8080-exec-1] DEBUG org.apache.jasper.servlet.JspServlet - 	     ServletPath: /index.jsp
2020-08-19 13:44:40 [http-nio-8080-exec-1] DEBUG org.apache.jasper.servlet.JspServlet - 	        PathInfo: null
2020-08-19 13:44:40 [http-nio-8080-exec-1] DEBUG org.apache.jasper.servlet.JspServlet - 	        RealPath: /home/tomz/demo/webapp/WEB-INF/views/index.jsp
2020-08-19 13:44:40 [http-nio-8080-exec-1] DEBUG org.apache.jasper.servlet.JspServlet - 	      RequestURI: /WEB-INF/views/index.jsp
2020-08-19 13:44:40 [http-nio-8080-exec-1] DEBUG org.apache.jasper.servlet.JspServlet - 	     QueryString: null

 

你可能感兴趣的:(Java,Spring)