2012-06-12 8 views
3

я следующий вопрос:@Autowired в DelegatingFilterProxy

Я занимаюсь разработкой веб-приложений с использованием Spring MVC 3. В моей конфигурации web.xml у меня есть два контекста (корень-context.xml -Global Контекст - загружается ContextLoadListener и servlet-context.xml - для DispatcherServlet).

Однако в моей конфигурации мне нужен фильтр, который я, реализованный с использованием DelegatingFilterProxy, и настроены следующим образом:

<filter> 
<filter-name>cheapigFilter</filter-name> 
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>  
</filter> 

Этот фильтр указывает на класс под названием SegurancaFilter, который простирается от OncePerRequestFilter. Но для того, чтобы этот фильтр выполнял его задачи, ему необходимо получить доступ к beans @Autowired в файле servlet-context.xml, и сам фильтр должен быть управляемым Spring компонентом, поэтому я должен пометить его с помощью @Component (который не будет работать , потому что я не устанавливаю ни корневого контекста, ни устанавливаю фильтр как XML-компонент).

Если я помещаю

<mvc:annotation-driven /> <context:component-scan base-package="br.com.cheapig" /> 

В моем корневом контексте, все мои бобы будут подключены два раза, в результате чего приложения для вызова методов бобов дважды. Это потому, что у меня будет такая же конфигурация в root-context.xml и servlet-context.xml. Но если я стираю этот конфиг сервлет-context.xml и сохранить его в корневой context.xml следующее сообщение об ошибке появляется:

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [org.hibernate.SessionFactory] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)} 
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:924) 
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:793) 
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:707) 
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:478) 
    ... 51 more 

Чтобы предоставить дополнительную информацию, мой фильтр реализован следующим образом:

package br.com.cheapig.seguranca; 

import java.io.IOException; 
import java.util.Date; 
import java.util.Locale; 

import javax.servlet.FilterChain; 
import javax.servlet.ServletException; 
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 
import javax.servlet.http.HttpSession; 

import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.context.i18n.LocaleContextHolder; 
import org.springframework.stereotype.Component; 
import org.springframework.web.filter.OncePerRequestFilter; 
import org.springframework.web.servlet.LocaleResolver; 

import br.com.cheapig.controlador.HistoricoVisitasController; 
import br.com.cheapig.dominio.HistoricoVisitas; 
import br.com.cheapig.dominio.Usuario; 
import br.com.cheapig.exception.ControleAcessoException; 
import br.com.cheapig.util.CheapigUtil; 
import br.com.cheapig.util.ConstantesAmbiente; 
import br.com.cheapig.util.ConstantesGenericas; 
import br.com.cheapig.util.ConstantesHistoricoVisitas; 
import br.com.cheapig.util.ConstantesSessao; 
import br.com.cheapig.util.WorkflowUtil; 
import br.com.cheapig.workflow.Request; 

/** 
* Classe responsável por fazer a filtragem do controle de acesso aos recursos do site 
* 
* @author Guilherme Macedo 
* @since Apr 30, 2012 
*/ 
@Component(value = "cheapigFilter") 
public class SegurancaFilter extends OncePerRequestFilter { 

    @Autowired 
    private ConstantesAmbiente constantesAmbiente; 

    @Autowired 
    private LocaleResolver localeResolver; 

    @Autowired 
    private ControleAcesso controleAcesso; 

    @Autowired 
    private HistoricoVisitasController historicoVisitasController; 

    /** 
    * Cria um novo objeto SegurancaFilter 
    */ 
    public SegurancaFilter() { 
     super(); 
    } 

    /** 
    * @see org.springframework.web.filter.OncePerRequestFilter#doFilterInternal(javax.servlet.http.HttpServletRequest, 
    *  javax.servlet.http.HttpServletResponse, javax.servlet.FilterChain) 
    */ 
    @SuppressWarnings("unchecked") 
    @Override 
    protected void doFilterInternal(HttpServletRequest pRequest, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { 
     Locale locale = new Locale("pt", "br"); 
     this.localeResolver.setLocale(pRequest, response, locale); 
     LocaleContextHolder.setLocale(locale); 
     String path = pRequest.getRequestURI().substring(pRequest.getContextPath().length()); 
     String uri = pRequest.getRequestURI(); 
     HttpSession vSession = pRequest.getSession(); 
     String appId = (String) vSession.getAttribute("facebookAppId"); 
     if(appId == null || appId.isEmpty()){ 
      vSession.setAttribute("facebookAppId", this.constantesAmbiente.getFacebookAppId()); 
     } 

     if (path.startsWith("/resources") || path.startsWith("/css")) { 
      filterChain.doFilter(pRequest, response); // Goes to default servlet. 
     } else { 
      this.salvaVisita(pRequest); 

      if (uri.equals("/") || uri.equals("/cheapig/")) { 
       pRequest.getSession().setAttribute("loadCidadeList", true); 
      } else { 
       pRequest.getSession().setAttribute("loadCidadeList", false); 
      } 
      String vUrl = uri.substring("/cheapig".length()); 
      String vLogado = (String) vSession.getAttribute(ConstantesSessao.SESSION_LOGADO); 

      if (vLogado == null) { 
       vLogado = ConstantesGenericas.SIGLA_NAO; 
       vSession.setAttribute(ConstantesSessao.SESSION_LOGADO, ConstantesGenericas.SIGLA_NAO); 
      } 

      if (vLogado.equals(ConstantesGenericas.SIGLA_SIM) && vUrl.contains("login")) { 
       String vRedirectURL = "/cheapig/"; 
       response.sendRedirect(vRedirectURL); 
      }else{ 
       Usuario vUsuario = (Usuario) vSession.getAttribute(ConstantesSessao.SESSION_USUARIO); 

       try { 
        if (vLogado.equalsIgnoreCase(ConstantesGenericas.SIGLA_NAO)) { 
         this.controleAcesso.verificaPermissoesAnonimas(vUrl); 
        } else { 
         this.controleAcesso.verificaAcesso(vUsuario, vUrl); 
        }     
        pRequest.getRequestDispatcher(uri).forward(pRequest, response); 
       } catch (ControleAcessoException e) { 
        Request vRequest = new Request(); 
        vRequest.setRequestURI(uri); 
        vRequest.setRequestURL(vUrl); 
        vRequest.setRequestParameters(WorkflowUtil.montaParametrosURLParameterMap(pRequest.getParameterMap())); 
        vRequest.setRequestMethod(pRequest.getMethod()); 
        vSession.setAttribute("COMING_REQUEST", vRequest); 
        response.sendRedirect("/cheapig/loginTela"); 
        return; 
       } 
      } 


     } 
    } 

    public ControleAcesso getControleAcesso() { 
     return this.controleAcesso; 
    } 

    public LocaleResolver getLocaleResolver() { 
     return this.localeResolver; 
    } 

    @Override 
    protected void initFilterBean() throws ServletException { 

    } 

    /** 
    * Coleta as informações do usuário e persiste no histórico de visitas 
    * 
    * @param request 
    *   HttpServletRequest 
    */ 
    private void salvaVisita(HttpServletRequest request) { 
     String locale = request.getLocale().getLanguage(); 
     String browser = CheapigUtil.identificaBrowser(request.getHeader(ConstantesHistoricoVisitas.HTTP_BROWSER)); 
     String metodo = request.getMethod(); 
     String ip = request.getRemoteAddr(); 
     String pagAcessada = request.getRequestURI(); 
     String host = request.getRemoteHost(); 

     HistoricoVisitas historico = new HistoricoVisitas(); 
     historico.setLinguagemNavegador(locale); 
     historico.setBrowser(browser); 
     historico.setDataAcesso(new Date()); 
     historico.setHost(host); 
     historico.setIpVisitante(ip); 
     historico.setPagAcessada(pagAcessada); 
     historico.setRequestMethod(metodo); 

     this.historicoVisitasController.cadastrarHistoricoVisitas(historico); 
    } 

    public void setControleAcesso(ControleAcesso controleAcesso) { 
     this.controleAcesso = controleAcesso; 
    } 

    public void setLocaleResolver(LocaleResolver localeResolver) { 
     this.localeResolver = localeResolver; 
    } 
} 

Мой корень-context.xml:

<?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns="http://www.springframework.org/schema/beans" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" 
    xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" 
    xmlns:mvc="http://www.springframework.org/schema/mvc" 
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
     http://www.springframework.org/schema/beans/spring-beans-3.1.xsd 
     http://www.springframework.org/schema/context 
     http://www.springframework.org/schema/context/spring-context-3.1.xsd 
     http://www.springframework.org/schema/tx 
     http://www.springframework.org/schema/tx/spring-tx-3.1.xsd 
     http://www.springframework.org/schema/aop  
     http://www.springframework.org/schema/aop/spring-aop-3.1.xsd 
     http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd 
     "> 

    <mvc:annotation-driven /> 
    <context:component-scan base-package="br.com.cheapig" /> 

    <!-- <import resource="cheapig/servlet-context.xml" /> --> 

    <!-- Root Context: defines shared resources visible to all other web components --> 
    <!-- Configurações de Internacionalização --> 
    <bean id="messageSource" 
     class="org.springframework.context.support.ReloadableResourceBundleMessageSource"> 
     <property name="basename" value="classpath:messages" /> 
     <property name="defaultEncoding" value="latin1" /> 
    </bean> 

    <bean id="localeChangeInterceptor" 
     class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"> 
     <property name="paramName" value="lang" /> 
    </bean> 

    <bean id="localeResolver" 
     class="org.springframework.web.servlet.i18n.CookieLocaleResolver"> 
     <property name="defaultLocale" value="pt" /> 
    </bean> 

    <bean id="handlerMapping" 
     class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"> 
     <property name="interceptors"> 
      <ref bean="localeChangeInterceptor" /> 
     </property> 
    </bean> 

    <!-- Mapeamento da view "rssViewer" para o bean "rssViewer" --> 
    <bean class="org.springframework.web.servlet.view.BeanNameViewResolver" /> 
    <bean id="rssViewer" class="br.com.cheapig.servico.CustomRssViewer" /> 

    <bean id="multipartResolver" 
     class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> 
     <!-- one of the properties available; the maximum file size in bytes --> 
     <property name="maxUploadSize" value="3145728" /> 
     <property name="maxInMemorySize" value="3145728"></property> 
    </bean> 

    <bean id="velocityEngine" 
     class="org.springframework.ui.velocity.VelocityEngineFactoryBean"> 
     <property name="velocityProperties"> 
      <value> 
       resource.loader=file 
       file.resource.loader.class=org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader 
      </value> 
     </property> 
    </bean> 
    <!-- <bean id="velocityEngine" class="org.springframework.ui.velocity.VelocityEngineFactoryBean"> 
     <property name="velocityProperties"> <value> resource.loader=class class.resource.loader.class=org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader 
     </value> </property> <property name="resourceLoaderPath"> <value>/WEB-INF/velocity</value> 
     </property> </bean> --> 



    <!-- <bean id="controleAcesso" class="br.com.cheapig.seguranca.ControleAcesso"> 
     <bean id="cheapigFilter" class="br.com.cheapig.seguranca.SegurancaFilter" 
     > <property name="controleAcesso" ref="controleAcesso" /> <property name="localeResolver" 
     ref="localeResolver" /> </bean> --> 

</beans> 

Мой сервлет-context.xml:

<?xml version="1.0" encoding="UTF-8"?> 
<beans:beans xmlns="http://www.springframework.org/schema/mvc" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:beans="http://www.springframework.org/schema/beans" 
    xmlns:context="http://www.springframework.org/schema/context" 
    xmlns:task="http://www.springframework.org/schema/task" 
    xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd 
     http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd 
     http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd 
     http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.1.xsd"> 

    <!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure --> 

    <!-- Enables the Spring MVC @Controller programming model --> 
<!-- <annotation-driven /> --> 
    <!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory --> 
    <resources mapping="/resources/**" location="/resources/" /> 

    <!-- Imports user-defined @Controller beans that process client requests --> 
    <beans:import resource="controllers.xml" /> 
    <beans:import resource="hibernateMySQL5.xml"/> 
    <beans:import resource="integracaoTiles2.xml"/> 
    <beans:import resource="servicoEmail.xml"/> 

    <!-- <context:component-scan base-package="br.com.cheapig" /> --> 
    <task:annotation-driven/> 
</beans:beans> 

Дело в том, как настроить приложение для работы @Autowired в моем фильтре, не загружая мои компоненты несколько раз?

ответ

2

Вы можете выборочно выполнять компонентное сканирование. В корневом контексте:

<context:component-scan base-package="..."> 
    <context:exclude-filter expression="org.springframework.stereotype.Controller" type="annotation"/> 
</context:component-scan> 

сервлет-context.xml

<context:component-scan base-package="..." use-default-filters="false"> 
    <context:include-filter expression="org.springframework.stereotype.Controller" type="annotation" /> 
    <context:include-filter expression=".*Filter" type="regex" /> 
</context:component-scan> 
+0

Я уже пробовал это. Но даже если я поместил все конфигурации в root-context.xml, а не в servlet-context.xml, фильтр вызывается дважды! – jguilhermemv

+0

Я не совсем понял @jguilhermemv, вы упомянули, что фильтр вызывается дважды, вызывается он дважды при вызове метода контроллера или вы чувствуете, что создаются два экземпляра bean? Кроме того, это похоже на то, что вы положили в root-context.xml, действительно должны перейти в файл servlet-context.xml - обработчик, обработчик аннотации, handlerMapping, messageSource и т. Д. –

+0

Возможно, вы перенаправляете к другому контроллеру, и фильтр снова выполняется, для нового запроса - который ожидается. Я сомневаюсь, что ваша конфигурация Spring - это проблема. –

Смежные вопросы