随手写个 Spring Boot微服务节点

随手写个 Spring Boot微服务节点

当年前圈内各路神仙开始实践服务拆分,开始做SOA, 6年前兴起的微服务,近几年火热的SpringCloud, 最近边车模式开始流行ServiceMesh服务网格.微服务在我们面前反复横跳, 顺手耗掉你几根头毛的同时不说吸还吸粉无数.今天我卢本伟随手写个微服务节点不是问题.

image

构建Spring Boot maven多模块项目

使用IDEA构建多模块maven 项目骨架, 基本操作不多bb.

Spring Boot 版本选择2.2.4

  • 打开idea选择new project选择Spring Initializr 创建第一个Springboot项目
    image
  • 保留以下文件,其他文件都删除
    image
  • 构建maven子模块
    image
    image
  • 将多余文件删除, 将pom中<parent>修改为如下所示[图片上传失败...(image-99397-1583248865412)]
  • web模块在构造的时候重复上面的步骤, 并勾选Spring Web选项
    image

模块功能

demo
|-- demo-api      jar文件 API二方包
|-- demo-core     jar文件 核心业务层
|-- demo-data     jar文件 持久层
|-- demo-server   jar文件 provider,发布的web服务
|-- demo-util     jar文件 工具包
`-- pom.xml       maven 发布文件

集成ORM框架Mybatis

集成方案

目前我知道的有四种方式:

  • Mybatis + XML
  • Mybatis + 注解
  • Mybatis-Plus
  • tkmybatis
    这里我们选用Mybatis-Plus这种方式集成,原因有以下几点:
  1. 相比 Mybatis + XML 配置项来说,Mybatis-Plus 增加了更多配置项,也因此我们无需在配置 mybatis-config.xml 配置文件

  2. Mybatis-Plus增加BaseMapper接口, 常规CRUD可以替我们自动生成

    • insert(DO do)
    • updateById(DO do)
    • deleteById(@Param("id") Integer id)
    • selectById(@Param("id") Integer id)
  3. 注解的方式不适合排版SQL, 且mapper接口很长显得杂乱

  • Mybatis官方文档
  • 因为最初设计时,MyBatis 是一个 XML 驱动的框架.配置信息是基于 XML 的,而且映射语句也是定义在 XML 中的.而到了 MyBatis 3,就有新选择了.MyBatis 3 构建在全面且强大的基于 Java 语言的配置 API 之上.这个配置 API 是基于 XML 的 MyBatis 配置的基础,也是新的基于注解配置的基础.注解提供了一种简单的方式来实现简单映射语句,而不会引入大量的开销.
  • 不幸的是,Java 注解的的表达力和灵活性十分有限.**尽管很多时间都花在调查、设计和试验上,最强大的 MyBatis 映射并不能用注解来构建——并不是在开玩笑,的确是这样.比方说,C#属性就没有这些限制,因此 MyBatis.NET 将会比 XML 有更丰富的选择.也就是说,基于 Java 注解的配置离不开它的特性.

就是说他们自己也不推荐这种写法.

  1. tkmybatis 是多个开源项目组合起来的, tk是toolkit 的缩写.

建议

不要在 service 中使用 QueryWrapper 拼接动态条件, 这样业务逻辑层会充斥着各种查询,不方便做统一管理.

Mybatis-Plus

https://mp.baomidou.com/

maven配置

<!--全局变量-->
<properties>
    <mysql.version>5.1.48</mysql.version>
    <mybatis.plus.version>3.2.0</mybatis.plus.version>
    <pagehelper.version>1.2.13</pagehelper.version>
</properties>
<!-- mysql -->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>${mysql.version}</version>
            </dependency>
            <!-- orm mybatis-->
            <dependency>
                <groupId>com.baomidou</groupId>
                <artifactId>mybatis-plus-annotation</artifactId>
                <version>${mybatis.plus.version}</version>
                <scope>compile</scope>
            </dependency>
            <dependency>
                <groupId>com.baomidou</groupId>
                <artifactId>mybatis-plus-boot-starter</artifactId>
                <version>${mybatis.plus.version}</version>
            </dependency>
            <!-- pagehelper -->
            <dependency>
                <groupId>com.github.pagehelper</groupId>
                <artifactId>pagehelper-spring-boot-starter</artifactId>
                <version>${pagehelper.version}</version>
            </dependency>

Mybatis-Plus配置

@Configuration
@MapperScan(basePackages = "com.barm.demo.data.*")
public class MybatisPlusConfig {
}

application.yaml

spring:
  datasource:
    url: jdbc:mysql://127.0.0.1:3306/demo?useSSL=false&useUnicode=true&characterEncoding=UTF-8
    driver-class-name: com.mysql.jdbc.Driver
    username: root
    password: 123456

mybatis-plus:
  global-config:
    db-config:
      logic-delete-field: flag  
      id-type: auto
  mapper-locations: classpath:mapper/*.xml
  type-aliases-package: com.barm.demo.domain

logging:
  level:
    cn:
      iocoder:
        springboot:
          lab12:
            mybatis:
              mapper: debug

其他

更多配置项,参考 MyBatis-Plus 使用配置

IDEA插件

看到这里有的观众老爷可能会问为“为啥没MybatisGenerate模块?”, 这里我们推荐使用MyBatisCodeHelper-Pro, Intellij下Mybatis插件.一个不错的生产力工具.

放上几个操作感受一下.

  • 根据DO生成DDL
    image
  • 生成Mapper
    image
  • 添加属性重复上面操作可直接修改原文件
    image
  • 根据方法生成Mapper接口及xml,命名当时类似JPA
    image
  • 从Mapper中生成对应Service方法实现
    image
  • 生成service分页方法,这里使用的是google的PageHelper
    image

    这个插件是收费的, 但是依然提供了很多免费功能, 可体验一个月.有兴趣的小伙伴可以试试.

抽象出全局common包

用于统一服务之间的交互格式,和一些常用的工具类

github源码地址: https://github.com/allennotes/common

maven 配置

<properties>
    <common.version>1.0.0SNAPSHOT</common.version>
</properties>  
<dependency>
    <groupId>com.barm</groupId>                                  <artifactId>common</artifactId>
    <version>${common.version}</version>
</dependency>

异常统一处理

  • 定义公用系统异常
@Getter
public class ApplicationException extends Exception{
    
    /** 结果枚举*/
    private final ResultEnum resultEnum;
    /** 自定义异常信息*/
    private String errMsg;
    /** 异常码 */
    private Integer errCode;

    public ApplicationException(ResultEnum resultEnum) {
        super(resultEnum.getMsg());
        this.errCode = resultEnum.getCode();
        this.errMsg = resultEnum.getMsg();
        this.resultEnum = resultEnum;
    }

    public ApplicationException(String errMsg) {
        super(ResultEnum.FAIL.getMsg());
        this.errCode = ResultEnum.FAIL.getCode();
        this.errMsg = errMsg;
        this.resultEnum = ResultEnum.FAIL;
    }
}
  • 如果全部异常处理返回json,那么可以使用 @RestControllerAdvice 代替 @ControllerAdvice
@Slf4j
@RestControllerAdvice
public class ExceptionHandlers {
    @ExceptionHandler(value = ApplicationException.class)
    public ResultVO applicationException(ApplicationException e){
        log.error("exception for system", e);
        return new ResultVO(ResultEnum.FAIL);
    }

    @ExceptionHandler(value = RuntimeException.class)
    public ResultVO runtimeException(RuntimeException e){
        log.error("exception for runtime", e);
        ResultVO resultVO = new ResultVO(ResultEnum.FAIL);
        return resultVO;
    }
}

基于线程池的异步注解

从Spring3开始提供了@Async注解,这里我们无需引入直接上配置.

@EnableAsync
@Configuration
public class AsyncConfig {

    private static final int corePoolSize = 10;
    private static final int maxPoolSize = 50;
    private static final int keepAliveTime = 10;
    private static final int queueCapacity = 100000;
    private static final String threadNamePrefix = "Async-Executor-";

    @Bean
    public ThreadPoolTaskExecutor getAsyncExecutor(){
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(corePoolSize);
        executor.setMaxPoolSize(maxPoolSize);
        executor.setQueueCapacity(queueCapacity);
        executor.setKeepAliveSeconds(keepAliveTime);
        executor.setThreadNamePrefix(threadNamePrefix);
        // 线程池对拒绝任务的处理策略
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        // 初始化
        executor.initialize();
        return executor;
    }
}

对象转化

DO,BO,VO各模块之间的转换, 我们使用mapstruct,请参考属性拷贝你还在用BeanUtils?

启动项目

image

总结

  • 本文主要讲述了使用Spring Boot 快速构建一个微服务节点主要功能
    • MybatisPlus集成
      • 通用增改
      • 统一逻辑删
      • 分页查询
    • 异常统一处理
    • 消息体格式统一
    • 对象转化
    • 基于线程池的异步注解
  • 后续会陆续更新新的功能,例如:
    • 配置注册中心
    • 远程调用
    • 配置缓存
    • 配置消息队列
    • 分布式事务
    • 配置分布式锁
    • 分布式定时任务
    • 配置配置中心
    • 集成token
    • 配置分库分
  • 更多github源码:https://github.com/allennotes/webserver
  • 欢迎issues提问
    这期就这么多了.欢迎大家评论,交流,关注,点赞~


    image
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,294评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,780评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,001评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,593评论 1 289
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,687评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,679评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,667评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,426评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,872评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,180评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,346评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,019评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,658评论 3 323
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,268评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,495评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,275评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,207评论 2 352

推荐阅读更多精彩内容