<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping" p:order="3">
<!--<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>-->
<bean name="/insertEmployee.do" class="com.easycompany.controller.InsertEmployeeController">
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
<bean name="/insertEmployee.do" class="com.easycompany.controller.InsertEmployeeController">
ControllerClassNameHandlerMapping
<bean class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping"/>
<bean class="com.easycompany.controller.hierarchy.EmployeeListController"/>
<bean class="com.easycompany.controller.hierarchy.InsertEmployeeController"/>
<bean class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping">
<property name="pathPrefix" value="/easycompany"/>
<property name="caseSensitive" value="true"/>
<property name="basePackage" value="com.easycompany.controller"/>
<bean class="com.easycompany.controller.hierarchy.EmployeeListController"/>
<bean class="com.easycompany.controller.hierarchy.InsertEmployeeController"/>
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<prop key="/employeeList.do">employeeListController</prop>
<prop key="/insertEmployee.do">insertEmployeeController</prop>
<prop key="/updateEmployee.do">updateEmployeeController</prop>
<prop key="/loginProcess.do">loginController</prop>
<prop key="/**/login.do">staticPageController</prop>
<prop key="/static/*.html">staticPageController</prop>
<bean id="loginController" class="com.easycompany.controller.hierarchy.LoginController"/>
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="interceptors">
<ref local="authenticInterceptor"/>
<prop key="/employeeList.do">employeeListController</prop>
<prop key="/insertEmployee.do">insertEmployeeController</prop>
<prop key="/updateEmployee.do">updateEmployeeController</prop>
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<prop key="/**/login.do">staticPageController</prop>
<prop key="/static/*.html">staticPageController</prop>
<bean id="loginController" class="com.easycompany.controller.hierarchy.LoginController"/>
<bean id="authenticInterceptor" class="com.easycompany.interceptor.AuthenticInterceptor" />
DefaultAnnotationHandlerMapping
<context:component-scan base-package="org.mycode.controller" />
package org.mycode.controller;
public class HelloController {
@RequestMapping(value="/hello.do")
......
}}
/hello.do로 URL 요청이 들어 오면 HelloController의 메소드 hellomethod가 실행된다.
SimpleUrlAnnotationHandlerMapping
DefaultAnnotationHandlerMapping에 interceptor를 등록하면, 모든 @Controller에 interceptor가 적용되는 문제점이 있다.
SimpleUrlAnnotationHandlerMapping은 @Controller 사용시에 url 단위로 Interceptor를 적용하기 위해 개발됬다.
비슷한 고민과 비슷한 해결 방법을 제시한 분이 있다. Scott Murphy의 블로그를 참고하라.
기능상에 큰 차이가 없는것 같아 일단 개발한 소스를 소개한다.
url 단위(Controller의 메소드 단위)로 Interceptor를 적용할 수 있는 대안이 Spring Source에서 나온다면 SimpleUrlAnnotationHandlerMapping는 deprecated 되어야 한다.
SimpleUrlAnnotationHandlerMapping은 아래와 같은 3가지 사항이 고려됬다.- HandlerMapping:Interceptors 관계의 스프링의 구조를 깨뜨리지 말자. (ex. Controller:Interceptor (X))
- 쉬운 사용을 위해 기존의 HandlerMapping과 비슷한 방식의 사용법을 선택하자. (ex.SimpleUrlHandlerMapping)
- 최소한의 커스터마이징을 하자. → 짧은 시간… 또한 추후 deprecated시에 시스템에 영향을 최소화 하기 위해.
웹 어플리케이션이 초기 구동될때, DefaultAnnotationHandlerMapping은 2가지 주요한 작업을 한다. (다른 HandlerMapping도 유사한 작업을 한다.)
- @RequestMapping의 url 정보를 읽어 들여 해당 Controller와 url간의 매핑 작업.
- 설정된 Interceptor들에 대한 정보를 읽어 들임.
1번 작업은 DefaultAnnotationHandlerMapping의 상위 클래스인 AbstractDetectingUrlHandlerMapping에서 이루어 지는데,
맵핑을 위한 url리스트를 가져오는 determineUrlsForHandler 메소드는 하위 클래스에서 구현하도록 abstract 선언 되어 있다.public abstract class AbstractDetectingUrlHandlerMapping extends AbstractUrlHandlerMapping {
...
protected void detectHandlers() throws BeansException {
if (logger.isDebugEnabled()) {
logger.debug("Looking for URL mappings in application context: " + getApplicationContext());
}
String[] beanNames = (this.detectHandlersInAncestorContexts ?
BeanFactoryUtils.beanNamesForTypeIncludingAncestors(getApplicationContext(), Object.class) :
getApplicationContext().getBeanNamesForType(Object.class));
// Take any bean name that we can determine URLs for.
for (int i = 0; i < beanNames.length; i++) {
String beanName = beanNames[i];
String[] urls = determineUrlsForHandler(beanName);
if (!ObjectUtils.isEmpty(urls)) {
// URL paths found: Let's consider it a handler.
registerHandler(urls, beanName);
}
else {
if (logger.isDebugEnabled()) {
logger.debug("Rejected bean name '" + beanNames[i] + "': no URL paths identified");
}
}
}
}
protected abstract String[] determineUrlsForHandler(String beanName);
}
DefaultAnnotationHandlerMapping의 determineUrlsForHandler 메소드는 @RequestMapping의 url 리스트를 전부 가져오기 때문에,
빈 설정 파일에 정의한 url 리스트만 가져오도록 SimpleUrlAnnotationHandlerMapping에서 determineUrlsForHandler 메소드를 구현 한다.package egovframework.rte.ptl.mvc.handler;
...
public class SimpleUrlAnnotationHandlerMapping extends DefaultAnnotationHandlerMapping {
//url리스트, 중복값을 허용하지 않음으로 Set 객체에 담는다.
private Set<String> urls;
public void setUrls(Set<String> urls) {
this.urls = urls;
}
/**
* @RequestMapping로 선언된 url중에 프로퍼티 urls에 정의된 url만 remapping해 return
* url mapping시에는 PathMatcher를 사용하는데, 별도로 등록한 PathMatcher가 없다면 AntPathMatcher를 사용한다.
* @param urlsArray - @RequestMapping로 선언된 url list
* @return urlsArray중에 설정된 url을 필터링해서 return.
*/
private String[] remappingUrls(String[] urlsArray){
if(urlsArray==null){
return null;
}
ArrayList<String> remappedUrls = new ArrayList<String>();
for(Iterator<String> it = this.urls.iterator(); it.hasNext();){
String urlPattern = (String) it.next();
for(int i=0;i<urlsArray.length;i++){
if(getPathMatcher().matchStart(urlPattern, urlsArray[i])){
remappedUrls.add(urlsArray[i]);
}
}
}
return (String[]) remappedUrls.toArray(new String[remappedUrls.size()]);
}
/**
* @RequestMapping로 선언된 url을 필터링하기 위해
* org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping의
* 메소드 protected String[] determineUrlsForHandler(String beanName)를 override.
*
* @param beanName - the name of the candidate bean
* @return 빈에 해당하는 URL list
*/
protected String[] determineUrlsForHandler(String beanName) {
return remappingUrls(super.determineUrlsForHandler(beanName));
}
}
인터셉터를 적용할 url들을 프로퍼티 urls에 선언하면 되며, Ant-style의 패턴 매칭이 지원된다.
SimpleUrlAnnotationHandlerMapping은 선언된 url만을 Controller와 매핑처리한다.
따라서, 아래와 같이 선언된 DefaultAnnotationHandlerMapping와 같이 선언되어야 하며, 우선순위는 SimpleUrlAnnotationHandlerMapping이 높아야 한다.<bean id="selectAnnotaionMapper" class="egovframework.rte.ptl.mvc.handler.SimpleUrlAnnotationHandlerMapping" p:order="1">
<property name="interceptors">
<list>
<ref local="authenticInterceptor"/>
</list>
</property>
<property name="urls">
<set>
<value>/*Employee.do</value>
<value>/employeeList.do</value>
</set>
</property>
</bean>
<bean id="annotationMapper" class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" p:order="2"/>
<bean id="authenticInterceptor" class="com.easycompany.interceptor.AuthenticInterceptor" />
'IT노트 > eGov&Spring F/W' 카테고리의 다른 글
Interceptor 와 Filter 의 차이점 (0) | 2015.01.30 |
---|---|
The Spring Tool Suite™ (STS) (0) | 2015.01.30 |
스프링의 스케쥴러 (0) | 2015.01.30 |
공통컴포넌트 all-in-one 2.2.0 (0) | 2015.01.30 |
전자정부 프레임워크의 공통컴포넌트 (0) | 2015.01.30 |