2023. 11. 26. 11:04ㆍSpring/스프링부트_핵심원리와 활용
번 시간에는 WAS와 스프링을 통합하는 작업을 할 것이다.
[목차]
1) 스프링 컨테이너 만들기
2) 컨트롤러를 스프링컨테이너에 빈등록
3) 디스패처 서블릿을 서블릿 컨테이너로 등록
이렇게 3가지 과정을 거칠것이다.
1) 스프링 컨테이너 만들기
일단 위에 프로젝트 파일 구조이다.
위 그림처럼 서블릿에 Dispatcher Servlet을 등록하는 과정을 해야한다. 그리고 스프링 컨테이너를 위해서 build.gradle에 스프링 라이브러리 추가가 필요하다.
//스프링MVC
implementation 'org.springframework:spring-webmvc:6.0.9'
위에 저 문장을 build.gradle에 추가한다. 추가하면 아래 소스처럼 될것이다.
plugins {
id 'java'
id 'war'
}
group = 'hello'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '17'
repositories {
mavenCentral()
}
dependencies {
//서블릿
implementation 'jakarta.servlet:jakarta.servlet-api:6.0.0'
//스프링MVC
implementation 'org.springframework:spring-webmvc:6.0.9'
}
tasks.named('test') {
useJUnitPlatform()
}
그리고서 gradle 새로고침 버튼을 누르면 스프링 관련 라이브러리가 다운로드가 진행된다. 다운로드가 완료되면 아래 그림처럼 라이브러리가 추가된 것을 볼 수 있다.
2) 컨트롤러를 스프링컨테이너에 빈등록
package hello.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@GetMapping("hello-spring")
public String hello() {
System.out.println("helloController.hello");
return "hello spring!!!";
}
}
그리고서 package controller를 생성 후에 패키지 안에 HelloController 클래스를 생성한다. 클래스 안에 내용은 간단하다. console에 메시지 추가 후에 String 형태로 "hello spring!!!" 을 반환하는 로직이다.
그리고 나서 HelloConfig라는 클래스를 만든 후 HelloController를 @Bean등록한다. 이렇게 하는 이유는 @Bean을 등록한다는 의미가 스프링 컨테이너에서 관리를 하겠다는 뜻이기 때문이다. 즉, Spring Container안에 HelloController가 들어가는 과정이다.
package hello.config;
import hello.controller.HelloController;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class HelloConfig {
@Bean
public HelloController helloController() {
return new HelloController();
}
}
등록은 위에 소스처럼 @Configuration이라는 annotation으로 이 클래스는 config 클래스라는 것을 지정하였고, 이 안에 @Bean annotation을 이용해서 수동으로 HelloController를 스프링 컨테이너에 등록하였다.
package hello.container;
import jakarta.servlet.ServletContext;
public class AppInitV2Spring implements AppInit {
@Override
public void onStartUp(ServletContext servletContext) {
System.out.println("AppInitV2Spring.onStartUp");
}
}
그 다음에 어플리케이션 초기화가 필요한데 servlet package 안에 AppInitV2Spring이라는 클래스를 만들고 AppInit를 구현한다.
그러면 onStartUp을 오버라이드해야하고 그 안에 문자를 출력하였다. 그런 다음에 tomcat서버를 재기동하였다.
MyContainerInitV2 c = [class hello.servlet.AppInitV1Servlet, class hello.container.AppInitV2Spring]
그랬더니 위처럼 AppInitV2Spring을 출력하는 것을 볼 수 있다. 왜냐하면 AppInit으로 구현을 하였기 때문에 MyContainerInitV2 class파일 안을 보면 관련 클래스들을 다 출력하도록 소스를 짰기 때문이다. 자세한 것은 지난 포스팅을 보면 도움이 될 것이다.
3) 디스패처 서블릿을 서블릿 컨테이너로 등록
package hello.container;
import jakarta.servlet.ServletContainerInitializer;
import jakarta.servlet.ServletContext;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.HandlesTypes;
import java.util.Set;
@HandlesTypes(AppInit.class)
public class MyContainerInitV2 implements ServletContainerInitializer {
@Override
public void onStartup(Set<Class<?>> c, ServletContext ctx) throws ServletException {
System.out.println("MyContainerInitV2.onStartUp");
System.out.println("MyContainerInitV2 c = " + c);
System.out.println("MyContainerInitV2 ctx = " + ctx);
//class hello.container.AppInitV1Servlet
for (Class<?> appInitClass : c) {
try {
//new AppInitV1Servlet() 같은 코드
AppInit appInit = (AppInit) appInitClass.getDeclaredConstructor().newInstance();
appInit.onStartUp(ctx);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
}
이제 컨테이너 초기화에서 AppInitV2Spring을 인식하였으니 AppInitV2Spring에서 스프링 컨테이너를 생성할 것이다. (아직 우리는 스프링 컨테이너가 존재하지 않았다.)
package hello.container;
import hello.config.HelloConfig;
import jakarta.servlet.ServletContext;
import jakarta.servlet.ServletRegistration;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;
public class AppInitV2Spring implements AppInit {
@Override
public void onStartUp(ServletContext servletContext) {
System.out.println("AppInitV2Spring.onStartUp");
//스프링 컨테이너 생성
AnnotationConfigWebApplicationContext appContext =
new AnnotationConfigWebApplicationContext();
appContext.register(HelloConfig.class);
//스프링 MVC Dispatcher Servlet 생성하고 스프링 컨테이너를 연결
DispatcherServlet dispatcherServlet = new DispatcherServlet(appContext);
//dispatcher Servlet을 서블릿 컨테이너에 등록한다.
ServletRegistration.Dynamic dispatcherV2 = servletContext.addServlet("dispatcherV2", dispatcherServlet);
// /spring/* 요청은 dispatcher servlet에 실행되도록 설정한다.
dispatcherV2.addMapping("/spring/*");
}
}
위에 전체 소스를 설명해보겠다. 먼저 스프링 컨테인너 생성하는 부분은 아래 코드와 같다.
//스프링 컨테이너 생성
AnnotationConfigWebApplicationContext appContext =
new AnnotationConfigWebApplicationContext();
appContext.register(HelloConfig.class);
AnnotationConfigWebApplicationContext을 통해서 스프링 컨테이너를 만들고 아까 만들었던 @Bean등록했던 HelloConfig.class를 appContext에 등록한다. 이렇게 하면 스프링 컨테이너가 만들어졌다. 아래 그림 상자가 만들어진것이다. 그리고서 HelloConfig에서 HelloController를 Bean등록하였기 때문에 아래 그림처럼 컨트롤러가 들어가있다.
//스프링 MVC Dispatcher Servlet 생성하고 스프링 컨테이너를 연결
DispatcherServlet dispatcherServlet = new DispatcherServlet(appContext);
위 소스는 Dispatcher Servlet을 생성하고 스프링 컨테이너를 연결하는 역할이다. 그 다음 아래처럼 Spring Container에 연결되는 모습이다. appContext에 HelloConfig를 등록하였기 때문에 이 작업이 가능한 것이다.
그리고 Disptcher Servlet을 이제 Servlet Container에 등록하는 작업이다. 내가 생각하기로는 서블릿 컨테이너를 만들고 그 안에 Dispatcher Servlet을 등록하고 스프링 컨테이너에 연결해야할거 같은데 내 생각과 다르게 Dispatcher Servlet을 먼저 만들고 스프링 컨테이너에 HelloController를 연결하고서 그 다음에 이것을 ServletContainer에 등록해야한다. 그래서 아래 소스처럼 DisPatcher Servlet을 서블릿 컨테이너에 등록하는 작업이다.
//dispatcher Servlet을 서블릿 컨테이너에 등록한다.
ServletRegistration.Dynamic dispatcherV2 =
servletContext.addServlet("dispatcherV2", dispatcherServlet);
그제서야 위에 그림처럼 서블릿 컨테이너 안에 dispatcher Servlet이 들어가있는 모습이다.
// /spring/* 요청은 dispatcher servlet에 실행되도록 설정한다.
dispatcherV2.addMapping("/spring/*");
그 다음은 요청하는 매핍을 해준다. "/spring/*"의 의미는 "localhost:8081/spring/" 이 다음에 아무거나 오는 url에서는 dispatcher Servlet으로 통하라는 말이다.
example)
http://localhost:8081/spring/1
http://localhost:8081/spring/2
http://localhost:8081/spring/3
http://localhost:8081/spring/etc
위 주소 모두 다 dispacther Servlet을 통하도록 되어있다.
server 재시작 후에 http://localhost:8081/spring/hello-spring를 들어가본다. /spring/인 주소가 있기 때문에 dispatcher Servlet을 통하도록 되어있다.
위 처럼 HelloController가 실행이 정상적으로 작동 되었고, console에도 아래처럼 helloController.hello가 잘 나오고 있다.
이번에는 dispatcher servlet을 만들고 servler container에 등록하고, 그리고 스프링 컨테이너도 만든다음 컨트롤러를 연결시키고, 수동으로 빈도 등록하고.. 진짜 많은 작업을 하였다. 이게 우리가 스프링부트를 사용하면 자동으로 해준다는 것인지 강의를 더 봐야알수 있겠지만 지금도 등록하는데에만 정말 많은 작업과 시간이 소요되었고, 포스팅을 하기 위해서 다시 처음부터 코드를 쳐보았는데 처음보았을 때보다 두번재 했을때 과정이 더 잘 들어왔던거 같다.
이 글을 보는 여러분들도 한번 직접 코드를 쳐보고 실행을 하면서 원리를 파악하면 정말 많은 도움이 될것이라고 생각한다.
'Spring > 스프링부트_핵심원리와 활용' 카테고리의 다른 글
스프링 MVC 서블릿 컨테이너 초기화 지원 (0) | 2023.11.27 |
---|---|
서블릿 컨테이너 초기화2 (0) | 2023.11.26 |
서블릿 컨테이너 초기화1 (1) | 2023.11.16 |