嘿,朋友,欢迎来到Java的世界。
如果你现在正盯着屏幕发呆,或者刚配好环境却不知道下一步该干嘛,别急,我懂那种感觉。十年前我也和你一样,对着满屏的public static void main不知道这玩意儿到底能干嘛。今天咱们不整那些虚头巴脑的官方文档,我就当是你隔壁那个写代码很溜的学长,手把手带你从那个只会打印“Hello World”的小白,一路通关到能用Spring Boot写出像模像样的后端系统。
这条路我走过,有点坑,也有点风景,咱们慢慢聊。
第一章:别让“Hello World”成为你的终点,但别跳过它
很多人看不起Hello World,觉得这太简单了,是小孩玩意儿。但我告诉你,理解Hello World,比写一百行业务代码都重要。
1.1 真正的Java入门:不只是打印
当你写下:
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello, Java!");
}
}
你觉得你是在学Java吗?是的,但更重要的是,你在理解程序是怎么跑起来的。
public class:Java是面向对象的,一切皆类。你没有类,代码就跑不起来。main方法:这是程序的入口,JVM(Java虚拟机)会从这里开始执行。String[] args:虽然你暂时用不到,但这是操作系统给你传参数的通道。
给你的小建议:别急着往下走。把这段代码改成打印你的姓名、年龄,再改成接受命令行参数输入名字并打招呼。你要建立起“代码是跟机器对话”的感觉。
1.2 环境配置:别被JDK劝退
这是第一个大坑。很多人卡在“环境变量配不上”这一步,然后放弃。
- JDK版本:现在主流是Java 17(LTS长期支持版)或Java 21。别学Java 8了,虽然它还活着,但新技术都在17+。
- IDE:我强烈建议你直接用 IntelliJ IDEA Community Edition。它比Eclipse智能十倍,比VS Code对Java支持更原生。安装后,新建项目时选“Maven”或“Gradle”,别选空项目。
1.3 基础语法:把这块啃下来
在你碰Spring之前,你必须对以下概念如指掌:
- 变量与数据类型:int, double, String, boolean。记住,Java是强类型语言,
int a = "hello"会报错,这是好事,它能帮你提前发现bug。 - 控制流:if-else, for, while, switch。
- 数组与集合:这是重点!List, Set, Map 你得滚瓜烂熟。Spring内部大量使用这些结构,你不会它们,看源码就像看天书。
- 面向对象三大特性:封装、继承、多态。特别是接口(Interface),Spring的灵魂就是面向接口编程,这块必须搞懂。
实战练习:写一个简单的“学生管理系统”,用命令行操作。能完成添加学生、查询学生、删除学生,你就过了基础关。
第二章:桥梁篇——为什么我们需要Maven/Gradle和Git?
你学会了写Java代码,但你的项目可能只有src文件夹和一堆.class文件。这时候你需要构建工具和版本控制。
2.1 Maven:依赖管理的救星
想象一下,你要做个Web项目,需要处理JSON,需要连接数据库,需要写单元测试。如果你手动去下载jar包,导入项目,那简直是噩梦。
Maven帮你自动化这一切。你只需要在pom.xml里写:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>3.2.0</version>
</dependency>
</dependencies>
然后Maven会自动去中央仓库下载这个包及其所有依赖。
核心概念:
- 坐标(GAV):GroupId, ArtifactId, Version。这是依赖的唯一身份证。
- 生命周期:clean, compile, test, package, install, deploy。
- 作用域:
compile(默认)、test(只测试用)、provided(容器提供,如Servlet API)。
2.2 Git:代码的时间机器
你不存Git,相当于你不备份手机照片。而且,Spring Boot的官方示例、GitHub上的开源项目,都依赖Git。
- 基本操作:
git init,git add,git commit,git push,git pull。 - 分支管理:学会用
branch,别在主分支上乱改。 - GitHub/GitLab:注册一个账号,把你的Hello World项目传上去。看着绿色的提交记录,成就感爆棚。
第三章:HTTP与Web基础——Spring Boot的前置技能
Spring Boot本质上是用来做Web开发的(当然也能做其他事)。但你得先懂Web是怎么工作的。
3.1 HTTP协议:浏览器和服务器怎么聊天
你不需要成为网络专家,但必须知道:
- 请求方法:GET(查), POST(增), PUT(改), DELETE(删)。
- 状态码:200(成功), 404(没找到), 500(服务器崩了), 401(没登录)。
- Header:Content-Type(告诉对方我发的是什么格式的数据,比如application/json), Authorization(认证信息)。
- Body:请求体里装的具体数据。
模拟练习:用Postman或curl发一个HTTP请求,比如curl https://api.github.com,看看返回的是什么。
3.2 RESTful API设计:前后端协作的通用语言
现在的后端,基本都是REST风格。简单说,就是用URL和资源来映射业务,用HTTP方法来表达操作。
- 获取用户列表:
GET /api/users - 创建用户:
POST /api/users - 更新用户:
PUT /api/users/1 - 删除用户:
DELETE /api/users/1
不要搞成GET /getUser?id=1这种老派风格,虽然能用,但不够专业。
第四章:Spring Boot初体验——从“麻烦”到“简单”
好了,前面的基础你打得差不多了。现在,我们进入正题:Spring Boot。
4.1 为什么要用Spring Boot?
在Spring Boot出现之前,写一个Spring MVC项目有多痛苦?
- 配置XML文件,几百行,改一个注释都要重启。
- 手动导入十几个jar包,版本冲突让人头秃。
- 需要部署到Tomcat,配置web.xml…
Spring Boot的核心理念是“约定优于配置”和“开箱即用”。
- 自动配置:你引入了
spring-boot-starter-web,Spring Boot就自动帮你配好了Tomcat、Spring MVC。你不用写任何XML。 - 起步依赖:一个starter就是一个依赖集合。
- 内嵌容器:打成一个jar包,直接
java -jar就能跑,不需要外部Tomcat。
4.2 第一个Spring Boot项目:Hello API
用IDE新建项目,选Spring Initializr,依赖选Web。
生成的项目结构长这样:
src/
├── main/
│ ├── java/
│ │ └── com/example/demo/
│ │ ├── DemoApplication.java // 启动类
│ │ └── controller/
│ │ └── HelloController.java // 控制器
│ └── resources/
│ └── application.properties // 配置文件
└── test/
HelloController.java:
package com.example.demo.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@GetMapping("/hello")
public String sayHello() {
return "Hello, Spring Boot!";
}
}
双击运行DemoApplication.java,打开浏览器访问http://localhost:8080/hello。
看到了吗?就这几行代码,一个Web服务就起来了。这就是Spring Boot的魅力。
4.3 核心注解:看懂这些,你就看懂了Spring Boot
- @SpringBootApplication:启动类上的注解,组合了
@Configuration、@EnableAutoConfiguration、@ComponentScan。它是整个应用的入口。 - @RestController:相当于
@Controller+@ResponseBody。意思是这个类里的方法返回值直接作为HTTP响应体(通常是JSON),而不是跳转页面。 - @GetMapping / @PostMapping:映射HTTP请求方法。
- @Autowired:自动注入依赖。Spring容器会帮你把需要的对象塞进来。
- @Service / @Repository / @Component:标记类属于哪一层,方便Spring管理。
避坑指南:别把@Autowired滥用。尽量用构造器注入,而不是字段注入,这样代码更易测试。
第五章:数据库交互——JPA与MyBatis
现实中的项目,没数据可不行。Java连接数据库,主流有两个选择:JPA(Spring Data JPA) 和 MyBatis。
5.1 方案一:Spring Data JPA(面向对象思维)
JPA的核心思想是:把数据库表映射成Java类,把SQL操作变成Java方法调用。
依赖:spring-boot-starter-data-jpa, mysql-connector-j (或H2用于测试)。
实体类:
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private String email;
// 省略getter/setter/构造方法
}
Repository接口:
public interface UserRepository extends JpaRepository<User, Long> {
// 你什么都不用写!JPA会根据方法名自动生成SQL
List<User> findByNameContaining(String keyword);
}
Controller调用:
@RestController
public class UserController {
@Autowired
private UserRepository userRepository;
@GetMapping("/users")
public List<User> getUsers() {
return userRepository.findAll();
}
}
优点:开发快,代码干净,无需写SQL(简单查询)。 缺点:复杂查询性能可能不如手写SQL,跨数据库迁移时可能有坑。
5.2 方案二:MyBatis / MyBatis-Plus(SQL思维)
如果你喜欢自己控制SQL,或者项目有复杂的报表查询,MyBatis是更好的选择。
依赖:mybatis-spring-boot-starter 或 mybatis-plus-boot-starter(国内更流行)。
Mapper接口:
@Mapper
public interface UserMapper {
List<User> findAll();
User findById(Long id);
int insert(User user);
}
XML映射文件(UserMapper.xml):
<mapper namespace="com.example.demo.mapper.UserMapper">
<select id="findAll" resultType="User">
SELECT * FROM users
</select>
<insert id="insert" parameterType="User">
INSERT INTO users (name, email) VALUES (#{name}, #{email})
</insert>
</mapper>
MyBatis-Plus 在此基础上增加了更多通用方法,比如IService,让你几乎不用写SQL就能完成大部分CRUD,同时保留手写SQL的能力。
我的建议:初学者先学JPA,理解ORM概念。工作后如果团队用MyBatis,再转过去,其实很简单。
第六章:项目实战——做一个简单的博客系统后端
光说不练假把式。我们综合前面的知识,做一个极简博客系统后端。
6.1 需求分析
- 用户模块:注册、登录、获取用户信息。
- 文章模块:发布文章、获取文章列表、获取文章详情、删除文章(仅作者)。
- 评论模块:给文章加评论。
6.2 技术选型
- Spring Boot 3.x
- Spring Security(处理认证和授权,这个难点后面单独说)
- Spring Data JPA
- MySQL数据库
- JWT(JSON Web Token)(无状态登录,前后端分离标配)
- Lombok(简化Java代码,必装插件)
6.3 核心代码示例
1. 实体类(用Lombok减少样板代码)
@Data
@Entity
public class Article {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String title;
private String content;
@ManyToOne
@JoinColumn(name = "author_id")
private User author;
private LocalDateTime createTime;
}
2. 统一响应格式
别返回裸的User或Article,包一层:
public class ApiResponse<T> {
private int code;
private String message;
private T data;
// 静态工厂方法,方便调用
public static <T> ApiResponse<T> success(T data) {
ApiResponse<T> response = new ApiResponse<>();
response.code = 200;
response.message = "success";
response.data = data;
return response;
}
// 省略error方法和getter/setter
}
3. Controller层
@RestController
@RequestMapping("/api/articles")
public class ArticleController {
@Autowired
private ArticleService articleService;
@GetMapping
public ApiResponse<List<ArticleDto>> listArticles(
@RequestParam(defaultValue = "1") int page,
@RequestParam(defaultValue = "10") int size) {
return ApiResponse.success(articleService.listArticles(page, size));
}
@PostMapping
public ApiResponse<ArticleDto> createArticle(
@AuthenticationPrincipal User user, // Spring Security获取当前登录用户
@Valid @RequestBody CreateArticleRequest request) {
return ApiResponse.success(articleService.createArticle(user, request));
}
}
4. Service层
@Service
@Transactional // 保证事务,要么全成功,要么全失败
public class ArticleService {
@Autowired
private ArticleRepository articleRepository;
@Autowired
private UserRepository userRepository;
public ArticleDto createArticle(User author, CreateArticleRequest request) {
Article article = new Article();
article.setTitle(request.getTitle());
article.setContent(request.getContent());
article.setAuthor(author);
article.setCreateTime(LocalDateTime.now());
Article saved = articleRepository.save(article);
return convertToDto(saved);
}
public List<ArticleDto> listArticles(int page, int size) {
Page<Article> pageResult = articleRepository.findAll(PageRequest.of(page - 1, size));
return pageResult.getContent().stream()
.map(this::convertToDto)
.collect(Collectors.toList());
}
}
6.4 认证与授权:Spring Security
这是Java后端最难啃的骨头之一。别怕,我们拆解一下。
核心概念:
- Authentication(认证):你是谁?(登录)
- Authorization(授权):你能做什么?(权限)
JWT流程:
- 用户登录,后端验证账号密码。
- 验证通过,后端生成一个JWT Token(包含用户ID等信息),用私钥签名。
- 返回Token给前端。
- 前端每次请求,在Header里带
Authorization: Bearer <token>。 - 后端有个过滤器,解析Token,验证签名,如果有效,就把用户信息塞进SecurityContext。
简单配置示例:
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Autowired
private JwtAuthenticationFilter jwtFilter;
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.csrf(csrf -> csrf.disable()) // 前后端分离通常关csrf
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/auth/**").permitAll() // 登录接口公开
.anyRequest().authenticated() // 其他接口需要登录
)
.addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class);
return http.build();
}
}
第七章:进阶与工程化——从“能跑”到“好用”
你的系统能跑了,但这离“生产级”还远。接下来这些是区分初级和中级工程师的关键。
7.1 日志管理
别用System.out.println!在生产环境,这是垃圾。
用 SLF4J + Logback。
@Slf4j
@Service
public class ArticleService {
public ArticleDto createArticle(...) {
log.info("开始创建文章, author: {}", author.getId());
try {
// 业务逻辑
log.info("文章创建成功, id: {}", saved.getId());
return ...;
} catch (Exception e) {
log.error("文章创建失败, author: {}", author.getId(), e);
throw new BusinessException("创建失败", e);
}
}
}
配置application.yml调整日志级别和输出格式。
7.2 异常处理
别让500错误直接甩给前端。
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(UserNotFoundException.class)
public ApiResponse<Void> handleUserNotFound(UserNotFoundException e) {
return ApiResponse.error(404, e.getMessage());
}
@ExceptionHandler(Exception.class)
public ApiResponse<Void> handleGlobalException(Exception e) {
log.error("系统异常", e);
return ApiResponse.error(500, "系统内部错误");
}
}
7.3 单元测试
不会写测试的代码,是不成熟的代码。
