webSpringTest 프로젝트

Controller 구성

MVC흐름에 대해서 배울때 DispatcherServlet이 요청을 받은 후 컨트롤러를 실행해서 데이터 처리와 뷰페이지 이름을 가져온다고 했다.

프로젝트를 생성할때 기본적으로 제공해주는 HomeController.java를 이용해서 페이지를 어떻게 구성하는지 알아보자.

HomeController.java

제공되는 컨트롤러는 이렇게 생겼다.

package com.poby.myapp;

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";
	}
	
}

여기서 필수적인거만 빼고 지워서,

package com.poby.myapp;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
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() {
		return "home";
	}
	
}

이렇게 구성해줬다. @RequestMapping 어노테이션으로 "/"이라는 url을 요청받았을때, 컨트롤러의 home()메소드를 통해서 view페이지로 이동시켜준다는 뜻이다.

home.jsp

홈페이지의 뷰 단을 구성해주는 jsp파일이다. WEB-INF폴더 아래에 home.jsp를 열어서 전부 비우고 새 페이지로 만들자.

<%@ page language="java" contentType="text/html; charset=UTF-8;" pageEncoding="UTF-8" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page session="false" %>
<html>
<head>
	<title>Home</title>
</head>
<body>
	<h1>홈페이지</h1>
</body>
</html>

페이지에 사용할 이미지 및 소스파일은 모두 /webapp/resources폴더에서 불러올 수 있다.

만약 다른 폴더를 만들어서 소스를 불러오고 싶다면, servlet-context.xml에서 경로를 추가해줘야한다.

<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
	<!-- <resources mapping="/resources/**" location="/resources/" /> -->
	<resources mapping="/img/**" location="/img/" />

우리는 resources폴더 말고, img폴더에 사진을 넣고 불러올 것이기 때문에 이렇게 매핑했다.

webapp폴더 아래에 img폴더를 만들고 거기에 아무 이미지하나를 넣은 다음, 홈페이지에 불러오자.

<%@ page language="java" contentType="text/html; charset=UTF-8;" pageEncoding="UTF-8" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page session="false" %>
<html>
<head>
	<title>Home</title>
</head>
<body>
	<h1>홈페이지</h1>
	<img src="/myapp/img/google.gif">
</body>
</html>

제대로 나온 것을 확인했다.

Javascript나 CSS를 <link>태그로 불러올때도 외부파일을 불러오는 것이기 때문에 매핑으로 해줘야한다.

webapp폴더 아래 js_css폴더를 만들고, style.css파일을 생성하고, servlet-context.xml에서 리소스매핑을 해준다.

<resources mapping="/js_css/**" location="/js_css/" />

@charset "UTF-8";
body, ul, li{
	margin:0;
	padding:0;
}

.container{
	width:1000px;
	margin:0 auto;
}

a:link, a:visited{
	text-decoration:none;
	color:blue;
}
a:hover{
	text-decoration:underline;
	color:red;
}
<%@ page language="java" contentType="text/html; charset=UTF-8;" pageEncoding="UTF-8" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page session="false" %>
<html>
<link rel="stylesheet" href="<%= request.getContextPath() %>/js_css/style.css" type="text/css">
<head>
	<title>Home</title>
</head>
<body>
	<div class="container">
		<h1 style="text-align:center">홈페이지</h1>
		<img src="<%= request.getContextPath() %>/img/google.gif" width="100%">
	</div>
</body>
</html>

이렇게 css파일을 불러올때 리소스매핑을 해줘야한다.

 

이제 컨트롤러 작동방식을 알아보자.

test.jsp

컨트롤러가 url요청이 들어오면 @RequestMapping에 따라 매핑되어있는 뷰페이지를 반환한다고 했다.

이때 반환하는 다양한 형태가 있는데, 무엇을 어떻게 만환하는지 test.jsp를 만들어서 알아보자.

views폴더 안에 controllerTest폴더를 만들어서 test.jsp파일을 생성했다.

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!-- attribute : name, num -->
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="<%= request.getContextPath() %>/js_css/style.css" type="text/css">
<title>controllerTest/test.jsp</title>
</head>
<body>
	<div class="container">
		<ul>
			<li>이름 : ${ name }</li>
			<li>번호 : ${ num }</li>
		</ul>
	</div>
</body>
</html>

컨트롤러에서 전달받을 attribute은 name과 num이라고 설정했고, 그것들을 페이지에 표시했다.

/test1

위 소제목은 클라이언트가 요청할 url이다. 지금은 localhost:1024/myapp/test1 이다.

// localhost:1024/myapp/test1
// 반환형은 문자열(뷰페이지 파일명)
@RequestMapping("/test1")	// 디폴트값: RequestMethod.GET
public String test1() {
//		<beans:property name="prefix" value="/WEB-INF/views/" />
//		<beans:property name="suffix" value=".jsp" />
	return "controllerTest/test";
}

여기까지는 정말 아무 작업 없이 test.jsp로 이동시켜주는 메소드이다.

반환하는 뷰페이지명이 완전해보이지 않는 이유는 servlet-context.xml에서 ViewResolver의 역할로 리턴받은 뷰페이지명 앞에는 /WEB-INF/views/를, 뒤에는 .jsp를 붙이도록 했기 때문이다. 주석처리된 부분이 servlet-context.xml에서 선언된 부분이다.

이렇게 바로 test.jsp로 넘겨주면 이름과 번호 옆에 아무런 값도 나타나지 않을 것이다.

setAttribute로 뷰페이지에 attribute를 넘겨주자.

이때 매개변수로 Model객체를 넣어주고, Model.addAttribute()로 attribute이름과 값을 넣어주면 된다.

// localhost:1024/myapp/test1
// 반환형은 문자열(뷰페이지 파일명)
@RequestMapping("/test1")	// 디폴트값: RequestMethod.GET
public String test1(Model model) {
	// **매개변수**로 있는 Model객체에 데이터를 세팅하면 뷰페이지에서 사용할 수 있다. (attribute넘겨주기)
	model.addAttribute("name", "조규성");
	model.addAttribute("num", 9);
	
	// 		/WEB-INF/views/controllerTest/test.jsp
	return "controllerTest/test";
}

test.jsp에서 필요로 하는 attribute는 name과 num이기 때문에 각각 문자열과 정수를 보내줬다.

/test2

똑같이 test.jsp로 이동시켜주지만, 요청받은 url에 따라서 전달해주는 attribute가 달라질 수 있다.

// localhost:1024/myapp/test2
@RequestMapping("/test2")
public ModelAndView test2() {
	// 뷰페이지와 데이터를 한번에 리턴
	ModelAndView mav = new ModelAndView();
	
	// 데이터
	mav.addObject("name", "이순신");
	mav.addObject("num", 12);
	
	// 뷰파일명
	mav.setViewName("controllerTest/test");
	return mav;
}

이번엔 ModelAndView클래스를 이용해서 attribute와 뷰페이지명을 한 군데에 담아서 넘겨줄 것이다.

뷰페이지명이 담겼기 때문에 메소드의 반환형 또한 ModelAndView가 되어야 한다.

여기선 addAttribute()가 아닌 addObject()를 사용하고, 뷰파일명은 setViewName()을 이용해서 설정했다.

/test3

클라이언트에게서 서버로 가져오는 데이터는 parameter라고 한다. url주소 뒤에 ?로 이어지는 변수값들을 말한다.

parameter를 가져올땐 request를 이용한다.

// 클라이언트에게서 서버로 데이터 가져오기 request
// localhost:1024/myapp/test3?num=1234&name=홍길동
@RequestMapping("/test3")
public String test3(HttpServletRequest req, Model model) {
	// parameter를 변수로 선언
	String num = req.getParameter("num");
	String name = req.getParameter("name");
	
	System.out.println("num = " + num);
	System.out.println("name = " + name);
	
	model.addAttribute("num", num);
	model.addAttribute("name", name);
	
	return "controllerTest/test";
}

HttpServletRequest클래스는 이젠 익숙하다.

/test4

@RequestParam 어노테이션을 이용해서 parameter를 전달받을 수도 있다.

// localhost:1024/myapp/test4?num=5678&name=세종대왕
    @RequestMapping("/test4")
    public ModelAndView test4(@RequestParam("num") int num, @RequestParam("name") String name) {
        System.out.println("num = " + num);
        System.out.println("name = " + name);

        ModelAndView mav = new ModelAndView();
        mav.addObject("num", num);
        mav.addObject("name", name);

        mav.setViewName("controllerTest/test");

        return mav;
    }
@RequestParam("parameter명") <T> 변수명

/test5

이번엔 VO를 이용해서 parameter값을 받아보자.

myapp패키지 안에 TestVO.java를 생성하자.

package com.poby.myapp;

public class TestVO {
	private int num;
	private String name;
	
	public int getNum() {
		return num;
	}
	public void setNum(int num) {
		this.num = num;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
}

컨트롤러에서 매개변수로 TestVO를 넣어주면, 자동으로 전달받은 parameter를 TestVO안에 있는 같은 이름의 변수들에 set해준다.

// localhost:1024/myapp/test5?num=1111&name=김상민
@RequestMapping("/test5")
public String test5(TestVO vo) {
	System.out.println("num = " + vo.getNum());
	System.out.println("name = " + vo.getName());
	
	return "controllerTest/test";
}

여기선 attribute를 전달해주지 않았기 때문에 뷰페이지에는 아무것도 표시되지 않는다.

/test6

parameter를 넘겨받는 또 다른 방법이 있다.

@RequestParam 어노테이션 있으면, 넘겨받은 parameter명과 매개변수명을 다르게 할 수 있지만, 굳이 그렇게 하지 않고 어노테이션 없이 parameter명을 매개변수로 선언하면 parameter로 인식하고 넘겨받는다.

// localhost:1024/myapp/test6?num=2222&name=대조영
@RequestMapping("/test6")
public String test6(int num, String name) {
	System.out.println("num = " + num);
	System.out.println("name = " + name);
	
	return "controllerTest/test";
}

parameter명이 꼭 일치해야 실행된다.

+ Recent posts