记录一点开发技巧

记录一个开发常见的风格

1.RESTful

好的,我们来详细讲解一下 RESTful(通常写作 RESTfulREST)架构风格。这是现代 Web 服务和 API 设计的核心范式。


什么是 RESTful?

RESTREpresentational State Transfer)是一种软件架构风格,由 Roy Fielding 在 2000 年提出。它定义了一套约束条件,用于创建可扩展、松耦合的网络服务(Web APIs)。

RESTful 是指符合 REST 原则的 API 或服务。


RESTful API 关键设计

1. 资源(Resources)
  • 所有数据抽象为资源(用户、订单、产品等)
  • URI(统一资源标识符) 定位资源
    示例
    • /books → 所有书籍
    • /books/42 → ID=42 的书籍
2. HTTP 方法(动词)
方法作用幂等性示例
GET获取资源GET /users
POST创建新资源POST /users
PUT更新/替换整个资源PUT /users/1
PATCH部分更新资源PATCH /users/1
DELETE删除资源DELETE /users/1

幂等性:多次执行效果相同(如重复 PUT 不改变结果)

3. 状态码(Status Codes)

用 HTTP 状态码表示结果:

  • 200 OK:成功
  • 201 Created:资源创建成功
  • 400 Bad Request:客户端错误
  • 401 Unauthorized:未认证
  • 404 Not Found:资源不存在
  • 500 Internal Server Error:服务器错误

一个完整的 RESTful 示例

用户管理 API
功能HTTP 方法URI说明
获取所有用户GET/users返回用户列表
创建用户POST/users提交新用户数据
获取单个用户GET/users/{id}返回 ID 对应的用户
更新用户PUT/users/{id}替换整个用户数据
部分更新PATCH/users/{id}只更新指定字段(如邮箱)
删除用户DELETE/users/{id}删除该用户

常见误区

  • ❌ 用动词命名 URI(如 /getUser → 应改用 GET /users
  • ❌ 忽略 HTTP 状态码(所有响应都返回 200
  • ❌ 在 GET 请求中使用 Body 传递参数
  • ❌ 返回 HTML 页面而非结构化数据(JSON/XML)

示例代码:

@Data
public class Result<T> implements Serializable {

    private Integer code; //编码:1成功,0和其它数字为失败
    private String msg; //错误信息
    private T data; //数据

    public static <T> Result<T> success() {
        Result<T> result = new Result<T>();
        result.code = 1;
        return result;
    }

    public static <T> Result<T> success(T object) {
        Result<T> result = new Result<T>();
        result.data = object;
        result.code = 1;
        return result;
    }
    public static <T> Result<T> success(String msg,T object) {
        Result<T> result = new Result<T>();
        result.data = object;
        result.msg = msg;
        result.code = 1;
        return result;
    }

    public static <T> Result<T> error(String msg) {
        Result result = new Result();
        result.msg = msg;
        result.code = 0;
        return result;
    }

}


@PostMapping("/upload")
    public Result<String> uploadFile(@RequestParam("file") MultipartFile file) {
        boolean saved = markdownDocsService.saveFile(file);
        if (saved)
            return Result.success("上传成功");
        return Result.error("上传失败");
    }

2.全局异常处理

1.我们定义一个异常的枚举类用来返回异常信息

@Getter
@AllArgsConstructor
@ToString
public enum ResponseEnum {

    SUCCESS(1, "成功"),
    ERROR(-1, "服务器内部错误"),

    //-1xx 服务器错误
    BAD_SQL_GRAMMAR_ERROR(-101, "sql语法错误"),
    SERVLET_ERROR(-102, "servlet请求异常"), //-2xx 参数校验
    DELETE_FILE_FAILED(103, "删除文件错误"),
    UPLOAD_ERROR(-103, "文件上传错误"),
    EXPORT_DATA_ERROR(104, "数据导出失败"),
    DATA_NOt_EXISITS(105, "数据不存在"),
    PARAM_IS_NULL_ERROR(-105, "参数不能为空"),
    IMPORT_DATA_ERROR(106, "数据导入失败"),
    FILE_IS_EMPTY(107, "上传文件内容为空"),
    DISALLOW_DELETE_DATA(108, "该数据有关联数据不能删除"),
    TOO_MANY_REQUESTS(109, "请求太频繁了"),

    //-2xx 参数校验
    USRE_ID_NULL_ERROR(-201, "用户Id不能为空"),
    MOBILE_NULL_ERROR(-202, "手机号码不能为空"),
    MOBILE_ERROR(-203, "手机号码不正确"),
    PASSWORD_NULL_ERROR(204, "密码不能为空"),
    CODE_NULL_ERROR(205, "验证码不能为空"),
    CODE_ERROR(206, "验证码错误"),
    MOBILE_EXIST_ERROR(207, "手机号已被注册"),
    LOGIN_MOBILE_ERROR(208, "用户不存在"),
    LOGIN_PASSWORD_ERROR(209, "密码错误"),
    LOGIN_LOKED_ERROR(210, "用户被锁定"),
    LOGIN_AUTH_ERROR(-211, "未登录"),
    REGISTER_FAIL(212, "注册失败"),
    USER_REPEAT(-212, "重复注册"),
    USER_PWD_ERROR(213, "用户密码错误"),
    ACCOUNT_UNREGISTER(-213, "用户未注册"),
    ACCOUNT_UNLOGIN(214, "用户未登录"),
    USER_NOT_EXIST(215, "用户不存在"),
    USER_ISNOT_ROLE(215, "用户角色不匹配"),
    USERNAME_IS_EXIST(216, "用户名已存在"),
    ORG_NOT_EXIST(217, "机构信息不存在"),
    DELETE_SUCCESS(218, "删除成功"),
    DELETE_FAIL(219, "删除失败"),
    UPDATE_SUCCESS(220, "更新成功"),
    UPDATE_FAIL(221, "更新失败"),
    UPDATE_ERROR(222, "更新操作异常"),
    USER_BIND_IDCARD_EXIST_ERROR(-301, "身份证号码已绑定"),
    USER_NO_BIND_ERROR(302, "用户未绑定"),
    LEND_INVEST_ERROR(305, "当前状态无法投标"),
    LEND_FULL_SCALE_ERROR(306, "已满标,无法投标"),
    NOT_SUFFICIENT_FUNDS_ERROR(307, "余额不足,请充值"),

    PAY_UNIFIEDORDER_ERROR(401, "统一下单错误"),

    ALIYUN_SMS_LIMIT_CONTROL_ERROR(-502, "短信发送过于频繁"),//业务限流
    ALIYUN_SMS_ERROR(-503, "短信发送失败"),//其他失败

    WEIXIN_CALLBACK_PARAM_ERROR(-601, "回调参数不正确"),
    WEIXIN_FETCH_ACCESSTOKEN_ERROR(-602, "获取access_token失败"),
    WEIXIN_FETCH_USERINFO_ERROR(-603, "获取用户信息失败"),
    USER_TYPE_ERROR(-604, "用户信息异常"),;
    private final Integer code;//状态码
    private final String message;//消息

    ResponseEnum(int code, String message) {
        this.code = code;
        this.message = message;
    }
}

2.自定义一个异常类

/**
 * 业务异常
 */
@Getter
public class BusinessException extends RuntimeException {

    //状态码
    private Integer code;


    public BusinessException(String message, Integer code) {
        super(message);
        this.code = code;
    }

    public BusinessException(ResponseEnum responseEnum) {
        super(responseEnum.getMessage());
        this.code = responseEnum.getCode();
    }
    public BusinessException(ResponseEnum responseEnum, Throwable cause) {
        super(responseEnum.getMessage(),cause);
        this.code = responseEnum.getCode();
    }
}

3.全局异常处理

@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

    /**
     * 未定义异常处理
     */
    @ExceptionHandler(Exception.class)
    public Result<Object> exception(Exception e) {
        log.error(e.getMessage(), e);
        return Result.error("系统异常");
    }

    /**
     * 参数绑定异常处理
     */
    @ExceptionHandler(BindException.class)
    public Result<Object> handleBindException(BindException e) {
        return Result.error(e.getMessage());
    }
    @ExceptionHandler(ExecutionException.class)
    public Result<Object> handleExecutionException(ExecutionException e) {
        log.error(e.getMessage(), e);
        Result<Object> result = new Result<>();
        result.setMsg(REGISTER_FAIL.getMessage());
        result.setCode(REGISTER_FAIL.getCode()); // 设置特定错误码
        return result;
    }
    /**
     * 自定义业务异常处理
     */
    @ExceptionHandler(BusinessException.class)
    public Result<Object> handleBusinessException(BusinessException e) {
        log.error(e.getMessage(), e.getCause());
        Result<Object> result = Result.error(e.getMessage());
        result.setCode(e.getCode()); // 设置自定义错误码
        return result;
    }
    @ExceptionHandler(NotLoginException.class)
    public Result <Object> handleNotLoginException(NotLoginException e) {
        log.error(e.getMessage(), e);
        Result<Object> result = Result.error(ResponseEnum.ACCOUNT_UNLOGIN.getMessage());
        result.setCode(ResponseEnum.ACCOUNT_UNLOGIN.getCode()); // 设置特定错误码
        return result;
    }
    @ExceptionHandler(SQLException.class)
    public Result<Object> handleSQLException(SQLException e) {
        log.error(e.getMessage(), e);
        Result<Object> result = Result.error(ResponseEnum.IMPORT_DATA_ERROR.getMessage());
        result.setCode(ResponseEnum.IMPORT_DATA_ERROR.getCode()); // 设置特定错误码
        return result;
    }
    /**
     * Servlet请求相关异常处理
     */
    @ExceptionHandler({
            NoHandlerFoundException.class,
            HttpRequestMethodNotSupportedException.class,
            HttpMediaTypeNotSupportedException.class,
            MissingPathVariableException.class,
            MissingServletRequestParameterException.class,
            HttpMessageNotReadableException.class,
            HttpMessageNotWritableException.class,
            MethodArgumentNotValidException.class,
            HttpMediaTypeNotAcceptableException.class,
            ServletRequestBindingException.class,
            ConversionNotSupportedException.class,
            MissingServletRequestPartException.class,
            AsyncRequestTimeoutException.class
    })
    public Result<Object> handleServletException(Exception e) {
        log.error(e.getMessage(), e);
        Result<Object> result = Result.error(ResponseEnum.SERVLET_ERROR.getMessage());
        result.setCode(ResponseEnum.SERVLET_ERROR.getCode()); // 设置特定错误码
        return result;
    }

}

4.在处理业务是我们就可以利用抛出异常的方法处理错误情况


public MarkdownDocsServiceImpl() {
        try {
            // 使用 ClassPathResource 确保路径正确指向 resources/document 目录
            ClassPathResource resource = new ClassPathResource(MD_SAVE_PATH);
            this.rootLocation = resource.getFile().toPath();
        } catch (Exception e) {
            throw new RuntimeException("初始化文件存储路径失败: " + MD_SAVE_PATH, e);
        }
    }

3.讲到这里了,再给大家讲一个 ClassPathResour

这个我也是今天刚用,很神奇,我的业务需求是我想存储前端的md文件到我的项目中下次启动的时候可以进行处理,当然还要立刻处理一下,存储是为了持久化,数据库我也想过,暂时还没有实现,我先尝试了这一种

ClassPathResource resource = new ClassPathResource(MD_SAVE_PATH);
String MD_SAVE_PATH ="classpath:document"

他会把文件存储到target的classes里面,很神奇我还在研究它的原理,

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一入JAVA毁终身

感谢,破费了,破费了

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值