Spring Boot導(dǎo)出Pdf文件

除了常見的jsp視圖外,還有pdf,excel等。不管哪種視圖,都會實現(xiàn)SpringMvc定義的視圖接口View。這篇文章就講講怎么使用Pdf視圖----AbstractPdfView。

AbstractPdfView屬于非邏輯視圖,不需要任何的視圖解析器(ViewResolver)去定位。它是一個抽象類,有一個抽象方法需要我們?nèi)崿F(xiàn)。

    /**
     * 通過數(shù)據(jù)模型自定義創(chuàng)建pdf文檔
     * @param model 數(shù)據(jù)模型
     * @param document 代表一個pdf文檔
     * @param writer pdf寫入器
     * @param request HttpServletRequest請求對象
     * @param response HttpServletResponse響應(yīng)對象
     */
    protected abstract void buildPdfDocument(Map<String, Object> model, Document document, PdfWriter writer,
            HttpServletRequest request, HttpServletResponse response) throws Exception;

我們首先創(chuàng)建一個Spring Boot工程,這里的orm使用Mybatis,數(shù)據(jù)源使用Druid,為了能夠使用pdf,我們需要加pom.xml中相關(guān)的依賴,下面貼出完整的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相關(guān)的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后,就得實現(xiàn)它的抽象方法,從而完成導(dǎo)出的邏輯,而每個控制器可能都有不同的導(dǎo)出邏輯,所以為了適應(yīng)不同控制器的自定義導(dǎo)出,先定義一個導(dǎo)出接口。

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;

/**
 * 定義一個導(dǎo)出的接口,方便每個控制器實現(xiàn)自己的導(dǎo)出邏輯
 * @author liu
 */
public interface PdfExportService {
    
    /**
     * 導(dǎo)出的方法
     * @param model 數(shù)據(jù)模型
     * @param document 代表一個pdf文檔
     * @param writer pdf寫入器
     * @param request HttpServletRequest請求對象
     * @param response HttpServletResponse響應(yīng)對象
     */
    public void make(Map<String, Object> model, Document document, PdfWriter writer, 
            HttpServletRequest request, HttpServletResponse response);
}

注意這里導(dǎo)的是com.lowagie.text包下的類。

有了這個接口后,各個控制器只需要實現(xiàn)這個接口,就能自定義導(dǎo)出pdf的邏輯。

接著就是繼承AbstractPdfView,通過它調(diào)度PdfExportService 的make方法就可以讓控制器去實現(xiàn)自定義的導(dǎo)出邏輯。

/**
 * 繼承AbstractPdfView類,實現(xiàn)抽象方法buildPdfDocument
 * @author liu
 */
public class PdfView extends AbstractPdfView {
    
    private PdfExportService pdfExportService = null;
    
    /**
     * 創(chuàng)建對象時載入導(dǎo)出服務(wù)接口
     * @param pdfExportService
     */
    public PdfView(PdfExportService pdfExportService) {
        this.pdfExportService = pdfExportService;
    }

    /**
     * 調(diào)用接口實現(xiàn)導(dǎo)出
     */
    @Override
    protected void buildPdfDocument(Map<String, Object> model, Document document, PdfWriter writer,
            HttpServletRequest request, HttpServletResponse response) throws Exception {
        
        // 調(diào)用導(dǎo)出服務(wù)接口類
        pdfExportService.make(model, document, writer, request, response);
    }

}

這里可以看到,在創(chuàng)建自定義pdf視圖時,需要自定義一個導(dǎo)出服務(wù)接口(PdfExportService ),通過實現(xiàn)這個接口,每個控制器都可以自定義其導(dǎo)出的邏輯。

完成了上面的工作,接下來就是正常的SSM結(jié)合。首先在Spring Boot的配置文件中進行配置

# 數(shù)據(jù)庫配置
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

可以看到進行了數(shù)據(jù)源的配置,還有mybatis的一些配置。

接下來就是在指定路徑下創(chuàng)建mybatis全局配置文件,創(chuàng)建實體類和創(chuàng)建映射文件,還有service層,這些就不寫了,最重要的就是控制層,在寫控制層之前,先寫兩個配置類,配置數(shù)據(jù)源和sqlSessionFactory。

/**
 * 配置數(shù)據(jù)源
 * @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));
        // 配置數(shù)據(jù)源
        sqlSessionFactory.setDataSource(dataSource);
        // 配置實體包的掃描路徑
        sqlSessionFactory.setTypeAliasesPackage(entityPath);
        return sqlSessionFactory;
    }
}

注意加上了@Configuration注解,表示這是一個配置類。這樣Spring Boot啟動的時候,就會進行相關(guān)的初始化。

現(xiàn)在可以來進行controller的編寫。

@Controller
@RequestMapping("/man")
public class ManController {
    
    @Autowired
    private ManService manService;
    
    /**
     * 導(dǎo)出接口
     * @return
     */
    @GetMapping("/export/pdf")
    public ModelAndView exportPdf() {
        List<Man> manList = manService.getManList();
        // 定義pdf視圖
        View view = new PdfView(exportService());
        ModelAndView mv = new ModelAndView();
        // 設(shè)置視圖
        mv.setView(view);
        // 加入數(shù)據(jù)模型
        mv.addObject("manList", manList);
        return mv;
    }
    
    
    /**
     * 導(dǎo)出pdf自定義,每個控制器可以實現(xiàn)自己的導(dǎo)出邏輯
     * @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);
                
                // 獲取數(shù)據(jù)模型中的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();
            }
        };
    }
}

可以看到我們先通過數(shù)據(jù)庫查詢出數(shù)據(jù),然后放入模型和視圖(ModelAndView)中,然后設(shè)置pdf視圖(PdfView)。而定義PdfView時,使用Lambda表達式實現(xiàn)了導(dǎo)出服務(wù)接口,這樣就可以很方便的讓每一個控制器自定義樣式和數(shù)據(jù)。導(dǎo)出pdf文件的邏輯在exportService方法中。

啟動Spring Boot文件后,輸入url,顯示下面的結(jié)果


20.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Boot 參考指南 介紹 轉(zhuǎn)載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 47,278評論 6 342
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,639評論 19 139
  • Spring Web MVC Spring Web MVC 是包含在 Spring 框架中的 Web 框架,建立于...
    Hsinwong閱讀 22,956評論 1 92
  • 第一部分:2017年回顧 參加易仁永澄年目標活動時制定的2017年目標:期待一:財務(wù)上額外收入15萬,增強家庭經(jīng)濟...
    oldmien閱讀 444評論 0 0
  • 2017年11月11日 星期六 晴 信任是雙方交往的基礎(chǔ),是人與人之間最美麗的語言。一個信任的眼神可以化解矛盾的堅...
    梓棱閱讀 392評論 0 0

友情鏈接更多精彩內(nèi)容