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

2023-07-06 10:50:09   来源:博客园

之前我们已经,出了一些列文章。 讲解如何封统一全局响应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 不耦合任何依赖 请使用最新版本

目前更新版本1.3.0 功能如下

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

github 地址

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

我们新建一个SpringBoot Web项目

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

            cn.soboys            rest-api-spring-boot-starter            1.2.0        

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

RestFull API使用

这样在项目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 */@Datapublic 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:    # 若前端无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进行配置

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

自定义错误响应

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

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

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

业务异常断言

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

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

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

抛出统一业务异常

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

Redis 工具库使用

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

            org.springframework.boot            spring-boot-starter-data-redis        

默认不会帮你引入。

然后在使用时候注入就行

@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 请求工具

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

@Autowired    private RestFulTemp restFulTemp;
@GetMapping("/doGet")    public Result doGet() {        ResponseEntity 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 代码生成依赖包即可。

                    com.baomidou            mybatis-plus-generator            3.4.1            true                                    mysql            mysql-connector-java            8.0.28            true                                    org.freemarker            freemarker            2.3.31            true        

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

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

标签: