簡體   English   中英

如何在REST API中的同一POJO中解析請求參數(查詢和路徑參數)和請求正文

[英]How to parse request parameter (query and path param) and request body in same POJO in REST API

我有一個rest API(PUT動詞),它接受請求正文和路徑參數:

例如:

curl --data {a:1,b:2} -X PUT“ https://example.com/users/ {username} / address / {addressname}”

我試圖在一個POJO中同時獲取請求正文和路徑參數

Response myAPI(@BeanParam Users user){
   system.out.println(user.username);
   system.out.println(user.a);

用戶類

public class Users{

    @PathParam(username)
    private String userName;
    ......

    private String a;
  ......
}

但是我正在將user.a的值設置為null。 如何在同一個類中解析請求正文和參數?

您可以使用自定義注釋和InjectionResolver InjectionResolver作用是允許您使用自己的注釋創建自定義注入點。 所以你可以做類似的事情

public class Users {

    @PathParam(username)
    private String userName;

    @Body
    private String a;
}

在實現InjectionResolver ,您將使用ContainerRequest#readEntity(Class)方法從ContainerRequest獲取實際主體。 您可以通過在InjectionResolver獲得的Field上進行一些反射來確定要傳遞的Class 以下是使用Jersey測試框架的完整示例。 像其他任何JUnit測試一樣運行它。

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Field;

import javax.inject.Inject;
import javax.inject.Singleton;
import javax.ws.rs.BeanParam;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.client.Entity;
import javax.ws.rs.core.Response;

import org.glassfish.hk2.api.Injectee;
import org.glassfish.hk2.api.InjectionResolver;
import org.glassfish.hk2.api.ServiceHandle;
import org.glassfish.hk2.api.TypeLiteral;
import org.glassfish.hk2.utilities.binding.AbstractBinder;
import org.glassfish.jersey.server.ContainerRequest;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.test.JerseyTest;
import org.junit.Test;

/**
 * Only one required dependency to run this test. Note this is using 2.25.1.
 * If you are using 2.26 or later, the implementation will be different,
 * and this will not work. You need to use the Jersey packaged `InjectionResolver`,
 * not the HK2 one. And you will also need to bind that `InjectionResolver`
 * to `GenericType` instead of `TypeLiteral` in the `AbstractBinder#configure()`.
 *
 * <dependency>
 *   <groupId>org.glassfish.jersey.test-framework.providers</groupId>
 *   <artifactId>jersey-test-framework-provider-grizzly2</artifactId>
 *   <version>2.25.1</version>
 *   <scope>test</scope>
 * </dependency>
 */
public class BeanParamTest extends JerseyTest {

    @Path("test")
    @Consumes("application/json")
    @Produces("application/json")
    public static class TestResource {

        @POST
        @Path("{username}")
        public String post(@BeanParam ModelBean bean) {
            return bean.toString();
        }
    }

    @Override
    public ResourceConfig configure() {
        return new ResourceConfig(TestResource.class)
                .register(new AbstractBinder() {
                    @Override
                    protected void configure() {
                        bind(BodyInjectionResolver.class)
                                .to(new TypeLiteral<InjectionResolver<Body>>() {})
                                .in(Singleton.class);
                    }
                });
    }

    @Test
    public void testIt() {
        final Response res = target("test/peeskillet")
                .request()
                .post(Entity.json("{\"foo\":\"bar\"}"));
        System.out.println(res.readEntity(String.class));
    }

    @Retention(RetentionPolicy.RUNTIME)
    @Target({ElementType.FIELD})
    public @interface Body {}

    public static class ModelBean {

        @PathParam("username")
        private String username;

        @Body
        private String body;

        public String getUsername() {
            return username;
        }

        public void setUsername(String username) {
            this.username = username;
        }

        public String getBody() {
            return body;
        }

        public void setBody(String body) {
            this.body = body;
        }

        @Override
        public String toString() {
            return "ModelBean{" +
                    "username='" + username + '\'' +
                    ", body='" + body + '\'' +
                    '}';
        }
    }

    public static class BodyInjectionResolver implements InjectionResolver<Body> {

        @Inject
        private javax.inject.Provider<ContainerRequest> requestProvider;

        @Override
        public Object resolve(Injectee injectee, ServiceHandle<?> serviceHandle) {
            if (injectee.getParent().isAnnotationPresent(Body.class)) {
                AnnotatedElement parent = injectee.getParent();
                if (parent instanceof Field) {
                    Class<?> entityType = ((Field) parent).getType();
                    return requestProvider.get().readEntity(entityType);
                }

            }
            return null;
        }

        @Override
        public boolean isConstructorParameterIndicator() {
            return false;
        }

        @Override
        public boolean isMethodParameterIndicator() {
            return false;
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM