Controller와 View의 연결 방법

Back-End/Spring 2019. 5. 29. 18:21
728x90
반응형

Controller와 view의 연결 실습

 

기본적인 코드는 spring01 -> src/main/java -> com.example.spring01 패키지 안에다가 파일 생성

 



  -연결의 흐름-


  컨트롤러에 갔다가 모델에 값을 저장하고 페이지로 넘겨서 출력을 시킨다.

 

 

 

 

 

-ajax란??-

 

Asynchronous JavaScript and XML의 약자 입니다.

 

javascript와 xml을 이용하여 비동기 통신을 하는 기능입니다.

쉽게 말해서 새로고침 없이 새로 고침 효과를 볼 수 있는 기능 (실시간으로 변화하는 페이지..)

ajax는 데이터를 갱신하는 곳에서 사용한다면 페이지 전환 없이 동적으로 변화하는 모습을 자연스럽게 구현할 수 있습니다.

 

 

 

-동기식과 비동기식-

 

동기식 방식 : 클라이언트가 서버에게 요청하고 응답이 올 때까지 기다리는 것.

 

비동기식 방식 : 클라이언트가 서버에게 요청을 하고 응답이 오기 전까지 다른일을 할 수 있다.

 

 

- JSON (JavaScript Object Notation) 이란? -

 

* JSON은 경량(Lightweight) 의 DATA-교환 형식

 

* Javascript에서 객체를 만들 때 사용하는 표현식을 의미한다.

 

* JSON 표현식은 사람과 기계 모두 이해하기 쉬우며 용량이 작아서, 최근에는 JSON이 XML을 대체해서 데이터 전송 등에 많이 사용한다.

 

* 특정 언어에 종속되지 않으며, 대부분의 프로그래밍 언어에서 JSON 포맷의 데이터를 핸들링 할 수 있는 라이브러리를 제공한다.

 

 

 

-예제-

 

main.jsp (메인)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!-- 설정상 jsp파일을 직접 실행할 수 없다. WEB-INF안에 있기 때문에 직접실행 불가 -->
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<%@include file = "Include/header.jsp" %>
</head>
<body>
<%@include file = "Include/menu.jsp" %>
<h2>${message }</h2>
</body>
</html>
cs

 

 

header.jsp (상단)

1
2
3
4
5
6
7
8
9
10
<%@ 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, fmt(숫자 지원) 태그를 작성 -->
<!-- pom.xml에 jstl이 라이브러리에 들어있기 때문에 바로 사용할 수 있다. -->
<c:set var = "path" value = "${pageContext.request.contextPath }"/>
<!-- contextpath가 사이트의 식별자(한서버에 여러가지 사이트가 돌아갈 경우에) -->
<script src="http://code.jquery.com/jquery-3.3.1.min.js"></script>
 
cs

 

 

menu.jsp (메뉴)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!-- views/include/menu.jsp -->
<!-- taglib랑 c:set는 header.jsp 에 있지만 만약 작성하지 않을시에 에러가 발생할 수 있으므로 작성한다. -->
<%@ taglib prefix = "c"
uri = "http://java.sun.com/jsp/jstl/core"%>
<c:set var = "path" value = "${pageContext.request.contextPath }"/>
<!-- 자바 코드에서 String path =request.getContextPath()와 같은뜻이다 -->
 
<div style = "text-align: center;">
    <a href = "${path }/">main</a>
    <a href = "${path }/gugu.do?dan=7">구구단</a>
    <!-- do를 jsp로 바꾸어도 WEB-INF폴더 안에 파일이 있으면  컨트롤러를 거치지 않으면 바로 이동할 수 없다. (보안 때문에) -->
<!-- 컨트롤러 파일로 이동한다 -->
    <a href = "${path }/test.do">테스트</a>
    <a href = "${path }/member/list.do">회원관리</a>
</div>
<hr>
cs

 

 

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
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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
package com.example.spring01.controller;
 
import java.util.HashMap;
import java.util.Map;
 
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;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
 
import model.dto.ProductDTO;
 
@Controller //@컨트롤러 어노테이션을 사용해야 서버가 구동될때 자동적으로 올라간다.
            //@Controller 어노테이션을 붙이면 해당 클래스가 컨트롤러 역할을 한다.
public class MainController {
    //로그 객체 생성 , maincontroller.class에서 로그를 가져온다.
    private static final Logger logger =
            LoggerFactory.getLogger(MainController.class);
    
    //시작페이지로 이동
    @RequestMapping("/") //url pattern mapping
    public String main(Model model) 
    {
        //Model : 데이터를 담는 그릇 역할, map 구조로 저장됨
        // 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"//원래 코드는   "/WEB-INF/views/main.jsp"이지만 servlet-context에 
                        //main을 제외한 나머지 코드가 정의되어 있기 때문에 따로 작성하지 않아도 된다.
        
    }
    
    @RequestMapping(value="gugu.do",method=RequestMethod.GET) //구구단 관련 메소드
    public String gugu(@RequestParam int dan, Model model) {
        
        //int dan = 7;
        String result = "";
        for(int i =1; i<=9; i++) {
            result += dan+"x"+i+"="+dan*i+"<br>";
        }
        model.addAttribute("result", result);
        // gugu.jsp 로 포워딩
        // <beans:property name = "prefix" value = "/WEB-INF/views/" />
        // <beans:property name = "suffix" value =".jsp" />
        
        return "test/gugu";
        //return "/WEB-INF/views/gugu.jsp";
    }
    
    
    //리턴 타입이 void 인 경우 RequestMapping와 동일한 페이지로 넘어감
    @RequestMapping("test")
    public void test() {
        
    }
    
    @RequestMapping("test/doA"//url pattern
    public String doA(Model model) {
        logger.info("doA called..."); //로그 출력
        //model.addAttribute(key,value)
        model.addAttribute("message""홈페이지 방문을 환영합니다.");
        // 리턴타입이 void 이면 method가 종료된 후 doA.jsp로 포워드 됨
 
        return "test/doB";  //doB.jsp로 포워딩됨
    }
    
    //void인 경우 url name과 같은 페이지로 포워딩 (method name과)
    @RequestMapping("test/doB")
    public void doB() {
        logger.info("doB called...");
        //method가 종료된 후 doB.jsp로 포워드 된다.
    }
    
        //ModelAndView : Model - 데이터 저장소, View 화면
        // 데이터와 포워드할 페이지의 정보
        // forward : 주소 그대로, 화면 전환, 대량의 데이터 전달
        // redirect : 주소 바뀜, 화면 전환, 소량의 get 방식 데이터 전달
    
    @RequestMapping("test/doC")
    //HasgMap에 값을 담아 전달하는 메소드
    public ModelAndView doC() {
        Map<String, Object> map = new HashMap<>();
        //맴에 객체 저장
        map.put("product"new ProductDTO("샤프"1000));
        //new ModelAndView("view의 이름", "맵변수명", 맵);
        //하지만 ModelAndView는 값을 하나밖에 못 받는다.
        return new ModelAndView("test/doC","map",map);
        
    }
    
    @RequestMapping("test/doD")
    public String doD() {
        //redirect의 경우 return type을 String으로 설정
        //doE.jsp로 리다이렉트 됨
        return "redirect:/test/doE"//포워드 //리다이렉트는 완전히 페이지가 변경되고, 다른 표현들은 값만 보내는것
        // return "redirect:/hello.jsp";
    }
    
    @RequestMapping("test/doE")
    public void doE() {
        //doE.jsp로 포워드
    }
}
 
 
cs

 

 

test.jsp (테스트 파일, doF()메소드 포함)

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
<%@ 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

 

 

gugu.jsp (구구단 출력)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<%@ 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"%>
</head>
<body>
<%@ include file = "../Include/menu.jsp"%>
<h2>구구단 계산 결과</h2>
${result }
</body>
</html>
cs

 

 

doB.jsp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<%@ 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" %> <!-- header.jsp 를 포함 -->
</head>
<body>
<%@ include file = "../Include/menu.jsp" %> <!-- menu.jsp 를 포함 -->
doB 페이지
<h2>${message }</h2>
</body>
</html>
cs

 

 

doC.jsp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<%@ 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"%>
</head>
<body>
<%@ include file = "../Include/menu.jsp" %>
상품명 : ${map.product.name }<br>
가격 : ${map.product.price }
</body>
</html>
cs

 

 

페이지별 View와 Controller 연결 방법

 

  
  메인에서 구구단 클릭 : 구구단 버튼을 클릭하면 dan="7" 값을 넘겨주고, 컨트롤러 파일로 이동해서 gugu()메소드를 사용해
                                 구구단 출력값을 gugu.jsp 파일로 넘겨서 gugu.jsp파일에서 출력됨.
                                 (http://localhost:8080/spring01/gugu.do?dan=7)


  테스트 클릭 : http://localhost:8080/spring01/test.do


  링크테스트 doA 클릭 : 메인 컨트롤러 파일로 이동해서 model을 매개변수로 받은 doA메소드에 있는 값들을 출력함
                (http://localhost:8080/spring01/test/doA)


  링크테스트 doB 클릭 : 메인 컨트롤러파일로 이동해서 doB()메소드를 실행하지만 리턴타입이 void라 method 종료된 후
                doB.jsp로 포워딩 (실행 된다)
                (http://localhost:8080/spring01/test/doB)


  링크테스트 doC 클릭 : 메인 컨트롤러 파일로 이동해서 doC() 메소드를 실행하고, HaspMap에 출력할 값을 담아 doC.jsp 파일로 리턴시켜서
                                doC.jsp 파일에서 출력이 된다.
                               (http://localhost:8080/spring01/test/doC)


  링크테스트 doD 클릭 : 미구현 (doE 파일을 아직 안만들었음)


  링크테스트 doF 클릭 : 링크테스트 화면에서 바로 출력됨 페이지 변경 X (비동기 방식이기 때문)
                (http://localhost:8080/spring01/test.do)

 

 

 

메인 컨트롤러 파일의 테스트 클래스 생성

 

MainController.java 우클릭 -> new -> other -> JUnit Test Case -> 이름 입력후 finish

 

 

 

 

 

 

 

MainControllerTest.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
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
package com.example.spring01.controller;
 
import static org.junit.Assert.*;
 
import javax.inject.Inject;
 
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MockMvcBuilder;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
 
//JUnit4로 테스트
//스프링에서 작동되는 junit4runner을 이용해서 테스트를 한다.
@RunWith(SpringJUnit4ClassRunner.class)
 
//웹 설정 파일의 경로 지정
@WebAppConfiguration
@ContextConfiguration(// src/main/webapp/WEB-INF/spring 디렉터리 내부에 있는 하위 모든 xml을 참조한다는 뜻
        locations = {"file:src/main/webapp/WEB-INF/spring/**/*.xml"})
 
public class MainControllerTest {
    //로깅 처리를 위한 객체 선언
    private static final Logger logger = LoggerFactory.getLogger(MainControllerTest.class);
 
    @Inject //의존관계 주입
    WebApplicationContext wac;
    MockMvc mockMvc; //가상으로 컨트롤러를 테스트하기 위한 객체
    
    @Before //테스트 전에 호출되는 코드
    public void setup() throws Exception{
        //컨트롤러를 셋업
        mockMvc=MockMvcBuilders.webAppContextSetup(this.wac).build();
        //셋업이 되었다고 출력
        System.out.println("setup...");
    }
    
    // 컨트롤러의 테스트 클래스를 만드는 이유는 테스트 클래스를 만들지 않으면 다른 클래스나 목록을 전부다 만들어야만 확인이 
// 가능하지만 테스트 클래스를 만들면 바로바로 확인이 가능하기 때문에 해보는 것이다.
    
    
    @Test //JUnit가 테스트 하는 코드
    public void testDoA() throws Exception {
        //뷰가 완성되지 않은 상태에서도 테스트가 가능하다.
 
        mockMvc.perform(MockMvcRequestBuilders.get("/doA")); 
 
        //현재 doA는 get방식이 아니기 때문에 찾을수 없다고 에러를 발생시킨다.
        //하지만 /doA 앞에 /test를 붙이면 컨트롤러 클래스에서 맵핑이 되기때문에 실행이 된다.
        logger.info("doA...");
        
    }
 
}
 
cs

 

mockMvc.perform(MockMvcRequestBuilders.get("/tast/doA")); 로 코드를 변경시 컨트롤러 클래스에서 맵핑이 되기때문에 "doA called..."출력

 

 

mockMvc.perform(MockMvcRequestBuilders.get("/doA")); 로 실행할 시에는 get방식이 아니기 때문에 "No mapping for GET /doA" 문구가 출력된다.

 

 

아래 책은 제가 공부할때 활용했던 책으로 추천드리는 책이니 한번씩 읽어보시는것을 추천드립니다!! ㅎㅎ

토비의 스프링 3.1 세트:스프링의 이해와 원리 + 스프링의 기술과, 에이콘출판

이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.

728x90
반응형

'Back-End > Spring' 카테고리의 다른 글

스프링 프레임워크 입문  (0) 2019.06.02
Spring를 이용한 회원정보관리  (0) 2019.05.31
Spring 데이터베이스 연결 테스트  (0) 2019.05.29
spring 로킹툴  (0) 2019.05.28
표준 프레임워크 오픈 커뮤니티  (0) 2019.05.28
: