У меня есть несколько конечных точек WebSockets, таких как
wss://localhost:8181/ContextPath/Push
Все такие конечные URL-адреса жестко закодированы в отдельных внешних файлах JavaScript (.js
). Эти файлы JavaScript включаются в соответствующие файлы XHTML по мере необходимости. Имя хоста и путь к контексту должны оцениваться программно, а не жестко кодироваться во всем, где они требуются.
Имя хоста (localhost:8181
) можно получить в JavaScript с помощью document.location.host
, но в JavaScript нет стандартного/канонического способа для получения пути к контексту, в котором выполняется приложение.
Я делаю что-то вроде следующего.
Глобальная переменная JavaScript объявляется на основном шаблоне следующим образом.
<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, в которых имя хоста и путь контекста жестко закодированы, включены в соответствующие шаблонные клиенты или любые разделы шаблона на север, юг, восток и запад следующим образом.
<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
выглядит следующим образом (вы можете просто игнорировать его).
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
. Это, однако, неверно.
Что происходит, так это то, что к файлу JavaScript с включенным кодом websockets.js
, к которому была обращена глобальная переменная contextPath
, помещается до жестко закодированный тег <script>
в сгенерированном HTML <head>
в основном шаблоне.
Другими словами, глобальная переменная JavaScript contextPath
фактически пыталась использовать во включенном файле websockets.js
перед объявлением.
В любом случае, как избавиться от жесткого кодирования пути контекста во внешних файлах JavaScript?
Единственная цель этого - в отличие от файлов CSS, EL не оценивается во внешних файлах JavaScript. Поэтому #{}
вещь не будет работать, если она не будет помещена в файл XHTML.