SpringBoot 入门经验

最近接触到SpringBoot,才接触(太落伍)

数据源配置:

spring:
  application:
    name: xxx.xxx.xxx
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
  aop:
    auto: true
    proxy-target-class: false

另外还有一个配置:

image.png

以这样的方式配置的数据源是没有问题的。但是仔细看SpringBoot会自动反复创建一个datasource,但是这个spring.datasource是配置不全的。
因而会反复报错。

[ERROR] [17:25:13.546][DiscoveryClient][1477]:Cannot fetch registry from server
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sqlSessionFactory' defined in URL [file:/E:/XXXXXX/target/classes/spring/applicationContext-mybatis.xml]: Cannot resolve reference to bean 'dataSource' while setting bean property 'dataSource'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSource' defined in class path resource [XXXXXXXXconfig/HikariCPConfig.class]: Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSourceInitializer': Invocation of init method failed; nested exception is java.lang.IllegalStateException: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@1fb5261 has been closed already
.....
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSource' defined in class path resource [XXXXXXXXconfig/HikariCPConfig.class]: Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSourceInitializer': Invocation of init method failed; nested exception is java.lang.IllegalStateException: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@1fb5261 has been closed already
    ... 23 more
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSourceInitializer': Invocation of init method failed; nested exception is java.lang.IllegalStateException: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@1fb5261 has been closed already
    ... 23 more
Caused by: java.lang.IllegalStateException: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@1fb5261 has been closed already
    ... 23 more


解决方法就是,要么把这个数据源写全。要么就加上一个

@EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class})

注解在@Configuration类上。
@SpringBootApplication包含了这个注解

就不会自动创建这个残缺的数据源了。

2017年9月30日 11:12:18 更新

上面说的问题,基本很少遇到,其实后来发现是因为Profile配置和Maven Resource标签写的很混乱,导致配置文件复制不全。

Spring Boot 正确配置

下面给出正确的配置

@EnableEurekaClient
@EnableDiscoveryClient
@SpringBootApplication
@ImportResource("classpath*:spring/applicationContext.xml")
@EnableFeignClients
public class Bootstrap {
    public static void main(String[] args) {
        SpringApplication.run(Bootstrap.class, args);
    }
}

注意,下面的这段是多余的,不用写。SpringBoot 会自动扫瞄到这个文件(resources根目录下)。

@PropertySources({
        @PropertySource("classpath:application.yaml"),
})

前两行是Eureka的配置,如果想连接上注册中心的话。
第三行是SpringBootApplication主要注解。等价于

@Configuration
@EnableAutoConfiguration
@ComponentScan

第四行是导入经典的xml配置,一般是Mybatis的。个人是比较喜欢Java Config和XML混合的方式去配置。如下

<bean id="yamlProperties" class="org.springframework.beans.factory.config.YamlPropertiesFactoryBean">
        <property name="resources" value="classpath:conf/application*.yaml"/>
    </bean>

    <context:property-placeholder properties-ref="yamlProperties" ignore-unresolvable="true"/>

    <import resource="applicationContext-mybatis.xml"/>

还有,如果用SpringBoot不需要下面的配置。

<mvc:annotation-driven>
        <mvc:message-converters>
            <bean class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter">
                <property name="features">
                    <list>
                        <value>DisableCircularReferenceDetect</value>
                        <value>WriteNullListAsEmpty</value>
                        <value>WriteNullStringAsEmpty</value>
                    </list>
                </property>
            </bean>
        </mvc:message-converters>
    </mvc:annotation-driven>

    <!-- spring实例化扫描器 -->
    <context:component-scan base-package="com.xxx.xxx" />

因为,mvc:annotation-driven 会和SpringBoot的Component一起扫瞄,这样会导致HandlerMapping 处理 Controller 的@RequestMapping 两次。简单说,看日志会打印两次Controller的 RequestMapping的URL。

那么,MessageConverter怎么处理呢?

MessageConverter

任意写一个Configuration类

@Configuration
public class SpringConfig {

    @Bean
    public HttpMessageConverter configureMessageConverter() {
        HttpMessageConverter<?> messageConverter = new FastJsonHttpMessageConverter();
        ((FastJsonHttpMessageConverter)messageConverter).setFeatures(SerializerFeature.DisableCircularReferenceDetect);
        ((FastJsonHttpMessageConverter)messageConverter).setFeatures(SerializerFeature.WriteNullListAsEmpty);
        ((FastJsonHttpMessageConverter)messageConverter).setFeatures(SerializerFeature.WriteNullStringAsEmpty);
        ((FastJsonHttpMessageConverter)messageConverter).setFeatures(SerializerFeature.WriteMapNullValue);

        return messageConverter;
    }
}

这样才算是正确的,清晰的,符合SpringBoot的理念的配置方式。

MessageConverter 更好的配置方式

 @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        super.configureMessageConverters(converters);
        FastJsonHttpMessageConverter4 fastConverter = new FastJsonHttpMessageConverter4();
        FastJsonConfig fastJsonConfig = new FastJsonConfig();
        fastJsonConfig.setSerializerFeatures(SerializerFeature.DisableCircularReferenceDetect);
        fastJsonConfig.setSerializerFeatures(SerializerFeature.WriteNullListAsEmpty);
        fastJsonConfig.setSerializerFeatures(SerializerFeature.WriteNullStringAsEmpty);
        fastJsonConfig.setSerializerFeatures(SerializerFeature.WriteMapNullValue);
        fastConverter.setFastJsonConfig(fastJsonConfig);
        converters.add(fastConverter);
    }

这是在使用Feign并且,因为FastJSON低版本的安全漏洞升级FastJSON 到1.2.29时遇到的。
改成这样就没问题了。具体原因没有详细探究,FastJSON 1.2.29是支持Spring Core 4.2.6的,并且通过FastJsonHttpMessageConverter4 进行支持。

Spring Boot 启动完成后执行特定代码

看了很多文章,一般都是判断DisplayName是否是Root Application这种,或者getParent() == null
感觉都不怎么好用,下面给出经过验证的代码。

@Component
public class ApplicationStartup implements ApplicationListener<ContextRefreshedEvent> {
    public void onApplicationEvent(ContextRefreshedEvent event) {
        ApplicationContext applicationContext = event.getApplicationContext();
        if(applicationContext instanceof EmbeddedWebApplicationContext) {
            log.info("ApplicationStartup {}", applicationContext.getDisplayName());
        }
    }
}

如果是使用

event.getApplicationContext().getParent() == null  

或者使用

event.getApplicationContext().getDisplayName().equals("Root WebApplicationContext")

都是不对的。

  1. EmbeddedWebApplicationContext 的Parent 不是 null。
  2. EmbeddedWebApplicationContext 的DisplayName是
    AbstractApplicationContext
/** Display name */
private String displayName = ObjectUtils.identityToString(this);

产生。不等于Root WebApplicationContext

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,530评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,403评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,120评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,770评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,758评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,649评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,021评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,675评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,931评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,751评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,410评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,004评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,969评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,042评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,493评论 2 343

推荐阅读更多精彩内容