programing

서블릿 필터에서 스프링 빈을 얻으려면 어떻게 해야 합니까?

codeshow 2023. 9. 4. 20:48
반응형

서블릿 필터에서 스프링 빈을 얻으려면 어떻게 해야 합니까?

정의했습니다.javax.servlet.Filter그리고 봄 주석이 달린 자바 수업이 있습니다.

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

@Configuration
public class SocialConfig {

    // ...

    @Bean
    public UsersConnectionRepository usersConnectionRepository() {
        // ...
    }
}

나는 콩을 사고 싶습니다.UsersConnectionRepository내 안에서Filter그래서 저는 다음을 시도했습니다.

public void init(FilterConfig filterConfig) throws ServletException {
    UsersConnectionRepository bean = (UsersConnectionRepository) filterConfig.getServletContext().getAttribute("#{connectionFactoryLocator}");
}

하지만 그것은 항상 돌아옵니다.null어떻게 하면 봄 콩을 얻을 수 있습니까?Filter?

세 가지 방법이 있습니다.

  1. 사용하다WebApplicationContextUtils:

    public void init(FilterConfig cfg) { 
        ApplicationContext ctx = WebApplicationContextUtils
          .getRequiredWebApplicationContext(cfg.getServletContext());
        this.bean = ctx.getBean(YourBeanType.class);
    }
    
  2. - 필터를 매핑하고 필터를 빈으로 선언합니다.그런 다음 위임 프록시는 다음을 구현하는 모든 빈을 호출합니다.Filter인터페이스

  3. 사용하다@Configurable필터에 있습니다.하지만 다른 두 가지 옵션 중 하나를 선호합니다. (이 옵션은 애스펙트j 직조를 사용합니다.)

시도:

UsersConnectionRepository bean = 
  (UsersConnectionRepository)WebApplicationContextUtils.
    getRequiredWebApplicationContext(filterConfig.getServletContext()).
    getBean("usersConnectionRepository");

어디에usersConnectionRepository응용 프로그램 컨텍스트에서 빈의 이름/ID입니다.또는 더 나은 것:

UsersConnectionRepository bean = WebApplicationContextUtils.
  getRequiredWebApplicationContext(filterConfig.getServletContext()).
  getBean(UsersConnectionRepository.class);

또한 GenericFilterBean 및 해당 하위 클래스도 살펴봅니다.

봄에는 이것만을 위한 효용이 있습니다.

필터 코드에서 init 메서드를 다음과 같이 재정의합니다.

public void init(FilterConfig cfg) { 
    super.init(cfg);
    SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
}

그런 다음 다른 콩을 주입하는 것과 같은 방식으로 @당신의 콩을 필터에 주입합니다.

@Inject
private UsersConnectionRepository repository;

컨텍스트 간에 콩에 액세스할 수 있는 방법에 대한 명확한 이해

봄에는 두 가지 유형의 상황이 있습니다.
루트 컨텍스트(ContextLoaderListener에서 컨텍스트가 로드됨)
서블릿 컨텍스트(Dispatcher Servlet에 의해 로드된 컨텍스트)

rootContext에 정의된 콩이 servletContext에 표시됩니까? - 네

루트 컨텍스트에서 정의된 콩은 기본적으로 모든 서블릿 컨텍스트에서 항상 표시됩니다.예를 들어, 루트 컨텍스트에 정의된 source been은 아래와 같이 servlet 컨텍스트에서 액세스할 수 있습니다.

@Configuration
public class RootConfiguration
{
    @Bean
    public DataSource dataSource()
    {
       ...
    }
}

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "com.pvn.mvctiles")
public class ServletConfiguration implements WebMvcConfigurer
{
    @Autowired
    private DataSource dataSource;

    ...
}

servletContext에 정의된 콩은 rootContext에 표시됩니다. 예*

(예에서 *를 선택하는 이유)
컨텍스트 순서의 초기화는 rootContext 먼저이고 servletContext 다음입니다.rootContext를 초기화하는 동안, 즉 루트 컨텍스트 구성 클래스/xml에서 servletContext에 정의된 빈을 가져오려고 하면 NULL이 표시됩니다. (servletContext가 아직 초기화되지 않았기 때문에 루트 컨텍스트 초기화 중에 빈이 표시되거나 등록되지 않았다고 말할 수 있습니다.)
그러나 servletContext 초기화 후 servletContext에 정의된 콩을 얻을 수 있습니다(애플리케이션 컨텍스트를 통해 콩을 얻을 수 있습니다).

당신은 그것을 인쇄하고 확인할 수 있습니다.

applicationContext.getBeanDefinitionNames();


필터 또는 다른 서블릿 컨텍스트에서 서블릿 컨텍스트의 빈에 액세스하려면 다음을 추가합니다."org.springframework.web.servlet" class 입니다.

@Configuration
@ComponentScan(basePackages = "org.springframework.web.servlet" )
public class RootConfiguration

한 후 콩을 수 .

springSecurityConfig,tilesConfigurer,themeSource,themeResolver,messageSource,localeResolver,requestMappingHandlerMapping,mvcPathMatcher,mvcUrlPathHelper,mvcContentNegotiationManager,viewControllerHandlerMapping,beanNameHandlerMapping,resourceHandlerMapping,mvcResourceUrlProvider,defaultServletHandlerMapping,requestMappingHandlerAdapter,mvcConversionService,mvcValidator,mvcUriComponentsContributor,httpRequestHandlerAdapter,simpleControllerHandlerAdapter,handlerExceptionResolver,mvcViewResolver,mvcHandlerMappingIntrospector

rootContext에서 사용자 정의 콩을 가져오려면 아래와 같이 rootContext 구성 요소에 기본 패키지 값을 추가합니다.

@Configuration
@ComponentScan(basePackages = { "com.your.configuration.package", "org.springframework.web.servlet" })
public class RootConfiguration

위의 지정된 구성은 주입된 종속성을 rootContext에서 사용할 수 있고 서블릿 필터에서 액세스할 수 있도록 하려면 유용합니다.를 들어 응답을 해야 합니다.HttpMessageConverter그러나 servletContext로 구성된 경우 구성된 변환기에 액세스하여 동일한 응답을 보낼 수 있습니다.

필터에서 작동하지 아래 자동 배선은 서블릿 필터에서 하지 않습니다.

@Autowired
private ApplicationContext appContext;

스프링 컨테이너가 초기화되기 전에 필터가 초기화되므로 서블릿 필터에서 ApplicationContext 자동 배선이 작동하지 않습니다.(필터 순서와 ProxyFilter 위임 순서에 따라 다름)

필터에서 applicationContext를 가져오려면

public class YourFilter implements Filter
{
    private ApplicationContext appContext;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException
    {
        Filter.super.init(filterConfig);
        appContext = WebApplicationContextUtils.getRequiredWebApplicationContext(filterConfig.getServletContext());
    }
}

그것이 문맥 사이에서 콩이 어떻게 접근될 수 있는지에 대한 명확한 아이디어를 제공하기를 바랍니다.

이 클래스 아래로 확장됩니다.

abstract public class SpringServletFilter implements Filter{
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        //must provide autowiring support to inject SpringBean
        SpringBeanAutowiringSupport.processInjectionBasedOnServletContext(this, filterConfig.getServletContext());      
    }

    @Override
    public void destroy() { }

    abstract public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException;
}

스프링 보안을 사용하고 OncePerRequestFilter를 확장하는 경우 한 가지 솔루션 더 제공

@Component
public class CustomAuthorizationFilter extends OncePerRequestFilter{

    @Autowired
    ResourceConfig resourceConfig;

    public CustomAuthorizationFilter() {
            SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
    }
...your code
... //resourceConfig will not be null

언급URL : https://stackoverflow.com/questions/7882042/how-can-i-get-a-spring-bean-in-a-servlet-filter

반응형