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

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

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

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

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

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

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

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

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

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

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

目前更新版本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 地址[7]

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

我们新建一个SpringBoot Web项目

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

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

在启动类或者配置类中加上 @EnableRestFullApi 注解即可

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

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

返回的就是全局统一RestFull API

我们也可以这么写

提供了很多返回方法。

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

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

就不会对返回内容进行任何包装处理。

帮你封装好了所有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;
    }

请求结果

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;
    }

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

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

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

  i18n:
    
    i18n-header: Lang
    default-lang: cn
    message:
      
      internal_server_error:
        en: Internal Server Error
        cn: 系统错误
      not_found:
        en: Not Found
        cn: 请求资源不存在

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

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

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

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

你自定义错误枚举 只需要实现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:
    
    i18n-header: Lang
    default-lang: cn
    message:
      
      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: 请求资源不存在


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

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

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

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

抛出统一业务异常

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

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

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

默认不会帮你引入。

然后在使用时候注入就行

@Autowired
    private RedisTempUtil redisTempUtil;

    @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请求 Post和GET 项目中使用时注入

 @Autowired
    private RestFulTemp restFulTemp;

    @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    

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

在项目中我们会频繁使用到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);
    }
}


效果如下

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

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

参考资料

[1]

https://mp.weixin.qq.com/s?__biz=Mzg4OTkwNjc2MQ==&mid=2247483741&idx=1&sn=2734d2ef008edcf1369dd7a31a88a142&chksm=cfe5f27bf8927b6d468a411fe2eaeeeb6dbdd5527dec77a77a0e580ea32b2b58f38922836552#rd: https://link.juejin.cn/?target=https%3A%2F%2Fmp.weixin.qq.com%2Fs%3F__biz%3DMzg4OTkwNjc2MQ%3D%3D%26mid%3D2247483741%26idx%3D1%26sn%3D2734d2ef008edcf1369dd7a31a88a142%26chksm%3Dcfe5f27bf8927b6d468a411fe2eaeeeb6dbdd5527dec77a77a0e580ea32b2b58f38922836552%23rd

[2]

https://mp.weixin.qq.com/s?__biz=Mzg4OTkwNjc2MQ==&mid=2247483752&idx=1&sn=eab94282e3f1e62682d2106cfb2949d1&chksm=cfe5f24ef8927b582e01863881a88452dcbcb102afdb9b50985304b97dfd74cd0c3ed0b8c2c3#rd: https://link.juejin.cn/?target=https%3A%2F%2Fmp.weixin.qq.com%2Fs%3F__biz%3DMzg4OTkwNjc2MQ%3D%3D%26mid%3D2247483752%26idx%3D1%26sn%3Deab94282e3f1e62682d2106cfb2949d1%26chksm%3Dcfe5f24ef8927b582e01863881a88452dcbcb102afdb9b50985304b97dfd74cd0c3ed0b8c2c3%23rd

[3]

https://mp.weixin.qq.com/s?__biz=Mzg4OTkwNjc2MQ==&mid=2247483761&idx=1&sn=dbc516d0ba14228c1f091dfa39d85209&chksm=cfe5f257f8927b41635fe1508c2829d73e2b788105b145bc51525be4574b83a1a8da23c49ec2#rd: https://link.juejin.cn/?target=https%3A%2F%2Fmp.weixin.qq.com%2Fs%3F__biz%3DMzg4OTkwNjc2MQ%3D%3D%26mid%3D2247483761%26idx%3D1%26sn%3Ddbc516d0ba14228c1f091dfa39d85209%26chksm%3Dcfe5f257f8927b41635fe1508c2829d73e2b788105b145bc51525be4574b83a1a8da23c49ec2%23rd

[4]

https://mp.weixin.qq.com/s?__biz=Mzg4OTkwNjc2MQ==&mid=2247483887&idx=1&sn=cb737d573adca7eaea7a59cad2a7bbfe&chksm=cfe5f2c9f8927bdfaf7e46fd38d26f56fffbb1ece8460eaffe2addee592e42ffee6ba49530b7#rd: https://link.juejin.cn/?target=https%3A%2F%2Fmp.weixin.qq.com%2Fs%3F__biz%3DMzg4OTkwNjc2MQ%3D%3D%26mid%3D2247483887%26idx%3D1%26sn%3Dcb737d573adca7eaea7a59cad2a7bbfe%26chksm%3Dcfe5f2c9f8927bdfaf7e46fd38d26f56fffbb1ece8460eaffe2addee592e42ffee6ba49530b7%23rd

[5]

https://mp.weixin.qq.com/s?__biz=Mzg4OTkwNjc2MQ==&mid=2247484102&idx=1&sn=e17772a12e6548755c341c2d9300e235&chksm=cfe5f1e0f89278f669c4c89548b3fdeec4dd58d6d7d7580315d07f20c9b52ffdd21ef5a7c232&token=691863430&lang=zh_CN#rd: https://link.juejin.cn/?target=https%3A%2F%2Fmp.weixin.qq.com%2Fs%3F__biz%3DMzg4OTkwNjc2MQ%3D%3D%26mid%3D2247484102%26idx%3D1%26sn%3De17772a12e6548755c341c2d9300e235%26chksm%3Dcfe5f1e0f89278f669c4c89548b3fdeec4dd58d6d7d7580315d07f20c9b52ffdd21ef5a7c232%26token%3D691863430%26lang%3Dzh_CN%23rd

[6]

https://mp.weixin.qq.com/s?__biz=Mzg4OTkwNjc2MQ==&mid=2247484160&idx=1&sn=37eea0079dd175634437f01dde38bb4c&chksm=cfe5f026f892793045fb242a556ce4e3010f4a4aae867a84fe3542ed18ac3c64b85e87fa536a#rd: https://link.juejin.cn/?target=https%3A%2F%2Fmp.weixin.qq.com%2Fs%3F__biz%3DMzg4OTkwNjc2MQ%3D%3D%26mid%3D2247484160%26idx%3D1%26sn%3D37eea0079dd175634437f01dde38bb4c%26chksm%3Dcfe5f026f892793045fb242a556ce4e3010f4a4aae867a84fe3542ed18ac3c64b85e87fa536a%23rd

[7]

https://github.com/coder-amiao/rest-api-spring-boot-starter: https://link.juejin.cn/?target=https%3A%2F%2Fgithub.com%2Fcoder-amiao%2Frest-api-spring-boot-starter

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

技术小羊

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值