我正在尝试从网页获取报告。实际上,报告是按预期生成的,可以正确下载。但是在调试时,我在控制台中得到了IllegalStateException。堆栈跟踪引用了我的一种方法,称为“ AddResponseHeaderFilter.doFilter()”。该方法仅设置字符集UTF-8,该类实现javax.servlet.Filter。
我使用的技术: 业务逻辑:Java(Spring), 报表引擎:JasperReports, 应用服务器:Tomcat9
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
chain.doFilter(request, response);
}
堆栈跟踪
java.lang.IllegalStateException: getOutputStream() has already been called for this response
at org.apache.catalina.connector.Response.getWriter(Response.java:582) ~[catalina.jar:9.0.20]
at org.apache.catalina.connector.ResponseFacade.getWriter(ResponseFacade.java:227) ~[catalina.jar:9.0.20]
at javax.servlet.ServletResponseWrapper.getWriter(ServletResponseWrapper.java:114) ~[servlet-api.jar:4.0.FR]
at org.springframework.boot.web.servlet.support.ErrorPageFilter$ErrorWrapperResponse.getWriter(ErrorPageFilter.java:374) ~[spring-boot-2.2.0.M2.jar:2.2.0.M2]
at org.thymeleaf.spring5.view.ThymeleafView.renderFragment(ThymeleafView.java:360) ~[thymeleaf-spring5-3.0.11.RELEASE.jar:3.0.11.RELEASE]
at org.thymeleaf.spring5.view.ThymeleafView.render(ThymeleafView.java:189) ~[thymeleaf-spring5-3.0.11.RELEASE.jar:3.0.11.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1370) ~[spring-webmvc-5.2.0.M1.jar:5.2.0.M1]
at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1116) ~[spring-webmvc-5.2.0.M1.jar:5.2.0.M1]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1055) ~[spring-webmvc-5.2.0.M1.jar:5.2.0.M1]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:942) ~[spring-webmvc-5.2.0.M1.jar:5.2.0.M1]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1005) ~[spring-webmvc-5.2.0.M1.jar:5.2.0.M1]
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:897) ~[spring-webmvc-5.2.0.M1.jar:5.2.0.M1]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:634) ~[servlet-api.jar:na]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:882) ~[spring-webmvc-5.2.0.M1.jar:5.2.0.M1]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:741) ~[servlet-api.jar:na]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[catalina.jar:9.0.20]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[catalina.jar:9.0.20]
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[tomcat-websocket.jar:9.0.20]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[catalina.jar:9.0.20]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[catalina.jar:9.0.20]
at org.apache.catalina.filters.SetCharacterEncodingFilter.doFilter(SetCharacterEncodingFilter.java:109) ~[catalina.jar:9.0.20]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[catalina.jar:9.0.20]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[catalina.jar:9.0.20]
at com.beybo.filters.AddResponseHeaderFilter.doFilter(AddResponseHeaderFilter.java:33) ~[classes/:na]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[catalina.jar:9.0.20]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[catalina.jar:9.0.20]
at org.springframework.boot.web.servlet.support.ErrorPageFilter.doFilter(ErrorPageFilter.java:130) ~[spring-boot-2.2.0.M2.jar:2.2.0.M2]
at org.springframework.boot.web.servlet.support.ErrorPageFilter.access$000(ErrorPageFilter.java:66) ~[spring-boot-2.2.0.M2.jar:2.2.0.M2]
at org.springframework.boot.web.servlet.support.ErrorPageFilter$1.doFilterInternal(ErrorPageFilter.java:105) ~[spring-boot-2.2.0.M2.jar:2.2.0.M2]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-5.2.0.M1.jar:5.2.0.M1]
at org.springframework.boot.web.servlet.support.ErrorPageFilter.doFilter(ErrorPageFilter.java:123) ~[spring-boot-2.2.0.M2.jar:2.2.0.M2]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[catalina.jar:9.0.20]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[catalina.jar:9.0.20]
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200) ~[spring-web-5.2.0.M1.jar:5.2.0.M1]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-5.2.0.M1.jar:5.2.0.M1]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[catalina.jar:9.0.20]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[catalina.jar:9.0.20]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:200) ~[catalina.jar:9.0.20]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) ~[catalina.jar:9.0.20]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:490) ~[catalina.jar:9.0.20]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139) ~[catalina.jar:9.0.20]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) ~[catalina.jar:9.0.20]
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:678) ~[catalina.jar:9.0.20]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) ~[catalina.jar:9.0.20]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) ~[catalina.jar:9.0.20]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408) ~[tomcat-coyote.jar:9.0.20]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) ~[tomcat-coyote.jar:9.0.20]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:836) ~[tomcat-coyote.jar:9.0.20]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1839) ~[tomcat-coyote.jar:9.0.20]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[tomcat-coyote.jar:9.0.20]
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) ~[na:na]
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) ~[na:na]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-util.jar:9.0.20]
at java.base/java.lang.Thread.run(Thread.java:834) ~[na:na]
代码
@Controller
@RequestMapping("/report")
public class RaporController {
@GetMapping() String reporting(Model model, HttpServletResponse response) throws IOException {
JasperPrint jasperPrint = reportService.report(new Date(), sqlTable, false);
response.setContentType("application/pdf");
response.setHeader("Content-Disposition", String.format("attachment; filename=\"" + reportService.getFilename() + "\""));
OutputStream out = response.getOutputStream();
JasperExportManager.exportReportToPdfStream(jasperPrint, out);
return "home";
}
}
答案 0 :(得分:0)
您正在混合PDF的下载和Thymeleaf的呈现。
相反,您应该返回一个带有一个包含PDF的byte []的ResponseEntity:
@Controller
@RequestMapping("/report")
public class RaporController {
@GetMapping()
public ResponseEntity reporting(Model model, HttpServletResponse response) throws IOException {
JasperPrint jasperPrint = reportService.report(new Date(), sqlTable, false);
ByteArrayOutputStream out = new ByteArrayOutputStream();
JasperExportManager.exportReportToPdfStream(jasperPrint, out);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_PDF);
headers.setContentDispositionFormData(reportService.getFilename(), reportService.getFilename());
headers.setCacheControl("must-revalidate, post-check=0, pre-check=0");
return new ResponseEntity(out.toByteArray(), headers, HttpStatus.OK);
}
}