본문 바로가기
Spring/study

spring 4강 Controller와 View의 연결 방법

by avvin 2019. 5. 29.

spring 4강 Controller와 View의 연결 방법


@Controller 어노테이션을 쓴 클래스는 개발자가 객체를 관리할 수 없다.

컨트롤러의 객체는 스프링 프레임워크가 관리한다.


view/include/header.jsp

1
2
3
4
5
6
7
8
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<c:set var="path" value="${pageContext.request.contextPath}" />
<script src="http://code.jquery.com/jquery-3.3.1.min.js">
</script>
 
cs


header.jsp는 모든 페이지에 include 시킬 예정 (모든 페이지에 포함되는 코드)

위 태그라이브러리를 쓰기위해서 JSP에선 jstl.jar을 다운받아 톰캣 라이브러리에 추가해야했지만 

메이븐 프로젝트에서는 pom.xml에 작성만 하면된다.


view/include/menu.jsp

14
<%@ page language="java" contentType="text/html; charset=UTF-8
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
 
//request로 받은 contextPath를 path라는 변수에 넣는 jstl태그
<c:set var="path" value="${pageContext.request.contextPath}" />
 
<div style="text-align: center;">
    <a href="${path}/">main</a>
    <a href="${path}/gugu.do?dan=7">구구단</a>
    <a href="${path}/test.do">테스트</a>
    <a href="${path}/member/list.do">회원관리</a>
</div>
<hr>
cs



WEB-INF 하위에 있으므로 직접 실행이 불가능하고 클래스를 경유하여 실행할 수 있다.

header와 menu 페이지를 include 시킨 test.jsp페이지 생성


test.jsp

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
<%@ 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>
<%@ include file="include/header.jsp" %>
<script>
function doF(){
    $.ajax({
        type: "post",
        url: "${path}/test/doF",
        success: function(result){
            $("#result").html(
                    "상품명:"+result.name+",가격:"+result.price);
        }
    });
}
</script>
</head>
<body>
<%@ include file="include/menu.jsp" %>
<h2>링크 테스트</h2>
<a href="${path}/test/doA">doA</a><br>
<a href="${path}/test/doB">doB</a><br>
<a href="${path}/test/doC">doC</a><br>
<a href="${path}/test/doD">doD</a><br>
<a href="javascript:doF()">doF</a><br>
<div id="result"></div>
</body>
</html>
cs



{path}는 Controller에서 리턴받거나 RequestMapping으로 받은 url인데

생략된 경로는 servlet-context에 설정돼있다.



Controller를 경유하여 실행한 화면




src/main/java > com.example.spring01.controller>MainController.java 생성


HomeController 대신 MainController로 실행하기위해 HomeController.java - home메서드를 막아준다


메서드 상단 @RequestMapping(value="/", method=RequestMethod.GET) 만 주석처리해주면 된다.


컨트롤러 클래스는 반드시 클래스명 상단에 @Controller 어노테이션을 추가해줘야한다. 

그래야만 서버가 실행될 때 해당 클래스가 자동으로 메모리에 올라간다.


MainController.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 
//컨트롤러 어노테이션(컨트롤러 객체를 자동으로 생성)
@Controller
public class MainController {
    // 로그 객체 생성
    private static final Logger logger = 
            LoggerFactory.getLogger(MainController.class);
    // 시작 페이지로 이동
    @RequestMapping("/"// url pattern mapping
    public String main(Model model) {
        //JSP 서블릿 클래스는 doGet doPost 메서드가 존재했는데 여기서 model이 그 역할을 한다.
        // Model : 데이터를 담는 그릇 역할, map 구조로 저장됨// key와 value로 구성
        // model.addAttribute("변수명", 값)
        model.addAttribute("message""홈페이지 방문을 환영합니다.");
        // <beans:property name="prefix" value="/WEB-INF/views/" />
        // <beans:property name="suffix" value=".jsp" />
        // /WEB-INF/views/main.jsp
        return "main"
        // main.jsp로 포워딩됨 //JSP에서 dispatcher 객체로 forward한것과 같은 역할
        //나머지 경로는 spring > appServlet > servlet-context.xml에 설정돼있음
        //컨트롤러에 대한 설정은 서블릿컨텍스트에 있다.
    }//>> main.jsp를 컨트롤 클래스를 경유하여 실행한다.
    
cs

 


URL name과 jsp페이지이름이 같으면 리턴값으로 페이지 주소를 주지 않아도되고

@RequestMapping(" ... ")에 입력된 곳으로 이동한다. 

단, 리턴하지 않으므로 model 에 데이터를 담아 보낼 수도 없다.


위 URL이 .do로 끝날 경우 @RequestMapping( "~.do" ) 이하의 메서드가 실행되고, 

그 메서드가 (.do가 빠진)페이지 이름을 리턴하는 식( 리턴하는 경로로 model을 포워드 )


1
2
3
4
    @RequestMapping("test")
    public void test() {
        
    }
cs


페이지 주소를 리턴하면서 객체를 함께 넘기는 방법


리턴타입 : ModelAndView

1
2
3
4
5
6
7
8
9
10
11
12
13
    @RequestMapping("test/doC")
    public ModelAndView doC() { 
 
        // Model (넘길 데이터 객체)과 View(넘길 페이지) 함께 처리하는 doC() 메서드 
 
        Map<String,Object> map=new HashMap<>();
        map.put("product"new ProductDTO("샤프",1000));
 
        //test/doC라는 jsp페이지로 갈 것, 
        //"map"이라는 변수명에 //map(위에서 생성한 해시맵) 객체 담아 보내기
 
        return new ModelAndView("test/doC","map",map);
    }
cs



forward와 redirect의 차이

리턴은 보여줄 페이지를 결정하는데 
forward 방식은 주소값이 @RequestMapping(" ... ") //...이면 하단 메서드 실행
... 그대로 유지된 채로 리턴한 페이지를 보여주고

리다이렉트는 리턴한 페이지의 주소와 페이지를 보여준다. 
(주소가 바뀐다. @RequestMapping(" ... ")의 ...과 다른 주소로 이동할 수 있다.)


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
    @RequestMapping("test/doA")
    public String doA(Model model) {
        logger.info("doA called...");
        model.addAttribute("message","홈페이지 방문을 환영합니다.");
        return "test/doB"//forward
 
    //URL : http://localhost:8090/spring01/test/doA
 
    //보여지는 페이지 : doB 페이지
 
    }
 
 
    @RequestMapping("test/doD")
    public String doD() {
        return "redirect:/test/doE"//redirct는 주소가 바뀐다.
 
    //URL : http://localhost:8090/spring01/test/doE
 
    //보여지는 페이지 : doE 페이지 
 
 
    }
 
 
    @RequestMapping("test")
    public void test() {
        
    //URL : http://localhost:8090/spring01/test.do //.do는 menu.jsp에서 설정
 
    //보여지는 페이지 : test페이지. URL이름과 페이지이름이 같으면 void로 처리해도 o.k.
 
    //리턴값이 없으면 URL에 있는 페이지명을 읽어와서 페이지를 띄운다.
    }
 
cs




Ajax 처리 전용 컨트롤러 (백그라운드에서 실행됨)

test.jsp 일부
1
2
3
4
5
6
7
8
9
10
11
12
<script>
function doF(){
    $.ajax({
        type: "post",
        url: "${path}/test/doF",
        success: function(result){
            $("#result").html(
                    "상품명:"+result.name+",가격:"+result.price);
        }
    });
}
</script>
cs

SampleRestController.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package com.example.spring01.controller;
 
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
 
import com.example.spring01.model.dto.ProductDTO;
 
@RestController // 스프링 4.0부터 사용 가능 
public class SampleRestController {
 
    @ResponseBody // json 형식으로 리턴
    @RequestMapping("test/doF"// url mapping
    public ProductDTO doF() {
        //호출한 곳으로 데이터가 넘어감(json 형식) 
        return new ProductDTO("냉장고",500000);
    }
}
cs



@RestController는 스프링 4.0부터 지원되기 때문에 이 전 버전에서는

@Controller를 사용하고 @ResponseBody를 생략해서는 안된다.



test.jsp에서 doF()함수 호출 > SampleRestController.java의 리턴값을 함수doF() 블럭 안의 result가 받는다.


result는 String 형밖에 받지 못하는데 SampleRestController가 리턴하는 값은 ProductDTO타입이므로


ProductDTO를 Json형식 ( {"name":"냉장고", "price":"500000"} ) String타입으로 변환해야한다.


메서드에 @ResponseBody가 적용된 경우, 리턴 객체를 JSON과 XML과 같은 알맞은 응답으로 변환한다.


이 때, 다른 데이터 타입을 json 형식의 String 타입으로 변환해주는 것이 jackson-databind 라이브러리


mvn.repository.com에서 라이브러리 코드 가져오기(groupID와 artitactId 확인)


Jackson Databind » 2.9.8


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.8</version>
</dependency>
 
cs


(라이브러리 추가한 것 외에 바뀐게 없는데 이유없이 에러나면 


Spring 개발 환경설정 

 글의 [ 에러 해결 방법 ] 정리해놓은 대로 실행해본다)