지난주 제이포쿠스에 있을 때 만난 마티 타보넨에서 근무하고 있습니다. Vaadin. 그들은 수년 동안 Java로 리치 인터넷 애플리케이션을 위한 오픈 소스 웹 프레임워크를 제안해 왔으며 정말 잘 해내고 있습니다. 저는 개인적으로 완전한 웹 최신 애플리케이션을 Java로만 작성하게 되어 정말 기쁩니다.
Couchbase에 개체를 저장하는 작동하는 Vaadin CRUD 샘플을 만드는 데 10분이 걸렸습니다. 결과는 다음에서 확인할 수 있습니다. Github. 그 이후로 JPA 기반 샘플도 마이그레이션했습니다. 여기. 작업이 얼마나 적게 필요하며 JPA에서 Couchbase로 전환하는 것이 얼마나 쉬운지 확인할 수 있습니다. diff.
스프링 데이터 카우치베이스와 바아딘의 만남
프로젝트 생성
Spring 프로젝트를 시작할 때 첫 번째 단계는 다음과 같습니다. 스프링 초기화. 여기에서 프로젝트에 원하는 버전과 종속성을 선택할 수 있습니다. Spring Boot 버전 1.4.0(스냅샷)을 선택하고 종속성으로 Vaadin 및 Couchbase를 추가합니다.

이제 프로젝트를 생성하고 원하는 편집기에서 Maven 프로젝트로 가져올 수 있습니다.
기본 개인 엔티티 CRUD
이 CRUD 샘플은 다음을 저장합니다. 고객 객체입니다. 고객이 id, a 이름 및 성. 또한 성은 null이 아니어야 합니다. 이를 엔티티로 표현하려면 엔티티에 문서 주석을 추가합니다, @Id 어노테이션을 필드에 추가하고, 게터와 세터를 생성하면 완료됩니다. null이 아닌 제약 조건을 표현하려면 Java 유효성 검사 어노테이션을 사용하면 됩니다. @NotNull. 엔티티를 작성할 때 이를 선택하도록 하려면 유효성 검사기 빈을 선언해야 합니다.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
package hello; import java.util.Objects; import java.util.UUID; import javax.validation.constraints.NotNull; import org.springframework.data.couchbase.core.mapping.Document; import com.couchbase.client.java.repository.annotation.Id; @Document public class Customer { @Id private String id = UUID.randomUUID().toString(); private String firstName; @NotNull private String lastName; protected Customer() { } public Customer(String firstName, String lastName) { this.firstName = firstName; this.lastName = lastName; } public String getId() { return id; } public void setId(String id) { this.id = id; } 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; } @Override public String toString() { return String.format("Customer[id=%s, firstName='%s', lastName='%s']", id, firstName, lastName); } @Override public int hashCode() { int hash = 7; hash = 37 * hash + Objects.hashCode(this.id); return hash; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } final Customer other = (Customer) obj; return Objects.equals(this.id, other.id); } } |
고객 리포지토리
엔티티를 정의한 후에는 관련 리포지토리를 만들어야 합니다. 리포지토리를 확장하는 인터페이스를 만듭니다. 카우치베이스 페이징 및 정렬 저장소. 이 리포지토리는 고객 엔티티에 문자열을 키로 지정합니다.
저는 findAll 메서드를 반환하는 목록 대신 반복 가능 Vaadin 구조와 더 잘 어울리기 때문입니다. 그리고 findAll 메서드는 뷰로 백업됩니다. 뷰가 자동으로 정의되도록 하려면 뷰에 ViewIndexed 주석을 추가합니다. 또한 다음과 같이 설정해야 합니다. spring.data.couchbase.auto-index 속성을 참으로 설정하고 application.properties 파일을 만듭니다.
또한 성으로 찾기(문자열 lastName) 메서드를 입력합니다. 메서드 이름에 따라 적절한 N1QL 쿼리가 자동으로 생성됩니다. 하지만 N1Ql 쿼리를 실행하려면 기본 인덱스가 필요합니다. 이는 또한 @N1QLPrimaryIndexed 어노테이션.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
package hello; import java.util.List; import org.springframework.data.couchbase.core.query.N1qlPrimaryIndexed; import org.springframework.data.couchbase.core.query.ViewIndexed; import org.springframework.data.couchbase.repository.CouchbasePagingAndSortingRepository; @ViewIndexed(designDoc = "customer") @N1qlPrimaryIndexed public interface CustomerRepository extends CouchbasePagingAndSortingRepository<Customer, String> { List<Customer> findAll(); List<Customer> findByLastName(String lastName); } |
구성
스프링 스프링 부팅 스타터 데이터 카우치베이스를 사용하고 있습니다. 자동 구성을 제공합니다. 이 자동 구성은 다음과 같이 설정하여 활성화할 수 있습니다. spring.couchbase.bootstrap-hosts 속성입니다. 지금까지 내 application.properties 는 다음과 같이 보입니다:
|
1 2 3 |
spring.couchbase.bootstrap-hosts=localhost spring.data.couchbase.auto-index=true |
고객 만들기
이제 저장에 필요한 모든 것을 갖추었습니다. 고객 엔티티를 만듭니다. 이를 쉽게 시도해 볼 수 있습니다. CommandLineRunner:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
@SpringBootApplication public class Application { private static final Logger log = LoggerFactory.getLogger(Application.class); public static void main(String[] args) { SpringApplication.run(Application.class); } @Bean public CommandLineRunner loadData(CustomerRepository repository) { return (args) -> { repository.save(new Customer(null, "Dessler")); }; } @Bean public Validator validator() { return new LocalValidatorFactoryBean(); } } |
앞서 언급한 유효성 검사기 빈도 추가한 것을 보실 수 있습니다. 이 빈은 카우치베이스 이벤트 리스너 유효성 검사 스프링 부팅 자동 구성에 의해 자동으로 선언됩니다.
UI에 Vaadin 사용
백엔드가 준비되었으니 이제 프론트엔드에 대해 생각해 볼 수 있습니다. 고객 목록을 표시하고 목록의 요소를 추가, 편집 또는 제거하는 기능을 갖춘 기본 CRUD 앱을 만들고 싶습니다. 여기 스크린샷이 있습니다:

이를 구축하려면 먼저 사용자가 이름과 성을 입력할 수 있는 양식을 만들어야 합니다. 양식을 확장하는 클래스를 만듭니다. AbstractForm 의 고객. 이 클래스는 Vaadin Core에서 사용할 수 없으므로 추가해야 합니다. 비리틴.
비리틴은 바아딘의 서버 측 개선 라이브러리입니다. 핵심 프레임워크의 일부 잘못된 기본값을 수정하고 기존 컴포넌트를 위한 보다 유창하고 지능적인 API를 제공합니다. 또한 데이터 바인딩에 대한 몇 가지 주요 개선 사항을 제공하며 서버 측 구성으로 만들어진 완전히 새로운 구성 요소를 제공합니다(위젯 세트가 필요 없음).
그리고 예 AbstractForm 클래스가 Spring 데이터 및 유효성 검사기와 깔끔하게 통합되어 있습니다. 우리는 이름 그리고 성 필드의 고객 클래스에서 두 개의 텍스트 필드를 정의합니다. 이름 그리고 성. 고객 필드와 이름이 같아야 합니다. 이 컴포넌트의 또 다른 장점은 엔티티의 유효성 검사 어노테이션을 가져온다는 점입니다. 이렇게 하면 클라이언트와 서버에서 자동 유효성 검사를 수행할 수 있습니다. 그리고 더 복잡한 어노테이션도 지원합니다.@NotNull 같은 @Size 또는 패턴.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
package hello; import org.vaadin.viritin.form.AbstractForm; import org.vaadin.viritin.layouts.MFormLayout; import com.vaadin.spring.annotation.SpringComponent; import com.vaadin.spring.annotation.UIScope; import com.vaadin.ui.Component; import com.vaadin.ui.TextField; @SpringComponent @UIScope public class CustomerEditor extends AbstractForm<Customer> { /* Fields to edit properties in Customer entity */ TextField firstName = new TextField("First name"); TextField lastName = new TextField("Last name"); public CustomerEditor() { setVisible(false); } @Override protected Component createContent() { return new MFormLayout(firstName, lastName, getToolbar()); } } |
이제 양식이 준비되었으므로 표 그리드를 표시하는 전체 UI를 구축할 수 있습니다. 이것이 Vaadin 애플리케이션의 주요 구성 요소인 메인 웹 페이지가 될 것입니다. 메인 웹 페이지의 고객 저장소 및 고객 편집자 가 Spring 빈이라면 생성자에서 직접 주입할 수 있습니다. Java UI 작성에 익숙하다면 아래의 주석 처리된 코드는 간단할 것입니다.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
package hello; import org.springframework.beans.factory.annotation.Autowired; import org.vaadin.viritin.fields.MTable; import org.vaadin.viritin.layouts.MVerticalLayout; import com.vaadin.annotations.Theme; import com.vaadin.server.FontAwesome; import com.vaadin.server.VaadinRequest; import com.vaadin.spring.annotation.SpringUI; import com.vaadin.ui.Button; import com.vaadin.ui.UI; @SpringUI @Theme("valo") public class VaadinUI extends UI { private final CustomerRepository repo; private final CustomerEditor editor; private final MTable<Customer> grid; private final Button addNewBtn; @Autowired public VaadinUI(CustomerRepository repo, CustomerEditor editor) { this.repo = repo; this.editor = editor; this.grid = new MTable<>(Customer.class).withProperties("id", "firstName", "lastName").withHeight("300px"); this.addNewBtn = new Button("New customer", FontAwesome.PLUS); } @Override protected void init(VaadinRequest request) { // Connect selected Customer to editor or hide if none is selected grid.addMValueChangeListener(e -> { if (e.getValue() == null) { editor.setVisible(false); } else { editor.setEntity(e.getValue()); } }); // Instantiate and edit new Customer the new button is clicked addNewBtn.addClickListener(e -> editor.setEntity(new Customer("", ""))); // Listen changes made by the editor, refresh data from backend editor.setSavedHandler(customer -> { repo.save(customer); listCustomers(); editor.setVisible(false); }); editor.setResetHandler(customer -> { editor.setVisible(false); listCustomers(); }); editor.setDeleteHandler(customer -> { repo.delete(customer); listCustomers(); }); // Initialize listing listCustomers(); // build layout setContent(new MVerticalLayout(addNewBtn, grid, editor)); } private void listCustomers() { grid.setBeans(repo.findAll()); } } |
이제 모든 준비가 끝났으니 일반적인 Java Spring Boot 애플리케이션으로 실행하기만 하면 됩니다. 꽤 쉽죠?