본문 바로가기
  • 실행력이 모든걸 결정한다
Spring Series/Spring Framework

[Spring] @Controller 보충 설명

by 김코더 김주역 2021. 1. 1.
반응형

아래 링크로 첨부한 포스팅에서 Controller이 하는 역할 및 동작을 간단히 설명하였다.

kimcoder.tistory.com/234

 

[Spring] MVC 프로젝트 구조 파악하기

* 이 블로그에서 설명하는 Spring 프로젝트의 서버 환경은 Tomcat이다. Spring을 공부하기 위해 여러 사전 지식들을 익혔는데 이제 드디어 본격적으로 Spring 프로젝트를 다뤄볼 시간이다. 이번 포스팅

kimcoder.tistory.com

 

이번 포스팅에서는 Controller에서 추가적으로 알아두면 좋은 것들을 소개 할 것이다.

 

1. Model, ModelAndView 객체

Model 객체 : 속성 값을 담아두는 객체

ModelAndView 객체 : 속성 값 뿐만 아니라 View 이름도 담아둘 수 있는 객체

 

한 번 예시 코드를 살펴보자.

설명할 소스 파일들의 위치는 이렇다.

 

 

<HomeController.java>

test1(), test2() 메소드에 주목해보면,

test1() 에서는 parameter으로 Model 객체를 가져와서 addAttribute() 메소드로 속성, 속성값 쌍을 넣고 있고,

test2() 에서는 parameter없이 ModelAndView 객체를 생성하여 addObject() 메소드로 속성, 속성값 쌍을 넣고

setViewName() 메소드로 뷰의 이름을 지정하고 있다.

test1()은 문자열(뷰 이름)을 반환하고, test2()는 ModelAndView 객체를 반환한다.

두 방법 모두 잘 동작한다.

package com.example.demo;

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;
import org.springframework.web.servlet.ModelAndView;

/**
 * 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";
	}
	
	@RequestMapping("test/test1")
	public String test1(Model model) {
		model.addAttribute("a",97);
		return "test/test1";
	}
	
	@RequestMapping("test/test2")
	public ModelAndView test2() {
		ModelAndView mav = new ModelAndView();
		mav.addObject("b", 98);
		mav.setViewName("test/test2");
		return mav;
	}
}

 

jsp 파일에서는 model 객체의 각 속성 값을 ${속성명} 으로 받을 수 있다.

 

<test1.jsp>

<%@ page language="java" contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	a -> ${a}
</body>
</html>

 

View

 

<test2.jsp>

<%@ page language="java" contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	b -> ${b}
</body>
</html>

 

View

 

 

2. @RequestMapping을 클래스에 설정하는 방법

아래와 같이 서로 성격이 다른 뷰 파일들이 섞여 있다면, 하나의 컨트롤러에서 모두 처리하는 것 보다는 여러 개의 컨트롤러 클래스로 분리시키는 것이 깔끔하다. ({test1, test2}, {home})

이러한 과정에서 도움이 될만한 방법이다.

 

그래서 컨트롤러 파일을 하나 더 만들었다.

+ 20220908 comment) 필자가 실수로 클래스명을 소문자로 지정했으니 양해 바랍니다.

 

<TestController.java>

클래스와 메소드의 두 RequestMapping 경로가 합쳐져서(각각 /test+/test1, /test+/test2),

요청이 각각 /test/test1, /test/test2로 들어왔을 때 두 메소드에서 처리가 가능하게 된다.

이 방법을 쓴다면 Spring 프로젝트를 훨씬 더 계층적으로 다룰 수 있게 될 것이다.

package com.example.demo;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

@Controller
@RequestMapping("/test")
public class TestController {
	
	@RequestMapping("/test1")
	public String test1(Model model) {
		model.addAttribute("a",97);
		return "test/test1";
	}
	
	@RequestMapping("/test2")
	public ModelAndView test2() {
		ModelAndView mav = new ModelAndView();
		mav.addObject("b", 98);
		mav.setViewName("test/test2");
		return mav;
	}
}

 

@RequestMapping에 대해 더 자세히 알고 싶다면 아래 포스팅을 참고하자.

https://kimcoder.tistory.com/513

 

[Spring] @RequestMapping 심화(1)

@RequestMapping은 들어온 요청을 특정 메소드와 매핑하기 위해 사용되는 메소드다. 이번 포스팅에서는 @RequestMapping을 자세하게 알아보자. 1. DefaultAnnotationHandlerMapping - 디폴트 핸들러 매핑 전략으로..

kimcoder.tistory.com

 

 

3. Controller은 싱글톤이다?

우리가 직접 싱글톤 코드를 작성하지 않아도, Application Context에서는 Bean들을 싱글톤 방식으로 관리한다.

@Controller도 Application Context에 Bean으로 등록해주는 어노테이션들 중 하나다.

싱글톤은 멀티스레드 환경이라면 여러 스레드가 동시에 접근해서 사용할 수 있기 때문에, 상태정보를 내부에 갖고 있지 않은 무상태 방식으로 만들어져야 한다. 즉, 최대한 인스턴스 변수를 두지 않아야 한다는 의미다.

반응형

댓글