使用spring boot和embedded tomcat开发时出现404找不到jsp问题的处理

2017/06/06 20:16:17 No Comments

初使用spring boot时,出现程序中配置了相应的指向地址,但前端界面始终报找不到jsp界面的404错误.但相同的程序在另一位同事时却正常工作.因此,有必要从源码角度分析一下,spring boot如何和embedded tomcat进行相应的整合.

本文开发时使用的为idea,相应的jsp放置在标准的src/main/webapp目录下,并且spring mvc也配置了 spring.mvc.view.prefix各项网上都能找到的配置信息.

首先是先将一个最简单的jsp文件放置在src/main/webapp,然后启动程序,直接访问此jsp(不通过mvc跳转), 仍然返回404.这就表示实际上这个src/main/webapp并没有被spring boot中tomcat所识别. 一般认为这个目录就是一个放置资源信息的地址目录,那么这里404表示在启动过程中,这个目录并没有被正常找到.

因为spring boot并没有一个显示配置项来配置此位置(从hello的demo来看),因此此地址的查找为一个简单的逻辑过程.从tomcat的角度来看,这属于一个documentRoot,即项目文件根目录,从尝试从整个源码中搜索有关于documentRoot,或者说对于tomcat一个上下文来讲为docBase的概念.最终找到的位置为 TomcatEmbeddedServletContainerFactory#prepareContext 方法.

简单的代码来看,主要的代码如下所示:

		File docBase = getValidDocumentRoot();
		docBase = (docBase != null ? docBase : createTempDir("tomcat-docbase"));
		context.setDocBase(docBase.getAbsolutePath());

这里尝试找到documentRoot,如果没找到就使用临时目录,并设置相应的docBase.那么继续查看如何来找到documentRoot处理.代码如下所示:

		//1 获取显式设置的根目录
		//默认情况下,在整个spring boot中,无其它地方会调用setDocumentRoot方法
		File file = getDocumentRoot();
		// If document root not explicitly set see if we are running from a war archive
		//2 如果没有,如果当前运行环境为一个war包,则认为就是当前war目录
		//即当前jar包是放到一个xx.war中的
		file = file != null ? file : getWarFileDocumentRoot();
		// If not a war archive maybe it is an exploded war
		//3 如果仍没有,那么如果当前运行环境在一个有 WEB-INF的路径下,则认为是一个目录结构形式的web项目
		// 即当前jar包放到一个目录下,此目录是类似xxx/WEB-INF/xxx的类似结构,如常规的xx/WEB-INF/lib/spring.jar这样的结构
		file = file != null ? file : getExplodedWarFileDocumentRoot();
		// Or maybe there is a document root in a well-known location
		//4 尝试探测一些常见的目录,如果找到就认为是相应的位置
		file = file != null ? file : getCommonDocumentRoot();
		......
		return file;

从上面的代码来看,只能是第4点找到相应的目录,此代码如下:

		//COMMON_DOC_ROOTS = { "src/main/webapp", "public","static" };
		for (String commonDocRoot : COMMON_DOC_ROOTS) {
			File root = new File(commonDocRoot);
			if (root.exists() && root.isDirectory()) {
				return root.getAbsoluteFile();
			}
		}
		return null;

这里,是通过获取一个文件夹对象,并判断文件夹是否存在来决定是否找到位置.那么按理在程序中的src/main/webapp是满足第1个条件的,但这里并不满足,惟一的可能性就是因为这里的file对象是相对路径,其的地址与我们的地址不匹配. 在断点情况下,可通过file.getAbsoluteFile来查看其具体位置.

那么,java相对文件的位置是如何确定,这就涉及到java命令工作目录的概念.在System.getProperties存在属性名为user.dir的属性,此值就是命令的工作目录.在程序中所有的相对文件均以此目录作为基准地址.

在idea中,可以通过run configurations进行相应的调整,在配置working directory中可以设置.在此程序中,我们需要将其调整为程序目录(如果为程序目录\target,则需要调整过来).

重新调整之后,再次运行,则相应的jsp则会被找到. 直接输入jsp,默认应该输出相应的内容,如果直接出现下载框,即jsp没有被解析,则检查 org.apache.tomcat.embed:tomcat-embed-jasper 在pom.xml有没有被引入.此依赖包作于处理jsp.

后注:

在上文中的第1步中的documentRoot,在spring boot中,可以通过编写一个EmbeddedServletContainerCustomizer来动态指定,如下参考所示:

@Component
public class DocumentDirectoryCustomizer implements EmbeddedServletContainerCustomizer {
    public void customize(ConfigurableEmbeddedServletContainer container) {
        container.setDocumentRoot(new File("你想指定的位置"));
    }
}

只需要将其设置为一个spring bean即可

转载请标明出处:i flym
本文地址:https://www.iflym.com/index.php/java-programe/201706060001.html

相关文章:

留下足迹