【问题标题】:Is it possible to define an end point in a Controller with a RequestBody and a RequestPart?是否可以在具有 RequestBody 和 RequestPart 的控制器中定义端点?
【发布时间】:2020-02-14 14:49:06
【问题描述】:

我需要创建一个接受 RequestBody 或 RequestPart 的单一端点。

如果请求包含RequestPart,它将执行一些逻辑来处理MultipartFile,否则它将处理RequestBody中传递的对象。

我检查了How to send @Requestbody and @Requestpart together in spring,但它与我的问题不同,因为我不想同时发送 RequestBody 和 RequestPart。

我将我的入口点定义为:

@RequestMapping(value="/xyz/api/{endPoint}", method= RequestMethod.POST)
public void endPointPost(
        @PathVariable String endPoint,
        HttpServletRequest request,
        HttpServletResponse response,
        @RequestBody(required=false) Object body,
        @RequestPart(required=false) MultipartFile uploadFile) throws Exception {

如果请求只包含 RequestBody 则可以正常工作,例如:

{"body":{"companyCD":"myTest"}}

但是,当发送多部分请求时,它会失败并出现以下错误:

2019-10-18 00:50:43,440 DEBUG [http-nio-8080-exec-8] org.springframework.web.servlet.handler.AbstractHandlerMapping: Mapped to public void com.monoplus.mcd.rest.GenericController.endPointPost(java.lang.String,javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse,java.lang.Object,org.springframework.web.multipart.MultipartFile) throws java.lang.Exception
2019-10-18 00:50:43,440 INFO  [http-nio-8080-exec-8] com.monoplus.mcd.rest.ServletControllerInterceptor: ServletControllerInterceptor - preHandle
2019-10-18 00:50:43,442 DEBUG [http-nio-8080-exec-8] org.springframework.web.method.support.InvocableHandlerMethod: Could not resolve parameter [3] in public void com.monoplus.mcd.rest.GenericController.endPointPost(java.lang.String,javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse,java.lang.Object,org.springframework.web.multipart.MultipartFile) throws java.lang.Exception: Content type 'multipart/form-data;boundary=----WebKitFormBoundaryG1Xr4xtC2rNYWuCd;charset=UTF-8' not supported
2019-10-18 00:50:43,446 DEBUG [http-nio-8080-exec-8] org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver: Using @ExceptionHandler public final org.springframework.http.ResponseEntity<java.lang.Object> org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler.handleException(java.lang.Exception,org.springframework.web.context.request.WebRequest) throws java.lang.Exception
2019-10-18 00:50:43,481 DEBUG [http-nio-8080-exec-8] org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor: No match for [text/html, application/xhtml+xml, image/webp, image/apng, application/signed-exchange;v=b3, application/xml;q=0.9, */*;q=0.8], supported: []
2019-10-18 00:50:43,482 DEBUG [http-nio-8080-exec-8] org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver: Resolved [org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'multipart/form-data;boundary=----WebKitFormBoundaryG1Xr4xtC2rNYWuCd;charset=UTF-8' not supported]
2019-10-18 00:50:43,483 INFO  [http-nio-8080-exec-8] com.monoplus.mcd.rest.ServletControllerInterceptor: ServletControllerInterceptor - afterCompletion - org.springframework.session.web.http.SessionRepositoryFilter$SessionRepositoryResponseWrapper@6c9a1e05
2019-10-18 00:50:43,484 DEBUG [http-nio-8080-exec-8] org.springframework.web.servlet.FrameworkServlet: Completed 415 UNSUPPORTED_MEDIA_TYPE

请注意,Could not resolve parameter [3]... 指的是 RequestBody 参数。

这是我的多部分请求:

  • 标题
Host: localhost:88
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:69.0) Gecko/20100101 Firefox/69.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: multipart/form-data; boundary=---------------------------262541039624932
Content-Length: 1401
Connection: keep-alive
Referer: http://localhost:88/appl/html/master/FileImport.html
Cookie: JSESSIONID=3f052417-1702-48b6-b7c2-cac5609ef525; SESSION=M2YwNTI0MTctMTcwMi00OGI2LWI3YzItY2FjNTYwOWVmNTI1
Upgrade-Insecure-Requests: 1
Pragma: no-cache
Cache-Control: no-cache
  • 身体
-----------------------------262541039624932
Content-Disposition: form-data; name="uploadFile"; filename="testFile.txt"
Content-Type: text/plain


1 - File content

-----------------------------262541039624932
Content-Disposition: form-data; name="_ns"


-----------------------------262541039624932
Content-Disposition: form-data; name="_qt"

false
-----------------------------262541039624932
Content-Disposition: form-data; name="_body"

{"USER_NAME":""}
-----------------------------262541039624932--

感谢任何帮助。

谢谢

【问题讨论】:

    标签: spring-boot tomcat9


    【解决方案1】:

    感谢 Chris 的建议,我能够解决我的问题,我为 Multipart 内容定义了一个不同的入口点。

        @RequestMapping(value="/xyz/api/{endPoint}", method= RequestMethod.POST, consumes = {"multipart/form-data"})
        public void multiPartEndPointPost(
                @PathVariable String endPoint,
                HttpServletRequest request,
                HttpServletResponse response
        ) throws Exception {
    
            this.doSomeStuff(endPoint, request, response);
        }
    

    重要的部分是consumes = {"multipart/form-data"} 然后我可以使用 Apache Commons FileUpload 上传文件。

    [Cannot use Apache Commons FileUpload with Spring Boot multipart.resolve-lazily 的答案也帮助我解决了我的问题。

    【讨论】:

      【解决方案2】:

      我从 RESTful 的角度考虑这个问题,不一定是 spring。如果您是 1) 尝试创建或编辑(发布或放置)资源或 2) 尝试上传文件;这些不应该是两个不同的URI路径吗?

      【讨论】:

      • 我有点同意,但有两件事,首先是规范,其次是使用 PathVariable 定义的端点,servlet 将决定将请求发送到哪里。在这种情况下,我只需要一个入口点而不是多个 RestController。
      猜你喜欢
      • 2010-10-23
      • 1970-01-01
      • 2015-08-19
      • 2011-12-02
      • 2011-09-26
      • 2014-10-29
      • 2019-03-31
      • 1970-01-01
      • 2018-05-13
      相关资源
      最近更新 更多