Spring Data REST 1.0.0.M2 发布

发布 | Jon Brisbin | 2012 年 5 月 16 日 | ...

紧随Spring Data JPA 1.1.0 GA 版本发布之后,我很高兴地宣布 Spring Data REST 的里程碑版本 2 发布。除了许多错误修复之外,此 M2 版本还包含了 Spring Data REST 导出器功能的主要更新。

新功能包括

  • 查询方法支持 - Spring Data REST 1.0.0.M2 包括对调用存储库接口的查询方法的支持。结果作为指向顶级资源的链接返回。
  • 全面的验证支持 - 除了 JSR-303 验证之外,Spring Data REST 导出器还识别在 ApplicationContext 中声明的 Spring Validator bean 以提供丰富的验证支持。您的 Validator bean 可以执行任何操作,甚至可以查找其他数据以验证对象图的完整性。
  • ApplicationEvent 处理 - 导出器的验证支持构建在 Spring ApplicationEvent 机制之上。在每个保存或删除操作之前和之后都会发出 ApplicationEvents,允许您的代码连接到这些生命周期事件并触发其他操作。
  • 基于注解的 URL 配置 - 有一个新的注解:@RestResource,您可以将其放在存储库接口或存储库的查询方法上,以影响导出资源的 URL 以及生成的指向该资源的链接的“rel”属性。

入门 Web 应用程序 | Wiki | 发行说明

要了解有关该项目的更多信息,请访问 Spring Data REST 的主页,或访问Github 存储库下载源代码。

Spring MVC 3.2 预览:聊天示例

工程 | Rossen Stoyanchev | 2012 年 5 月 16 日 | ...

上次更新于 2012 年 11 月 5 日(Spring MVC 3.2 RC1)

之前的博客文章中,我介绍了 Spring MVC 3.2 中基于 Servlet 3 的异步功能,并使用了spring-mvc-showcase和 Spring AMQP 的股票示例来演示它。这篇文章介绍了一个聊天示例,其中外部事件不是 AMQP 消息,而是带有聊天消息的 HTTP POST 请求。在文章的第二部分,我将切换到一个分布式聊天,其中事件是Redis 通知。

聊天不是 Web 应用程序的常见需求。但是,它是一个只能通过实时通知才能满足的需求的很好的例子。它比电子邮件或状态警报对时间延迟更敏感,并且在浏览器中与朋友聊天、在网络研讨会期间与同事聊天或在购物网站上与真人聊天并不罕见。您可以想象其他类型的在线协作。

示例

spring-mvc-chat示例可在 Github 上获得。虽然不是本文的重点,但客户端使用Thymeleafknockout.js和 jQuery。Thymeleaf 是 JSP 的一个极好的替代方案,它支持带有预览功能的干净 HTML 模板,允许设计人员双击 HTML 模板并查看它,这与需要 Servlet 容器的 JSP 不同。knockout.js是一个客户端 MVC 框架,非常适合将行为附加到 HTML 元素。要快速了解它,请按照其出色的教程之一进行操作。jQuery 用于 DOM 脚本和 Ajax 请求。

ChatController

ChatController公开了获取和发布聊天消息的操作。以下是获取消息的方法


@RequestMapping(method=RequestMethod.GET)
@ResponseBody
public DeferredResult<List<String>> getMessages(@RequestParam int messageIndex) {

  final DeferredResult<List<String>> deferredResult = new DeferredResult<List<String>>(null, Collections.emptyList());
  this.chatRequests.put(deferredResult, messageIndex);

  deferredResult.onCompletion(new Runnable() {
    @Override
    public void run() {
      chatRequests.remove(deferredResult);
    }
  });

  List<String> messages = this.chatRepository.getMessages…

Spring AMQP 1.1.0 发布

发布 | Gary Russell | 2012 年 5 月 16 日 | ...

Spring AMQP 将 Spring 编程模型的熟悉优势应用于 AMQP,特别是 Rabbit MQ。

我们很高兴地宣布 Spring AMQP for Java 1.1.0 版本的正式发布,该版本支持 RabbitMQ 2.8.x 客户端,并提供以下功能...

  • 镜像队列
  • 代理故障转移
  • 发布者确认
  • 返回
  • 联合交换
  • ...以及更多

有关更多信息,请参阅项目主页

Spring Integration 2.2.0 里程碑版本 1 发布支持此 spring-amqp 版本的功能。

Spring MVC 3.2 预览:将长轮询添加到现有 Web 应用程序

工程 | Rossen Stoyanchev | 2012 年 5 月 14 日 | ...

上次更新于 2012 年 11 月 5 日(Spring MVC 3.2 RC1)

在我的上一篇文章中,我讨论了如何通过返回Callable来使 Spring MVC 控制器方法异步,然后由 Spring MVC 在单独的线程中调用该方法。

但是,如果异步处理取决于在 Spring MVC 未知线程中接收一些外部事件怎么办——例如,接收 JMS 消息、AMQP 消息、Redis 发布-订阅通知、Spring Integration 事件等?我将通过修改来自Spring AMQP项目的现有示例来探索这种情况。

示例

Spring AMQP 有一个股票交易示例,其中 QuoteController通过 Spring AMQP 的RabbitTemplate发送交易执行消息,并通过 Spring AMQP 的 RabbitMQ侦听器容器以消息驱动的 POJO 样式接收交易确认和价格报价消息。

在浏览器中,该示例使用轮询来显示价格报价。对于交易,初始请求提交交易并返回确认 ID,然后使用该 ID 轮询最终确认。我已更新该示例以利用 Spring 3.2 Servlet 3 异步支持。master分支包含更改之前的代码,而spring-mvc-async分支包含更改之后的代码。下面的图像显示了对价格报价请求频率的影响(使用 Chrome 开发者工具)

更改前:传统轮询

更改后:长轮询

如您所见,使用常规轮询,新请求非常频繁地发送(相隔几毫秒),而使用长轮询,请求可以相隔 5 秒、10 秒、20 秒或更长时间——显着减少了请求总数,而不会损失延迟,即新价格报价出现在浏览器中的时间。

获取报价

那么需要进行哪些更改?从客户端的角度来看,传统轮询和长轮询是无法区分的,因此 HTML 和 JavaScript 没有改变。从服务器的角度来看,必须将请求保持到新的报价到达为止。以下是控制器处理报价请求的方式



// Class field
private Map<String, DeferredResult> suspendedTradeRequests = new ConcurrentHashMap<String, DeferredResult>();

...

@RequestMapping("/quotes")
@ResponseBody
public DeferredResult<List<Quote>> quotes(@RequestParam(required = false) Long timestamp) {

  final DeferredResult<List<Quote>> result = new DeferredResult<List<Quote>>(null, Collections.emptyList());
  this.quoteRequests.put(result, timestamp);

  result.onCompletion(new Runnable() {
    public void run() {
      quoteRequests…

Spring Mobile 1.0.0 发布

发布 | Roy Clarkson | 2012 年 5 月 14 日 | ...

尊敬的 Spring 社区:

我们很高兴地宣布Spring Mobile 1.0正式发布!

Spring Mobile 为 Spring MVC 提供扩展,有助于开发跨平台移动 Web 应用程序。

此 GA 版本包含自 RC2 版本以来的少量修复和更改。请参阅更改日志参考手册以获取更多信息。

要检索软件,请下载发行版,或将Maven 工件添加到您的项目中。示例应用程序可在github.com/SpringSource/spring-mobile-samples找到。

我们要感谢 Scott Rossillo、Tristan Burch、Craig Walls 和 Keith Donald 对此 GA 版本做出的贡献,我们期待与他们以及 Spring 社区的其他成员合作开发未来的版本。如果您正在构建移动 Web 应用程序,我们鼓励您试用 Spring Mobile 1.0 并与我们合作开发该项目的下一个版本。

视频:使用 Spring Integration 的更多实用技巧

新闻 | Adam Fitzgerald | 2012 年 5 月 11 日 | ...

此视频是对Oleg Zhurakousky成功举办的Spring Integration 提示和技巧网络研讨会的后续课程,探讨了更深入和更复杂的集成模式。此课程的问题来自实际的客户参与以及在 Spring Integration 论坛上最常被问到的问题。在本期“实用技巧”中,Oleg 涵盖了企业集成的高级主题,例如高级聚合和重新排序、异步消息流、消息 ID 自定义、内容丰富和高级消息路由等。此视频基于Oleg 在 2011 年 SpringOne 2GX 大会上发表的非常成功的演讲的改进版本。

要复习消息传递和 Spring Integration 的基础知识,请观看 Mark Fisher 制作的此消息驱动架构视频,并观看本系列中的上一期视频:Spring Integration 提示和技巧

如果您觉得此演示文稿有用,请点赞,并订阅SpringSourceDev频道以查看其他录制内容和屏幕截图。

Spring MVC 3.2 预览:使控制器方法异步

工程 | Rossen Stoyanchev | 2012年5月10日 | ...

上次更新于 2012 年 11 月 5 日(Spring MVC 3.2 RC1)

之前文章中,我介绍了Spring MVC 3.2 中基于 Servlet 3 的异步功能,并讨论了实时更新的技术。在这篇文章中,我将深入探讨更多技术细节,并讨论异步处理如何融入 Spring MVC 请求生命周期。

作为快速提醒,您可以通过将其更改为返回Callable来使任何现有的控制器方法异步。例如,返回视图名称的控制器方法可以改为返回Callable<String>。返回名为Person的对象的@ResponseBody可以改为返回Callable<Person>。对于任何其他控制器返回值类型,情况也是如此。

一个核心思想是,您已经了解的关于控制器方法如何工作的所有内容尽可能保持不变,只是其余的处理将在另一个线程中发生。在异步执行方面,保持简单很重要。正如您将看到的,即使在这种看似简单的编程模型更改中,也有很多需要考虑的地方。

spring-mvc-showcase已更新至 Spring MVC 3.2。请查看CallableController。正如您可能预期的那样,@ResponseBody@ResponseStatus等方法注释也适用于Callable的返回值。从Callable引发的异常将像控制器引发异常一样处理,在本例中使用@ExceptionHandler方法。以此类推。

如果您通过浏览器中的“异步请求”选项卡执行其中一个CallableController方法,您应该会看到类似于以下内容的输出

08:25:15 [http-bio-8080-exec-10] DispatcherServlet - DispatcherServlet with name 'appServlet' processing GET request for [...]
08:25:15 [http-bio-8080-exec-10] RequestMappingHandlerMapping - Looking up handler method for path /async/callable/view
08:25:15 [http-bio-8080-exec-10] RequestMappingHandlerMapping - Returning handler method [...]
08:25:15 [http-bio-8080-exec-10] WebAsyncManager - Concurrent handling starting for GET [...]
08:25:15 [http-bio-8080-exec-10] DispatcherServlet - Leaving response open for concurrent…

使用 Cloud Foundry Workers 与 Spring

工程 | Josh Long | 2012年5月9日 | ...

您无疑已经阅读了Jennifer Hickey的精彩博文,这些博文介绍了 Cloud Foundry workers,它们在设置Ruby Resque 后台作业中的应用,以及今天发布的文章介绍了 Spring 支持

Spring 开发人员的关键要点

  1. 您需要使用gem update vmc更新您的vmc版本。
  2. Cloud Foundry workers 允许您运行public static void main作业。也就是说,Cloud Foundry worker 本质上是一个进程,比 Web 应用程序更低级,这自然映射到许多所谓的后台作业。
  3. 您需要提供 Cloud Foundry 将运行的命令。您可以提供您希望它使用的java命令,但更简单的方法是提供一个 shell 脚本,让 Cloud Foundry 为您运行该 shell 脚本。您提供的命令应该使用$JAVA_OPTS,Cloud Foundry 已经提供了它以确保一致的内存使用和 JVM 设置。
  4. 有多种方法可以自动化 Cloud Foundry 可部署应用程序的创建。如果您使用 Maven,那么org.codehaus.mojo:appassembler-maven-plugin插件将帮助您创建一个启动脚本并打包您的.jars以方便部署,以及指定一个入口点类。
  5. 其他一切都基本相同。当您对 Java .jar项目执行vmc push时,Cloud Foundry 会询问您该应用程序是否是独立应用程序。确认后,它将引导您完成后续设置。

因此,让我们看看一些常见的架构和安排,它们使用 Cloud Foundry workers 变得更容易和更自然。我们将根据 Spring 框架和两个相关项目(Spring IntegrationSpring Batch)来查看这些模式,这两个框架在 Web 应用程序内部和外部都非常活跃。正如我们将看到的,这两个框架都支持解耦和改进的可组合性。我们将什么发生与何时发生分离,并将什么发生与哪里发生分离,这两者都是为了释放前端的容量。

我有一个时间表需要遵守!

我经常被问到一个问题:如何在 Cloud Foundry 上进行作业调度?Cloud Foundry 支持 Spring 应用程序,当然 Spring 一直以来都支持企业级调度抽象,例如Quartz和 Spring 3.0 的@Scheduled注释。@Scheduled非常棒,因为它非常易于添加到现有应用程序中。在最简单的情况下,您将@EnableScheduling添加到您的 Java 配置中,或将<task:annotation-driven/>添加到您的 XML 中,然后在代码中使用@Scheduled注释。这在企业应用程序中是一件非常自然的事情——也许您有一个需要运行的分析或报表流程?一些长时间运行的批处理流程?我编写了一个示例,演示了如何使用@Scheduled运行Spring BatchJob。Spring Batch 作业本身是一个工作线程,它与一个 Web 服务一起工作,该 Web 服务的服务水平协议(SLA)较差,不适合实时使用。在 Spring Batch 中处理工作更安全、更简洁,因为它的恢复和重试功能可以弥补任何网络中断、网络延迟等带来的影响。我将您引导至代码示例以获取大部分详细信息,我们只查看入口点,然后查看将应用程序部署到 Cloud Foundry。

					    
// set to every 10s for testing.
@Scheduled(fixedRate = 10 * 1000)
public void runNightlyStockPriceRecorder() throws Throwable {
	JobParameters params = new JobParametersBuilder()
		.addDate("date", new Date())
		.toJobParameters();
	JobExecution jobExecution = jobLauncher.run(job, params);
	BatchStatus batchStatus = jobExecution.getStatus();
	while (batchStatus.isRunning()) {
		logger.info("Still running...");
		Thread.sleep(1000);
	}
	logger.info(String.format("Exit status: %s", jobExecution.getExitStatus().getExitCode()));
	JobInstance jobInstance = jobExecution.getJobInstance…

Spring MVC 3.2 预览:实时更新的技术

工程 | Rossen Stoyanchev | 2012年5月8日 | ...

上次更新于 2012 年 11 月 5 日(Spring MVC 3.2 RC1)

在我的上一篇文章中,我介绍了Spring MVC 3.2 中新的基于 Servlet 3 的异步支持,并讨论了长时间运行的请求。异步处理的第二个非常重要的动机是浏览器需要接收实时更新。示例包括在浏览器中聊天、股票行情、状态更新、实时体育赛事结果等。当然,并非所有示例都同样延迟敏感,但它们都具有类似的需求。

在标准的 HTTP 请求-响应语义中,浏览器发起请求,服务器发送响应,这意味着服务器只有在收到浏览器的请求后才能发送新信息。已经发展出几种方法,包括传统轮询长轮询HTTP 流,最近我们还有WebSocket协议。

传统轮询

浏览器不断发送请求以检查是否有新信息,服务器每次都会立即响应。这适合可以以合理稀疏的间隔进行轮询的场景。例如,邮件客户端可以每 10 分钟检查一次新邮件。它很简单,而且有效。但是,当必须尽快显示新信息时,这种方法效率低下,在这种情况下,轮询必须非常频繁。

长轮询

浏览器不断发送请求,但服务器只有在有新信息要发送时才会响应。从客户端的角度来看,这与传统轮询相同。从服务器的角度来看,这与长时间运行的请求非常相似,并且可以使用第 1 部分中讨论的技术进行扩展。

响应可以保持打开多长时间?浏览器设置为在 5 分钟后超时,并且网络中介(如代理)可以更早超时。因此,即使没有新的信息到达,长轮询请求也应该定期完成,以允许浏览器发送新的请求。这IETF 文档建议使用 30 到 120 秒之间的超时值,但实际使用的值可能取决于您对将浏览器与服务器隔开的网络中介的控制程度。

长轮询可以显著减少接收低延迟信息更新所需的请求数量,尤其是在新信息以不规则间隔提供的情况下。但是,更新越频繁,它就越接近传统轮询。

HTTP 流

浏览器向服务器发送请求,服务器在有信息要发送时响应。但是,与长轮询不同的是,服务器保持响应打开,并在新更新到达时继续发送更多更新。这种方法消除了轮询的需要,但也与典型的 HTTP 请求-响应语义有更大的偏离。例如,客户端和服务器需要就如何解释响应流达成一致,以便客户端知道一个更新在哪里结束,另一个更新在哪里开始。此外,网络中介可以缓存响应流,这会破坏这种方法的意图。这就是为什么今天长轮询更常用。

WebSocket 协议

浏览器向服务器发送 HTTP 请求以切换到 WebSocket 协议,服务器通过确认升级进行响应。此后,浏览器和服务器可以通过 TCP 套接字双向发送数据帧。

WebSocket 协议旨在取代轮询的需求,特别适用于需要在浏览器和服务器之间高频率交换消息的场景。通过 HTTP 的初始握手确保 WebSocket 请求能够通过防火墙。但是,也存在重大挑战,因为大多数已部署的浏览器不支持 WebSockets,并且在通过网络中介时存在更多问题

WebSockets 围绕文本或二进制消息的双向交换展开。它导致了一种与基于 RESTful 的 HTTP 架构显著不同的方法。事实上,需要在 WebSockets 之上使用另一种协议,例如 XMPP、AMQP、STOMP 或其他协议,哪一个(或哪些)将成为主流还有待观察。

IETF 已经标准化了WebSocket 协议,而W3C 正在标准化的最后阶段中WebSocket API。已经出现了一些 Java 实现,包括 Jetty 和 Tomcat 等 servlet 容器。Servlet 3.1 规范可能会支持初始 WebSocket 升级请求,而单独的JSR-356 将定义基于 Java 的 WebSocket API。

回到 Spring MVC 3.2,Servlet 3 异步特性可用于长时间运行的请求以及 HTTP 流,Filip Hanik提到这些技术为“客户端 AJAX 调用的服务器版本”。至于 WebSockets,Spring 3.2 中尚不支持,但很可能会包含在 Spring 3.3 中。您可以关注SPR-9356 以获取进度更新。

下一篇文章 将转向示例代码,并更详细地解释新的 Spring MVC 3.2 功能。

Spring MVC 3.2 预览:引入 Servlet 3,异步支持

工程 | Rossen Stoyanchev | 2012 年 5 月 7 日 | ...

上次更新于 2012 年 11 月 5 日(Spring MVC 3.2 RC1)

概述

Spring MVC 3.2 引入了基于 Servlet 3 的异步请求处理。这是涵盖此新功能的几篇博文中的一篇,并提供理解如何以及为何使用它的上下文。

早期版本的的主要目的是寻求反馈。自从 3.2 M1 版本发布后首次发布以来,我们在这里和JIRA 中都收到了大量反馈。感谢所有尝试并发表评论的人!已经进行了许多更改,并且仍然有时间提供更多反馈!

概览

从编程模型的角度来看,新功能看起来非常简单。控制器方法现在可以返回一个java.util.concurrent.Callable 以异步完成处理。Spring MVC 然后将在单独的线程中使用TaskExecutor 调用Callable。以下是在之前的代码片段


// Before
@RequestMapping(method=RequestMethod.POST)
public String processUpload(final MultipartFile file) {
    // ...
    return "someView";
}

// After
@RequestMapping(method=RequestMethod.POST)
public Callable<String> processUpload(final MultipartFile file) {

  return new Callable<String>() {
    public Object call() throws Exception {
      // ...
      return "someView";
    }
  };
}

控制器方法还可以返回一个DeferredResult(Spring MVC 3.2 中的新类型)以在 Spring MVC 未知的线程中完成处理。例如,对 JMS 或 AMQP 消息、Redis 通知等做出反应。以下是如何另一个代码片段


@RequestMapping("/quotes")
@ResponseBody
public DeferredResult<String> quotes() {
  DeferredResult<String> deferredResult…

获取 Spring 新闻通讯

与 Spring 新闻通讯保持联系

订阅

领先一步

VMware 提供培训和认证,以加速您的进步。

了解更多

获取支持

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

了解更多

即将举行的活动

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

查看全部