SpringBoot定义优雅全局统一Restful API 响应框架完结撒花篇封装starter组件

kenx
• 阅读 368

之前我们已经,出了一些列文章。 讲解如何封统一全局响应Restful API。

感兴趣的可以看我前面几篇文章 (整个starter项目发展史)

SpringBoot定义优雅全局统一Restful API 响应框架

SpringBoot定义优雅全局统一Restful API 响应框架二

SpringBoot定义优雅全局统一Restful API 响应框架三

SpringBoot定义优雅全局统一Restful API 响应框架四

SpringBoot定义优雅全局统一Restful API 响应框架五

SpringBoot定义优雅全局统一Restful API 响应框架六

后续我萌生里新的想法,SpringBoot 不是提供了自己的starter。我们也可以自定义starter吗,于是我定义了rest-api-spring-boot-starter,已经发布到maven中央仓库,对之前Restful API 响应框架 做了集成和重构,

在这个基础上我又总结封装了我自己工作以常用的很多工具,结合SpringBoot 封装了全能的工具。 已经更新到了1.3.0 不耦合任何依赖 请使用最新版本

SpringBoot定义优雅全局统一Restful API 响应框架完结撒花篇封装starter组件

目前更新版本1.3.0 功能如下

  1. 支持一键配置自定义RestFull API 统一格式返回
  2. 支持RestFull API 错误国际化
  3. 支持全局异常处理,全局参数验证处理
  4. 业务错误断言工具封装,遵循错误优先返回原则
  5. redis工作封装。支持所有key操作工具
  6. RestTemplate 封装 POST,GET 请求工具
  7. 日志集成。自定义日志路径,按照日志等级分类,支持压缩和文件大小分割。按时间显示
  8. 工具库集成 集成了lombok,hutool,commons-lang3,guava。不需要自己单个引入
  9. 集成mybatisPlus一键代码生成

github 地址

下面我讲一下怎么在项目中去使用

我们新建一个SpringBoot Web项目

我们只需要在pom中引入即可

 <dependency>
            <groupId>cn.soboys</groupId>
            <artifactId>rest-api-spring-boot-starter</artifactId>
            <version>1.2.0</version>
        </dependency>

在启动类或者配置类中加上@EnableRestFullApi 注解即可 SpringBoot定义优雅全局统一Restful API 响应框架完结撒花篇封装starter组件

RestFull API使用

这样在项目controller中我们写普通的请求如:

 @PostMapping("/chat")
    public HashMap chatDialogue() {
        HashMap m = new HashMap();
        m.put("age", 26);
        m.put("name", "Judy");
        return m;
    }

返回的就是全局统一RestFull API

SpringBoot定义优雅全局统一Restful API 响应框架完结撒花篇封装starter组件

我们也可以这么写

SpringBoot定义优雅全局统一Restful API 响应框架完结撒花篇封装starter组件

提供了很多返回方法。

当然如果你这个接口不想包装成全局返回,想自定义单独返回 如我们只需要在方法上加上@NoRestFulApi 注解即可

   @PostMapping("/chat")
    @NoRestFulApi
    public HashMap chatDialogue() {
        HashMap m = new HashMap();
        m.put("age", 26);
        m.put("name", "Judy");
        return m;
    }

就不会对返回内容进行任何包装处理。 SpringBoot定义优雅全局统一Restful API 响应框架完结撒花篇封装starter组件

全局错误拦截,参数校验

帮你封装好了所有http常见错误,和所有请求类型和参数错误。

如请求错误

{
    "success": false,
    "code": "405",
    "msg": "方法不被允许",
    "timestamp": "2023-07-03 22:36:47",
    "data": "Request method 'GET' not supported"
}

请求资源不存在

{
    "success": false,
    "code": "404",
    "msg": "请求资源不存在",
    "timestamp": "2023-07-03 22:42:35",
    "data": "/api"
}

参数校验错误

验证Studen对象参数

/**
 * @author 公众号 程序员三时
 * @version 1.0
 * @date 2023/6/26 22:10
 * @webSite https://github.com/coder-amiao
 */
@Data
public class Student {
    @NotBlank
    private String nam;
    @NotBlank
    private String hobby;
}
    @PostMapping("/chat")
    public HashMap chatDialogue(@Validated  Student student) {
        HashMap m = new HashMap();
        m.put("age", 26);
        m.put("name", "Judy");
        return m;
    }

请求结果 SpringBoot定义优雅全局统一Restful API 响应框架完结撒花篇封装starter组件

JSON Body参数

    @PostMapping("/chat")
    public HashMap chatDialogue(@RequestBody @Validated  Student student) {
        HashMap m = new HashMap();
        m.put("age", 26);
        m.put("name", "Judy");
        return m;
    }

SpringBoot定义优雅全局统一Restful API 响应框架完结撒花篇封装starter组件

SpringBoot定义优雅全局统一Restful API 响应框架完结撒花篇封装starter组件

错误国际化

内置封装错误默认支持英文和中文两种国际化。你不做任何配置自动支持

如果需要内置支持更多语言,覆盖即可。

自定义自己错误国际化和语言

  i18n:
    # 若前端无header传参则返回中文信息
    i18n-header: Lang
    default-lang: cn
    message:
      # admin
      internal_server_error:
        en: Internal Server Error
        cn: 系统错误
      not_found:
        en: Not Found
        cn: 请求资源不存在

message 对应错误提示 对应internal_server_error 自定义 下面语言自己定义 和前端传入i18n-header 对应上,就显你定义错误语言

我不传错误国际化默认就是中文在 default-lang: cn 进行配置

SpringBoot定义优雅全局统一Restful API 响应框架完结撒花篇封装starter组件

当我传入 指定语言 就会按照你配置的国际化自定义返回错误提示

SpringBoot定义优雅全局统一Restful API 响应框架完结撒花篇封装starter组件

自定义错误响应

如果我内置错误无法满足你业务需求,你也可以自定义自己错误码

你自定义错误枚举 只需要实现ResultCode接口即可

package cn.soboys.restapispringbootstarter;

import cn.soboys.restapispringbootstarter.i18n.I18NKey;

/**
 * @author 公众号 程序员三时
 * @version 1.0
 * @date 2023/6/26 10:21
 * @webSite https://github.com/coder-amiao
 * 响应码接口,自定义响应码,实现此接口
 */
public interface ResultCode extends I18NKey {

    String getCode();

    String getMessage();

}

如果要支持国际化还需要实现国际化接口I18NKey 参考我内部HttpStatus实现即可

package cn.soboys.restapispringbootstarter;

import cn.soboys.restapispringbootstarter.i18n.I18NKey;

/**
 * @author 公众号 程序员三时
 * @version 1.0
 * @date 2023/6/26 11:01
 * @webSite https://github.com/coder-amiao
 */
public enum HttpStatus implements ResultCode, I18NKey {
    /**
     * 系统内部错误
     */
    INTERNAL_SERVER_ERROR("500", "internal_server_error"),
    BAD_GATEWAY("502", "bad_gateway"),
    NOT_FOUND("404", "not_found"),
    UNAUTHORIZED("401", "unauthorized"),
    FORBIDDEN("403", "forbidden"),
    METHOD_NOT_ALLOWED("405", "method_not_allowed"),
    REQUEST_TIMEOUT("408", "request_timeout"),

    INVALID_ARGUMENT("10000", "invalid_argument"),
    ARGUMENT_ANALYZE("10001", "argument_analyze"),
    BUSINESS_EXCEPTION("20000", "business_exception");


    private final String value;

    private final String message;

    HttpStatus(String value, String message) {
        this.value = value;
        this.message = message;
    }


    @Override
    public String getCode() {
        return value;
    }

    @Override
    public String getMessage() {
        return message;
    }


    @Override
    public String key() {
        return message;
    }
}

rest-api:
  enabled: false
  i18n:
    # 若前端无header传参则返回中文信息
    i18n-header: Lang
    default-lang: cn
    message:
      # admin
      internal_server_error:
        en: Internal Server Error
        cn: 系统错误
      bad_gateway:
        en: Bad Gateway
        cn: 错误的请求
      unauthorized:
        en: Unauthorized
        cn: 未授权
      forbidden:
        en: Forbidden
        cn: 资源禁止访问
      method_not_allowed:
        en: Method Not Allowed
        cn: 方法不被允许
      request_timeout:
        en: Request Timeout
        cn: 请求超时
      invalid_argument:
        en: Invalid Argument {}
        cn: 参数错误 {}
      argument_analyze:
        en: Argument Analyze {}
        cn: 参数解析异常 {}
      business_exception:
        en: Business Exception
        cn: 业务错误
      not_found:
        en: Not Found
        cn: 请求资源不存在

SpringBoot定义优雅全局统一Restful API 响应框架完结撒花篇封装starter组件

SpringBoot定义优雅全局统一Restful API 响应框架完结撒花篇封装starter组件

SpringBoot定义优雅全局统一Restful API 响应框架完结撒花篇封装starter组件

SpringBoot定义优雅全局统一Restful API 响应框架完结撒花篇封装starter组件

内部错误不需要做任何配置,自动支持国际化。如果需要支持更多语言,可以自定义进行覆盖。

业务异常断言

在项目开发中我们有时需要封装自己异常类,信息我封装了统一的错误异常类。 BusinessException 对业务异常类做了全局错误拦截,

封装·了统一业务异常断言工具,遵循错误优先返回原则。代码更优雅

SpringBoot定义优雅全局统一Restful API 响应框架完结撒花篇封装starter组件

    @GetMapping("/exception")
    public Result exception(){
        Student s=null;
        Assert.isFalse(s==null,"学生不能为空");
        return Result.buildSuccess();
    }

抛出统一业务异常

SpringBoot定义优雅全局统一Restful API 响应框架完结撒花篇封装starter组件

当然如果你要定义自己的异常类。可以定义自己异常类·继承我的BusinessException

Redis 工具库使用

进一步封装的对Redis所以相关key,value操作,在使用redis工具库时候。我们需要引入

 <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

默认不会帮你引入。

然后在使用时候注入就行

@Autowired
    private RedisTempUtil redisTempUtil;

SpringBoot定义优雅全局统一Restful API 响应框架完结撒花篇封装starter组件

    @GetMapping("/redis")
    public Result redis() {
        redisTempUtil.set("test", "123456");
        return Result.buildSuccess();
    }


    @GetMapping("/redis/get")
    public Result redisGet() {
        String value = redisTempUtil.get("test").toString();
        log.info("redis值{}", value);
        return Result.buildSuccess();
    }

RestTemplate 请求工具

进一步封装了RestTemplate请求 Post和GET 项目中使用时注入

 @Autowired
    private RestFulTemp restFulTemp;

SpringBoot定义优雅全局统一Restful API 响应框架完结撒花篇封装starter组件

    @GetMapping("/doGet")
    public Result doGet() {
        ResponseEntity<String> response = restFulTemp.doGet("http://127.0.0.1:8000/redis/get");
        return Result.buildSuccess(response.getBody());
    }

日志使用

进一步封装了 日志处理达到开箱即用。在属性文件中配置相关日志配置即可

rest-api:
  enabled: false
  logging:
    path: ./logs   #日志存储路径(服务器上绝对)
    max-history: 90 # 保存多少天
    max-file-size: 3MB  # 每个文件大小
    max-total-size-cap: 1GB  #总文件大小超过多少压缩
    level-root: INFO    # 这里的INFO可以替换为其他日志等级,如DEBUG, WARN, ERROR, TRACE, FATAL, OFF等。 日志等级由低到高分别是debugger-info-warn-error

如果你的属性文件不做任何日志配置,默认日志就是上面这样配置。

集成mybatisPlus一键代码生成

在项目中我们会频繁使用到mybatisPlus 但是简单的模板代码我们一键生成就好。 默认不依赖mybatisPlus任何相关包。如果需要使用自动代码生成引入mybatisPlus 代码生成依赖包即可。

 <!--生成器依赖-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-generator</artifactId>
            <version>3.4.1</version>
            <optional>true</optional>
        </dependency>
        <!-- MySQL -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.28</version>
            <optional>true</optional>
        </dependency>
        <!--代码生成依赖的模板引擎-->
        <dependency>
            <groupId>org.freemarker</groupId>
            <artifactId>freemarker</artifactId>
            <version>2.3.31</version>
            <optional>true</optional>
        </dependency>

你可以直接写测试类,然后直接去调用代码生成即可

public class Test {
    public static void main(String[] args) {
        GenerateCodeConfig config=new GenerateCodeConfig();
        config.setDriverName("com.mysql.cj.jdbc.Driver");
        config.setUsername("root");
        config.setPassword("root");
        config.setUrl("jdbc:mysql://127.0.0.1:3306/ry?useUnicode=true&useSSL=false&characterEncoding=utf8");
        //生成代码保存路径,不设置就是当前项目下路径,如何设置请使用绝对路径
        config.setProjectPath("superaide");
        config.setPackages("cn.soboys.superaide");
        MyBatisPlusGenerator.generate(config);
    }
}

效果如下 SpringBoot定义优雅全局统一Restful API 响应框架完结撒花篇封装starter组件

关注公众号,程序员三时 持续输出优质内容 希望给你带来一点启发和帮助

下篇文章就这个源码剖析讲解 如何封装自己的stater

点赞
收藏
评论区
推荐文章
kenx kenx
1年前
SpringBoot定义优雅全局统一Restful API 响应框架
假如现在有一个Java项目,老板让你做项目组长,定义项目基础框架,系统技术架构选型,你应该如何设计一个规范的统一的RestfulAPI响应框架呢思考目前项目开发,都是基于前后端分离模式开发的,基于后端模板引擎那一套,可能已经不适用一些项目开发流程,和当下开
kenx kenx
1年前
SpringBoot定义优雅全局统一Restful API 响应框架二
这里解决之前留下来的问题,当程序没有正常返回时候就是程序由于运行时异常导致的结果,有些异常我们可,能无法提前预知,不能正常走到我们return的R对象返回。这个时候该如何处理在SpringBoot中,可以使用@ControllerAdvice注解来启用全局
kenx kenx
1年前
SpringBoot定义优雅全局统一Restful API 响应框架三
我们目前已经设计出了,包含全局响应,异常错误响应进行了统一返回。但是错误内容我们设计的比较模糊统一,还可以进行细化这样更有利于定位错误当我们需要调用Http接口时,无论是在Web端还是移动端,都有可能遇到各种错误,例如参数缺失、类型错误、系统错误等。为了规
Stella981 Stella981
3年前
Spring Boot自定义starter必知必会条件
SpringBoot自定义starter必知必会前言在目前的SpringBoot框架中,不管是SpringBoot官方还是非官方,都提供了非常多的starter系列组件,助力开发者在企业应用中的开发,提升研发人员的工作效率,SpringBoot框架提出的约定大于配置的规则,确实帮助开发者简化了以前SpringMVC时代的很多繁杂的
Stella981 Stella981
3年前
Spring Boot(六):自定义starter
在springboot中,使用最多的就是starter。starter可以理解为一个可拔插式的插件,例如,你想使用jdbc插件,那么可以使用springbootstarterjdbc。随着版本的推移Starter家族成员也与日俱增。在传统Maven项目中通常将一些层、组件拆分为模块来管理,以便相互依赖复用,在SpringBoot项目中我们则可以创建自
Stella981 Stella981
3年前
SpringBoot 简介
什么是SpringBoot    SpringBoot是一种全新的框架,目的是为了简化Spring应用的初始搭建以及开发过程。该框架使用特定的方式(集成starter,约定优于配置)来进行配置,从而使开发人员不需要再定义样板化的配置。SpringBoot提供了一种新的编程范式,可以更加快速便捷地开发Spring
kenx kenx
1年前
SpringBoot定义优雅全局统一Restful API 响应框架四
好代码是优化出来的,不是写出来的!!如果没看前面文章,可以先看前面几篇SpringBoot定义优雅全局统一RestfulAPI响应框架
kenx kenx
1年前
SpringBoot定义优雅全局统一Restful API 响应框架五
闲话不多说,继续优化全局统一RestfulAPI响应框架做到项目通用接口可扩展。如果没有看前面几篇文章请先看前面几篇这里解决上一篇留下问题如何实现接口错误国际化。还有上一篇错误提示也不是很友好我们可以在进一步抽象出通用异常接口。异常信息应由固定异常编码信息
kenx kenx
1年前
SpringBoot定义优雅全局统一Restful API 响应框架六
闲话不多说,继续优化全局统一RestfulAPI响应框架做到项目通用接口可扩展。如果没有看前面几篇文章请先看前面几篇这里讲一讲最后的版本和需要修复的一些问题java@PostMapping("/add/UserApiCombo")publicRaddApi
Spring Boot Starter 剖析与实践 | 京东云技术团队
本文介绍了在没有SpringBoot和Starter之前,开发人员在使用传统的SpringXML开发Web应用时需要引用许多依赖,并且需要大量编写XML代码来描述Bean以及它们之间的依赖关系。也了解了如何利用SPI加载自定义标签来加载Bean并进行注入。