2017 年不容错过的 10+ 个开源 Java 库

liangshe093u 7年前
   <p>这些开源库非常棒,我已经将它们整理成参考清单,附上简短的功能清单连同案例一同分享。</p>    <p><strong>Guice</strong></p>    <p>Guice(音同“juice”)是谷歌开发的一个轻量级的依赖注入框架,支持 java 6 及以上版本。</p>    <pre>  <code class="language-java"># Typical dependency injection  public class DatabaseTransactionLogProvider implements Provider<TransactionLog> {    @Inject Connection connection;      public TransactionLog get() {      return new DatabaseTransactionLog(connection);    }  }</code></pre>    <pre>  <code class="language-java"># FactoryModuleBuilder generates factory using your interface  public interface PaymentFactory {     Payment create(Date startDate, Money amount);   }</code></pre>    <p><strong>OkHttp</strong></p>    <p>HTTP 是现代应用程序实现互联的机制。数据和媒体的交互都基于此。高效的 http 机制能提升你的下载速度和节约带宽。</p>    <p>OkHttp 作为一个HTTP客户端,默认:</p>    <p>HTTP/2 服务默认发往同一台主机的所有请求共用一个套接字。</p>    <p>连接池减少请求的延迟(如 HTTP/2 不可用)。</p>    <p>gzip 压缩下载大小可见。</p>    <p>通过响应缓存完全避免了网络的重复请求。</p>    <pre>  <code class="language-java">OkHttpClient client = new OkHttpClient();String run(String url) throws IOException {    Request request = new Request.Builder()        .url(url)        .build();      Response response = client.newCall(request).execute();    return response.body().string();  }</code></pre>    <p><strong>Retrofit</strong></p>    <p>来自 Square 公司的 HTTP 客户端,类型案例,可用于 Android 和 Java。Retrofit 会按照 HTTP API 生成 Java 接口。</p>    <pre>  <code class="language-java">public interface GitHubService {      @GET("users/{user}/repos")      Call<List<Repo>listRepos(@Path("user") String user);  }</code></pre>    <p>Retrofit 类实现 GitHubService 接口。</p>    <pre>  <code class="language-java">Retrofit retrofit = new Retrofit.Builder()      .baseUrl("https://api.github.com/")      .build();     GitHubService service = retrofit.create(GitHubService.class);</code></pre>    <p>来自 GitHubService 的每个 Call 都会向远端 Web 服务器发送一个同步或异步的 HTTP 请求。</p>    <pre>  <code class="language-java">Call<List<Repo>> repos = service.listRepos("octocat");</code></pre>    <p><strong>JDeferred</strong></p>    <p>Java 的 Deferred/Promise 库,与 JQuery 的 Deferred/Promise 相似</p>    <ul>     <li>Deferred 和 Promise 对象</li>     <li>Promise 回调:.then(…), .done(…), .fail(…), .progress(…), .always(…)</li>     <li>同时处理多个 Promise - .when(p1, p2, p3, …).then(…)</li>     <li>Callable 和 Runnable - wrappers.when(new Runnable() {…})</li>     <li>使用执行服务(ExecutorService)</li>     <li>Java Generics 支持: Deferred<Integer, Exception, Doubledeferred;, deferred.resolve(10);, deferred.reject(new Exception());,deferred.notify(0.80);,</li>     <li>支持 Android</li>     <li>可以使用 Java 8 Lambda</li>    </ul>    <p><strong>RxJava</strong></p>    <p>RxJava – JVM 的 Reactive Extensions (响应式扩展) – 一个用于 Java VM 的库,它通过可观测序列构成异步及基于事件的程序。</p>    <p>它扩展了观察者模式以支持数据/事件流,并添加了操作符,使你能以申明的方式组合处理序列,对一些事情进行抽象,比如低级线程、同步、线程安全和并发数据结构。</p>    <p>RxJava 常见的应用是在后台线程运行一些计算或网络请求,并在 UI 线程显示结果(或错误):</p>    <pre>  <code class="language-java">Flowable.fromCallable(() -{      Thread.sleep(1000); //  imitate expensive computation    return "Done";  })    .subscribeOn(Schedulers.io())    .observeOn(Schedulers.single())    .subscribe(System.out::println, Throwable::printStackTrace);     Thread.sleep(2000); // <--- wait for the flow to finish</code></pre>    <p><strong>MBassador</strong></p>    <p>MBassador 是一个轻量级、高性能的事件总线,它实现了发布/订阅模式。它的设计目的是易用、功能丰富和可扩展,同时保持资源的高效利用和良好性能。</p>    <p>MBassador 高性能的核心在于一个专用的数据结构,这个数据结构提供了非阻塞读功能以及在写时最小化锁竞争,因此它将并行读/写访问造成的性能损耗降到最低。</p>    <ul>     <li>注解驱动</li>     <li>分发的所有东西都会考虑类型层级</li>     <li>同步和异步的消息分发</li>     <li>可配置的引用类型</li>     <li>消息过滤</li>     <li>封装消息</li>     <li>多级优先层次处理</li>     <li>自定义错误处理</li>    </ul>    <pre>  <code class="language-java">// Define your listener  class SimpleFileListener{      @Handler           public void handle(File msg){        // do something with the file          }  }    // somewhere else in your codeMBassador bus = new MBassador();  Object listener = new SimpleFileListener();  bus.subscribe (listener);  bus.post(new File("/tmp/smallfile.csv")).now();  bus.post(new File("/tmp/bigfile.csv")).asynchronously();</code></pre>    <p><strong>Project Lombok</strong></p>    <p>通过注解来减少 Java 中的重复性代码,比如 getter 和 setter、非空检查、生成 Builder 等。</p>    <ul>     <li>val - 终级解决方案!简化 final 局部变量定义。</li>     <li>@NonNull - 或者:了解我是怎样停止担心并爱上 NullPointerException 的。</li>     <li>@Cleanup - 怎么资源管理:方便而安全地调用 close() 方法。</li>     <li>@Getter / @Setter - 不再需要写像 public int getFoo() {return foo;} 这样的代码。</li>     <li>@ToString - 不用启动调试器就能观察字段值:让 Lombok 为你生成 toString!</li>     <li>@EqualsAndHashCode - 让等值比较变得容易:在项目中由字段实现 hashCode 和 equals。</li>     <li>@NoArgsConstructor, @RequiredArgsConstructor and @AllArgsConstructor - 定制构造器:生成无参构造函数,对每个 final/非空 字段产生构造器,对每个字段产生构造器。</li>     <li>@Data - 它合并所有注解:相当于对所有字段应用 @ToString、@EqualsAndHashCode、@Getter,并对所有非 final 字段应用 @Setter,以及应用 @RequiredArgsConstructor!</li>     <li>@Value - 简单创意不可变类。</li>     <li>@Builder - … 一切都很简单:简单直接地创建对象的 API!</li>     <li>@SneakyThrows - 大胆的抛出以前不能轻易抛出的异常!</li>     <li>@Synchronized - 正确的同步:不要暴露你的锁。</li>     <li>@Getter(lazy=true) 懒加载是种美德!</li>     <li>@Log - 舰长日志,星历 24435.7: “这是什么行?”</li>    </ul>    <p><strong>Simple Logging Facade for Java</strong></p>    <p>Simple Logging Facade for Java(SLF4J)是对各种日志框架(比如 java.util.logging、logback、log4j 等)的简单门面或者抽象,它让用户可以在开发时使用喜欢的日志框架。</p>    <p>简单地说,库和其它嵌入式组件考虑使用 SLF4J 来记录日志,因为它们不能把自己选用的日志框架强加给用户。另一方面,独立的应用程序就不必在意是否使用 SLF4J。独立的应用程序可以直接使用自己选用的日志框架。在使用 logback 的时候会有一个争议,因为它是使用 SLF4J 来提供日志 API 的。</p>    <p><strong>JUnitParams</strong></p>    <p>参数化测试</p>    <pre>  <code class="language-java">@Test  @Parameters({"17, false",                "22, true" })  public void personIsAdult(int age, boolean valid) throws Exception {    assertThat(new Person(age).isAdult(), is(valid));  }</code></pre>    <p>与标准 JUnit Parametrised 运行器的主要区别:</p>    <ul>     <li>更明确 - 参数是测试方法的参数,而不是类中定义的字段</li>     <li>更少代码 - 不需要通过构造器来设置参数</li>     <li>可以在一个类里混合参数化或非参数化的方法</li>     <li>参数可以由 CSV 文本提供,也可以由专门的参数提供类提供</li>     <li>参数提供类可以有任意多个参数提供方法,所以你可以对不同的情况分组</li>     <li>可以由测试方法提供参数(而不是其它类或静态方法)</li>     <li>可以在 IDE 中看到实际的参数值(JUnit 的 Parametrised 中只有连续编号的参数)</li>    </ul>    <p><strong>Mockito</strong></p>    <p>Java 中不错的 mock 框架</p>    <pre>  <code class="language-java">//You can mock concrete classes, not just interfaces  LinkedList mockedList = mock(LinkedList.class);    //stubbing  when(mockedList.get(0)).thenReturn("first");  when(mockedList.get(1)).thenThrow(new RuntimeException());    //following prints "first"  System.out.println(mockedList.get(0));    //following throws runtime exception  System.out.println(mockedList.get(1));    //following prints "null" because get(999) was not stubbed  System.out.println(mockedList.get(999));    //Although it is possible to verify a stubbed invocation, usually it's just redundant  //If your code cares what get(0) returns, then something else breaks (often even before verify() gets executed).  //If your code doesn't care what get(0) returns, then it should not be stubbed. Not convinced? See here.  verify(mockedList).get(0);</code></pre>    <p><strong>Jukito</strong></p>    <ul>     <li>结合了 JUnit、Guice 和 Mockito 的力量,听起来很有技术含量。</li>     <li>大大降低了自动 mock 的古板,使阅读测试变得容易</li>     <li>在测试对象的 API 变化时更有弹性</li>     <li>通过 @Inject 注解的字段可以自动注入</li>     <li>更容易将对象绑在一起,因此可以将单元测试扩展到部分集成测试</li>    </ul>    <pre>  <code class="language-java">@RunWith(JukitoRunner.class)  public class EmailSystemTest {      @Inject EmailSystemImpl emailSystem;    Email dummyEmail;      @Before    public void setupMocks(        IncomingEmails incomingEmails,        EmailFactory factory) {      dummyEmail = factory.createDummy();      when(incomingEmails.count()).thenReturn(1);      when(incomingEmails.get(0)).thenReturn(dummyEmail);    }      @Test    public void shouldFetchEmailWhenStarting(        EmailView emailView) {      // WHEN      emailSystem.start();        // THEN      verify(emailView).addEmail(dummyEmail);    }  }</code></pre>    <p><strong>Awaitility</strong></p>    <p>Awaitility 是一个小型的 DSL(领域专用语言),用于将异步操作同步化。</p>    <p>测试异步系统是件难事,不仅需要处理线程、超时和并发问题,测试代码的意图还可能被这些细节所掩盖。Awaitility 是一个 DSL,它能以一个简洁易读的方式表达异步系统要做的事情。</p>    <pre>  <code class="language-java">@Test  public void updatesCustomerStatus() throws Exception {      // Publish an asynchronous event:      publishEvent(updateCustomerStatusEvent);      // Awaitility lets you wait until the asynchronous operation completes:      await().atMost(5, SECONDS).until(customerStatusIsUpdated());      ...  }</code></pre>    <p><strong>Spock</strong></p>    <p>用于企业的测试和规范框架。</p>    <pre>  <code class="language-java">class HelloSpockSpec extends spock.lang.Specification {    def "length of Spock's and his friends' names"() {      expect:      name.size() == length        where:      name     | length      "Spock"  | 5      "Kirk"   | 4      "Scotty" | 6    }  }</code></pre>    <p><strong>WireMock</strong></p>    <ul>     <li>模拟 HTTP 服务的工具</li>     <li>HTTP 响应头,匹配 URL、标题和正文模式</li>     <li>验证请求</li>     <li>在单元测试中运行、独立运行或作为 WAR 应用运行</li>     <li>通过 Java API、JSON 文件或者通过 HTTP 获取的 JSON 来进行配置</li>     <li>录制/回放存根</li>     <li>故障注入</li>     <li>针对每个请求的条件代理</li>     <li>浏览器代码用于注入请求或更换请求</li>     <li>有状态的行为</li>     <li>可配置响应延迟</li>    </ul>    <pre>  <code class="language-java">{      "request": {          "method": "GET",          "url": "/some/thing"      },      "response": {          "status": 200,          "statusMessage": "Everything was just fine!"      }  }</code></pre>    <p>原文:Java libraries you can't miss in 2017</p>    <p>链接:http://blog.jevsejev.io/2017/02/19/java-libraries-you-cannot-miss-in-2017/</p>    <p>译者:边城, Tocy, butta</p>    <p> </p>    <p>来自:http://www.iteye.com/news/32170</p>    <p> </p>