retrieve JsonObject in POST with jersey

前端 未结 3 1680
我寻月下人不归
我寻月下人不归 2021-01-03 04:50

I have some problems in my application, I send a POST request, but I cannot retrieve the JsonObject in my server, this is the code to send:

String quo = \"{\         


        
3条回答
  •  抹茶落季
    2021-01-03 05:52

    In order to convert JSON to a Java type, there is need to for a MessageBodyReader and a MessageBodyWriter implementation to do the conversion to and from. Since you are using JsonObject which is a GSON type, you can see this implementation. There is a problem with the implementation though, as the readFrom method doesn't compile with Jersey 2. Here is the a fixed version

    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.io.OutputStream;
    import java.io.OutputStreamWriter;
    import java.lang.annotation.Annotation;
    import java.lang.reflect.Type;
    
    import javax.ws.rs.Consumes;
    import javax.ws.rs.Produces;
    import javax.ws.rs.WebApplicationException;
    import javax.ws.rs.core.MediaType;
    import javax.ws.rs.core.MultivaluedMap;
    import javax.ws.rs.ext.MessageBodyReader;
    import javax.ws.rs.ext.MessageBodyWriter;
    import javax.ws.rs.ext.Provider;
    
    import com.google.gson.Gson;
    import com.google.gson.GsonBuilder;
    
    
    @Provider
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.APPLICATION_JSON)
    public final class GsonMessageBodyHandler implements MessageBodyWriter,
            MessageBodyReader {
    
        private static final String UTF_8 = "UTF-8";
    
        private Gson gson;
    
        private Gson getGson() {
            if (gson == null) {
                final GsonBuilder gsonBuilder = new GsonBuilder();
                gson = gsonBuilder.create();
            }
            return gson;
        }
    
        @Override
        public boolean isReadable(Class type, Type genericType,
                java.lang.annotation.Annotation[] annotations, MediaType mediaType) {
            return true;
        }
    
        @Override
        public Object readFrom(Class type, Type type1, Annotation[] antns,
                MediaType mt, MultivaluedMap mm, InputStream in) 
                throws IOException, WebApplicationException {
            InputStreamReader streamReader = new InputStreamReader(in, UTF_8);
            try {
                Type jsonType;
                if (type.equals(type1)) {
                    jsonType = type;
                } else {
                    jsonType = type1;
                }
                return getGson().fromJson(streamReader, jsonType);
            } finally {
                streamReader.close();
            }
        }
    
        @Override
        public boolean isWriteable(Class type, Type genericType, 
                Annotation[] annotations, MediaType mediaType) {
            return true;
        }
    
        @Override
        public long getSize(Object object, Class type, Type genericType, 
                Annotation[] annotations, MediaType mediaType) {
            return -1;
        }
    
        @Override
        public void writeTo(Object object, Class type, Type genericType, 
                Annotation[] annotations, MediaType mediaType, 
                MultivaluedMap httpHeaders, OutputStream entityStream) 
                throws IOException, WebApplicationException {
            OutputStreamWriter writer = new OutputStreamWriter(entityStream, UTF_8);
            try {
                Type jsonType;
                if (type.equals(genericType)) {
                    jsonType = type;
                } else {
                    jsonType = genericType;
                }
                getGson().toJson(object, jsonType, writer);
            } finally {
                writer.close();
            }
        }
    }
    
    
    

    Then we just need to register it with both the client and the application. I'm using a standalone test, where you can see the configuration here

    final ResourceConfig resourceConfig = new ResourceConfig()
            .packages("jersey.stackoverflow.standalone")
            .register(GsonMessageBodyHandler.class);
    ...
    Client c = ClientBuilder.newClient();
    c.register(GsonMessageBodyHandler.class);
    

    Here is the resource class I used for the test

    import com.google.gson.JsonObject;
    import javax.ws.rs.Consumes;
    import javax.ws.rs.POST;
    import javax.ws.rs.Path;
    import javax.ws.rs.Produces;
    import javax.ws.rs.client.Client;
    import javax.ws.rs.client.ClientBuilder;
    import javax.ws.rs.client.Entity;
    import javax.ws.rs.core.MediaType;
    import javax.ws.rs.core.Response;
    import jersey.stackoverflow.standalone.provider.GsonMessageBodyHandler;
    
    @Path("/gson")
    public class GsonResource {
    
        private final Client client;
        private static final String BASE_URI = "http://localhost:8080/api/gson";
    
        public GsonResource() {
            client = ClientBuilder.newClient().register(GsonMessageBodyHandler.class);
        }
    
        @POST
        @Path("/proxy")
        @Consumes(MediaType.APPLICATION_JSON)
        @Produces(MediaType.APPLICATION_JSON)
        public Response proxyPost(JsonObject json) {
            Response response = client.target(BASE_URI)
                    .path("main-resource").request().post(Entity.json(json));
            JsonObject fromMainResource = response.readEntity(JsonObject.class);
            return Response.created(null /* should be a created URI */)
                    .entity(fromMainResource).build();
        }
    
        @POST
        @Path("/main-resource")
        @Consumes(MediaType.APPLICATION_JSON)
        @Produces(MediaType.APPLICATION_JSON)
        public Response mainResource(JsonObject json) {
            return Response.ok(json).build();
        }  
    }
    

    Here's the complete test, which requires this maven dependency

    import com.google.gson.Gson;
    import com.google.gson.GsonBuilder;
    import com.google.gson.JsonObject;
    import com.google.gson.JsonParser;
    import java.net.URI;
    import javax.ws.rs.client.Client;
    import javax.ws.rs.client.ClientBuilder;
    import javax.ws.rs.client.Entity;
    import javax.ws.rs.client.WebTarget;
    import javax.ws.rs.core.Response;
    import static jersey.stackoverflow.standalone.Main.BASE_URI;
    import jersey.stackoverflow.standalone.provider.GsonMessageBodyHandler;
    import org.glassfish.grizzly.http.server.HttpServer;
    import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;
    import org.glassfish.jersey.server.ResourceConfig;
    import org.junit.Test;
    
    public class GsonProviderTest {
    
        public static HttpServer startServer() {
            final ResourceConfig resourceConfig = new ResourceConfig()
                    .packages("jersey.stackoverflow.standalone")
                    .register(GsonMessageBodyHandler.class);
            return GrizzlyHttpServerFactory.createHttpServer(URI.create(BASE_URI), resourceConfig);
        }
    
        public static Client getClient() {
            Client c = ClientBuilder.newClient();
            c.register(GsonMessageBodyHandler.class);
            return c;
        }
    
        @Test
        public void testGetIt() {
            HttpServer server = startServer();
            Client c = getClient();
    
            c.register(GsonMessageBodyHandler.class);
    
            String quo = "{\"network\": {\"label\": \"new net 111\",\"cidr\": \"10.20.105.0/24\"}}";
    
            GsonBuilder builder = new GsonBuilder();
            Gson gson = builder.create();
            JsonParser json = new JsonParser();
            JsonObject jo = (JsonObject) json.parse(quo);
    
            WebTarget target = c.target("http://localhost:8080/api/gson/proxy");
            Response response = target.request().post(Entity.json(jo));
            String responseString = response.readEntity(String.class);
            System.out.println(responseString);
            response.close();
    
            c.close();
            server.stop();
        }
    }
    

    All the test does is send the JsonObject. Though there isn't any visible conversion to JSON, in any of my code, it is happening behind the scenes by the GsonMessageBodyHandler. If you look at the GsonResource class, you can see the methods don't do anything but send out the JsonObject. In the client test, I read the response as a String, and you can see the result the same as what sent out in the initial request.

    • See more about MessageBodyReaders and MessageBodyWriters

    提交回复
    热议问题