Return 在 Spring MVC 处理程序中有条件地使用 PDF 视图的 thymeleaf 视图

Return a thymeleaf view conditionally with PDF view in Spring MVC handler

我正在开发 spring 引导应用程序并使用 spring 验证。如果验证后出现任何错误,需要 return thymeleaf 页面。

@ResponseBody
@PostMapping(params = "_action_preview_pdf", produces = MediaType.APPLICATION_PDF_VALUE)
public ResponseEntity<byte[]> getTemplatePDF(@Valid @ModelAttribute(COMMAND_NAME) RxTemplateConfiguration configuration,
                                             BindingResult result) {

    if(result.hasErrors()){
        return VIEW_FORM;  //Error
    }

    ....

    return new ResponseEntity<>(prescriptionHelper.getTemplatePdf(configuration), headers, HttpStatus.OK);

}

出现以下错误:

error: return VIEW_FORM; incompatible types: String cannot be converted to ResponseEntity<byte[]>

在这里,VIEW_FORM = "config-form" 这是百里香叶页面。 我如何 return thymeleaf 页面?

解决方案:

  1. 删除了 @ResponseBody 标签。
  2. 已将 return 类型从 ResponseEntity<byte[]> 替换为 Object

更新后的代码:

@PostMapping(params = "_action_preview_pdf", produces = MediaType.APPLICATION_PDF_VALUE)
public Object getTemplatePDF(@Valid @ModelAttribute(COMMAND_NAME) RxTemplateConfiguration configuration,
                                         BindingResult result) {

    if(result.hasErrors()){
        return VIEW_FORM;  //Error fixed.
    }

    ....

    return new ResponseEntity<>(prescriptionHelper.getTemplatePdf(configuration), headers, HttpStatus.OK);

}

当您从处理程序 returning ResponseEntity<byte[]> 时,也无法使用 view-name return。如果您希望生成 PDF 视图以及有条件的其他视图,有几种方法可以做到这一点。我更喜欢使用 BeanNameViewResolveritexpdf library

BeanNameViewResolver

这将解析声明为 bean 的视图。这意味着您可以使用视图的 bean 名称作为视图名称。在 Spring Boot 中,默认注册了 BeanNameViewResolver bean。要从 bean 生成 PDF 视图,您需要这个 iText API。将此添加到您的 build.gradle

compile group: 'com.itextpdf', name: 'itext7-core', version: '7.1.3'

要占用 BeanNameViewResolver,您需要创建一个扩展 AbstratView 的 bean,您将在其中使用 itex7 生成 PDF 文档。

@Component("reportView")
public class HelloPdfView extends AbstractView {

    @Override
    protected void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request,
                                           HttpServletResponse response) throws Exception {

        response.setHeader("Content-Disposition", "attachment; filename=myReport.pdf");

        // get your bean for generating pdf say it is Report
        Report report = (Report) model.get("report");

        //use IText API
        PdfWriter pdfWriter = new PdfWriter(response.getOutputStream());
        PdfDocument pdf = new PdfDocument(pdfWriter);
        Document pdfDocument = new Document(pdf);

        //do other customization you like
        Paragraph title = new Paragraph(report.getName());
        title.setFont(PdfFontFactory.createFont(StandardFonts.HELVETICA));
        title.setFontSize(18f);
        title.setItalic();
        pdfDocument.add(title);


        //content
        Paragraph content = new Paragraph(report.getContent());
        pdfDocument.add(content);

        pdfDocument.close();

    }
}

现在当你像其他视图一样从控制器调用它时

@PostMapping("/report")
public String showPdf(@Valid @ModelAttribute(COMMAND_NAME) RxTemplateConfiguration configuration, BindingResult result) {
    model.addAttribute("report", getReport()); //get your data

    if(result.hasErrors()){
       return ERROR_VIEW; 
    }


    return "reportView";
}

另见