Start
最近公司要求所有的开发,无论是前端后端还是测开一律转成全栈,在Agent的辅助下转型,没招了,之前还有点精神洁癖想保持纯洁性的,这下真没招了,那就搞吧,出去面试还能多点钱呢,现在公司这里拿着前端的钱干着全栈的活搞几天吧,后面一定要跑路的🏃。
其实全栈这件事情没这么难,我说实话,再有了一定的语言基础之后,哪怕js和java一个是强类型语言一个是弱类型语言,但是前端其实很少用纯js写东西,都是ts,该有的东西其实都有,概念都知道是啥意思,无非就是换个语法形式写。如果之前做过node,尤其是用过像nest或者midway框架写过服务端,你会发现其实Spring什么的也就那样了,不要怕,上手写一下就好了,尤其是现在有AI,看不懂的就问AI,写不来的就AI写,反正要有后端帮你CR,大不了搞几个故障出来,让上面的老板知道一下半吊子全栈的厉害,顺手领个大礼包跑路这不是美滋滋~
好了,下面进入正文:
前端工程师的 Java 后端快速入门指南
这是一份专为有 JavaScript 基础的前端工程师准备的 Java 后端入门教程。我会用你熟悉的 JS 概念来对比讲解,帮你快速建立认知。
一、学习路线总览
arduino
阶段一:Java 语言基础(1-2 周)
├── 环境搭建(JDK + IDEA + Maven)
├── 基础语法(变量、类型、控制流)
├── 面向对象(类、接口、继承、多态)
└── 进阶特性(泛型、集合、异常、Lambda、Stream)
阶段二:构建工具与生态(3-5 天)
├── Maven / Gradle(类似 npm)
└── 依赖管理与项目结构
阶段三:核心框架(2-3 周)
├── Spring / Spring Boot(核心,类似 Express 全家桶)
├── MyBatis / MyBatis-Plus(操作数据库,类似 ORM)
└── Spring MVC(写接口)
阶段四:实战配套(持续)
├── 数据库(MySQL)
├── Redis(缓存)
├── 接口测试(Postman)
└── 部署(Docker、服务器)
二、环境搭建(先动手)
| 工具 | 作用 | 前端类比 |
|---|---|---|
| JDK 17+ | Java 运行环境和编译器 | Node.js |
| IntelliJ IDEA | 开发工具(社区版免费) | VS Code |
| Maven | 包管理 + 构建工具 | npm + webpack |
安装 JDK 后,验证:
bash
java -version
javac -version
三、语法对比:从 JS 到 Java
核心区别先认知
| 维度 | JavaScript | Java |
|---|---|---|
| 类型系统 | 动态弱类型 | 静态强类型(必须声明类型) |
| 运行方式 | 解释执行 | 先编译成字节码再运行 |
| 一切皆... | 一切皆对象(函数也是) | 一切皆类(代码必须在类里) |
| 分号 | 可选 | 必须 |
1. 变量声明
javascript
// JavaScript
let name = "张三";
const age = 18;
var flag = true;
let num = 3.14;
java
// Java:必须先声明类型
String name = "张三"; // 字符串
final int age = 18; // final = JS 的 const
boolean flag = true;
double num = 3.14;
// Java 10+ 也支持类型推断(但仍是静态类型)
var city = "北京"; // 编译器自动推断为 String
2. 基本数据类型(这是 JS 没有的概念)
JS 只有 number,Java 把数字分得很细:
java
// 整数类
byte b = 1; // 1字节
short s = 2; // 2字节
int i = 100; // 4字节,最常用
long l = 100L; // 8字节,注意加 L
// 浮点
float f = 1.5f; // 注意加 f
double d = 3.14; // 最常用的小数类型
// 其他
char c = 'A'; // 单个字符,用单引号
boolean flag = true;
关键点 :基本类型(小写 int)和包装类型(大写 Integer)的区别。 集合、泛型里必须用包装类型:
List<Integer>而不是List<int>。
3. 字符串
javascript
// JS
let s = "hello";
let str = `你好 ${name}`; // 模板字符串
let len = s.length; // 属性
java
// Java:String 是一个类,length() 是方法
String s = "hello";
int len = s.length(); // 注意是方法,要括号
// 拼接
String str = "你好 " + name;
// Java 15+ 文本块(类似模板字符串的多行)
String json = """
{
"name": "张三"
}
""";
// 字符串格式化
String msg = String.format("你好 %s,今年 %d 岁", name, age);
4. 控制流(基本一样)
java
// if-else 一致
if (age >= 18) {
System.out.println("成年");
} else {
System.out.println("未成年");
}
// for 循环一致
for (int i = 0; i < 10; i++) {
System.out.println(i);
}
// 增强 for(类似 JS 的 for...of)
int[] arr = {1, 2, 3};
for (int item : arr) {
System.out.println(item);
}
// switch(Java 14+ 新写法很好用)
String result = switch (age) {
case 18 -> "成年了";
case 1, 2, 3 -> "小孩";
default -> "其他";
};
5. 函数(方法)
javascript
// JS:函数是一等公民,可以独立存在
function add(a, b) {
return a + b;
}
const add2 = (a, b) => a + b;
java
// Java:方法必须写在类里,且要声明返回类型和参数类型
public int add(int a, int b) {
return a + b;
}
// 无返回值用 void
public void printName(String name) {
System.out.println(name);
}
// 修饰符说明:
// public = 访问权限(公开)
// int = 返回值类型
// add = 方法名
四、面向对象:Java 的核心
JS 也有 class,但 Java 的 OOP 更严格、更体系化。
1. 类与对象
javascript
// JS
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
sayHi() {
return `我是 ${this.name}`;
}
}
const p = new Person("张三", 18);
java
// Java
public class Person {
// 1. 成员变量(字段)需要声明类型
private String name;
private int age;
// 2. 构造方法(方法名 = 类名,无返回值)
public Person(String name, int age) {
this.name = name;
this.age = age;
}
// 3. getter / setter(Java 习惯用私有字段 + 公开方法访问)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
// 4. 普通方法
public String sayHi() {
return "我是 " + name;
}
}
// 使用
Person p = new Person("张三", 18);
System.out.println(p.sayHi());
2. 访问修饰符(JS 几乎没有的概念)
| 修饰符 | 含义 |
|---|---|
public |
任何地方都能访问 |
private |
只能在本类访问(最常用于字段) |
protected |
本类 + 子类访问 |
| 不写 | 同一个包内访问 |
3. 继承
java
// extends 关键字(和 JS 一样)
public class Student extends Person {
private String school;
public Student(String name, int age, String school) {
super(name, age); // 调用父类构造,类似 JS 的 super()
this.school = school;
}
// @Override 注解表示重写父类方法
@Override
public String sayHi() {
return "我是学生 " + getName();
}
}
4. 接口(重点,JS 里基本没有)
接口 = 一套规范/契约,只定义"能做什么",不实现。
java
// 定义接口
public interface Animal {
void eat(); // 抽象方法,没有方法体
void sleep();
}
// 实现接口用 implements
public class Dog implements Animal {
@Override
public void eat() {
System.out.println("狗吃骨头");
}
@Override
public void sleep() {
System.out.println("狗睡觉");
}
}
TS 程序员会很熟悉 :和 TypeScript 的
interface概念类似,但 Java 接口是运行时真实存在的。
5. 抽象类
java
// 抽象类:介于普通类和接口之间,可以有实现也可以有抽象方法
public abstract class Shape {
abstract double area(); // 抽象方法,子类必须实现
public void print() { // 普通方法,可直接继承使用
System.out.println("面积是:" + area());
}
}
五、集合框架(类似 JS 的数组和对象)
javascript
// JS
let arr = [1, 2, 3];
let map = { name: "张三" };
let set = new Set([1, 2, 3]);
java
import java.util.*;
// List:有序可重复,类似 JS 数组
List<String> list = new ArrayList<>();
list.add("a");
list.add("b");
String first = list.get(0);
int size = list.size();
// Map:键值对,类似 JS 对象/Map
Map<String, Integer> map = new HashMap<>();
map.put("张三", 18);
Integer age = map.get("张三");
// Set:不重复集合
Set<String> set = new HashSet<>();
set.add("a");
set.add("a"); // 重复无效
// 遍历 Map
for (Map.Entry<String, Integer> entry : map.entrySet()) {
System.out.println(entry.getKey() + ":" + entry.getValue());
}
六、泛型(和 TS 泛型类似)
泛型 = 类型参数化,让代码复用且类型安全。
typescript
// TypeScript
function identity<T>(arg: T): T {
return arg;
}
let list: Array<string> = [];
java
// Java 泛型
// 1. 泛型方法
public <T> T identity(T arg) {
return arg;
}
// 2. 泛型在集合中(最常见)
List<String> names = new ArrayList<>(); // 只能放 String
// 3. 自定义泛型类
public class Box<T> {
private T content;
public void set(T content) {
this.content = content;
}
public T get() {
return content;
}
}
// 使用
Box<String> box = new Box<>();
box.set("hello");
String s = box.get();
后端开发中你会大量见到泛型,比如统一返回结果
Result<User>、分页Page<Order>。
七、Lambda 与 Stream(前端会爱上的部分)
Java 8 引入了函数式编程,和 JS 的数组方法极其相似。
javascript
// JS
let nums = [1, 2, 3, 4, 5];
let result = nums
.filter(n => n > 2)
.map(n => n * 2)
.reduce((a, b) => a + b, 0);
java
// Java Stream(链式调用,几乎一一对应)
List<Integer> nums = List.of(1, 2, 3, 4, 5);
int result = nums.stream()
.filter(n -> n > 2) // 过滤
.map(n -> n * 2) // 映射
.reduce(0, Integer::sum); // 归约
// 收集成 List
List<Integer> doubled = nums.stream()
.map(n -> n * 2)
.collect(Collectors.toList());
// forEach
nums.forEach(n -> System.out.println(n));
| JS 数组方法 | Java Stream |
|---|---|
.filter() |
.filter() |
.map() |
.map() |
.reduce() |
.reduce() |
.forEach() |
.forEach() |
.find() |
.findFirst() |
.some() |
.anyMatch() |
.every() |
.allMatch() |
八、异常处理
javascript
// JS
try {
throw new Error("出错了");
} catch (e) {
console.log(e.message);
} finally {
console.log("结束");
}
java
// Java:异常是分类型的
try {
int result = 10 / 0;
} catch (ArithmeticException e) { // 捕获特定异常
System.out.println("除零错误:" + e.getMessage());
} catch (Exception e) { // 兜底
System.out.println("其他错误");
} finally {
System.out.println("结束");
}
// 主动抛异常
throw new RuntimeException("自定义错误");
九、构建工具 Maven(类似 npm)
pom.xml 相当于 package.json:
xml
<project>
<groupId>com.example</groupId> <!-- 组织名 -->
<artifactId>demo</artifactId> <!-- 项目名 -->
<version>1.0.0</version>
<!-- 依赖,类似 dependencies -->
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
</project>
| Maven 命令 | npm 类比 |
|---|---|
mvn install |
npm install |
mvn package |
npm run build |
mvn test |
npm test |
Maven 会从中央仓库下载 jar 包到本地
.m2目录(类似 node_modules,但全局共享)。
十、核心框架介绍
框架是干什么的?
| 框架 | 作用 | 前端类比 |
|---|---|---|
| Spring | 整个生态的核心,管理对象、解耦 | 类似 Angular 的依赖注入体系 |
| Spring Boot | 简化 Spring 配置,开箱即用 | 类似 create-react-app / Vite 脚手架 |
| Spring MVC | 处理 HTTP 请求,写接口 | 类似 Express 的路由 |
| MyBatis / MyBatis-Plus | 操作数据库 | 类似 Prisma / TypeORM |
| MySQL | 关系型数据库 | 数据存储 |
| Redis | 内存缓存 | 缓存数据 |
核心概念:IoC 与依赖注入
这是 Spring 的灵魂。
javascript
// 传统方式:自己 new 对象
class UserService {
constructor() {
this.userDao = new UserDao(); // 自己创建依赖
}
}
java
// Spring:由容器创建和注入对象,你只管"要"
@Service
public class UserService {
@Autowired // 自动注入,不用自己 new
private UserDao userDao;
}
理解:Spring 帮你管理所有对象(叫 Bean),需要的时候自动"喂"给你,让代码解耦。
十一、Spring Boot 快速上手
1. 创建项目
访问 start.spring.io,选择:
- Project: Maven
- Language: Java
- 依赖勾选:
Spring Web、MyBatis Framework、MySQL Driver
下载后用 IDEA 打开。
2. 项目结构
bash
src/main/java/com/example/demo/
├── DemoApplication.java # 启动入口(类似 main.js)
├── controller/ # 接口层(类似路由)
├── service/ # 业务逻辑层
├── mapper/ # 数据库操作层
└── entity/ # 数据模型(类似 model)
src/main/resources/
└── application.yml # 配置文件(类似 .env + config)
3. 启动类
java
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
4. 写一个接口(对比 Express)
javascript
// Express
app.get('/user/:id', (req, res) => {
res.json({ id: req.params.id, name: "张三" });
});
java
// Spring MVC
@RestController // 声明这是接口控制器
@RequestMapping("/user") // 路由前缀
public class UserController {
@GetMapping("/{id}") // GET /user/{id}
public User getUser(@PathVariable Long id) {
User user = new User();
user.setId(id);
user.setName("张三");
return user; // 自动转成 JSON
}
@PostMapping // POST /user
public String create(@RequestBody User user) { // 接收 JSON body
return "创建成功:" + user.getName();
}
// 接收查询参数 ?name=xxx
@GetMapping("/search")
public String search(@RequestParam String name) {
return "搜索:" + name;
}
}
常用注解对照:
| Spring 注解 | 作用 |
|---|---|
@RestController |
标记接口类,返回 JSON |
@GetMapping/@PostMapping |
对应 HTTP 方法 |
@PathVariable |
路径参数 /user/1 |
@RequestParam |
查询参数 ?name=x |
@RequestBody |
请求体 JSON |
5. 配置数据库
application.yml:
yaml
server:
port: 8080
spring:
datasource:
url: jdbc:mysql://localhost:3306/test
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
6. MyBatis-Plus 操作数据库(推荐入门)
java
// 1. 实体类,对应数据库表
@Data // Lombok 注解,自动生成 getter/setter
@TableName("user")
public class User {
@TableId
private Long id;
private String name;
private Integer age;
}
// 2. Mapper 接口,继承后自动拥有增删改查
public interface UserMapper extends BaseMapper<User> {
// 基础 CRUD 都内置了,复杂查询才需要自己写
}
// 3. 在 Service 中使用
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
public User getById(Long id) {
return userMapper.selectById(id); // 内置方法,直接查
}
public void add(User user) {
userMapper.insert(user); // 内置插入
}
public List<User> list() {
return userMapper.selectList(null); // 查全部
}
}
7. 完整调用链
markdown
HTTP 请求
↓
Controller(接收参数)
↓
Service(业务逻辑)
↓
Mapper(数据库操作)
↓
MySQL
十二、学习建议与实战路径
推荐第一个练手项目:用户管理系统
实现这些功能,把上面知识串起来:
- 用户的增删改查接口(CRUD)
- 分页查询
- 统一返回结果封装
- 全局异常处理
- 用 Postman 测试接口
统一返回结果(实战必备)
java
// 用泛型封装统一返回格式
@Data
public class Result<T> {
private int code;
private String message;
private T data;
public static <T> Result<T> success(T data) {
Result<T> result = new Result<>();
result.code = 200;
result.message = "成功";
result.data = data;
return result;
}
}
// 使用
@GetMapping("/{id}")
public Result<User> getUser(@PathVariable Long id) {
User user = userService.getById(id);
return Result.success(user);
}
学习顺序总结
markdown
1. 先把语法部分敲一遍(1周)------ 重点:类、接口、集合、泛型、Stream
2. 搭一个 Spring Boot 项目跑通 Hello World
3. 写第一个 GET 接口,用 Postman 调通
4. 接数据库,实现完整 CRUD
5. 完善:分页、异常处理、参数校验
6. 进阶:Redis 缓存、登录鉴权(JWT)、文件上传
给前端的几条心法
- 拥抱类型系统:刚开始觉得啰嗦,但它能帮你在编译期发现错误,写惯了 TS 的话很快适应。
- 理解"一切都在类里":Java 没有游离的函数,所有代码都在类的方法里。
- Spring 的核心是 IoC:先用起来,不用一开始就深究原理。
- 善用 IDEA:自动补全、自动导包、重构功能极强,比手敲快很多。
- Lombok 必装 :
@Data注解省去大量 getter/setter 样板代码。
结语
作为前端,JS/TS 经验会大大加速 Java 学习。最大的门槛是静态类型思维 和面向对象的体系化设计。先动手把一个 CRUD 项目跑通,比看一百遍教程都管用。