Java Springboot 快速入门
在IDEA里面选择Spring Initializr
创建一个全新的Spring项目

安装依赖,Spring Web必选,用来实现Web服务,其他根据开发需求加,后面也能选

初始化完之后的项目结构如下

好的,上面的SpringDemoApplication
就是我们的主启动类,我们要依照分层架构来创建各种层.
一个典型的Java Springboot应用大概会有Controller
Service
Model
Repository
Config
等层级.
一个典型的请求处理流程是:
- Controller层接收HTTP请求
- Controller调用Service层进行业务处理
- Service层使用Repository层访问数据
- Repository层操作Entity/Model对象
- 处理结果沿着调用链返回给客户端
我们来写一个简单的Controller:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| package com.demo.spring_demo.controller;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController;
@RestController public class HelloController{ @GetMapping("/hello") public String hello(){ return "Hello World"; } @GetMapping("/api/version") public String getVersion(){ return "1.0.0"; } }
|

你可能会看到很多@
,它们在Java应用程序中被称为注解。Springboot是一个框架,它通过扫描你的注解和逻辑来知道应用程序应该如何工作.
架构包初探
通常的架构大概会分成这些软件包来做:
Controller
是一个控制器,它负责根据我们的路由来分发请求,接受用户输入并返回响应.
Service
用于具体的实现我们的业务逻辑.
Model
层往往是一些数据结构层,定义了应用中的数据结构.
Repository
提供对数据源的访问.
Config
用于管理应用程序的配置.
根据架构,我们设计一个更能体现Spring特色的应用程序:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| com.demo.spring_demo ├── SpringDemoApplication.java (主启动类) ├── controller │ ├── HelloController.java │ └── UserController.java (用户API控制器) ├── service │ ├── UserService.java (服务接口) │ └── UserServiceImpl.java (服务实现) ├── repository │ ├── UserRepository.java (数据访问接口) │ └── UserRepositoryImpl.java (数据访问实现) ├── model │ └── User.java (用户模型类) └── config └── AppConfig.java (应用配置类)
|
SpringDemoApplication
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| package com.demo.spring_demo;
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication public class SpringDemoApplication {
public static void main(String[] args) { SpringApplication.run(SpringDemoApplication.class, args); }
}
|
@SpringBootApplication
是主应用类上的注解,它标志了这是一个主类,从此处开始整个应用程序.它会支持所有注解的扫描和自动配置的实现.
数据结构的确定
这个应用主要实现的是对用户的CRUD增删改查,所以我们先创建一个model包,在里面定义一个User类.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
| package com.demo.spring_demo.model;
import java.util.Date;
public class User { private Long id; private String username; private String email; private Date createdAt;
public User() { }
public User(Long id, String username, String email) { this.id = id; this.username = username; this.email = email; this.createdAt = new Date(); }
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public String getUsername() { return username; }
public void setUsername(String username) { this.username = username; }
public String getEmail() { return email; }
public void setEmail(String email) { this.email = email; }
public Date getCreatedAt() { return createdAt; }
public void setCreatedAt(Date createdAt) { this.createdAt = createdAt; }
@Override public String toString() { return "User{" + "id=" + id + ", username='" + username + '\'' + ", email='" + email + '\'' + ", createdAt=" + createdAt + '}'; } }
|
设置了id
username
email
createdAt
等几个字段,设置了getter和setter方法来访问类的私有字段,并编写了toString
的实现.这样我们有了最小的操作单元,我们可以基于User来进行操作.这个系统的目标就是做一个关于User的CRUD.
数据操作的定义
在repository
包中确定一些数据操作,包括简单的
获取所有用户findAll
以Id
为键获取单个User的findById
更新用户的方法save
删除用户的方法deleteById
UserRepository.java
1 2 3 4 5 6 7 8 9 10 11 12
| package com.demo.spring_demo.repository;
import com.demo.spring_demo.model.User; import java.util.List; import java.util.Optional;
public interface UserRepository { List<User> findAll(); Optional<User> findById(Long id); User save(User user); void deleteById(Long id); }
|
这并不是一个类.这是一个接口,它定义了我们要实现什么东西来帮助我们完成我们的业务逻辑.
在UserRepositoyImpl.java
中,我们实现它.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
| package com.demo.spring_demo.repository;
import com.demo.spring_demo.model.User; import org.springframework.stereotype.Repository;
import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.concurrent.atomic.AtomicLong;
@Repository public class UserRepositoryImpl implements UserRepository {
private final Map<Long, User> userMap = new HashMap<>(); private final AtomicLong idGenerator = new AtomicLong(1L);
public UserRepositoryImpl() { User user1 = new User(idGenerator.getAndIncrement(), "zhangsan", "[email protected]"); User user2 = new User(idGenerator.getAndIncrement(), "lisi", "[email protected]");
userMap.put(user1.getId(), user1); userMap.put(user2.getId(), user2); }
@Override public List<User> findAll() { return new ArrayList<>(userMap.values()); }
@Override public Optional<User> findById(Long id) { return Optional.ofNullable(userMap.get(id)); }
@Override public User save(User user) { if (user.getId() == null) { user.setId(idGenerator.getAndIncrement()); } userMap.put(user.getId(), user); return user; }
@Override public void deleteById(Long id) { userMap.remove(id); } }
|
Java新手可能看不懂HashMap是什么,没关系。
你可以把它当成Python中的字典(键值存储数据结构).
在这里我们把它用来模拟从数据库获取数据的实现.
@Repository
表明被注解的类是一个”仓库”(Repository),用于封装存储、检索和查询数据的逻辑。
@Override
是Java语言的标准注解,用于表明被注解的方法是覆盖(重写)父类或实现接口的方法。
构造方法会新定义一些User对象,并把它们添加到数据源,在此之后实现了应用程序的逻辑.
业务逻辑的实现
UserService.java
1 2 3 4 5 6 7 8 9 10 11 12 13
| package com.demo.spring_demo.service;
import com.demo.spring_demo.model.User; import java.util.List; import java.util.Optional;
public interface UserService { List<User> getAllUsers(); Optional<User> getUserById(Long id); User createUser(User user); Optional<User> updateUser(Long id, User user); boolean deleteUser(Long id); }
|
在UserService
中确定了业务逻辑的接口,在之后的UserServiceImpl
里完成实现.
UserServiceImpl.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
| package com.demo.spring_demo.service;
import com.demo.spring_demo.model.User; import com.demo.spring_demo.repository.UserRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service;
import java.util.List; import java.util.Optional;
@Service public class UserServiceImpl implements UserService {
private final UserRepository userRepository;
@Autowired public UserServiceImpl(UserRepository userRepository) { this.userRepository = userRepository; }
@Override public List<User> getAllUsers() { return userRepository.findAll(); }
@Override public Optional<User> getUserById(Long id) { return userRepository.findById(id); }
@Override public User createUser(User user) { return userRepository.save(user); }
@Override public Optional<User> updateUser(Long id, User userDetails) { return userRepository.findById(id) .map(existingUser -> { existingUser.setUsername(userDetails.getUsername()); existingUser.setEmail(userDetails.getEmail()); return userRepository.save(existingUser); }); }
@Override public boolean deleteUser(Long id) { if (userRepository.findById(id).isPresent()) { userRepository.deleteById(id); return true; } return false; } }
|
这里定义了一些常见的CRUD逻辑,调用了之前提到的Repository里面的数据操作方法来获取具体的内容.
路由函数的映射
回到我们亲爱的Controller层,也是我们直接和路由交互的函数入口:
UserController.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
| package com.demo.spring_demo.controller;
import com.demo.spring_demo.model.User; import com.demo.spring_demo.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController @RequestMapping("/api/users") public class UserController {
private final UserService userService;
@Autowired public UserController(UserService userService) { this.userService = userService; }
@GetMapping public ResponseEntity<List<User>> getAllUsers() { List<User> users = userService.getAllUsers(); return ResponseEntity.ok(users); }
@GetMapping("/{id}") public ResponseEntity<User> getUserById(@PathVariable Long id) { return userService.getUserById(id) .map(ResponseEntity::ok) .orElseGet(() -> ResponseEntity.notFound().build()); }
@PostMapping public ResponseEntity<User> createUser(@RequestBody User user) { User createdUser = userService.createUser(user); return ResponseEntity.status(HttpStatus.CREATED).body(createdUser); }
@PutMapping("/{id}") public ResponseEntity<User> updateUser(@PathVariable Long id, @RequestBody User user) { return userService.updateUser(id, user) .map(ResponseEntity::ok) .orElseGet(() -> ResponseEntity.notFound().build()); }
@DeleteMapping("/{id}") public ResponseEntity<Void> deleteUser(@PathVariable Long id) { boolean deleted = userService.deleteUser(id); return deleted ? ResponseEntity.noContent().build() : ResponseEntity.notFound().build(); } }
|
这里介绍几个用的比较多的注解:
@RestController
- 作用:用于创建 RESTful Web 服务的控制器,等同于
@Controller
和 @ResponseBody
的组合。它使得类中的每个方法默认都返回响应体,且响应体会被自动转换为 JSON 或 XML 格式。
- 用法:标记在控制器类上,自动将方法的返回值转化为 JSON 或 XML 格式的响应体。
1 2 3 4 5 6 7 8 9
| @RestController public class GreetingController {
@GetMapping("/greeting") public String greet(@RequestParam(name = "name", defaultValue = "World") String name) { return "Hello, " + name + "!"; } }
|
@RequestMapping
作用:用于处理 HTTP 请求的映射。可以与 HTTP 方法(GET、POST、PUT 等)一起使用,也可以指定路径。它是 Spring 中最基本的请求映射注解,支持多种 HTTP 方法(如 GET、POST、PUT、DELETE 等)和路径匹配。
用法:可以用于类或方法上,指定请求的 URL 路径和请求方法。如果没有指定请求方法,它会匹配所有的 HTTP 方法(GET、POST 等)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| @RestController @RequestMapping("/api") public class MyController {
@RequestMapping(value = "/greeting", method = RequestMethod.GET) public String greeting(@RequestParam(name = "name", defaultValue = "World") String name) { return "Hello, " + name + "!"; }
@RequestMapping(value = "/submit", method = RequestMethod.POST) public String submit(@RequestBody String data) { return "Received: " + data; } }
|
@GetMapping("/")
@PostMapping("/")
@PutMapping("/")
@DeleteMapping("/")
等Mapping方法会在@RestController
提供的基础路径上做细化的方法映射,如果没有@RestController
那么默认的路径就是根路由.
另外还有一些获取参数的注解,简单贴一下
@PathVariable
获取rest风格路径参数
@RequestParam
绑定请求参数到方法形参
@RequestHeader
获取请求中的请求头
@CookieValue
获取指定的 Cookie 的值
@RequestBody
获取请求体Body的值
之后就是调用Service层中的方法,完成我们的整个调用链即可.
整理一下我们的整个调用链逻辑:
HTTP请求
->Controller
->Service
->Repoistory
->Model
整个架构的逻辑大概就是这样,这也被称为典型的Springboot MVC架构.
打包成Jar包
用Idea打包
文件->项目结构->工件->Jar->打包并选择主类
之后打开侧边栏->Maven->clean->package 打包完成





用Maven插件打包
SpringBoot
自带一个更简单的spring-boot-maven-plugin
插件可以用来打包,只需要在pom.xml中加入以下配置:
1 2 3 4 5 6 7 8 9 10 11
| <project> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
|
之后运行mvn clean package
即可.
运行Jar包
java -jar 运行jar包,注意java版本号需要和开发版本相匹配
