iT邦幫忙

DAY 18
0

今天要分享輸出PDF格式,跟輸出Excel幾乎相同,最大的差別在於要render PDF麻煩多了,相關的API比較多,雖然iText官網上都有提供教學,不過還是google "iText table"比較快。

在新增class之前需要加入iText的Dependency:

<dependency>
	<groupId>com.itextpdf</groupId>
	<artifactId>itextpdf</artifactId>
	<version>5.5.3</version>
</dependency>

到Mvnrepository網站上的最新版是5.5.3,但還有一個舊版及其groupId跟最新版的不同,之後會提到目前Springframework似乎只認得舊版的groupId,等會會看到例外,Springframework提供o.s.web.servlet.view.document.AbstractPdfView供開發者繼承後override buildPdfDocument方法,新增PdfView Class繼承該class,要設定PDF為A4且為橫向,需要再override newDocument方法並設定PageSize參數為A4並呼叫rotate方法,

其code如下

import com.itextpdf.text.Chunk;
import com.itextpdf.text.Document;
import com.itextpdf.text.Element;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;


public class PdfView extends AbstractPdfView {
	
	@Autowired
	private DCNService dcnService; 
	
	@Override
	protected Document newDocument() {
		// TODO Auto-generated method stub
		return new Document(PageSize.A4.rotate());
	}

	protected void buildPdfDocument(Map<String, Object> model,
			Document document, PdfWriter writer, HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		// TODO Auto-generated method stub
		Paragraph p=new Paragraph();//新增一個段落,類似html的<p>
		p.add(new Chunk("DCN List")); //新增一個字串然後加到Paragraph
		p.setSpacingAfter(30); //設定Space
		document.add(p); //每個element都要加到document才會顯示
		
		List<DCN> dcnList=dcnService.findAll();
		
		PdfPTable table=new PdfPTable(DCN.class.getDeclaredFields().length-2); //初始化Table然後指定欄位數目
		table.setWidthPercentage(100.0f); //設定Table填滿至頁面Margin          //利用Reflect取得DCN的屬性數目然後扣掉
		table.setWidths(new int[] {1,2, 1,1,2,1,2});//設定相對欄寬                      //Serializable以及MultipartFile兩個屬性
		
		PdfPCell cell = new PdfPCell(); //初始化Cell(欄位)
		cell.setPhrase(new Phrase("Serial")); //填入Cell欄位字串,要new一個Phrase
		cell.setHorizontalAlignment(Element.ALIGN_CENTER); //置中對齊
		table.addCell(cell); //cell加到table中
		
		cell.setPhrase(new Phrase("DCN No"));
		cell.setHorizontalAlignment(Element.ALIGN_CENTER);
		table.addCell(cell);
		
		cell.setPhrase(new Phrase("DCN Rev"));
		cell.setHorizontalAlignment(Element.ALIGN_CENTER);
		table.addCell(cell);
		
		cell.setPhrase(new Phrase("Cateogy"));
		cell.setHorizontalAlignment(Element.ALIGN_CENTER);
		table.addCell(cell);
		
		cell.setPhrase(new Phrase("Tracking Number"));
		cell.setHorizontalAlignment(Element.ALIGN_CENTER);
		table.addCell(cell);
		
		cell.setPhrase(new Phrase("Issued Date"));
		cell.setHorizontalAlignment(Element.ALIGN_CENTER);
		table.addCell(cell);
		
		cell.setPhrase(new Phrase("Completed Date"));
		cell.setHorizontalAlignment(Element.ALIGN_CENTER);
		table.addCell(cell);
		
		Integer recordCounts=1; 
		for(DCN dcn:dcnList){ //利用for迴圈,把資料填入Cell
			table.addCell(recordCounts.toString()); //未支援數值,但可接受字串
			table.addCell(dcn.getNo());
			table.addCell(dcn.getRev().toString());
			table.addCell(dcn.getCategory());
			table.addCell(dcn.gettrackNumber().toString());
			table.addCell(dcn.getIssuedDate());
			table.addCell(dcn.getCompletedDate());
			recordCounts++;
		}
		document.add(table); //table加到document顯示
		
	}
}

接著更新dispatchservletcontext.xml,新增pdfView bean以及加入defaultViews list中

<!-- 新增PDF View bean並指定對應的class -->
	<bean id="pdfView" class=" tw.blogger.springtech.springmvc.view.PdfView"/>
	<bean
		class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
		<property name="defaultViews">
			<list>
				<ref bean="jsonView" />
				<ref bean="xmlView" />
				<ref bean="excelView"/>
				<ref bean="pdfView"/>
			</list>
		</property>
	</bean>

啟動Server,存取DCNList.jsp時會產生Exception,畫面如下。

因為iText新版的套件的名稱已經更換,AbstractPdfView僅認得com.lowagie套件的iText,故須用舊版的dependency:

<dependency>
	<groupId>com.lowagie</groupId>
	<artifactId>itext</artifactId>
	<version>4.2.1</version>
</dependency>

回到PdfView重新import相關套件,其實新版跟舊版的iText基本組件名稱並未改變,只是套件名稱不同而已。

並重新啟動Server,DCN List清單畫面如下:

輸出PDF檔以及Console log如下

23:18:14 [http-nio-8080-exec-36] DispatcherServlet - DispatcherServlet with name 'dispatcher' processing GET request for [/SpringMVC/dcn.pdf]
23:18:14 [http-nio-8080-exec-36] RequestMappingHandlerMapping - Looking up handler method for path /dcn.pdf
23:18:14 [http-nio-8080-exec-36] RequestMappingHandlerMapping - Returning handler method [public java.lang.String tw.blogger.springtech.springmvc.controller.DCNController.DCNList(org.springframework.ui.Model)]
23:18:14 [http-nio-8080-exec-36] DispatcherServlet - Last-Modified value for [/SpringMVC/dcn.pdf] is: -1
Hibernate: select dcn0_.prikey as prikey1_0_, dcn0_.category as category2_0_, dcn0_.completedDate as complete3_0_, dcn0_.issuedDate as issuedDa4_0_, dcn0_.no as no5_0_, dcn0_.rev as rev6_0_, dcn0_.trackNumber as trackNum7_0_ from DCN dcn0_
23:18:14 [http-nio-8080-exec-36] ContentNegotiatingViewResolver - Requested media types are [application/pdf] based on Accept header types and producible media types [*/*])
23:18:14 [http-nio-8080-exec-36] ContentNegotiatingViewResolver - Returning [tw.blogger.springtech.springmvc.view.PdfView: name 'pdfView'] based on requested media type 'application/pdf'
23:18:14 [http-nio-8080-exec-36] DispatcherServlet - Rendering view [tw.blogger.springtech.springmvc.view.PdfView: name 'pdfView'] in DispatcherServlet with name 'dispatcher'
Hibernate: select dcn0_.prikey as prikey1_0_, dcn0_.category as category2_0_, dcn0_.completedDate as complete3_0_, dcn0_.issuedDate as issuedDa4_0_, dcn0_.no as no5_0_, dcn0_.rev as rev6_0_, dcn0_.trackNumber as trackNum7_0_ from DCN dcn0_
23:18:15 [http-nio-8080-exec-36] DispatcherServlet - Successfully completed request

明日預計開始分享Spring Security或是穿插Hibernate Validator。


上一篇
[View]輸出Excel格式報表
下一篇
[Security]Spring Security簡介與第一個login畫面
系列文
無痛學習SpringMVC與Spring Security31

尚未有邦友留言

立即登入留言