当前位置: 首页 > 面试题库 >

POST期间在REST Web服务中使用FormParam包含自己的对象(例如实体)的HTTP 400错误

吕晟睿
2023-03-14
问题内容

对于我的REST服务中的订购过程,我必须从客户端到服务器发送“文章”列表。这些商品对象属于自制实体类型。我已经发现发送STRING或INTEGER对象的列表确实可以通过@FormParam发送。

但是,一旦我尝试发送自己的对象列表(甚至只有一个对象),我总是会收到 HTTP 400错误“错误的请求”

我尝试了完全相同的代码,如下所示(仅更改了form.add()的参数和server方法的参数),并且成功地编写了Postet字符串,整数和字符串列表。这只会使发送自己的对象类型产生问题。
记录告诉我未达到服务器方法。这个过程以前被打破了。

我还尝试通过使用代理(Apache
JMeter)来获取请求。它说参数kunde包含值entities.Kunde%40af8358。因此,我猜该对象没有彻底(或根本没有)序列化。但是在响应中将这种对象从服务器发送到客户端可以正常工作-
在这里XML序列化没有问题。

可能是什么原因?是否可能无法通过POST发送自己的类型?
(PS:Kunde示例中的类型是可序列化的,并带有注释@XmlRootElement。)

预先感谢您的帮助!
亚娜

注意 :我正在使用SAP Netweaver AS。但是到目前为止,它的行为与其他所有Java
AS一样,所以我认为这不是原因。其他所有REST操作都可以正常工作,即使没有自己的实体的POST也可以。

另外 :我正在使用JERSEY库。

我在服务器端的代码:

@Path("/test")
    @POST
    @Produces(MediaType.TEXT_XML)
    @Consumes(MediaType.APPLICATION_FORM_URLENCODED)    
    public String test(
        @FormParam("kunde") Kunde kunde) {

        return "The name of the customer is: "
           +kunde.getVorname()+" "+kunde.getNachname();        
    }

我在客户端的代码(该方法在会话Bean中):

public String  test() {

    Kunde kunde = new Kunde();
    kunde.setNachname("Müller");
    kunde.setVorname("Kurt");

    Form form = new Form();
    form.add("kunde", kunde);

    return service
        .path("test")
        .type(MediaType.APPLICATION_FORM_URLENCODED)
        .accept(MediaType.TEXT_XML)
        .post(String.class, form);
}

像这样构建 服务的 地方:

com.sun.jersey.api.client.Client;
com.sun.jersey.api.client.WebResource;
com.sun.jersey.api.client.config.ClientConfig;
com.sun.jersey.api.client.config.DefaultClientConfig;

ClientConfig config = new DefaultClientConfig();
Client client = Client.create(config);
service = client.resource(UriBuilder.fromUri("<service-url>").build());

问题答案:

由于新的信息,即实体“ Kunde”的传输不正确,我找到了一个
解决方案

我明确地将实体类转换为XML / JSON(无论哪种方式都可行),然后将该XML / JSON作为String形式放入表单中。在服务器端,我将XML /
JSON字符串转换回了Entity,这很有效。
(似乎无法传输不像String或Integer 那样 的对象。)

希望这将帮助面临相同问题的每个人都通过REST将对象从客户端传输到服务器。
发送 XML / JSON转换后的对象的 列表 仍在测试中。我很快会在这里添加结果。

问候,并感谢chrylis的评论和提示。
亚娜

这是解决方案的代码,但简短地说,这只是新部分。

1)XML解决方案:

在客户端将实体更改为XML字符串:

...
OutputStream out = new ByteArrayOutputStream();

JAXBContext context = JAXBContext.newInstance(Kunde.class);
Marshaller m = context.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
m.marshal(kunde, out);
out.close();

Form form = new Form();
form.add("entity", out.toString());
...

要将XML转换回服务器端的对象:

...
public String test(
    @FormParam("entity") String entityString) {

    InputStream inputStream = new ByteArrayInputStream(entityString.getBytes());        
    Kunde kunde = JAXB.unmarshal(inputStream, Kunde.class);

    return "Der Name des Kunden ist: "+kunde.getVorname()+" "+kunde.getNachname();
}

2)JSON解决方案:

要在客户端将Entity更改为JSON String:

...
OutputStream out = new ByteArrayOutputStream();

ObjectMapper mapper = new ObjectMapper();
mapper.writeValue(out, kunde);
out.close();

Form form = new Form();
form.add("entity", out.toString());
...

要将JSON字符串转换回服务器端的对象:

...
public String test(
    @FormParam("entity") String entityString) {

    InputStream inputStream = new ByteArrayInputStream(entityString.getBytes());        
    Kunde kunde = new ObjectMapper().read((inputStream, Kunde.class));

    return "Der Name des Kunden ist: "+kunde.getVorname()+" "+kunde.getNachname();
}

JAXB,JAXBContext,Marshaller等类来自package
javax.xml.bind.*。ObjectMapper类来自package org.codehaus.jackson.map.*

PS:
因为现在传输纯String,所以您也可以使用@QueryParam。但是我不建议这样做,因为您会将整个XML作为URL中的文本String进行传输。同样适用@PathParam

我建议使用JSON ,因为该格式比XML格式更细长,而细长是REST的目标。



 类似资料:
  • 我正在使用和。 我正在努力获取子对象的子对象来填充。下面是我的课。 应用程序类; 子类: ChildRelationshipType类: 存储库中GetAll方法的一部分,以返回所有应用程序: 子类包含对ChildRelationshipType类的引用。要处理应用程序的子级,我需要这样做: 我在这里得到一个错误,即对象上下文已经关闭。 如何指定每个子对象必须包括对象,就像我上面所做的那样?

  • 我试图在我自己的包中使用data.table包。MWE如下:

  • 我有一个python应用程序要测试。此应用程序正在导入许多包,例如: 其中mypackage是我自己的包。 当我开始应用程序时,一切正常。然而,一旦我试图运行毒物测试它,我就会得到以下错误: 我知道tox无法安装mypackage依赖项,因为它不在pip中。您知道如何在此类应用程序上运行tox,或者如何使用tox安装自己的软件包吗? 我的tox.ini文件内容:

  • 获取未定义id的错误。如果我使用,它工作得很好。这是客户端代码: 下面是我自己的代码: 我做错了什么? 如果我使用以下代码:

  • 我的实体如下。 除了IDE错误之外,项目可以正确地构建和运行。

  • 注意:用户界面已经在 Dreamweaver CC 和更高版本中做了简化。因此,您可能在 Dreamweaver CC 和更高版本中找不到本文中描述的一些选项。有关详细信息,请参阅此文章。 关于服务器端包含 您可以使用 Dreamweaver 在您的页面中插入服务器端包含、编辑这些包含内容或者预览包含这些内容的页面。 服务器端包含是浏览器向服务器请求您的文档时服务器向您的文档所并入的一个文件。 当