본문으로 바로가기

▶Controller의 리턴 타입

스프링 MVC의 구조가 기존의 상속과 인터페이스에서 어노테이션을 사용하는 방식으로 변한 이후에 가장 큰 변화 중 하나는 리턴 타입이 자유로워 졌다는 점임.


Controller의 메서드가 사용할 수 있는 리턴 타입은 주로 다음과 같음.


-String: jsp를 이용하는 경우에는 jsp파일의 경로와 파일이름을 나타내기 위해서 사용함.

-void: 호출하는 URL과 동일한 이름의 jsp를 의미함.

-VO,DTO 타입: 주로 JSON 타입의 데이터를 만들어서 반환하는 용도로 사용함.

-ResponseEntity 타입: response 할 때 Http헤더 정보와 내용을 가공하는 용도로 사용함.

-Model, ModelAndView: Model로 데이터를 반환하거나 화면까지 같이 지정하는 경우에 사용함.(최근에는 많이 사용하지 않음)

-HttpHeaders: 응답에 내용 없이 Http헤더 메시지만 전달하는 용도로 사용함.


 


▶void타입

메서드의 리턴 타입을 void로 지정하는 경우 일반적인 경우에는 해당 URL의 경로를 그대로 jsp파일의 이름으로 사용하게 됨.


SampleController클래슬 일부 


1
2
3
4
5
@GetMapping("/ex05")
    public void ex05() {
        System.out.println("ex05");
        
    }
cs


브라우저에서 SampleController의 경로 에 xe05( )의 경로를 합쳐'/sample/ex05'를 호출하면 다음과 같은 결과를 보게 됨.



에러 메세지를 자세히 보면 에러 메세지의 원인이 '/WEB-INF/view/sample/ex05.jsp'가 존재하지 않아서 생기는 문제라는 것을 볼 수 있음.이것은 servlet-context.xml의 아래 설정과 같이 맞물려  URL 경로를 View로 처리하기 때문에 생기는 결과임.


servelt-context.xml의 일부

 

1
2
3
4
5
<!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
    <beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <beans:property name="prefix" value="/WEB-INF/views/" />
        <beans:property name="suffix" value=".jsp" />
    </beans:bean>
cs


▶String 타입


void 타입과 더불어서 가장 많이 사용하는 것은 String 타입임.String 타입은 상황에 따라 다른 화면을 보여줄 필요가 있을 경우에 유용하게 사용함.

(if~else와 같은 처리가 필요한 상황).일반적으로 String 타입은 현재 프로젝트의 경우JSP파일의 이름을 의미함.프로젝트 생성 시 기본으로 만들어진 HomeController의 코드를 보면 String을 반환 타입으로 사용하는 것을 볼 수 있음.



HomeController의 일부 

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
package org.zerock.controller;
 
import java.text.DateFormat;
import java.util.Date;
import java.util.Locale;
 
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
 
/**
 * Handles requests for the application home page.
 */
@Controller
public class HomeController {
    
    private static final Logger logger = LoggerFactory.getLogger(HomeController.class);
    
    /**
     * Simply selects the home view to render by returning its name.
     */
    @RequestMapping(value = "/", method = RequestMethod.GET)
    public String home(Locale locale, Model model) {
        logger.info("Welcome home! The client locale is {}.", locale);
        
        Date date = new Date();
        DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale);
        
        String formattedDate = dateFormat.format(date);
        
        model.addAttribute("serverTime", formattedDate );
        
        return "home";
    }
}
 
cs


home( )메서드는 'home'이라는 문자열을 리턴했기 때문에 경로는 '/WEB-INF/views/home.jsp'경로가 됨.


String 타입에는 다음과 같은 특별한 키워드를 붙여서 사용할 수 있음.

-redirect: 리다이렉트 방식으로 처리하는 경우 

-forward: 포워드 방식으로 처리하는 경우


▶객체 타입

controller의 메서드 리턴 타입을 VO(Value Object)나 DTO(Data Transfer Object)타입 등

데이터가 들어간 객체 타입으로 지정할 수 있는데 , 이 경우 주로JSON 데이터를 만들어 내는 용도로 사용함.  


우선 이를 위해서는 jackson-databind 라이브러리를 pom.xml에 추가함.


1
2
3
4
5
6
7
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.9.4</version>
</dependency>
 
cs


SamplController에는 아래와 같은 메서드를 생성함.

SamplController의 일부 


1
2
3
4
5
6
7
8
9
@GetMapping("/ex06")
    public @ResponseBody SampleDTO ex06() {
        System.out.println("ex06...............");
        SampleDTO dto =new SampleDTO();
        dto.setAge(10);
        dto.setName("김선영");
        
        return dto;
    }
cs

스프링 MVC는 자동으로 브라우저에 JSON타입으로 객체를 변환해서 전달하게 됨.



개발자 도구를 통해서 살보펴면 서버에서 전송하는 MIME 타입이 'application/json'으로 처리되는 것을 볼 수 있음. 만일 Jackson-databind 라이브러리가 포함되지 않았다면 다음과 같은 에러 화면을 보게 됨. 스프링 MVC는 리턴 타입에 맞게 데이터를 변환해 주는 역할을 지정할 수 있는데 기본적으로 JSON은 처리가 되므로 별도의 설정이 필요로 하지 않음.(스프링3버전까지는 별도의 Converter를 작성해랴만 했음.)


▶ResponseEntity타입

Web을 다루다 보면 HTTP프로토콜의 헤더를 다루는 경우도 종종 있음.스프링MVC의 사상은 HttpServletRequest나 HttpServletReponse를 직접 핸들링하지 않아도 이런 작업이 가능하도록 작성되었기 때문에 이러한 처리를 위해 ResponseEntity를 통해서 원하는 헤더 정보나 데이터를 전달할 수 있음 .


sampleController클래스 일부 


1
2
3
4
5
6
7
8
9
@GetMapping("/ex07")
    public ResponseEntity<String> ex07() {
        System.out.println("ex07...............");
        //{"name":"김선영"}
        String msg="{\"name\":\"김선영\"}";
        
        HttpHeaders header=new HttpHeaders();
        header.add("Content-Type","application/json;charset=UTF-8");
        return new ResponseEntity<>(msg,header,HttpStatus.OK);
cs

ResponseEntity는 HttpHeaders 객체를 같이 전달할 수 있고, 이를 통해서 원하는 HTTP 헤더 메세지를 가공하는 것이 가능함.ex07()의 경우 브라우저에는 JSON타입이라는 헤더 메세지와 200 OK상태 코드를 전송함. 




▶ResponseEntity타입

Controller의 많은 작업은 스프링 MVC를 통해서 처리하기 때문에 개발자는 자신이 해야 하는 역할에만 집중해서 코드를 작성할 수 있지만,조금 신경 써야 하는 부분이 있다면 파일을 업로드하는 부분에 대한 처리일 것임.파일 업로드를 하기 위해서는 전달되는 파일 데이터를 분석해야 하는데,이를 위해서 Servlet3.0전까지는 commons의 파일업로드를 이용하거나 cos.jsr 등을 이용해서 처리를 해 왔음.Servlet 3.0이후 (Tomcat7.0)에는 기본적으로 업로드되는 파일을 처리할 수 있는 기능이 추가 되어 있으므로 더 이상 추가적인 라이브러리가 필요하지 않음.


조금아쉬운 점은'Spring Legacy Project'로 생성되는 프로젝트의 경우Servlet 2.5를 기준으로 생성되기 때문에 3.0이후에 지원되는 설정을 사영하기 어렵다는 점임.3.0이상의 파일 업로드 방식은 후반부에 별도 파트에서 다루도록 하고 예제는 일반적으로 많이 사용하는 commons-fileupload를 이용하도록 하겠음.


1
2
3
4
5
6
7
<!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.3.3</version>
</dependency>
 
cs


라이브러리를 추가한 후 파일이 임시로 업로드될 폴더를 C드라이브 아래 upload/tmp 로 작성함.




-servlet-context.xml설정

servlet-context.xml은 스프링 MVC의 특정한  객체(빈)를 설장해서 파일을  처리함.다른 객체(Bean)를 설정하는 것과 달리 파일 업로드의 경우에는 반드시 id 속성의 값을 'multiparResolver'로 정확하게 지정해야 하므로 주의가 필요함.  

1
2
3
4
5
6
7
8
9
<beans:bean id="mutipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <beans:property name="defaultEncoding" value="utf-8"></beans:property>
    <!-- 1024 * 1024 * 10 bytes 10 MB -->
    <beans:property name="maxUploadSize" value="104857560"></beans:property>
    <!--1024 * 1024 * 2 bytes 2MB  -->
    <beans:property name="maxUploadSizePerFile" value="2097152"></beans:property>
    <beans:property name="uploadTempDir" value="file:/C:/upload/tmp"></beans:property>
    <beans:property name="maxInMemorySize" value="10485756"></beans:property>
 
cs


maxUploadSize는 한 번의  Request로 전달될 수 있는 최대의 크기를 의미한고, maxUploadSizePerFile은 하나의 파일 최대크기 maxInMemorySize는 메모리 상에서 유지하는 최대의 크기를 의미함. 만일 이 크기 이상의 데이터는 uploadTempDir에 임시 파일의 혈태로 보관됨.uploadTempDir에서 절대 경로를 이용하려면 URI 형태로 제공해야하기 때문에 'file:/'로 시작하도록 함. defaultEncoding은 업로드하는 파일의 이름이 한글일 경우 깨지는 문제를 처리함.


SampleController에서는 다음과 같이 get방식으로 파일을 업로드할 화면을 처리함.

1
2
3
4
    @GetMapping
    public void exUpload() {
        System.out.println("/exUpload...................");
    }
cs
파일 업로드를 해 볼 /WEB-INF/views/sample/exUpload.jsp 파일을 작성함.



exUpload.jsp


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="/sample/exUploadPost" method="post" enctype="multiPART/form-data">
 
<div><input type="file" name="files"></div>
<div><input type="file" name="files"></div>
<div><input type="file" name="files"></div>
<div><input type="file" name="files"></div>
<div><input type="file" name="files"></div>
<div><input type="submit"></div>
 
</form>
</body>
</html>
cs


exUpload.jsp는 여러 개의 파일을 한꺼번에 업로드하는 예제로 작성해 봄.<form>태그의 action속성,method속성,enctype속성에 주의 해서 작성해야함.

브라우저는 아래와 같음 모습임.



ex07.jsp의 action 속성값은'/sample/exUploadPost'로 작성되었으므로, 이에 맞는 메서드를 SampleController에 추가함.



SampleController

1
2
3
4
5
6
7
8
    @PostMapping("/exUploadPost")
    public void exUploadPost(ArrayList<MultipartFile> files) {
        files.forEach(file->{
            System.out.println("----------------------------------------");
            System.out.println("name:"+file.getOriginalFilename());
            System.out.println("size:"+file.getSize());
        });
    }
cs


스프링 MVC는 전달되는 파라미터가 동일한 이름으로 여러 개 존재하면 배열로  처리가 가능하므로 파라미터를 MultiparFile의 배열 타입으로 작성함.실제로 파일을 업로드해 보면 아래와 같은 결과를 볼 수 있음. 현재 설정은 한 파일의 최대 크기가 2MB이므로그보다 작은 크기의 파일을 지정해서 업로드를 테스트함.


그림 중간에서 보이는 로그는 SampleController에서 업로드 정보가 올버르게 처리되는 것을 보여주고 있음.최종 업로드를 하려면 byte[]를 처리해야 하는데 예제는 아직처리하지 않은 상태임.(이에 대한 예제는 책의 뒤쪽에서 예제로 작성될 것임.)


JAVA 설정을 이용하는경우

-@Bean을 이용해서 처리하기는 하지만,id속성을 같이 부여함.servlet-context.xml과 관련된 설정이므로 ServletConfig클래스를 이용해서 처리함.