月度归档: 2014 年 10 月

  • Spring Mvc的参数注入分析

    Spring Mvc的一个强大之处在于对于各种参数注入的支持。

    除了基本的request,session等等以外,还支持RequestParam等等便利的东西。基本而言使用Spring mvc你可以直接在方法中指明你希望获得的参数,让Spring注入即可。

    参数注入的原理

    Spring Mvc中有一个HandlerMethodArgumentResolver接口,其中包含两个方法:

    publicbooleansupportsParameter(MethodParameter parameter)
    publicObject (MethodParameter parameter,ModelAndViewContainer mavContainer,NativeWebRequest webRequest, WebDataBinderFactory binderFactory)throws Exception

    当请求被Spring Mvc处理并获取到对应的执行方法时,它会首先检查所需的所有参数,然后依次检查现有的HandlerMethodArgumentResolver等否支持此类型,如果可以再调用resolveArgument方法获取参数对象。

    Spring Mvc自身有RequestParamMethodArgumentResolver,RequestParamMapMethodArgumentResolver等等常用的参数解析器。

    在RequestMappingHandlerAdapter中的getDefaultArgumentResolvers方法中硬编码了它们,而且顺序是固定无法改变的。

    Cookie的注入

    只要实现了HandlerMethodArgumentResolver就可以实现参数注入,以Spring Mvc自带的ServletCookieValueMethodArgumentResolver。

    因为从request从取出cookie值本身是一件相对简单的事情,所以这个类是一个很好的学习的例子。

    @Overrideprotected ObjectresolveName(String cookieName, MethodParameter parameter, NativeWebRequest webRequest)throws Exception {
    HttpServletRequest servletRequest = 
  • 修改Gradle中Wrapper版本

    一直在用Gradle,它提供的wrapper是一个很实用的功能。

    可以快速切换版本,保证构建的一致性,还可以方便没有安装Gradle的用户,也能保持构建工具版本的一致性。

    启用Wrapper以后会创建一个gradle目录,其中包含一个gradle-wrapper.properties文件,内容一般如下:

    distributionBase=GRADLE_USER_HOME
    distributionPath=wrapper/dists
    zipStoreBase=GRADLE_USER_HOME
    zipStorePath=wrapper/dists
    distributionUrl=https://services.gradle.org/distributions/gradle-2.0-bin.zip

    偶尔需要修改Gradle Wrapper版本的时候我会直接修改最后一行的distributionUrl参数。

    今天看文档才发现了一个Wrapper任务,每次的修改只需要修改这个任务,然后运行就会自动创建或者修改上面那个文件了。

    task wrapper(type: Wrapper) {
    gradleVersion = '2.0'
    }

    之后运行./gradlew wrapper即可。…

  • Mockito中RETURNS_DEEP_STUBS对于enum的处理

    Mockito是一个测试常用的库,可以快速模拟对象。

    加上对于Junit的支持不错,配有对应的Runner,使用起来也是相当方便。

    一般使用

    最常用的使用自然是SomeClass some=mock(SomeClass.class),如果你使用注解,还可以写成

    @Mock
    private SomeClass some;

    如果这个类有这样的方法some.getObjectOne().getValue(),我们是不能直接使用given或者when断言简单mock的,需要使用

    ObjectOne one=mock(ObjectOne.class);
    given(some.getObjectOne()).willReturn(one);
    given(one.getValue()).willReturn("value");

    Mockito提供了RETURNS_DEEP_STUBS模式,可以自己处理这种情况,如果我们使用SomeClass some=mock(SomeClass.class, RETURNS_DEEP_STUBS),我们就只需要一句简单的

    given(some.getObjectOne().getValue()).willReturn("value");

    就解决了。

    对于Enum的处理

    RETURNS_DEEP_STUBS本质上调用的ReturnsDeepStubs类。

    这个类在org.mockito.internal.stubbing.defaultanswers下面。

    public Objectanswer(InvocationOnMock invocation)throws Throwable {
    GenericMetadataSupport returnTypeGenericMetadata = actualParameterizedType(invocation.getMock()).resolveGenericReturnType(invocation.getMethod());
    Class 
  • 自定义Homebrew的Formula

    Homebrew是Mac Os X系统下一个非常优秀的软件包管理工具。使用包管理工具的优势就是省心,不再需要在网页上下载安装或者下载后解压再配置环境变量了,只需要使用brew install就可以完成安装了。

    Homebrew支持很多热门的应用和软件,而每一个支持都是一个.rb文件提供的,成为Formula。

    虽然官方支持上千种Formula,但是总有需要自己自定义的时候。

    本文以Moco为例子,创建一个Formula。

    基本内容

    Moco提供了一个命令行的jar,这也是最简单的情况,我们不需要下载编译,而是直接下载,然后链接就行了。

    我们需要的是一个standalone的jar包,版本是0.9.2,地址在这里。

    首先创建一个Formula,运行命令行brew create moco,编辑生成的moco.rb文件,添加内容

    require"formula"
    class Moco < Formula
    homepage"https://github.com/dreamhead/moco"
    url"http://central.maven.org/maven2/com/github/dreamhead/moco-runner/0.9.2/moco-runner-0.9.2-standalone.jar"
    sha1"a21445d7b275c48874ed7756477ade74de299e17"
    def install
    libexec.install"moco-runner-0.9.2-standalone.jar"
    bin.write_jar_script libexec/"moco-runner-0.9.2-standalone.jar","moco"
    end
    end

    这是一个基本的情况,我们下载对应地址的jar包,然后用命令moco链接。

    完成后运行brew install moco就可以看到效果。

    添加测试

    Homebrew提供了测试方法以测试Formula的可靠性,最简单的就是调用…