2
votes

I would like to have a Servlet handle all requests to JSP pages first. The Servlet will be used to set server side variables depending on the requested JSP.

For example, what I would like to achieve is given the url:example.com/index.jsp, the Servlet first handles the request by parsing out the requested JSP (index.jsp), sets variables that are specific to the requested index.jsp (using request.setAttribute) and then dispatches to the actual index.jsp (eg. /WEB-INF/index.jsp). The JSP will then have the correct variables it needs.

My problem so far is that I'm using "/*" as the mapping pattern for my Servlet. It handles the request, then uses requestDispatcher.forward("/WEB-INF/index.jsp") which ends up in an infinite loop since this matches the "/*" pattern as well.

How should my Servlet(s) handle the requested url? What should the I use as the mapping pattern(s) in web.xml?

Is there a standard setup for this? I'm just looking for a "best practices" way to set up pre-processing for all my JSPs.

1
Actually the forward() call should not run through the pattern match. Can you check if maybe index.jsp forwards back to '/' or something? - John Smith
@kw4nta the WEB-INF/index.jsp doesn't do any forwarding and I don't see anything in web.xml (I removed the welcome file entry as well). Is there somewhere else I should check? - Matthew
@kw4nta: You are wrong. How do you think that the JSPs are otherwise handled by the container's builtin JspServlet which is mapped on *.jsp? Matthew: please don't pay attention to this incorrect statement. It would only confuse you more. - BalusC

1 Answers

1
votes

The /* is in first place a strange choice for a servlet URL pattern. This is normally exclusively to be used by filters. Servlets are by default namely also invoked on forwards and includes, but filters not. Using /* would completely override the container's builtin JspServlet which ought to be invoked on *.jsp during a forward.

Rather use a more specific URL pattern like /pages/*, /app/*, *.do, *.html, etcetera.

When using a prefix servlet mapping, like /pages/* and you would like to hide the extra path from the URL, then you should keep the prefix servlet mapping as is, put all other resources in a common path (usually it are only the static resources like CSS/JS/images) and create an additional filter which checks if it's a resource request and if so, then continue the chain or if not, then forward to the servlet. This does not change the URL. The servlet can in turn just safely forward to the JSP.

Here's an example assuming that your servlet is mapped on /pages/* and that all your (static) resources which should not be handled by the servlet are placed in /resources folder (you can just keep your JSPs in /WEB-INF, that part doesn't need to be changed; the forward wouldn't hit the filter anyway).

HttpServletRequest req = (HttpServletRequest) request;
String path = req.getRequestURI().substring(req.getContextPath().length());

if (path.startsWith("/resources/")) {
    chain.doFilter(request, response);
} else {
    request.getRequestDispatcher("/pages" + path).forward(request, response);
}

Finally just map the above filter on an URL pattern of /*.

See also: