slog-spring-boot1.1.0文档—第二章 开发者文档

一、概述

场景示例

                                       图1.1 数据系统架构设计

系统主要分为4部分:

  • 网站:提供给用户交互界面
  • 业务系统:用户服务、报表服务、财务服务,用于业务处理和查询
  • 数据服务:大数据定时任务加工处理平台,执行结果回写入数据库
  • 数据库:提供数据存储、检索,业务系统和数据系统的存储区

系统主要角色分为3个:

  • 用户:系统使用者。不了解业务系统、数据服务
  • 数据开发:操作数据平台的开发人员。不了解业务系统、只熟悉SQL、HIVE
  • 业务开发:编写代码开发各业务逻辑

问题分析

这种设计产生了一个问题,当服务正式上线后,随着时间推移改变,系统必然会出现数据BUG,定位的方式一般是:

访问前端——>获得接口——>后端定位SQL——>数据定位SQL表对应的加工逻辑

因为数据开发不懂如何定位后端服务中的SQL,就必须后端开发人员介入,但后端开发一般并不需要调整,这会导致数据开发的需求无法及时响应和后端开发的碎片化。

解决思考

所以我们需要将问题SQL定位调整为:

前端——>查看请求——>获得执行SQL

我们可以通过前端访问接口的形式,获得后端执行的SQL,同时要考虑安全性,不同环境安全策略,以及可快速配置集成。

二、概要设计

命名

先给准备一个名字,嗯...一个好名字,能让人知道这可能是干什么,或者自己喜欢的个性名字,你才能更主动的构建和维护它,让我们拥有一个匠人的心。这个框架主要用来返回接口SQL,同时也算做一种日志采集,所以应该有单词log,然后让后端人员一直重复这无聊的工作很繁重,就叫slog好了,希望它能减少这项重复繁重的工作。

技术设计

                                                                                              图1.2 技术设计

我们首先思考如何去做,它需要在Http响应中获得SQL,所以需要Servlet Filter;关系到数据的读取和写入,需要用到字节流;需要在执行Mybatis获得SQL,需要使用Mybatis Filter;每个用户请求返回的SQL都可能不一样,所以跟线程存储相关,需要用到ThreadLocal;SpringBoot环境需要自动集成,需要Springboot stater。我们将这些串联起来,就是图1.2的技术设计图,流程如下:

  1. 通过@Bean集成至SpringBoot
  2. 用户请求Http接口
  3. 检查请求头判断触发条件(前置过滤)
  4. 符合条件,包装重写输出流(前置过滤)
  5. 初始化ThreadLocal(前置过滤)
  6. 执行SQL拦截器,记录至ThreadLocal(Mybatis拦截器)
  7. 将SQL写入Body体重,清除ThreadLocal(后置过滤)

项目结构设计

Springboot官方starter以spring-boot-starter-xxx的方式命名。官方建议自定义的starter使用xxx-spring-boot-starter命名规则,用来区分springboot生态提供的starter。我们定义如下的项目结构:

slog-spring-boot

——slog-spring-boot-starter

——slog-spring-boot-autoconfigure

——slog

对各部分作出说明:

  • slog-spring-boot:父类项目,用于统一依赖版本
  • slog-spring-boot-starter:定义springboot依赖,其他引用该jar可以自动集成
  • slog-spring-boot-autoconfigure:通过@Bean、@ConfigurationProperties自动加载springboot配置类、配置文件
  • slog:核心逻辑处理类,这里面不包含springboot相关引用和代码。可以看做是一个不依赖springboot环境也可以运行的类库,如果在非springboot环境,我们可以引用它来手动集成slog。

合理的项目工程化构建有利于后期的维护。比如slog是处理SQL的,slog-mybatis是可以直接作用于mybatis的,slog-hibernate是可以直接作用于hibernate的,因为使用方技术不是固定的,他们可以根据业务技术选型不同选择合适的依赖,同时编写mybatis处理时,不需要考虑hibernate的兼容问题。

maven命名

<groupId>com.v2hoping</groupId>

<artifactId>slog-spring-boot</artifactId>

<version>1.0.0-SNAPSHOT</version>

三、关键技术点

Servlet Filter

这里我们思考一下为什么使用Servlet的过滤器,而不使用SpringMvc拦截器?

因为第一我们需求对最终的结果进行修改,所以要获得输出流;第二点Servlet作为Springmvc的内核,如果不使用Springmvc也仍然可用,更通用。

我们实现javax.servlet.Filter接口的doFilter接口,调用下面责任链连执行逻辑,在该语句前为前置过滤,后则为后置过滤,最大区别是后置过滤时Reponse流中会保存结果。

chain.doFilter(request, filterResponseWrapper);

HttpServletRespnse输出流

这里我们思考一个问题,在执行完成chain.doFilter后,springmvc会将方法执行的结果自动写入输出流,我们该如何在拦截器中修改呢?

所以我们需要用到HttpServletResponseWrapper包装类,在调用chain.doFilter之前将原有的输出流包装成我们自定义的HttpServletResponseWrapper类,它的主要作用是在内部保存一个ByteArrayOutputStream,实际上是一个byte[],然后springmvc写入的数据会被暂存在该对象,之后我们可以使用自定义的getResponseData获得字符串。

mybatis Filter

             图1.3 mybatis执行流程

如图1.3所示,执行流程如下:

  1. Executor:拦截执行器的方法。
  2. ParameterHandler:拦截参数的处理。
  3. ResultHandler:拦截结果集的处理。
  4. StatementHandler:拦截Sql语法构建的处理。

我们可以对各个节点的各个方法进行拦截,例如以下注解就是对StatementHandler的查询、修改、批量操作进行拦截

@Intercepts({@Signature(type = StatementHandler.class, method = "query", args = {Statement.class, ResultHandler.class}),
@Signature(type = StatementHandler.class, method = "update", args = {Statement.class}),
@Signature(type = StatementHandler.class, method = "batch", args = {Statement.class})})

因为我们要获得SQL、参数,所以选择StatementHandler对象拦截,从流程图中可以看出该对象用于构建SQL。

ThreadLocal

ThreadLocal是JDK提供的本地线程变量,每个线程访问这个变量都是独占数据,互不影响。主要使用以下3个方法

private static final ThreadLocal<SlogContext> CONTEXT_THREAD_LOCAL = new ThreadLocal<>();
SlogContext slogContext = new SlogContext();
CONTEXT_THREAD_LOCAL.set(slogContext);//初始化线程变量
CONTEXT_THREAD_LOCAL.get();//获得线程变量
CONTEXT_THREAD_LOCAL.remove();//删除线程变量,防止内存溢出

四、结语

至此概要设计和技术要点就介绍完毕了,主要是给大家介绍如何遇到重复繁琐的工作时,通过技术优化工作,我觉得作为开发人员要具有工具化思维,如果一个东西重复用到3次以上,就应该考虑工具化,可能别人也会需要。如果一段代码重复修改3次以上,就应该考虑使用设计模式、代码重构优化它,让该段代码达到最小修改和复用。最后附上源码供大家参考。

github地址源码:https://github.com/v2hoping/slog-spring-boot

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值