はじめに
Spring Boot + Apache Wicket はできてきた感があるので、Vaadinにも挑戦してみる。
Vaadin4Spring
Spring Boot + Vaddin の先駆として、peholmst/vaadin4springがある。まずはこれを使わせてもらう。
README.mdの通りに、まず、SPRING INITIALIZRで、Webプロジェクトを作成する。
次に、pom.xmlのdependencies
にspring-boot-vaadin
, vaadin-themes
, vaadin-client-compiled
を登録する
<!-- Vaadin4Spring -->
<!-- 記事の執筆時点でspring-boot-vaadin 0.0.3.1のvaadinは7.3.6なので、後ほど実行時にはコンソールにアラートが発生する。バージョンを合わせたいときは調整する -->
<dependency>
<groupId>org.vaadin.spring</groupId>
<artifactId>spring-boot-vaadin</artifactId>
<version>0.0.3.1</version>
</dependency>
<dependency>
<groupId>com.vaadin</groupId>
<artifactId>vaadin-themes</artifactId>
<version>7.3.9</version>
</dependency>
<dependency>
<groupId>com.vaadin</groupId>
<artifactId>vaadin-client-compiled</artifactId>
<version>7.3.9</version>
</dependency>
ログイン画面を作ってみる
VaadinのWikiにCreating a simple login viewという記事があるので、これを参考にし、簡単なログイン画面を作ってみる。
画面を制御するためのMainUI
クラス、ログイン画面を表示するLoginView
クラス、ログイン後の画面を表示するLoginedView
クラスの3種類を作成する。
MainUI
以下、WikiのSimpleLoginUI
を引用し改変している。
package com.example.ui;
import org.springframework.beans.factory.annotation.Autowired;
import org.vaadin.spring.VaadinUI;
import org.vaadin.spring.navigator.SpringViewProvider;
import com.vaadin.annotations.Theme;
import com.vaadin.navigator.Navigator;
import com.vaadin.navigator.ViewChangeListener;
import com.vaadin.server.VaadinRequest;
import com.vaadin.ui.UI;
@Theme("valo")
@VaadinUI
public class MainUI extends UI {
@Autowired
private SpringViewProvider viewProvider;
@Override
protected void init(VaadinRequest request) {
Navigator navigator = new Navigator(this, this);
navigator.addProvider(viewProvider);
navigator.addViewChangeListener(new ViewChangeListener() {
@Override
public boolean beforeViewChange(ViewChangeEvent event) {
boolean isLoggedIn = getSession().getAttribute("user") != null;
boolean isLoginView = event.getNewView() instanceof LoginView;
if (!isLoggedIn && !isLoginView) {
getNavigator().navigateTo(LoginView.NAME);
return false;
} else if (isLoggedIn && isLoginView) {
return false;
}
return true;
}
@Override
public void afterViewChange(ViewChangeEvent event) {
}
});
setNavigator(navigator);
}
}
@VaadinUI
で、URLでアクセス可能なUIであることを設定。Vaadinではページ遷移はNavigator
で行うが、これをアノテーションで管理するためのSpringViewProvider
をInjectする。
@Theme("valo")
で、Vaadinの綺麗なCSSテーマであるValoを利用してくれる。
LoginView
以下、WikiのSimpleLoginView
を引用し改変している。
package com.example.ui;
import org.vaadin.spring.UIScope;
import org.vaadin.spring.navigator.VaadinView;
import com.vaadin.annotations.Theme;
import com.vaadin.data.validator.AbstractValidator;
import com.vaadin.data.validator.EmailValidator;
import com.vaadin.navigator.View;
import com.vaadin.navigator.ViewChangeListener.ViewChangeEvent;
import com.vaadin.shared.ui.MarginInfo;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button;
import com.vaadin.ui.CustomComponent;
import com.vaadin.ui.PasswordField;
import com.vaadin.ui.TextField;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.themes.Reindeer;
@UIScope
@VaadinView(name = LoginView.NAME)
public class LoginView extends CustomComponent implements View {
public static final String NAME = "";
private final TextField user;
private final PasswordField password;
private final Button loginButton;
public LoginView() {
setSizeFull();
user = new TextField("ユーザー名:");
user.setWidth("300px");
user.setRequired(true);
user.setInputPrompt("例:user@example.com");
user.addValidator(new EmailValidator("ユーザ名かパスワードが不正です"));
user.setInvalidAllowed(false);
password = new PasswordField("パスワード:");
password.setWidth("300px");
password.addValidator(new PasswordValidator());
password.setRequired(true);
password.setValue("");
password.setNullRepresentation("");
loginButton = new Button("ログイン", e -> {
if (!user.isValid() || !password.isValid()) {
return;
}
String username = user.getValue();
String password = this.password.getValue();
boolean isValid = username.equals("test@test.com")
&& password.equals("passw0rd");
if (isValid) {
getSession().setAttribute("user", username);
getUI().getNavigator().navigateTo(LoginedView.NAME);
} else {
this.password.setValue(null);
this.password.focus();
}
});
VerticalLayout fields = new VerticalLayout(user, password, loginButton);
fields.setCaption("ログインしてください (test@test.com/passw0rd)");
fields.setSpacing(true);
fields.setMargin(new MarginInfo(true, true, true, false));
fields.setSizeUndefined();
VerticalLayout viewLayout = new VerticalLayout(fields);
viewLayout.setSizeFull();
viewLayout.setComponentAlignment(fields, Alignment.MIDDLE_CENTER);
viewLayout.setStyleName(Reindeer.LAYOUT_BLUE);
setCompositionRoot(viewLayout);
}
@Override
public void enter(ViewChangeEvent event) {
user.focus();
}
private static final class PasswordValidator extends AbstractValidator<String> {
public PasswordValidator() {
super("ユーザ名かパスワードが不正です");
}
@Override
protected boolean isValidValue(String value) {
return value != null ? value.length() >= 8 && value.matches(".*\\d.*") : false;
}
@Override
public Class<String> getType() {
return String.class;
}
}
}
ちょっとバリデーションなどが設定されていてごちゃごちゃしてる感があるけど、原則的にはTextField
やButton
のコンポーネントに設定を付け加えてあるだけ。
@UIScope
でスコープを設定する。@VaadinView
は、ページとなるViewにマッピングされる名称。(Vaadin的に、初期ページは空文字でマッピングしないといけない...?ちょっと自信ない)。
ボタンのリスナーにラムダ式を使えるのがすっきりしてて素敵。
LoginedView
以下、WikiのSimpleLoginMainView
を引用し改変している。
package com.example.ui;
import org.vaadin.spring.UIScope;
import org.vaadin.spring.navigator.VaadinView;
import com.vaadin.navigator.View;
import com.vaadin.navigator.ViewChangeListener.ViewChangeEvent;
import com.vaadin.ui.Button;
import com.vaadin.ui.CssLayout;
import com.vaadin.ui.CustomComponent;
import com.vaadin.ui.Label;
@UIScope
@VaadinView(name = LoginedView.NAME)
public class LoginedView extends CustomComponent implements View {
public static final String NAME = "LoginedView";
private Label text = new Label();
private Button logout = new Button("ログアウト", e -> {
getSession().setAttribute("user", null);
getUI().getNavigator().navigateTo(NAME);
});
public LoginedView() {
setCompositionRoot(new CssLayout(text, logout));
}
@Override
public void enter(ViewChangeEvent event) {
String username = String.valueOf(getSession().getAttribute("user"));
text.setValue("ようこそ、 " + username);
}
}
実行結果
Vaadinを使うと(Layoutの使い方に慣れが必要そうだけど)HTMLを書かずにWebシステムを構築していける。Spring4Vaadinを使えば、Navigatorなどの面倒になりがちな設定もアノテーションを拾って自動設定してくれる。慣れてくると爽快に開発できそうだなあ。
なお、ここまでのソースコードはgishi-yama/springboot-vaadin-sample/tree/61086783ecにpushしてある。