在 Spring Boot Web Thymeleaf 应用程序中进行 AJAX 调用的正确方法是获取 getOutputStream() 已经为此响应调用

Posted

技术标签:

【中文标题】在 Spring Boot Web Thymeleaf 应用程序中进行 AJAX 调用的正确方法是获取 getOutputStream() 已经为此响应调用【英文标题】:What is correct way to make AJAX call in Spring Boot web Thymeleaf application Getting getOutputStream() has already been called for this response 【发布时间】:2019-10-27 05:02:28 【问题描述】:

我正在开发基于 Spring Boot 的 Web 应用程序并在前端使用 Thymeleaf。我需要进行 AJAX 调用,发布从 AJAX 调用返回的数据和成功显示数据。

下面是调用Controller方法的AJAX调用

          var myObject = new Object();
          myObject.acctTypeValue = 22;
          myObject.amtBalance = "121334";
          myObject.custNo="12121";
          myObject.userId="2345rest";
          
        $.ajax(
            url : '/testDocWeb/forwardToCallingSystem',
            type :'POST',
            data : myObject,
            dataType:'html',
            cache: false,
                 timeout: 600000,
            success : function(data)                
                alert('Data: '+JSON.stringify(data));
            ,
            error : function(request,error)
            
                alert("Error : "+JSON.stringify(request));
            
        );

下面是 Spring MVC 控制器:-

    @PostMapping(path="/forwardToCallingSystem")
      public @ResponseBody DummuyResponse forwardToCallingSystem(@ModelAttribute DummyInput dummyInput,Model model, HttpServletRequest request) 
         log.info("Inside forwardToCallingSystem method." );
         DummuyResponse dummyResponse = new DummuyResponse ();
         dummyResponse .setDocId("756");
         dummyResponse .setReasonCode('0');
         dummyResponse .setReturnCode(100);
         dummyResponse .setStatusCode(200);
         return dummyResponse ;

下面是我要返回的模型对象:-

            @Data
            @JsonIgnoreProperties(ignoreUnknown = true)
            public class DummyResponse implements Serializable 
            private static final long serialVersionUID = -8191562770215698813L;
            private int statusCode;
            private char reasonCode;
            private int returnCode;
            private String docId;

我不确定出了什么问题,但在进行 AJAX 调用时出现以下错误:-

    [ERROR]~2019-06-12-10.32.54.030CDT~~~~~~ o.a.c.c.C.[.[localhost] Exception Processing ErrorPage[errorCode=0, location=/error]
    org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.IllegalStateException: getOutputStream() has already been called for this response
        at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1013)
        at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:908)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:660)
        at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:882)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
        at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:712)
        at org.apache.catalina.core.ApplicationDispatcher.doInclude(ApplicationDispatcher.java:580)
        at org.apache.catalina.core.ApplicationDispatcher.include(ApplicationDispatcher.java:516)
        at org.apache.catalina.core.StandardHostValve.custom(StandardHostValve.java:388)
        at org.apache.catalina.core.StandardHostValve.status(StandardHostValve.java:253)
        at org.apache.catalina.core.StandardHostValve.throwable(StandardHostValve.java:348)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:173)
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
        at net.rakugakibox.spring.boot.logback.access.tomcat.LogbackAccessTomcatValve.invoke(LogbackAccessTomcatValve.java:91)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
        at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408)
        at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
        at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:834)
        at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1415)
        at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
        at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
        at java.lang.Thread.run(Thread.java:745)
    Caused by: java.lang.IllegalStateException: getOutputStream() has already been called for this response
 

我只是在为普通 Spring MVC 制作 AJAX 调用表单 Thymeleaf 网页时遇到问题。它工作正常。任何帮助将不胜感激

【问题讨论】:

【参考方案1】:

在您的 ajax 请求中,您使用的是dataType:'html',但是根据jQuery’s Ajax-Related Methods Description,您从控制器返回了一个对象

// The type of data we expect back
dataType : "html"

将您的 ajax 请求更新为

$.ajax(
        url : '/testDocWeb/forwardToCallingSystem',
        type :'POST',
        data : myObject,
        cache: false,
        timeout: 600000,
        success : function(data)                
            alert('Data: ' + JSON.stringify(data));
        ,
        error : function(request,error) 
            alert("Error : " + JSON.stringify(request));
        
    );

另外,this Post 也会有所帮助。

【讨论】:

感谢您的回答。

以上是关于在 Spring Boot Web Thymeleaf 应用程序中进行 AJAX 调用的正确方法是获取 getOutputStream() 已经为此响应调用的主要内容,如果未能解决你的问题,请参考以下文章

springboot中模板 freemark,thymeleaf,jsp

如何在不从 spring-boot-starter-web 继承的情况下在 Spring Boot 中获取 ObjectMapper 实例?

spring-boot-starter-tomcat 与 spring-boot-starter-web

spring boot框架学习6-spring boot的web开发

Spring boot 默认首页配置 Spring boot web默认首页配置 Spring boot web项目默认首页配置

Spring Boot Sample 011之spring-boot-web-webjars