繁体   English   中英

在根上下文和servlet上下文中创建Spring控制器bean

[英]Spring controller bean is created in root context AND in servlet context

我正在编程一个Tomcat应用程序,该应用程序充当某些内部服务的代理。

在遇到一些问题(请参阅ApplicationContext )后,我的Tomcat应用程序几乎可以按预期运行。

但是我的应用程序的日志记录说控制器bean初始化了两次,我没有找到原因。 我不使用XML配置,仅使用注释和Java配置。

在我看来,根上下文中的注释属性excludeFilters被忽略了。

请参阅下面的课程。 web.xml为空。

春季靴

package com.application.config;

import javax.servlet.*;

import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.filter.DelegatingFilterProxy;
import org.springframework.web.servlet.DispatcherServlet;

public class MyAppSpringBoot implements WebApplicationInitializer
{

    @Override
    public void onStartup(ServletContext container) throws ServletException
    {
        initRootContext(container);

        initDispatcherContext(container);

        addFilters(container);
    }

    private void initDispatcherContext(ServletContext container)
    {
        AnnotationConfigWebApplicationContext servletContext = new AnnotationConfigWebApplicationContext();
        servletContext.register(MyAppDispatcherServletContext.class);
        ServletRegistration.Dynamic dispatcher =
                container.addServlet("myAppDispatcherServlet", new DispatcherServlet(servletContext));
        dispatcher.setLoadOnStartup(1);
        dispatcher.addMapping("/");
    }

    private void initRootContext(ServletContext container)
    {
        AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
        rootContext.register(MyAppRootContext.class);
        container.addListener(new ContextLoaderListener(rootContext));
    }

    private void addFilters(ServletContext container)
    {
        FilterRegistration.Dynamic registration =
                container.addFilter("userDbAuthenticationFilter", DelegatingFilterProxy.class);
        registration.addMappingForUrlPatterns(null, false, "/mapgate/*");

        registration = container.addFilter("prepareRequestFilter", DelegatingFilterProxy.class);
        registration.addMappingForUrlPatterns(null, false, "/mapgate/*");

        registration = container.addFilter("responseTextXmlFilter", DelegatingFilterProxy.class);
        registration.addMappingForUrlPatterns(null, false, "/mapgate/*");
    }
}

根上下文Java配置:

package com.application.config;

import java.io.File;
import java.io.IOException;
import java.util.Properties;
import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;
import javax.xml.stream.*;

import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.context.annotation.*;
import org.springframework.jdbc.datasource.lookup.DataSourceLookupFailureException;
import org.springframework.jdbc.datasource.lookup.JndiDataSourceLookup;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.stereotype.Controller;

import com.application.controller.MyAppXmlFilterWords;
import com.application.urlmapping.UrlPairing;

@Configuration
@ComponentScan(basePackages = "com.application", excludeFilters = @ComponentScan.Filter(Controller.class))
public class MyAppRootContext
{

    private static Logger logger = LogManager.getLogger(MyAppRootContext.class.getName());

    /*

    These 3 filter beans are annotated with @Component. They are working as expected

    @Bean
    public UserDbAuthenticationFilter userDbAuthenticationFilter()
    {
        return new UserDbAuthenticationFilter();
    }

    @Bean
    public PrepareRequestFilter prepareRequestFilter()
    {
        return new PrepareRequestFilter();
    }

    @Bean
    public ResponseTextXmlFilter responseTextXmlFilter()
    {
        return new ResponseTextXmlFilter();
    }

    */
    @Bean
    public DataSource userDbJpaDataSource() throws DataSourceLookupFailureException
    {

        JndiDataSourceLookup lookup = new JndiDataSourceLookup();
        DataSource dataSource = lookup.getDataSource("jdbc/userDbPostgres");
        logger.info("U3R Datasource: {}", dataSource);
        return dataSource;
    }

    @Bean
    public EntityManagerFactory entityManagerFactory()
    {
        LocalContainerEntityManagerFactoryBean fb = new LocalContainerEntityManagerFactoryBean();
        fb.setDataSource(userDbJpaDataSource());
        fb.afterPropertiesSet();
        return fb.getNativeEntityManagerFactory();
    }

    @Bean
    public DiskFileItemFactory diskFileItemFactory()
    {
        DiskFileItemFactory factory = new DiskFileItemFactory();
        factory.setSizeThreshold(50_000 * 1024);
        factory.setRepository(new File("/WEB-INF/upload"));
        return factory;
    }

    @Bean
    public XMLOutputFactory xmlOutputFactory()
    {
        return XMLOutputFactory.newInstance();
    }

    @Bean
    public XMLInputFactory xmlInputFactory()
    {
        return XMLInputFactory.newInstance();
    }

    @Bean
    public XMLEventFactory xmlEventFactory()
    {
        return XMLEventFactory.newInstance();
    }

    @Bean
    public UrlPairing urlPairing() throws IOException
    {
        return new UrlPairing(myAppProperties().getProperty("myApp.UrlPairingFile"));
    }

    @Bean
    public Properties myAppProperties() throws IOException
    {
        Properties p = new Properties();
        p.load(MyAppRootContext.class.getResourceAsStream("/myAppConfig.properties"));
        return p;
    }

    @Bean
    public MyAppXmlFilterWords xmlFilterWords() throws IOException
    {
        MyAppXmlFilterWords words = MyAppXmlFilterWords.createFilterWords(myAppProperties().getProperty("myApp.xmlFilterWordFile"));
        return words;
    }

}

servlet上下文配置(此处没有bean,全部在根上下文中)

package com.application.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Controller;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;

/** myApplication Spring dispatcher servlet context
 *
 * Created by ulrich.knaack on 11.08.2015.
 */
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "com.application.controller", useDefaultFilters = false, includeFilters = @ComponentScan
        .Filter(Controller.class))
public class MyAppDispatcherServletContext
{
// no servlet specific beans required, all in root context
}

控制器类

package com.application.controller;

import java.io.*;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.*;
import javax.annotation.PostConstruct;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.apache.http.*;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.*;
import org.apache.http.entity.*;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.application.filter.MyAppRequestHelper;
import com.application.misc.MyAppHttpTools;

import static com.application.misc.MyAppConstants.*;

@Controller
@RequestMapping(value = "mapgate/**")
public class MyAppProxyController implements ApplicationContextAware
{
    private static final Logger logger = LogManager.getLogger(MyAppProxyController.class.getName());

    @Autowired
    Properties myAppProperties;

    @Autowired
    private DiskFileItemFactory diskFileItemFactory;

    private ApplicationContext appContext;

    @PostConstruct
    public void init() throws ServletException
    {
        requestLogIntervall = (Integer.parseInt(myAppProperties.getProperty("myApp.requestLogIntervall")));
        logger.debug("Controller {} initialisiert. App-Context: {} {}", this.getClass().getName(),
                appContext.hashCode(), appContext);

        logger.debug("Beans im Zugriff von Controller:");
        for (String beanName : appContext.getBeanDefinitionNames())
        {
            logger.debug("          {}", beanName);
        }

        MyAppProxyController controller = (MyAppProxyController) appContext.getBean("myAppProxyController");
        logger.debug("controller-hash im Controller={}", controller.hashCode());
    }

    @SuppressWarnings("TryFinallyCanBeTryWithResources")
    @RequestMapping(method = RequestMethod.POST)
    protected void doPost(HttpServletRequest customerRequest,
                          HttpServletResponse response) throws ServletException,
            IOException
    {
    // some code
    }

    @RequestMapping(method = RequestMethod.GET)
    protected void doGet(HttpServletRequest customerRequest, HttpServletResponse customerResponse)
    {
    // some code
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
    {
        appContext = applicationContext;
    }

}

记录

20150814-165337 INFO  [RMI TCP Connection(5)-127.0.0.1] Root WebApplicationContext: initialization started
20150814-165337 INFO  [RMI TCP Connection(5)-127.0.0.1] Refreshing Root WebApplicationContext: startup date [Fri Aug 14 16:53:37 CEST 2015]; root of context hierarchy
20150814-165337 INFO  [RMI TCP Connection(5)-127.0.0.1] Registering annotated classes: [class com.application.config.MyAppRootContext]
20150814-165337 INFO  [RMI TCP Connection(5)-127.0.0.1] URL-Paring Konstruktor, Datei D:/doorman-ent/doorman-conf/urlpairing.txt
20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1] URL-Paare aus Datei <D:/doorman-ent/doorman-conf/urlpairing.txt> lesen...
20150814-165337 INFO  [RMI TCP Connection(5)-127.0.0.1] URL-Pairing: es existieren 17 Service-Paar(e) und 2 File-Paar(e)
20150814-165337 INFO  [RMI TCP Connection(5)-127.0.0.1] Filter com.application.filter.PrepareRequestFilter initialisiert. App-Context: 615649080 Root WebApplicationContext: startup date [Fri Aug 14 16:53:37 CEST 2015]; root of context hierarchy
20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1] Konstruktor com.application.filter.ResponseTextXmlFilter
20150814-165337 INFO  [RMI TCP Connection(5)-127.0.0.1] Filter com.application.filter.ResponseTextXmlFilter initialisiert. App-Context: 615649080 Root WebApplicationContext: startup date [Fri Aug 14 16:53:37 CEST 2015]; root of context hierarchy
20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1] Beans im Zugriff von XMLFilter:
20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1]           org.springframework.context.annotation.internalConfigurationAnnotationProcessor
20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1]           org.springframework.context.annotation.internalAutowiredAnnotationProcessor
20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1]           org.springframework.context.annotation.internalRequiredAnnotationProcessor
20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1]           org.springframework.context.annotation.internalCommonAnnotationProcessor
20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1]           org.springframework.context.annotation.internalPersistenceAnnotationProcessor
20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1]           org.springframework.context.event.internalEventListenerProcessor
20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1]           org.springframework.context.event.internalEventListenerFactory
20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1]           myAppRootContext
20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1]           org.springframework.context.annotation.ConfigurationClassPostProcessor.importAwareProcessor
20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1]           org.springframework.context.annotation.ConfigurationClassPostProcessor.enhancedConfigurationProcessor
20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1]           myAppDispatcherServletContext
20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1]           prepareRequestFilter
20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1]           responseTextXmlFilter
20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1]           userDbAuthenticationFilter
20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1]           myAppProxyController
20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1]           org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration
20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1]           requestMappingHandlerMapping
20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1]           mvcContentNegotiationManager
20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1]           viewControllerHandlerMapping
20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1]           beanNameHandlerMapping
20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1]           resourceHandlerMapping
20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1]           mvcResourceUrlProvider
20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1]           defaultServletHandlerMapping
20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1]           requestMappingHandlerAdapter
20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1]           mvcConversionService
20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1]           mvcValidator
20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1]           mvcPathMatcher
20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1]           mvcUrlPathHelper
20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1]           mvcUriComponentsContributor
20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1]           httpRequestHandlerAdapter
20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1]           simpleControllerHandlerAdapter
20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1]           handlerExceptionResolver
20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1]           mvcViewResolver
20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1]           diskFileItemFactory
20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1]           entityManagerFactory
20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1]           urlPairing
20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1]           myAppProperties
20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1]           xmlInputFactory
20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1]           userDbJpaDataSource
20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1]           xmlFilterWords
20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1]           xmlOutputFactory
20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1]           xmlEventFactory
20150814-165338 DEBUG [RMI TCP Connection(5)-127.0.0.1] Controller com.application.controller.MyAppProxyController initialisiert. App-Context: 615649080 Root WebApplicationContext: startup date [Fri Aug 14 16:53:37 CEST 2015]; root of context hierarchy
20150814-165338 DEBUG [RMI TCP Connection(5)-127.0.0.1] controller-hash im Controller=1369268001
20150814-165338 DEBUG [RMI TCP Connection(5)-127.0.0.1] controller-hash im XMLFilter=1369268001
20150814-165338 INFO  [RMI TCP Connection(5)-127.0.0.1] U3R Datasource: org.apache.tomcat.dbcp.dbcp2.BasicDataSource@7c912e88
20150814-165338 INFO  [RMI TCP Connection(5)-127.0.0.1] Building JPA container EntityManagerFactory for persistence unit 'userDbPersistence'
20150814-165339 INFO  [RMI TCP Connection(5)-127.0.0.1] Filter com.application.filter.UserDbAuthenticationFilter initialisiert. App-Context: 615649080 Root WebApplicationContext: startup date [Fri Aug 14 16:53:37 CEST 2015]; root of context hierarchy
20150814-165339 DEBUG [RMI TCP Connection(5)-127.0.0.1] EntityManagerFactory: org.hibernate.jpa.internal.EntityManagerFactoryImpl@6567e35f
20150814-165340 INFO  [RMI TCP Connection(5)-127.0.0.1] Mapped "{[/mapgate/**],methods=[GET]}" onto protected void com.application.controller.MyAppProxyController.doGet(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)
20150814-165340 INFO  [RMI TCP Connection(5)-127.0.0.1] Mapped "{[/mapgate/**],methods=[POST]}" onto protected void com.application.controller.MyAppProxyController.doPost(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse) throws javax.servlet.ServletException,java.io.IOException
20150814-165340 INFO  [RMI TCP Connection(5)-127.0.0.1] Looking for @ControllerAdvice: Root WebApplicationContext: startup date [Fri Aug 14 16:53:37 CEST 2015]; root of context hierarchy
20150814-165340 INFO  [RMI TCP Connection(5)-127.0.0.1] Root WebApplicationContext: initialization completed in 2831 ms
20150814-165340 INFO  [RMI TCP Connection(5)-127.0.0.1] FrameworkServlet 'myAppDispatcherServlet': initialization started
20150814-165340 INFO  [RMI TCP Connection(5)-127.0.0.1] Refreshing WebApplicationContext for namespace 'myAppDispatcherServlet-servlet': startup date [Fri Aug 14 16:53:40 CEST 2015]; parent: Root WebApplicationContext
20150814-165340 INFO  [RMI TCP Connection(5)-127.0.0.1] Registering annotated classes: [class com.application.config.MyAppDispatcherServletContext]
20150814-165340 DEBUG [RMI TCP Connection(5)-127.0.0.1] Controller com.application.controller.MyAppProxyController initialisiert. App-Context: 332892020 WebApplicationContext for namespace 'myAppDispatcherServlet-servlet': startup date [Fri Aug 14 16:53:40 CEST 2015]; parent: Root WebApplicationContext
20150814-165340 DEBUG [RMI TCP Connection(5)-127.0.0.1] controller-hash im Controller=1145466717
20150814-165340 INFO  [RMI TCP Connection(5)-127.0.0.1] Mapped "{[/mapgate/**],methods=[GET]}" onto protected void com.application.controller.MyAppProxyController.doGet(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)
20150814-165340 INFO  [RMI TCP Connection(5)-127.0.0.1] Mapped "{[/mapgate/**],methods=[POST]}" onto protected void com.application.controller.MyAppProxyController.doPost(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse) throws javax.servlet.ServletException,java.io.IOException
20150814-165340 INFO  [RMI TCP Connection(5)-127.0.0.1] Looking for @ControllerAdvice: WebApplicationContext for namespace 'myAppDispatcherServlet-servlet': startup date [Fri Aug 14 16:53:40 CEST 2015]; parent: Root WebApplicationContext
20150814-165340 INFO  [RMI TCP Connection(5)-127.0.0.1] FrameworkServlet 'myAppDispatcherServlet': initialization completed in 86 ms
20150814-165340 WARN  [http-apr-8080-exec-4] No mapping found for HTTP request with URI [/doorman/] in DispatcherServlet with name 'myAppDispatcherServlet'
20150814-165341 WARN  [http-apr-8080-exec-10] No mapping found for HTTP request with URI [/doorman/] in DispatcherServlet with name 'myAppDispatcherServlet'

@Configuration@Component的元注释。 换句话说,它还将一个类标记为组件扫描的候选对象。

在您的根配置中,您将组件扫描声明为

@ComponentScan(basePackages = "com.application", excludeFilters = @ComponentScan.Filter(Controller.class))

您的MyAppDispatcherServletContext类位于

package com.application.config;
// [imports]
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "com.application.controller", useDefaultFilters = false, includeFilters = @ComponentScan
        .Filter(Controller.class))
public class MyAppDispatcherServletContext

因此,它将被拾取,加载并根上下文中执行其自身的配置(具有其自身的组件扫描)。

然后,它将在servlet上下文中执行相同的操作。

更明确地分离软件包。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM