首页 文章

@Autowired在DelegatingFilterProxy中

提问于
浏览
3

我有以下问题:

我正在使用Spring MVC 3开发基于Web的应用程序 . 在我的web.xml配置中,我有两个上下文(root-context.xml -Global Context - 由ContextLoadListener和servlet-context.xml加载 - 用于DispatcherServlet) .

但是在我的配置中,我需要一个使用DelegatingFilterProxy实现的过滤器,并配置如下:

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

此过滤器指向一个名为SegurancaFilter的类,该类从OncePerRequestFilter扩展 . 但是,为了使这个过滤器执行它需要访问servlet-context.xml中的bean @Autowired,并且过滤器本身必须是一个Spring托管bean,所以我必须用@Component标记它(这将无法工作) ,因为我既没有在root-context中设置也没有将过滤器设置为XML bean) .

如果我放置

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

在我的root-context中,我的所有bean都会被连线两次,导致应用程序调用beans方法两次 . 那是因为我在root-context.xml和servlet-context.xml中有相同的配置 . 但是如果我删除了servlet-context.xml的这个配置并将其保存在root-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;
    }
}

我的root-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>

我的servlet-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在我的过滤器中工作而不会多次加载我的bean?

2 回答

  • 0

    您可以选择性地进行组件扫描 . 在根上下文中:

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

    在servlet-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>
    
  • 2

    过滤器设计为两次调用 . 查看the diagram on this page

    FilterX ---> FilterY ---> Servlet ---> FilterY ---> FilterX

相关问题