Java API接口从0到1实战:新手也能看懂的编写指南

Java API 接口从 0 到 1 实战指南
(2025–2026 年最常用、最务实写法,新手友好版)

目标:
用最短路径,让一个刚学完 JavaSE 的同学能在 3–5 天 内独立写出生产级 RESTful API(包含增删改查、分页、参数校验、统一响应、异常处理、日志、接口文档)。

技术选型推荐(2026 年新项目主流组合)

技术项推荐选择(新手友好)为什么选它(2026 年视角)替代选项(可选了解)
框架Spring Boot 3.3.x / 3.4.x自动配置最彻底、生态最全Spring MVC 纯手工
Web 层@RestController + Spring Web最简单、最常用WebFlux(高并发场景)
JSON 处理Jackson(Spring Boot 默认)性能好、兼容性强Fastjson(慎用)
参数校验jakarta.validation + @Valid标准、注解式、易读
统一响应自定义 R / Result公司规范 90% 都这么做ResponseEntity
异常处理@ControllerAdvice + @ExceptionHandler全局统一、优雅
日志lombok + slf4j + logback最轻、最常用log4j2
接口文档springdoc-openapi 2.x(OpenAPI 3)免费、美观、替代 swagger-uiKnife4j(国内更流行)
构建工具Maven(最稳)面试/公司项目主流Gradle(越来越多人用)
数据库访问(可选)MyBatis-Plus 3.5.x代码少、功能强、分页方便Spring Data JPA

完整项目结构(推荐)

demo-api
├── src
│   ├── main
│   │   ├── java
│   │   │   └── com/example/demo
│   │   │       ├── common          # 统一响应、异常、常量
│   │   │       ├── config          # 配置类(可选)
│   │   │       ├── controller
│   │   │       ├── entity          # 实体类
│   │   │       ├── mapper          # MyBatis Mapper(可选)
│   │   │       ├── service
│   │   │       └── vo              # 入参/出参 DTO
│   │   └── resources
│   │       ├── application.yml
│   │       └── logback-spring.xml(可选)
│   └── test
└── pom.xml

步骤 1:快速创建项目(5 分钟)

方式一(最推荐):

  1. 打开 https://start.spring.io/
  2. 配置:
  • Project: Maven
  • Language: Java
  • Spring Boot: 3.3.5 或 3.4.x(最新稳定)
  • Group: com.example
  • Artifact: demo-api
  • Java: 17 或 21
  • Dependencies(至少选):
    • Spring Web
    • Lombok
    • Spring Boot DevTools
    • Validation
    • SpringDoc OpenAPI UI
    • (可选)MyBatis Plus + MySQL Driver + druid
  1. Generate → 解压 → IDEA 打开

步骤 2:核心代码清单(复制粘贴就能跑)

1. 统一响应类(common/R.java)

package com.example.demo.common;

import lombok.Data;

@Data
public class R<T> {
    private int code;
    private String msg;
    private T data;

    public static <T> R<T> ok() {
        return ok(null);
    }

    public static <T> R<T> ok(T data) {
        R<T> r = new R<>();
        r.setCode(200);
        r.setMsg("success");
        r.setData(data);
        return r;
    }

    public static <T> R<T> error(int code, String msg) {
        R<T> r = new R<>();
        r.setCode(code);
        r.setMsg(msg);
        return r;
    }

    public static <T> R<T> error(String msg) {
        return error(500, msg);
    }
}

2. 全局异常处理(common/GlobalExceptionHandler.java)

package com.example.demo.common;

import jakarta.validation.ConstraintViolationException;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;

@RestControllerAdvice
public class GlobalExceptionHandler {

    // 参数校验异常
    @ExceptionHandler({MethodArgumentNotValidException.class, BindException.class})
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public R<Void> handleValidException(Exception e) {
        String msg = e.getMessage();
        if (e instanceof MethodArgumentNotValidException ex) {
            msg = ex.getBindingResult().getFieldError().getDefaultMessage();
        } else if (e instanceof BindException ex) {
            msg = ex.getAllErrors().get(0).getDefaultMessage();
        }
        return R.error(400, msg);
    }

    // 通用异常兜底
    @ExceptionHandler(Exception.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public R<Void> handleException(Exception e) {
        // 实际项目建议把异常信息记录日志
        return R.error(500, "服务器内部错误:" + e.getMessage());
    }
}

3. 实体 + DTO 示例(以用户为例)

// entity/User.java
package com.example.demo.entity;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;

@Data
public class User {
    @TableId(type = IdType.AUTO)
    private Long id;
    private String username;
    private String email;
    private Integer age;
}

// vo/UserVO.java(出参)
@Data
public class UserVO {
    private Long id;
    private String username;
    private String email;
    private Integer age;
}

// vo/UserQueryVO.java(分页查询入参)
@Data
public class UserQueryVO {
    private Integer page = 1;
    private Integer size = 10;
    private String username;
}

4. Controller(最核心部分)

package com.example.demo.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.demo.common.R;
import com.example.demo.entity.User;
import com.example.demo.service.UserService;
import com.example.demo.vo.UserQueryVO;
import com.example.demo.vo.UserVO;
import jakarta.validation.Valid;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/api/v1/users")
public class UserController {

    @Autowired
    private UserService userService;

    // 新增
    @PostMapping
    public R<UserVO> create(@RequestBody @Valid User user) {
        userService.save(user);
        UserVO vo = new UserVO();
        BeanUtils.copyProperties(user, vo);
        return R.ok(vo);
    }

    // 修改
    @PutMapping("/{id}")
    public R<UserVO> update(@PathVariable Long id, @RequestBody @Valid User user) {
        user.setId(id);
        userService.updateById(user);
        UserVO vo = new UserVO();
        BeanUtils.copyProperties(user, vo);
        return R.ok(vo);
    }

    // 删除
    @DeleteMapping("/{id}")
    public R<Void> delete(@PathVariable Long id) {
        userService.removeById(id);
        return R.ok();
    }

    // 单个查询
    @GetMapping("/{id}")
    public R<UserVO> getById(@PathVariable Long id) {
        User user = userService.getById(id);
        if (user == null) {
            return R.error(404, "用户不存在");
        }
        UserVO vo = new UserVO();
        BeanUtils.copyProperties(user, vo);
        return R.ok(vo);
    }

    // 分页查询(带条件)
    @GetMapping
    public R<Page<UserVO>> page(@ModelAttribute UserQueryVO query) {
        Page<User> page = new Page<>(query.getPage(), query.getSize());
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.like(query.getUsername() != null, User::getUsername, query.getUsername());
        wrapper.orderByDesc(User::getId);

        Page<User> userPage = userService.page(page, wrapper);

        // 转 VO
        Page<UserVO> voPage = new Page<>();
        BeanUtils.copyProperties(userPage, voPage, "records");
        List<UserVO> records = userPage.getRecords().stream()
                .map(u -> {
                    UserVO vo = new UserVO();
                    BeanUtils.copyProperties(u, vo);
                    return vo;
                })
                .collect(Collectors.toList());
        voPage.setRecords(records);

        return R.ok(voPage);
    }
}

5. application.yml(基础配置)

server:
  port: 8080

spring:
  application:
    name: demo-api
  datasource:
    url: jdbc:mysql://localhost:3306/demo?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
    username: root
    password: 123456
    driver-class-name: com.mysql.cj.jdbc.Driver

mybatis-plus:
  configuration:
    map-underscore-to-camel-case: true
  global-config:
    db-config:
      id-type: auto

最后 10 分钟检查清单(新手最容易忘)

  • [ ] 加了 spring-boot-maven-plugin 吗?
  • [ ] application.yml 数据库连得上吗?
  • [ ] @RestController 而不是 @Controller?
  • [ ] @Valid + jakarta.validation 依赖加了吗?
  • [ ] lombok 插件装了吗?(IDEA)
  • [ ] 启动类有 @SpringBootApplication?
  • [ ] 浏览器打开 http://localhost:8080/swagger-ui.html 能看到文档吗?
  • [ ] Postman 测试过所有接口了吗?

完成以上步骤,你就已经从 0 写出了一个相对规范、可维护、生产可用的 RESTful API 项目

下一阶段推荐(按顺序)

  1. 加登录 + JWT 鉴权(最重要)
  2. 集成 Redis 做缓存
  3. 文件上传(MinIO / 阿里 OSS)
  4. 全局日志 + 请求链路追踪(TraceId)
  5. Docker 打包 + 部署

有哪一步卡住了?把报错信息或想加的功能告诉我,我直接给你最简代码补丁。加油!

文章已创建 3996

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

相关文章

开始在上面输入您的搜索词,然后按回车进行搜索。按ESC取消。

返回顶部