Java 并非一无是处 - 驾驭 JVM

工程 | Brian Dussault | 2015年2月11日 | ...

最近,James Ward 撰写了一篇很棒的博客文章,““Java 并非一无是处 - 你只是用错了它””,其中强调了企业 Java 开发人员在日常构建 Java 应用程序时面临的众多挑战。好消息是,摆脱开发困境比你想象的要容易得多。在过去的几年里,Spring 重塑了现代 Java 应用程序的构建方式,同时极大地提高了开发速度。在这篇文章中,我将以 James Ward 的博客文章为背景,解释 Spring 如何帮助开发人员驾驭 JVM(使用 Java),同时解决 James 提出的每个问题。

##即时开发环境设置很酷 在 James 的博客中,他断言“10 页的 Wiki 来设置开发环境很糟糕”。我们都在职业生涯的某个阶段创建过这些 Wiki 页面,并努力尝试保持其更新。这些 Wiki 长期以来一直是新团队成员的挫折源,因为它们通常充斥着过时的信息。好消息是,Spring Boot 的构建支持使自动化此过程变得非常容易。

从现有应用程序开始就像克隆源代码库并运行应用程序一样简单。Spring Boot 支持 Java 最流行的构建工具 Maven 和 Gradle。使用你喜欢的构建工具运行一个功能齐全的应用程序就像

Maven 示例

mvn spring-boot:run

Gradle 示例

gradle bootRun

由于 Spring Boot 应用程序是一个自包含的工作负载,它将应用程序代码、服务器和第三方依赖项组合到单个构建和部署单元(可执行 .jar 文件)中,因此开发团队可以确保获得简单、可重复的开发体验,而无论 IDE 如何。开发人员无需执行繁琐的环境设置说明,而是可以专注于构建优秀的应用程序。可以在构建外部执行 Spring Boot 应用程序,方法是执行

java -jar target/my-application-1.0.1-SNAPSHOT.jar

提示:想自己尝试一下吗?请按照 spring.io 上的众多入门指南进行操作。对于 Spring Boot 新手,一个很好的起点是使用 Spring Boot 构建应用程序指南。

##一致的部署环境很酷 James Ward 强调的下一个挑战是“为了最大程度地降低从开发到登台再到生产的构建风险,每个环境之间唯一应该改变的是配置”。手动修改部署工件是灾难的根源,最终会导致部署延迟或失败。应将环境特定的配置外部化,确保在开发中测试的相同代码成为进入生产的“黄金副本”。这是证明你测试的内容就是你部署内容的唯一经济高效的方式!

Spring Boot 使使用非常特殊的 PropertySource 顺序外部化配置变得轻而易举,该顺序旨在允许对值进行合理的覆盖。在你的项目中为本地开发提供默认配置,但在通过环境提升代码时覆盖这些值通常是可取的。Spring Boot 通过命令行参数、JNDI 属性、Java 系统属性、操作系统环境变量、配置文件、配置文件驱动的配置变体以及更多方式为外部化配置提供了全面的支持。Spring Boot 对环境变量的支持使得遵循十二要素应用程序配置最佳实践(严格分离代码与配置)变得轻而易举。

提示 1:当使用 Cloud Foundry 等云平台时,Spring Boot 应用程序可以利用Spring Cloud Connectors自动绑定到 Cloud Foundry 服务(如数据库和消息系统)。这具有减少应用程序需要维护的环境特定配置属性数量的优势,从而大大降低了在环境之间提升代码时出错的风险。

提示 2:好奇为什么十二要素应用程序很重要?请查看这篇博文为什么十二要素应用程序模式、微服务和 CloudFoundry 如此重要

##快速服务器启动很酷 Spring Boot 支持轻量级、可嵌入的容器/服务器,这些容器/服务器启动速度很快。一个简单的 REST 应用程序可以在短短 3 秒内启动。从 Spring Boot 1.2 开始,嵌入式应用程序服务器支持 Tomcat(默认容器)、Jetty 和 Undertow。Spring Boot 不仅支持领先的轻量级容器,而且还通过简化默认容器的交换来让开发人员完全控制这些决策。

以下 Gradle 构建配置支持全栈 Web 开发,包括对嵌入式 Tomcat 和 spring-webmvc 的支持。

Gradle 示例

...

apply plugin: 'java'

repositories { jcenter() }
dependencies {
    compile("org.springframework.boot:spring-boot-starter-web:1.2.0.RELEASE")
}

...

正如 James Ward 在他最初的博客文章中指出的那样,可以通过将单体部署分解为微服务来进一步提高启动时间。在这篇文章的后面,将更详细地讨论微服务主题(请参阅标题为“微服务架构很酷”的部分)。

托管依赖项很酷

现代开发人员需要能够让他们快速上手并减少摩擦的工具和技术。他们还要求使用模块化、轻量级和有见地的技术来优化生产力。Spring Boot 正致力于解决快速启动和运行的问题,同时极大地提高了开发速度。

正如 James Ward 正确指出的那样,“如果你的任何库依赖项没有由构建工具管理,那就会很糟糕”。Spring Boot 通过不仅支持现代构建技术,还提供称为启动器 POM的便捷依赖项描述符,将此最佳实践作为首要实践。启动器 POM 为常见开发工作负载提供依赖项组,你可以简单地将其包含在你的应用程序中。

要开始使用 Spring Boot,你可以将浏览器指向 Spring Initializer - http://start.spring.io。Spring Initializr 提供了一个基于 Web 的界面,允许开发人员选择应用程序/工作负载和相关依赖项。然后,它将生成一个带有构建支持的启动应用程序(支持 Maven POM、Maven 项目、Gradle 配置、Gradle 项目)。

Spring Initializr 的屏幕截图:Spring Initializer

对于喜欢使用命令行的开发人员,你可以通过发出以下命令来安装 Spring Boot CLI

curl http://start.spring.io/install.sh | sh

可以通过简单地发出以下命令来使用命令行初始化新项目

spring init --dependencies=web,data-jpa my-project

此初始化(通过 Spring Initializr 或 Boot CLI)的结果是一个完全可操作的应用程序,其中 Spring Boot 已包含并自动配置了所需的依赖项。

Spring IO Platform(包括 Spring Boot)还提供了 Spring Boot 启动器 POM 所管理的依赖项的超集。Spring IO 在整个 Spring 产品组合中设置依赖项版本,并且具有比 Spring Boot 更长的发布周期,从而为企业提供了经过测试且已知可以协同工作的依赖项版本的快照。Spring IO Platform 发行版不是库的单体下载,开发人员可以自由选择他们应用程序中需要的部分。Spring IO Platform 发行版包含 Spring 模块、测试库、日志框架、数据库管理、SQL/No-SQL 等版本的版本。对于希望以更渐进的节奏使用 Spring IO Platform 依赖项的企业来说,Spring IO 发行版非常理想。

以下 Gradle 配置演示了如何配置 Spring IO Platform 物料清单并利用 Spring Boot 的 Web 启动器 POM


buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'io.spring.gradle:dependency-management-plugin:0.3.0.RELEASE'
    }
}

apply plugin: 'io.spring.dependency-management'

repositories {
    mavenCentral()
}

dependencyManagement {
    imports {
        mavenBom 'io.spring.platform:platform-bom:1.1.0.RELEASE'
    }
}

dependencies {
    compile 'org.springframework.boot:spring-boot-starter-web'
}

##简短的开发/验证周期真的很酷 大多数现代应用程序都使用与后端服务通信的丰富用户界面构建。以这种方式构建应用程序的好处在于 UI 和服务器端逻辑之间有很强的关注点分离。大多数现代 IDE 都提供静态资源的动态重新加载,允许开发人员在不重新启动服务器的情况下查看更改。

Spring Boot 还支持 Thymeleaf、Freemarker 和 Groovy 等服务器端模板技术。Spring Boot 允许动态重新加载这些模板技术,而无需重新启动服务器。对于 Thymeleaf,这就像在 application.properties 文件中设置以下属性一样简单

spring.thymeleaf.cache: false

在服务器端,将单体应用程序分解为微服务将减少 Spring Boot 应用程序的启动时间(由于它使用轻量级嵌入式容器,因此启动时间已经非常快)。此外,Spring Boot 提供了对测试实用程序自动配置的支持。启用 Boot 的测试自动配置就像包含 spring-boot-starter-test 启动器 POM 一样简单。这将启用 Spring Test、JUnit、Hamcrest 和 Mockito 依赖项,从而可以轻松地将测试驱动开发 (TDD) 整合到日常工作流程中。TDD 使开发人员能够立即收到对其代码更改的反馈。

最后,JRebel 为类重新加载提供了全面的支持,并支持超过 80 个 Java 框架(包括 Spring)。请查看 Josh Long 和 Adam Koblentz 举办的网络研讨会Spring Boot 和 JRebel 6,以了解更多详细信息。

##微服务架构真棒 James声称“单体应用发布很糟糕”,对于大型或复杂的分布式系统来说,这句话再贴切不过了。大多数开发人员希望以更迭代的方式(敏捷)工作并更频繁地发布。微服务架构风格越来越受欢迎,因为它可以解决单体应用的挑战。对于刚接触微服务的人来说,Martin Fowler在他的博客中对这种架构风格进行了很好的描述。

在构建分布式应用程序(包括微服务风格的应用程序)时,会出现许多常见的系统模式。Spring Cloud通过提供开箱即用的服务来解决最常见的挑战,从而简化了采用这些模式的过程。Spring Cloud实现了诸如配置管理、服务发现、断路器、智能路由、微代理和控制总线等模式。Spring Boot使得将这些功能集成到您的应用程序中变得非常简单。

例如,Spring Cloud Netflix项目使使用Netflix的Eureka启动服务发现服务变得像这样简单


@SpringBootApplication 
@EnableEurekaServer

public class Application {
    public static void main(String[] args) {
        new SpringApplicationBuilder(Application.class).web(true).run(args);
    }

}

客户端应用程序可以通过简单地使用@EnableEurekaClient来注册为Eureka客户端


@SpringBootApplication
@EnableEurekaClient
@RestController
public class Application {

    @RequestMapping("/")
    public String home() {
        return "Hello world";
    }

    public static void main(String[] args) {
        new SpringApplicationBuilder(Application.class).web(true).run(args);
    }

}

提示1:Spring Cloud支持多种分布式处理模式。为了帮助您入门,请查看Spring Cloud示例 GitHub存储库。Dave Syer和Spencer Gibb的Spring Cloud、Spring Boot和Netflix OSS SpringOne研讨会是另一种了解和学习如何操作微服务架构风格的好方法。

提示2:如果您想构建超媒体风格的REST API,请务必查看入门指南使用REST访问JPA数据Spring Data REST将帮助您加速服务开发。Spring Data REST支持SQL和NoSQL存储库。

拥有允许您快速编写微服务的技术只是成功的一半。开发人员经常会遇到将代码部署到生产平台的诸多延迟。一些最常见的障碍包括手动部署、测试、基础设施配置和服务配置。持续交付旨在自动化将代码提升到生产环境的过程,同时最大程度地降低风险。这使组织能够对应用程序进行增量更改,从而使部署成为业务决策,而不是资源决策。这本身就是一个很大的话题,但我强烈推荐Matt Stine的演讲使用Spring和Cloud Foundry为PaaS开发微服务,它很好地突出了将敏捷工程实践与Pivotal Cloud Foundry的自动化相结合的好处。

##无状态应用程序真棒 James指出,“粘性会话和服务器状态通常是降低性能和弹性的最佳方法之一。会话状态(以传统的Servlet意义上)使得进行持续交付和水平扩展变得非常困难”。

从您的应用程序中移除会话状态可以极大地简化操作,允许应用程序重新部署、终止或扩展,而无需担心丢失会话数据。维护状态确实有一些有效的用例,例如共享身份验证状态,但是此状态应该持久化在应用程序外部(通常在高性能存储库中,例如NoSQL、分布式缓存,甚至内存数据存储)。外部化应用程序状态并不一定是一项繁重的工作,Spring Session提供了通用的基础架构,使此过程变得简单且可移植。Spring Session提供

  • 以供应商中立的方式支持集群
  • RESTful API支持 - 支持标头中的会话ID
  • 可插拔的策略来确定会话ID
  • 支持在WebSocket处于活动状态时保持HttpSession处于活动状态
  • 支持Redis和Hazelcast支持的会话存储
  • 能够在单个浏览器中管理多个同时会话(即类似于多个Google帐户支持)

使用Redis配置Spring Session就像这样简单

@EnableRedisHttpSession
public class Config {

    @Bean
    public JedisConnectionFactory connectionFactory() {
        return new JedisConnectionFactory();
    }
}

提示:Spring Session 1.0最近发布了GA版本,因此请尝试Spring Session示例以查看其全部功能。Dave Syer最近发表了一篇名为API网关模式:Angular JS和Spring Security 第四部分的博客文章,其中详细介绍了共享身份验证状态用例。强烈推荐阅读!

最后,如果您使用的是Pivotal Cloud Foundry,则Cloud Foundry Java构建包提供了另一个选项,可以通过自动配置的CF会话状态存储轻松地外部化状态。查看这篇博文以了解更多详细信息。

##非阻塞应用程序真棒许多现代应用程序架构可以从异步和非阻塞请求处理中获益匪浅。这些用例可能包括组合多个后端服务调用和WebSocket风格的应用程序。

Project Reactor(Spring IO Platform的一部分)为构建这些异步、非阻塞应用程序提供了基础。在2.0版本中,Reactor将提供Reactive Streams规范的完整实现,这将开启与其他Reactive Streams实现(如Akka StreamsRatpackRxJava)的集成。

以下代码片段显示了如何使用Reactive Streams API创建流、向其中添加业务逻辑,然后将数据发布到其中

// by default Streams use the Disruptor RingBufferDispatcher
Broadcaster<String> helloStream = Streams.broadcast(env);

helloStream.map(s -> "Hello " + s + "!")
           .consume(log::info);

helloStream.onNext("World");

提示:Spring Boot支持Project Reactor,使入门变得简单。按照使用Reactor创建异步、事件驱动的应用程序入门指南中的步骤创建您的第一个响应式应用程序。此外,请务必查看网络研讨会使用Reactor构建异步、非阻塞微服务

Spring Framework 4引入了对WebSocket风格的事件驱动应用程序的支持。这种务实的做法超越了JSR-356,包括带有SockJS的客户端回退选项、对消息传递子协议(STOMP)的支持、安全性(Spring Security 4)、消息代理支持、基于Reactor的MessageChannel用于消息传递、客户端断开连接处理以及熟悉的Spring编程模型。

提示:Spring Boot使配置WebSocket应用程序变得轻而易举。按照使用WebSocket构建交互式Web应用程序指南中的步骤开始操作。

Java语言真棒

Spring Boot为开发人员提供了使用Java 6、7、8以及Groovy构建下一代应用程序的选项。在James的帖子中,他指出“Java语言有点糟糕”,但是随着Java 8的发布,Java得到了极大的发展,并提供了许多强大的语言特性,可以提高生产力。一些很棒的Java 8特性包括对Lambda表达式、流和并发改进的支持。Spring Boot使使用Java 8或Groovy变得轻而易举。

提示:如果您不熟悉Java 8的功能,我强烈推荐Venkat Subramaniam的书Java中的函数式编程:利用Java 8 Lambda表达式的强大功能以及他的SpringOne2GX 2014演讲

##结论构建现代Java应用程序不必是一件痛苦的事情。Spring Boot消除了构建应用程序的繁琐步骤,使Java再次变得有趣。Spring消除了应用程序各个层面的样板代码 - 业务逻辑(Spring Foundation项目)、配置和运行时(Spring Boot)以及分布式系统模式(Spring Cloud)。入门最好的方法是深入研究Spring的入门指南并将应用程序部署到Pivotal Web Services(Cloud Foundry的公共托管版本,免费试用60天)。

获取Spring新闻

关注Spring新闻

订阅

领先一步

VMware提供培训和认证,助您快速提升。

了解更多

获取支持

Tanzu Spring在一个简单的订阅中提供OpenJDK™、Spring和Apache Tomcat®的支持和二进制文件。

了解更多

即将举行的活动

查看Spring社区中所有即将举行的活动。

查看全部