如何在REST API中解析请求参数(查询和路径参数)和同一POJO中的请求正文

编程入门 行业动态 更新时间:2024-10-27 00:30:51
本文介绍了如何在REST API中解析请求参数(查询和路径参数)和同一POJO中的请求正文的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

我有一个rest API(PUT动词),它可以接受请求正文和路径参数:

I have a rest API (PUT verb) which accepts both request body and path params:

例如:

curl --data {a:1,b:2} -X PUT" example /users/ {username}/address/{addressname}"

curl --data {a:1, b:2} -X PUT "example/users/{username}/address/{addressname}"

我正在尝试在一个POJO中同时获取请求正文和路径参数

I am trying to fetch both request body and path param in one 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. 如何在同一类中解析请求正文和参数?

But I am getting value of user.a as null. How to parse both request body and param in same class?

推荐答案

您可以使用自定义注释和InjectionResolver进行此操作. InjectionResolver的作用是允许您使用自己的注释创建自定义注入点.所以你可以做类似的事情

You can do this with a custom annotation and an InjectionResolver. What the InjectionResolver does is allow you to create a custom injection point with your own annotation. So you could do something like

public class Users { @PathParam(username) private String userName; @Body private String a; }

实现InjectionResolver时,您将使用ContainerRequest#readEntity(Class)方法从ContainerRequest中获取实际主体.您可以通过对Field进行一些反射来确定要通过的Class,您可以在InjectionResolver内部获得该反射.以下是使用 Jersey测试框架的完整示例.像其他任何JUnit测试一样运行它.

When implementing the InjectionResolver, you would grab the actual body from the ContainerRequest using the ContainerRequest#readEntity(Class) method. You would determine the Class to pass by doing some reflection on the Field that you can obtain inside the InjectionResolver. Below is a complete example using Jersey Test Framework. Run it like any other JUnit test.

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; } } }

更多推荐

如何在REST API中解析请求参数(查询和路径参数)和同一POJO中的请求正文

本文发布于:2023-10-29 09:35:11,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1539353.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:参数   路径   如何在   正文   REST

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!