Servlet and path parameters like /xyz/{value}/test, how to map in web.xml?
Asked Answered
J

7

40

Does servlet support urls as follows:

/xyz/{value}/test

where value could be replaced by text or number.

How to map that in the web.xml?

Jeana answered 3/1, 2012 at 16:40 Comment(1)
Related to: stackoverflow.com/questions/8252442/… (possible duplicate).Pirbhai
M
54

Your best bet is the URL pattern /xyz/*.

The Servlet API doesn't support to have the URL pattern wildcard * in the middle of the mapping such as /xyz/*/test nor URI templates. It only allows the wildcard * in the end of the mapping like so /prefix/* or in the start of the mapping like so *.suffix.

You can extract the path information using HttpServletRequest#getPathInfo(). Here's a basic kickoff example how to extract the path information, null and array index out of bounds checks omitted for brevity:

@WebServlet("/xyz/*")
public class XyzServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String pathInfo = request.getPathInfo(); // /{value}/test
        String[] pathParts = pathInfo.split("/");
        String value = pathParts[1]; // {value}
        String action = pathParts[2]; // test
        
        if ("test".equals(action)) {
            // ...
        }
    }
}

If you want to be able to use URI templates nonetheless, and this is actually intended to be a REST endpoint rather than a HTML page, then take a look at Jakarta REST (JAX-RS):

@Path("/xyz/{value}/test")
public class XyzResource {

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public String getTest(@PathParam("value") String value) {
        // ...
    }
}

If you want more finer grained control liks as possible with Apache HTTPD's mod_rewrite, then you could look at Tuckey's URL rewrite filter or homegrow your own URL rewrite filter.

Moffatt answered 3/1, 2012 at 16:46 Comment(6)
Is this really the way one needs to extract url parameters which are not GET-parameters? This seems quite bloated, hard to maintain, prone to offset-bugs and 1995 in general.Avelar
@Herbert: just use a framework on top of Servlet API which supports path parameters, such as JAX-RS or MVC.Moffatt
Another option is getRequestURI(), in my case getPathInfo() was empty.Provincial
@leventunver: it will be empty in a filter, or when a badly implemented request wrapper is being used somewhere in the request, or due to a bug in the servletcontainer.Moffatt
I modified a class that extends GenericFilterBean. Uses ServletRequest as input.Provincial
@leventunver: well, a filter is clearly not a servlet.Moffatt
P
10

As others have indicated, the servlet specification does not allow such patterns; however, you might consider JAX-RS which does allow such patterns, if this is appropriate for your use case.

@Path("/xyz/{value}/test")
public class User { 

    public String doSomething(@PathParam("value") final String value) { ... }

}

Or:

@Path("/xyz/{value}")
public class User { 

    @Path("test")
    public String doTest(@PathParam("value") final String value) { ... }

}

(Related to: https://mcmap.net/q/18117/-servlet-mappings-with-variables-tomcat-7-0.)

Pirbhai answered 3/1, 2012 at 19:53 Comment(0)
G
3

It does support mapping that url; but doesn't offer any validation.

In your web xml, you could do this....

/xyz/*

But that won't guarantee that the trailing test is present and that it is the last item. If you're looking for something more sophisticated, you should try urlrewritefilter.

http://code.google.com/p/urlrewritefilter/

Gangue answered 3/1, 2012 at 16:46 Comment(0)
H
1

You shouldn't be doing that in web.xml rather you can point every request to your filter (Patternfilter) and can check for URL

package com.inventwheel.filter;

import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;

/**
 * Servlet Filter implementation class PatternFilter
 */
@WebFilter("/*")
public class PatternFilter implements Filter {

    /**
     * Default constructor. 
     */
    public PatternFilter() {
        // TODO Auto-generated constructor stub
    }

    /**
     * @see Filter#destroy()
     */
    public void destroy() {
        // TODO Auto-generated method stub
    }

    /**
     * @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
     */
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
            String servletPath = ((HttpServletRequest)request).getServletPath();
            String requestURI = ((HttpServletRequest)request).getRequestURI();
            Pattern pattern = Pattern.compile(".*"+servletPath+"/(.*)");
            Matcher matcher = pattern.matcher(requestURI);
            if (matcher.matches())
            {
            String param = matcher.group(1);
            // do stuff with param here..
            }

        chain.doFilter(request, response);
    }

    /**
     * @see Filter#init(FilterConfig)
     */
    public void init(FilterConfig fConfig) throws ServletException {
        // TODO Auto-generated method stub
    }

}
Hornswoggle answered 3/1, 2012 at 17:55 Comment(0)
A
1

No Servlet doesn't support patterns like that, possible approach as mentioned by other folks as well is to use /* after xyz but that doesn't check for {value} or /test. Better you go for Spring or JAX-RS. However if you plan to stick with Servlet a better way to write it:

@WebServlet(urlPatterns = {"/xyz/*"})

Andres answered 25/8, 2020 at 20:20 Comment(0)
P
0

As stated above, base servlets does not support patterns like you specified in your question. Spring MVC does support patterns. Here is a link to the pertinent section in the Spring Reference Document.

Preparator answered 3/1, 2012 at 16:58 Comment(0)
P
0

An answer from the year 2022.

  1. Servlets do still not allow wildcards, so we can't do things like:
    /xyz/{value}/test

  2. Paul Tuckeys urlrewritefilter is still in version 4.0.3, and not compatible with the new jakarta namespace [1] (Version 5 is in development).

I found a solution in Tomcat itself, with its feature RewriteValve.
See https://rmannibucau.metawerx.net/post/tomcat-rewrite-url for a step-by-step manual. This is a convenient solution for allowing wildcards in the middle of a URL.

[1] https://github.com/paultuckey/urlrewritefilter/issues/239

Prudish answered 24/3, 2022 at 20:41 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.