Spring MVC를 이용한 웹 페이지 작성 2

oyeon·2021년 1월 21일
0

Web Backend

목록 보기
56/87

DispatcherServlet을 FrontController로 설정 방법

  • web.xml 파일에 설정
  • javax.servlet.ServletContainerInitializer 사용
    • 서블릿 3.0 스펙 이상에서 web.xml파일을 대신해서 사용할 수 있다.
  • org.springframework.web.WebApplicationInitializer 인터페이스를 구현해서 사용

web.xml 파일에서 DispatcherServlet 설정

  • xml spring 설정 읽어들이도록 DispathcerServlet 설정
  • Java config spring 설정 읽어들이도록 DispathcerServlet 설정
<url-pattern>/</url-pattern> // 이 부분으로 인해 모든 요청을 다 받아들임

WebApplicationInitializer 구현해서 설정

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

@Configuration

  • org.springframework.context.annotation의 Configuration 애너테이션과 Bean 애너테이션 코드를 이용하여 스프링 컨테이너에 새로운 Bean 객체를 제공할 수 있다.

@EnableWebMvc

  • DispatcherServlet의 RequestMappingHandlerMapping, RequestMappingHandlerAdapter, ExceptionHandlerExceptionResolver, MessageConverter 등 Web에 필요한 빈들을 대부분 자동으로 설정해준다.
  • xml로 설정의 mvc:annotation-driven/ 와 동일하다.
  • 기본 설정 이외의 설정이 필요하다면 WebMvcConfigurerAdapter 를 상속받도록 Java config class를 작성한 후, 필요한 메서드를 오버라이딩 하도록 한다.

@ComponentScan

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

WebMvcConfigurerAdapter

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

Controller(Handler) 클래스 작성하기

  • @Controller 애너테이션을 클래스 위에 붙인다.
  • 맵핑을 위해 @RequestMapping 애너테이션을 클래스나 메서드에서 사용한다.

@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")

실습

  • Directory 구조
  1. config package 생성 - kr.or.connect.mvcexam.config
  2. WebMvcContextConfiguration class 작성 - WebMvcConfigurerAdapter를 상속받도록 생성
// WebMvcContextConfiguration.java : DispatcherServlet이 실행될 때 읽어들이는 설정 파일
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" })
public class WebMvcContextConfiguration extends WebMvcConfigurerAdapter {
	/* <url-pattern>/</url-pattern>을 사용해 모든 요청을 다 받아들이도록 하고 있음
	 * 각각의 디렉토리를 만들어 놓고 / 이하 요청이 들어오면 해당 디렉터리에서 찾는다는 의미
	 * URL /css/** 요청 -> /css/ 디렉터리에서 찾음
	 * */
	@Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        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를 사용하게 한다.
	 * Mapping 정보가 없는 url 요청은 Spring의 DefaultServletHttpRequestHandler가 처리하게 한다.
	 * DefaultServletHttpRequestHandler는 WAS의  DefaultServlet에게 해당 일을 넘긴다.
	 * WAS는 DefaultServlet이 static한 자원을 읽어서 보여주게 한다.
	 */
    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }
   
    /* 특정 URL에 대한 처리를 Controller 클래스를 작성하지 않고 매핑할 수 있도록 해준다.
     * 요청이  "/"로 들어오면 "main" 이름의 view로 보여준다.
     * main 이름만으로는 보여줄 수 없고 view name은 ViewResolver 객체를 이용해서 찾아온다.
     * 뷰 정보는 아래 getInternalResourceViewResolver()를 통해 찾는다.
     * 결국 /WEB-INF/views/main.jsp 를 찾으면 된다.
     */
    @Override
    public void addViewControllers(final ViewControllerRegistry registry) {
    		System.out.println("addViewControllers가 호출됩니다. ");
        registry.addViewController("/").setViewName("main");
    }
    
    @Bean
    public InternalResourceViewResolver getInternalResourceViewResolver() {
        InternalResourceViewResolver resolver = new InternalResourceViewResolver();
        resolver.setPrefix("/WEB-INF/views/");
        resolver.setSuffix(".jsp");
        return resolver;
    }
}
 public void addResourceHandlers(ResourceHandlerRegistry registry) {
        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를 사용하게 한다.
	 * Mapping 정보가 없는 url 요청은 Spring의 DefaultServletHttpRequestHandler가 처리하게 한다.
	 * WAS는 DefaultServlet에게 해당 일을 넘겨 static한 자원을 읽게 하고 보여주게 해준다.
	 */
    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }
   
    /* 특정 URL에 대한 처리를 Controller 클래스를 작성하지 않고 매핑할 수 있도록 해준다.
     * 요청이  "/"로 들어오면 "main" 이름의 view로 보여준다.
     * main 이름만으로는 보여줄 수 없고 view name은 ViewResolver 객체를 이용해서 찾아온다.
     * 뷰 정보는 아래 getInternalResourceViewResolver()를 통해 찾는다.
     * 결국 /WEB-INF/views/main.jsp 를 찾으면 된다.
     */
    @Override
    public void addViewControllers(final ViewControllerRegistry registry) {
    		System.out.println("addViewControllers가 호출됩니다. ");
        registry.addViewController("/").setViewName("main");
    }
    
    @Bean
    public InternalResourceViewResolver getInternalResourceViewResolver() {
        InternalResourceViewResolver resolver = new InternalResourceViewResolver();
        resolver.setPrefix("/WEB-INF/views/");
        resolver.setSuffix(".jsp");
        return resolver;
    }
}
  1. 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>Spring JavaConfig Sample</display-name>

  <servlet>
    <servlet-name>mvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    
    <!-- 설정 파일 클래스가 등록되고 있다. 항상 패키지명까지 포함해서 등록해야 한다. -->
    <!-- AnnotationConfigWebApplicationContext를 사용할 것이다. 컨테이너 등록 -->
    <init-param>
      <param-name>contextClass</param-name>
      <param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
    </init-param>
    <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>
  <!-- url이 "/" 즉 모든 요청이 들어오면 -->
  <!-- mvc라는 이름을 가진 sevlet element 안에 있는 mvc를 찾고 그곳에 등록되어 있는 servlet-class를 본다. --> 
  <!-- Spring이 제공하고 있는 DispatcherServlet를 FrontController로 하는 것을 볼 수 있다. -->
    <servlet-name>mvc</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>
</web-app>
  1. main.jsp 생성 - 동작하는지 테스트
  • ※ 프로젝트 생성시 기본적으로 생성되어있는 index.jsp 를 삭제하자.
  • index.jsp의 위치나 이름이 변경되지 않으면 기본적으로 index.jsp을 먼저 찾아간다.

결과

profile
느리더라도 꾸준히, 즐겁게

0개의 댓글