'FRAMEWORK/SPRING'에 해당되는 글 39건

  1. 2014.12.02 Spring MVC download files(04)
  2. 2014.12.02 Spring MVC download files(03)
  3. 2014.12.02 Spring MVC download files(02)
  4. 2014.12.02 Spring MVC download files(01)
  5. 2014.11.19 Spring MVC with Excel View Example (Apache POI and JExcelApi)
  6. 2014.11.19 Spring MVC – View (JSON, XML, PDF or Excel)
  7. 2014.11.11 <util:properties/> 와 Spring EL 로 값 가져오기
  8. 2014.11.10 Spring annotation
  9. 2014.11.05 뷰에 모델(Model) 전달
  10. 2014.11.05 @ModelAttribute 어노테이션

Spring MVC download files(04)

FRAMEWORK/SPRING 2014. 12. 2. 14:52


spring304.zip



FileDownloadController.java

package sp.mvc.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

 

@Controller
public class FileDownloadController {


 @RequestMapping(value="/filedown.sp")
 public ModelAndView fileDownload(){
  System.out.println("----- FileDownloadController.fileDownload() -----");
  
  ModelAndView modelAndView = new ModelAndView("filedownload");

  return modelAndView;
 }
}

 

FileDownloadView.java

package sp.mvc.view;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.servlet.view.AbstractView;

 

public class FileDownloadView extends AbstractView {

 

 public FileDownloadView(){
  setContentType("application/download; ccharset=utf-8");
 }
 
 @Override
 protected void renderMergedOutputModel(Map<String, Object> model,
   HttpServletRequest req, HttpServletResponse res) throws Exception {
  // TODO Auto-generated method stub

  System.out.println("---- FileDownloadView.renderMergedOutputModel() ----");
  
  java.io.File file = new java.io.File("C:\\Ins.log");
  
  res.setContentType(getContentType());
  res.setContentLength(100);

  
  String userAgent = req.getHeader("User-Agent");
  String fileName = null;
  
  if(userAgent.indexOf("MSIE") > -1){
   fileName = URLEncoder.encode(file.getName(), "utf-8");
  }else{
   fileName = new String(file.getName().getBytes("utf-8"), "iso-8859-1");
  }
  
  res.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\";");
  res.setHeader("Content-Transfer-Encoding", "binary");

  
  OutputStream os = res.getOutputStream();
  FileInputStream fis = null;
  
  try{
   fis = new FileInputStream(file);
   FileCopyUtils.copy(fis, os);
  }finally{
   if(fis != null){
    try{
     fis.close();
    }catch(IOException e){
     System.out.println("exception : " + e.toString());
    }
   }
  }
  os.flush();
  
 }
}

 

main_config.xml

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:context="http://www.springframework.org/schema/context
 xmlns:p="http://www.springframework.org/schema/p"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context-3.0.xsd">

 

 <context:annotation-config/>
 <context:component-scan base-package="sp.mvc.controller"/>
 
 <!-- bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" p:alwaysUseFullPath="true"/ -->
 <!-- bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" p:alwaysUseFullPath="true"/ --> 
 
  
 <!-- ViewResolver 설정 -->
 <bean id="beanNameViewResolver" class="org.springframework.web.servlet.view.BeanNameViewResolver" p:order="1"/>
 
 <bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"
  p:order="2" p:prefix="/WEB-INF/jsp/" p:suffix=".jsp"></bean>


 
 <!-- 각종 bean 설정 -->
 <bean id="filedownload" class="sp.mvc.view.FileDownloadView"></bean>
 
</beans>

● BeanNameViewResolver : 뷰 이름과 동일한 이름을 갖는 빈을 뷰 객체로 사용

 

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance
 xmlns="http://java.sun.com/xml/ns/javaee
 xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd
 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
  
  <display-name>spring304</display-name>

 <filter>
  <filter-name>characterEncodingFilter</filter-name>
  <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
  <init-param>
   <param-name>encoding</param-name>
   <param-value>UTF-8</param-value>
  </init-param>
 </filter>

 <filter-mapping>
  <filter-name>characterEncodingFilter</filter-name>
  <url-pattern>/*</url-pattern>
 </filter-mapping>


 <!-- 공통 빈 설정
 <context-param>
  <param-name>contextConfigLocation</param-name>
  <param-value>/WEB-INF/applicationContext.xml</param-value>
 </context-param>
   
 <listener>
  <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
 </listener>
 -->
 
 <servlet>
  <servlet-name>spring304</servlet-name>
  <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  <init-param>
   <param-name>contextConfigLocation</param-name>
   <param-value>
    /WEB-INF/main_config.xml
   </param-value>
  </init-param>
  <load-on-startup>1</load-on-startup>
 </servlet>
 
 <servlet-mapping>
  <servlet-name>spring304</servlet-name>
  <url-pattern>*.sp</url-pattern>
 </servlet-mapping>


</web-app>

 

 

결과

요청URL

   http://localhost:8090/spring304/filedown.sp

 

----- FileDownloadController.fileDownload() -----
---- FileDownloadView.renderMergedOutputModel() ----

 


출처 - http://0px.kr/326

'FRAMEWORK > SPRING' 카테고리의 다른 글

스프링 시큐리티(SPRING SECURITY)  (0) 2016.10.05
파일 업로드  (0) 2015.01.07
Spring MVC download files(03)  (0) 2014.12.02
Spring MVC download files(02)  (0) 2014.12.02
Spring MVC download files(01)  (0) 2014.12.02
:

Spring MVC download files(03)

FRAMEWORK/SPRING 2014. 12. 2. 14:51


SpringMVCDownloadFiles.7z


Spring MVC download files

In this tutorial you will see how to create Spring MVC application to download files from client interface:

  • pom.xml:

  • web.xml:

  •  helloWorld.jsp:

  • dispatcher-servlet.xml:

  • SpringMVCController.java:



출처 -http://javahonk.com/spring-mvc-download-files/

'FRAMEWORK > SPRING' 카테고리의 다른 글

파일 업로드  (0) 2015.01.07
Spring MVC download files(04)  (0) 2014.12.02
Spring MVC download files(02)  (0) 2014.12.02
Spring MVC download files(01)  (0) 2014.12.02
Spring MVC with Excel View Example (Apache POI and JExcelApi)  (0) 2014.11.19
:

Spring MVC download files(02)

FRAMEWORK/SPRING 2014. 12. 2. 14:49


FileDownloadSpringMVC.zip


The file to be downloaded in this application is SpringProject.zip file which resides in the downloads directory which is relative to the application’s directory.

1. Code of download page

Create index.jsp file under WebContent directory with the following HTML code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
    "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Download Page</title>
</head>
<body>
    <center>
        <h2><a href="/download.do">Click here to download file</a></h2>
    </center>
</body>
</html>

This page simply shows a link “Click here to download file” with URL points to the relative path: download.do. We’ll configure Spring controller class to handle this URL.


2. Code of Spring controller class

Create FileDownloadController.java file under the source package net.codejava.spring with the following code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
package net.codejava.spring;
 
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
 
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
 
@Controller
@RequestMapping("/download.do")
public class FileDownloadController {
     
    /**
     * Size of a byte buffer to read/write file
     */
    private static final int BUFFER_SIZE = 4096;
             
    /**
     * Path of the file to be downloaded, relative to application's directory
     */
    private String filePath = "/downloads/SpringProject.zip";
     
    /**
     * Method for handling file download request from client
     */
    @RequestMapping(method = RequestMethod.GET)
    public void doDownload(HttpServletRequest request,
            HttpServletResponse response) throws IOException {
 
        // get absolute path of the application
        ServletContext context = request.getServletContext();
        String appPath = context.getRealPath("");
        System.out.println("appPath = " + appPath);
 
        // construct the complete absolute path of the file
        String fullPath = appPath + filePath;      
        File downloadFile = new File(fullPath);
        FileInputStream inputStream = new FileInputStream(downloadFile);
         
        // get MIME type of the file
        String mimeType = context.getMimeType(fullPath);
        if (mimeType == null) {
            // set to binary type if MIME mapping not found
            mimeType = "application/octet-stream";
        }
        System.out.println("MIME type: " + mimeType);
 
        // set content attributes for the response
        response.setContentType(mimeType);
        response.setContentLength((int) downloadFile.length());
 
        // set headers for the response
        String headerKey = "Content-Disposition";
        String headerValue = String.format("attachment; filename=\"%s\"",
                downloadFile.getName());
        response.setHeader(headerKey, headerValue);
 
        // get output stream of the response
        OutputStream outStream = response.getOutputStream();
 
        byte[] buffer = new byte[BUFFER_SIZE];
        int bytesRead = -1;
 
        // write bytes read from the input stream into the output stream
        while ((bytesRead = inputStream.read(buffer)) != -1) {
            outStream.write(buffer, 0, bytesRead);
        }
 
        inputStream.close();
        outStream.close();
 
    }
}

This is a typical Spring controller class which is annotated by Spring MVC annotation types. The method doDownload() will receive requests from the client, read the file on server and send it to the client for downloading. Note that, unlike traditional Spring controller’s methods, the method doDownload()does not return a view name, because our purpose is to send a file to the client. The method exits as soon as the file is completely transferred to the client.

 


3. Code of Spring configuration file

Create spring-mvc.xml file under WebContent\WEB-INF directory with the following content:

1
2
3
4
5
6
7
8
9
10
11
12
13
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.0.xsd">
 
    <context:component-scan base-package="net.codejava.spring" />
 
    <!-- your beans declaration goes here -->
</beans>

This is a deadly simple Spring configuration file which tells the framework to scan the package net.codejava.spring for annotated types (element <context:component-scan />). Of course your application will have some bean definitions, but for the purpose of this application, such configuration is enough to work.

 

 


4. Code of web.xml

The Spring dispatcher servlet is configured to handle requests in the web.xml file as follows:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
        http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    id="WebApp_ID" version="3.0">
    <display-name>FileDownloadSpringMVC</display-name>
    <servlet>
        <servlet-name>SpringController</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/spring-mvc.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
 
    <servlet-mapping>
        <servlet-name>SpringController</servlet-name>
        <url-pattern>*.do</url-pattern>
    </servlet-mapping>
</web-app>

  


5. Required jar files

Add the following jar files into the WebContent\WEB-INF\lib directory:

    1. commons-logging-1.1.1.jar
    2. spring-beans-3.2.1.RELEASE.jar
    3. spring-context-3.2.1.RELEASE.jar
    4. spring-core-3.2.1.RELEASE.jar
    5. spring-expression-3.2.1.RELEASE.jar
    6. spring-web-3.2.1.RELEASE.jar
    7. spring-webmvc-3.2.1.RELEASE.jar

The Commons Logging jar files can be downloaded from Apache Commons Logging, other jar files come from Spring framework 3.2.1 RELEASE download.


출처 - http://www.codejava.net/frameworks/spring/spring-mvc-sample-application-for-downloading-files

:

Spring MVC download files(01)

FRAMEWORK/SPRING 2014. 12. 2. 14:47

스프링에서 지원하는 다운로드를 쓰려면 아래와 같이 하시오.!

일단 기본적으로 파일 다운로드 처리하기에 앞서서 알아야 할 사항을 배워보도록 하자.

1. 파일링크를 클릭할때 컨트롤러 클래스에게 파일패스와 파일이름을 던져주고 

2. 받은 컨트롤러 클래스에서 그 파일 패스와 파일이름으로 file 을 만들어서 (DownloadController)

3. 뷰로 전달을 할 것이다. 

4. 그럼 뷰에서 받은 file 정보를 이용해서 실제 파일을 읽어들인 다음 원하는 위치에 쓰는 작업을 한다. (DownloadView)

 

 

일반적인 컨트롤러 클래스에서 작업을 한 후, 뷰 페이지로 결과값을 뿌려주는 것인데

일반적인 뷰페이지는 JSP 페이지였다.

하지만 다운로드에 사용될 뷰는 JSP 가 아니라  클래스 파일이다. 



그렇기 때문에 아래처럼 일반적으로 사용하던 viewResolver 가 처리하는 것이 아니라

<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">

<property name="prefix" value="/"/>

<property name="suffix" value=".jsp"/>

<property name="order" value="1"/>

</bean>  






download 만을 처리하는 viewResolver 가 따로 존재해야 한다. 여기에는 id값이 없다...주의할것!!!!!!!!!

<bean class="org.springframework.web.servlet.view.BeanNameViewResolver">

       <property name="order" value="0"/>

</bean>


주의할 점은 위 두 코드에 포함된 프로퍼티를 보면 order 라는 프로퍼티가 있는데

이 프로퍼티는 두개이상 존재하는 viewResolver 를 위해서

우선순위를 매기는 것이다. 만약 우선순위를 명시 하지 않으면 "가장 낮은 우선순위를 갖게 된다."

우선순위는 "0"이 가장 먼저 실행되고, 이후로 매겨지는 순서에 따라 실행된다.


다음 viewResolver가 실행되는 기준은 "null" 이 반환되느냐 가 기준이다. 

그렇기 때문에 널값이 있을수 없는 InternalResourceViewResolver 가 우선순위가 높게 되면, 
다른 viewResolver 는 사용되지 않게되는
문제가 있다. (항상 뷰 이름에 매핑이 되는 뷰 객체를 리턴하기 때문)

 그래서 InternalResourceViewResolver 은 우선순위가 가장 낮아야 한다.





그러면 이제 BeanNameViewResolver 를 사용하는 법을 알아 보자


BeanNameViewResolver (파일 다운로드 viewResolver)

"null" 이 반환되지 않는다면, (즉 컨트롤러 클래스에서 리턴되온 뷰페이지 값과 일치하는 빈이 있는 경우)


컨트롤러 클래스에서 리턴되온 뷰페이지 값과 일치하는  빈이 등록되있는 경우는 그 빈에 해당하는 컨트롤러 클래스가

파일 다운로드를 처리하게 된다.  

그렇기 때문에 컨트롤러 클래스에서 viewResolver 로 던져줄 뷰페이지 이름과, 처리할 View 클래스 빈이름이 같아야 한다. 
(이말을 반대로 하자면, 실제 jsp 가 보여져야될 때는 리턴값과, view 빈 이름이 같아서는 절대 안된다.)
 

<bean id="download" class="Spring.DownloadView"/>
    - 이 코드가 다운로드를 처리할 뷰 클래스를 등록하는 것이다.
       저기 id="download" 라고 되있는 부분과, 클래스에서 리턴된 값이 같아야 한다.



그리고 url 을 처리할 컨트롤러 클래스도 등록되야되겠지.

<bean id="down" class="Spring.DownloadController"/>




여기 까지가 좀 복잡하지만 servlet.xml 파일을 설정하는 부분이다. 
하나하나 천천히 다시 읽어보면 이해가 될 것이다.






이제 처음부터 하나씩 따라가보자.


파일 이름에 링크를 걸어서 컨트롤러 클래스로 넘기는 부분부터 시작

<a href="/Spring_margo/download.do?path=${path }&fileName=${itemBean.fileName }" >       ${itemBean.fileName }      </a>

download.do 로 파일네임과 패스를 넘기게 되어있다. 







그럼 저 url 을 처리하는 컨트롤 클래스는 아래와 같다.
<bean id="down" class="Spring.DownloadController"/>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
@Controller
public class DownloadController implements ApplicationContextAware{
 
    private WebApplicationContext context = null;
     
    @RequestMapping("download.do")
    public ModelAndView download(@RequestParam("path")String path,
                                  @RequestParam("fileName")String fileName){
         
        String fullPath = path + "\\" + fileName;
         
        File file = new File(fullPath);
         
        return new ModelAndView("download", "downloadFile", file);
    }
 
    @Override
    public void setApplicationContext(ApplicationContext arg0)
            throws BeansException {
        // TODO Auto-generated method stub
         
        this.context = (WebApplicationContext)arg0;
         
    }
     
}


@RequestMapping("download.do") 어노테이션으로 지정해준것처럼 
download.do 가 들어오면 저 메소드가 동작한다. 
링크에서 준것처럼 패스와 파일네임을 받아서

파일에 조합해서 쓰고 "download" 뷰페이지로 파일을 "downloadFile"이름으로 삽입하고 리턴시킨다.

그러면 <bean class="org.springframework.web.servlet.view.BeanNameViewResolver">

저 viewResolver 가 먼저 리턴을 처리하려 할 것이다.

"download"로 등록된 빈이 있는지 찾아 보는데 우리는 아까 "download"로 뷰클래스를 등록시켜 놓았다.  
<bean id="download" class="Spring.DownloadView"/>

이제 DownloadView.java 클래스가 뷰페이지로 동작할 것이다.
뷰페이지에서는 map 에 등록된 파일을 이용해서 encoding 설정과 헤더설정을 해준 후 파일을 지정위치에 쓴다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
import java.io.File;
import java.io.FileInputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.Map;
 
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
import org.springframework.util.FileCopyUtils;
import org.springframework.web.servlet.view.AbstractView;
 
public class DownloadView extends AbstractView {
 
 
    public void Download(){
         
        setContentType("application/download; utf-8");
         
    }
         
    @Override
    protected void renderMergedOutputModel(Map<string, object=""> model,
            HttpServletRequest request, HttpServletResponse response) throws Exception {
        // TODO Auto-generated method stub
         
        File file = (File)model.get("downloadFile");
        System.out.println("DownloadView --> file.getPath() : " + file.getPath());
        System.out.println("DownloadView --> file.getName() : " + file.getName());
         
        response.setContentType(getContentType());
        response.setContentLength((int)file.length());
         
        String userAgent = request.getHeader("User-Agent");
         
        boolean ie = userAgent.indexOf("MSIE") > -1;
         
        String fileName = null;
         
        if(ie){
             
            fileName = URLEncoder.encode(file.getName(), "utf-8");
                         
        } else {
             
            fileName = new String(file.getName().getBytes("utf-8"));
             
        }// end if;
 
         
        response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\";");
         
        response.setHeader("Content-Transfer-Encoding", "binary");
         
        OutputStream out = response.getOutputStream();
         
        FileInputStream fis = null;
         
        try {
             
            fis = new FileInputStream(file);
             
            FileCopyUtils.copy(fis, out);
             
             
        } catch(Exception e){
             
            e.printStackTrace();
             
        }finally{
             
            if(fis != null){
                 
                try{
                    fis.close();
                }catch(Exception e){}
            }
             
        }// try end;
         
        out.flush();
         
    }// render() end;
}
</string,>



출처 - http://winmargo.tistory.com/103

:

Spring MVC with Excel View Example (Apache POI and JExcelApi)

FRAMEWORK/SPRING 2014. 11. 19. 17:29


SpringMvcExcelViewDemo.zip


SpringMvcExcelViewDemo2.zip




About Apache POI

Apache POI is a set of pure Java libraries for reading and writing Microsoft Office documents such as Word, Excel, Powerpoint, Outlook, etc. Click the following link to download its latest distribution (which is Apache POI 3.9, as of this writing):

Apache POI Download

The distribution comes with several jar files, but the only the poi-VERSION.jar file is required for typical usage of generating Excel documents (if you want to generate Excel XML format such as *.xlsx files, use the poi-ooxml-VERSION.jar file).

To generate an Excel document using Apache POI within Spring, we need to create a view class that extends from theAbstractExcelView class and override its method buildExcelDocument(). Then using Apache POI’s Excel API to generate the excel document.

About JExcelApi

JExcelApi is a Java library that is dedicated for reading, writing and modifying Excel spreadsheets. It supports Excel 2003 file format and older versions. You can download JExcelApi from the following link:

                JExcelApi Download

To work with JExcelApi, you need to add its only jar file: jxl.jar - to your project’s classpath. And Spring provides an abstract class calledAbstractJExcelView which should be extended to generate an Excel document using JExcelApi, similarly to the case of Apache POI.

This tutorial will use Apache POI for the sample application. However, you can also download a JExcelApi version of the project in the Attachments section.

In Eclipse IDE, create a Dynamic Web Project calledSpringMvcExcelViewDemo. We will end up with the following project structure:



The jar files used are:

      • spring-beans-3.2.3.RELEASE.jar
      • spring-context-3.2.3.RELEASE.jar
      • spring-context-support-3.2.3.RELEASE.jar
      • spring-core-3.2.3.RELEASE.jar
      • spring-expression-3.2.3.RELEASE.jar
      • spring-web-3.2.3.RELEASE.jar
      • spring-webmvc-3.2.3.RELEASE.jar
      • commons-logging-1.1.1.jar
    • Apache POI:
      • poi-3.9-20121203.jar

 

Recommended Book: Getting started with Spring Framework

 

1. Creating Model Class

We will generate an Excel document that contains a list of Java books, so create the following model class (Book.java):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package net.codejava.spring;
 
public class Book {
    private String title;
    private String author;
    private String isbn;
    private String publishedDate;
    private float price;
 
    public Book(String title, String author, String isbn, String publishedDate,
            float price) {
        this.title = title;
        this.author = author;
        this.isbn = isbn;
        this.publishedDate = publishedDate;
        this.price = price;
    }
 
    // getters and setters
 
}


2. Coding Entry JSP Page

We need to create a JSP page that displays a hyperlink on which the users will click to download the Excel file. Create a folder called jsp inside WEB-INF directory and create a JSP file called home.jsp under WEB-INF\jsp with the following content:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
    "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Spring MVC Excel View Demo (Apache POI)</title>
</head>
<body>
    <div align="center">
        <h1>Spring MVC Excel View Demo (Apache POI)</h1>
        <h3><a href="/downloadExcel">Download Excel Document</a></h3>
    </div>
</body>
</html>

The hyperlink Download Excel Document points to a relative URL downloadExcel which will be handled by a Spring controller class as described below.

 


3. Coding Spring Controller

Create a Spring controller class called MainController with the following code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
package net.codejava.spring;
 
import java.util.ArrayList;
import java.util.List;
 
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;
 
/**
 * A Spring controller that allows the users to download an Excel document
 * generated by the Apache POI library.
 *
 * @author www.codejava.net
 *
 */
@Controller
public class MainController {
 
    /**
     * Handle request to the default page
     */
    @RequestMapping(value = "/", method = RequestMethod.GET)
    public String viewHome() {
        return "home";
    }
 
    /**
     * Handle request to download an Excel document
     */
    @RequestMapping(value = "/downloadExcel", method = RequestMethod.GET)
    public ModelAndView downloadExcel() {
        // create some sample data
        List<Book> listBooks = new ArrayList<Book>();
        listBooks.add(new Book("Effective Java""Joshua Bloch""0321356683",
                "May 28, 2008"38.11F));
        listBooks.add(new Book("Head First Java""Kathy Sierra & Bert Bates",
                "0596009208""February 9, 2005"30.80F));
        listBooks.add(new Book("Java Generics and Collections",
                "Philip Wadler""0596527756""Oct 24, 2006"29.52F));
        listBooks.add(new Book("Thinking in Java""Bruce Eckel""0596527756",
                "February 20, 2006"43.97F));
        listBooks.add(new Book("Spring in Action""Craig Walls""1935182358",
                "June 29, 2011"31.98F));
 
        // return a view which will be resolved by an excel view resolver
        return new ModelAndView("excelView""listBooks", listBooks);
    }
}

As we can see, this controller class implements two request handling methods:

    • viewHome(): this method simply returns a logical view name “home” which will be resolved to the home.jsp page (We will configure view resolver for JSP later).
    • downloadExcel(): this method creates some dummy data, e.g. creating some books and add them to a list. Finally this method returns a logical view name “excelView” and passes the list of books as the name “listBooks” to the model. We will configure an Excel view class for this view later.

       

Recommended Book: Spring in Action


4. Coding Excel View Class

To generate an Excel document from the model data passed by the controller, create a subclass of theAbstractExcelView class as follows:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
package net.codejava.spring;
 
import java.util.List;
import java.util.Map;
 
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Font;
import org.springframework.web.servlet.view.document.AbstractExcelView;
 
/**
 * This class builds an Excel spreadsheet document using Apache POI library.
 * @author www.codejava.net
 *
 */
public class ExcelBuilder extends AbstractExcelView {
 
    @Override
    protected void buildExcelDocument(Map<String, Object> model,
            HSSFWorkbook workbook, HttpServletRequest request, HttpServletResponse response)
            throws Exception {
        // get data model which is passed by the Spring container
        List<Book> listBooks = (List<Book>) model.get("listBooks");
         
        // create a new Excel sheet
        HSSFSheet sheet = workbook.createSheet("Java Books");
        sheet.setDefaultColumnWidth(30);
         
        // create style for header cells
        CellStyle style = workbook.createCellStyle();
        Font font = workbook.createFont();
        font.setFontName("Arial");
        style.setFillForegroundColor(HSSFColor.BLUE.index);
        style.setFillPattern(CellStyle.SOLID_FOREGROUND);
        font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
        font.setColor(HSSFColor.WHITE.index);
        style.setFont(font);
         
        // create header row
        HSSFRow header = sheet.createRow(0);
         
        header.createCell(0).setCellValue("Book Title");
        header.getCell(0).setCellStyle(style);
         
        header.createCell(1).setCellValue("Author");
        header.getCell(1).setCellStyle(style);
         
        header.createCell(2).setCellValue("ISBN");
        header.getCell(2).setCellStyle(style);
         
        header.createCell(3).setCellValue("Published Date");
        header.getCell(3).setCellStyle(style);
         
        header.createCell(4).setCellValue("Price");
        header.getCell(4).setCellStyle(style);
         
        // create data rows
        int rowCount = 1;
         
        for (Book aBook : listBooks) {
            HSSFRow aRow = sheet.createRow(rowCount++);
            aRow.createCell(0).setCellValue(aBook.getTitle());
            aRow.createCell(1).setCellValue(aBook.getAuthor());
            aRow.createCell(2).setCellValue(aBook.getIsbn());
            aRow.createCell(3).setCellValue(aBook.getPublishedDate());
            aRow.createCell(4).setCellValue(aBook.getPrice());
        }
    }
 
}

 

For working with JExcelApi, make the class extends the AbstractJExcelView class like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
package net.codejava.spring;
 
import java.util.List;
import java.util.Map;
 
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
import jxl.write.Label;
import jxl.write.WritableSheet;
import jxl.write.WritableWorkbook;
 
import org.springframework.web.servlet.view.document.AbstractJExcelView;
 
/**
 * This class builds an Excel spreadsheet document using JExcelApi library.
 * @author www.codejava.net
 *
 */
public class ExcelBuilder extends AbstractJExcelView {
 
    @Override
    protected void buildExcelDocument(Map<String, Object> model,
            WritableWorkbook workbook, HttpServletRequest request,
            HttpServletResponse response) throws Exception {
         
        // get data model which is passed by the Spring container
        List<Book> listBooks = (List<Book>) model.get("listBooks");
         
        // create a new Excel sheet
        WritableSheet sheet = workbook.createSheet("Java Books"0);
         
        // create header row
        sheet.addCell(new Label(00"Book Title"));
        sheet.addCell(new Label(10"Author"));
        sheet.addCell(new Label(20"ISBN"));
        sheet.addCell(new Label(30"Published Date"));
        sheet.addCell(new Label(40"Price"));
         
        // create data rows
        int rowCount = 1;
         
        for (Book aBook : listBooks) {
            sheet.addCell(new Label(0, rowCount, aBook.getTitle()));
            sheet.addCell(new Label(1, rowCount, aBook.getAuthor()));
            sheet.addCell(new Label(2, rowCount, aBook.getIsbn()));
            sheet.addCell(new Label(3, rowCount, aBook.getPublishedDate()));
            sheet.addCell(new jxl.write.Number(4, rowCount, aBook.getPrice()));
             
            rowCount++;
        }
    }
}

The above code is self-explanatory. As you can see, there are some differences between the Apache POI API and the JExcelApi.

 

Recommended Book: Spring Integration in Action


5. Configuring Excel View Class

Next, we need to tell Spring to use the above ExcelBuilder class as view class for the view name “excelView” returned from the controller’s downloadExcel() method. There are two ways to do this by creating either a .properties file or an XML file.

Using views.properties file:

Create a .properties file called views.properties under the project’s classpath (which is under src directory in the Eclipse project), with the following line:

1
excelView.(class)=net.codejava.spring.ExcelBuilder

That tells the Spring’s view resolver to use the net.codejava.spring.ExcelBuilder class to process output for the view name “excelView”.

 

Using views.xml file:

An alternative to the views.properties file is to use XML version. Create views.xml file under WEB-INF directory with the following content:

1
2
3
4
5
6
7
8
9
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
     
    <bean id="excelView" class="net.codejava.spring.ExcelBuilder" />
     
</beans>

Note that the bean’s ID attribute must correspond to the view name “excelView”.

 


6. Writing Spring Configuration File

Create a Spring configuration file named spring-mvc.xml under WEB-INF directory. In case you are usingviews.properties file, put the following content:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.0.xsd">
 
    <context:component-scan base-package="net.codejava.spring" />
 
   <bean id="viewResolver1" class="org.springframework.web.servlet.view.ResourceBundleViewResolver">
        <property name="order" value="1"/>
        <property name="basename" value="views"/>
    </bean>
     
    <bean id="viewResolver2"
        class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="order" value="2"/>
        <property name="prefix" value="/WEB-INF/jsp/" />
        <property name="suffix" value=".jsp" />
    </bean>
     
</beans>

As seen in the above configuration, there are two view resolvers used here:

    • ResourceBundleViewResolver: to resolve view names specified in the views.properties file.
    • InternalResourceViewResolver: to resolve view names to JSP pages.

The order property does matter here, in which the first resolver has higher priority than the second one.

 

In case the views.xml is used, configure Spring as follows:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.0.xsd">
 
    <context:component-scan base-package="net.codejava.spring" />
 
   <bean id="viewResolver1" class="org.springframework.web.servlet.view.XmlViewResolver">
        <property name="order" value="1"/>
        <property name="location" value="/WEB-INF/views.xml"/>
    </bean>
     
    <bean id="viewResolver2"
        class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="order" value="2"/>
        <property name="prefix" value="/WEB-INF/jsp/" />
        <property name="suffix" value=".jsp" />
    </bean>
 
     
</beans>

 

Recommended Book: Spring Batch in Action


7. Configuring Spring MVC in web.xml

The final step is to configure Spring MVC in the web deployment descriptor file as follows:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
        http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    id="WebApp_ID" version="3.0">
     
    <display-name>SpringMvcExcelViewDemo</display-name>
     
    <servlet>
        <servlet-name>SpringController</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/spring-mvc.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
 
    <servlet-mapping>
        <servlet-name>SpringController</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping
</web-app>


8. Testing the application

Type the following URL into browser to access the application we’ve built:

http://localhost:8080/SpringMvcExcelViewDemo/


 

Download Eclipse project for this application in the Attachments section below. 

Recommended Book: Pro Spring 3

Related Course: The Java Spring Tutorial


출처 - http://www.codejava.net/frameworks/spring/spring-mvc-with-excel-view-example-apache-poi-and-jexcelapi


'FRAMEWORK > SPRING' 카테고리의 다른 글

Spring MVC download files(02)  (0) 2014.12.02
Spring MVC download files(01)  (0) 2014.12.02
Spring MVC – View (JSON, XML, PDF or Excel)  (0) 2014.11.19
<util:properties/> 와 Spring EL 로 값 가져오기  (0) 2014.11.11
Spring annotation  (0) 2014.11.10
:

Spring MVC – View (JSON, XML, PDF or Excel)

FRAMEWORK/SPRING 2014. 11. 19. 17:22

Spring MVC – View (JSON, XML, PDF or Excel)

Content negotiation in Spring MVC allows you to view data in different format based on the request media type. Here we will see how to view the same data in different media types “json, xml, pdf & excel”.

Objectives:

  • How to configure spring to respond to different media type request?
  • How to return data in json, xml, pdf or excel format?
  • How to write PDF view using iText & Excel view using Apache POI for Excel 2007+?

Environment & Tools:

  • Eclipse
  • Maven
  • Jetty (or any other server)

Libraries:

About This Sample:

  • Client will send GET request to view data “list of articles” in one of the available formats “mime type” (json, xml, pdf or excel).
  • The request is mapped to Spring MVC controller which will respond to the client with the data in requested format.
  • Spring is configured to detect the requested content type and prepare data in required format accordingly.
  • Formatting data in JSON and XML is straight forward no coding is needed if the default output is meeting our requirement.
  • However formatting the data in PDF or Excel needs some coding to prepare the layout of these documents. For PDF we will be using iText and for Excel we will be using Apache POI
  • The data source in this example “list of articles” is an XML file “articles.xml” which will be converted into Java object “LinkedList<Article>” using Castor XML mapping before responding to the client. The data source can be DB, text file, or just hard coded data.

( 1 ) Project Structure



( 2 ) Data Model & Source

  • src/main/java/com/hmkcode/vo/Article.java

This is a class is data model that will hold our data

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package com.hmkcode.vo;
 
import java.util.LinkedList;
import java.util.List;
 
public class Article {
 
    private String title;
    private String url;
    private List<String> categories;
    private List<String> tags;
 
    //getters & setters...
 
}
  • articles.xml

This XML file is just the source of data to be sent to the client. The data source can be also database, text file or hard-coded data.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?xml version="1.0" encoding="UTF-8"?>
<linked-list>
    <article xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  xsi:type="java:com.hmkcode.vo.Article">
        <categories xsi:type="java:java.lang.String">Spring</categories>
        <tags xsi:type="java:java.lang.String">Spring</tags>
        <tags xsi:type="java:java.lang.String">JSON</tags>
        <tags xsi:type="java:java.lang.String">XML</tags>
        <tags xsi:type="java:java.lang.String">iText</tags>
        <tags xsi:type="java:java.lang.String">Apache POI</tags>
        <title> Spring MVC View (JSON, XML, PDF or Excel) </title>
    </article>
.....
.....
</linked-list>

( 3 ) Web & Spring Configuration

  • Controller.java
  • rest-servlet.xml
  • web.xml
  • index.html
  • /src/main/java/com/hmkcode/controllers/Controller.java

This class is the controller that will receive client request. Client can call this controller by send GET request to /rest/controller/get URL.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
package com.hmkcode.controllers;
 
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.util.LinkedList;
import org.exolab.castor.xml.MarshalException;
import org.exolab.castor.xml.Unmarshaller;
import org.exolab.castor.xml.ValidationException;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
 
import com.hmkcode.vo.Article;
 
@Controller
@RequestMapping("/controller")
public class MyController {
 
    public MyController(){
        System.out.println("Init MyController");
    }
 
    @RequestMapping(value = "/get", method = RequestMethod.GET)
     public  LinkedList<Article>  get(Model model) {                
 
        FileReader reader;
 
        LinkedList<Article> articles = null;
 
        try {
 
            reader = new FileReader("articles.xml");
            //convert "unmarshal" data from XML "articles.xml" to Java object LinkedList<Article>
            articles = (LinkedList) Unmarshaller.unmarshal(LinkedList.class, reader);
            model.addAttribute("articles",articles);
 
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (MarshalException e) {
            e.printStackTrace();
        } catch (ValidationException e) {
            e.printStackTrace();
        }
 
        return articles;
 
    }
 
}
  • /src/main/webapp/WEB-INF/rest-servlet.xml

In this file we configure spring to handle the request of different media type by setting upContentNegotiatingViewResolver bean. Two properties of ContentNegotiatingViewResolver need to be set  “mediaTypes” & “defaultViews“. The first property “mediaTypes” will contain a map of accepted types, the key of this map is the extension that will be passed with request e.g. /rest/controller/get.xlsx while the value is the media type standard name e.g. application/json. The second “defaultViews” list the beans that will generate the data in the requested format.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
    xsi:schemaLocation="
 
 
 
 
 
 
 
 
 
 
 
 
    <context:component-scan base-package="com.hmkcode.controllers" />
    <mvc:annotation-driven />
 
    <bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">     
        <property name="order" value="1" />     
        <property name="mediaTypes">       
            <map>          
              <entry key="json" value="application/json" />          
              <entry key="xml" value="application/xml" />          
              <entry key="pdf" value="application/pdf" />
              <entry key="xlsx" value="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" />       
            </map>     
        </property>      
 
        <property name="defaultViews">       
            <list>         
                <!-- JSON View -->         
                <bean            class="org.springframework.web.servlet.view.json.MappingJacksonJsonView">         
                </bean>         
 
                <!--  XML view -->           
                <bean class="org.springframework.web.servlet.view.xml.MarshallingView">           
                <constructor-arg>               
                    <bean class="org.springframework.oxm.castor.CastorMarshaller">                             
                    </bean>           
                </constructor-arg>         
                </bean>         
 
                <!--  PDF view -->         
                <bean class="com.hmkcode.view.PDFView">            
                </bean>
 
                <!--  XLSX "Excel" view -->         
                <bean class="com.hmkcode.view.ExcelView">            
                </bean>
            </list>     
        </property>     
 
        <property name="ignoreAcceptHeader" value="true" />    
    </bean>
</beans>
  • /src/main/webapp/WEB-INF/web.xml

This is the standard web.xml to define our servlets. Here we define the URL pattern of the requests to be passed to Spring DispatcherServlet.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?xml version="1.0" encoding="UTF-8"?>
  <display-name>SpringMVC</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
  </welcome-file-list>
  <servlet>
    <servlet-name>rest</servlet-name>             
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>rest</servlet-name>
    <url-pattern>/rest/*</url-pattern>
  </servlet-mapping>
</web-app>
  • /src/main/webapp/index.html

Just a simple file to display the first page of our web app. Twitter bootstrap is used just for good looking design!.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Spring MVC - View (JSON, XML, PDF, Excel)</title>
    <link href="bootstrap/css/bootstrap.min.css" rel="stylesheet">
</head>
 
<body>
 
<h1>Spring MVC - View (JSON, XML, PDF, Excel)</h1>
<div style="margin:10px;width:700px;text-align:center">   
    <a href="/spring-mvc-json-pdf-xls/rest/controller/get.json" class="label label-info">JSON</a>
    <a href="/spring-mvc-json-pdf-xls/rest/controller/get.xml" class="label label-info">XML</a>
    <a href="/spring-mvc-json-pdf-xls/rest/controller/get.pdf" class="label label-info">PDF</a>
    <a href="/spring-mvc-json-pdf-xls/rest/controller/get.xlsx" class="label label-info">Excel</a>
</div>
 
</body>
</html>

( 4 ) Views PDF & Excel

Spring provides an abstract classorg.springframework.web.servlet.view.document.AbstractPdfView that we can extends to write our PDF view implementation. This class supports only old version of iText “Bruno Lowagie’siText“. If we would like to use the newer version of iText then we need to rewriteAbstractPdfView to be compatible with iText (5.x).

Spring provides abstract classorg.springframework.web.servlet.view.document.AbstractExcelView that we can extends to write our Excel view implementation. This class support only Excel 97 – 2007 or “.xls” file. If we want to create Excel 2007+  or “.xlsx” document we need to rewrite AbstractExcelView to be compatible with POI-XSSF.

  • /src/main/java/com/hmkcode/view/PDFView.java

This is class create our PDF document using iText (5.4.2)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
package com.hmkcode.view;
 
import java.util.LinkedList;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.hmkcode.view.abstractview.AbstractPdfView;
import com.hmkcode.vo.Article;
import com.itextpdf.text.Anchor;
import com.itextpdf.text.BaseColor;
import com.itextpdf.text.Chunk;
import com.itextpdf.text.Document;
import com.itextpdf.text.Font;
import com.itextpdf.text.Font.FontFamily;
import com.itextpdf.text.pdf.PdfWriter;
 
public class PDFView extends AbstractPdfView {
 
    protected void buildPdfDocument(       
            Map<String, Object> model,       
            Document document,       
            PdfWriter writer,       
            HttpServletRequest req,       
            HttpServletResponse resp)       
                    throws Exception {
 
        // Get data "articles" from model
        @SuppressWarnings("unchecked")
        LinkedList<Article> articles = (LinkedList<Article>) model.get("articles");
 
        // Fonts
        Font fontTitle = new Font(FontFamily.TIMES_ROMAN, 14, Font.BOLD, BaseColor.BLACK);
        Font fontTag = new Font(FontFamily.HELVETICA, 10, Font.BOLD, BaseColor.WHITE);
 
        for(Article article:articles){
 
            // 1.Title
            document.add(new Chunk("Title: "));
            Chunk title = new Chunk(article.getTitle(), fontTitle);
            document.add(title);
            document.add(new Chunk(" "));
 
            // -- newline
            document.add(Chunk.NEWLINE);
 
            // 2.URL
            document.add(new Chunk("URL: "));
            Anchor url  = new Anchor(article.getUrl());
            url.setName(article.getUrl());
            url.setReference(article.getUrl());
            document.add(url);
 
            // -- newline
            document.add(Chunk.NEWLINE);
 
            // 3.Categories
            Chunk cat = null;
            document.add(new Chunk("Category: "));
            for(String category:article.getCategories()){
                cat =  new Chunk(category, fontTag);
                cat.setBackground(new BaseColor(72, 121, 145), 1f, 0.5f, 1f, 1.5f);
                document.add(cat);
                document.add(new Chunk(" "));
 
            }
 
            // -- newline
            document.add(Chunk.NEWLINE);
 
            // 4.Tags
            Chunk tg = null;
            document.add(new Chunk("Tags: "));
            for(String tag:article.getTags()){
                tg =  new Chunk(tag, fontTag);
                tg.setBackground(new BaseColor(97, 97, 97), 1f, 0.5f, 1f, 1.5f);
                document.add(tg);
                document.add(new Chunk(" "));
 
            }
 
            // -- newline
            document.add(Chunk.NEWLINE);
            document.add(Chunk.NEWLINE);
 
        }
 
    }
 
}
  • /src/main/java/com/hmkcode/view/ExcelView.java

This class create Excel document using Apache POI-XSSF

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
package com.hmkcode.view;
 
import java.util.LinkedList;
import java.util.Map;
 
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
import org.apache.poi.ss.formula.functions.Hyperlink;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
 
import com.hmkcode.view.abstractview.AbstractExcelView;
import com.hmkcode.vo.Article;
 
public class ExcelView extends AbstractExcelView {
 
    @Override
    protected void buildExcelDocument(Map<String, Object> model,
            Workbook workbook, HttpServletRequest request,
            HttpServletResponse response) throws Exception {
 
        Sheet sheet = workbook.createSheet("sheet 1");
 
        @SuppressWarnings("unchecked")
        LinkedList<Article> articles = (LinkedList<Article>) model.get("articles");
 
        Row row = null;
        Cell cell = null;
        int r = 0;
        int c = 0;
 
        //Style for header cell
        CellStyle style = workbook.createCellStyle();
        style.setFillForegroundColor(IndexedColors.GREY_40_PERCENT.index);
        style.setFillPattern(CellStyle.SOLID_FOREGROUND);
        style.setAlignment(CellStyle.ALIGN_CENTER);
 
        //Create header cells
        row = sheet.createRow(r++);
 
        cell = row.createCell(c++);
        cell.setCellStyle(style);
        cell.setCellValue("Title");
 
        cell = row.createCell(c++);
        cell.setCellStyle(style);
        cell.setCellValue("URL");
 
        cell = row.createCell(c++);
        cell.setCellStyle(style);
        cell.setCellValue("Categories");
 
        cell = row.createCell(c++);
        cell.setCellStyle(style);
        cell.setCellValue("Tags");
 
        //Create data cell
        for(Article article:articles){
            row = sheet.createRow(r++);
            c = 0;
            row.createCell(c++).setCellValue(article.getTitle());
            row.createCell(c++).setCellValue(article.getUrl());
            row.createCell(c++).setCellValue(article.getCategories().toString());
            row.createCell(c++).setCellValue(article.getTags().toString());
 
        }
        for(int i = 0 ; i < 4; i++)
            sheet.autoSizeColumn(i, true);
 
    }
 
}

출처 - http://hmkcode.com/spring-mvc-view-json-xml-pdf-or-excel/


:

<util:properties/> 와 Spring EL 로 값 가져오기

FRAMEWORK/SPRING 2014. 11. 11. 14:38


SpringProperty.zip



XML 설정

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?xml version=" 1.0"="" encoding="UTF-8" ?=""><beans xmlns="http://www.springframework.org/schema/beans"
    xsi:schemaLocation="
 
    ....
 
    <util:properties id="prop" location="classpath:config/properties/sample.properties"/>
 
    ....
 
</beans>





sample.properties

1
2
3
4
sample.prop1 = test
 
# 우쭈쭈~
sample.prop2 = \uc6b0\ucb48\ucb48~






Spring EL 로 값 가져오기(SampleBean.java)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package com.tistory.stove99;
 
import java.util.Properties;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
 
@Component
public class SampleBean {
    // Spring EL 로 값 가져오기
    // Spring EL 이기 때문에 자유롭게 메소드 호출도 가능함. String 의 concat 메소드 호출
    @Value("#{prop['sample.prop1'].concat(' abc')}") private String value1;
    @Value("#{prop['sample.prop2']}") private String value2;
     
     
     
    // util:properties 로 생성된 빈은 java.util.Properties 의 인스턴스이기 때문에
    // 요렇게 Autowired 해서 쓸 수 있다.
    @Autowired Properties prop;
     
     
     
     
    public String val(String key){
        return prop.getProperty(key);
    }
     
    public String toString(){
        return String.format("value1 : %s, value2 : %s", value1, value2);
    }
}

Spring EL에 대해서 더 알아보고 싶으면 요 사이트를 참고하면 친절하게 알려줌.

http://static.springsource.org/spring/docs/3.0.x/reference/expressions.html






Test(SampleTest.java)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import org.springframework.context.support.ClassPathXmlApplicationContext;
 
import com.tistory.stove99.SampleBean;
 
 
public class SampleTest {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("config/spring/*-context.xml");
         
        SampleBean sample = context.getBean(SampleBean.class);
         
        // test
        System.out.println(sample.val("sample.prop1"));
         
        // value1 : test abc, value2 : 우쭈쭈~
        System.out.println(sample);
    }
}



출처 - http://stove99.tistory.com/150

:

Spring annotation

FRAMEWORK/SPRING 2014. 11. 10. 17:59

목차

@Component
@Required
@Autowired
@Resource
@Scope
@PostConstruct
@PreDestroy
@Inject
@Service
@Repository
@Controller
@RequestMapping
@RequestParam
@SessionAttributes
@InitBinder

@ModelAttribute

@RequestBody
@ResponseBody

@PathVariable






@Component

패키지 : org.springframework.stereotype

버젼 : spring 2.5

개요 : <context:component-scan> 태그를 설정파일에 추가하면 해당 어노테이션이 적용된 클래스를 빈으로 등록하게 된다. 범위는 디폴트로 singleton이며 @Scope를 사용하여 지정할 수 있다.


설정위치: 클래스 선언부 위 

추가설정 : XML 설정파일에 <context:component-scan>을 정의하고 적용할 기본  패키지를 base-package 속성으로 등록한다.


context:annotation-config 태그는 어노테이션과 관련해서 다음의 BeanPostProcessor를 함께 등록 한다.

           - @Required(RequiedAnnotationBeanPostProcessor)

           - @Autowired(AutowiredAnnotationBeanPostProcessor)

           - @Resource, @PostConstruct, @PreDestory(CommonAnnotationBeanPostProcessor)

           - @Configuration(ConfigurationClassPostProcessor)


* 그 외 Repository, Service, Controller 포함


예를 들어 <context:component-scan base-package="xxx" />에서 xxx패키지 하위에서 


@Component로 선언된 클래스를 bean으로 자동 등록한다.

bean의 이름은 해당클래스명(첫글자는 소문자)이 사용된다.       


<context:component-scan /> 요소에는 scoped-proxy 속성이 존재 한다. 

scoped-proxy 속성은 <aop:scoped-poxy/> 요소처럼 WebApplicationContext 에서만 유효하며 

"session", "globalSession", "request" 이외의 scope는 무시 되며 아래의 3가지 값을 설정 할 수 있다.

        no : proxy를 생성하지 않는다.(기본값)

        interfaces : JDK Dynamic Proxy를 이용한 Proxy 생성

        targetClass : 클래스에 대해 프록시를 생성(CGLIB를 이용한 Proxy 생성)


사용 예 :

1
2
3
4
5
@Component
@Scope("prototype")   // 생략하면 싱글톤
public class Test {
       .....
}


   - CGLIB

   기존의 자바 클래스파일로부터 자바의 소스코드를 동적으로 생성하는 라이브러리(자바 소스 변경)

    http://sourceforge.net/projects/cglib/


     - 스캔 대상 클래스 범위 지정하기

       <context:include-filter> 태그와 <context:exclude-filter> 태그를 사용하면 자동 스캔 대상에 포함시킬 클래스와 포함시키지 않을 클래스를 구체적으로 명시할 수 있다.

      <context:component-scan base-package="spring.demo" scoped-proxy="no">

           <context:include-filter type="regex" expression="*HibernateRepository"/>

           <context:exclude-filter type="aspectj" expression="..*IBatisRepository"/>

      </context:component-scan>


      위와 같이 <context:include-filter> 태그와 <context:exclude-filter> 태그는 각각 type 속성과 expresseion 속성을 갖는데, type 속성에 따라 expression 속성에 올 수 있는 값이 달라지는데 type 속성에 입력 가능한 값을 다음과 같다


     * Type 속성에 올 수 있는 값

        annotation : 클랙스에 지정한 어노테이션이 적용됐는지의 여부

            expression 속성에서는 "org.example.SomeAnnotation"와 같은 어노테이션 이름을 입력한다.

        assignable : 클래스가 지정한 타입으로 할당 가능한지의 여부. 

            expression 속성에는 "org.exampleSomeClass" 와 같은 타입 이름을 입력한다.

       regex : 클래스 이름이 정규 표현식에 매칭되는 지의 여부.

           expression 속성에는 "org\.example\.Default.*" 와 같이 정규표현식을 입력한다.

       aspectj : 클래스 이름이 AspectJ 의 표현식에 매칭되는 지의 여부.

          expression 속성에는 "org.example..*Service+" 와 같이 AspectJ 의 표현식을 입력한다.



@Required

패키지 : org.springframework.beans.factory.annotation

버젼 : spring 2.0

Required 어노테이션은 필수 프로퍼티임을 명시하는 것으로 필수 프로퍼티를 설정하지 않을 경우 

빈 생성시 예외를 발생시킨다.


설정위치 : setter 메소드

추가설정 : 

<bean class="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor" /> 클래스를 빈으로 등록시켜줘야 한다. 

해당 설정 대신에<context:annotation-config> 태그를 사용해도 된다.


    - 1단계 : 코드내에 프로퍼티 설정 메소드에 @Required 어노테이션을 붙인다.

     import org.springframework.beans.factory.annotation.Required

     public class TestBean {

         private TestDao testDao;

  

         @Required

         public void setTestDao(TestDao testDao) {

            this.testDao = testDao;

         }

     }


    - 2단계 : 스프링 설정 파일에 RequiredAnnotationBeanPostProcessor 클래스를 빈으로 등록

    <bean class="org.springframework.beans.factory.annotation.RequiredAnnotationBeanpostProcessor"/>


    <bean name="testBean"  class="han.test.TestBean">

        <property name="testDao" ref="testDao"/>  

<!-- @Required 어노테이션을 적용하였으므로 설정하지 않으면 예외를 발생시킨다. -->

    </bean>


     RequiredAnnotationBeanPostProcessor 클래스는 스프링 컨테이너에 등록된 bean 객체를 조사하여 @Required 어노테이션으로 설정되어 있는 프로퍼티의 값이 설정되어 있는지 검사하고 설정되어있지 않으면 bean 생성시 예외를 발생시킨다.

 

     RequiredAnnotationBeanPostProcessor 클래스를 빈으로 등록하지 않고

     <context:annotation-config> 다음과 같이 태그를 이용할 수도 있다.

1
2
3
4
5
6
7
8
9
10
11
12
<?xml version="1.0" encoding="UTF-8"?>
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
 
      <context:annotation-config/>
 
    </beans>



@Autowired

패키지 : org.springframework.beans.factory.annotation

버젼 : spring 2.5

개요 : 오토 와이어링 어노테이션은 의존관계를 자동설정할 때 사용하며 타입을 이용하여 의존하는 객체를 삽입해 준다. 그러므로 해당 타입의 빈객체가 존재하지 않거나 또는 2개 이상 존재할 경우 스프링은 예외를 발생시키게 된다.


설정 위치 : 생성자, 필드, 메소드(setter메소드가 아니여도 된다)

추가설정 : <bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor" /> 클래스를 빈으로 등록시켜줘야 한다. 해당 설정 대신에 <context:annotation-config> 태그를 사용해도 된다.


옵션 : required - @Autowired어노테이션을 적용한 프로퍼티에 대해 설정할 필요가 없는 경우에 false값을 주며 이때 해당 프로퍼티가 존재하지 않더라도 스프링은 예외를 발생시키지 않는다.

       @Autowired(required=false)로 선언한다. (기본값은 true)


특징 : byType으로 의존관계를 자동으로 설정할 경우 같은 타입의 빈이 2개 이상 존재하게 되면 예외가 발생하는데, Autowired도 이러한 문제가 발생한다. 이럴 때 @Qualifier를 사용하면 동일한 타입의 빈 중 특정 빈을 사용하도록 하여 문제를 해결할 수 있다.

       @Autowired

       @Qualifier("test")

       private Test test;

 

● @Qualifier

패키지 : org.springframework.beans.factory.annotation

버젼 : spring 2.5

개요 : 콸리파이어 어노테이션은 @Autowired의 목적에서 동일 타입의 빈객체가 존재시 특정빈을 삽입할 수 있게 설정한다. @Qualifier("mainBean")의 형태로 @Autowired와 같이 사용하며 해당 <bean>태그에 <qualifire value="mainBean" /> 태그를 선언해주어야 한다. 메소드에서 두개이상의 파라미터를 사용할 경우는 파라미터 앞에 선언해야한다.


설정위치 : @Autowired 어노테이션과 함께 사용된다.

추가설정 : 동일타입의 빈객체 설정에서 <qualifier value="[alias명]" />를 추가해 준다.

옵션 : name - alias명


사용 예 :

1
2
3
4
5
6
7
<bean id="user2" class="com.sp4.UserImpl">
    <property name="name" value="스프링"/>
    <property name="age" value="20"/>
    <property name="tel" value="000-0000-0000"/>
</bean>
 
<bean id="userService1" class="com.sp4.UserService"/>


1
2
3
4
5
6
7
8
9
public class UserService {
    @Autowired
    @Qualifier("user2")
    private User user;
 
    public String result() {
        return user.getData();
    }
}



@Resource

개요 : 자바 6버전 및 JEE5 버전에 추가된 것으로 어플리케이션에서 필요로 하는 자원을 자동 연결할 때 사용 한다. 스프링 2.5 부터 지원하는 어노테이션으로 스프링에서는 의존하는 빈 객체를 전달할 때 사용하다.

              @Autowired 와 같은 기능을 하며 @Autowired와 차이점은 @Autowired는 타입으로(by type),  @Resource는 이름으로(by name)으로 연결시켜준다는 것이다.


설정위치 : 프로퍼티, setter 메소드


추가설정 : <bean class="org.springframework.beans.factory.annotation.CommonAnnotationBeanPostProcessor"/> 클래스를 빈으로 등록시켜줘야 한다. 해당 설정 대신에 <context:annotation-config> 태그를 사용해도 된다.

옵션 : name 

      name속성에 자동으로 연결될 빈객체의 이름을 입력한다.

      @Resource(name="testDao")


CommonAnnotationBeanPostProcessor 클래스를 설정파일에 빈객체로 등록하여 어노테이션을 적용시킨다.

    <bean class="org.springframework.beans.factory.annotation.CommonAnnotationBeanPostProcessor"/>


    <bean name="testBean"  class="han.test.TestBean">

        <property name="testDao" ref="testDao"/>  

<!-- @Required 어노테이션을 적용하였으므로 설정하지 않으면 예외를 발생시킨다. -->

    </bean>


사용 예 :

1
2
3
4
5
6
7
8
9
10
11
12
13
public class UserService {
        @Resource(name="user2")
    private User user; 
        //UserImpl user2 = new UserImpl();
        //User user = user2;
 
    public void setUser(User user) {
        this.user = user;
    }
    public String result() {
        return user.getData();
    }
}



@Scope

패키지 : org.springframework.beans.factory.annotation

개요 : 스프링은 기본적으로 빈의 범위를 "singleton" 으로 설정한다. "singleton" 이 아닌 다른범위를 지정하고 싶다면 @Scope 어노테이션을 이용하여 범위를 지정한다.

설정 : prototype, singleton, request, session, globalSession


사용 예 - 1

1
2
3
4
5
@Component
@Scope(value="prototype")
public class Worker {
         :
}


사용 예 - 2

1
2
3
4
5
@Component
@Scope(value="prototype", proxyMode=ScopedProxyMode.TARGET_CLASS)
public class Worker {
        :
}



@PostConstruct

패키지 : javax.annotation

버젼 : jdk1.6, spring 2.5

개요 : 의존하는 객체를 설정한 이후에 초기화 작업을 수행하기 위해 사용

설정위치 : 초기화 작업 수행 메소드

추가설정 : CommonAnnotationBeanPostProcessor 클래스를 빈으로 등록시켜줘야 한다. 해당 설정 대신에 <context:annotation-config> 태그를 사용해도 된다.


사용 예 :

1
2
3
4
@PostConstruct
public void init() {
    System.out.println("객체 생성 후 내가 먼저 실행된다.");
}



@PreDestroy

패키지 : javax.annotation

버젼 : jdk1.6, spring 2.5

개요 : 컨테이너에서 객체를 제거하기 전에 해야할 작업을 수행하기 위해 사용

설정위치 : 해당 작업 메소드

추가설정 : CommonAnnotationBeanPostProcessor 클래스를 빈으로 등록시켜줘야 한다. 해당 설정 대신에 <context:annotation-config> 태그를 사용해도 된다.



@Inject

개요 : JSR-330 표준 Annotation으로 Spring 3 부터 지원하는 Annotation이다. 특정 Framework에 종속되지 않은 어플리케이션을 구성하기 위해서는 @Inject를 사용할 것을 권장한다. @Inject를 사용하기 위해서는 클래스 패스 내에 JSR-330 라이브러리인 javax.inject-x.x.x.jar 파일이 추가되어야 함에 유의해야 한다. 



@Service

개요 : @Service를 적용한 Class는 비지니스 로직이 들어가는 Service로 등록이 된다.


Controller에 있는 @Autowired는 @Service("xxxService")에 등록된 xxxService와 변수명이 같아야 하며

Service에 있는 @Autowired는 @Repository("xxxDao")에 등록된 xxDao와 변수명이 같아야 한다.


@Service("helloService")

public class HelloServiceImpl implements HelloService {


@Autowired

private HelloDao helloDao;


public void hello() {

System.out.println("HelloServiceImpl :: hello()");

helloDao.selectHello();

}

}

helloDao.selectHello(); 와 같이 @Autowired를 이용한 객체를 이용하여 Dao 객체를 호출한다.


사용 예 :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Service("test2.testService")
//괄호 속 문자열은 식별자를 의미한다.
//괄호를 생략할 경우 클래스명 그대로 사용한다.
//따라서 ,같은 클래스명이 존재 할 시 같은 식별자가 생성되기때문에 에러가 발생한다.
public class TestService {
    public String result(int num1, int num2, String oper) {
String str = null;
         
if(oper.equals("+")){
...
생략
...
        return str;
    }
}


@Resouce로 연결

1
2
3
4
5
6
7
8
9
@Resource(name="test2.testService")
//name에 필요한 것은 @Service("test2.testService") <- 여기서 괄호 속 문자열, 즉 식별자
private TestService service;
//TestService service = new TestService(); 라고 하는것과 같은 식
     
@RequestMapping(value="/test2/oper.action", method={RequestMethod.GET})
public String form() throws Exception {
    return "test2/write";
}



@Repository

패키지 : org.springframework.stereotype

버젼 : spring 2.0

개요 : 레포지 토리 어노테이션은 일반적으로 DAO에 사용되며 DB Exception을 DataAccessException으로 변환한다.


사용 예 :

1
2
3
4
5
6
7
8
@Repository("bbs.boardDAO")
public class BoardDAO {
    private SqlSession sqlSession;
     
    public int insertBoard(Board dto) throws Exception {
        ...
    }
}


1
2
3
4
5
6
public class BoardServiceImpl implements BoardService {
    @Resource(name="bbs.boardDAO")
    private BoardDAO dao;
 
    public int insertBoard(Board dto){}
}



@Controller

패키지 : org.springframework.stereotype

버젼 : spring 2.5

개요 : spring MVC의 Controller 클래스 선언을 단순화시켜준다. 스프링 컨트롤러, 

서블릿을 상속할 필요가 없으며, @Controller로 등록된 클래스 파일에 대한 bean을 자동으로 생성해준다.


Controller로 사용하고자 하는 클래스에 @Controller 지정해 주면 component-scan으로 자동 등록된다.


- xml 설정

<context:component-scan base-package="han.*"/>


- java

package han.test;


import org.springframework.stereotype.Controller;


@Controller

public class SpringC {


}


※ 컨트롤러 메서드의 파라미터 타입

 파라미터 타입설명 

 HttpServletRequest

 , HttpServletResponse, HttpSession     

 서플릿 API 

 java.util.Locale 

 현재 요청에 대한 Locale 

 InputStream, Reader

 요청 컨텐츠에 직접 접근할 때 사용 

 OutputStream, Writer

 응답 컨텐츠를 생성할 때 사용 

 @PathVariable 어노테이션 적용 파라미터

 URI 템플릿 변수에 접근할 때 사용 

 @RequestParam 어노테이션 적용 파라미터

 HTTP 요청 파라미터를 매핑 

 @RequestHeader 어노테이션 적용 파라미터

 HTTP 요청 헤더를 매핑 

 @CookieValue 어노테이션 적용 파라미터

 HTTP 쿠키 매핑 

 @RequestBody 어노테이션 적용 파라미터

 HTTP 요청의 몸체 내용에 접근할 때 사용, HttpMessage Converter를 이용해서 HTTP 요청 데이터를 해당 타입으로 변환한다. 

 Map, Model, ModelMap 

 뷰에 전달할 모델 데이터를 설정할 때 사용

 커맨드 객체

 HTTP 요청 파라미터를 저장한 객체. 기본적으로 클래스 이름을 모델명으로 사용. @ModelAttribute 어노테이션을 사용하여 모델명을 설정할 수 있다. 

 Errors, BindingResult

 HTTP 요청 파라미터를 커맨드 객체에 저장한 결과. 커맨드 객체를 위한 파라미터 바로 다음에 위치 

 SessionStatus

 폼 처리를 완료 했음을 처리하기 위해 사용. @SessionAttribute 어노테이션을 명시한 session 속성을 제거하도록 이벤트를 발생시킨다. 


설명 보기


※ 컨트롤러 메서드의 리턴 타입

 리턴타입설명 

 ModelAndView

 뷰 정보 및 모델 정보를 담고 있는 ModelAndView 객체 

 Model

 뷰에 전달할 객체 정보를 담고 있는 Model을 리턴한다. 이때 뷰 이름은 요청 URL로부터 결정된다. (RequestToViewNameTranslator를 통해 뷰 결정) 

 Map

 뷰에 전달할 객체 정보를 담고 있는 Map을 리턴한다. 이때 뷰 이름은 요청 URL로부터 결정된다. (RequestToViewNameTranslator를 통해 뷰 결정) 

 String

 뷰 이름을 리턴한다. 

 View 객체

 View 객체를 직접 리턴. 해당 View 객체를 이용해서 뷰를 생성한다. 

 void

 메서드가 ServletResponse나 HttpServletResponse 타입의 파라미터를 갖는 경우 메서드가 직접 응답을 처리한다고 가정한다. 그렇지 않을 경우 요청 URL로부터 결정된 뷰를 보여준다. (RequestToViewNameTranslator를 통해 뷰 결정) 

 @ResponseBody 어노테이션 적용

 메서드에서 @ResponseBody 어노테이션이 적용된 경우, 리턴 객체를 HTTP 응답으로 전송한다. HttpMessageConverter를 이용해서 객체를 HTTP 응답 스트림으로 변환한다. 


설명 보기



@RequestMapping

개요 : RequestMapping annotation은 url을 class 또는 method와 mapping 시켜주는 역활을 한다. annotation을 쓰지 않을때 지정했던 Controller등록을 위한 url bean 설정을 생략 할 수 있다. class에 하나의 url mapping을 할 경우, class위에 @RequestMapping("/url")을 지정하며

, GET 또는 POST 방식 등의 옵션을 줄 수 있다. 해당되는 method가 실행된 후, return 페이지가 따로 정의되어 있지 않으면 RequestMapping("/url")에서 설정된 url로 다시 돌아간다.

● 상세 속성 정보

- value 

 : "value='/getMovie.do'"와 같은 형식의 매핑 URL 값이다. 디폴트 속성이기 때문에 value만 정의하는 경우에는 'value='은 생략할 수 있다.

예 : @RequestMapping(value={"/addMovie.do", "/updateMovie.do" }) 

"/addMovie.do", "/updateMovie.do" 두 URL 모두 처리한다.


- method

 : GET, POST, HEAD 등으로 표현되는 HTTP Request method에 따라 requestMapping을 할 수 있다. 'method=RequestMethod.GET' 형식으로 사용한다. method 값을 정의하지 않는 경우 모든 HTTP Request method에 대해서 처리한다.

예 : @RequestMapping(method = RequestMethod.POST) 

value 값은 클래스 선언에 정의한 @RequestMapping의 value 값을 상속받는다.  


- params 

 : HTTP Request로 들어오는 파라미터 표현이다. 'params={"param1=a", "param2", "!myParam"}' 로 다양하게 표현 가능하다.

예 : @RequestMapping(params = {"param1=a", "param2", "!myParam"}) 

HTTP Request에 param1과 param2 파라미터가 존재해야하고 param1의 값은 'a'이어야하며, myParam이라는 파라미터는 존재하지 않아야한다. 또한, value 값은 클래스 선언에 정의한 @RequestMapping의 value 값을 상속받는다. 


- headers

 : HTTP Request의 헤더 값이다.'headers="someHader=someValue"', 'headers="someHader"', 'headers="!someHader"' 로 다양하게 표현 가능하다. Accept나 Content-Type 같은 헤더에 대해서 media type 표현 시 '*' 도 지원한다.

예 : @RequestMapping(value="/movie.do", headers="content-type=text/*") 

HTTP Request에 Content-Type 헤더 값이 "text/html", "text/plain" 모두 매칭이 된다. 또한, Type-Level, Method-Level에서 모두 사용할 수 있는데, Type-Level에 정의된 경우, 하위의 모든 핸들러 메소드에서도 Type-Level에서 정의한 헤더값 제한이 적용된다.


produces

 : 확인중. 명시하지 않아도 큰 문제는 발생하지 않는것으로 보인다. 다음처럼 설정할 경우 클라이언트는 json타입의 값을 받게 된다.

    @RequestMapping(value="...", produces = "application/json")

    @RequestBody

    public HashMap<String, String> testMethod(Model model) {

        HashMap<String, String> map = new HashMap<String, String>();

        map.put("code", "0");

        return map;

    }



사용 예 : 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@Controller
@RequestMapping("/han/test/*")
public class HelloController {
 
@RequestMapping(method=RequestMethod.GET, value="go")
public returntype getMethodName(){
    :
}
 
@RequestMapping(method=RequestMethod.POST, value="go2")
public returntype getMethodName2(){
    :
}
 
@Controller("mainController")
@RequestMapping(value="/main.action")
public class MainController {
      
    @RequestMapping(method=RequestMethod.GET)
    public String method() {
        return ".mainLayout";
    }
}



@RequestParam

개요 : RequestParam annotation은 key=value 형태로 화면에서 넘어오는 파라미터를 맵핑 된 메소드의

파라미터로 지정해 준다. 주로 get 방식으로 들어오는 request에서 사용한다.


아래에서 xxx/editBlog.do?blogId=3 과 같이 접근할 때, editBlogHandler 메소드의 파라미터인 blogId에는 

3이 셋팅된다. 필수 요건이 아닐 경우, @RequestParam(value="id", required="false")와 같이 옵션을 

주고 사용할 수 있다.


1
2
3
4
5
6
7
8
9
10
11
12
@Controller
public class BlogController {
    // 중간생략
     
    @RequestMapping("/editBlog")
    public ModelMap editBlogHandler(@RequestParam("blogId") int blogId) {
        blog = blogService.findBlog(blogId);
        return new ModelMap(blog);
    }
  
    // 중간생략
}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@RequestMapping(value="/...", method={RequestMethod.GET, RequestMethod.POST})
public String submit(HttpServletRequest req
        , @RequestParam(value="num1") int num1
        , @RequestParam(value="num2") int num2
        , @RequestParam(value="oper") String oper) throws Exception {
    ...  //value : form객체가 넘겨줄 값의 name
}
 
//@RequestParam 어노테이션이 적용된 파라미터는 기본적으로 필수 파라미터이다.
//따라서, 명시한 파라미터가 존재하지 않을 경우 400 에러가 발생한다.
//여기서 파라미터에 값이 있을수도 없을수도 있는 로직을 구현하려면 다음처럼 작성한다.
 
@RequestMapping(value="/...", method={RequestMethod.GET, RequestMethod.POST})
public String submit(HttpServletRequest req
        , @RequestParam(value="num1", defaultValue = "0") int num1
        , @RequestParam(value="num2", defaultValue = "0") int num2
        , @RequestParam(value="oper", required=false) String oper) throws Exception {
    ...
}



사용 예 :

파라미터를 각각 지정하는것이 번거롭다면 다음처럼 작성한다:

1
2
3
4
5
@RequestMapping("/faqDetail")
public String faqDetail(@RequestParam HashMap<String, String> map) {
     
    return "board/faq/faqDetail";
}

이렇게 작성하면 뷰에서 전달된 파라미터는 모두 하나의 컬렉션으로 전달된다. 



@SessionAttributes

개요 : SessionAttribute annotation은 세션상에서 model의 정보를 유지하고 싶을 경우 사용 할 수 있다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Controller
@SessionAttributes("blog")
public class BlogController {
    // 중간생략
  
    @RequestMapping("/createBlog")
    public ModelMap createBlogHandler() {
        blog = new Blog();
        blog.setRegDate(new Date());
        return new ModelMap(blog);
    }
  
    // 중간생략
}



@InitBinder

개요 : WebDataBinder를 초기화하는 method를 지정 할 수 있는 설정을 제공한다. 


일반적으로 WebDataBinder는 annotation handler 메소드의 command 와 form 객체 인자를 조작하는데 사용된다. 


InitBinder 메소드가 필수적으로 반환값을 가질 필요는 없으며, 일반적으로 이런 경우에 void를 선언한다. 특별한 인자는 WebdataBinder와 WebRequest또는 Locale의 조합으로 이루어지며, 이러한 조건이 만족되면 context-specific editors를 등록하는것이 허용된다.


WebdataBinder : WebDataBinder는 web request parameter를 javaBean 객체에 바인딩하는 특정한 DataBinder이다. WebDataBinder는 웹 환경이 필요하지만, Servlet API에 의존적이지 않다. servlet API에 의존적인 ServletRequestDataBinder와 같이 특정한 DaraBinder를 위한 더많은 base class를 제공한다.


RequestMapping : RequestMapping annotation은 web request를 특정한 handler class와 handler method에 mapping하는 역활을 수행한다. 대응하는 handlerMapping(for type level annotation)과 HandlerAdapter(for method level annotation)가 dispatch에 존재한다면, @RequestMapping이 처리된다.


WebRequest : WebRequest는 웹 요청에 대한 Generic interface이다. 주로 일반 request metadata에 generic web request interceptors의 접근을 허용하여 metadata에 대한 처리를 하기 위한 것이지 request 자체를 처리하기 위한 것은 아니다.



Annotation 기반 Controller 에서 ServletContext 구하기 :

1
2
3
4
5
6
7
8
9
10
11
12
@Controller
@RequestMapping("/common/download")
public class DownloadController {
    @Autowired
    private ServletContext sc;
 
    @RequestMapping
    public ModelAndView download(@RequestParam("filePath") String filePath) throws Exception {
        String path = sc.getRealPath(filePath);
        return new ModelAndView("common.download", "downloadFile", new File(path));
    }
}



@ModelAttribute

● 파라미터에 지정하는 경우

 화면에서 전달된 model을 파라미터 객체의 프로퍼티와 매핑한다.

1
2
3
4
5
6
7
8
9
10
11
public class MyModel {
    private String title;
 
    public void setTitle(String title) {
        this.title = title;
    }
 
    public String getTitle() {
        return this.title;
    }
}

1
2
3
4
5
6
7
8
@RequestMapping(value = "/titleSubmit")
public String titleSubmit(@ModelAttribute MyModel params) throws Exception {
 
    params.getTitle();
 
    // 생략
    // ...
}


● 메서드 혹은  리턴타입에 지정하는 경우

 컨트롤러에서 뷰에 전달할 일종의 공통 모델을 설정한다.


예를 들어 다음과 같은 TestController가 존재할 때 :

1
2
3
4
5
6
7
8
9
10
11
@Controller
@RequestMapping("/sample")
public class TestController {
 
    @ModelAttribute("modelTest")
    public String[] refModelTest() {
        return new String[] {"하나", "둘", "셋"};
    }
 
    ...
}


@ModelAttribute 어노테이션이 적용된 메소드가 리턴하는 값은 Request객체에 전달된다. 

전달 범위는 해당 메소드가 존재하는 컨트롤러 전체에 해당된다. (전역변수가 되는 셈)


EL을 적용해 접근할 땐 다음처럼 작성한다 :

1
2
3
4
5
6
7
<table>
    <tr>
        <c:forEach var="entity" items="${modelTest}">
            <td>${entity}</td>
        </c:forEach>
    </tr>
</table>






@RequestBody

@RequestBody 어노테이션이 적용된 파라미터는 HTTP Request body의 내용이 전달된다.


참고페이지

http://java.ihoney.pe.kr/283


1
2
3
4
5
6
7
@RequestMapping(value="/test")
public void penaltyInfoDtlUpdate(@RequestBody String body,
        HttpServletRequest req, HttpServletResponse res,
        Model model, HttpSession session) throws Exception  {
 
    System.out.println(body);  
}



@ResponseBody

컨트롤러가 응답할 값 혹은 객체를 HTTP Response body로 전달한다.


참고페이지

http://ismydream.tistory.com/140


클라이언트로 JSON 객체를 전달할 때 유용하다. 메서드에 @ResponseBody를 적용한 후 객체를 리턴하면 그 값은 VIEW를 통해 전달되는 것이 아니라 HTTP ResponseBody에 직접 쓰여진다. 보통 AJAX를 처리할 메서드에 적용한다. 이 경우 클라이언트 스크립트의 AJAX 옵션 설정에 주의해야 한다. ($.ajax()의 경우라면 받는 데이터를 JSON으로 파싱하도록 dataType: "json" 옵션 추가)


1
2
3
4
5
6
7
@RequestMapping("/getVocTypeList")
@ResponseBody
public ArrayList<Object> getVocTypeList() throws Exception {
     
    HashMap<String, Object> vocData = gvocInf.searchVocTypeList();
    return (ArrayList<Object>) vocData.get("data");
}


HashMap 객체를 리턴하면 JSON은 Map형태로 변환되며, 위처럼 ArrayList로 리턴할 경우엔 배열의 형태로 변환된다.



@PathVariable

URL의 일부를 파라미터 혹은 변수로 사용한다.

1
2
3
4
5
6
7
8
9
10
11
12
package com.sp.ex;
 
@Controller("ex.exController")
public class ExController{
    @RequestMapping(value="/blog/{userId}/main.action", method=RequestMethod.GET)
    public String main(HttpServletRequest req
                       , @PathVariable String userId) throws Exception  {
 
        req.setAttribute("userId", userId);
        return "restful/result";
    }
}



출처 - http://noritersand.tistory.com/156

:

뷰에 모델(Model) 전달

FRAMEWORK/SPRING 2014. 11. 5. 10:28


※ @RequestMapping 어노테이션이 적용된 메소드의 파라미터나 리턴 타입으로 ModelAndView, Model, ModelMap, Map, 커맨드 객체 등을 이용해서 모델을 뷰어 전달

 

◆ @RequestMapping 메소드가 ModelAndView, Model, Map을 리턴하는 경우 이들에 담긴 모델 데이터가 뷰에 전달

  ● 추가적으로 다음의 항목도 뷰에 함께 전달

    => 커맨드 객체

    => @ModelAttribute 어노테이션이 적용된 메소드가 리턴한 객체

    => 메서드의 Map, Model, ModelMap 타입의 파라미터를 통해 설정된 모델

 



 

 

UserVO.java

package sp.mvc.vo;

 

public class UserVO {
 private String userName;
 private String address;
 private String fruit;
 
 public String getUserName() {
  return userName;
 }
 public void setUserName(String userName) {
  this.userName = userName;
 }
 public String getAddress() {
  return address;
 }
 public void setAddress(String address) {
  this.address = address;
 }
 public String getFruit() {
  return fruit;
 }
 public void setFruit(String fruit) {
  this.fruit = fruit;
 }
 
 @Override
 public String toString() {
  return "UserVO [userName=" + userName + ", address=" + address + ", fruit=" + fruit + "]";
 }
} 

 

UserController.java

package sp.mvc.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.ExtendedModelMap;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;

import sp.mvc.vo.UserVO;

 

@Controller
public class UserController {

 

 @ModelAttribute("popularFruit")
 public String[] refPopularFruit(){
  return new String[]{"사과", "포도", "수박", "참외"};
 }
 
 @RequestMapping(value="/userForm.sp", method=RequestMethod.GET)
 public String userForm(){
  System.out.println("----- UserController.userForm() : GET -----");
  return "user/userForm";
 }

 
 @RequestMapping(value="/userSave.sp", method=RequestMethod.POST)
 public ModelAndView userSave(UserVO userVo, Model model){
// public ModelAndView userSave(@ModelAttribute("userVo") UserVO userVo, Model model){ 
  System.out.println("----- UserController.userSave() : POST -----");
  System.out.println("userInfo : " + userVo.toString());
  
  model.addAttribute("msg", "SUCCESS");
  
  ModelAndView modelAndView = new ModelAndView();
  modelAndView.setViewName("user/userInfo");
  modelAndView.addObject("userVo", userVo);
  
  return modelAndView;
 }
 
 @RequestMapping("/userView.sp")
 public Model userView(){
  System.out.println("----- UserController.userView() -----");
  
  Model model = new ExtendedModelMap();
  model.addAttribute("msg", "member info");
  
  return model;
 }

}

▦ Map, Model, ModelMap을 통한 모델 설정 방법

  ■ Map, Model, ModelMap 중 한 가지를 파라미터로 전달

  ■ Map, Model을 리턴

    => Map, Model은 인터페이스 이므로 인터페이스를 구현한 클래스의 객체를 생성해서 리턴

 

● @ModelAttribute("popularFruit") : @ModelAttribute 어노테이션이 적용된 메소드가 리턴한 객체

● public ModelAndView userSave(UserVO userVo, Model model: Model 파라미터, ModelAndView 리턴 타입

● public ModelAndView userSave(@ModelAttribute("userVo") UserVO userVo, Model model: @ModelAttribute 어노테이션, ModelAndView 리턴 타입

● public Model userView() : Model 리턴 타입

 

 

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance
 xmlns="http://java.sun.com/xml/ns/javaee
 xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd
 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
  
  <display-name>spring303</display-name>

 <filter>
  <filter-name>characterEncodingFilter</filter-name>
  <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
  <init-param>
   <param-name>encoding</param-name>
   <param-value>UTF-8</param-value>
  </init-param>
 </filter>

 <filter-mapping>
  <filter-name>characterEncodingFilter</filter-name>
  <url-pattern>/*</url-pattern>
 </filter-mapping>


 <!-- 공통 빈 설정
 <context-param>
  <param-name>contextConfigLocation</param-name>
  <param-value>/WEB-INF/applicationContext.xml</param-value>
 </context-param>
   
 <listener>
  <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
 </listener>
 -->
 
 <servlet>
  <servlet-name>spring303</servlet-name>
  <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  <init-param>
   <param-name>contextConfigLocation</param-name>
   <param-value>
    /WEB-INF/main_config.xml
   </param-value>
  </init-param>
  <load-on-startup>1</load-on-startup>
 </servlet>
 
 <servlet-mapping>
  <servlet-name>spring303</servlet-name>
  <url-pattern>*.sp</url-pattern>
 </servlet-mapping>

</web-app>

 

main_config.xml

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:context="http://www.springframework.org/schema/context
 xmlns:p="http://www.springframework.org/schema/p"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context-3.0.xsd">

 <context:annotation-config/>
 <context:component-scan base-package="sp.mvc.controller"/>
 
 <!-- ViewResolver 설정 -->
 <bean id="internalResource" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
  <property name="prefix" value="jsp/"></property>
  <property name="suffix" value=".jsp"></property>
 </bean>


 <!-- 각종 bean 설정 -->

 
</beans>

 

userForm.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>  
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>회원정보 입력</title>
</head>
<body>

<form action="userSave.sp" method="post">
 <table border="1">
  <tr>
   <td>이름</td>
   <td><input type="text" name="userName" value=""/></td>
  </tr>
  <tr>
   <td>주소</td>
   <td><input type="text" name="address" value=""/></td>
  </tr>
  <tr>
   <td>과일</td>
   <td>
   <c:forEach var="fruit" items="${popularFruit}">
    ${fruit},&nbsp;
   </c:forEach> 

   </td>
  </tr>
 </table>
 
 <input type="submit" name="submit" value="전송"/>
</form>
</body>
</html>

 

userInfo.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>    
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>회원정보 출력</title>
</head>
<body>
<h2>${msg}</h2>
<form action="userView.sp" method="post">
 <table border="1">
  <tr>
   <td>이름</td>
   <td>${userVo.userName}</td>
  </tr>
  <tr>
   <td>주소</td>
   <td>${userVo.address}</td>
  </tr>
  <tr>
   <td>과일</td>
   <td>
   <c:forEach var="fruit" items="${popularFruit}">
    ${fruit},&nbsp;
   </c:forEach>

   </td>
  </tr>
 </table>
 <input type="submit" name="submit" value="뷰"/>
</form>
</body>
</html>

 

userView.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>    
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>회원정보 출력</title>
</head>
<body>
<h2>${msg}</h2>
<c:forEach var="fruit" items="${popularFruit}">
${fruit} &nbsp;
</c:forEach>
</body>
</html>

 

 

로그 결과

----- UserController.userView() -----
----- UserController.userSave() : POST -----
userInfo : UserVO [userName=스누피, address=제주도 456, fruit=null]
----- UserController.userView() -----

 

 



 

 


출처 - http://snoopy81.tistory.com/311

'FRAMEWORK > SPRING' 카테고리의 다른 글

<util:properties/> 와 Spring EL 로 값 가져오기  (0) 2014.11.11
Spring annotation  (0) 2014.11.10
@ModelAttribute 어노테이션  (0) 2014.11.05
@ModelAttribute와 @RequestParam의 차이점  (0) 2014.11.05
Bean 정의시 id vs name  (0) 2014.09.26
:

@ModelAttribute 어노테이션

FRAMEWORK/SPRING 2014. 11. 5. 10:26


■ @ModelAttribute 어노테이션의 작업 수행

  ● @RequestMapping 어노테이션이 적용되지 않은 별도 메서드로 모델에 추가될 객체 생성(공통 데이터 생성)

    => @ModelAttribute 어노테이션을 메서드에 적용하면 해당 메서드가 생성한 객체가 뷰에 전달 됨

    => "뷰에 모델(Model) 전달(@ModelAttribute("popularFruit")" 게시물 참조

  ● 커맨드 객체의 초기화 작업 수행

    => @ModelAttribute 어노테이션이 적용된 메서드가 @RequestMapping 어노테이션이 적용된 메서드 보다 먼저 호출 됨

  ● @ModelAttribute 어노테이션이 적용된 메서드가 사용 가능한 파라미터

    => HttpServletRequest, Locale, @RequestParam 어노테이션 적용 파라미터, @PathVariable 어노테이션 적용 파라미터 등등

 

 

UserVO.java 

package sp.mvc.vo;

 

public class UserVO {
 private String userName;
 private String address;
 private String fruit;
 
 public String getUserName() {
  return userName;
 }
 public void setUserName(String userName) {
  this.userName = userName;
 }
 public String getAddress() {
  return address;
 }
 public void setAddress(String address) {
  this.address = address;
 }
 public String getFruit() {
  return fruit;
 }
 public void setFruit(String fruit) {
  this.fruit = fruit;
 }
 
 @Override
 public String toString() {
  return "UserVO [userName=" + userName + ", address=" + address + ", fruit=" + fruit + "]";
 }
}

 

UserController.java

package sp.mvc.controller;

import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;

import sp.mvc.vo.UserVO;

 

@Controller
public class UserController {
 
 @ModelAttribute("userVo")
 public UserVO initData(HttpServletRequest req){
  System.out.println("--- @ModelAttribute() ---");
  
  if(req.getMethod().equalsIgnoreCase("GET")){
   System.out.println("--- @ModelAttribute(): GET ---");
   UserVO userVo = new UserVO();
   userVo.setUserName("input name");
   userVo.setAddress("input address");

   userVo.setFruit("input fruit");
   return userVo;
  }else{  
   System.out.println("--- @ModelAttribute(): POST ---");
   return new UserVO();
  }
 }
 
 @RequestMapping(value="/userForm.sp", method=RequestMethod.GET)
 public String userForm(){
  System.out.println("----- UserController.userForm() : GET -----");
  return "user/userForm";
 }

 
 @RequestMapping(value="/userSave.sp", method=RequestMethod.POST)
 public ModelAndView userSave(@ModelAttribute("userVo") UserVO userVo, Model model){
  System.out.println("----- UserController.userSave() : POST -----");
  System.out.println("userInfo : " + userVo.toString());
  
  model.addAttribute("msg", "SUCCESS");
  
  ModelAndView modelAndView = new ModelAndView();
  modelAndView.setViewName("user/userInfo");
  modelAndView.addObject("userVo", userVo);
  
  return modelAndView;
 }
}

● @ModelAttribute 어노테이션이 적용된 메소드가 @RequestMapping 어노테이션이 적용된 메소드 보다 먼저 호출되기 때문에, 커맨드 객체에 대한 초기화 작업이 필요하다면 커맨드 객체와 동일한 이름을 갖는 @ModelAttribute 어노테이션이 적용된 메소드를 이용 => (결과화면 참고)

 

main_config.xml

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:context="http://www.springframework.org/schema/context
 xmlns:p="http://www.springframework.org/schema/p"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context-3.0.xsd">

 <context:annotation-config/>
 <context:component-scan base-package="sp.mvc.controller"/>
 
 <!-- ViewResolver 설정 -->
 <bean id="internalResource" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
  <property name="prefix" value="jsp/"></property>
  <property name="suffix" value=".jsp"></property>
 </bean>


 <!-- 각종 bean 설정 -->

 
</beans>

 

userForm.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>  
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>회원정보 입력</title>
</head>
<body>

<form action="userSave.sp" method="post">
 <table border="1">
  <tr>
   <td>이름</td>
   <td><input type="text" name="userName" value="${userVo.userName}"/></td>
  </tr>
  <tr>
   <td>주소</td>
   <td><input type="text" name="address" value="${userVo.address}"/></td>
  </tr>
 </table> 
 <input type="submit" name="submit" value="전송"/>
</form>
</body>
</html>

 

userInfo.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>    
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>회원정보 출력</title>
</head>
<body>
<h2>${msg}</h2>
<form action="userView.sp" method="post">
 <table border="1">
  <tr>
   <td>이름</td>
   <td>${userVo.userName}</td>
  </tr>
  <tr>
   <td>주소</td>
   <td>${userVo.address}</td>
  </tr>
 </table>
 <input type="submit" name="submit" value="뷰"/>
</form>
</body>
</html>

 

 

결과

요청 URL

   http://localhost:8090/spring303/userForm.sp

 

--- @ModelAttribute() ---
--- @ModelAttribute(): GET ---
----- UserController.userForm() : GET -----

 



 

데이터 입력 후 '전송'버튼 클릭

 

--- @ModelAttribute() ---
--- @ModelAttribute(): POST ---
----- UserController.userSave() : POST -----
userInfo : UserVO [userName=스누피, address=제주도 456, fruit=null]

 



 

 출처 - http://0px.kr/314 

: