创建日期:2026-09-08 | 最近更新:2026-09-08 本篇演示项目 本机实测跑通:JDK 11 + Maven 3.9.16 离线打包并运行,输出见 §4。
Java 复习手册 5:搭一个完整项目(Maven 命令行待办)
前几篇学的是「零件」。这篇把它们组装成第一个能跑的完整项目——一个分层的命令行待办清单:model(数据)→ service(业务)→ Main(入口)。它会把你学过的封装、继承、接口思路落到位,也为将来接 Spring Boot(Java Web 的完整项目形态)打底。
1. 为什么用 Maven,不手敲 javac
javac 适合 1 个文件;项目一多,编译、打包、依赖、测试都要工具管 → 用 Maven(详见本站 Maven 入门)。你只需遵守:
项目根/
├─ pom.xml # 项目声明:坐标、JDK 版本、打包配置
└─ src/main/java/... # 源码目录(按 package 放)
Maven 帮你:编译(compile)→ 测试(test)→ 打 jar(package)。
2. 项目结构:先想清楚「分几层」
一个「能长大」的小项目,至少分三层——这是所有 Java 项目的通用骨架:
| 层 | 放什么 | 对应类 |
|---|---|---|
| model(领域) | 数据和自己的基本行为 | Task |
| service(业务) | 怎么管理数据、业务规则 | TodoService |
| 入口(presentation) | 跟用户打交道(命令行/HTTP/UI) | Main |
原则:presentation 不写业务,model 不放逻辑,业务集中在 service。将来把「内存 List」换成数据库,只动 service/数据层,Main 和 Task 不用改。
3. 代码(三段,每段复习一篇)
① Task.java —— 复习「封装 + 构造器 + toString」(篇 2/3)
package com.example.todo;
public class Task {
private final int id; // final:构造后不变
private final String title;
private boolean done;
public Task(int id, String title) {
this.id = id;
this.title = title;
}
public int getId() { return id; }
public String getTitle() { return title; }
public boolean isDone() { return done; }
public void markDone() { this.done = true; }
@Override
public String toString() { // 让打印好看
return (done ? "[x] " : "[ ] ") + id + ". " + title;
}
}
② TodoService.java —— 复习「List/泛型 + 异常 + StringBuilder」(篇 4)
package com.example.todo;
import java.util.ArrayList;
import java.util.List;
public class TodoService {
private final List<Task> tasks = new ArrayList<>(); // 内存当数据库
private int nextId = 1;
public Task add(String title) {
if (title == null || title.trim().isEmpty()) {
throw new IllegalArgumentException("标题不能为空"); // 业务校验 + 异常
}
Task t = new Task(nextId++, title);
tasks.add(t);
return t;
}
public List<Task> all() { return new ArrayList<>(tasks); } // 返回副本
public void complete(int id) {
for (Task t : tasks) {
if (t.getId() == id) { t.markDone(); return; }
}
throw new IllegalArgumentException("找不到 id=" + id + " 的任务");
}
public String render() { // StringBuilder 拼文本
StringBuilder sb = new StringBuilder("待办清单(共 ").append(tasks.size()).append(" 条)\n");
for (Task t : tasks) sb.append(" ").append(t).append('\n');
return sb.toString();
}
}
③ Main.java —— 复习「static main + 输入 + try/catch」(篇 0/4)
package com.example.todo;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
if (args.length > 0 && "--demo".equals(args[0])) { runDemo(); return; }
interactive();
}
private static void runDemo() {
TodoService svc = new TodoService();
svc.add("复习 Java 语法");
svc.add("搭一个完整项目");
System.out.print(svc.render());
svc.complete(1);
System.out.println("完成 id=1 之后:");
System.out.print(svc.render());
}
private static void interactive() {
TodoService svc = new TodoService();
Scanner in = new Scanner(System.in);
System.out.println("待办清单。命令:add <标题> | done <id> | list | exit");
while (true) {
System.out.print("> ");
String line = in.nextLine();
if (line == null || line.equals("exit")) break;
try {
if (line.startsWith("add ")) svc.add(line.substring(4));
else if (line.startsWith("done ")) svc.complete(Integer.parseInt(line.substring(5).trim()));
else if (line.equals("list")) System.out.print(svc.render());
else System.out.println("看不懂,试试 add xxx / done 1 / list");
} catch (IllegalArgumentException e) {
System.out.println("出错:" + e.getMessage()); // 业务异常 → 友好提示
}
}
}
}
4. 跑起来(本机实测输出)
pom.xml 记得声明主类(maven-jar-plugin 的 <mainClass>),然后:
mvn -o package # 编译 + 打包(-o 离线;首次建议去掉 -o 拉依赖)
java -jar target/todo-cli-1.0.0.jar --demo # 跑内置演示
真实运行输出:
待办清单(共 2 条)
[ ] 1. 复习 Java 语法
[ ] 2. 搭一个完整项目
完成 id=1 之后:
待办清单(共 2 条)
[x] 1. 复习 Java 语法
[ ] 2. 搭一个完整项目
交互模式(管道喂命令)真实输出:
> > > > 待办清单(共 2 条)
[x] 1. 复习集合
[ ] 2. 写总结
> bye
看到没:你已经把 0–4 篇所有内容用起来了——package/main、类与封装、List/异常、StringBuilder、遍历。这就是「一个完整项目」的最小闭环。
5. 从 CLI 走向 Web(下一步路线)
命令行待办没有「网页/接口」——那需要把「入口层」从 Main 换成 Web 框架。本站已备好衔接:
- 把 Maven 搞熟 → Maven 入门;
- Java Web 完整项目 → Spring & Spring Boot 入门(你会看到一模一样的分层:Controller → Service → …,只是入口变成 HTTP);
- 想再补的 Java 知识点:I/O 读文件、多线程、
record/switch新语法、Stream链式操作——用到再学即可。
收尾:这本手册你「记住」了什么
| 篇 | 一句话核心 |
|---|---|
| 0 | .java→javac→.class→java→JVM;public 类名=文件名 |
| 1 | 8 个基本类型 + String(用 equals)+ 流程控制 + 数组(length 无括号) |
| 2 | 类=图纸、new=实物;封装 private + getter/setter;static 属于类 |
| 3 | 单继承 + 接口多实现;抽象类管「是」,接口管「能」;多态看实际类型 |
| 4 | List/Set/Map + 泛型;异常 try/catch/finally;StringBuilder |
| 5 | model/service/presentation 三层 + Maven 打包 = 完整项目闭环 |
复习建议:别重读全文,只看每篇的「最容易忘」和「自测」——答得上来就过,答不上来才回去看那一段。重复 2–3 轮,Java 就真的是你的了。
动手
把待办项目改造成:done 能撤销(加个 uncomplete);给 Task 加 deadline 字段并按截止时间排序(提示:service 里用 Comparator 或先 List.sort)。改完跑 --demo 看效果。