博客

  • bytedeco opencv在gradle中无法使用的问题

    bytedeco opencv是一个opencv的封装,所有依赖都可以在maven中央库中找到,是一个非常方便的东西。

    如果你是用构建工具,那么只需要引入

     <dependency>
        <groupId>org.bytedeco</groupId>
        <artifactId>javacv</artifactId>
        <version>1.2</version>
      </dependency>

    就应该可以正常使用。

    因为opencv对于不同平台需要不同平台对应的编译,所以构建项目的时候会去下载对应的编译依赖,如果你使用gradle就会遇到这种问题

    Could not resolve all dependencies for configuration ':compileClasspath'.
    > Could not find javacpp-presets-Windows 8.1-amd64.jar (org.bytedeco:javacpp-presets:1.2).
      Searched in the following locations:
          https://repo1.maven.org/maven2/org/bytedeco/javacpp-presets/1.2/javacpp-presets-1.2-Windows 8.1-amd64.jar
    

    去仓库看看,的确没有这个文件。但是这种方式在maven中工作。

    那是因为默认的解析规则是javacpp-presets-${os.name}-${os.arch}.jar,而maven和gradle中的解析有一些不同之处,所以最简单的处理办法是自己手动引入对应的编译依赖

    compile group: 'org.bytedeco.javacpp-presets', name: 'opencv', version: 
  • Gradle生成独立运行包时出现Can’t Expand ZIP的问题

    有时候我们需要打包一个可独立运行的jar文件并分发出去,特别是桌面图形化程序。

    Gradle要打这种包是很方便的,网上有很多例子,比如以下这个

    jar {
      manifest { 
        attributes "Main-Class": "$mainClassName"
      }  
    
      from {
        configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
      }
    }

    又或者这样

    task fatJar(type: Jar) {
    	manifest {
            attributes "Main-Class": "$mainClassName"
        }
        baseName = project.name + '-all'
        from { 
  • 使用spring-retry实现自动重试和错误异常管理

    经常会遇到一些有很高错误率的情况,比如需要从外部获取数据,而对应的网络条件又很一般,那么常常会出现一些错误和重试的情况,代码可能是这样的

    public class Demo {
        public Data featch() {
            int current = 0;
            Data data;
            while (current < MAX_TRY_LIMIT) {
                try {
                    data = service.call();
                } catch (Exception ex) {
                    index++;
                }
            }
            return data;
        }
    }

    如果项目代码中这种类似的比较多就有点难管理了,而且上面这段代码只处理了重试的情况,并没有超时控制,错误追溯等等。

    spring-retry是专为这种情况而生的,它被spring多个子项目使用,比如batch,integration等。

    @Service
    
  • 自定义Jackson Serializer实现复杂Json转换

    Jackson绝对是一个方便好用的工具,可以快速的在json和java object之间转换。Spring中也集成了Jackson,所以可以方便的自动赋予这个特性,比如使用restOperations消费API的时候。

    但是有时候要消费的API要求的json很诡异,比如创建新用户,对方要求的格式如下:

    {
    	"data": {
    		"attrs": {
    			"firstName": "FN",
    			"lastName": "LN"
    		},
    		"dateOfBirth": {
    			"detail": "1900-01-01"
    		}
    	}
    }

    如果直接使用,那么我们的类对象就有点复杂了,需要嵌套好几层。但是我们也清楚,业务需要的不过就是三个数据而已,姓;名;生日。

    这个时候就可以考虑自定义Serializer了。

    比如这样

    class CustomerSerializer extends JsonSerializer<Customer> {
        @Override
        public void serialize(Customer value, JsonGenerator gen, SerializerProvider provider) throws IOException {
            
  • Spring中RestOperations的错误处理

    Spring提供了RestOperations来方便支持rest api的使用。不仅对于常用的方法语义有支持,对于常用的错误处理也有考虑,简单来说,用起来方便顺手,如果是返回json等常见格式,也能自动转为Java对象。

    RestOperations的默认错误处理由DefaultResponseErrorHandler负责,其中的方法hasError的返回值决定了是否将当前返回作为错误来对待。默认的实现是

    protected boolean hasError(HttpStatus statusCode) {
    		return (statusCode.series() == HttpStatus.Series.CLIENT_ERROR ||
    				statusCode.series() == HttpStatus.Series.SERVER_ERROR);
    	}

    也就是说4和5开头的状态码看作错误。然后在直接将返回内容封装一下抛出

    @Override
    	public void handleError(ClientHttpResponse response) throws IOException {
    		HttpStatus statusCode = getHttpStatusCode(response);
    		switch (statusCode.series()) {
    			case CLIENT_ERROR:
    				throw new HttpClientErrorException(statusCode, response.getStatusText(),
    						response.getHeaders(), 
  • Spring Boot在Paypal中的应用

    看着分享,slideshare上的,可能需要外网访问权限

    http://www.slideshare.net/SpringCentral/spring-boot-paypal

     

    PayPal很有趣的地方在于虽然Spring体系已经成为一定程度上的事实标准,但是PayPal还是先采用的JSR标准,然后将Spring家族的一部分作为JSR的实现来使用。…

  • 谈Gradle多项目工程的初始化

    Gradle可谓java世界最流行的依赖管理和构建工具。

    在安装了Java环境的情况再搭配Gradle Init Script工具我们可以很快初始化一个项目。比如

    $ gradle init --type java-library
    :wrapper
    :init
    
    BUILD SUCCESSFUL
    
    Total time: 3.551 secs

    这样初始化出来的项目包含了基本的配置和src目录,依赖默认有两个

    dependencies {
        compile 'org.slf4j:slf4j-api:1.7.5'
        testCompile 'junit:junit:4.11'
    }

    对于简单的工程而言这样就足够了,方便快捷。但是如果是一个多项目工程就创建不出来了。

    从目前Gradle官方的roadmap来说,init模块是会被废弃的,而且之后还会新增不同的工程类型,所以之后可能会增加对于多项目工程的支持,但是目前没有。

    所以目前来说简单的办法如下

    1. 建立basic项目
    2. 创建子项目的目录
    3. 进入子项目目录,创建java-library项目
    4. 删除所有子项目中的gradle相关文件
    5. 修改basic项目的settings.gradle,include所有子项目

    这样操作虽然很繁琐,但是可以很流畅的工作。

    这样创建出来的多项目工程的依赖管理全部依赖于主项目的build.gradle文件,也就是类似这样的写法

    project("spring-context") {
    	description = "Spring 
  • Spring Boot 1.4发布

    Spring Boot 1.4昨天(7月28日)发布了,1.3系列经历了7个版本,终于来到了1.4系列。

    1.4有很多更新和新的功能支持,我个人觉得以下几个改动比较实用

    兼容Thymeleaf 3

    虽然默认的支持还是Thymeleaf 2.1,不过对于Thymeleaf 3还是可以用的。本来1.4是不准备支持Thymeleaf 3的,不过社区呼声非常高,所以最后还是采用了兼容方案。

    启动错误信息

    Spring Boot由于各种便利的特性广受喜爱,但是便利特性的同时也引入了一些不成为的规定和注解,而且大量的aop,自动配置穿插其中。如果你的项目有利用这些特性有一些自定义的东西,那么启动失败的追查原因就会非常复杂了。

    2016-02-16 17:46:14.334 ERROR 24753 --- [           main] o.s.boot.SpringApplication               : Application startup failed
    
    java.lang.RuntimeException: java.net.BindException: Address already in use
        at io.undertow.Undertow.start(Undertow.java:181) ~[undertow-core-1.3.14.Final.jar:1.3.14.Final]
        at org.springframework.boot.context.embedded.undertow.UndertowEmbeddedServletContainer.start(UndertowEmbeddedServletContainer.java:121) ~[spring-boot-1.3.2.RELEASE.jar:1.3.2.RELEASE]
        at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.startEmbeddedServletContainer(EmbeddedWebApplicationContext.java:293) ~[spring-boot-1.3.2.RELEASE.jar:1.3.2.RELEASE]
        
  • 利用Docker快速搭建Spark本地环境

    Spark模式是直接local直接开发的,也就是在SparkConf中直接设定为local[*]之类,就可以在本地启动Spark然后开始工作。

    但是有时候还是希望将这些分开,也就是说有一个独立的Spark Master和一些Workers,本地开发,但是运行还是在简单的集群上。

    因为需求很简单,所以直接自己写一个Dockerfile

    FROM java:8
    WORKDIR /opt
    RUN wget -q http://apache.fayea.com/spark/spark-1.6.2/spark-1.6.2-bin-hadoop2.6.tgz -O spark.tgz
    RUN tar xfz spark.tgz && mv spark-1.6.2-bin-hadoop2.6 spark
    EXPOSE 8080 7077 6066
    ENTRYPOINT ./spark/sbin/start-master.sh && ./spark/sbin/start-slave.sh spark://$(ip addr show eth0 | grep "inet\b" | awk '{print 
  • 为wordpress加上Redis

    wordpress随着文章数量增加,有时候访问稍微有一些就变得很慢了。

    今天有空就决定给wordpress加上Redis缓存。

    首先在Docker-compose中加上Redis依赖

    redis:
      image: redis:alpine

    然后link到wordpress中

    links:
    - redis

    然后安装Redis Object Cache,并在wp-config.php中把host改成redis,然后连接即可。

    redis-cache