Spring MVC (4) 웹 페이지 작성 실습 2

DispatcherServlet을 FrontController로 설정하는 방법

✔ 방법 1. web.xml 파일에서 설정 ✔

1) xml spring 설정 읽어들이도록 DispatcherServlet 설정

2) Java config spring 설정 읽어들이도록 DispatcherServlet 설정
url-pattern을 '/'으로 두어 모든 요청이 들어올 수 있도록 함

방법 2. WebApplicationInitializer를 구현해 설정

  • Spring MVC는 ServletContainerInitializer를 구현하고 있는 SpringServletContainerInitializer를 제공함
  • SpringServletContainerInitializer는 WebApplicationInitializer 구현체를 찾아 인스턴스를 만들고 해당 인스턴스의 onStartup 메소드를 호출하여 초기화

Spring MVC 설정 개념

JavaConfig로 DispatcherServlet이 읽어들여야 할 설정을 정의

  • @Configuration
    Java Config 파일임을 명시

  • @EnableWebMvc
    Web에 필요한 대부분의 빈들을 자동으로 설정

  • @ComponentScan

    • Controller, Service, 등의 어노테이션이 붙은 클래스를 찾아 스프링 컨테이너가 빈으로 관리할 수 있게 함
    • DefaultAnnotationHandlerMapping과 RequestMappingHandlerMapping 구현체는 다른 핸드러 매핑보다 훨씬 더 정교한 작업을 수행, 어노테이션을 사용해 매핑 관계를 찾음, 스프링 컨테이너애플리케이션 컨텍스트에 있는 요청 처리 빈)에서 RequestMapping 어노테이션을 클래스나 메소드에서 찾아 HandlerMapping 객체 생성
    • HandlerMapping은 서버로 들어온 요청을 어느 핸들러로 전달할지 결정
    • DefaultAnnotationHandlerMapping은 DispatcherServlet이 기본으로 등록하는 기본 핸들러 맵핑 객체이고, RequestMappingHandlerMapping은 더 강력하고 유연하지만 사용하려면 명시적으로 설정해야 함
  • WebMvcConfigurerAdapter

    • org.springframework.web.servlet.config.annotation. WebMvcConfigurerAdapter
    • @EnableWebMvc 를 이용하면 기본적인 설정이 모두 자동으로 되지만, 기본 설정 이외의 설정이 필요할 경우 해당 클래스를 상속 받은 후, 메소드를 오버라이딩 하여 구현
  • @RequestMapping

    • Http 요청과 이를 다루기 위한 Controller 의 메소드를 연결하는 어노테이션
    • Http Method 와 연결하는 방법
      • @RequestMapping(value="/users", method=RequestMethod.POST)
      • From Spring 4.3 version (@GetMapping, @PostMapping, @PutMapping, @DeleteMapping, @PatchMapping)
    • Http 특정 해더와 연결하는 방법
      • @RequestMapping(method = RequestMethod.GET, headers = "content-type=application/json")
    • Http Parameter 와 연결하는 방법
      • @RequestMapping(method = RequestMethod.GET, params = "type=raw")
    • Content-Type Header 와 연결하는 방법
      • @RequestMapping(method = RequestMethod.GET, consumes = "application/json")
    • Accept Header 와 연결하는 방법
      • @RequestMapping(method = RequestMethod.GET, produces = "application/json")

Controller 작성 실습 1/3

전체적인 파일 구조는 아래 사진 참고

1) resource 폴더와 동일 위치에 java 폴더 생성

2) java 폴더 내에 kr.or.connect.mvcexam.config 패키지 생성

3) WebMvcContextConfiguration 클래스 생성, 생성 시 WebMvcConfigurerAdapter를 상속받도록 함

WebMvcContextConfiguration.java

package kr.or.connect.mvcexam.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = { "kr.or.connect.mvcexam.controller" })
// controller에서 컴포넌트 스캔할 것, base packages는 꼭 지정하기
public class WebMvcContextConfiguration extends WebMvcConfigurerAdapter {
	@Override
	public void addResourceHandlers(ResourceHandlerRegistry registry) {
		// css, img 등의 파일들까지 요청 들어올 때는 특정 부분에서만 찾도록 하여 컨트롤러 request mapping까지 가지 않도록 함
		registry.addResourceHandler("/assets/**").addResourceLocations("classpath:/META-INF/resources/webjars/")
				.setCachePeriod(31556926);
		registry.addResourceHandler("/css/**").addResourceLocations("/css/").setCachePeriod(31556926);
		registry.addResourceHandler("/img/**").addResourceLocations("/img/").setCachePeriod(31556926);
		registry.addResourceHandler("/js/**").addResourceLocations("/js/").setCachePeriod(31556926);
	}

	// default servlet handler를 사용하게 합니다.
	@Override
	public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
		// 핸들러 사용 -> 매핑 정보가 없는 url 요청을 처리
		// WAS의 default servlet에 넘김 -> static한 자원 읽어 view
		configurer.enable();
	}

	@Override
	public void addViewControllers(final ViewControllerRegistry registry) {
		// 특정 URL에 대한 처리를 컨트롤러 클래스 작성하지 않고 처리
		System.out.println("addViewControllers가 호출됩니다. ");
		registry.addViewController("/").setViewName("main");
	}

	@Bean
	public InternalResourceViewResolver getInternalResourceViewResolver() {
		InternalResourceViewResolver resolver = new InternalResourceViewResolver();
		resolver.setPrefix("/WEB-INF/views/"); // view name 앞에 붙임
		resolver.setSuffix(".jsp"); // view name 뒤에 붙임
		// 즉 이 메서드를 거쳐 /WEB-INF/views/main.jsp 파일을 보여주게 되는 것
		return resolver;
	}
}

4) src/main/webapp/WEB-INF/web.xml 파일 수정

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
	<display-name>Archetype Created Web Application</display-name>
	<servlet>
		<!-- servlet-mapping과 연결되어 있음 -->
		<servlet-name>mvc</servlet-name>
		<!-- Front Controller로 사용하기 위해 DispatcherServlet 클래스 등록 -->
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<!-- 스프링 빈 컨테이너 설정 -->
		<init-param>
			<param-name>contextClass</param-name>
			<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
		</init-param>
		<!-- Configuration 정보 읽어내기 위해 위치 등록 -->
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>kr.or.connect.mvcexam.config.WebMvcContextConfiguration</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>mvc</servlet-name>
		<!-- 모든 요청이 들어오면 servlet-name과 같은 서블릿에 등록되어 있는 서블릿 클래스 실행  -->
		<url-pattern>/</url-pattern>
	</servlet-mapping>

</web-app>

5) src/main/webapp/WEB-INF 경로에 views 폴더 생성, main.jsp 파일 생성

main.jsp

<%@ page language="java" contentType="text/html; charset=EUC-KR"
    pageEncoding="EUC-KR"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">
<title>Insert title here</title>
</head>
<body>
<h1>main page!</h1>
</body>
</html>

6) 프로젝트를 톰캣 서버에서 실행

각종 에러

No mapping found for HTTP request with URI [/mvcexam/] in DispatcherServlet with name 'mvc'

web.xml is missing and <failOnMissingWebXml> is set to true

크게 다음과 같은 두가지 에러를 마주쳤다. 첫번째는 구글링해보니 컨트롤러 부분과 관련이 있다는데, 나는 addViewControllers를 사용하고 있는지라 관련이 없어보였다.

두번째 문제는 web.xml 파일과 pom.xml 파일 간의 에러였는데 Deployment Assembly를 건들다가 생긴 오류 같았다.
아래는 정상적으로 동작한 프로젝트의 deploy path이니 나중에 에러가 난다면 참고해봐야겠다.

분명 코드도 잘 작성했고 버전도 맞고 다른사람들 보니 잘 작동되는 듯 했는데 안되고 몇시간째 해결책을 찾던 중 다음 글을 발견했다.

https://stackoverflow.com/questions/28054929/eclipse-fails-to-import-maven-project

결국 이클립스 설정을 건들다보니 꼬여버렸던 것 같다. 하루를 지나지 않고 문제가 해결되어 참 다행이었다...

좋은 웹페이지 즐겨찾기