什么是接口
- API接口 是一组规则和协议,允许不同的软件应用程序之间进行交互和通信。它定义了如何请求服务、数据格式、返回值以及错误处理等方面的规范
实现目标
要写好一个接口(API),不仅需要具备一定的技术技能,还需要考虑设计、健壮性和易用性。总结16大字:功能明确、设计合理、性能优化、易于维护。
操作步骤
编写接口的详细步骤
1.明确需求:
- 确定接口的具体功能。例如:是创建用户、更新数据还是执行某种业务逻辑。
理解接口输入输出的需求(需要接收哪些参数,返回什么数据)。
2.设计接口:
-
URL 路径设计:接口路径应简洁清晰,遵循 RESTful 风格,使用名词来代表资源。
-
定义参数:
-
路径参数:用来在 URL 中传递动态的资源 ID,例如 /users/{id}。
-
查询参数:用于筛选、排序等功能,例如 /users?page=2&size=10。
-
请求体参数:对于 POST、PUT、PUT、DELETE请求,通常需要一个请求体传递数据。
GET:获取资源 POST:创建资源 PUT:更新资源 DELETE:删除资源 例如:GET /users(获取用户列表)、POST /users(创建用户)、GET /users/{id}(根据用户 ID 获取用户详细信息)。
-
-
请求格式:如果接口需要接收数据,通常使用 JSON 格式传递请求体的数据。例如,登录接口的请求体可以包含用户名和密码。
3.校验输入参数:
- 对客户端传入的参数进行校验,确保数据合法、格式正确。
- 例如,检查用户名是否为空,密码是否符合安全要求。
4.业务逻辑处理:
- 在 Service 层 实现核心业务逻辑,例如注册用户、检查用户名是否重复、密码加密等。
- DAO 层(数据访问层)负责与数据库交互,完成数据存储、更新、查询等操作。
5.错误处理:
- 根据业务逻辑处理可能的错误场景,并返回合适的错误码和错误信息。
- 例如,用户不存在、数据不合法、权限不足等。
6.返回响应:
- 统一格式的响应体返回结果数据,包含 code(状态码)、message(说明信息)、data(具体数据,可能为空)。
-
200 OK:请求成功。 201 Created:资源成功创建。 400 Bad Request:请求参数有误。 401 Unauthorized:认证失败,用户未登录或凭证无效。 403 Forbidden:用户无权限访问资源。 404 Not Found:请求的资源不存在。 500 Internal Server Error:服务器内部错误。
- 示例响应:
{
"code": 200,
"message": "Registration successful",
"data": null
}
7.测试接口:
- 使用工具(如 Postman)或自动化测试脚本,测试接口的各类功能,确保其正常工作。
- 包含正向测试(正常输入),和负向测试(异常输入,如缺少参数、参数格式错误等)。
8.编写文档:
- 使用文档工具(如 Swagger)编写接口文档,描述请求路径、方法、参数说明、示例请求和响应。
- 让其他开发者或前端人员了解如何使用接口。**
示例:(用户注册接口)
- Controller 层:负责接收客户端请求,调用 Service 层处理逻辑,返回响应结果。
// Controller 层,负责处理 HTTP 请求
@RestController // 标记为一个 RESTful 控制器
@RequestMapping("/api") // 为所有接口统一设置一个路径前缀
public class UserController {
@Autowired // 自动注入 UserService
private UserService userService;
/**
* 用户注册接口
* @param userDTO 从请求体中接收的用户信息
* @return 注册结果
*/
@PostMapping("/register") // 映射 HTTP POST 请求到 /api/register
public Result register(@RequestBody UserDTO userDTO) {
// 校验输入参数是否合法
if (userDTO.getUsername() == null || userDTO.getPassword() == null) {
// 如果用户名或密码为空,返回 400 错误
return Result.error(400, "用户名或密码不能为空");
}
// 调用 Service 层处理业务逻辑
boolean isRegistered = userService.register(userDTO);
// 根据业务逻辑结果返回响应
return isRegistered ? Result.success("注册成功") : Result.error(409, "用户名已存在");
}
}
- @RestController:声明这是一个控制器,返回的结果会自动转换为 JSON。
- @RequestBody:用于将请求体中的 JSON 数据自动绑定到 UserDTO 对象。
- userService.register(userDTO):调用 Service 层注册逻辑。
- Service 层:定义业务逻辑接口,提供服务调用的入口。
// Service 层接口,定义注册相关的业务逻辑
public interface UserService {
/**
* 用户注册业务逻辑接口
* @param userDTO 包含用户信息的对象
* @return 是否注册成功
*/
boolean register(UserDTO userDTO);
}
- boolean register(UserDTO userDTO):定义一个注册方法,返回 true 表示成功,false 表示失败。
- ServiceImpl 层:实现 Service 层接口,编写具体的业务逻辑。
// Service 层实现类,具体实现业务逻辑
@Service // 标记为 Spring 的 Service 组件,表示这是一个服务
public class UserServiceImpl implements UserService {
@Autowired // 自动注入 Mapper 层,用于数据库操作
private UserMapper userMapper;
/**
* 实现用户注册逻辑
* @param userDTO 包含用户信息的对象
* @return 是否注册成功
*/
@Override // 标注这是接口方法的实现
public boolean register(UserDTO userDTO) {
// 调用 Mapper 层,查询用户名是否已存在
User existingUser = userMapper.findByUsername(userDTO.getUsername());
if (existingUser != null) {
// 如果用户已存在,返回 false 表示注册失败
return false;
}
// 如果用户名不存在,调用 Mapper 层保存用户信息
userMapper.save(userDTO);
return true; // 返回 true 表示注册成功
}
}
- @Service:声明这是一个业务服务组件。
- userMapper.findByUsername(userDTO.getUsername()):检查用户名是否已存在。
- userMapper.save(userDTO):如果用户名不存在,保存新用户信息。
- Mapper 层:负责与数据库交互,执行 SQL 查询和插入操作。
// Mapper 层,负责与数据库交互
@Mapper // 标记为 MyBatis 的 Mapper,自动生成实现类
public interface UserMapper {
/**
* 根据用户名查询用户是否存在
* @param username 要查询的用户名
* @return 如果存在则返回用户对象,否则返回 null
*/
@Select("SELECT * FROM users WHERE username = #{username}") // 使用 MyBatis 注解编写 SQL 查询语句
User findByUsername(String username);
/**
* 保存用户信息到数据库
* @param userDTO 包含用户信息的对象
*/
@Insert("INSERT INTO users (username, password, email) VALUES (#{username}, #{password}, #{email})") // 插入用户信息
void save(UserDTO userDTO);
}
- @Mapper:表示这是 MyBatis 的 Mapper 接口,Spring 会自动实现接口的实现类。
- @Select 和 @Insert:分别用于查询和插入 SQL 语句。
- findByUsername:通过用户名查询用户信息。
- save:将新用户信息插入到数据库中。
- DTO(数据传输对象):用于封装请求体中的数据。
// 数据传输对象,用于封装请求数据
@NoArgsConstructor//生成无参构造函数
@AllArgsConstructor//生成全参构造函数
@Data // 使用 @Data 注解自动生成 getter 和 setter 方法
public class UserDTO {
private String username; // 用户名
private String password; // 密码
private String email; // 邮箱
}
- Result(统一响应对象):用于统一处理返回的响应结果。
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data // 自动生成 getter、setter、toString、equals 和 hashCode 方法
@NoArgsConstructor // 生成无参构造函数
@AllArgsConstructor // 生成全参构造函数
public class Result {
private Integer code; // 响应码,1 代表成功; 0 代表失败
private String msg; // 响应信息 描述字符串
private Object data; // 返回的数据
// 增删改 成功响应
public static Result success() {
return new Result(1, "success", null);
}
// 查询 成功响应
public static Result success(Object data) {
return new Result(1, "success", data);
}
// 失败响应
public static Result error(String msg) {
return new Result(0, msg, null);
}
}
-
@Data: 这个注解会为所有字段生成 getter 和 setter 方法,toString() 方法,以及 equals() 和 hashCode() 方法。这使得这个类更简洁,同时提供了常用的功能。
-
@NoArgsConstructor: 生成一个无参构造函数,可以方便地创建 Result 对象。
-
@AllArgsConstructor: 生成一个全参构造函数,可以通过提供所有字段的值来创建 Result 对象。
-
响应方法:
- public static Result success(): 创建一个表示成功但不带任何数据的响应。
- public static Result success(Object data): 创建一个表示成功并包含数据的响应。
- public static Result error(String msg): 创建一个表示失败并包含错误信息的响应。
架构
- Controller 层:处理 HTTP 请求,将请求体数据转换为对象,并调用 Service 层执行业务逻辑。
- Service 层:定义业务逻辑接口,由 ServiceImpl 实现实际的业务处理。
- ServiceImpl 层:通过调用 Mapper 层来执行数据库操作,实现具体的业务逻辑。
Mapper 层:负责执行数据库操作,查询和保存数据。 - DTO:封装请求数据,使得数据传输格式统一。
- Result:用于统一 API 响应结构,便于前端处理返回数据。
通过这个结构,接口开发的逻辑清晰,每一层都各司其职,降低了代码耦合性,同时提高了代码的可读性和维护性。
调用关系
- UserController (Controller) 调用 UserService (Service) 来处理业务逻辑。
- UserService (Service) 是 UserServiceImpl (ServiceImpl) 的接口。
- UserServiceImpl (ServiceImpl) 调用 UserMapper (Mapper) 进行数据库操作。
- UserMapper (Mapper) 使用 UserDTO (DTO) 进行数据传输。
- UserController (Controller) 返回 Result (Response) 对象,表示接口的响应结果。