java前端框架使用教程:新手完成第一张作品的方法
提到 Java 前端,很多人会想到用 Java 写接口,再用 Vue 或 React 写页面。但还有另一条路线:使用 Vaadin 这类 Java Web UI 框架,在 Java 代码中描述页面组件和交互,由框架负责将界面呈现在浏览器中。本文会带你从空项目做出一张可以添加、完成和删除任务的清单页面。
这里的“第一张作品”是一款适合练手的任务清单,不是完整的生产级任务管理系统。示例使用 Vaadin、Spring Boot 和 Java 17,数据暂存在内存中。照着创建文件后,可以在本机运行并通过浏览器查看效果。
一、先弄清楚:什么是 Java 前端框架
Vaadin 是一个用 Java 构建 Web 用户界面的框架。开发者可以在 Java 中创建输入框、按钮、表格等组件,设置它们的布局,并为交互注册事件。用户访问的是浏览器页面,应用运行在服务器端;框架负责组件状态与浏览器之间的通信。
这与“Java 后端加 Vue 前端”的项目结构不同。采用 Vaadin 时,常见页面逻辑和组件代码集中在 Java 项目中,不必为这张练习页面另外编写 Vue 单文件组件,也不必手动设计前后端 JSON 接口。但这不代表应用不使用浏览器技术:页面最终仍然在浏览器中显示,Vaadin 也会通过前端资源和通信机制完成界面交互。
需要注意,“Java 前端框架”不是一个边界严格、含义唯一的名称。本文选择 Vaadin,是因为它适合用 Java 快速搭建服务端驱动的 Web 界面,并不是说所有 Java 项目都应该采用这种方式。
二、适用场景与关键边界
比较适合的场景
- 内部业务系统:例如管理后台、数据录入工具、审批流程页面。页面以表单、表格和业务操作为主时,用 Java 组件组织界面通常比较直接。
- 团队熟悉 Java,但不想单独维护一套前端工程:原型或规模适中的应用可以减少前后端项目拆分带来的配置成本。
- 需要快速验证业务交互:可以先用 Java 组件完成一条可运行的页面流程,再根据项目发展情况决定是否调整架构。
需要谨慎评估的场景
- 高度定制的前端体验:如果页面依赖复杂动画、特殊图形交互、丰富的浏览器端状态管理,采用专门的前端框架可能更合适。
- 公开网站的搜索引擎优化要求很高:应结合页面渲染方式、内容可发现性和实际搜索需求评估,不能只因为代码写在 Java 中,就默认页面一定适合 SEO。
- 前后端必须独立演进或提供多端 API:例如同一套服务还要支持移动端、第三方接入,通常需要认真设计独立的 API 边界。UI 框架本身不能替代 API 设计。
还要区分“页面开发”和“业务安全”。Vaadin 能帮助开发者构建界面与组件交互,但不会自动替你完成登录授权、数据权限、输入校验、数据库事务或审计。隐藏一个按钮也不等于限制了接口访问;真正的权限检查必须在服务器端完成。
三、准备环境并创建项目
示例使用 Java 17、Maven、Vaadin 24.5.13 和 Spring Boot 3.4.4。安装 JDK 17 后,可在终端分别运行 java -version 和 mvn -version 检查环境。请确认 Maven 实际使用的 Java 版本也是 17 或更高。
创建如下目录结构:
java-first-work/
├── pom.xml
└── src/
└── main/
└── java/
└── com/
└── example/
└── demo/
├── DemoApplication.java
└── TaskView.java
先创建 pom.xml。Vaadin 依赖通过 BOM 管理版本,示例固定了版本,方便复现;实际项目应根据团队的升级策略选择并维护依赖版本。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>java-first-work</artifactId>
<version>1.0.0</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.4.4</version>
<relativePath/>
</parent>
<properties>
<java.version>17</java.version>
<vaadin.version>24.5.13</vaadin.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.vaadin</groupId>
<artifactId>vaadin-bom</artifactId>
<version>${vaadin.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>com.vaadin</groupId>
<artifactId>vaadin-spring-boot-starter</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
然后创建 Spring Boot 启动类 src/main/java/com/example/demo/DemoApplication.java:
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
四、实现任务清单页面
接下来创建 TaskView.java。页面包含标题、任务输入框、添加按钮和任务表格。每条任务有完成状态,也可以删除。为了让示例独立运行,任务暂时存放在当前页面对象中的列表里。
package com.example.demo;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.checkbox.Checkbox;
import com.vaadin.flow.component.grid.Grid;
import com.vaadin.flow.component.html.H2;
import com.vaadin.flow.component.notification.Notification;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.component.textfield.TextField;
import com.vaadin.flow.router.Route;
import java.util.ArrayList;
import java.util.List;
@Route("")
public class TaskView extends VerticalLayout {
private final List<Task> tasks = new ArrayList<>();
private final Grid<Task> grid = new Grid<>(Task.class, false);
public TaskView() {
setSizeFull();
setPadding(true);
setSpacing(true);
H2 title = new H2("我的任务清单");
TextField taskInput = new TextField("新任务");
taskInput.setPlaceholder("例如:整理本周计划");
taskInput.setMaxLength(120);
taskInput.setWidth("24em");
Button addButton = new Button("添加任务", event -> {
String text = taskInput.getValue().trim();
if (text.isEmpty()) {
Notification.show("请先填写任务内容");
return;
}
tasks.add(new Task(text));
refreshGrid();
taskInput.clear();
taskInput.focus();
});
taskInput.addKeyPressListener(
com.vaadin.flow.component.Key.ENTER,
event -> addButton.click()
);
grid.addColumn(Task::getDescription)
.setHeader("任务")
.setAutoWidth(true)
.setFlexGrow(1);
grid.addComponentColumn(task -> {
Checkbox completed = new Checkbox("已完成");
completed.setValue(task.isCompleted());
completed.addValueChangeListener(event -> {
task.setCompleted(Boolean.TRUE.equals(event.getValue()));
refreshGrid();
});
return completed;
}).setHeader("状态");
grid.addComponentColumn(task -> new Button("删除", event -> {
tasks.remove(task);
refreshGrid();
Notification.show("任务已删除");
})).setHeader("操作");
add(title, new HorizontalLayout(taskInput, addButton), grid);
expand(grid);
refreshGrid();
}
private void refreshGrid() {
grid.setItems(tasks);
}
private static class Task {
private final String description;
private boolean completed;
private Task(String description) {
this.description = description;
}
public String getDescription() {
return description;
}
public boolean isCompleted() {
return completed;
}
public void setCompleted(boolean completed) {
this.completed = completed;
}
}
}
代码中的 @Route("") 将页面映射到应用根路径。继承 VerticalLayout 后,可以用 add 将组件按垂直方向放入页面;输入框和按钮则放在 HorizontalLayout 中。Grid 负责展示任务列表,addComponentColumn 用来在表格单元格中放入可交互的组件。
setMaxLength(120) 为输入框设置客户端组件的最大长度,帮助用户避免输入过长内容。不过,界面上的长度限制不能替代服务端验证:如果数据还会通过其他入口写入,服务端仍应检查字符长度、空值和业务规则。这里的示例只处理当前页面中的输入,没有数据库或外部接口。
五、运行并验证
在项目根目录执行:
mvn spring-boot:run
首次启动时 Maven 需要下载依赖,等待应用启动完成后,在浏览器中打开 http://localhost:8080/。输入任务内容,点击“添加任务”或按回车;勾选“已完成”可以更新状态,点击“删除”可以移除任务。
也可以先打包,再运行生成的 JAR:
mvn clean package
java -jar target/java-first-work-1.0.0.jar
这份练习作品的数据仅保存在运行中的页面对象内存中。刷新页面、重新启动程序或切换到新的页面实例后,不能保证数据仍然存在。因此它适合学习组件、布局和事件,不适合作为需要持久化的真实任务系统。生产应用应通过服务层读写数据库,并根据实际需求处理用户身份、数据归属、并发修改和事务。
六、常见错误与排查方法
1. Java 版本和依赖版本不匹配
如果构建时报编译版本错误,先查看 java -version、mvn -version 和 pom.xml 中的 java.version。有时命令行使用了一个 JDK,IDE 却配置了另一个 JDK。不要只改代码来绕过版本问题;应确认所用 Vaadin、Spring Boot 与 JDK 版本彼此兼容。
2. 页面返回 404
检查启动类与 TaskView 的包路径。Spring Boot 默认扫描启动类所在包及其子包;如果页面放到了扫描范围之外,组件路由可能无法被发现。还要确认浏览器访问的是 http://localhost:8080/,以及控制台中没有启动失败信息。
3. 修改数据后表格没有更新
练习代码在增加、完成或删除任务后都会调用 refreshGrid()。使用组件状态时,要确认更新操作作用在当前页面实际使用的数据上,并按需要通知或刷新相应组件。若后续换成数据库服务,也要将查询结果重新交给表格,而不能只更新一个与表格无关的列表。
4. 把页面输入限制当成安全校验
setMaxLength 和非空判断改善了当前表单的使用体验,但不能代替完整的服务端验证,也不能防止所有绕过客户端的请求。涉及持久化时,应在服务层验证数据,并使用参数化数据库操作;涉及身份权限时,应在服务端对每次敏感操作授权。不要因为按钮没有显示,就认为用户无法访问对应的业务操作。
5. 误以为内存列表就是持久化存储
ArrayList 只存在于当前 JVM 的内存中。应用重启会丢失数据;如果把可变集合做成多个用户共享的全局状态,还可能造成用户数据串扰和并发问题。本例将列表放在页面实例中,只用于演示交互。正式项目应定义合适的服务层和数据模型,再选择数据库及访问方式。
6. 不检查组件版本就复制网上代码
不同版本的 Vaadin、Spring Boot 或 Java 可能存在 API 与配置差异。复制示例时,如果出现类找不到、方法签名不一致或依赖冲突,应先核对项目的依赖版本与文档版本,不要通过随意加入多套版本的依赖来消除报错。
七、下一步怎么扩展
完成第一张作品后,可以按业务复杂度逐步扩展:把 Task 移到独立文件,为任务加入创建时间和筛选状态,再增加服务类负责业务操作,最后接入数据库。每次只增加一个明确能力,并验证页面、服务和数据之间的边界,通常比一次性堆入登录、权限、数据库和复杂布局更容易排错。
若项目需要多人协作、复杂状态管理或独立前后端发布,也可以比较 Vaadin 与“Spring Boot API 加 Vue/React”的方案。选择框架时,重点不是代码写在哪种语言里,而是团队能否维护、架构是否满足产品需求,以及服务端的数据和安全边界是否清晰。
通过这个任务清单,你已经完成了一个可启动、可交互的 Java Web 页面:用组件搭布局,用事件响应操作,用表格展示数据。它是理解 Vaadin 工作方式的起点;要成为可交付的应用,还需要补上持久化、验证、权限和部署等工程环节。










