Spring Boot导出Pdf文件

作者: 秃头哥编程 | 来源:发表于2018-10-14 14:32 被阅读189次

    除了常见的jsp视图外,还有pdf,excel等。不管哪种视图,都会实现SpringMvc定义的视图接口View。这篇文章就讲讲怎么使用Pdf视图----AbstractPdfView。

    AbstractPdfView属于非逻辑视图,不需要任何的视图解析器(ViewResolver)去定位。它是一个抽象类,有一个抽象方法需要我们去实现。

        /**
         * 通过数据模型自定义创建pdf文档
         * @param model 数据模型
         * @param document 代表一个pdf文档
         * @param writer pdf写入器
         * @param request HttpServletRequest请求对象
         * @param response HttpServletResponse响应对象
         */
        protected abstract void buildPdfDocument(Map<String, Object> model, Document document, PdfWriter writer,
                HttpServletRequest request, HttpServletResponse response) throws Exception;
    

    我们首先创建一个Spring Boot工程,这里的orm使用Mybatis,数据源使用Druid,为了能够使用pdf,我们需要加pom.xml中相关的依赖,下面贴出完整的pom文件

        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-aop</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>1.3.2</version>
            </dependency>
    
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <scope>runtime</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-tomcat</artifactId>
                <scope>provided</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
            <!-- pdf相关的jar -->
            <dependency>
                <groupId>org.xhtmlrenderer</groupId>
                <artifactId>core-renderer</artifactId>
                <version>R8</version>
            </dependency>
            <dependency>
                <groupId>com.itextpdf</groupId>
                <artifactId>itextpdf</artifactId>
                <version>5.5.12</version>
            </dependency>
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid</artifactId>
                <version>1.1.6</version>
            </dependency>
        </dependencies>
    

    继承了AbstractPdfView后,就得实现它的抽象方法,从而完成导出的逻辑,而每个控制器可能都有不同的导出逻辑,所以为了适应不同控制器的自定义导出,先定义一个导出接口。

    import java.util.Map;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import com.lowagie.text.Document;
    import com.lowagie.text.pdf.PdfWriter;
    
    /**
     * 定义一个导出的接口,方便每个控制器实现自己的导出逻辑
     * @author liu
     */
    public interface PdfExportService {
        
        /**
         * 导出的方法
         * @param model 数据模型
         * @param document 代表一个pdf文档
         * @param writer pdf写入器
         * @param request HttpServletRequest请求对象
         * @param response HttpServletResponse响应对象
         */
        public void make(Map<String, Object> model, Document document, PdfWriter writer, 
                HttpServletRequest request, HttpServletResponse response);
    }
    

    注意这里导的是com.lowagie.text包下的类。

    有了这个接口后,各个控制器只需要实现这个接口,就能自定义导出pdf的逻辑。

    接着就是继承AbstractPdfView,通过它调度PdfExportService 的make方法就可以让控制器去实现自定义的导出逻辑。

    /**
     * 继承AbstractPdfView类,实现抽象方法buildPdfDocument
     * @author liu
     */
    public class PdfView extends AbstractPdfView {
        
        private PdfExportService pdfExportService = null;
        
        /**
         * 创建对象时载入导出服务接口
         * @param pdfExportService
         */
        public PdfView(PdfExportService pdfExportService) {
            this.pdfExportService = pdfExportService;
        }
    
        /**
         * 调用接口实现导出
         */
        @Override
        protected void buildPdfDocument(Map<String, Object> model, Document document, PdfWriter writer,
                HttpServletRequest request, HttpServletResponse response) throws Exception {
            
            // 调用导出服务接口类
            pdfExportService.make(model, document, writer, request, response);
        }
    
    }
    

    这里可以看到,在创建自定义pdf视图时,需要自定义一个导出服务接口(PdfExportService ),通过实现这个接口,每个控制器都可以自定义其导出的逻辑。

    完成了上面的工作,接下来就是正常的SSM结合。首先在Spring Boot的配置文件中进行配置

    # 数据库配置
    jdbc.driver = com.mysql.jdbc.Driver
    jdbc.url = jdbc:mysql://localhost:3306/springboot?characterEncoding=utf-8
    jdbc.username = root
    jdbc.password = 1311664842
    
    # mybatis 配置文件的路径
    mybatis_config_file = /mybatis/mybatis-config.xml
    # 映射文件的路径
    mapper_path = /mapper/**.xml
    # 实体类的路径
    entity_package = com.codeliu.entity
    
    # 日志配置
    logging.level.root = DEBUG
    logging.level.org.springframework = DDEBUG
    logging.level.org.mybatis = DEBUG
    

    可以看到进行了数据源的配置,还有mybatis的一些配置。

    接下来就是在指定路径下创建mybatis全局配置文件,创建实体类和创建映射文件,还有service层,这些就不写了,最重要的就是控制层,在写控制层之前,先写两个配置类,配置数据源和sqlSessionFactory。

    /**
     * 配置数据源
     * @author liu
     */
    @Configuration
    // 扫描dao层
    @MapperScan(value = "com.codeliu.dao")
    public class DataSourceConfig {
        
        @Value(value = "${jdbc.driver}")
        private String jdbcDriver;
        
        @Value(value = "${jdbc.url}")
        private String jdbcUrl;
        
        @Value(value = "${jdbc.username}")
        private String jdbcUsername;
        
        @Value(value = "${jdbc.password}")
        private String jdbcPassword;
        
        @Bean(value = "dataSource")
        public DruidDataSource getDataSource() {
            DruidDataSource dataSource = new DruidDataSource();
            dataSource.setDriverClassName(jdbcDriver);
            dataSource.setUrl(jdbcUrl);
            dataSource.setUsername(jdbcUsername);
            dataSource.setPassword(jdbcPassword);
            return dataSource;
        }
    }
    
    /**
     * SqlSessionFactory配置
     * @author liu
     */
    @Configuration
    public class SqlSessionFactoryConfig {
    
        // mybatis配置文件的路径
        @Value(value = "${mybatis_config_file}")
        private String mybatisConfigPath;
        
        // mybatis映射文件的路径
        @Value(value = "${mapper_path}")
        private String mapperPath;
        
        // 实体包的路径
        @Value(value = "${entity_package}")
        private String entityPath;
        
        @Autowired
        private DataSource dataSource;
        
        @Bean(value = "sqlSessionFactory")
        public SqlSessionFactoryBean getSqlSessionFactoryBean() throws IOException {
            SqlSessionFactoryBean sqlSessionFactory = new SqlSessionFactoryBean();
            
            // mybatis配置文件的路径
            sqlSessionFactory.setConfigLocation(new ClassPathResource(mybatisConfigPath));
            
            PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
            String packageSearchPath = PathMatchingResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + mapperPath;
            // 指定映射文件的路径
            sqlSessionFactory.setMapperLocations(resolver.getResources(packageSearchPath));
            // 配置数据源
            sqlSessionFactory.setDataSource(dataSource);
            // 配置实体包的扫描路径
            sqlSessionFactory.setTypeAliasesPackage(entityPath);
            return sqlSessionFactory;
        }
    }
    

    注意加上了@Configuration注解,表示这是一个配置类。这样Spring Boot启动的时候,就会进行相关的初始化。

    现在可以来进行controller的编写。

    @Controller
    @RequestMapping("/man")
    public class ManController {
        
        @Autowired
        private ManService manService;
        
        /**
         * 导出接口
         * @return
         */
        @GetMapping("/export/pdf")
        public ModelAndView exportPdf() {
            List<Man> manList = manService.getManList();
            // 定义pdf视图
            View view = new PdfView(exportService());
            ModelAndView mv = new ModelAndView();
            // 设置视图
            mv.setView(view);
            // 加入数据模型
            mv.addObject("manList", manList);
            return mv;
        }
        
        
        /**
         * 导出pdf自定义,每个控制器可以实现自己的导出逻辑
         * @return
         */
        @SuppressWarnings("unchecked")
        public PdfExportService exportService() {
            // 使用Lambda表达式
            return(model, document, writer, request, response)-> {
                try {
                    // A4纸张
                    document.setPageSize(PageSize.A4);
                    // 标题
                    document.addTitle("用户信息");
                    // 换行
                    document.add(new Chunk("\n"));
                    // 表格,3列
                    PdfPTable table = new PdfPTable(3);
                    // 单元格
                    PdfPCell cell = null;
                    // 字体,定义为蓝色加粗
                    Font f8 = new Font();
                    f8.setColor(Color.BLUE);
                    f8.setStyle(Font.BOLD);
                    // 标题
                    cell = new PdfPCell(new Paragraph("id", f8));
                    // 居中对齐
                    cell.setHorizontalAlignment(1);
                    // 将单元格加入表格
                    table.addCell(cell);
                    
                    // 标题
                    cell = new PdfPCell(new Paragraph("age", f8));
                    // 居中对齐
                    cell.setHorizontalAlignment(1);
                    // 将单元格加入表格
                    table.addCell(cell);
                    
                    // 标题
                    cell = new PdfPCell(new Paragraph("name", f8));
                    // 居中对齐
                    cell.setHorizontalAlignment(1);
                    // 将单元格加入表格
                    table.addCell(cell);
                    
                    // 获取数据模型中的manList
                    List<Man> manList = (List<Man>)model.get("manList");
                    for(Man man:manList) {
                        document.add(new Chunk("\n"));
                        cell = new PdfPCell(new Paragraph(man.getId() + ""));
                        // 居中对齐
                        cell.setHorizontalAlignment(1);
                        table.addCell(cell);
                        cell = new PdfPCell(new Paragraph(man.getAge() + ""));
                        // 居中对齐
                        cell.setHorizontalAlignment(1);
                        table.addCell(cell);
                        cell = new PdfPCell(new Paragraph(man.getName()));
                        // 居中对齐
                        cell.setHorizontalAlignment(1);
                        table.addCell(cell);
                    }
                    // 文档中加入表格
                    document.add(table);
                } catch(DocumentException e) {
                    e.printStackTrace();
                }
            };
        }
    }
    

    可以看到我们先通过数据库查询出数据,然后放入模型和视图(ModelAndView)中,然后设置pdf视图(PdfView)。而定义PdfView时,使用Lambda表达式实现了导出服务接口,这样就可以很方便的让每一个控制器自定义样式和数据。导出pdf文件的逻辑在exportService方法中。

    启动Spring Boot文件后,输入url,显示下面的结果


    20.png

    相关文章

      网友评论

        本文标题:Spring Boot导出Pdf文件

        本文链接:https://www.haomeiwen.com/subject/xkbzaftx.html