Jersey method selection by query parameters

后端 未结 3 1251
渐次进展
渐次进展 2021-01-23 03:14

I need to implement a webservice that uses the first query parameter to identify the operation, i.e. the client call would be something like: http://localhost:8080/ws/oper

3条回答
  •  自闭症患者
    2021-01-23 03:52

    I think Claudio is correct - you could use Jersey, but you'd be on your own to handle the query parameters since it only matches on the path.

    You could inject a UriInfo and pull the query parameters out of that:

    @Path("/operation") 
    public class Operation {
    
        @Context
        protected UriInfo info;
    
        @GET 
        public String operation() {
            if (info.getQueryParameters().containsKey("create"))
                // do stuff
            else if (info.getQueryParameters().containsKey("info"))
                // other stuff
        } 
    

    }

    You could switch from Jersey to another framework. I believe that Spring can route to multiple methods based on query parameters.

    As you mentioned, perhaps you could write something that is a bit more standard and then remap the requests to that. For example, you could use a Servlet filter or a front end server like Apache httpd or nginx to modify the request.

    Thinking in terms of resources what is it that these operations are acting on? Customer accounts, movies, stock trades, etc. For arguments sake, let's say it's "Foo". You might go with something like this:

    @Path("/foo") 
    public class FooResource {
    
        @Context
        protected UriInfo info;
    
        @GET
        @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
        public Foo getById(@QueryParam("id") int id) {
             // get Foo by id
             Foo = ....
    
             // return an instance of Foo and let Jersey convert it to XML
             // or JSON depending on the "Accept" header that the client sent
             return foo;
        } 
    
        @POST
        @Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
        public Response create(Foo instance)
        {
             // let Jersey deserialize the request body from JSON or XML.
             // save the instance however you want
             int id = fooService.save(instance);
    
             // return a 204 "created" with a "Location" header
             URI location = info.getAbsolutePathBuilder().path("{id}").build(id);
         return Response.created(location).build();
        }
    

    }

    It sounds like your URI structure is mandated by someone else so this might not be an option for you. If you do proceed with the current URI structure, there's one major pitfall that you should be aware of.

    According to the HTTP 1.1 spec, GET requests should be idempotent. It appears that your current design is creating new server side instances with GET requests. There's potential for breakage... intermediate proxies or web browsers could cache responses to your GET requests and prevent new instances from being created.

提交回复
热议问题