极简 Java 入门
极简 Java 入门
概述
语言的学习
很多人说“我要学习 Python”,但如果深入问一句:“你是想用 Python 做什么?”这时候答案往往就会变得具体起来——有人是为了做 AI,有人是为了数据处理,有人是为了 Web 开发。如果没有明确的回答,这门语言大概率无法顺利地学下去,学习外语也是这样。在具体场景中使用一门语言发挥生产力,实际上要是掌握它在各个领域的应用场景、业务流程和最佳实践。拿 Python 举例:
- 如果是做 AI 的,重点可能在 PyTorch、JAX、Transformers 等深度学习框架;
- 如果是搞数据分析的,可能围绕 pandas、NumPy、matplotlib、Scikit-learn;
- 做 Web 的,会涉及 Django、Flask、FastAPI;
- 自动化脚本、爬虫、数据处理、脚本化工具也是 Python 的强项。
当然,光去记住这些库的说明书,对于理解这个库其实也没有什么帮助,尤其是现在有了大模型的情况下,关键是要理解整个流程。在这种背景下,一种比较高效的学习路径是:
先快速建立基本图像,然后基于某个具体应用方向纵向跑通业务流程,最后在横向拓展功能的过程中,逐渐掌握更多语言细节。
Java 应用
Java 最典型的标签就是“企业级开发”。换句话说,Java 的主战场是中后台系统、Web 服务、微服务架构、大型分布式系统。
Java 生态中最核心的技术栈就是:
Spring 全家桶(Spring Framework、Spring Boot、Spring MVC、Spring Cloud)
Spring 系列提供了企业开发中几乎所有需要的能力:控制反转(IoC)、依赖注入(DI)、Web 框架、数据库访问、安全认证、分布式配置、服务注册与发现、微服务通信、消息中间件等。
除了 Spring 生态,Java 在以下领域也有成熟的支持:
领域 | 技术栈 |
---|---|
持久化(ORM) | Hibernate、JPA、MyBatis |
构建工具 | Maven、Gradle |
单元测试 | JUnit、Mockito |
Web 应用 | Spring Boot、Jakarta EE、Servlet |
微服务 | Spring Cloud、Dubbo |
安全认证 | Spring Security、OAuth2 |
前后端接口通信 | RESTful API、JSON、Jackson、Feign |
云原生 | Spring Cloud + Kubernetes、Spring Boot Docker 化部署 |
运维监控 | Actuator、Micrometer、Prometheus |
总之,学习 Java,最重要的不只是掌握它的语法,而是理解它在“企业级应用”这条主航道上的生态布局,尤其是围绕 Spring 为核心的一整套解决方案。所以,与其去啃厚重的语法教程,不如从一个简单的 Spring Boot 项目入手,跑通第一个接口,理解 MVC 流程,再逐步拓展数据库访问、配置管理、接口返回、安全控制等功能,然后更多地熟悉这个语言。
Java 底线知识
语言类型
按程序的执行方式划分,编程语言大致可以分为三类:
🟡 解释型语言
如 Shell、Python,这类语言不需要预先编译,源代码由解释器逐行读取并执行。因为不直接和系统底层打交道,跨平台能力很强,开发调试也很灵活。不过也因此牺牲了部分执行效率。例如运行 Python 脚本时,其实是 Python 解释器在实时翻译并执行代码。
🔵 编译型语言
如 C、C++,编写好的源码需要通过编译器编译成特定平台的机器码,生成
.exe
或.out
文件,才能执行。这类语言的优势是运行效率高、控制能力强,但每个平台都需要重新编译一次,跨平台不太友好。🟩 中间型语言 / 混合型语言
代表语言有 Java 和 C#,这类语言先将源码编译为一种平台无关的“中间语言”格式(如 Java 字节码、C# 的 IL),再由虚拟机运行。这样既保持了一定的跨平台能力,又能通过虚拟机的优化(如 JIT)获得不错的执行效率。
Java 是中间型语言的典型代表,它的执行流程大致如下:
- 开发者编写
.java
源代码; - 使用 JDK 中的
javac
命令将源码编译为.class
文件,其中包含了 Java 的 字节码; - 执行
java 类名
(如java HelloWorld
),由 JVM(Java 虚拟机) 加载.class
文件,并执行其中的字节码。
Java 虚拟机会将字节码逐条解释执行,也可能通过 JIT(即时编译) 技术将热代码优化为机器码,提高性能。
这一模式让 Java 实现了它的核心口号:
Write Once, Run Anywhere(一次编写,到处运行)
只要系统中安装了 JVM,不论是 Windows、Linux 还是 macOS,都可以运行相同的 .class
文件,无需重新编译。当然,在实际开发中,我们不会每次都手动敲 javac
和 java
。这就像我们不会在每个 Node.js 项目里手动用 node
跑 .js
文件,而是用 npm run dev
启动前端服务、用 vite
创建 Vue 项目、或者用 webpack
进行构建打包。
Java 也有类似的构建工具,常见的有 Maven 和 Gradle,它们可以帮助我们自动编译 Java 代码、管理依赖(比如引入第三方库)、打包成可运行的 .jar
文件、执行单元测试、部署、生成文档等。构建工具在实际项目中非常关键,不过我们可以先了解 Java 的语言机制和基本运行方式,后续再深入 Maven 等工具的使用。
JDK 和 JRE
在使用 Java 进行开发时,两个最常被提到的组件是 JDK(Java Development Kit) 和 JRE(Java Runtime Environment)。它们虽然经常一起出现,但其实职责不同:
- JRE 是“运行环境”:它包含了 Java 虚拟机(JVM)和 Java 标准类库,目的是让你能够运行
.class
文件(字节码)。 - JDK 是“开发工具包”:它包含了 JRE,同时还额外提供了编译器
javac
、调试器、打包工具等,目的是为了编写和构建 Java 程序。
比如我们写了一个最简单的 HelloWorld.java
程序(具体的语法后面再介绍):
1 | // HelloWorld.java |
这个程序的执行流程分为两步:
使用 JDK 提供的编译器,将源码编译为字节码:
1
javac HelloWorld.java
这会生成一个
HelloWorld.class
文件,里面是 Java 的中间表示(字节码)。使用 Java 虚拟机运行字节码:
1
java HelloWorld
控制台就会输出:
1
Hello World!
所以简单来说,JRE 是“跑 Java 程序”的工具,JDK 是“写 Java 程序”的工具。由于 JDK 本身就包含了完整的 JRE,我们在安装 Java 时只需要安装 JDK 就足够了。反过来,如果只安装了 JRE,就没法编译 .java
文件(因为它没有 javac
),也就无法完整开发 Java 程序。
在安装了 JDK 后,有一个非常重要的系统变量叫做 JAVA_HOME
,它的作用是告诉操作系统和各种工具,JDK 安装在哪里。比如像 Maven、Gradle、IDEA、Eclipse 等工具,都会通过读取 JAVA_HOME
变量来找到正确的 java
和 javac
命令。我们在安装了 JDK 后,需要新建一个把这个变量设置为我们的安装目录,比如 C:\Program Files\Java\jdk-17
。
JAR 包
Java 程序在开发完成并编译成 .class
文件后,通常会进一步打包成一种特殊格式 —— JAR 包(Java ARchive),这是 Java 世界中最常见的打包形式。JAR 本质上是一个压缩文件(类似 .zip
),它可以包含:
- 编译好的
.class
字节码; - 程序依赖的资源文件(如配置文件、图片等);
- 一个
MANIFEST.MF
文件,用于定义元信息,比如程序入口类; - 可选的第三方依赖。
作用类似于 Python 中的 .whl
文件、Node.js 的 npm 包
,用于程序分发、部署、共享。
Java 概念 | 类比 Python 中的概念 |
---|---|
.class 文件 |
.pyc 字节码文件 |
.jar 包 |
.whl 包(wheel),或 .pyz 可执行包 |
manifest |
setup.py 中的 entry_points 或 __main__.py |
mvn package |
python setup.py sdist / pip install . |
第三方 jar | Python 的依赖库(如 numpy.whl) |
继续以上例子,我们已经有一个 HelloWorld.class
文件,现在我们希望把它打包成一个可运行的 jar 包。
步骤 1:编写 manifest 文件
新建一个 manifest.txt
,写入以下内容,指定程序入口类:
1 | Main-Class: HelloWorld |
之所以要这个东西,是因为一个 JAR 包中可以包含多个文件和多个公共类,而每个类理论上都可以有自己的 main()
方法(入口点)。所以 JVM 并不知道我们到底想运行哪个类作为“主程序”。这个文件,会被传递给 jar
命令,在 JAR 包里生成 META-INF/MANIFEST.MF
文件,用于描述 JAR 包的入口。当然,假如我们只写了一堆工具类,别人只会 import
我们的类,而不是直接运行我们的 JAR 包,那么也就不需要这个文件了。
步骤 2:打包
使用 Java 自带的 jar
命令进行打包:
1 | jar cfm HelloWorld.jar manifest.txt HelloWorld.class |
解释:
c
:create(创建)f
:file(输出到文件)m
:manifest(使用自定义 manifest)
这会生成一个 HelloWorld.jar
包。
步骤 3:运行 jar 包
1 | java -jar HelloWorld.jar |
输出:
1 | Hello World! |
JAR 包可以把项目代码打成一个独立的应用(类似 Python 的 pyz),就像 Python 的 wheel 包一样,Java 的第三方库也几乎都是以 .jar
的形式分发的。多个 jar 可以组成一个大项目,像拼装积木一样。比如我们在使用 Spring Boot、Gson、Lombok 等库时,实际上它们的核心就是 .jar
包,只是通过 Maven 自动下载和管理而已。
Java 语法常识
Java 的语法和 C、C++ 十分类似,甚至对熟悉 C++ 的人来说,Java 的基础语法几乎可以直接读懂。但对于初学 Java 的开发者来说,仍有一些看起来“神秘”但实际很有逻辑的规则,尤其是关于类、方法、文件结构等。我们通过一个最简单的 Hello World 程序来逐步分析:
1 | // HelloWorld.java |
☝️ 第一:所有代码必须写在类中
Java 是一个 “纯面向对象” 的语言。和 Python 不同,Python 中我们可以在模块的最外层直接写表达式或函数:
1 | print("Hello World!") # 顶层语句,不需要类 |
而 Java 中,所有代码必须写在类或接口中,包括程序的入口函数。这是 Java 语言设计的基本原则。哪怕只是输出一行文字,也必须“包裹在类里”才能编译运行。
✌️ 第二:.java
文件只能有一个 public
类,且文件名必须与其一致
在 Java 中,一个 .java
文件中可以包含多个类,但最多只能有一个 public
类。而且这个 public
类的名称必须与文件名完全一致(大小写敏感)。
比如:
- 如果类名是
HelloWorld
,文件名必须是HelloWorld.java
; - 否则会报错:
类 HelloWorld 是公共的,应在名为 HelloWorld.java 的文件中声明
🤟 第三:main
方法是 Java 程序的入口
1 | public static void main(String[] args) |
这是 Java 程序的标准入口方法,JVM 在执行一个类时,会自动从这个方法开始执行。
public
:必须公开,JVM 才能访问;static
:不依赖对象就能运行(因为入口方法是在没有类实例的情况下运行的);void
:方法不返回任何值;String[] args
:命令行参数传入数组。
如果一个类中没有包含这个方法,运行它时就会报错:
1 | 错误: 在类 HelloWorld 中找不到 main 方法, 请将 main 方法定义为: |
✋ 第四:Java 的包与目录结构强绑定,导入类而非文件
在实际开发中,我们不可能所有代码都写在一个类里,会有多个 .java
文件。此时,就需要引入 Java 的包机制(package)来管理代码结构。
假设我们有如下目录结构:
1 | comac/ |
此时,Java 要求:
HelloWorld.java
中必须指定包名为:1
package comac;
Person.java
中必须指定包名为:1
package comac.submodule;
包名必须严格匹配目录结构(以根目录为起点),否则编译会报错。
🙌 使用 import
导入类,而不是导入文件
与 Python 不同,Java 的 import
是用来导入类或整个包中的类,而不是导入文件名。
假设在 Person.java
中写了一个类:
1 | // comac/submodule/Person.java |
要在 HelloWorld.java
中使用这个类,需要:
1 | // comac/HelloWorld.java |
也可以使用通配符一次导入一个包下的所有类:
1 | import comac.submodule.*; |
但不能像 Python 那样 import person
或导入整个文件——Java 的 import
是按类名来的,不是按文件名。
🔐 Java 中的访问权限与包结构关系
Java 对“类能否被访问”有一套清晰且严格的规则。前面也提到过了,Java 强制要求:
- 每个文件最多有一个
public
类; - 非
public
的类在“包内可见”,包外隐藏。
这种设计体现了 Java 的模块化思想:每个 .java
文件就是一个明确的“编译单元”,它对外只暴露一个清晰的“公共接口”。public
类相当于模块的“入口”,是我们愿意暴露给外部使用的部分;其他 default 类,则是模块内部的“实现细节”,不鼓励外部直接依赖。这种结构帮助 Java 项目在复杂工程中保持清晰的依赖边界。
需要注意的是,默认类只能在“同一包内”访问,即使是在“子包”中也不能访问!假设我们有如下结构:
1 | src/ |
文件内容如下:
1 | // com/example/HelloWorld.java |
1 | // com/example/utils/Helper.java |
虽然两个类文件目录上是“父子关系”,但包名不同 → 它们是完全不同的命名空间。default 权限只在“同一个包”里有效。
Maven
前面我们提到了,项目的包结构、用 JDK 编译、用 JRE 运行,以及管理第三方依赖等,如果每次都靠手动操作是非常繁琐且容易出错的。好在 Java 社区为此发展出了一套标准化的构建工具,最常用的就是:
工具 | 构建描述文件 | 特点说明 |
---|---|---|
Maven | pom.xml |
最主流的构建工具,强调约定优于配置 |
Gradle | build.gradle |
语法更现代(基于 Groovy 或 Kotlin) |
这两个工具可以自动生成标准的项目结构、编译项目源代码、管理和自动下载第三方依赖、运行测试用例、打包为可执行 JAR/WAR、甚至还支持部署和发布版本。相比来说,Maven 使用的更加广泛,Maven 使用 pom.xml
来配置项目的元信息以及管理依赖。如果我们之前接触过 Node 项目,可以这样理解:
npm 命令 | Maven 对应 |
---|---|
npm create vite |
mvn archetype:generate |
npm install |
自动解析 pom.xml 中依赖并下载 |
package.json |
pom.xml |
node_modules (局部依赖) |
.m2 目录(全局依赖缓存) |
不过与 npm 不同,Maven 并不是每个项目都保留一份依赖副本,而是把所有下载的依赖统一保存在用户主目录的 .m2/repository/
目录中,所有项目共享使用。可以通过设置 .m2/settings.xml
自定义这个缓存目录:
1 | <settings> |
Maven 初次执行时会联网下载构建工具本身的插件和模板,比如生成项目结构需要 maven-archetype-plugin
,编译代码需要 maven-compiler-plugin
,它们都来自 Maven 官方中央仓库,以后构建就不需要重新下载了。这些工具基本上都是 JAR 包及其相对应的 .pom
文件:
文件类型 | 示例文件名 | 含义 | 用途 |
---|---|---|---|
.jar |
maven-compiler-plugin-3.10.1.jar |
Java 的二进制包 | 这是插件/库的真正可执行代码 |
.pom |
maven-compiler-plugin-3.10.1.pom |
项目的元信息(Project Object Model) | 描述该 jar 包的依赖、作者、版本等信息 |
Maven 的依赖管理是基于 POM 文件构建的“依赖树”,Maven 首先读取 .pom
文件来知道这个 jar 依赖了哪些 jar(传递依赖),需要哪些插件协助编译/运行,然后才去下载 .jar
本体和它依赖的 jar。所以,没有 .pom
,Maven 无法知道构建图谱,也就无法自动化下载和解析依赖。我们后面可以通过 mvn install
来让 Maven 安装我们自己的项目到全局目录中,Maven 会自动生成项目的 .pom
文件。这整个流程其实和 Python 也很类似:
Java Maven | Python |
---|---|
my-lib-1.0.jar |
my_lib-1.0-py3-none.whl |
my-lib-1.0.pom |
setup.py or pyproject.toml |
mvn install |
pip install . (安装到 site-packages) |
发布到远程 Maven 仓库 | 发布到 PyPI |
最简单的 Maven 项目
我们可以使用 Maven 的脚手架快速生成一个 Java 项目模板:
1 | mvn archetype:generate -DgroupId=com.mycompany.app -DartifactId=my-app -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false |
参数说明如下表所示:
参数名 | 含义 |
---|---|
groupId |
包名/组织名(约定域名反写,确保包名在全球范围不冲突。如果公司官网是 www.comac.com ,那么域名反写后就是 com.comac ) |
artifactId |
项目名(将成为生成 jar 的名字) |
archetypeArtifactId |
使用哪个模板构建(此处为最简模板) |
interactiveMode=false |
关闭交互式问答,直接生成 |
生成的目录结构大体如下所示,Maven 会默认把 src/main/java
当作项目源代码的根目录,因此 .java
文件中 package
字段都要以这个根目录节点开始算起:
1 | my-app/ |
App.java
默认是一个输出 Hello World!
的入口类,在项目根目录执行:
1 | mvn compile |
会将 .java
编译为 .class
文件,输出到:
1 | target/classes/ |
我们可以运行:
1 | mvn exec:java -Dexec.mainClass=com.mycompany.app.App |
来使用 Maven 的 exec 插件执行编译好的 .class
文件。如果我们没有在 pom.xml
中手动指定 exec
的插件版本,那么 Maven 会自动下载最新兼容版本的 exec 插件来执行这个命令。和之前一样,Maven 会下载相应的 JAR 包放到全局目录里。
我们也可以在 pom.xml
中进行打包相关的配置:
1 | <build> |
上面的配置指定了插件和入口类:
元素 | 作用 |
---|---|
groupId |
插件所属组织(通常是 Maven 官方) |
artifactId |
插件名称,这里是构建 JAR 的插件 |
version |
插件的具体版本号 |
mainClass (在 manifest 中) |
指定打包后 JAR 的程序入口类,用于 java -jar 启动 |
执行:
1 | mvn package |
会生成一个可执行的 JAR 文件:
1 | target/my-app-1.0-SNAPSHOT.jar |
用以下命令可以直接运行:
1 | java -jar target/my-app-1.0-SNAPSHOT.jar |
Spring Boot
有了上面的基本概念,我们就可以正式开始 Spring Boot 的开发实践了。
Spring 是一个庞大的 Java 开发生态系统,可以类比 Python 的科学计算生态。例如:
- Python 的 NumPy 是底层基础,Pandas、Scikit-learn、Matplotlib 等都是在它上面构建的;
- Java 的 Spring 也是底层框架,围绕它构建了众多子项目,比如 Spring Boot、Spring Security、Spring Cloud、Spring Data 等等。
Spring 本质上是一种组件式开发框架,它提供了 IoC(控制反转)容器、AOP(面向切面编程)、统一配置和资源管理机制、声明式事务管理等基础能力。在这个基础之上,Spring 团队和社区开发了大量用于特定场景的组件:
框架 | 用途 |
---|---|
Spring Boot | 快速构建独立、可部署的 Spring 应用 |
Spring Security | 安全框架,处理认证、授权、加密等 |
Spring Data JPA | 数据访问抽象,简化数据库交互 |
Spring Cloud | 构建分布式微服务系统 |
Spring Batch | 大批量数据处理 |
Spring WebSocket | 实现实时通信 |
... | ... |
其中,Spring Boot 是 Spring 家族中最受欢迎的子项目之一,它的设计目标就是为了大幅简化 Spring 应用的创建、配置和部署。如果是第一次接触 Spring Boot,可以将它理解为一个“快速开发的 Web 框架”,它通过约定大于配置的方式,封装了大量 Spring 的繁琐配置,降低了开发门槛。使用 Spring Boot,有几个明显优势:
- 可以一键启动应用,不再需要部署到外部的 Tomcat 或 WebLogic;
- 内置了常用中间件和技术栈的整合方案(如 Web、JPA、Redis、Security 等);
- 通过 Starter 和自动装配机制,按需添加依赖,按需激活功能;
- 提供了大量运维工具,比如应用健康检查、日志、监控接口(Actuator);
- 支持热部署、命令行运行、Docker 化部署、Kubernetes 集成等现代开发方式。
所以说,Spring Boot 就像是为 Java 后端开发者准备的一整套后端“车间”:一旦搭好结构,就可以专注在业务逻辑本身,无需为框架拼装浪费太多时间。
我们先不考虑什么复杂的应用,假如我们就要开发一个最简单的 Web 服务,访问 /
返回 Hello World!
。
在 Flask 中,我们只需要写几行代码:
1 | from flask import Flask |
Flask 自动帮我们完成了 HTTP 服务器的搭建、请求处理流程、路由注册等任务,非常轻量。
那使用 Spring Boot 完成相同的功能,需要做哪些工作呢?
项目初始化
首先,我们可以在 start.spring.io 网站上通过 Spring Initializr 工具初始化我们的 Spring 项目。这一步就像是为我们预先打包好一个标准化的工程骨架。在初始化页面中,我们选择语言为 Java,构建工具为 Maven,Spring Boot 版本可选择稳定的 3.x 或尝试最新的 4.0.0 M1(里程碑版本)。然后填写项目信息,例如:
- Group:
com.comac.data
(推荐使用公司域名反写形式) - Artifact:
demo
- Package name:
com.comac.data.demo
- Java 版本:24
接着在右侧“Dependencies”中添加两个常用依赖:
- Spring Boot DevTools:它是一种开发辅助工具,支持代码修改后自动重启应用,相当于 Flask 的 debug 模式;
- Spring Web:提供了 Web MVC、REST API、JSON 转换等核心功能,是开发 Web 服务必备的模块。

点击 “Generate” 按钮后,即可下载生成的 Maven 项目源码包。解压后,我们可以看到一个符合 Maven 规范的标准 Java 项目结构。
项目结构
在标准的 Spring Boot Web 项目中,通常会有如下几个核心部分。当然这里的内容已经超出了这个博客的原本范围,这里也只是让我自己有一个大致了解。
1 | src/ |
启动类:DemoApplication.java
1 |
|
该类包含 main()
方法,整个应用的启动入口,执行后会启动 Spring 容器、自动扫描所在包及子包的组件、启动内嵌服务器(Tomcat)。运行这个类之后,Spring Boot 就会在默认端口 8080
启动服务,我们的应用就上线了。如果我们在 Vscode 中要启动热更新,则还要开启 Java 的自动编译。我们可以在终端里执行:
1 | mvn spring-boot:run |
来启动应用,也可以在 Vscode 里直接点击 Run 来运行应用,它会调用 Java 来执行 .class
文件。
控制器类(Controller):路由处理器
1 |
|
控制器类负责处理 HTTP 请求,类似 Flask 的 @app.route
。
@RestController
=@Controller + @ResponseBody
,默认返回 JSON 或字符串@GetMapping
/@PostMapping
/@PutMapping
/@DeleteMapping
映射到 HTTP 方法@RequestMapping
可以统一设置路由前缀
这里的 @
都是注解(Annotation),本质上和 Python 的装饰器类似,为类或方法添加元信息,供框架在运行时读取并处理。上面的 @RestController
的作用,就像 Flask-Restful 中的一个资源类。我们可以在这个类里用 @GetMapping
、@PostMapping
等注解开发对应 HTTP 方法的处理函数。
服务类(Service):业务逻辑层
1 |
|
- 放业务处理逻辑(如计算、合并数据、调用第三方 API)
- 控制器中调用服务层方法来获取/处理数据
- 使用
@Service
注解标记为 Spring 管理的组件
大概就是 Spring 提供了某些事件管理机制,@Service
就是告诉 Spring 这个类是处理业务逻辑的,Spring 会为他提供一些管理方法。在 Flask 的开发中,虽然我们也会大致分成 路由 -> 服务 -> 数据 这么三层,但是不需要通过注解告诉框架每个类的作用,因为 Flask 很轻量没有提供这些管理功能。
数据访问类(Repository / DAO):数据层(操作数据库)
1 |
|
- 和数据库打交道的地方
- 一般使用 Spring Data JPA、MyBatis、JDBC 等工具
@Repository
是 Spring 管理的持久层组件(带异常转换)
Spring 会明确这个类是数据访问层的,执行一些自动管理操作,比如自动将底层数据库异常转换到 Spring 的统一异常体系。
配置文件:全局设置(端口、数据库、日志等)
路径:src/main/resources/application.yml
或 application.properties
1 | server: |
听说推荐用依赖注入的方式读取,这个后面再慢慢总结。
静态资源
src/main/resources/static/
:放图片、JS、CSS,浏览器可以直接访问src/main/resources/templates/
:放模板文件(如 Thymeleaf)
Hello World!
我们开发一个最简单的 Spring 项目,提供一个简单的问候接口:
1 | package com.comac.data.demo.controller; |
运行入口类后,访问 127.0.0.1:8080
,就可以看到 Hello World!
了。