1. 程式人生 > >Spring Boot匯出Pdf檔案

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,顯示下面的結果
20.png