从0写好一个接口(工作必备)
本文最后更新于70 天前,其中的信息可能已经过时,如有错误请发送邮件到3082654005@qq.com

第一部分:从0开始写一个接口 (Hands-on Tutorial)

假设我们使用最流行的 Spring Boot 框架来创建一个简单的 GET /users/{id} 接口,用于根据用户ID查询用户信息。

第1步:环境准备

  1. 安装JDK:确保安装了JDK 8或以上版本。
  2. 安装IDE:推荐使用 IntelliJ IDEA (社区版即可) 或 Eclipse。
  3. 创建项目:使用 Spring Initializr 快速生成项目。
    • Project: Maven
    • Language: Java
    • Spring Boot: 选择最新的稳定版(如3.2.x)
    • Groupcom.example (你的公司域名反写)
    • Artifactdemo
    • Packaging: Jar
    • Java: 选择你安装的JDK版本
    • Dependencies: 添加 Spring Web (这是构建Web接口的核心)

点击“Generate”下载压缩包,并解压到你的工作目录,用IDE打开。

第2步:理解项目结构

打开项目后,你会看到类似这样的结构:

text

src
└── main
    ├── java
    │   └── com
    │       └── example
    │           └── demo
    │               ├── DemoApplication.java // Spring Boot启动类
    │               └── controller           // 【建议创建】存放控制器(接口)的包
    │               └── service              // 【建议创建】存放业务逻辑的包
    │               └── entity               // 【建议创建】存放实体类的包
    └── resources
        └── application.properties // 配置文件

第3步:编写代码

我们将遵循 MVC(Model-View-Controller) 模式。

  1. 创建实体类 (Model)
    在 entity 包下创建 User.java,代表一个用户数据模型。javapackage com.example.demo.entity; public class User { private Long id; private String name; private String email; // 1. 无参构造器 public User() { } // 2. 带参构造器 public User(Long id, String name, String email) { this.id = id; this.name = name; this.email = email; } // 3. Getter和Setter方法 (必须要有,否则无法序列化为JSON) public Long getId() { return id; } public void setId(Long id) { this.id = id; } // … 省略name和email的getter和setter }
  2. 创建控制器 (Controller)
    在 controller 包下创建 UserController.java。这里定义接口的URL、方法和参数。javapackage com.example.demo.controller; import com.example.demo.entity.User; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; @RestController // 这个注解标明这个类是一个控制器,并且返回的是JSON数据,而不是视图页面。 public class UserController { // 模拟一些静态数据,代替数据库 private static final List<User> USER_LIST = Arrays.asList( new User(1L, “张三”, “zhangsan@example.com”), new User(2L, “李四”, “lisi@example.com”) ); // @GetMapping 注解将HTTP GET请求映射到特定的方法上。 // {id} 是路径变量。 @GetMapping(“/users/{id}”) public User getUserById(@PathVariable Long id) { // @PathVariable 用来接收路径变量 // 简单的业务逻辑:遍历列表查找用户 return USER_LIST.stream() .filter(user -> user.getId().equals(id)) .findFirst() .orElseThrow(() -> new RuntimeException(“User not found with id: ” + id)); // 如果没找到,抛出一个异常 } }

第4步:运行和测试

  1. 启动应用:运行 DemoApplication.java 中的 main 方法。
  2. 测试接口:打开浏览器或使用Postman等API测试工具,访问 http://localhost:8080/users/1
    你应该能看到返回的JSON数据:json{ “id”: 1, “name”: “张三”, “email”: “zhangsan@example.com” }

恭喜!你已经从0到1完成了第一个接口。但这只是一个开始,真实的工作场景要复杂得多。


第二部分:如何在工作中写好一个接口 (Best Practices)

写一个“能跑”的接口很简单,但写一个“好”接口需要考虑到很多方面。

1. 清晰的职责划分 (MVC & Layer Architecture)

不要把所有代码都写在Controller里!优秀的后端代码应该有清晰的分层:

  • Controller层只负责接收请求、解析参数、调用Service、返回响应。不应该包含复杂的业务逻辑。
  • Service层核心业务逻辑所在的地方。处理业务规则、计算、事务管理等。
  • Repository/Dao层:负责与数据库进行交互,执行CRUD(增删改查)操作。

在我们的例子中,应该创建一个 UserService 接口及其实现类 UserServiceImpl,将查找用户的逻辑从Controller挪到Service中。Controller只负责调用 userService.getUserById(id)

2. 规范的 RESTful 设计

  • URL语义化:使用名词复数,而不是动词。/users 比 /getUsers 更好。
  • HTTP方法:正确使用HTTP动词表达操作意图。
    • GET:查询/获取资源
    • POST:创建新资源
    • PUT:更新整个资源
    • PATCH:部分更新资源
    • DELETE:删除资源
  • 状态码:返回合适的HTTP状态码。
    • 200 OK:成功
    • 201 Created:创建成功
    • 400 Bad Request:客户端请求错误(如参数校验失败)
    • 404 Not Found:资源不存在
    • 500 Internal Server Error:服务器内部错误

3. 全面的参数校验 (Validation)

永远不要相信前端传来的数据!必须在后端进行校验。

  • 使用注解:在实体类字段上使用 javax.validation.constraints 或 jakarta.validation.constraints 包下的注解。javapublic class User { @NotNull(message = “用户ID不能为空”) private Long id; @NotBlank(message = “用户名不能为空”) @Size(max = 50, message = “用户名长度不能超过50个字符”) private String name; @Email(message = “邮箱格式不正确”) private String email; }
  • 在Controller方法中使用 @Valid:java@PostMapping(“/users”) public User createUser(@RequestBody @Valid User user) { // @Valid 会触发校验 return userService.createUser(user); }
  • 处理校验异常:通常使用 @ControllerAdvice 进行全局异常处理,统一返回格式。

4. 统一的响应格式 (Response Wrapper)

不要直接返回实体对象,应该用一个统一的包装类包裹起来,方便前端处理。

java

// 定义一个标准响应类
public class ApiResponse<T> {
    private int code; // 状态码 (200, 400, 500等,或自定义业务码)
    private String message; // 提示信息
    private T data; // 返回的数据

    // 成功静态方法
    public static <T> ApiResponse<T> success(T data) {
        ApiResponse<T> response = new ApiResponse<>();
        response.setCode(200);
        response.setMessage("Success");
        response.setData(data);
        return response;
    }
    // 失败静态方法...
    // Getter and Setter...
}

// Controller中这样用
@GetMapping("/users/{id}")
public ApiResponse<User> getUserById(@PathVariable Long id) {
    User user = userService.getUserById(id);
    return ApiResponse.success(user);
}

这样,所有接口返回的格式都是 {“code": 200, "message": "Success", "data": {...}}

5. 细致的异常处理 (Exception Handling)

使用 @ControllerAdvice 和 @ExceptionHandler 进行全局异常处理,避免将晦涩的服务器异常直接抛给前端。

java

@ControllerAdvice
public class GlobalExceptionHandler {
    
    @ExceptionHandler(RuntimeException.class)
    @ResponseBody
    public ApiResponse<String> handleRuntimeException(RuntimeException e) {
        // 记录日志
        return ApiResponse.fail(500, "服务器繁忙,请稍后再试: " + e.getMessage());
    }
    
    // 专门处理参数校验异常
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ApiResponse<String> handleValidationException(MethodArgumentNotValidException e) {
        String errorMessage = e.getBindingResult().getFieldError().getDefaultMessage();
        return ApiResponse.fail(400, errorMessage);
    }
}

6. 必不可少的日志 (Logging)

在关键位置添加日志,方便排查问题。

  • 记录入参和出参:特别是在复杂接口中。
  • 记录业务操作:比如“用户XXX下单成功”。
  • 使用SLF4J + Logback:java@Slf4j // Lombok注解,自动生成log变量 @RestController public class UserController { @GetMapping(“/users/{id}”) public ApiResponse<User> getUserById(@PathVariable Long id) { log.info(“Received request for user id: {}”, id); // 使用{}占位符 User user = userService.getUserById(id); log.info(“Return user: {}”, user); return ApiResponse.success(user); } }

7. 接口文档 (API Documentation)

代码写完,文档也要生成。不要维护单独的Word文档,代码一变文档就过期。

  • 使用 Swagger/OpenAPI:通过在代码中添加注解(如 @Operation@ApiResponse),自动生成实时、可交互的API文档。访问 http://localhost:8080/swagger-ui.html 即可查看。

8. 性能与安全 (Performance & Security)

  • 性能:关注数据库查询效率(使用索引),必要时引入缓存(Redis)。
  • 安全
    • 敏感数据(如密码)加密存储。
    • 接口权限控制(使用Spring Security),防止越权访问。
    • 防止SQL注入(使用MyBatis等ORM框架本身就解决了这个问题)。
    • 防止XSS攻击(对用户输入进行转义)。

总结:写好一个接口的 checklist

  1. 设计:URL和HTTP方法是否符合RESTful规范?
  2. 参数:是否对所有输入参数进行了校验?
  3. 分层:业务逻辑是否放在了Service层?
  4. 响应:是否使用了统一的响应格式?
  5. 异常:是否处理了可能的异常并返回友好提示?
  6. 日志:是否在关键位置添加了日志记录?
  7. 文档:是否更新或生成了API文档(如Swagger)?
  8. 安全:是否考虑了权限、SQL注入、XSS等安全问题?

从写出第一个接口到写出一个健壮、可靠、易维护的接口,需要不断地学习和实践。希望这份指南能为你提供一个清晰的路径!

文末附加内容
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇