Post/Put/Delete http Json with additional paramete

2019-03-16 21:00发布

问题:

For some reason, I haven't found any normal way to do the following:

I want to Post a json object, and add additional parameters to the call (in this case, an authentication token). This is a simple RESTful server in myUrl/server, which should give access to different resources of a "person" in the url myUrl/server/person/personCode/resourceName.

GET is easy, and requires no object, only parameters. The problem arrises when I get to POST - how do I attach the JSON, and keep the other parameters as well?

The class (much has been removed for clarity and proprietary reasons...):

//Handles the person's resources
@Path("/person/{personCode}/{resourceName}")
public class PersonResourceProvider {

@GET
@Produces("application/json")
public String getPersonResource(@PathParam("personCode") String personCode, @PathParam("resourceName") String resourceName, @DefaultValue("") @QueryParam("auth_token") String auth_token) throws UnhandledResourceException, UnauthorizedAccessException {

    //Authenticates the user in some way, throwing an exception when needed...
    authenticate(personCode, auth_token, resourceName);

    //Returns the resource somehow...
}

@POST
@Produces("application/json")
public String postPersonResource(@PathParam("personCode") String personCode, @PathParam("resourceName") String resourceName, @DefaultValue("") @QueryParam("resourceData") String resourceData, @DefaultValue("") @QueryParam("auth_token") String auth_token) throws UnhandledResourceException, UnauthorizedAccessException {

    //Again, authenticating
    authenticate(personCode, auth_token, resourceName);

    //Post the given resource
    }
}

Now, the GET method works perfectly, when you go to myUrl/person/personCode/resourceName, it gives me the correct resource. The auth_token is used with every single call to the server (for now, authentication is done by comparing with a predefined string), so it's needed. All the other parameters are provided through the path, except for the authentication token, which should not be in the path as it does not relate to the identity of the required resource.

When I get to POST, it's a problem. I know there's a way to tell the method it consumes a JSON, but in that case, what will happen to the other parameters (auth_token is one of them)? Should I use Multipart?

Another related question, this is the first time I've designed such a server, is this design correct?

Thanks!

回答1:

I am not sure I understand what you are trying to achieve. Let me try explain a few things - hope it will be relevant to your question: @QueryParam injects parameters which are part of your path - i.e. the part of the URL that goes after "?". E.g. if you have a URL like this: http://yourserver.com/person/personCode/resourceName?resourceData=abc&token=1234

Then there would be 2 query params - one named resourceData with value "abc" and the other one named token with value "1234".

If you are passing an entity in the POST request, and that entity is of application/json type, you can simply annotate your post method using @Consumes("application/json") annotation and add another parameter to your method, which does not need to be annotated at all. That parameter can be either a String (in that case Jersey would pass a raw JSON string and you would have to parse it yourself) or it can be a java bean annotated with @XmlRootElement annotation - in that case (if you also include jersey-json module on your classpath) Jersey will try to unmarshall the json string into that object using JAXB. You can also use Jackson or Jettison libraries to do that - see this section of Jersey User Guide for more info: http://jersey.java.net/nonav/documentation/latest/json.html



回答2:

Found!

Client side:

Client c = Client.create();
WebResource service = c.resource("www.yourserver.com/");
String s = service.path("test/personCode/resourceName")
                .queryParam("auth_token", "auth")
                .type("text/plain")
                .post(String.class, jsonString);

Server side:

import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.WebResource;

@Path("/test/{personCode}/{resourceName}")
public class TestResourceProvider {

@POST
@Consumes("text/plain")
@Produces("application/json")
public String postUserResource(String jsonString,                                              
                               @PathParam("personCode") String personCode,                                                                                      
                               @PathParam("resourceName") String resourceName,                                                   
                               @QueryParam("auth_token") String auth_token)                                                  
                               throws UnhandledResourceException {

    //Do whatever...    

    }
}

In my case, I will parse the json I get in the server depending on the resource name, but you can also pass the object itself, and make the server consume an "application/json".