Spring Boot匯出Pdf檔案
除了常見的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,顯示下面的結果