看新闻很累?看技术新闻更累?试试下载 InfoQ 手机客户端,每天上下班路上听新闻,有趣还有料!
JSR-371 规范 1.0(Model-View-Controller,MVC)开始进入公开评审阶段。这是在 2017 年 4 月份 Oracle 将其所有权移交给 Ivar Grimstad 之后发布的第一个主要版本。在移交之后不久,来自 Ingenit GmbH 的高级开发工程师与 Christian Kaltepoth 一起领导该规范的制定。后来,JSR-371 将许可协议改为 Apache License 2.0。2017 年 10 月,Grimstad 表示,在 MVC 1.0 最终版发布之后,他想要将它移交给 Eclipse 基金会。
自 Early Draft Review 2 以来的新特性包括:
- 国际化——支持 I18N 。
- 改进了数据绑定——可通过 @MvcBinding 注解和 BindingResult 类来定义数据绑定和数据验证规则。
规范文档列出了 MVC 1.0 的目标:
- 基于现有的 Java EE 技术。
- 集成 CDI( JSR-346 )和 Bean Validation( JSR-349 )。
- 定义用于构建 MVC 应用程序的方法,但在第一版本中不需要支持所有特性。
- 尝试在 JAX-RS 之上构建其他层,并重用已有的匹配和绑定层。
- 提供内置的 JSP 和 Facelet 视图语言。
Eclipse 的 Ozark 项目完整地实现了 JSR-371,支持 RESTEasy 、 Jersey 和 Apache CXF 。Ozark 1.0 版本有望在 2018 年第二季度发布,与 JSR-371 的最终版接轨。
入门
下面的例子使用 @Controller 注解定义了一个 MVC 1.0 的控制器,该控制器会生成一个 JSP 页面。
@Path("hello") @Controller public class HelloController { @GET public String view() { return "hello.jsp"; } }
这个方法可以返回各种各样 MVC 1.0 能够处理的类型,如:
- void——必须与 @View 一起使用(请看下面的例子)。
- String——返回视图的路径(请看下面的例子)。
- JAX-RS Response——返回 HTTP 响应消息,包括头部信息(请看下面的例子)。
下面是一个典型的 MVC 1.0 控制器的例子(来自 Grimstad GitHub代码库里的 hello-cli 示例):
@Path("hello") @Controller public class HelloController { @Inject private BindingResult br; @Inject private Messages messages; @Inject private HelloBean helloBean; @GET @View("form.jsp") public void form() { } @POST public Response formPost(@Valid @BeanParam HelloForm form) { if (br.isFailed()) { messages.setErrors( br.getAllValidationErrors().stream() .collect(toList())); return Response.status(BAD_REQUEST).entity("form.jsp").build(); } helloBean.setFirstName(form.getFirstName()); helloBean.setLastName(form.getLastName()); return Response.status(OK).entity("hello.jsp").build(); } }
示例中使用 @Inject 将 BindingResult 的实例(用于进行验证)和 Model、Message 和 HelloBean 自动注入到控制器中。被 @View 注解的 form() 方法指定了要渲染的页面 form.jsp。formPost() 方法里会做一些验证,并返回 Response 类型。HelloForm 类定义了用户输入字符串的长度:
public class HelloForm { @MvcBinding @NotNull @Size(min = 1, max = 16) @FormParam("firstName") private String firstName; @MvcBinding @NotNull @Size(min = 2, max = 24) @FormParam("lastName") private String lastName; public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } }
规范文档对绑定和验证的过程进行了描述:
可以通过给 @FormParam 和 @QueryParam 添加 @MvcBinding 注解来定义绑定规则。在进行 MVC 绑定时,出现验证错误并不会抛出 ConstraintViolationException 异常。相反,ConstraintViolation 会被保存到具有 Request 作用域的 BindingResult 实例中,该实例可以被注入到控制器当中。这样,控制器就可以处理错误,而不是使用全局的异常处理机制来处理错误,比如使用 ExceptionMapper。
运行 hello-cli 示例,form.jsp 经过渲染后就会呈现成下面的样子:
用户输入如下的信息,只要长度符合要求,就会渲染出hello.jsp 页面:
下面是出现验证错误的例子,输入框会被清空,并显示错误消息:
来自Cybercom Group 的首席顾问Grimstad 向InfoQ 透露了MVC 1.0 的最新进展情况。
InfoQ:为什么 Oracle 不想再为 MVC 1.0 提供支持?
Ivar Grimstad:这个问题应该让 Oracle 来回答。不过我认为,Oracle 之所以将 MVC 1.0 从 Java EE 8 中剥离出来,是因为他们认为 MVC 与他们的云应用不相干,因为他们的大部分应用是 headless 的。
InfoQ:你对将 MVC 1.0 集成到 EE4J 中做何期待?在这之前,需要做些什么吗?
Grimstad:我们已经创建了一个提案项目 Ozark,也就是 MVC 1.0 的一个参考实现。具体信息可参看: https://projects.eclipse.org/proposals/eclipse-ozark。
我们希望在 MVC 1.0 最终版发布之后,尽快将其剩余部分集成到 EE4J 中。我们计划在今年的第二个季度完成这项工作。我们之所以要这么做,是因为我们希望 MVC 能够在发布最终版之后再将其移交给 Eclipse 基金会。
InfoQ:Rest Client 1.0 和 JAX-RS 2.0 已经被集成到 MicroProfile 1.3 中,那么 MVC 1.0 API 也适合被集成进 MicroProfile 吗?
Grimstad:从技术方面来看,MVC 1.0 应用程序可以运行在 MicroProfile 上。不过,MicroProfile 的目标是为微服务优化企业版 Java,所以我不确定 MVC 被集成到 MicroProfile 中是否是一个明智之举。它只是一项额外的补充技术,因为是运行在相同的技术栈上,所以在这方面没有什么问题。不过,MVC 更适合被放在 EE4J 中。
InfoQ:MVC 1.0 接下来会有哪些动作?
Grimstad:MVC 1.0 的下一件大事就是它的公开评审,评审开放时间为 2 月 6 号至 2 月 12 号。在完成评审之后,我们会继续完成剩下的工作。目前计划在 2018 年第二季度发布最终版。
可以查看如下信息来了解我们的进度,或者加入到我们的工作中: https://github.com/mvc-spec https://www.mvc-spec.org/ https://twitter.com/mvc_spec
InfoQ:你的本职工作是什么?或者说,你日常都做些什么?
Grimstad:我的本职工作是瑞士 Cybercom Group 的首席顾问。我们每天都会写代码,并通过参与开源项目和参加技术大会保持技术上的与时俱进。我是 JCP 执行委员会成员,也是 EE4J 的项目管理委员会成员。
其他资源
- MVC 1.0 by Example by Ivar Grimstad (May 22, 2017)
- mvc-samples GitHub repository by Ivar Grimstad
查看英文原文: Public Review of Java MVC 1.0 Specification is Now Open
评论