简体   繁体   中英

Concatenate class @Path annotation to method @Path annotation when using colon

I ran into a problem when trying to port our old ERX rest routes to Jerey/JAX-RX.

I am trying to do something like this:

@Path("/v0/user")
@Controller
public class UserRouteController {

    @GET
    public Response getAllUsers(){
    ...
    }

    @GET
    @Path("/{name}")
    public Response getUserWithName(@PathParam("name") String name){
    ...
    }

    @GET
    @Path(":accessibleWithNoRestriction")
    public Response getUsersAccessibleWithNoRestriction(){
        ...
    }

    @GET
    @Path(":withAdminStatus")
    public Response getUsersWithAdminStatus(){
        ...
    }

However, Jersey does not want to match my http request.

blahblah.com/v0/user:accessibleWithNoRestriction

I get a No Method Allowed response.

I normally don't include the leading/trailing / 's in my paths, so I'm pretty sure @Path("rootLevel") and @Path("methodLevel") actually maps to rootLevel/methodLevel not rootLevelMethodLevel .

So in your example, @Path("/v0/user") and @Path(":withAdminStatus") maps to /v0/user/:withAdminStatus . Try changing your paths to something like this:

@Path("v0")
@Controller
public class UserRouteController {
  @GET
  @Path("user")
  public Response getAllUsers(){
    //...
  }

  @GET
  @Path("user/{name}")
  public Response getUserWithName(@PathParam("name") String name){
    //...
  }

  @GET
  @Path("user:accessibleWithNoRestriction")
  public Response getUsersAccessibleWithNoRestriction(){
    //...
  }

  @GET
  @Path("user:withAdminStatus")
  public Response getUsersWithAdminStatus(){
    //...
  }
}

Alternatively, you might be able to pull something off with some kind of redirection. For example, with a Pre-matching Filter . I've never done anything like this, but the documentation suggests that "you can even modify request URI". With that in mind, you could replace any request with :withAdminStatus in the URI with /:withAdminStatus so that it can be matched with the correct resource.

I came across this post: JAX-RS Application on the root context - how can it be done?

Try using this:

@WebFilter(urlPatterns = "/*")
public class PathingFilter implements Filter { 
    Pattern[] restPatterns = new Pattern[] {
        Pattern.compile("/v0/user:.*")
    };

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // TODO Auto-generated method stub
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        if (request instanceof HttpServletRequest) {

            String path = ((HttpServletRequest) request).getPathInfo();

            for (Pattern pattern : restPatterns) {
                if (pattern.matcher(path).matches()) {
                    String[] segments = path.split(":");
                    String newPath = segments[0] + "/" + segments[1];
                    newPath = ((HttpServletRequest) request).getServletPath() + "/" + newPath;
                    request.getRequestDispatcher(newPath).forward(request, response);
                    return;
                }
            }
        }
        chain.doFilter(request, response);
    }

    @Override
    public void destroy() {
        // TODO Auto-generated method stub
    }
}

Then you'll have to change the @Path annotation in your method to "/accessibleWithNoRestriction"

What this would do is change the uri of your request before the matching happens.

Try that

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM