首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計疑難解答

JAX-RS 如何根據 DAO 返回值動態設置 HTTP 狀態碼

     編輯:程式設計疑難解答

核心思路

在 JAX-RS (如 Jersey、RESTEasy) 中,資源方法可直接返回 Response 對象,通過 Response.status(int).entity(Object).build() 靈活控制 HTTP 狀態碼、響應體、Headers。DAO 層只需返回業務狀態 (枚舉、布爾值、自定義結果對象),資源層映射為對應 HTTP 狀態。

推薦分層設計

1. 定義統一業務結果封裝

public class Result<T> {
    private boolean success;
    private T data;
    private String errorCode;
    private String errorMsg;
    // getter/setter + 靜態工廠方法 ok()/fail()
}

2. DAO 層返回 Result

@Repository
public class UserDao {
    public Result<User> save(User user) {
        try {
            // 持久化邏輯
            return Result.ok(user);
        } catch (DataIntegrityViolationException e) {
            return Result.fail("DUP_KEY", "用戶已存在");
        } catch (Exception e) {
            return Result.fail("DB_ERR", "數據庫異常");
        }
    }
}

3. 資源層映射 HTTP 狀態

@Path("/users")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class UserResource {

    @Inject UserDao userDao;

    @POST
    public Response createUser(User user) {
        Result<User> result = userDao.save(user);

        if (result.isSuccess()) {
            // 201 Created,並返回 Location 頭
            return Response.status(Response.Status.CREATED)
                           .entity(result.getData())
                           .header("Location", "/users/" + result.getData().getId())
                           .build();
        }

        // 根據錯誤碼映射具體狀態
        switch (result.getErrorCode()) {
            case "DUP_KEY":  return Response.status(Response.Status.CONFLICT).entity(result).build(); // 409
            case "VALID_ERR": return Response.status(Response.Status.BAD_REQUEST).entity(result).build(); // 400
            default:         return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(result).build(); // 500
        }
    }
}

常見 HTTP 狀態碼映射表

業務場景HTTP 狀態Response.Status 常量
創建成功201CREATED
查詢/更新成功200OK
刪除成功無內容204NO_CONTENT
參數校驗失敗400BAD_REQUEST
未授權/Token 失效401UNAUTHORIZED
無權限訪問403FORBIDDEN
資源不存在404NOT_FOUND
資源衝突 (如唯一鍵重複)409CONFLICT
服務器內部錯誤500INTERNAL_SERVER_ERROR

進階技巧:異常映射器

若不想在每個資源方法寫 if-else,可拋出自定義異常,配合 ExceptionMapper 統一轉換:

@Provider
public class BusinessExceptionMapper implements ExceptionMapper<BusinessException> {
    @Override
    public Response toResponse(BusinessException e) {
        return Response.status(e.getStatus())
                       .entity(Result.fail(e.getCode(), e.getMessage()))
                       .build();
    }
}

// 資源方法簡化為
@POST
public User createUser(User user) {
    Result<User> r = userDao.save(user);
    if (!r.isSuccess()) throw new BusinessException(r.getErrorCode(), r.getErrorMsg(), mapToHttpStatus(r.getErrorCode()));
    return r.getData(); // 直接返回實體,JAX-RS 自動轉 200/201
}

總結

  • DAO 返回 業務結果對象,不直接返回 HTTP 狀態。
  • 資源層負責 業務狀態 → HTTP 狀態映射,使用 Response.status(...).build()。
  • 複雜項目引入 ExceptionMapper 實現關注點分離,代碼更乾淨。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved