nickjoIT

@Controller VS, @RestController, ResponseEntity 본문

FRAMEWORK/SPRING

@Controller VS, @RestController, ResponseEntity

nickjo 2018. 2. 5. 23:08

@Controller VS, @RestController (Controller와 RestController의 차이점)


전통적인 Spring MVC 컨트롤러와 Restful 웹서비스 컨트롤러의 주요 차이점은 HTTP Response Body가 생성되는 방식이다. 기존의 MVC 컨트롤러는 view기술을 사용하지만 Restful 웹서비스 컨트롤러는 객체를 반환하기만 하면 객체 데이터는 JSON/XML 형식의 HTTP 응답을 직접 작성하게된다.

다시 정리하자면 @Controller의 주용도는 view(화면)을 리턴하는 것이고, @RestController는 데이터를 리턴하는 것이 주용도하고 할 수 있다. 물론 @Cotroller의 경우 메서드에 @ResposeBody를 사용하여 객체를 리턴할 수도 있다.


Spring MVC의 전통적인 Work Flow

Controller(BasicController)

package com.example.spring02.controller.test;
 
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
 
@Controller
@RequestMapping("/basic/*")
public class BasicController {
    @RequestMapping("/hello")
    public String sayHello(){
        return "hello";
    }
}
cs


View(hello.jsp)

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title></title>
</head>
<body>
    hello world
</body>
</html>
cs


브라우저 화면


Spring MVC Rest의 Work Flow

1. 클라이언트는 URI 형식으로 웹서비스에 요청을 보낸다.

2. 요청은 Handler Mapping과 그 타입을 찾는 DispatcherServlet에 의해 인터셉트

3. 요청은 Controller에 의해 처리되고 응답은 DispatcherServlet으로 리턴된 후 DispatcherServlet은 View로 디스패치


위의 그림을 보면 전통적인 Spring MVC Work Flow는 ModelAndView 객체가 컨트롤러에서 클라이언트로 전달되는 것을 알 수 있다. @ResponseBody 어노테이션을 사용하면 View를 리턴하지 않고 컨트롤러에서 직접 테이터를 리턴할 수 있다. Spring 4.0부터는 @RestController 어노테이션을 통해 더 단순화 되었다.



@ResponseBody

Spring 3.x MVC Restful Web Service Work Flow



Controller(BasicController2)

@RequestMapping("/basic/*")
public class BasicController2 {
    @RequestMapping("/sendVO")
    //@ResponseBody <- 메서드 상단 또는 리턴타입 앞에 어노테이션 추가
    public @ResponseBody BoardVO sayHello(){
        BoardVO vo = new BoardVO();
        vo.setBno(1);
        vo.setWriter("DoubleS");
        vo.setContent("게시글 내용입니다");
        vo.setRecnt(1);
        vo.setTitle("게시글 1");
        vo.setUserName("DoubleS");
        return vo;
    }
}
cs


브라우저 화면


@ResponseBody을 사용하면, Spring은 HTTP 응답에 리턴 값을 자동으로 변환해준다. 컨트롤러 클래스의 각 메서드에 @ResponseBody 어노테이션을 작성해줘야 한다.


@RestController

Spring 4.x MVC Restful Web Service Work Flow

RestController(RestController)

package com.example.spring02.controller.test;
 
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
 
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
 
import com.example.spring02.model.board.dto.BoardVO;
 
@RestController
@RequestMapping("/basic/*")
public class ControllerRest {
    
    // json객체 리턴
    @RequestMapping("/sendVO2")
    public BoardVO sendVO2(){
        BoardVO vo = new BoardVO();
        vo.setBno(1);
        vo.setWriter("DoubleS");
        vo.setContent("게시글 내용입니다");
        vo.setRecnt(1);
        vo.setTitle("게시글 1");
        vo.setUserName("DoubleS");
        return vo;
    }
    
    // json 객체 배열 리턴
    @RequestMapping("/sendList")
    public List<BoardVO> sendList(){
        // ArrayList 객체 생성
        List<BoardVO> items = new ArrayList<>();
        for(int i=1; i <=10; i++){
            BoardVO vo = new BoardVO(); //vo 객체 생성
            vo.setBno(i);
            vo.setWriter("DoubleS"+i);
            vo.setContent("게시글 내용입니다"+i);
            vo.setRecnt(i);
            vo.setTitle("게시글"+i);
            vo.setUserName("DoubleS"+i);
            items.add(vo); // 리스트에 vo추가
        }
        return items; // 리스트를 리턴함
    }
    
    // json객체를 map에 저장하여 
    @RequestMapping("/sendMap")
    public Map<Integer, BoardVO> sendMap(){
        // Map<Key자료형, Value자료형>
        Map<Integer, BoardVO> map = new HashMap<Integer, BoardVO>();
        for(int i=1; i <=10; i++){
            BoardVO vo = new BoardVO(); //vo 객체 생성
            vo.setBno(i);
            vo.setWriter("DoubleS"+i);
            vo.setContent("게시글 내용입니다"+i);
            vo.setRecnt(i);
            vo.setTitle("게시글"+i);
            vo.setUserName("DoubleS"+i);
            map.put(i, vo); // 맵에 vo추가
        }
        return map;
    }
}
 
cs


브라우저 화면



Spring4.0에서는 @RestController 어노테이션이 추가 되었는데 컨트롤러 클래스의 각 메서드마다 @ResponseBody을 추가할 필요가 없어졌고, 모든 메서드는 @ResponseBody 애노테이션이 기본으로 작동이 된다.


ResponseEntity

RestController는 별도의 View를 제공하지 않는 형태로 서비스를 실행하기 때문에, 때로는 결과데이터가 예외적인 상황에서 문제가 발생할 수 있다. ResponseEntity는 개발자가 직접 결과 데이터와 HTTP 상태 코드를 직접 제어할 수 있는 클래스로 개발자는 404나 500같은 HTTP 상태 코드를 전송하고 싶은 데이터와 함께 전송할수 있기 때문에 좀더 세밀한 제어가 필요한 경우 사용할 수 있다.


// ResponseEntity : 데이터 + http status code
@RequestMapping("/sendMap2")
public ResponseEntity<Map<Integer, BoardVO>> sendMap2(){
    // Map<Key자료형, Value자료형>
    //Map<Integer, BoardVO> map = new HashMap<Integer, BoardVO>();
    Map<Integer, BoardVO> map = new HashMap<Integer, BoardVO>();
    for(int i=1; i <=10; i++){
        BoardVO vo = new BoardVO(); //vo 객체 생성
        vo.setBno(i);
        vo.setWriter("DoubleS"+i);
        vo.setContent("게시글 내용입니다"+i);
        vo.setRecnt(i);
        vo.setTitle("게시글"+i);
        vo.setUserName("DoubleS"+i);
        map.put(i, vo); // 맵에 vo추가
    }
    // 리턴시 map과 상태메시지를 함께 전송
    return new ResponseEntity<>(map, HttpStatus.INTERNAL_SERVER_ERROR);
}
    
@RequestMapping("/sendErrorAuth")
public ResponseEntity<Void> sendListAuth(){
    return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
}
cs


[참고]

http://doublesprogramming.tistory.com/105

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

MVC1, MVC2 패턴의 차이점과 Spring MVC 구조  (3) 2016.02.12
Spring interceptore, Spring filter 차이점  (0) 2016.02.12
AOP  (0) 2016.02.06
Comments