[Spring framework] 공부를 해보자 1탄
Spring framework
Spring내에서 가장 기초적이고 가장 중요한 두개의 패키지는 org.springframework.beans
와 org.springframework.context
패키지이다. 이 패키지내 코드는 Spring의 Inversion of Control(대안으로 Dependency Injection으로 불리는)기능의 기초를 제공한다. BeanFactory는 잠재적으로 어떤 종류의 저장 기능을 사용하여 어떤 성질의 bean을 관리하는 향상된 설정 기법을 제공한다.
ApplicationContext
는 BeanFactory
(또는 하위클래스)의 가장 상위에 위치하고, 향상된 점 중에서 Spring AOP기능의 좀더 쉬운 통합, 메시지 자원 핸들링(국제화내에서 사용하기 위한), 이벤트 위임, ApplicationContext와 옵션적으로 부모 컨텍스트를 생성하기 위한 선언적인 기법, WebApplicationContext
와 같은 애플리케이션 레이어 특정 컨텍스트를 사용하는 것과 같은 다른 기능을 추가한다.
ApplicationContext
를 사용하는 것이 좋다. BeanFactory의 모든 기능을 포함하고 있다. (몇 가지 상황을 제외하고서는 좋은 선택이다.)
기본 BeanFactory를 사용할 경우 트랜잭션, AOP 같은 많은 기능을 개발자가 만들어 줘야 한다.(힘들껄..?)
@RequestMapping관련 글은 링크를 참조하면 된다.
DispatcherServlet
스프링 웹 MVC 프레임워크는 요청 중심 즉, 중앙에서 모든 요청을 받은 뒤, 각각 역할에 맞는 기능을 분산 시키게 된다.
중앙 서블릿 중심으로 설계되어 있어 웹 어플리케이션을 개발하는 데 기능들을 제공한다. 또한, DispatcherServlet
은 스프링 IoC 컨테이너와 완전히 통합되어 있어서 스프링이 가진 모든 다른 기능을 사용할 수 있다. (즉, IoC 컨테이너가 디스패처의 기능을 일임 받을 수 있다는 것으로 볼 수 있지 않을까 … ?)
DispatcherServlet은 실제로도 Servlet이며, HttpServlet 기반 클래스를 상속 받는다. web.xml 파일에 선언 되어 있다.(없으면 안...)
<web-app>
<servlet>
<servlet-name>example</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>example</servlet-name>
<url-pattern>/example/*</url-pattern>
</servlet-mapping>
</web-app>
WebApplicationContext는 ApplicationContext의 확장이며, 웹 어플리케이션이 필요로 하는 기능을 추가한 것이다.
xx-servlet.xml
에서 설정 하는 것들이 몇 가지가 기본적으로 존재한다.
<context:component-scan base-package="com.seungdols.web" />
위는 사용할 빈들을 자동적으로 스캔하여 빈으로 등록을 해준다.
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/WEB-INF/views/jsp/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
위는 view에 대한 설정을 하는 것인데, prefix는 jsp 파일들의 경로를 지정하는 것을 뜻하고, suffix는 파일들의 확장자를 .jsp로 지정한다.
특히, InternalResourceViewResolver의 경우에는 prefix, suffix 이들을 이용해 나중에 컨트롤러에서 리턴받은 view name을 prefix + name + suffix를 붙여 view를 찾게 된다.
<mvc:resources mapping="/resources/**" location="/resources/" />
위 설정은 스크립트, 이미지, 파일들의 경로를 결정하는 것이다.
<mvc:annotation-driven />
- DefaultAnnotationHandlerMapping
- @RequestMapping을 이용한 핸들러 매핑 전략 등록, 가장 우선된다.
- AnnotationMethodHandlerAdapter
- 디폴트 핸들러 어댑터
- ConfigurableWebBidingIntializer
- Message Converter
<spring:eval>
을 위한 컨버젼 서비스 노출용 인터셉터- Validator
- Conversion-service
Logging
log를 사용하여 문제점을 찾는데 쉽게 활용 할 수 있고, 중요한 정보로 활용 할 수 있기에 로그는 중요하다.
그 중에서 다양한 Logging framework가 존재하는데, 이를 입맛대로 설정 할 수 있게끔 사용하고 싶다면, SLF4J를 사용하면 된다. 이는 로깅 퍼사드로 로깅에 대한 추상화만 제공하며, 구현체를 어떤 로깅 프레임워크를 사용해도 무방합니다.
사실 이 중에서 가장 많이 사용했던 것은 log4j지만, log4j의 단점들을 개선 시킨 Logback이 그 자리를 교체해가고 있다.
즉, SLF4J는 추상화 (Interface만 제공) Logback은 해당 SLF4J를 그대로 구현한 것이라 이해 하면 됩니다.
Maven에서 사용하기 위해서는 pom.xml에 다음을 추가를 하면 된다.
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>${org.slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${org.slf4j.version}</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.1.7</version>
</dependency>
또한, spring-context가 JCL을 사용하는데, 그냥 두면, commons-logging이 의존성이 자동으로 추가가 되어 있어 문제가 되니 제거를 해야 한다.
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
그리고 사용 하기 위해서는 src/main/resources/
하위에 logback.xml 파일이 필요합니다.
단, logback은 파일의 우선순위가 존재합니다.
- logback.groovy
- logback-test.xml
- logback.xml
- Basic config
위와 같은 순서로 파일을 찾아 해당 파일의 내용을 설정합니다.
간단 설정
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<layout class="ch.qos.logback.classic.PatternLayout">
<Pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</Pattern>
</layout>
</appender>
<logger name="com.seungdols.web" level="DEBUG"/>
<root level="debug">
<appender-ref ref="STDOUT" />
</root>
</configuration>
사용
static final Logger logger = LoggerFactory.getLogger(BoardController.class);
static final
로 선언해야 하며, transient
를 쓰면 NullPointerException(비싼 에러)을 발생 시킨다.
@RequestMapping(value = {"/", "/hello"}, method = RequestMethod.GET)
public String printWelcome(ModelMap model) {
logger.debug("Home Page");
model.addAttribute("message", "Spring 3 MVC Hello World");
return "hello";
}
결과
18:02:05.574 [http-apr-8080-exec-3] DEBUG c.s.web.controller.BoardController - Home Page
참고 LogBack.xml 설정 변경사항
<layout class="ch.qos.logback.classic.PatternLayout">
위에서 ch.qos.logback.classic.PatternLayout
는 Deprecated 되었다.
그래서 변경해야 한다.
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">