이전 포스트에서는 eclipse 환경에서 gradle기반 프로젝트를 생성해봤습니다.
이번에는 이전에 만들어진 gradle 프로젝트를 spring mvc환경에 맞게 설정을 해보겠습니다.
프로젝트가 생성되면 위와 같이 생성됩니다.
eclipse에서 gradle 프로젝트를 생성하는 건 버전이 오래되었기 때문에 java-library 프로젝트로 생성되기 때문에 조금 손을 봐줍니다.
settings.gradle의 파일내용을 변경해줍니다.
루트 디렉토리 하위의 폴더명을 참조하기 위해 변경합니다.
아래에 폴더명 변경에 대한 내용이 있습니다.
include('lib') => include('app')
그리고 build.gradle의 파일내용을 아래와 같이 변경해줍니다.
id 'java-library' => id 'war'
이렇게 변경하면 플러그인이 맞지 않기 때문에 프로젝트를 조금 청소를 합니다.
아래와 같이 미리 만들어져 있는 Library.java, LibraryTest.java 파일을 삭제합니다.
파일을 삭제한 후에 저는 루트 디렉토리 아래의 폴더명을 app으로 변경하였습니다.
※Rename으로 변경하게 되면 폴더명만 변경되니 Move > More Project의 Location을 변경해야 합니다.
청소가 완료되었으면 이제부터 spring mvc프로젝트에 필요한 라이브러리들을 추가합니다.
스프링은 Servlet기반이므로 Servlet 4.0을 사용하여 web.xml 없이 작성할 수 있도록 라이브러리를 설치했습니다.
스프링이 기본적으로 동작하려면 core, context가 필요합니다.
스프링 웹을 사용하려면 web, webmvc가 필요합니다.
- spring servlet 특징
1. 스프링의 Servlet 지원 패키지 구조가 이해하기 난해한 것 같습니다.
2. Servlet 4.0 web.xml 대용으로 사용하는 콜백 클래스들을 등록해 놓았지만 webmvc에 DispatcherServlet이 정의되어 있습니다. 그리고 servlet의 기본인 routing인 Controller를 찾아가는 HandlerMapper는 보이지 않는 @EnableWebMvc로 동작합니다.
위와 같이 세팅을 마친 후에 아래와 같이 프로젝트를 refresh합니다.
refresh를 하면 build.gradle에 정의되어 있는 라이브러리가 다운로드되며 프로젝트 기초세팅이 완료됩니다.
아래와 같이 Gradle Tasks탭을 클릭해 build 폴더가 나오면 정상적으로 세팅이 된겁니다.
※Gradle Tasks탭이 없는 분들은 메뉴에서 추가하시면 됩니다.
이젠 web.xml 대신 사용할 WebInitializer를 만들어 봅시다.
XML을 대신에 Initalizer를 사용합니다.
WebInitializer용도는 DispatcherServlet을 초기화하는데 사용됩니다.
단순하게 말하면 web.xml은 서블릿들 명세와 각 경로가 지정되는 테이블이라고 생각하시면 됩니다.
DispatcherServlet은 하나의 디자인 패턴으로 web.xml에 단 하나의 서블릿만 지정하고 이것이 다시 Request를 Controller로 넘겨주는 방식입니다.
그렇기 때문에 DispatcherServletInitalizer에서 DispatcherServlet을 생성하고 ServletContext와 연결합니다.
서블릿의 경로를 지정해 주는 것도 당연한 역할입니다.
web.xml을 대신하는 용도로 사용하는데 이름이 긴 이유는 ServletContext와 ApplicationContext를 다루기 때문입니다.
XML을 사용하려면 이것의 부모 클래스 중에서 AbstractDispatcherServletInitializer를 사용하면 됩니다.
AbstractAnnotationConfigDispatcherServletInitializer을 상속받아 클래스를 생성합니다.
해당 클래스는 하는 일이 web.xml과 동일합니다.
getServletConfig에 WebMvcConfigurer를 구현한 클래스를 설정 클래스로 등록하면 Controller가 동작하지 않습니다.
ServletConfig에 등록한 설정 클래스에 @ComponentScan을 달면 컨트롤러가 동작하지 않습니다.
RootConfg, ServletConfig는 ApplicationContext의 단계적 구조 때문에 정의하는 부분인데, 단일 레벨로 사용하려면 RootConfig만 정의해도 되고 거기에 설정 파일을 넣으면 됩니다.
일반적으로 Root에 공통적으로 사용하는 데이터베이스 접근과 서비스 레이어의 빈들을 생성합니다.
이제 설정파일을 만들어 봅니다. 중요한 건 WebMvcConfigurer을 implements 한 것입니다.
AppConfig.java는 단순 ApplicationContext에 등록할 빈을 정의하는 설정클래스입니다.
이 클래스에 WebMvcConfigurer를 구현하면 다양한 기능을 추가할 수 있습니다.
DispatcherServlet이 Http 메시지를 받았을 때 수행하는 기본적인 일에 어떤 구현객체를 사용할지를 지정할 수 있습니다.
아래 내용을 처리하기 위한 객체를 설정하는 것이 이 인터페이스의 역할입니다.
- DispatcherServlet은 Request를 받으면 WebApplicationContext를 찾아 Request에 붙입니다.
- 그런 후 locale에 관련된 작업을 합니다.
- 다음에는 view가 사용할 theme을 결정하게 됩니다.
- 이제 Request객체의 Content-Type이 Multipart인지를 확인하고 맞으면 MultiPartHttpServletRequest로 변환합니다.
- URL을 분석하여 적절한 Handler를 찾습니다. handler는 일반적으로 @Controller입니다.
- 처리가 끝나면 ViewResolver를 통해 view을 생성하고 돌려줍니다.
AppConfig.java 파일을 생성해봅시다.
아래의 AppConfig.java의 설정을 보면 아무 것도 없는데 스프링은 DispatcherServlet.properties에서 기본값을 가져옵니다.
- DispatcherServlet은 webmvc 패키지에 들어있습니다.
- 아래는 jsp 렌더링을 위해서 InternalResourceViewResolver를 사용했습니다.
- InternalResourceViewResolver를 사용하지 않으면 Controller에서 pre, post fix를 다 붙여주어야 하는 불편함이 있습니다.
- 또 하나 중요한 부분은 @EnableWebMvc인데 이게 없으면 Controller 라우팅이 되지 않습니다.
- 라우팅을 하려면 RouterFunctionMapping, HandlerFunctionAdapter가 필요한데 기본객체가 생성되지 않습니다.
- @EnableWebMvc는 DelegatingWebMvcConfiguration.class를 호출하는데 이것이 라우팅 객체를 생성합니다.
package application.server.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
@Configuration
@ComponentScan("application.server")
@EnableWebMvc
public class AppConfig implements WebMvcConfigurer {
@Bean
public ViewResolver viewResolver() {
return new InternalResourceViewResolver("/WEB-INF/views/", ".jsp");
}
}
이제 Controller와 index.jsp 하나 생성합니다.
/app/src/main/java/application/server/controller/HomeController.java
package application.server.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class HomeController {
@GetMapping("/hello")
public String hello() {
return "index";
}
}
/app/src/main/webapp/WEB-INF/views/index.jsp
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>Hello, BNY</h1>
</body>
</html>
서버를 실행 후 해당 URL을 접근하면 정상적으로 나오게 됩니다.
참고로 다른 방법으로는 DispatcherServletInitalizer는 편의를 위해 WebApplicationInitailizer를 구현한 클래스입니다.
아래처럼 web.xml에서 하듯 서블릿을 생성하고 ApplicationContext 생성하고 서블릿과 ServletContext를 매핑하고, 매핑과 콘테이너 기동 설정을 해 줄 수 있습니다.
WebApplicationInitializer.java
public class WebApplicationInitializer implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext servletContext) {
// Load Spring web application configuration
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.register(AppConfig.class);
// Create and register the DispatcherServlet
DispatcherServlet servlet = new DispatcherServlet(context);
ServletRegistration.Dynamic registration = servletContext.addServlet("app", servlet);
registration.setLoadOnStartup(1);
registration.addMapping("/app/*");
}
}
404에러나 정상적으로 나오지 않는 분들은 Project > build path > Configure build path 메뉴에서 아래와 같이 webapp 경로가 빠져 있는지 확인한 후 배포 경로에 맞게 설정해주시면 됩니다.
'programming_kr > spring' 카테고리의 다른 글
vscode 환경에서 spring 프로젝트 초기 설정 방법 (1) | 2022.06.19 |
---|---|
Invalid bound statement (not found) 에러 처리 (1) | 2020.12.21 |
댓글