摆脱外部JavaScript文件中Web应用程序的上下文路径的硬编码 [英] Get rid of hard-coding the context path of web apps in external JavaScript files

查看:103
本文介绍了摆脱外部JavaScript文件中Web应用程序的上下文路径的硬编码的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有几个WebSockets端点,例如,

I have several WebSockets endpoints such as,

wss://localhost:8181/ContextPath/Push

所有这些端点URL都在单独的外部JavaScript文件中进行硬编码(的.js )。这些JavaScript文件在需要时包含在各自的XHTML文件中。应该以编程方式评估主机名和上下文路径,而不是在需要它们的地方进行硬编码。

All of such endpoint URLs are hard-coded in separate, external JavaScript files (.js). These JavaScript files are included in respective XHTML files as and when required. The host name and the context path should be evaluated programmatically instead of hard-coding all over the place where they are required.

主机名( localhost:8181 )可以使用 document.location.host 在JavaScript中获取,但JavaScript中没有标准/规范方式来获取上下文路径应用程序运行的位置。

The host name (localhost:8181) can be obtained in JavaScript using document.location.host but there is no standard/canonical way in JavaScript to obtain a context path where the application runs.

我正在执行以下操作。

在主模板上声明全局JavaScript变量,如下所示。

A global JavaScript variable is declared on the master template as follows.

<f:view locale="#{bean.locale}" encoding="UTF-8" contentType="text/html">
        <f:loadBundle basename="messages.ResourceBundle" var="messages"/>

        <ui:param name="contextPath" value="#{request.contextPath}"/>
        <ui:insert name="metaData"></ui:insert>

        <h:head>
            <script type="text/javascript">var contextPath = "#{contextPath}";</script>
        </h:head>

        <h:body id="body">

        </h:body>
    </f:view>
</html>

主机名和上下文路径硬编码的JavaScript文件包含在相应的模板中客户或模板北部,南部,东部和西部的任何部分如下。

The JavaScript files in which the host name and the context path are hard-coded are included in respective template clients or any of sections of the template north, south, east and west as follows.

<html lang="#{bean.language}"
      xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://xmlns.jcp.org/jsf/html">

    <h:form>
        <h:outputScript library="default" name="js/websockets.js" target="head"/>
    </h:form>

仅出于观点, websockets.js 看起来如下(你可以简单地忽略它)。

For the sake of viewpoint only, websockets.js looks like the following (you can simply ignore it).

if (window.WebSocket) {
    // The global variable "contextPath" is unavailable here
    // because it is declared afterwards in the generated HTML.
    var ws = new WebSocket("wss://"+document.location.host + contextPath + "/Push");
    ws.onmessage = function (event) {
        // This handler is invoked, when a message is received through a WebSockets channel.
    };

    $(window).on('beforeunload', function () {
        ws.close();
    });
} else {}

现在,全局JavaScript变量 contextPath主模板中声明的预计将在包含的JavaScript文件中提供,即 websockets.js 。然而这是不真实的。

Now, the global JavaScript variable contextPath declared in the master template is expected to be available in the included JavaScript file namely websockets.js. This is however untrue.

所包含的JavaScript文件是 websockets.js 其中全局变量<尝试访问code> contextPath , 之前硬编码< script> 标记在主模板中生成的HTML < head> 标记中。

What happens is that the included JavaScript file namely websockets.js where the global variable contextPath is attempted to be accessed, is placed before the hard-coded <script> tag in the generated HTML <head> tag in the master template.

换句话说,全局JavaScript变量 contextPath 实际上是在声明之前尝试在包含的文件 websockets.js 中使用。

In other words, the global JavaScript variable contextPath is actually attempted to use in the included file websockets.js before being declared.

无论如何,如何摆脱硬编码外部JavaScript文件中的上下文路径?

Anyway, how to get rid of hard-coding the context path in external JavaScript files?

做的唯一目的这与CSS文件不同,EL不在外部JavaScript文件中进行评估。因此,#{} 除非将其置于XHTML文件中,否则无效。

The sole purpose of doing this is that unlike CSS files, EL isn't evaluated in external JavaScript files. Therefore, #{} thing will not work unless it is placed in an XHTML file.

推荐答案


所包含的JavaScript文件名为 websockets.js 其中全局变量<尝试访问code> contextPath , 之前硬编码< script> 主模板中生成的HTML < head> 标记中的标记

What happens is that the included JavaScript file named websockets.js where the global variable contextPath is attempted to be accessed, is placed before the hard-coded <script> tag in the generated HTML <head> tag in the master template

这是出乎意料的。您在< h内声明了< h:outputScript> 引用 websockets.js 文件:body> target =head。这应该在 c>< h:head> 中已经声明的所有其他脚本资源之后结束。另见a.o. 如何在Facelets模板中引用CSS / JS /图像资源?毕竟,这似乎是由捆绑的PrimeFaces引起的 HeadRenderer 有意自动包含一些CSS资源并负责< ; facet name =first | middle | last>

This is unexpected. You declared the <h:outputScript> referring websockets.js file inside <h:body> with target="head". This is supposed to end up after all other script resources already declared in <h:head>. See also a.o. How to reference CSS / JS / image resource in Facelets template? After all, this appears to be caused by PrimeFaces bundled HeadRenderer which is intented to auto-include some CSS resources and take care of the <facet name="first|middle|last">.

这对PF家伙来说是值得的问题报告(如果还没有完成的话) )。同时,最好的办法是通过显式注册JSF实现自己的 HeadRenderer 来关闭它,如下面的 faces-config.xml (假设您使用的是Mojarra)。

This is worth an issue report to PF guys (if not already done). In the meanwhile, your best bet is to turn off it by explicitly registering the JSF implementation's own HeadRenderer back as below in faces-config.xml (provided that you're using Mojarra).

<render-kit>
    <renderer>
        <component-family>javax.faces.Output</component-family>
        <renderer-type>javax.faces.Head</renderer-type>
        <renderer-class>com.sun.faces.renderkit.html_basic.HeadRenderer</renderer-class>
    </renderer>
</render-kit>

明确包含PrimeFaces主题特定的 theme.css 如下所示< h:head>

And explicitly include the PrimeFaces theme-specific theme.css as below in <h:head>:

<h:outputStylesheet library="primefaces-aristo" name="theme.css" />






回到真正的问题,


Coming back to the real question,


无论如何,如何摆脱硬编码外部JavaScript文件中的上下文路径?

将其设置为基本URI(注意:HTML4 / IE6-8不支持相对路径)。

Either set it as base URI (note: relative path isn't supported in HTML4 / IE6-8).

<h:head>
    <base href="#{request.contextPath}/" />
    ...
</h:head>





var baseURI = $("base").attr("href");

或者将其设置为HTML根元素的数据属性。

Or set it as data attribute of HTML root element.

<!DOCTYPE html>
<html lang="en" data-baseuri="#{request.contextPath}/" ...>
    ...
</html>





var baseURI = $("html").data("baseuri");






不相关到具体问题,作为建议,透明地涵盖http + ws和https + wss,考虑使用 location.protocol 而不是硬编码 wss


Unrelated to the concrete problem, as a word of advice, to transparently cover both http+ws and https+wss, consider using location.protocol instead of a hardcoded wss.

var ws = new WebSocket(location.protocol.replace("http", "ws") + "//" + location.host + baseURI + "Push");

这篇关于摆脱外部JavaScript文件中Web应用程序的上下文路径的硬编码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆