因服务端路径引用问题导致的事故

问题描述

今天在项目中使用JSP包含指令(动态包含)引入一个html页面,打开浏览器测试时,却发现运行到加载的那里直接崩了。
如图:
在这里插入图片描述

目录结构及异常。
在这里插入图片描述
异常详情

08-Apr-2020 21:36:12.201 SEVERE [http-nio-8081-exec-3] org.apache.catalina.core.ApplicationDispatcher.invoke Servlet.service() for servlet [default] threw exception
	java.io.FileNotFoundException: The requested resource [/ee/ee/html/TopPage.html] is not available
		at org.apache.catalina.servlets.DefaultServlet.serveResource(DefaultServlet.java:852)
		at org.apache.catalina.servlets.DefaultServlet.doGet(DefaultServlet.java:504)
		at javax.servlet.http.HttpServlet.service(HttpServlet.java:634)
		at org.apache.catalina.servlets.DefaultServlet.service(DefaultServlet.java:484)
		at javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
		at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
		at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
		at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:728)
		at org.apache.catalina.core.ApplicationDispatcher.doInclude(ApplicationDispatcher.java:591)
		at org.apache.catalina.core.ApplicationDispatcher.include(ApplicationDispatcher.java:527)
		at org.apache.jasper.runtime.JspRuntimeLibrary.include(JspRuntimeLibrary.java:868)
		at org.apache.jsp.index_jsp._jspService(index_jsp.java:138)
		at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
		at javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
		at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:476)
		at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:386)
		at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:330)
		at javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
		at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
		at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
		at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
		at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
		at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
		at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199)
		at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
		at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:528)
		at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
		at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81)
		at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:678)
		at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
		at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
		at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:798)
		at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
		at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:810)
		at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1500)
		at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
		at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
		at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
		at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
		at java.lang.Thread.run(Thread.java:748)
08-Apr-2020 21:36:12.202 SEVERE [http-nio-8081-exec-3] org.apache.catalina.core.StandardWrapperValve.invoke Servlet.service() for servlet [jsp] in context with path [/ee] threw exception
	java.io.IOException: An exception occurred processing [/index.jsp] at line [25]

22: <body>
23:     <div class="container">
24:         <p>${pageContext.request.contextPath}/html/TopPage.html</p>
25:         <jsp:include page="${pageContext.request.contextPath}/html/TopPage.html" flush="true"/>
26: 
27: <%--        <p id="error_msg" class="display-5" style="color: red;">${sessionScope.session_msg}</p>--%>
28: 


Stacktrace:
		at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:504)
		at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:386)
		at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:330)
		at javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
		at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
		at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
		at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
		at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
		at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
		at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199)
		at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
		at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:528)
		at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
		at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81)
		at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:678)
		at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
		at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
		at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:798)
		at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
		at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:810)
		at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1500)
		at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
		at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
		at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
		at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
		at java.lang.Thread.run(Thread.java:748)
	Caused by: java.io.FileNotFoundException: The requested resource [/ee/ee/html/TopPage.html] is not available
		at org.apache.catalina.servlets.DefaultServlet.serveResource(DefaultServlet.java:852)
		at org.apache.catalina.servlets.DefaultServlet.doGet(DefaultServlet.java:504)
		at javax.servlet.http.HttpServlet.service(HttpServlet.java:634)
		at org.apache.catalina.servlets.DefaultServlet.service(DefaultServlet.java:484)
		at javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
		at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
		at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
		at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:728)
		at org.apache.catalina.core.ApplicationDispatcher.doInclude(ApplicationDispatcher.java:591)
		at org.apache.catalina.core.ApplicationDispatcher.include(ApplicationDispatcher.java:527)
		at org.apache.jasper.runtime.JspRuntimeLibrary.include(JspRuntimeLibrary.java:868)
		at org.apache.jsp.index_jsp._jspService(index_jsp.java:138)
		at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
		at javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
		at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:476)
		... 25 more

问题分析

可以清楚的看到所报的异常为文件找不到的异常,所以肯定是路径写错了,而且它还已经把错误的路径打印出来了。可以看到,contextPath重复拼接了。

解决方案

删去我们手动获取的contextPath即可。

思考

既然我们的问题解决了,那么为啥呢?
原来,

  • 在服务器端默认是相对contextPath(一般与项目名一致,但两者概念不同,也可以不同)来解析的。

  • 在浏览器端默认是相对域名(服务器地址)解析的。

添加斜杠/的情况

  • 在服务器端,URL前添加斜杠/代表从contentPath开始。
  • 在浏览器端,URL前添加斜杠/代表从域名(服务器地址)开始。

当然不添加斜杠/就代表从当前文件目录开始。

注意:上文所说的 在服务器或在浏览器 都是指在 服务器或浏览器执行的操作。还有就是服务器端向浏览器发送的重定向与上文所说的不同,重定向是发送什么地址浏览器就转向什么地址,不存在相对路径问题。

总结

所以涉及到浏览器端获取资源的,最好加上contextPath。
如:
在这里插入图片描述

注意:通过${pageContext.request.contextPath}request.getContextPath()获取的contextPath,其前面都默认添加了斜杠/,不要再重复添加斜杠/,不然会直接覆盖掉域名(服务器地址)。

如图:
在这里插入图片描述

补充

我转载的大佬的文章:https://blog.csdn.net/weixin_43670802/article/details/104705147

原文地址:https://www.cnblogs.com/tfxz/p/12701702.html