1. 소개
이 기사에서는 Spring MVC의 핵심 개념인 컨트롤러에 초점을 맞출 것입니다.
2. 개요
한 걸음 뒤로 물러나 일반적인 Spring Model View Controller 아키텍처 에서 Front Controller 의 개념을 살펴보는 것으로 시작하겠습니다 .
매우 높은 수준에서 우리가 보고 있는 주요 책임은 다음과 같습니다.
- 수신 요청 가로채기
- 요청의 페이로드를 데이터의 내부 구조로 변환
- 추가 처리를 위해 데이터를 모델 로 보냅니다.
- 모델 에서 처리된 데이터를 가져 오고 렌더링을 위해 해당 데이터를 보기 로 이동합니다.
다음은 Spring MVC 의 상위 수준 흐름에 대한 빠른 다이어그램입니다 .
보시다시피 DispatcherServlet 은 아키텍처에서 Front Controller 역할을 합니다 .
다이어그램은 일반적인 MVC 컨트롤러와 RESTful 컨트롤러 모두에 적용할 수 있습니다. 약간의 차이가 있습니다(아래 설명 참조).
전통적인 접근 방식에서 MVC 응용 프로그램은 서비스 지향이 아니므 로 컨트롤러 에서 받은 데이터를 기반으로 최종 뷰를 렌더링하는 View Resolver 가 있습니다 .
RESTful 애플리케이션은 서비스 지향적이고 원시 데이터(일반적으로 JSON/XML)를 반환하도록 설계되었습니다. 이러한 애플리케이션은 뷰 렌더링을 수행하지 않기 때문에 뷰 확인자가 없습니다 . 컨트롤러 는 일반적으로 HTTP 응답을 통해 직접 데이터를 보낼 것으로 예상됩니다.
MVC0 스타일 컨트롤러부터 시작하겠습니다.
3. 메이븐 의존성
Spring MVC 로 작업할 수 있으려면 먼저 Maven 의존성을 처리해야 합니다.
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.0.6.RELEASE</version>
<dependency>
최신 버전의 라이브러리를 얻으려면 Maven Central에서 spring-webmvc를 살펴보십시오 .
4. 프로젝트 웹 구성
이제 컨트롤러 자체를 살펴보기 전에 먼저 간단한 웹 프로젝트를 설정하고 빠른 서블릿 구성을 수행해야 합니다.
먼저 web.xml 을 사용하지 않고 초기화 프로그램을 사용 하여 DispatcherServlet 을 설정 하는 방법을 살펴보겠습니다 .
public class StudentControllerConfig implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext sc) throws ServletException {
AnnotationConfigWebApplicationContext root =
new AnnotationConfigWebApplicationContext();
root.register(WebConfig.class);
root.refresh();
root.setServletContext(sc);
sc.addListener(new ContextLoaderListener(root));
DispatcherServlet dv =
new DispatcherServlet(new GenericWebApplicationContext());
ServletRegistration.Dynamic appServlet = sc.addServlet("test-mvc", dv);
appServlet.setLoadOnStartup(1);
appServlet.addMapping("/test/*");
}
}
XML 없이 설정하려면 클래스 경로에 servlet-api 3.1.0이 있어야 합니다.
web.xml 은 다음 과 같습니다.
<servlet>
<servlet-name>test-mvc</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/test-mvc.xml</param-value>
</init-param>
</servlet>
여기 에서 Spring 컨텍스트를 로드하는 데 사용되는 XML 파일 을 가리키는 contextConfigLocation 속성 을 설정하고 있습니다. 속성이 없으면 Spring은 {servlet_name}-servlet.xml 이라는 파일을 검색합니다 .
우리의 경우 servlet_name 은 test-mvc 이므로 이 예제에서 DispatcherServlet 은 test-mvc-servlet.xml 이라는 파일을 검색합니다 .
마지막으로 DispatcherServlet 을 설정 하고 특정 URL 에 매핑하여 여기에서 Front Controller 기반 시스템 을 완성해 보겠습니다.
<servlet-mapping>
<servlet-name>test-mvc</servlet-name>
<url-pattern>/test/*</url-pattern>
</servlet-mapping>
따라서 이 경우 DispatcherServlet 은 /test/* 패턴 내의 모든 요청을 가로챕 니다.
5. 스프링 MVC 웹 구성
이제 Spring Config 를 사용하여 Dispatcher Servlet 을 설정 하는 방법을 살펴보겠습니다 .
@Configuration
@EnableWebMvc
@ComponentScan(basePackages= {
"com.baeldung.controller.controller",
"com.baeldung.controller.config" })
public class WebConfig implements WebMvcConfigurer {
@Override
public void configureDefaultServletHandling(
DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
@Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver bean =
new InternalResourceViewResolver();
bean.setPrefix("/WEB-INF/");
bean.setSuffix(".jsp");
return bean;
}
}
이제 XML 을 사용하여 Dispatcher Servlet 을 설정하는 방법을 살펴보겠습니다 . DispatcherServlet XML 파일 의 스냅샷 – DispatcherServlet 이 사용자 정의 컨트롤러 및 기타 Spring 엔터티 를 로드하는 데 사용 하는 XML 파일 은 다음과 같습니다.
<context:component-scan base-package="com.baledung.controller" />
<mvc:annotation-driven />
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/WEB-INF/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
이 간단한 구성을 기반으로 프레임워크는 물론 클래스 경로에서 찾을 모든 컨트롤러 빈을 초기화합니다.
뷰 렌더링을 담당하는 View Resolver도 정의하고 있다는 점에 유의 하십시오. 여기서는 Spring의 InternalResourceViewResolver 를 사용할 것입니다. 이는 보기의 이름이 확인 될 것으로 예상합니다. 즉, 접두어와 접미어(둘 다 XML 구성 에 정의됨)를 사용하여 해당 페이지를 찾는 것을 의미합니다 .
예를 들어 컨트롤러 가 " welcome" 이라는 보기 를 반환하면 보기 확인 자는 WEB-INF 폴더 에서 "welcome.jsp" 라는 페이지를 확인하려고 시도 합니다.
6. MVC 컨트롤러
이제 마지막으로 MVC 스타일 컨트롤러를 구현해 보겠습니다.
모델 맵 과 뷰 객체 를 포함하는 ModelAndView 객체를 반환하는 방법에 주목하십시오 . 둘 다 데이터 렌더링을 위해 View Resolver 에서 사용됩니다.
@Controller
@RequestMapping(value = "/test")
public class TestController {
@GetMapping
public ModelAndView getTestData() {
ModelAndView mv = new ModelAndView();
mv.setViewName("welcome");
mv.getModel().put("data", "Welcome home man");
return mv;
}
}
그래서 우리는 여기서 정확히 무엇을 설정 했습니까?
먼저 TestController 라는 컨트롤러를 만들고 "/test" 경로 에 매핑했습니다 . 클래스에서 우리는 ModelAndView 객체 를 반환하고 GET 요청에 매핑되는 메서드를 생성했습니다. 따라서 “ test ” 로 끝나는 모든 URL 호출 은 DispatcherServlet 에 의해 TestController 의 getTestData 메서드 로 라우팅됩니다 .
물론 좋은 측정을 위해 일부 모델 데이터와 함께 ModelAndView 개체를 반환하고 있습니다.
뷰 개체의 이름은 " welcome "으로 설정되어 있습니다. 위에서 설명한 것처럼 View Resolver 는 WEB-INF 폴더에서 " welcome.jsp "라는 페이지를 검색합니다 .
아래에서 예제 GET 작업 의 결과를 볼 수 있습니다 .
URL 은 "test" 로 끝납니다 . URL 의 패턴 은 "/test/test "입니다.
첫 번째 "/test" 는 Servlet에서 가져오고 두 번째는 컨트롤러 매핑에서 가져옵니다.
7. REST에 대한 더 많은 스프링 의존성
이제 RESTful 컨트롤러를 살펴보겠습니다. 물론 시작하기에 좋은 곳은 필요한 추가 Maven 의존성입니다.
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.0.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.0.6.RELEASE</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.5</version>
</dependency>
</dependencies>
이러한 의존성의 최신 버전은 jackson-core , spring-webmvc 및 spring-web 링크를 참조하십시오 .
여기서 Jackson 은 물론 필수는 아니지만 JSON 지원을 활성화하는 좋은 방법임에는 틀림없습니다. 해당 지원에 대해 자세히 알아 보려면 여기에서 메시지 변환기 문서를 살펴보십시오 .
8. REST 컨트롤러
Spring RESTful 애플리케이션 의 설정은 View Resolver 와 모델 맵 이 없다는 유일한 차이점을 제외 하면 MVC 애플리케이션의 설정과 동일합니다.
API는 일반적으로 원시 데이터(일반적으로 XML 및 JSON 표현)를 클라이언트에 다시 반환하므로 DispatcherServlet 은 뷰 확인자를 우회 하고 HTTP Response body에서 바로 데이터를 반환합니다 .
간단한 RESTful 컨트롤러 구현을 살펴보겠습니다.
@Controller
public class RestController {
@GetMapping(value = "/student/{studentId}")
public @ResponseBody Student getTestData(@PathVariable Integer studentId) {
Student student = new Student();
student.setName("Peter");
student.setId(studentId);
return student;
}
}
메소드의 @ResponseBody 어노테이션에 주목하십시오. Spring이 뷰 리졸버 를 우회 하고 본질적으로 HTTP 응답의 본문에 직접 출력을 작성하도록 지시합니다 .
출력의 빠른 스냅샷이 아래에 표시됩니다.
위의 출력은 학생 ID 가 1 인 API에 GET 요청을 보낸 결과입니다 .
여기서 한 가지 간단한 참고 사항은 @RequestMapping 어노테이션은 잠재력 을 최대한 활용하기 위해 실제로 탐색해야 하는 핵심 어노테이션 중 하나라는 것입니다.
9. 스프링 부트와 @RestController 어노테이션
Spring Boot 의 @RestController 어노테이션은 기본적으로 항상 @ResponseBody를 정의하지 않아도 되는 빠른 지름길 입니다 .
다음은 이 새 어노테이션을 사용하는 이전 예제 컨트롤러입니다.
@RestController
public class RestAnnotatedController {
@GetMapping(value = "/annotated/student/{studentId}")
public Student getData(@PathVariable Integer studentId) {
Student student = new Student();
student.setName("Peter");
student.setId(studentId);
return student;
}
}
10. 결론
이 사용방법(예제)에서는 일반적인 MVC 애플리케이션과 RESTful API의 관점에서 Spring에서 컨트롤러를 사용하는 기본 사항을 살펴봅니다.
물론 기사의 모든 코드는 GitHub에서 사용할 수 있습니다 .