Spring MVC 활용

라코마코·2020년 4월 21일
3

부스트코스 이론

목록 보기
5/6

Spring MVC 설정

구조

  1. Maven Project 생성 Spring MVC는 웹에서 돌아가는 프로젝트 임으로
    Maven web-app archetype 으로 생성

의존성 추가

servlet , jsp , jstl 의존성 추가.

jsp, jstl은 리액트나 뷰같은 프론트 프레임워크를 따로 사용한다면 필요하지 않지만

javax.servlet 은 필수적이다.

Spring에서 servlet은 Dispatcher Servlet이 사용되고 Front Controller로써 작동하게 된다.

Spring 의존성

spring-context : 스프링 bean context 사용을 위해서 필요!

spring-webmvc : spring web mvc 모델을 사용할 예정이여서 추가 !

db 도 사용한다면

spring-tx , dbcp , spring-jdbc등도 필요하지만 , 이번 실습에서는 사용하지 않아 넣지 않았다.

기본적으로 의존성들은 그때 그때 필요에 의하여 더하고 설정을 하면 된다.

추가적 설정

eclipse facest , pom.xml에서 target/source jdk 설정 들을 마무리 해주면 Spring 설정의 기반을 닦게 된것이다.

Spring MVC 설정

의존성을 다운 받았다고 해서 설정이 끝난것이 아니다.

사용자가 직접 Spring MVC 설정을 건들여야 하는 경우도 존재한다.

Dispatcher Servlet을 FrontControlelr로 설정하기

Dispatcher Servlet을 설정하는 방법은 3가지가 존재한다.

  1. web.xml 파일에서 수행하거나
  2. javax.servlet.ServletContainerInitializer 을 이용하여 설정하거나
  3. org.springframework.web.WebApplicationInitializer 인터페이스를 구현하여 설정한다.

보통 1,3을 많이 쓰인다고 한다.

web.xml에서 설정하는 방법

maven-archetypes의 WEB-INF의 web.xml에

<?xml version="1.0" encoding="UTF-8"?>

<web-app xmlns="http://java.sun.com/xml/ns/javaee" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
version="3.1" 
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_1.xsd"
metadata-complete="true">
	<display-name>Spring JavaConfig Sample</display-name>
	<servlet>
		<servlet-name>dispatcher</servlet-name>
		<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>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>
			kr.or.connect.mvcexam.config.WebMvcContextConfiguration
			kr.or.connect.mvcexam.config.WebMvcControllerConfiguration
			</param-value>
			
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>dispatcher</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>
</web-app>

servlet은 was에서 쓰일 servlet을 설정하는 xml 태그이고.
init-param으로 지정하면 나중에 servlet-config에서 해당 설정됙 이름으로 value값을 가져오는것이 가능하다.
http://wiki.metawerx.net/wiki/Web.xml.InitParam
여기서는 servlet handler에 정보를 입력하는것으로 기억하자.

contextClass에는 스프링 config 방식을 지원하는 클래스를 입력하고
(AnnotationConfigWebApplicationContext은 어노테이션 방식 스프링 설정을 의미한다.)

contextConfigLocation에는 스프링 설정을 저장한 부분을 패키지 포함해서 놓아두면 된다.

그후 servlet-mapping을 지정하면

servlet 설정은 어느정도 끝이 났다.

Spring Java Config 설정

Spring MVC 설정

무엇을 설정하는가?
MVC와 관련된 설정들.

맨 위에 나온 그림들중

HandlerMapping , HandlerAdapter , ViewResolver에 관련된 설정을 진행한다.
많은 설정을 해야하지만 @EnableWebMvc 어노테이션을 적용시키면 대부분 Spring Web에 필요한 빈들은 자동으로 설정 해준다.

나머지, 추가적인 설정을 해야한다면 spring 5 버전부터 WebMvcConfigurer 가상 객체 상속시켜
오버라이딩 하여 고쳐나가면 된다.

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.WebMvcConfigurer;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

@Configuration
@EnableWebMvc
public class WebMvcContextConfiguration implements WebMvcConfigurer{
  // resource 요청 처리하는 위치를 지정해줌.
  @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를 사용하게 합니다. 매핑정보가 없을경우 실행
  @Override
  public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
      configurer.enable();
  }
 
  // 특정 url에 대한 처리를 지정해줌
  @Override
  public void addViewControllers(final ViewControllerRegistry registry) {
          System.out.println("addViewControllers가 호출됩니다. ");
      registry.addViewController("/").setViewName("main");
  }
  
  // view name을 찾는 resolver 설정 Prefix,suffix 설정한 부분에서 찾아줌
  @Bean
  public InternalResourceViewResolver getInternalResourceViewResolver() {
      InternalResourceViewResolver resolver = new InternalResourceViewResolver();
      resolver.setPrefix("/WEB-INF/views/");
      resolver.setSuffix(".jsp");
      return resolver;
  }
}
리소스 요청 처리 설정
@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);
  }

addResourceHandlers를 오버라이딩, 서비스가 아닌 , resource를 요구하는 요청을 처리하는 핸들러를 등록한다.

기본 servlet handler 사용.
  @Override
  public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
      configurer.enable();
  }

매핑 정보가 없을 경우, default servlet handler가 실행되도록 설정함 ( 리소스 요청 의 경우 handler mapping 매핑되어 있지 않음으로 필요하다. )

특정 url 처리 설정
  @Override
  public void addViewControllers(final ViewControllerRegistry registry) {
          System.out.println("addViewControllers가 호출됩니다. ");
      registry.addViewController("/").setViewName("main");
  }

이 메소드에서 registry에 매핑된 주소가 들어오게 되면, 리턴할뷰 를 지정해준다.

View 이름을 찾아주는 resolver 설정 view resolver 설정
  @Bean
  public InternalResourceViewResolver getInternalResourceViewResolver() {
      InternalResourceViewResolver resolver = new InternalResourceViewResolver();
      resolver.setPrefix("/WEB-INF/views/");
      resolver.setSuffix(".jsp");
      return resolver;
  }

getInternalResourceViewResolver

setPrefix , Suffix으로 , view의 위치와 확장자를 정하여 리턴할 수 있도록 해준다.

Spring Context

package kr.or.connect.mvcexam.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan(basePackages= {"kr.or.connect.mvcexam.controller"})
public class WebMvcControllerConfiguration {

}

Controller

import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;

@Controller
public class PlusController {
  // String , ModelAndView 2가지 타입으로 넘겨줄 수 있음.
  @GetMapping(path="/plusForm")
  public String plusform() {
    return "plusForm";
  }
  
  //@RequestParam : Mapping argument에붙을 수 있음 url/meta?no=1;
  //http parameter의 name과 매핑되어서 값을 꺼내옴.
  //required 속성으로 필수 여부 지정 가능
  
  //@PathVariable , url PathVariable을 가져옴  url/{id}
  // placeholder와 @PathVariable이 같다면 값을 가져옴.
  // 
  @PostMapping(path="/plusForm")
  public String plusForm(@RequestParam(name="value1",required=true) int value1,
      @RequestParam(name="value2",required=true) int value2,ModelMap modelMap) {
    //requestScope에 넣어도 되지만, spring이 제공하는 modelMap에 넣어도 된다. 이게 더 권장
    //알아서 requestScope에 넣음
    modelMap.addAttribute("value1",value1);
    modelMap.addAttribute("value2",value2);
    modelMap.addAttribute("value3",value1+value2);
    return "plusResult";
  }
}

TransactionManager

  1. 원자성 : ( 전체가 성공하거나 전체가 실패함 )
  2. 일관성 : ( 작업 처리 결과가 항상 일관되어야 한다. )
  3. 독립성 : ( 2 이상의 트랜잭션이 동시에 실행되고 있다고 해도 , 트랜잭션끼리 트랜잭션 연산에 끼어들 수 없다 . )
  4. 지속성 :

Jdbc 트랜잭션 처리

Connection 객체의 setAutoCommit을 false로 지정해야한다.

모든 SQL이 실행후 Connection의 commit()을 호출 하고 나서 connection을 종료시킨다.

@EnableTransactionManagement

Spring Java Config에서 트랜잭션 활성화 하는데 사용.

PlatFormTransactionManager 구현체를 매핑하여 사용하게됨

트랜잭션 매니저를 특정해서 사용하고 싶다면 TransactionManagementConfigurer 를 JavaConfig에서 구현하여 리턴한후 사용해야한다.

아니면 트랜잭션 매니저 객체를 생성할때 @Primary 애노테이션을 지정하여 사용한다.

Spring DB 설정

@Configuration
@EnableTransactionManagement
public class DBConfig implements TransactionManagementConfigurer{
  private String drivuerClassName = "com.mysql.jdbc.Driver";
  private String url = "jdbc:mysql://localhost:3306/connectdb?useSSL=false";
  private String username = "connectuser";
  private String userPassword = "connect123!@#";
  
  @Bean
  public DataSource dataSource() {
    BasicDataSource ds = new BasicDataSource();
    ds.setDriverClassName(drivuerClassName);
    ds.setUrl(url);
    ds.setUsername(username);
    ds.setPassword(userPassword);
    return ds;
  }
  
  // 트랜 잭션 매니저 지정
  @Override
  public PlatformTransactionManager annotationDrivenTransactionManager() {
    return transactionManager();
  }
  
  //플랫폼 트랜잭션 매니저 지정
  @Bean
  public PlatformTransactionManager transactionManager() {
    return new DataSourceTransactionManager(dataSource());
  }
}

annotationDrivenTransactionManager() 로 사용할 트랜잭션 매니저를 지정한다.

트랜잭션 매니저를 물론 빈으로 등록되어 있어야 함으로 빈으로 생성한다.

설정 분리

DispatcherServlet이 2개 생성되면 2개의 servlet에는 2개의 독립적인 context가 생성되어 빈을 공용으로 사용할 수 없다.

이러한 문제점은 ContextLoaderListener로 해결할 수 있다.

ContextLoaderListener가 생성하는 Context가 root 컨텍스트고, 2개의 servlet context가 자식 context로써 사용하게 하는것 이다.

filter example

	<filter>
		<filter-name>encodingFilter</filter-name>
		<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
		<init-param>
			<param-name>encoding</param-name>
			<param-value>UTF-8</param-value>
		</init-param>
	</filter>
	<filter-mapping>
		<filter-name>encodingFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>

전체 xml example

<?xml version="1.0" encoding="UTF-8"?>

<web-app>
	<display-name>Spring JavaConfig Sample</display-name>
	<context-param>
		<param-name>contextClass</param-name>
		<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext
		</param-value>
	</context-param>
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>
			config.ComponentConfig
		</param-value>
	</context-param>
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener
		</listener-class>
	</listener>
	
	<servlet>
		<servlet-name>dispatcher</servlet-name>
		<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>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>
				config.MvcConfig
			</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
	
	<servlet-mapping>
		<servlet-name>dispatcher</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>
	
	<filter>
		<filter-name>encodingFilter</filter-name>
		<filter-class>org.springframework.web.filter.CharacterEncodingFilter
		</filter-class>
		<init-param>
			<param-name>encoding</param-name>
			<param-value>UTF-8</param-value>
		</init-param>
	</filter>
	
	<filter-mapping>
		<filter-name>encodingFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>
</web-app>

0개의 댓글