ChatGPT解决这个技术问题 Extra ChatGPT

如何以正确的方式从 JavaScript 中获取 contextPath?

使用基于 Java 的后端(即 servlet 和 JSP),如果我需要来自 JavaScript 的 contextPath,那么推荐的模式是什么,为什么?我能想到几种可能性。我有什么遗漏吗?

1. 将 SCRIPT 标签刻录到页面中,并在一些 JavaScript 变量中设置它

<script>var ctx = "<%=request.getContextPath()%>"</script>

这是准确的,但在加载页面时需要执行脚本。

2.在一些隐藏的DOM元素中设置contextPath

<span id="ctx" style="display:none;"><%=request.getContextPath()%></span>

这是准确的,并且在加载页面时不需要执行任何脚本。但是当需要访问 contextPath 时,您确实需要一个 DOM 查询。如果您非常关心性能,则可以缓存 DOM 查询的结果。

<强> 3。尝试通过检查 document.URL 或 BASE 标记在 JavaScript 中找出答案

function() {
    var base = document.getElementsByTagName('base')[0];
    if (base && base.href && (base.href.length > 0)) {
        base = base.href;
    } else {
        base = document.URL;
    }
    return base.substr(0,
        base.indexOf("/", base.indexOf("/", base.indexOf("//") + 2) + 1));
};

这在加载页面时不需要执行任何脚本,如果需要,您还可以缓存结果。但这仅在您知道上下文路径是单个目录时才有效——而不是根目录 (/) 或多个目录 (/mypath/iscomplicated/)。

我向哪个方向倾斜

我更喜欢隐藏的 DOM 元素,因为它不需要在页面加载时执行 JavaScript 代码。只有当我需要 contextPath 时,我才需要执行任何操作(在这种情况下,运行 DOM 查询)。

我一生都无法理解为什么“但在加载页面时需要执行脚本”是一个如此大的问题,以至于您宁愿回退到 DOM 摆弄/遍历。你能详细说明一下吗?另外,你到底需要什么上下文路径?也许还有其他方法可以让您根本不需要它。
加载页面时执行 JavaScript 会阻止并行下载。也许单线没关系。 DOM 遍历可能更具惩罚性,但至少您可以选择延迟惩罚,直到您绝对需要它(如果您需要它)。我不确定按 ID 查找是否会受到惩罚。
我自己不需要 contextPath。我只是提出了一个“如果”。这是一个可能的例子:我正在动态加载一个 JS 文件并且需要知道它的路径。如果我提前知道 contextPath,我可以使用绝对路径,但是如果 contextPath 发生变化,那么我的脚本就会中断。我可以使用相对路径,但这取决于父 HTML 文档的位置。如果我移动文件,我的分页符。了解 contextPath,我可以通过动态生成的绝对路径来保护自己免受这些类型的破坏。
在现代浏览器中,分配一个全局变量基本上是无操作的。我不会单独使用老式的 scriptlets ,而只是使用 EL。 var ctx = '${pageContext.request.contextPath}';
@BalusC 你太棒了。感谢您总是发布您对如何使用 JSP 的了解。另外,我无法让您的建议生效。当我将它放在脚本标签中时,无法识别 EL。当我不把它放在脚本标签中时,错误表示变量定义错误。我该怎么做你上面发布的?

M
Mike M. Lin

根据评论中的讨论(特别是来自 BalusC),可能不值得做比这更复杂的事情:

<script>var ctx = "${pageContext.request.contextPath}"</script>

虽然很乏味,但我总是更喜欢让我的 JavaScript 对象接收一个定义“baseUrl”或上下文的属性。我将在 jsp 中有一个脚本标记来“初始化”页面的 JavaScript 对象,并将 baseUrl 传递给它们。这样我就不必假设某些全局变量是可用的。
@Mike M. Lin,如果我们使用使用 document.url 获取路径的选项,是否有任何陷阱
有人能帮我吗?我在我的 javascript 文件中添加了全局变量,但它返回的是原始字符串“${pageContext.request.contextPath}”,而不是项目的 contextPath。
@FelipeMosso 它进入您的 .jsp 文件,而不是您的 JavaScript 文件。
@MikeM.Lin 谢谢你,我稍后再试.. 标签让我觉得我应该添加到 JavaScript 文件中
C
Cedric Simon

明白了:D

function getContextPath() {
   return window.location.pathname.substring(0, window.location.pathname.indexOf("/",2));
}
alert(getContextPath());

重要说明:仅适用于“根”上下文路径。不适用于“子文件夹”,或者上下文路径中有斜杠(“/”)。


这是最好的答案!它不会将 jsp 与 javascript 定义混合使用
FWIW 如果上下文路径中有斜杠(例如 /foo/bar),则此操作失败。
我看到 window.location.pathname 的值类似于“/context/p1/p2/p3.html”,所以这个建议返回“/context”。但是 Java Web 应用程序可能部署在 ROOT 上下文中,因此路径名的第一个组件不是上下文字符串。我不知道如何使用仅限客户端的脚本来处理这个问题,这是一个问题,因为我没有使用 JSP 或 Servlet。
这不会返回上下文路径。这将返回 URL 的第一个路径名,它不一定是上下文路径。
最近两天我都面临这个问题。最后我找到了这个问题的解决方案。非常感谢@Cedric
佚名

我认为您可以通过将数字 1 与调用数字 3 中的函数相结合来实现您正在寻找的东西。

您不想在页面加载时执行脚本并希望稍后调用函数?很好,只需创建一个函数来返回您在变量中设置的值:

function getContextPath() {
   return "<%=request.getContextPath()%>";
}

它是一个函数,因此在您实际调用它之前不会执行,但它直接返回值,无需进行 DOM 遍历或修改 URL。

在这一点上,我同意@BalusC 使用 EL:

function getContextPath() {
   return "${pageContext.request.contextPath}";
}

或者取决于 JSP 回退到 JSTL 的版本:

function getContextPath() {
   return "<c:out value="${pageContext.request.contextPath}" />";
}

很酷的想法,但这实际上会更多开销。因为现在除了变量赋值之外,我还有一个函数声明。 function getContextPath() {..} 实际上扩展为 window.getContextPath = function() {..}。在这一点上,我同意 BalusC 的观点,即 var ctx = '${pageContext.request.contextPath}'; 之类的东西没有任何问题。它尽可能接近无操作。
A
Armando Cordova

通过此查看解决方案检查此页面的解决方案,制作以下解决方案我希望它有效:示例:

Javascript:

var context = window.location.pathname.substring(0, window.location.pathname.indexOf("/",2)); 
var url =window.location.protocol+"//"+ window.location.host +context+"/bla/bla";

O
Oleg Shavrov

我使用 id="contextPahtHolder" 将上下文路径渲染到链接标签的属性,然后在 JS 代码中获取它。例如:

<html>
    <head>
        <link id="contextPathHolder" data-contextPath="${pageContext.request.contextPath}"/>
    <body>
        <script src="main.js" type="text/javascript"></script>
    </body>
</html>

main.js

var CONTEXT_PATH = $('#contextPathHolder').attr('data-contextPath');
$.get(CONTEXT_PATH + '/action_url', function() {});

如果上下文路径为空(如在嵌入式 servlet 容器中),它将是空字符串。否则它包含 contextPath 字符串


不错的解决方案,在我的 Grails 应用程序和如下 gsp 代码段的情况下对我有用:${request.contextPath}
这项工作为我使用带有百里香叶的 springboot 进行了小修改。在 HTML THEN IN JS var CONTEXT_PATH = $('#contextPathHolder').attr('data-contextPath'); $.get(CONTEXT_PATH + 'action_url', function() {});
M
Michael Hegner

带有 Thymeleaf 解决方案的 Spring Boot 可能如下所示:

假设我的上下文路径是 /app/

在 Thymeleaf 中,您可以通过以下方式获得它:

<script th:inline="javascript">
    /*<![CDATA[*/
        let contextPath    = /*[[@{/}]]*/
    /*]]>*/
</script>