Struts2 에서 엑셀로 저장하기(Result를 엑셀로 지정)
물론 CSV로 요구사항을 충분히 만족시킬 수 있을 경우도 있으나 고품질의 엑셀 양식을 요구할 경우 위 두 방법은 웬지 부족함이 있다. 이럴 경우 엑셀 포맷으로 출력할 필요가 있는데 여러가지 솔루션이 있어 어렵지 않게
Java로 엑셀을 다루기 위한 방법은 여러가지 있으며 대표적인 것 3가지만 살펴본다.
apache 재단에서 진행되는 프로젝트이며 POI 패키지는 여러개의 다른 패키지(commons, log4j 같은..)를 필요로 한다. 풍부한 API를 제공하는 대신에 사용하기 번거로운 점이 있으며 많은 패키지를 필요로 한다는 부담이 있다.
사실 jXLS은 Javarta POI 패키지를 기반으로 동작한다. 따라서 jXLS을 사용하기 위해서는 POI가 사용하는 많은 다른 패키지를 필요로 한다.
반면 jXLS 자체는 매우 작으며 복잡한 보고서 생성이나 일정한 양식의 엑셀 데이터를 규칙에 따라 읽게 한다는 뚜렷한 목적이 있어 범용성은 약간 떨어지더라도 대부분의 엑셀 관련 작업에 훌륭한 솔루션이 될 수 있다.
우리는 jXLS을 이용하여 위 문제를 풀어본다.
jXLS은 템플릿을 기반으로 최종 엑셀파일을 생성한다.
JSP나 Velocity 또는 Freemarker 같이 템플릿을 만들고 출력할 데이터를 템플릿을 이용하여 변환하면 템플릿 모양대로 최종결과물이 생성하는 구조다.
간단한 예제로 설명을 한다.
private Long no;
private String name;
private String cellphone;
private String email;
public Long getNo() {
return no;
}
...
}
List<Customer> customers = new ArrayList<Customer>();
Customer customer = new Customer();
customer.setNo(1L);
...
customers.add(customer);
...
Map<String, Object> beans = new HashMap<String, Object>();
beans.put("customers", customers);
XLSTransformer transformer = new XLSTransformer();
transformer.transformXLS("엑셀템플릿파일이름.xls", beans, "엑셀결과파일이름.xls");
엑셀템플릿
이제 프로그램을 구동하면 자바객체를 이용하여 엑셀파일을 생성할 것이다.
우리는 경우에 따라 고객목록을 HTML로 출력하거나 엑셀파일로 다운로드할 것이다. 즉 동일한 데이터가 경우에 따라 표현하는 방법 만 달리하는 경우에 해당한다.
이런 요구사항은 흔히 발생하고 이런 경우 MVC 모델을 응용한 아키텍처를 많이 사용한다.
JXLSResult.java
(아래 소스의 저작권은 넥스트리소프트에 있습니다. 참조하여 사용하는 것은 문제가 없으나 저작권은 반드시 명시하여 주시기 바랍니다.)
private String template;
/** 엑셀에 출력할 객체들 */
private String beans;
/** 파일이름을 얻어올 키값 */
private String filenameKey = "filename";
public void execute(ActionInvocation invocation) throws Exception {
ActionContext actionContext = invocation.getInvocationContext();
= (ServletContext) actionContext.get(StrutsStatics.SERVLET_CONTEXT);
HttpServletResponse response
= (HttpServletResponse) actionContext.get(StrutsStatics.HTTP_RESPONSE);
Map<String, Object> beanParams = new HashMap<String, Object>();
String[] beanNames = splitBeans();
for (String beanName : beanNames) {
beanParams.put(beanName, invocation.getStack().findValue(beanName));
}
InputStream is = null;
HSSFWorkbook workbook;
try {
is = readTemplate(finalTemplate, context);
workbook = transformer.transformXLS(is, beanParams);
} finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {
// 무시
}
}
}
if (filename == null)
filename = "기본파일이름";
writeWorkbook(filename, response, workbook);
}
private String[] splitBeans() {
return this.beans.split(",");
}
private void writeWorkbook(
String filename, HttpServletResponse response, HSSFWorkbook workbook)
throws IOException {
response.setHeader(
"Content-disposition", "attachment;filename=" + encodeFileName(filename + ".xls"));
response.setContentType(FileServerUtil.getContentTypeOfFile("xls"));
}
private String encodeFileName(String filename) {
try {
return URLEncoder.encode(filename, "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e.getMessage, e);
}
}
private InputStream readTemplate(
String finalTemplate, ServletContext context) throws FileNotFoundException {
String templateFilePath = context.getRealPath(finalTemplate);
return new FileInputStream(templateFilePath);
}
* @param template 엑셀 템플릿
*/
public void setTemplate(String template) {
this.template = template;
}
* @param beans 엑셀에 출력할 객체들
*/
public void setBeans(String beans) {
this.beans = beans;
}
* @param filenameKey 파일이름을 얻어올 키값
*/
public void setFilenameKey(String filenameKey) {
this.filenameKey = filenameKey;
}
Struts2에 Result Type 추가
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
...
<package name="my-default" extends="struts-default">
<result-types>
<result-type name="excel" class="com.nextree.fw.commonweb.struts.result.JXLSResult" />
</result-types>
...
</package>
</struts>
Controller 작성
private List<Customer> customers;
public String execute() {
....
this.customers = ....; // 여기서 출력해야 할 데이터를 조회한다.
return Action.SUCCESS;
}
public List<Customer> getCustomers() {
return new JSONResult(this.zipCodeList);
}
/* 위 Excel Result type의 경우 file이름을 controller에서 가져오게 되어 있다. */
public String getFilename() {
return "고객목록";
}
}
<package name="mypackage" namespace="/mypackage" extends="my-default">
<action name="customers" class="test.CustomerListController" method="execute">
<result type="excel">
<param name="template">/customer/CustomerList.xls</param>
<param name="beans">customers</param>
<param name="filenameKey">filename</param>
</result>
</action>
...
이제 http://hostname:port/context/mypackage/customers.do 로 접속하면 Excel 파일을 다운로드 할 것이다.
'개발 이야기 > Java' 카테고리의 다른 글
[Hudson] Your container doesn't use UTF-8 to decode URLs (0) | 2009.09.08 |
---|---|
JOTM을 이용한 분산 트랜잭션 처리 - Spring (0) | 2009.06.15 |
ThreadLocal의 사용법과 활용 (0) | 2009.04.03 |
[JavaFX] 웹 서비스 액세스 :학습 곡선 일지 4편 (0) | 2008.09.25 |
[JavaFX] JavaFX 스크립트 함수 : 학습 곡선 일지 3편 (0) | 2008.09.25 |