[SPRING] 다중 Dispatcher가있는 Spring Java 구성
SPRING다중 Dispatcher가있는 Spring Java 구성
나는 지금 약간의 경험을 봄과 또한 사용중인 일부 자바 구성 웹 응용 프로그램을 가지고있다. 그러나 이들은 일반적으로 조용한 간단한 설정에 기반합니다.
현재 프로젝트에서 다른 구성을 가진 별도의 디스패처 컨텍스트가 필요합니다. Dispatcher 구성과 독립적 인 전용 ContextLoaderListener가 있으므로 XML 기반 구성에는 문제가 없습니다. 하지만 자바 설정으로 내가 지금하고있는 일이 지금까지 괜찮은 것인지 잘 모르겠다;)
다음은 일반적인 DispatcherConfig입니다.
public class MyWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return new class[]{MyAppConfig.class};
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{MyDispatcherConfig.class};
}
@Override
protected String[] getServletMappings() {
return new String[]{"/mymapping/*"};
}
@Override
protected String getServletName() {
return "myservlet";
}
}
말했듯이 다른 매핑 (및 확인자 확인)을 사용하여 두 번째 (세 번째, ...) 디스패처가 필요합니다. 그래서 config를 복사하고 getServletName ()을 추가했습니다 (그렇지 않으면 둘 다 오류를 발생시키는 '디스패처'로 이름 지정됩니다). 두 번째 구성은 다음과 같이 보입니다.
public class AnotherWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return new class[]{MyAppConfig.class};
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{AnotherDispatcherConfig.class};
}
@Override
protected String[] getServletMappings() {
return new String[]{"/another_mapping/*"};
}
@Override
protected String getServletName() {
return "anotherservlet";
}
}
이런 식으로 사용하면 ContextLoaderListener에 문제가있는 응용 프로그램이 시작됩니다.
java.lang.IllegalStateException: Cannot initialize context because there is already a root application context present - check whether you have multiple ContextLoader* definitions in your web.xml!
at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:277)
...
그래서 두 번째 MyAppConfig.class 반환을 제거했습니다. AbstractAnnotationConfigDispatcherServletInitializer 및 그것은 잘 작동합니다. 그러나, 그것은 옳은 길로 느껴지지 않습니다;)
내 이해를 위해 : 하나의 AbstractAnnotationConfigDispatcherServletInitializer 내에서 모든 DispatcherConfig를 처리해야합니까? 그렇지 않으면 분리해야합니까? 한 클래스에서 그들을 구성하려고했지만 내 구성이 완전히 섞여서 (그래서 원하는 방식이 아닌 것 같습니다).
그러한 사례를 어떻게 구현합니까? AbstractAnnotationConfigDispatcherServletInitializer 외부의 java config에서 ContextLoaderListener를 설정할 수 있습니까? 또는 루트 구성 만있는 DefaultServlet을 만들어야합니까? 해당 구성 WebApplicationInitializer의 기본 인터페이스를 구현하는 것은 어떻습니까?
해결법
-
==============================
1.Mahesh C.는 올바른 길을 보여 주었지만 구현이 너무 제한적입니다. 그는 한 순간에 맞습니다. 여러 Dispatcher 서블릿에 대해 AbstractAnnotationConfigDispatcherServletInitializer를 직접 사용할 수 없습니다. 그러나 구현은 다음을 수행해야합니다.
Mahesh C.는 올바른 길을 보여 주었지만 구현이 너무 제한적입니다. 그는 한 순간에 맞습니다. 여러 Dispatcher 서블릿에 대해 AbstractAnnotationConfigDispatcherServletInitializer를 직접 사용할 수 없습니다. 그러나 구현은 다음을 수행해야합니다.
다음은보다 완벽한 구현입니다.
@Override public void onStartup(ServletContext servletContext) throws ServletException { // root context AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext(); rootContext.register(RootConfig.class); // configuration class for root context rootContext.scan("...service", "...dao"); // scan only some packages servletContext.addListener(new ContextLoaderListener(rootContext)); // dispatcher servlet 1 AnnotationConfigWebApplicationContext webContext1 = new AnnotationConfigWebApplicationContext(); webContext1.setParent(rootContext); webContext1.register(WebConfig1.class); // configuration class for servlet 1 webContext1.scan("...web1"); // scan some other packages ServletRegistration.Dynamic dispatcher1 = servletContext.addServlet("dispatcher1", new DispatcherServlet(webContext1)); dispatcher1.setLoadOnStartup(1); dispatcher1.addMapping("/subcontext1"); // dispatcher servlet 2 ... }
그렇게하면 bean이 XML 컨텍스트에서와 마 y 가지로 컨텍스트에서 끝나는지를 완전히 제어 할 수 있습니다.
-
==============================
2.스프링 - AbstractAnnotationConfigDispatcherServletInitializer에서 제공하는 추상 구현을 사용하는 대신 일반 WebApplicationInitializer 인터페이스를 사용하면 해결할 수 있다고 생각합니다.
스프링 - AbstractAnnotationConfigDispatcherServletInitializer에서 제공하는 추상 구현을 사용하는 대신 일반 WebApplicationInitializer 인터페이스를 사용하면 해결할 수 있다고 생각합니다.
그렇게하면 두 개의 별도 초기화 프로그램을 만들 수 있으므로 startUp () 메서드에서 서로 다른 ServletContext를 얻고 각 AppConfig 및 dispatcher 서블릿을 각각 등록해야합니다.
그러한 구현 클래스 중 하나는 다음과 같이 보일 수 있습니다.
public class FirstAppInitializer implements WebApplicationInitializer { public void onStartup(ServletContext container) throws ServletException { AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext(); ctx.register(AppConfig.class); ctx.setServletContext(container); ServletRegistration.Dynamic servlet = container.addServlet( "dispatcher", new DispatcherServlet(ctx)); servlet.setLoadOnStartup(1); servlet.addMapping("/control"); } }
-
==============================
3.나는 똑같은 문제에 직면했다. 사실 여러 디스패처 서블릿, 필터 및 리스너가있는 복잡한 구성이 있습니다.
나는 똑같은 문제에 직면했다. 사실 여러 디스패처 서블릿, 필터 및 리스너가있는 복잡한 구성이 있습니다.
나는 아래처럼 web.xml을 가지고 있었다.
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1"> <listener> <listener-class>MyAppContextLoaderListener</listener-class> </listener> <context-param> <param-name>spring.profiles.active</param-name> <param-value>${config.environment}</param-value> </context-param> <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>MyAppConfig</param-value> </context-param> <servlet> <servlet-name>restEntryPoint</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>MyRestConfig</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>restEntryPoint</servlet-name> <url-pattern>/api/*</url-pattern> </servlet-mapping> <servlet> <servlet-name>webSocketEntryPoint</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>MyWebSocketWebConfig</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>webSocketEntryPoint</servlet-name> <url-pattern>/ws/*</url-pattern> </servlet-mapping> <servlet> <servlet-name>webEntryPoint</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>MyWebConfig</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>webEntryPoint</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <filter> <filter-name>exceptionHandlerFilter</filter-name> <filter-class>com.san.common.filter.ExceptionHandlerFilter</filter-class> </filter> <filter-mapping> <filter-name>exceptionHandlerFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <filter> <filter-name>validationFilter</filter-name> <filter-class>MyValidationFilter</filter-class> </filter> <filter-mapping> <filter-name>validationFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <filter> <filter-name>lastFilter</filter-name> <filter-class>MyLastFilter</filter-class> </filter> <filter-mapping> <filter-name>lastFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> </web-app>
위의 web.xml을 java 파일로 대체했습니다.
import java.util.EnumSet; import javax.servlet.DispatcherType; import javax.servlet.FilterRegistration; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.ServletRegistration; import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; import org.springframework.web.filter.DelegatingFilterProxy; import org.springframework.web.servlet.DispatcherServlet; import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer; public class AppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { @Override public void onStartup(ServletContext servletContext) throws ServletException { servletContext.addListener(MyAppContextLoaderListener.class); servletContext.setInitParameter("spring.profiles.active", "dev"); servletContext.setInitParameter("contextClass", "org.springframework.web.context.support.AnnotationConfigWebApplicationContext"); servletContext.setInitParameter("contextConfigLocation", "MyAppConfig"); // dispatcher servlet for restEntryPoint AnnotationConfigWebApplicationContext restContext = new AnnotationConfigWebApplicationContext(); restContext.register(MyRestConfig.class); ServletRegistration.Dynamic restEntryPoint = servletContext.addServlet("restEntryPoint", new DispatcherServlet(restContext)); restEntryPoint.setLoadOnStartup(1); restEntryPoint.addMapping("/api/*"); // dispatcher servlet for webSocketEntryPoint AnnotationConfigWebApplicationContext webSocketContext = new AnnotationConfigWebApplicationContext(); webSocketContext.register(MyWebSocketWebConfig.class); ServletRegistration.Dynamic webSocketEntryPoint = servletContext.addServlet("webSocketEntryPoint", new DispatcherServlet(webSocketContext)); webSocketEntryPoint.setLoadOnStartup(1); webSocketEntryPoint.addMapping("/ws/*"); // dispatcher servlet for webEntryPoint AnnotationConfigWebApplicationContext webContext = new AnnotationConfigWebApplicationContext(); webContext.register(MyWebConfig.class); ServletRegistration.Dynamic webEntryPoint = servletContext.addServlet("webEntryPoint", new DispatcherServlet(webContext)); webEntryPoint.setLoadOnStartup(1); webEntryPoint.addMapping("/"); FilterRegistration.Dynamic validationFilter = servletContext.addFilter("validationFilter", new MyValidationFilter()); validationFilter.addMappingForUrlPatterns(null, false, "/*"); FilterRegistration.Dynamic lastFilter = servletContext.addFilter("lastFilter", new MyLastFilter()); lastFilter.addMappingForUrlPatterns(null, false, "/*"); } @Override protected Class<?>[] getRootConfigClasses() { // return new Class<?>[] { AppConfig.class }; return null; } @Override protected Class<?>[] getServletConfigClasses() { // TODO Auto-generated method stub return null; } @Override protected String[] getServletMappings() { // TODO Auto-generated method stub return null; } }
from https://stackoverflow.com/questions/28877982/spring-java-config-with-multiple-dispatchers by cc-by-sa and MIT license
'SPRING' 카테고리의 다른 글
[SPRING] Spring 3에서 applicationContext를 주입하는 모범 사례 (0) | 2019.02.03 |
---|---|
[SPRING] 주석이있는 PRIVATE 메소드를위한 AspectJ pointcut (0) | 2019.02.03 |
[SPRING] Spring Security 잘못된 remember-me 토큰 (시리즈 / 토큰) 불일치. 이전의 쿠키 도용 공격을 암시합니다. (0) | 2019.02.03 |
[SPRING] 엔티티가 지속되지 않음 - Spring + Hibernate + JPA (0) | 2019.02.03 |
[SPRING] Spring Hibernate 사용시 문제들 (0) | 2019.02.03 |