gpt4 book ai didi

java - 如何在生成文件时处理 Spring Controller 上的异常

转载 作者:行者123 更新时间:2023-12-02 04:16:59 25 4
gpt4 key购买 nike

我已经实现了一个 Spring Controller ,它可以生成 PDF 文件,并使用我的服务层。问题是,当方法执行过程中抛出一些异常时,即使我用 try-catch block 得到异常,spring 也会尝试根据当前 URL 解析 View 。

老实说,我不知道是什么导致了这种行为。

    @RequestMapping("/cliente")
public void relatorioCliente(EdicaoMovimentacaoWrapper wrapper, @AuthenticationPrincipal Usuario usuario) {
try {
gerarReportService.relatorioParaCliente(wrapper.getContaId(), usuario);

} catch (Exception e) {
e.printStackTrace();
// TODO alguma coisa
}
}

relatorioParaCliente 方法生成 PDF 并将其导出到响应的 OutputStream。

预期:异常被捕获,堆栈跟踪被打印,并且用户没有任何反应。实际结果:Spring 将用户重定向到 views/cliente.jsp

更新

我尝试更改方法的返回类型,现在看起来像这样:

    @RequestMapping("/cliente")
public ModelAndView relatorioCliente(EdicaoCadastroMovimentacaoWrapper wrapper, @AuthenticationPrincipal Usuario usuario) {
try {
gerarReportService.relatorioParaCliente(wrapper.getContaId(), usuario);

} catch (Exception e) {
e.printStackTrace();
return new ModelAndView("/contas/" + wrapper.getContaId());
}
return null;
}

但这对我的代码没有影响。我认为这不会影响代码,因为输出流在服务上使用。看看:

@Service
public class ExportarReportPdfService {

@Autowired
private HttpServletResponse res;

public void exportar(List<JasperPrint> jasperPrintList) throws IOException {

JRPdfExporter exporter = new JRPdfExporter();

exporter.setExporterInput(SimpleExporterInput.getInstance(jasperPrintList));

exporter.setExporterOutput(new SimpleOutputStreamExporterOutput(res.getOutputStream()));

SimplePdfExporterConfiguration configuration = new SimplePdfExporterConfiguration();

configuration.setCreatingBatchModeBookmarks(true);

exporter.setConfiguration(configuration);

res.setContentType("application/x-pdf");
res.setHeader("Content-disposition", "inline; filename=relatorio.pdf" );


try {
exporter.exportReport();
} catch (Exception e) {
e.printStackTrace();
throw new CriacaoReportException("Erro ao exportar para PDF");
} finally {
OutputStream out = res.getOutputStream();
out.flush();
out.close();

}
}

最佳答案

这是我为解决该问题所做的操作:

我生成一个 byteArray 并将其返回到 Controller ,而不是 Autowiring 服务上的响应并从那里导出 pdf:

@Service
public class ExportarReportPdfService {

public byte[] exportar(List<JasperPrint> jasperPrintList) {

final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

JRPdfExporter exporter = new JRPdfExporter();

exporter.setExporterInput(SimpleExporterInput.getInstance(jasperPrintList));

exporter.setExporterOutput(new SimpleOutputStreamExporterOutput(outputStream));

[OMITED CODE]

try {
exporter.exportReport();
return outputStream.toByteArray();
} catch (Exception e) {
e.printStackTrace();
throw new CriacaoReportException("Erro ao exportar para PDF");
}
}
}

Controller 将响应作为 ResponseEntity 发送:

        @RequestMapping("/geral")
public ResponseEntity<InputStreamResource> relatorioAdministrador(EdicaoCadastroMovimentacaoWrapper wrapper, @AuthenticationPrincipal Usuario usuario) {

byte[] arquivo = gerarReportService.relatorioParaAdmin(wrapper.getContaId(), usuario);

return ResponseEntity
.ok()
.contentLength(arquivo.length)
.contentType(MediaType.parseMediaType("application/pdf"))
.header("Content-Disposition", "attachment; filename=relatorio.pdf")
.body(new InputStreamResource(new ByteArrayInputStream(arquivo)));
}


因此,如果发生任何异常,它将被捕获在 ExceptionHandler 中,正如 @cmoetzing 在评论中所解释的那样:

    @ExceptionHandler(CriacaoReportException.class)
public ModelAndView trataGeracaoRelatorio(CriacaoReportException exception) {
return new ModelAndView("redirect:/");
}

关于java - 如何在生成文件时处理 Spring Controller 上的异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56655744/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com