为什么我的 EL 语句只在我不通过 src 引用导入 js.file 的脚本标签中工作?
Why is my EL-statement only working in a script-tag where I do not import a js.file through a src-reference?
我有一个 javascript 文件,我在其中收集了需要在我的 Web 应用程序的所有页面上可用的登录和其他用户配置文件 ajax 调用。
对于我所有的 ajax 调用,我需要 webapp 的上下文路径才能获得正确的 URL。 baseUrl 变量可以定义为 var baseUrl = "${pageContext.request.contextPath}";
.
不过我遇到了一个令人费解的错误。如果我尝试在我的 login.js
文件中初始化 baseUrl 变量,它不起作用。它只是设置为字符串值 "${pageContext.request.contextPath}"
这个 .js 文件包含我实际需要变量的所有脚本。但是,如果我在 .jsp 文件本身的无源脚本标签内定义它,它就像一个魅力。 (代码在底部)
我猜测这与表达式编译的时间和范围有关 and/or 执行,也可能与代码的动态和静态导入之间的区别有关。我只是无法完全理解正在发生的事情,以及为什么我想要的方法(在 login.js
文件中定义变量)不起作用。
工作导入语句:
<script>var baseUrl = "${pageContext.request.contextPath}";</script>
<script src="<c:url value="/js/login.js"/>" type="text/javascript"></script>
EL 表达式仅由具有此功能的 servlet 求值。此类 servlet 的示例有 JSP's JspServlet
and JSF's FacesServlet
。一个能够计算模板文本中的 ${...}
,另一个能够计算模板文本中的 ${...}
和 #{...}
。容器的默认 servlet 负责静态资源,如 *.js
文件。
鉴于您正在使用 JSP,只需告诉您的网络应用程序使用 JspServlet
来处理任何 *.js
请求。容器的内置 JspServlet
通常有一个默认的 servlet 名称 jsp
(至少,对于 Tomcat 和克隆是这样),所以你的 webapp 的 web.xml
中的下面条目应该做为了让 EL 在 *.js
文件中进行评估。
<servlet-mapping>
<servlet-name>jsp</servlet-name>
<url-pattern>*.js</url-pattern>
</servlet-mapping>
不过这有一个小警告。一些容器强行将内容类型 header 更改为 text/html
而不管 js
文件扩展名,然后浏览器在下载 JS 文件时感到困惑。防止这种情况的一种方法是在 JS 文件顶部以 JSP 方式显式设置所需的内容类型 header:
<%@page contentType="application/javascript" %>
一个完全不同的替代方法是将上下文路径打印为 <html>
标记的 HTML5 数据属性。
<!DOCTYPE html>
<html lang="en" data-baseuri="${pageContext.request.contextPath}/">
...
</html>
然后它就可以在 JS 中的任何地方使用,如下所示:
var baseuri = document.documentElement.dataset.baseuri;
或者如果您是 jQuery 粉丝:
var baseuri = $("html").data("baseuri");
我有一个 javascript 文件,我在其中收集了需要在我的 Web 应用程序的所有页面上可用的登录和其他用户配置文件 ajax 调用。
对于我所有的 ajax 调用,我需要 webapp 的上下文路径才能获得正确的 URL。 baseUrl 变量可以定义为 var baseUrl = "${pageContext.request.contextPath}";
.
不过我遇到了一个令人费解的错误。如果我尝试在我的 login.js
文件中初始化 baseUrl 变量,它不起作用。它只是设置为字符串值 "${pageContext.request.contextPath}"
这个 .js 文件包含我实际需要变量的所有脚本。但是,如果我在 .jsp 文件本身的无源脚本标签内定义它,它就像一个魅力。 (代码在底部)
我猜测这与表达式编译的时间和范围有关 and/or 执行,也可能与代码的动态和静态导入之间的区别有关。我只是无法完全理解正在发生的事情,以及为什么我想要的方法(在 login.js
文件中定义变量)不起作用。
工作导入语句:
<script>var baseUrl = "${pageContext.request.contextPath}";</script>
<script src="<c:url value="/js/login.js"/>" type="text/javascript"></script>
EL 表达式仅由具有此功能的 servlet 求值。此类 servlet 的示例有 JSP's JspServlet
and JSF's FacesServlet
。一个能够计算模板文本中的 ${...}
,另一个能够计算模板文本中的 ${...}
和 #{...}
。容器的默认 servlet 负责静态资源,如 *.js
文件。
鉴于您正在使用 JSP,只需告诉您的网络应用程序使用 JspServlet
来处理任何 *.js
请求。容器的内置 JspServlet
通常有一个默认的 servlet 名称 jsp
(至少,对于 Tomcat 和克隆是这样),所以你的 webapp 的 web.xml
中的下面条目应该做为了让 EL 在 *.js
文件中进行评估。
<servlet-mapping>
<servlet-name>jsp</servlet-name>
<url-pattern>*.js</url-pattern>
</servlet-mapping>
不过这有一个小警告。一些容器强行将内容类型 header 更改为 text/html
而不管 js
文件扩展名,然后浏览器在下载 JS 文件时感到困惑。防止这种情况的一种方法是在 JS 文件顶部以 JSP 方式显式设置所需的内容类型 header:
<%@page contentType="application/javascript" %>
一个完全不同的替代方法是将上下文路径打印为 <html>
标记的 HTML5 数据属性。
<!DOCTYPE html>
<html lang="en" data-baseuri="${pageContext.request.contextPath}/">
...
</html>
然后它就可以在 JS 中的任何地方使用,如下所示:
var baseuri = document.documentElement.dataset.baseuri;
或者如果您是 jQuery 粉丝:
var baseuri = $("html").data("baseuri");