月度归档: 2016 年 2 月

  • Spring Boot starter

    Spring Boot推出后取得了巨大的成功,方便快速上手,还附带了很多product-ready特性。对微服务架构也很友好。

    随着Spring Boot一起推出的还有Spring Boot众多的starter。当你喜欢使用某些组件时,试试starter,只需要使用构建工具引用一个依赖,你就可以快速获得它。

    了解starter之后你也可以自己实现自己的starter,以便其他同事快速使用公司内部特有的组件。

    spring.factories

    每个starter都有一个spring.factories文件,位于META-INF目录下。

    # Auto Configure
    org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
    org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
    org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
    org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
    org.springframework.boot.autoconfigure.MessageSourceAutoConfiguration,\

    随便开一个文件来看

    @Configuration
    @ConditionalOnClass({ RabbitTemplate.class, Channel.class })
    @EnableConfigurationProperties(RabbitProperties.class)
    @Import(RabbitAnnotationDrivenConfiguration.class)
    public class RabbitAutoConfiguration {
    
    	@Bean
    	@ConditionalOnProperty(prefix = "spring.rabbitmq", name = "dynamic", matchIfMissing = true)
    	@ConditionalOnMissingBean(AmqpAdmin.class)
    	public 
  • Spring Boot输出日志到文件

    Spring Boot对于日志的支持是比较到位的,默认logback实现,输出到console。

    如果你的console支持ANSI,那么还可以选择彩色输出。

    很多时候可能并不只是希望日志能够输出到console,还希望能够保存到目录,甚至后期配合splunk等等做分析统计。

    Spring Boot会检测logging.file和logging.path是否存在,如果存在的话就会输出到文件中。这个配置可以在application.properties中设置。

    如果应用打包已经完成了,可以直接在命令行配置

    java -jar app.jar -Dlogging.path=/alidata/log

     …

  • Spring Boot的Banner

    Spring Boot应用在启动的时候会输出一个Banner,同时还会输出使用的Spring Boot的版本。

    默认的Banner如下

    spring-default-banner

    如果你需要自己替换的话可以放置一个banner.txt文件,这样Spring Boot就会使用自定义的banner,而不是默认的banner。

    Spring Banner的选择逻辑

    Banner的优先级和具体逻辑在SpringApplication中。

    	private Banner selectBanner(Environment environment) {
    		String location = environment.getProperty(BANNER_LOCATION_PROPERTY,
    				BANNER_LOCATION_PROPERTY_VALUE);
    		ResourceLoader resourceLoader = this.resourceLoader != null ? this.resourceLoader
    				: new DefaultResourceLoader(getClassLoader());
    		Resource resource = resourceLoader.getResource(location);
    		if (resource.exists()) {
    			return new ResourceBanner(resource);
    		
  • 包含Spring Data Rest到mappings endpoint中

    Spring Boot提供了一套方便使用的endpoint,暴露了常用的一些应用信息,比如路由情况,堆栈情况等等,灵活的使用不仅可以加快调试,也可以方便运维。

    RequestMappingEndpoint类提供了地址为mappings的endpoint,提供了是当前的路由情况,什么样的路径解析到什么样的执行器中。大概的输出如下

    mapping-endpoint-sample

    当然,任何你自己定义的Controller等等,都会被自动包含到这个mappings中。但是如果你使用Spring Data Rest,你就会发现它的相关信息并没有被包含到这个里面。

    Mappings Endpoint原理

    要解决这个问题,就需要先来看看RequestMappingEndpoint是如何工作的。

    首先它并没有缓存,这意味着每次访问的时候它都会调用invoke方法来获取信息

    public Map<String, Object> invoke() {
         ....
    }

    而Spring中的路由的映射大致讲只有两种,一种是UrlHandlerMapping,一种是MethodMapping。我们最常用的Controller配合RequestMapping的属于后者。

    而处理这两种情况都是从applicationContext中获取所有实例,然后提取信息。唯一的不同是两种映射的对应信息保持方式不同而已。

    Map <String,AbstractUrlHandlerMapping > mappings = applicationContext.getBeansOfType(AbstractUrlHandlerMapping.class);
    for (Entry < String, AbstractUrlHandlerMapping > mapping: mappings.entrySet()) {
        Map < String, Object > handlers 
  • Spark的Datasets

    对于Spark的使用者来说,越简单易用的API越好。所以在原有的RDD之上,Spark陆续添加了DataFrames和Spark SQL。特别是DataFrames,对于小数据集的快速上手非常简单,其API也是从R中借鉴的,很有亲切感。当然在这之下,底层的实现还是RDD,只是对于使用者,抽象程度更高而已。

    DataSets是为了解决类型安全和面向对象思维而添加的新API,包含在Spark 1.6中,其也是下个版本集中的方向。

    DataSets并不是从关系型数据结构抽象出来的,所以它的API反而和RDD类似,比如

    val lines = sqlContext.read.text("/wikipedia").as[String]
    val words = lines
      .flatMap(_.split(" "))
      .filter(_ != "")
    val counts = words 
        .groupBy(_.toLowerCase)
        .count()

    在直接使用的效率和资源消耗上要好一些(图来自DataBricks)

    Memory-Usage-when-Caching-Chart-1024x359Distributed-Wordcount-Chart-1024x371

    当然,另外一个增强面向对象的特性使用很简单, 主要基于Encoders

    public class Person implements Serializable {
        private String name;
    
        get/set function{}
    }
    
    Dataset<Person> 
  • Http2在JVM环境的支持

    先来看看容器

    • Undertow
    • Jetty
    • Tomcat9

    然后还有 Netty。

    对于TLS的支持

    • Java6只支持v1
    • Java7支持v1.2
    • Java8支持v1.2
    • Java9支持ALPN
  • netflix的gradle插件

    Netflix在开源界的声誉稳步上涨,主要源于其公司产品特性中抽象出的微服务体系概念落地的开源技术。NetflixOSS不管包含主要的抽象组件,也开源了它使用的gradle插件,很多插件非常易用。

    Gradle作为构建工具,有远优于Maven的配置灵活性和Groovy对于Java世界极高的亲和力。

    一个普通的模板项目一般只是用了java和对应IDE插件,比如

    apply plugin: java
    apply plugin: idea
    apply plugin: eclipse

    但是除此之外还有一些基本的,比如发布,版本号升级,项目联系人,协议检查等等等等基本配置。

    Netflix的gradle-netflixoss-project-plugin可以快速实现这些。

    buildscript {
      repositories { jcenter() }
      dependencies { classpath 'com.netflix.nebula:gradle-netflixoss-project-plugin:3.2.2' }
    }
    
    allprojects {
        apply plugin: 'nebula.netflixoss'
    }

    这个插件其实也是调用其他插件,除了协议检查使用了hierynomus的以外,其他都是 Netflix自己的。默认的协议header是Netflix的,需要自己重新配置,格式如下:

    Copyright ${year} Netflix, Inc.