移動優先時代,Java 後端通過 RESTful API 為 App/Web 提供統一數據服務。本文講解 REST 核心原則、Spring MVC 註解式開發、JSON 序列化、統一響應封裝、異常處理、安全與最佳實踐,附完整登錄接口示例代碼。
| 原則 | 說明 | 示例 |
|---|---|---|
| 資源導向 | URL 標識資源,非動作 | GET /users/123 而非 /getUserById |
| HTTP 動詞 | GET/POST/PUT/DELETE 對應 CURD | POST /users 創建 |
| 無狀態 | 服務端不保存客戶端上下文 | 每請求攜帶 Token/JWT |
| 統一響應 | 固定結構:code、message、data | {"code":200,"data":{...}} |
| 版本控制 | URL 或 Header 管理版本 | /api/v1/users |
@RestController = @Controller + @ResponseBody,直接返回對象自動轉 JSON。@RequestMapping / @GetMapping / @PostMapping 映射路徑與方法。@PathVariable 綁定 URL 佔位符 {id}。@RequestBody 綁定請求體 JSON 反序列化為對象。@RequestParam 綁定查詢參數 ?name=xxx。@Data @AllArgsConstructor @NoArgsConstructor
public class Result<T> {
private int code; // 200 成功,其他業務錯誤碼
private String message; // 提示信息
private T data; // 業務數據
public static <T> Result<T> ok(T data) {
return new Result<>(200, "成功", data);
}
public static <T> Result<T> fail(int code, String msg) {
return new Result<>(code, msg, null);
}
}
@Data
public class LoginDTO {
private Integer username; // 學號/工號
private String password;
}
public interface UserService {
boolean login(Integer username, String password);
}
@Service
public class UserServiceImpl implements UserService {
@Autowired private UserDao userDao; // Hibernate/JPA/MyBatis
@Override
public boolean login(Integer username, String password) {
User user = userDao.findByUsername(username);
return user != null && passwordEncoder.matches(password, user.getPassword());
}
}
NSString *urlStr = [NSString stringWithFormat:@"%@/api/v1/auth/login", BASE_URL];
NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:urlStr]];
req.HTTPMethod = @"POST";
req.setValue(@"application/json", forHTTPHeaderField:@"Content-Type");
NSDictionary *body = @{@"username": @12345, @"password": @"123456"};
req.HTTPBody = [NSJSONSerialization dataWithJSONObject:body options:0 error:nil];
NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:req
completionHandler:^(NSData *data, NSURLResponse *resp, NSError *err) {
if (err) { NSLog(@"網絡錯誤: %@", err); return; }
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
NSNumber *code = json[@"code"];
if ([code intValue] == 200) {
NSLog(@"登錄成功");
} else {
NSLog(@"登錄失敗: %@", json[@"message"]);
}
}];
[task resume];
@ControllerAdvice + @ExceptionHandler 統一捕獲異常返回 Result。@Valid + JSR-303 註解 (@NotNull、@Size) + BindingResult。| 問題 | 原因 | 解決 |
|---|---|---|
| 返回 406 Not Acceptable | 缺少 Jackson 依賴或未啟用 @EnableWebMvc | 引入 spring-boot-starter-web (含 Jackson) |
| 日期字段序列化為時間戳 | Jackson 默認格式 | 配置 spring.jackson.serialization.write-dates-as-timestamps=false + @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss") |
| 循環引用導致 StackOverflow | 雙向關聯實體 | @JsonIgnore / @JsonManagedReference + @JsonBackReference / DTO 打破循環 |
| 大文件上傳 OOM | 默認內存緩衝 | 配置 spring.servlet.multipart.max-file-size + 流式處理 |
RESTful 不是新技術,而是架構風格約定。Spring MVC + Jackson 讓 Java 實現 REST API 變得極簡:定義 DTO → 寫 Service → Controller 註解映射 → 統一響應封裝。生產級項目再疊加「安全、文檔、觀測、治理」四大支柱,即可構建穩健、可演進的移動端後端服務。建議下一步:實戰項目中引入 Spring Boot 3 + Spring Doc + JWT 完整落地。