如何在不包括上下文根名称的情况下使用相对路径?

80
要使用静态文件(CSS、JS),我必须写绝对路径,例如/AppName/templates/style/main.css。是否有解决方案,使我可以写相对路径,例如style/main.css

2
为什么(以及在哪里)必须写全路径?我能想到的几乎任何地方,style/main.css都应该可以工作。可能有一些地方不行,但是如果你不告诉别人你实际上想做什么,那么帮助你的人会非常随意,很难成功。 - T.J. Crowder
我只想将CSS文件链接到我的JSP页面。我没有写解释,因为这是我能想象到的最简单和唯一的用途,所以我认为每个人都可以猜到。即便如此:我很抱歉。我的错误... - kspacja
6个回答

169
如果你关心的是Web应用程序上下文的动态性(即"AppName"部分),那么只需通过HttpServletRequest#getContextPath()动态检索它即可。
<head>
    <link rel="stylesheet" href="${pageContext.request.contextPath}/templates/style/main.css" />
    <script src="${pageContext.request.contextPath}/templates/js/main.js"></script>
    <script>var base = "${pageContext.request.contextPath}";</script>
</head>
<body>
    <a href="${pageContext.request.contextPath}/pages/foo.jsp">link</a>
</body>

如果您希望为所有相对链接设置基本路径,以便不必在每个相对链接中重复使用${pageContext.request.contextPath},则可以使用<base>标记。这里有一个示例,使用JSTL functions的帮助。
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
...
<head>
    <c:set var="url">${pageContext.request.requestURL}</c:set>
    <base href="${fn:substring(url, 0, fn:length(url) - fn:length(pageContext.request.requestURI))}${pageContext.request.contextPath}/" />
    <link rel="stylesheet" href="templates/style/main.css" />
    <script src="templates/js/main.js"></script>
    <script>var base = document.getElementsByTagName("base")[0].href;</script>
</head>
<body>
    <a href="pages/foo.jsp">link</a>
</body>

这样,每个相对链接(即不以/或方案开头的链接)都将变成相对于<base>。顺便提一下,这与Tomcat无关,只涉及HTTP/HTML基础知识。在任何其他Web服务器中,您都会遇到同样的问题。
另请参见:

1
${pageContext...对我不起作用。只是生成类似localhost:8080/profile/$%7BpageContext.request.context%7D/css/profile/的东西。 - Matt
5
请升级至至少JSP 2.0(发布于十年前),或者使用<c:out>。完全不了解并拥有非常古老的软件并不是一个合理的负评原因。 - BalusC
1
@Vnge:只需让JSP将其打印为JS变量即可吗? - BalusC
谢谢,这很有道理!经过一些搜索,我发现我可以像pageContext一样在${}之间打印变量。 - Vnge
1
@Natix:Break?它被设计为所有相对URL的基本URL。另请参见https://dev59.com/enI-5IYBdhLWcg3wYXL8#1889957。如果不适合您的技术实现,请不要使用它。 - BalusC
显示剩余8条评论

21

使用应用程序上下文相对路径,只需使用 <c:url> 标签即可。

value参数以 / 开头时,标签将把它视为应用程序相关的URL,并将应用程序名称添加到URL中。

例如:

JSP:

<c:url value="/templates/style/main.css" var="mainCssUrl" />`
<link rel="stylesheet" href="${mainCssUrl}" />
...
<c:url value="/home" var="homeUrl" />`
<a href="${homeUrl}">home link</a>

将成为此HTML,带有相对于域名的URL:

<link rel="stylesheet" href="/AppName/templates/style/main.css" />
...
<a href="/AppName/home">home link</a>

3
这可以更简单地完成:
<base href="${pageContext.request.contextPath}/"/>

所有URL都将不含无用的domain:port部分,但会包含应用程序上下文。

2

您可以从某个目录启动Tomcat,该目录是Tomcat的$cwd。您可以指定相对于此$cwd的任何路径。

假设您有

home
- tomcat
 |_bin
- cssStore
 |_file.css

假设您使用命令“bin/startup.sh”从~/tomcat启动Tomcat。
~/tomcat成为Tomcat的主目录($cwd)。
现在,您可以从servlet中的类文件访问“../cssStore/file.css”。
希望这能帮到您,- M.S.

2

我们可以将整个链接修改为以下方式(解决方案涉及jsp文件):

使用JSTL,我们可以这样做: 要链接资源,如css、js:

     <link rel="stylesheet" href="${pageContext.request.contextPath}/style/sample.css" />
     <script src="${pageContext.request.contextPath}/js/sample.js"></script>   

制作链接的方法:

     <a id=".." class=".." href="${pageContext.request.contextPath}/jsp/sample.jsp">....</a>

值得熟悉标签。
   <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>

以下是另一种使用 JSP 方法的实现方式,但上述方法更好:
   <link rel="stylesheet" href="<%=request.getContextPath()%>/style/sample.css" />
   <script type="text/javascript" src="<%=request.getContextPath()%>/js/sample.js"></script>

制作超链接的方法:

   <a id=".." class=".." href="<%=request.getContextPath()%>/jsp/sample.jsp">....</a>

-1
这是我一直在使用的@Ralph建议的衍生版本。将添加到您的JSP页面顶部。
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<c:url value="/" var="root" />

然后在您的页面中只需引用根变量即可:

<link rel="stylesheet" href="${root}templates/style/main.css">

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接