为何JavaScript文件无法像JSP一样正确识别Servlet路径?
问题描述
我有一个标注了@WebServlet("/UserServlet")的Servlet,在JSP里用action="UserServlet"能正常访问,但单独的JS文件里用fetch('/UserServlet')却不行。相关文件路径:
- Servlet:
src/main/java/com.name.controller/UserServlet - JSP:
webapp/view/ - JS文件:
webapp/js/
JS里用相对路径请求时,会跳转到localhost:8080/UserServlet,而非预期的localhost:8080/ProjectName/UserServlet,只有写全路径才能正常工作。想知道有没有办法不用全路径,只用Servlet名称就能发起请求?
问题根源
这是因为JSP和JS里的路径解析逻辑不一样:
- JSP中的
action="UserServlet"是相对当前页面的URL路径解析的,比如你的JSP访问地址是http://localhost:8080/ProjectName/user.jsp,浏览器会自动把它解析为http://localhost:8080/ProjectName/UserServlet,刚好匹配Servlet的映射。 - 而JS文件是从
http://localhost:8080/ProjectName/js/xxx.js加载的,JS里的/UserServlet是相对于域名根目录的绝对路径,所以浏览器会直接请求http://localhost:8080/UserServlet,漏掉了项目的上下文路径(也就是/ProjectName)。
解决方案
1. 在JSP中注入上下文路径给JS用
JSP可以通过${pageContext.request.contextPath}获取项目的上下文路径,你可以在JSP页面里定义一个全局变量,然后让JS文件引用这个变量:
在JSP的合适位置(比如<head>里)添加:
<script> // 定义全局变量存储上下文路径 const contextPath = "${pageContext.request.contextPath}"; </script> <!-- 加载你的JS文件 --> <script src="${pageContext.request.contextPath}/js/你的JS文件名.js"></script>
然后在JS文件里拼接路径:
fetch(contextPath + '/UserServlet', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: registrationDataJSON }) .then(response => response.json()) .then(data => { if (data.status === 'success') { // 处理成功逻辑 } else { alert(data.message); } }) .catch(error => { console.error(error); });
2. 纯JS提取上下文路径
如果不想依赖JSP的变量,也可以用JS从当前页面的URL里自动提取上下文路径:
// 提取当前页面的上下文路径 const getContextPath = () => { const pathName = window.location.pathname; // 找到第一个/之后的第二个/的位置 const index = pathName.indexOf('/', 1); // 返回上下文路径,没有的话返回空字符串 return index > 0 ? pathName.substring(0, index) : ''; }; const contextPath = getContextPath(); // 发起请求 fetch(contextPath + '/UserServlet', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: registrationDataJSON }) // 后续处理逻辑...
这种方法不用改JSP,纯JS就能实现,还能兼容项目部署在根路径的情况。
3. 把JS代码内嵌到JSP里
如果这个JS逻辑只在某个JSP页面使用,直接把JS代码写在JSP里就行,这样可以直接用JSP的上下文路径变量:
<script> fetch('${pageContext.request.contextPath}/UserServlet', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: registrationDataJSON }) .then(response => response.json()) .then(data => { // 处理逻辑 }) .catch(error => { console.error(error); }); </script>
这种方法简单直接,但不利于JS代码的复用和维护,适合小范围使用的场景。
内容的提问来源于stack exchange,提问作者ctrlCat
相关产品推荐
相关产品推荐

