【问题标题】:Resteasy javax - How to map content-type */* to application/json on server-side?Resteasy javax - 如何将内容类型 */* 映射到服务器端的应用程序/json?
【发布时间】:2020-12-09 18:55:27
【问题描述】:

问题:通过更改服务器代码而不是客户端代码,我无法在客户端消息中将 */* 的内容类型映射到服务器端的 application/json。 (后者部署的客户端太多)

在 WildFly 10 上一切正常(使用 */*),但在 WildFly 14/18 上却失败了

RESTEASY002010: Failed to execute: javax.ws.rs.NotSupportedException: RESTEASY003200: Could not find message body reader for type: class xxxx of content type: */* at org.jboss.resteasy.resteasy-
jaxrs@3.9.1.Final//org.jboss.resteasy.core.interception.ServerReaderInterceptorContext.throwReaderNotFound

以上所有内容都在 Java 8 上。下面的代码显示了无需服务器端编辑即可让 WF14+ 工作的客户端更改:

HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "*/*");  // works for WF10, not WF14+
// conn.setRequestProperty("Content-Type", "application/json; charset=UTF-8"); // works for all

适用的服务器端代码如下:

@POST
@Path("fileDownload")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_OCTET_STREAM)
// Consume options tried that still failed:
// @Consumes({ MediaType.APPLICATION_JSON, MediaType.WILDCARD, MediaType.APPLICATION_OCTET_STREAM, "*/*", "*/*\r\n", "*/*; charset=UTF-8" } )
public Response fileDownload(@HeaderParam("Range") String range, FileDownloadRequest fileDwnReq) throws IOException { ... }

我的网络搜索都指向客户端更改(这将起作用),但我们必须更改服务器端或留在 WF10 上。我也尝试在 web.xml 中设置字符集行为或映射媒体类型,但没有任何区别。例如:

<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
  <display-name>MyRestServices</display-name>
    <listener>
    <listener-class>org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap
    </listener-class>
    </listener>
    
    <!--   
    To specify the previous behavior, in which UTF-8 was used for text media types, but 
    the explicit charset was not appended, the context parameter "resteasy.add.charset" may be 
    set to "false". It defaults to "true". 
    See https://docs.jboss.org/resteasy/docs/3.1.2.Final/userguide/html_single/index.html
    This did not work.
     -->
<!--     <context-param> -->
<!--        <param-name>resteasy.add.charset</param-name> -->
<!--        <param-value>false</param-value> -->
<!--     </context-param> -->
        
     <context-param>
        <param-name>resteasy.media.type.mappings</param-name>
        <param-value>*/* : application/json</param-value>
<!-- <param-value>html : text/html, json : application/json, xml : application/xml</param-value> -->
    </context-param>

我被难住了。任何建议/指针将不胜感激。

编辑:下面是失败的 http 请求的转储:

 URI=/xxx/fileDownload
 characterEncoding=null
     contentLength=94
       contentType=[*/*]
            header=Accept=text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
            header=Connection=keep-alive
            header=Content-Type=*/*
            header=Content-Length=94
            header=User-Agent=Java/1.8.0_152
            header=Host=127.0.0.1:8014
            locale=[]
            method=POST
          protocol=HTTP/1.1
       queryString=
        remoteAddr=/127.0.0.1:59867
        remoteHost=127.0.0.1
            scheme=http
              host=127.0.0.1:8014
        serverPort=8014
          isSecure=false
--------------------------RESPONSE--------------------------
     contentLength=0
       contentType=null
            header=Connection=keep-alive
            header=Content-Length=0
            header=Date=Thu, 20 Aug 2020 13:36:44 GMT
            status=415

【问题讨论】:

    标签: java json wildfly resteasy content-type


    【解决方案1】:

    我通过添加一个 ContainerRequestFilter 找到了一种方法,该方法在匹配之前更改了标头。下面是诀窍:

    import javax.ws.rs.core.UriInfo;
    import javax.ws.rs.container.ContainerRequestFilter;
    import javax.ws.rs.container.ContainerRequestContext;
    import javax.ws.rs.ext.Provider;
    import javax.ws.rs.container.PreMatching;
    
    @Provider
    @PreMatching
    // Mapp */* to JSON for /filedownload
    public final class ContentFilter implements ContainerRequestFilter {
       @Override
       public void filter(ContainerRequestContext ctx) throws IOException {
          UriInfo uri = ctx.getUriInfo();
          if ((uri != null) && uri.getPath().toLowerCase().contains("filedownload")) {
              String ctp = ctx.getHeaderString("Content-Type");
              if ("*/*".equals(ctp))
                 ctx.getHeaders().putSingle("Content-Type", "application/json; charset=UTF-8");
          }
       }
    }
    

    我还必须将以下内容添加到我的 web.xml 中

     <context-param>
        <param-name>resteasy.providers</param-name>
        <param-value>xxx.yyy.ContentFilter</param-value>
    </context-param>
    

    【讨论】:

      【解决方案2】:

      根据documentation,您应该能够将请求正文作为字符串参数获取,然后手动将其编组为所需的对象形式。

      【讨论】:

        【解决方案3】:

        在客户端的“Content-Type”中使用通配符是没有意义的。

        客户端可以接受多种格式的服务器响应(使用“Accept”标头)

        服务器 可以接受(消费)多种媒体,但客户端必须知道他有效发布的数据类型。如果您不告诉服务器您在 http 正文中发送的内容,服务器就无法(总是)猜到它。

        【讨论】:

        • 我同意这没有意义;但是,这已经是该领域的内容了,我必须找到一种方法让它在 WF18 上仍然有效,直到我们修复客户端。
        猜你喜欢
        • 2012-12-31
        • 1970-01-01
        • 1970-01-01
        • 2020-04-24
        • 2013-12-29
        • 1970-01-01
        • 2016-03-19
        • 1970-01-01
        • 2020-11-19
        相关资源
        最近更新 更多