tomcat启动时没有把spring配置文件定义的bean加载进来

本文涉及的产品
云数据库 Tair(兼容Redis),内存型 2GB
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云原生网关 MSE Higress,422元/月
简介: tomcat启动时没有把spring配置文件定义的bean加载进来最近在把自己的之前搭建的那个通用的ssh框架,配置成dubbo+zookeeper这样的分布式架构。

tomcat启动时没有把spring配置文件定义的bean加载进来

最近在把自己的之前搭建的那个通用的ssh框架,配置成dubbo+zookeeper这样的分布式架构。搭建的思路就是把项目的service和controller分离出来。两个项目之间的服务就通过zookeeper注册和订阅的方式来完成。service层的搭建还是比较顺利的。在加入了zookeeper和dubbo的相关配置和分离了controller层的配置后接口服务能够自动的注册到dubbo。


img_2886a4de66734f8062af9564270fe8cc.png
2018-10-15 09-41-26屏幕截图.png

但是在搭建controller层的项目时,在相关的配置完成后,服务通过tomcat启动,一开始是发现项目能够订阅到service层的服务的,以为就没有错了,但是后面我在测试项目的整合的redis的时候发现controller层的容器没有成功初始化redis配置文件中定义的bean对象。


img_59e9b5dc20bcf61dd1bdabfad3828238.png
2018-10-15 09-45-17屏幕截图.png

(服务是已经订阅到的)

我在服务启动后把容器管理的bean对象信息都打印出来发现我spring整合redis配置文件定义的bean都没有在里面。

 [DUBBO] Refer dubbo service com.lung.application.inter.TestService from url zookeeper://127.0.0.1:2181/com.alibaba.dubbo.registry.RegistryService?anyhost=true&application=dubbo-project-manager-consumer&check=false&default.delay=-1&default.retries=0&default.timeout=1200000&delay=-1&dubbo=2.5.3&interface=com.lung.application.inter.TestService&methods=queryAreaInfo,getResult&pid=29313&revision=1.0-SNAPSHOT&side=consumer&timestamp=1539567979182, dubbo version: 2.5.3, current host: 172.17.0.1
[INFO ] 2018-10-15 09:46:19,274 method:com.lung.common.utils.ManagerBeansName.init(ManagerBeansName.java:25)
beanDefinitionCount29
roleController
testController
superController
managerBeansName
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
org.springframework.web.servlet.resource.DefaultServletHttpRequestHandler#0
org.springframework.web.servlet.handler.SimpleUrlHandlerMapping#0
mvcCorsConfigurations
org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping
org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter
org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter
mvcHandlerMappingIntrospector
mvcContentNegotiationManager
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping
org.springframework.format.support.FormattingConversionServiceFactoryBean#0
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter
mvcUriComponentsContributor
org.springframework.web.servlet.handler.MappedInterceptor#0
org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver#0
org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver#0
org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver#0
fastJsonHttpMessageConverter
org.springframework.web.servlet.view.InternalResourceViewResolver#0
multipartResolver
[INFO ] 2018-10-15 09:46:19,541 method:org.springframework.web.servlet.handler.AbstractUrlHandlerMapping.registerHandler(AbstractUrlHandlerMapping.java:362)
Mapped URL path [/**] onto handler 'org.springframework.web.servlet.resource.DefaultServletHttpRequestHandler#0'
[INFO ] 2018-10-15 09:46:19,628 method:org.springframework.web.servlet.handler.AbstractHandlerMethodMapping$MappingRegistry.reg

这是我的springMVC配置文件

<?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:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
       http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

    <!--<context:property-placeholder ignore-unresolvable="true" location="classpath*:config.properties"/>-->
    <!--1. 扫描 -->
    <context:component-scan
            base-package="com.lung.application,com.lung.common.controller,com.lung.common.utils">
        <!--<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service"/>-->
    </context:component-scan>
    <!--2.两个标准配置 -->
    <!--将springmvc不能处理的请求交给tomcat -->
    <mvc:default-servlet-handler/>
    <!--能支持springmvc更高级的一些功能,JSR303校验,快捷的ajax...映射动态请求 -->
    <mvc:annotation-driven>
        <mvc:message-converters register-defaults="true">
            <bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter"/>
            <bean class="org.springframework.http.converter.FormHttpMessageConverter"/>
            <bean class="org.springframework.http.converter.xml.SourceHttpMessageConverter"/>
            <ref bean="fastJsonHttpMessageConverter"/>
            <!--<ref bean="jsonMessageConverter"/>-->
        </mvc:message-converters>
    </mvc:annotation-driven>

    <!--jackson配置json为空不输出-->
    <!--<bean id="jsonMessageConverter"
          class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
        <property name="objectMapper">
            <bean class="com.fasterxml.jackson.databind.ObjectMapper">
                &lt;!&ndash;设置不输出null字段&ndash;&gt;
                <property name="serializationInclusion" value="NON_NULL"/>
            </bean>
        </property>
    </bean>-->
    <!-- 使用fastJson来支持JSON数据格式 -->
    <bean id="fastJsonHttpMessageConverter"
          class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter">
        <property name="supportedMediaTypes">
            <list>
                <value>text/html;charset=UTF-8</value>
                <value>application/json</value>
            </list>
        </property>
        <property name="features">
            <list>
                <!-- 避免循环引用 -->
                <value>DisableCircularReferenceDetect</value>
                <!-- 输出key时是否使用双引号 -->
                <value>QuoteFieldNames</value>
                <!-- 数值字段如果为null,输出为0,而非null -->
                <value>WriteNullNumberAsZero</value>
                <!-- List字段如果为null,输出为[],而非null -->
                <value>WriteNullListAsEmpty</value>
                <!-- 字符类型字段如果为null,输出为"",而非null -->
                <value>WriteNullStringAsEmpty</value>
                <!-- Boolean字段如果为null,输出为false,而非null -->
                <value>WriteNullBooleanAsFalse</value>
                <!-- Date的日期转换器 -->
                <value>WriteDateUseDateFormat</value>
            </list>
        </property>
    </bean>

    <!--3.配置视图解析器,方便页面返回-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/pages/"></property>
        <property name="suffix" value=".jsp"></property>
    </bean>

    <!--file upload settings-->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <property name="defaultEncoding" value="UTF-8"/>
        <property name="maxUploadSize" value="10485760000"/>
        <property name="maxInMemorySize" value="40960"/>
    </bean>

    <!--拦截器配置-->

</beans>

然后这是web.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://java.sun.com/xml/ns/javaee"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
                        http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
          version="3.0">

    <display-name>Project Web Application</display-name>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <!--1.Spring容器applicationContext.xml -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath*:spring/spring-introduce.xml</param-value>
    </context-param>

    <!--2.springmvc的前端控制器 -->
    <servlet>
        <servlet-name>springDispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath*:/spring/springmvc.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>springDispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

    <!--3.编码过滤 解决post乱码 -->
    <filter>
        <filter-name>CharacterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>utf-8</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>CharacterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <!--4、使用Rest风格的URI,将页面普通的post请求转为指定的delete或者put请求 -->
    <filter>
        <filter-name>HiddenHttpMethodFilter</filter-name>
        <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>HiddenHttpMethodFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <filter>
        <filter-name>HttpPutFormContentFilter</filter-name>
        <filter-class>org.springframework.web.filter.HttpPutFormContentFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>HttpPutFormContentFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
</web-app>

通过测试发现redis的bean对象没有,报一个空指针异常。


img_c1deb42ff8ccf60c0ce73c4adabff978.png
2018-10-15 09-53-19屏幕截图.png

img_8cc23604056ec59484d7a116e93ecf54.png
2018-10-15 09-53-42屏幕截图.png

在这里先给出解决方案:(其实这个算是我配置的问题了,自己基础不好包含而且粗心导致的。我的项目地址commonManageProject(mybatis-plus-version分支)
根本原因就是我在web.xml配置springDispatcherServlet的时候只是把springMVC的配置文件指定了,spring的配置文件没有指定。所以导致了tomcat启动后,只加载了pringmvc配置文件指定的bean。(因为分布式配置后,很多原来定义在springMVC配置文件bean都定义在了spring配置文件中)

这个问题在这里我卡住了很久都没有解决,一开始也是认为是我自己的配置问题,尝试着从几个方面找原因。
1、通过单元测试看看容器中redis对象是否存在:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath*:/spring/spring-introduce.xml",
        "classpath*:/spring/springmvc.xml"})
public class TestRedis {

    @Autowired
    BaseRedisDao baseRedisDao;

    @Test
    public void TestRedis() {
        try {
            boolean set = baseRedisDao.set("baseRedisKey", "baseRedisvalue");
            System.out.println(set);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

发现对象是存在的

[INFO ] 2018-10-15 10:03:57,861 method:com.alibaba.dubbo.config.ReferenceConfig.createProxy(ReferenceConfig.java:423)
 [DUBBO] Refer dubbo service com.lung.application.inter.TestService from url zookeeper://127.0.0.1:2181/com.alibaba.dubbo.registry.RegistryService?anyhost=true&application=dubbo-project-manager-consumer&check=false&default.delay=-1&default.retries=0&default.timeout=1200000&delay=-1&dubbo=2.5.3&interface=com.lung.application.inter.TestService&methods=queryAreaInfo,getResult&pid=30327&side=consumer&timestamp=1539569037813, dubbo version: 2.5.3, current host: 172.17.0.1
[INFO ] 2018-10-15 10:03:57,868 method:com.lung.common.utils.ManagerBeansName.init(ManagerBeansName.java:25)
beanDefinitionCount39
poolConfig
jedisConnectionFactory
redisTemplate
baseRedisDao
com.lung.common.utils.PropertyPlaceholder#0
config
dubbo-project-manager-consumer
com.alibaba.dubbo.config.RegistryConfig
roleServiceImpl
testServiceImpl
roleController
testController
superController
managerBeansName
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
org.springframework.web.servlet.resource.DefaultServletHttpRequestHandler#0
org.springframework.web.servlet.handler.SimpleUrlHandlerMapping#0
mvcCorsConfigurations
org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping
org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter
org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter
mvcHandlerMappingIntrospector
mvcContentNegotiationManager
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping
org.springframework.format.support.FormattingConversionServiceFactoryBean#0
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter
mvcUriComponentsContributor
org.springframework.web.servlet.handler.MappedInterceptor#0
org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver#0
org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver#0
org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver#0
fastJsonHttpMessageConverter
org.springframework.web.servlet.view.InternalResourceViewResolver#0
multipartResolver
[INFO ] 2018-10-15 10:03:58,045 method:org.springframework.web.servlet.handler.AbstractUrlHandlerMapping.registerHandler(AbstractUrlHandlerMapping.java:362)
Mapped URL path [/**] onto handler 'org.springframework.web.servlet.resource.DefaultServletHttpRequestHandler#0'

2、通过ClassPathXmlApplicationContext查看spring容器是否把redis的相关对象给初始化了:


public class TestSpring {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext classPathXmlApplicationContext =
                new ClassPathXmlApplicationContext("classpath:/spring/spring-introduce.xml");
        int beanDefinitionCount = classPathXmlApplicationContext.getBeanDefinitionCount();
        System.out.println(beanDefinitionCount);
        String[] beanDefinitionNames = classPathXmlApplicationContext.getBeanDefinitionNames();
        for (String str :
                beanDefinitionNames) {
            System.out.println(str);
        }
    }
}

发现也是正常的

[INFO ] 2018-10-15 10:06:13,113 method:org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:317)
Loading XML bean definitions from URL [file:/home/lung/IdeaProjects/commonManageProject/commons-manager/commons-manager-web/target/classes/dubbo/dubbo-consumer.xml]
[INFO ] 2018-10-15 10:06:13,214 method:
using logger: com.alibaba.dubbo.common.logger.log4j.Log4jLoggerAdapter
10
poolConfig
jedisConnectionFactory
redisTemplate
baseRedisDao
com.lung.common.utils.PropertyPlaceholder#0
config
dubbo-project-manager-consumer
com.alibaba.dubbo.config.RegistryConfig
roleServiceImpl
testServiceImpl
[INFO ] 2018-10-15 10:06:14,425 method:com.alibaba.dubbo.config.AbstractConfig$1.run(AbstractConfig.java:450)

无奈之下,我重新去复习一下springMVC的相关基础了,后面发现自己好像在配置分布式服务,把spring的配置做了更加细分的解耦后,我在web.xml配置servlet时只声明的配置文件是不行的,这个时候需要把其他spring配置文件也指定才行。
所以:

 <!--2.springmvc的前端控制器 -->
    <servlet>
        <servlet-name>springDispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath*:/spring/springmvc.xml,classpath*:/spring/applicationContext-*.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>springDispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

修改成上面后测试接口就正常了:


img_82dce8acdbf97be6317c19a07a48c9e5.png
2018-10-15 10-12-21屏幕截图.png

谨记!!!

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
8天前
|
监控 Java 应用服务中间件
Spring Boot整合Tomcat底层源码分析
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置和起步依赖等特性,大大简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是其与Tomcat的整合。
27 1
|
15天前
|
缓存 Java Spring
实战指南:四种调整 Spring Bean 初始化顺序的方案
本文探讨了如何调整 Spring Boot 中 Bean 的初始化顺序,以满足业务需求。文章通过四种方案进行了详细分析: 1. **方案一 (@Order)**:通过 `@Order` 注解设置 Bean 的初始化顺序,但发现 `@PostConstruct` 会影响顺序。 2. **方案二 (SmartInitializingSingleton)**:在所有单例 Bean 初始化后执行额外的初始化工作,但无法精确控制特定 Bean 的顺序。 3. **方案三 (@DependsOn)**:通过 `@DependsOn` 注解指定 Bean 之间的依赖关系,成功实现顺序控制,但耦合性较高。
实战指南:四种调整 Spring Bean 初始化顺序的方案
|
1月前
|
XML Java 数据格式
Spring从入门到入土(bean的一些子标签及注解的使用)
本文详细介绍了Spring框架中Bean的创建和使用,包括使用XML配置文件中的标签和注解来创建和管理Bean,以及如何通过构造器、Setter方法和属性注入来配置Bean。
70 9
Spring从入门到入土(bean的一些子标签及注解的使用)
|
1月前
|
Java 测试技术 Windows
咦!Spring容器里为什么没有我需要的Bean?
【10月更文挑战第11天】项目经理给小菜分配了一个紧急需求,小菜迅速搭建了一个SpringBoot项目并完成了开发。然而,启动测试时发现接口404,原因是控制器包不在默认扫描路径下。通过配置`@ComponentScan`的`basePackages`字段,解决了问题。总结:`@SpringBootApplication`默认只扫描当前包下的组件,需要扫描其他包时需配置`@ComponentScan`。
|
2月前
|
XML Java 数据格式
spring复习02,xml配置管理bean
详细讲解了Spring框架中基于XML配置文件管理bean的各种方式,包括获取bean、依赖注入、特殊值处理、属性赋值、集合类型处理、p命名空间、bean作用域及生命周期和自动装配。
spring复习02,xml配置管理bean
|
1月前
|
Java 开发者 Spring
Spring bean的生命周期详解!
本文详细解析Spring Bean的生命周期及其核心概念,并深入源码分析。Spring Bean是Spring框架的核心,由容器管理其生命周期。从实例化到销毁,共经历十个阶段,包括属性赋值、接口回调、初始化及销毁等。通过剖析`BeanFactory`、`ApplicationContext`等关键接口与类,帮助你深入了解Spring Bean的管理机制。希望本文能助你更好地掌握Spring Bean生命周期。
83 1
|
1月前
|
Java Spring
获取spring工厂中bean对象的两种方式
获取spring工厂中bean对象的两种方式
40 1
|
1月前
|
Java 开发者 Spring
Spring bean的生命周期详解!
本文详细介绍了Spring框架中的核心概念——Spring Bean的生命周期,包括实例化、属性赋值、接口回调、初始化、使用及销毁等10个阶段,并深入剖析了相关源码,如`BeanFactory`、`DefaultListableBeanFactory`和`BeanPostProcessor`等关键类与接口。通过理解这些核心组件,读者可以更好地掌握Spring Bean的管理和控制机制。
87 1
|
1月前
|
Java 应用服务中间件 Maven
idea+maven+tomcat+spring 创建一个jsp项目
这篇文章介绍了如何在IntelliJ IDEA中使用Maven和Tomcat创建一个JSP项目,包括配置Maven依赖、设置Tomcat服务器、编写JSP页面、创建控制器和配置文件,以及项目的运行结果。
179 0
idea+maven+tomcat+spring 创建一个jsp项目
|
2月前
|
XML Java 数据格式
spring复习03,注解配置管理bean
Spring框架中使用注解配置管理bean的方法,包括常用注解的标识组件、扫描组件、基于注解的自动装配以及使用注解后的注意事项,并提供了一个基于注解自动装配的完整示例。
spring复习03,注解配置管理bean