作为 Java 开发人员,您无需了解 HTML5、CSS 或 JavaScript 就可以开始创建交互式 Web 应用程序。借助 Vaadin 框架及其丰富的现成增件(add-on)和组件库,您可以通过使用熟悉的 IDE 和服务器端技术创建 100% 的全堆栈 Java 应用程序。我的 developerWorks 文章 “使用 Vaadin 实现全堆栈 Java Web 开发” 解释了 Vaadin 的幕后工作原理,帮助您开始使用 Vaadin 创建 Web 应用程序。
Vaadin 应用程序在 Bluemix 中表现良好,提供了 Vaadin Rich Web Starter 样板。部署在 Bluemix 上的 Vaadin 应用程序可以享受行业标准 Liberty Profile 应用程序服务器运行时支持,以及针对关系数据存储的 IBM DB2。Bluemix 上的所有 Vaadin 应用程序都可以充分利用各种丰富的、种类不断增长的服务器端服务。
在本教程中,我将引导您逐步为一个简单的 order desk(指令台)构建一个完整 Vaadin Web 应用程序。您将通过使用 Vaadin Contexts and Dependency Injection (CDI) 以及 Java Persistence API (JPA) 构造应用程序与组件,以便访问一个后端数据库。您会在熟悉的 Eclipse IDE 中进行编码,并将生成的应用程序部署到 Bluemix。
加入 为期 60 天的 IBM + Vaadin 挑战赛,参赛时间为 2015 年 10 月 1 日至 11 月 30 日。您可以炫耀从本教程及其配套教程中获得的技术, "使用 Vaadin 实现全堆栈 Java Web 开发",构建出色的应用程序并赢得奖品。
您将学习如何:
观看:Vaadin 分步指南
观看:Vaadin 简介
“Bluemix 上的所有 Vaadin 应用程序都可以充分利用各种丰富的、种类不断增长的服务器端服务。 ”
前提条件:
如果您想修改或研究该代码:
单击运行应用程序按钮(此步骤的前面)并尝试创建 order-desk 应用程序:
Customer
数据库,这是实现登录要执行的必要操作。单击 Fill test data into DB 按钮。brian@robinson.com
和密码 abc123
进行登录:本教程将开始介绍针对 Bluemix 的 Vaadin 样板中的代码并添加它。或者,您可以单击获取代码按钮(在本教程的 第 1 步. 探索应用程序的 UI 的前面),转到包含最终代码的 Bluemix DevOps Services 项目。然后,您可以将该项目中的最终代码与本教程中的样板版本进行比较。
git clone
https://hub.jazz.net/git/vaadin/vaadin-jpa-app
cd vaadin-jpa-app
mvn install
cf push appname -p
target/vaadin-jpa-application.war
要修改或重新构建您的代码,可以将它加载到 Eclipse 中并重新构建 WAR。您必须使用 Maven 构建,而不是默认的 Eclipse 项目构建工作流。
<jdbcDriver id="DerbyEmbedded" libraryRef="DerbyLib"/> <library filesetRef="DerbyFileset" id="DerbyLib"/> <fileset dir="${shared.resource.dir}/derby" id="DerbyFileset" includes="derby.jar"/> <!-- Configure an in-memory db for the vaadin app configuration --> <dataSource id="jdbc/vaadindb" jdbcDriverRef="DerbyEmbedded" jndiName= "jdbc/vaadindb" transactional="true"> <properties createDatabase="create" databaseName="memory:jpasampledatabase"/> </dataSource>
<featureManager> <feature>localConnector-1.0</feature> <feature>webProfile-6.0</feature> </featureManager>
package
作为 Maven 目标:样板应用程序使用了 Vaadin CDI 来处理自定义导航,并插入 UI 对象作为 CDI 托管 bean。Vaadin CDI 增件 位于 Vaadin Add-ons 目录中。
此外,在 Vaadin Add-ons 目录中,有一组 cdi-helpers
UI 组件,Bluemix Vaadin
样板代码依赖于这些组件。研究这组辅助工具的操作可以帮助您了解如何在应用程序中使用 Vaadin CDI。
ViewMenuUI
UI
实例。您可以查看使得该实例成为 org.vaadin.presentation.AppUI
类中应用程序的主 UI
实例的代码。视图更改是通过成为 ViewMenu
一部分 Vaadin Navigator
实例来精心策划的。org.vaadin.presentation.views.LoginView
的新类,您可以从 源代码存储库 中复制它。Login 视图使用了一个来自 Vaadin Add-ons 目录的 Vaadin 组件加载项 — 由
Ingo Kegel 开发的 LoginForm
UI 组件。
要将此组件添加到您的项目中,必须在依赖关系部分将其 Maven 工件添加到项目的 pom.xml 文件:
<dependency> <groupId>org.vaadin.addons</groupId> <artifactId>loginform</artifactId> <version>0.5.2</version> </dependency>
LoginView
类中,该增件使得显示表单变得很容易:
final DefaultVerticalLoginForm loginForm = new DefaultVerticalLoginForm(); loginForm.addLoginListener(new LoginListener() { @Override ... }); ... add(loginForm);
@ViewMenuItem()
注释:
@ViewMenuItem(icon = FontAwesome.SIGN_IN, title =
"Login-Logout", order = ViewMenuItem.END)
告诉 Navigator
此视图是默认视图,请使用具有空白视图名称的
@CDIView()
:
@CDIView("")
如果您继续执行后续操作并修改样板,还需要更改
AboutView
的注释,将它从 @CDIView("")
更改为
@CDIView("about")
。
如果立刻构建和部署应用程序,它将在新的 Login 视图中运行,但什么都不会发生,因为您还没有访问控制权。
password
字段、一个 role
字段和一个
findByEmail()
命名查询添加到客户数据库。首先,修改
org.vaadin.backend.domain.Customer
类中的域模型 POJO:
@NamedQueries({ ... @NamedQuery(name="Customer.findByEmail", query="SELECT c FROM Customer c WHERE LOWER(c.email) LIKE :filter") }) ... private String password; private String role; ... public String getPassword() { return password; } ... public void setRole(String role) { this.role = role; }
org.vaadin.backend.CustomerService
类的
ensureTestData()
方法中,使用常数填充两个新字段:
c.setRole("user"); c.setPassword("abc123");
CustomerListView
类中,在 adjustTableColumn()
方法中,添加您想要显示的字段:
customerTable.setVisibleColumns("firstName", "lastName", "email", "status", "role", "password"); customerTable.setColumnHeaders("First name", "Last name", "Email", "Status", "Role", "Password");
CustomerService
实例,让 LoginView
生效。该服务被用于从数据库中获取用户电子邮件和密码信息。请注意,如果登录成功,可以使用 ViewMenuUI.getMenu()
导航器导航到 AboutView
:
public class LoginView extends MVerticalLayout implements View { @Inject private CustomerService service; ... Customer cust = service.findByEmail(event.getUserName()); if(cust != null) { ... System.err.println("PASSWORD verified"); ViewMenuUI.getMenu().navigateTo(AboutView.class); } else { System.err.println("PASSWORD invalid"); loginForm.clear(); } } else { System.err.println("no user found"); loginForm.clear(); }
如果立刻构建并运行应用程序,并尝试登录,您会被重定向到
AboutView
。不过,因为尚未添加访问控制来保护视图,所以您仍然可以通过单击来查看客户列表或地图。
CDIViewProvider
负责检查一个名为
javax.annotation.security.RolesAllowed
的特殊注释。访问冲突被定向到的默认视图(在本例中为 LoginView
)。要向项目添加注释,请将以下 Maven 依赖关系添加到
pom.xml 文件:
<dependency> <groupId>javax.annotation</groupId> <artifactId>javax.annotation-api</artifactId> <version>1.2-b01</version> </dependency>
RoleAllowed
注释来保护视图,请将代码行 @RolesAllowed({"user"})
添加到每个视图(除了 LoginView
和 AboutView
)。
此更改可确保只有已登录的用户与用户角色可以访问该视图。(请回顾 第 5 步. 扩展客户数据库来实现身份验证,每一位客户都被设置为拥有用户角色。)
org.vaadin.presentation.views.UserInfo
类来包含当前用户详细信息。此类被附加到
UIScope
(专门的 Vaadin CDI 上下文,每个会话中都存在 UI 实例):
@UIScoped public class UserInfo implements Serializable { private Customer user; private List<String> roles = new LinkedList<String>(); ...
查看
UserInfo
的源代码,获得全部的详细信息。
UserInfo
注入到 LoginView
中,允许视图在成功登录时填充
UserInfo
:
public class LoginView extends MVerticalLayout implements View { ... @Inject private UserInfo user; ... public void onLogin(LoginEvent event) { ... Customer cust = service.findByEmail(event.getUserName()); if(cust != null) { if (cust.getPassword().equals(event.getPassword())) { user.setUser(cust); ... }
AccessControl
类来检查访问控制权。将这个类替换为您自己的已参照注入的 UIScoped UserInfo
实例检查过的
AccessControl
实现:
@Alternative public class CustomAccessControl extends AccessControl { @Inject private UserInfo userInfo; @Override public boolean isUserSignedIn() { return userInfo.getUser() != null; } ...
参见 org.vaadin.presentation.views.CustomAccessControl
的源代码,获得有关的详细信息。
CustomAccessControl
实现被 Vaadin CDI 使用,必须向 beans.xml
文件添加一行代码:
<alternatives> <class>org.vaadin.presentation.views.CustomAccessControl</class> </alternatives>
onEnter()
方法中已注入的
UserInfo
实例来注销:
@Override public void enter(ViewChangeListener.ViewChangeEvent viewChangeEvent) { user.setUser(null); }
如果立刻重新构建并运行应用程序,所有视图(除了 About)都会受到保护,您必须登录才能访问这些视图。在登录后,您可以通过再次选择 Login 视图来注销。
Search 视图是来自 Vaadin Add-ons 目录的开源第三方附加 UI 组件 — 是由 Teppo Kurki 开发的 FilteringTable
UI 组件(源代码回购)。
<dependency> <groupId>org.vaadin.addons</groupId> <artifactId>filteringtable</artifactId> <version>0.9.13.v7</version> </dependency>
org.vaadin.presentation.views.SearchView
类。视图的 UI 部分是在
init()
方法中构建的,这部分非常简单。此视图还使用
@RolesAllowed({"user"})
进行了保护:
@CDIView("search") @RolesAllowed({"user"}) @ViewMenuItem(icon = FontAwesome.SUPPORT) public class SearchView extends MVerticalLayout implements View { private FilterTable filterTable; @PostConstruct void init() { filterTable = buildFilterTable(); add(filterTable); setExpandRatio(filterTable, 1); add(buildButtons()); setMargin(new MarginInfo(false, true, true, true)); setStyleName(ValoTheme.LAYOUT_CARD); } ...
SearchView
代码的其余部分(在
org.vaadin.presentation.views.SearchView
、org.tepi.filterable.demo.DemoFilterDecorator
和 org.tepi.filterable.demo.DemoFilterGenerator
中)只用于此演示视图的设置。您可以在空闲时间探索该代码。
cf push
命令将完整的 WAR 部署到
Bluemix: cf push appname -p target/vaadin-jpa-application.war
Bluemix 上的 Vaadin 通过使用一个全堆栈 Java 方法,向 Java 开发人员提供了创建引人注目的交互式 Web 的能力。针对 Bluemix 的 Vaadin 样板提供了一个准备好部署的应用程序,可以很容易地扩展它来满足您的特定需求。
Vaadin Rich Web Starter 样板:演示了如何使用 Vaadin UI Framework 来构建丰富的 HTML5 应用程序,并在云中使用 Liberty for Java 运行时和 SQL Database 服务(受 DB2 支持)。
SQL Database 服务:(sqldb) 将向您的应用程序添加一个按需关系数据库。它由 DB2 驱动,提供了一个托管的数据库服务来处理要求苛刻的 Web 和事务性工作负载。
Bluemix Liberty for Java 运行时:可以帮助您轻松地开发、部署和扩展 Java Web 应用程序。IBM WebSphere Liberty Profile 是专为云设计的 IBM WebSphere Application Server 的高度可组合的、超快的、超轻型的配置文件。