We use the tomcat urlrewrite plugin to rewrite outbound URLs as well as inbound ones. To do this, you need to use the JSTL tag.
This works great for clean urls and i18n, however it yields ugly code, including tags-within-tags, like this:
<link href='<c:url value="/content/bootstrap/css/bootstrap.css" />' rel="stylesheet" />
or:
<a href='<c:url value="/nextPage.jsp"/>' />Next Page</a>
One alternative is to use a variable, like this:
<c:url value="/nextPage.jsp" var="nextPageUrl"/>
<a href='${nextPageUrl}' />Next Page</a>
This is really clean, but verbose.
Is there an expression-language friendly way to do this?
I was sort of hoping for something like:
<a href='${url "/nextPage.jsp}' />Next Page</a>
Thanks.
There is nothing out of the box, but nothing prevents you to write your own EL functions, and thus use something like that:
<a href='${myFn:url("/nextPage.jsp")}' />Next Page</a>
I don't feel that it's more readable than the standard c:url tag, and it would be even worse if it has to accept parameter names and values, though.
See http://docs.oracle.com/javaee/1.4/tutorial/doc/JSPIntro7.html for how to define and use EL functions.
Where are several approaches.
1) Bind base to variable in common fragment:
common.jspf
:
<%@tag language="java" pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<c:url value="/" var="base"/>
or like:
<c:set var="base" value="${pageContext.request.contextPath}"/>
and include fragment in each page:
<%@include file="base.jspf"%>
<script src="${base}/js/jquery.js"></script>
<link href="${base}/css/bootstrap.css" rel="stylesheet" type="text/css">
<a href="${base}/index.html">Home</a>
2) Use ${pageContext.request.contextPath}
everywhere:
<script src="${pageContext.request.contextPath}/js/jquery.js"></script>
<link href="${pageContext.request.contextPath}/css/bootstrap.css" rel="stylesheet" type="text/css">
<a href="${pageContext.request.contextPath}/index.html">Home</a>
3) is my favorite: add filter that include base for attribute:
/src/java/company/project/web/filter/BaseFilter.java
import java.io.IOException;
import javax.servlet.*;
/**
* Make sane JSP, instead of:
* <pre><a href="<c:url value='/my/path/${id}.html'/>">Title</a></pre>
* allow to use:
* <pre><a href="${ctx}/my/path/${id}.html">Title</a></pre>
*/
public class BaseFilter implements Filter {
@Override
public void init(FilterConfig fc) {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
request.setAttribute("base", request.getServletContext().getContextPath());
chain.doFilter(request, response);
}
@Override
public void destroy() { }
}
and register that filter in web.xml
:
<filter>
<filter-name>BaseFilter</filter-name>
<filter-class>company.project.web.filter.BaseFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>BaseFilter</filter-name>
<url-pattern>*.htm</url-pattern>
<url-pattern>*.json</url-pattern>
</filter-mapping>
and use clean syntax (like above but without need to include boilerplate fragments):
<script src="${base}/js/jquery.js"></script>
<link href="${base}/css/bootstrap.css" rel="stylesheet" type="text/css">
<a href="${base}/index.html">Home</a>
NOTE I set additional attributes in that filter, for example to switch between development and minified version of CSS/JS:
private String min;
@Override
public void init(FilterConfig fc) {
min = fc.getServletContext().getInitParameter("min");
if (min == null)
min = fc.getInitParameter("min");
if (min == null)
min = "min";
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
request.setAttribute("ctx", request.getServletContext().getContextPath());
request.setAttribute("min", min);
chain.doFilter(request, response);
}
and corresponding JSP code:
<script src="${base}/js/jquery.${min}.js"></script>
<link href="${base}/css/bootstrap.${min}.css" rel="stylesheet" type="text/css">
Initial parameter min
may set to dev
or min
in externally to WAR file in contex deployment descriptor with fall-back to minified version when not set.
4) Use a scriplets:
<a href="<%=request.getContextPath()%>/index.html">Home</a>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With