eladmin JPA转Mybatis与后端框架迭代更新历程

2020-10-24T10:56:00
本文会持续记录博主对eladmin框架的完善以及转化mybatis plus的历程

[scode type="share"]2020年8月15日受腾飞学长委托,要为小组搭建一个之后要一直使用的后端管理系统框架,并以el admin为主,进行删改和重构,将原有的持久层框架jpa修改为mybatis plus[/scode]
[scode type="blue"]2020年8月16日正式开始转化[/scode]

  • 首先一开始是熟悉eladmin的后端开发手册,其次是了解eladmin的源码。
  • 一开始由于eladmin本身功能比较丰富,也比较“重”,可能对于部分小项目用不了那么多完备的功能,首先是对原有的eladmin进行删模块,将原本的5个核心模块删为了两个,一个是system,另一个是权限控制secuirty,并删去了很多无需的表和方法,最终测试可以运行。

[scode type="blue"]2020年8月17日比葫芦画瓢[/scode]

  • 开始对着原eladmin开始比葫芦画瓢,自己一点点分模块开始搭建,一开始搭建还是比较慢的,要改pom,注释等等;直接复制jar还要改import等等,还是比较慢的。
  • 晚上继续搭建后端系统,主要是处理登录这一块的内容,因为接口转化还过早,所以现在先把security这块转了,但是我发现这一块也很麻烦,弄了一晚上自己的还没等上去,主要因为security里就用到了jpa查询,而且还不少。所以转化很慢。

[scode type="blue"]2020年8月18日——jpa+mp计划[/scode]

  • 上午继续针对转化security这一块开动,仿照他的查询我也写了不少方法,但是由于eladmin没有使用bo,所以实体类里直接有关联属性,但是我查询的时候就比较模糊,不知道是全查还是单个查,导致数据总是为null。
  • 还有mapStruct的转化,用于转化dto和entity的(没有用于转化bo的)。
  • 还有各种jackson和缓存的报错

    org.springframework.security.authentication.InternalAuthenticationServiceException: com.alibaba.fastjson.JSONObject cannot be cast to me.zhengjie.modules.system.service.dto.UserDto
    //
    No cache could be resolved for...
  • 所以这一块还需要大量的时间去研究才行。
  • 因为项目可能就要用到这个后台管理系统,所以我的转化只能先停掉,采用他的原jpa加上我们的mp做这次后端。
  • 所以我在他的代码基础上引入了mp,并测试了新接口,没问题。
  • 但是发现验证码为0时会报错误,经发现是esay-capture生成结果为0的验证码时存入redis的时0.0,所以会和0匹配错误。而eladmin这边也没处理这个问题。明天我会修改这两个问题并提两个pr。

[scode type="blue"]2020年8月19日——给eladmin提PR[/scode]

  • 上午主要修改昨天发现的验证码出现浮点数的问题,主要在/auth/code接口中:

    //当验证码类型为 arithmetic时且长度 >= 2 时,captcha.text()的结果有几率为浮点型
    String captchaValue = captcha.text();
    if (captcha.getCharType() - 1 == LoginCodeEnum.arithmetic.ordinal() & captchaValue.contains(".")) {
      captchaValue = captchaValue.split("\\.")[0];
    }
    // 保存
    redisUtils.set(uuid, captchaValue, loginProperties.getLoginCode().getExpiration(), TimeUnit.MINUTES);
  • 也是学了学如何在github上提pr,相对于这个是修复bug的,所以要先提issue,在提pr关联这个issue。
  • 上午针对其修复的方式其实治标不治本,真正意义上还要修改easy-captcha本身的代码才行。所以我又把easy-captcha的代码拉了下来,研究产生浮点数的根本原因。
  • 最终定位在这一句:

    ScriptEngineManager manager = new ScriptEngineManager();
          ScriptEngine engine = manager.getEngineByName("javascript");
          try {
              chars = String.valueOf(engine.eval(sb.toString().replaceAll("x", "*")));
          } catch (ScriptException e) {
              e.printStackTrace();
          }
  • 目前的解决方法还是使用split分割。
  • 之后继续转化security,目标是多对多查询,在我查询user的时候,把其部门也查出来,还有他的多个角色和多个工作。但是这个sql语句执行之后一直查询失败,目前还在找原因。

[scode type="blue"]2020年8月21日——理解jpa_mp中的security流程[/scode]

  • 上午继续对jpa_mp分支做调整。删除一些无用类,修改一些注释,补添了微信授权接口。
  • 下午开始理解jpa_mp中的security流程,了解整个项目中各个类的作用。
  • 之后对后端框架进行打包,发现打包过程中就出现了不少错误,得先把原先的target都删掉,再对核心模块进行打包。
  • 之后在cmd上运行时发现乱码,原因是cmd默认系统编码是gbk,需要先修改系统的编码。而且cmd不支持彩色日志。

[scode type="blue"]2020年8月22日——master完成关联查询[/scode]

  • 上午继续推荐mybatis转化——master分支的推进。
  • 上午还是在处理查询用户的超难关联查询,在查询用户的同时把多个job和多个role查出来,其中role里还包含了多个menu,所以整体就很麻烦。
  • 而且还有id封装为null的bug,最后各种调试才解决。并且抛弃了bo,直接把关联实体写在了entity里,使用@TableField(exist = false)来标明。
  • 有关与中间表的查询,关联类的查询需要自己再写sql语句:

    @Select("SELECT * FROM user u WHERE u.username = '${name}'")
    @Results({
          @Result(column = "user_id", property = "id"),
          @Result(column = "dept_id", property = "deptId"),
          @Result(column = "dept_id", property = "dept",
                  one = @One(select = "marchsoft.modules.api.mapper.DeptMapper.selectById" ,
                          fetchType = FetchType.EAGER)),
          @Result(column = "user_id", property = "roles",
                  many = @Many(select = "marchsoft.modules.api.mapper.RoleMapper.findWithMenuByUserId",
                          fetchType = FetchType.EAGER)),
          @Result(column = "user_id", property = "jobs",
                  many = @Many(select = "marchsoft.modules.api.mapper.JobMapper.findByUserId",
                          fetchType = FetchType.EAGER))
    })
    User findByName(String name);         
    @Select("SELECT r.* FROM role r, users_roles ur WHERE r.role_id = ur.role_id AND ur.user_id = ${id}")
    @Results({
          @Result(column = "role_id", property = "id"),
          @Result(column = "role_id", property = "menus",
                  many = @Many(select = "marchsoft.modules.api.mapper.MenuMapper.findByRoleId",
                          fetchType = FetchType.EAGER))
    })
    Set<Role> findWithMenuByUserId(Long id);
  • mybatis关联查询时column的值不能加表名!
  • 下午继续推进登录流程的转化,完善其他的方法。
  • 晚上继续完善登录流程,处理了一个大问题,首先是redis缓存,总是报错,之后发现类上少加了一个注解,方法上也要加注解:

    @CacheConfig(cacheNames = "user")   +   @Cacheable(key = "'username:' + #p0")
  • 还有一个问题是缓存和数据库不统一,需要及时清理缓存,从新查数据库。

[scode type="blue"]2020年8月23日——完成主页面显示[/scode]

  • 上午继续完善登录流程,最终是通过了前端的验证,但是想要显示主页,还要完善Menu的build接口。主要是查询菜单的。
  • 之后一直完善菜单的接口。也是各种的多表查询和封装,最后完成,可以成功登录并显示首页了。
  • 下午是对第一版转化成功(登录)做一些完善,加一些注释。

[scode type="blue"]2020年8月24日——验证权限管理[/scode]

  • 上午开始对各个接口进行转化,第一个是部门接口,先转化了download接口,但是第二个就难到我了。第二个接口是queryAll,其中用到了他们的Query、QueryHelp、DataPermision,这些是和JPA强耦合的,所以转化起来会慢一些。
  • 之后学长给我之前的jpa_mp提了一些建议,我开始修改,主要是让其他同学上手容易。之后一直在完善readme.md文档。
  • 下午学长让我验证一下jpa_mp权限这一块,包括新增角色、用户,分配权限等。研究了后台管理系统如何给角色分配菜单等等。
  • 自己在前端新建接口的时候发现权限拦截不了,最后才发现原来一直运行的是之前打的jar包。
  • 最后验证权限分配拦截没有问题。

[scode type="blue"]2020年8月25日——mp分支转化dept接口[/scode]

  • 上午继续转化dept接口,继续研究其中最难的查询方法,但是看了一段时间后还是无果,转向其他接口了。
  • 其中包含基础的增删改接口。
  • 下午继续转化dept接口,这些接口相对来说简单一些,所以其他接口基本上转换完毕。
  • 同时之前的jpa_mp分支又出现了一些bug,并修复。

[scode type="blue"]2020年8月26日——mp分支转化menu接口[/scode]

  • 上午主要就是处理menu的接口的转化,当然是排除查询接口。
  • 下午把menu接口转化完毕。
  • 晚上在处理角色的缓存bug,eladmin是这么设计的,如果该角色是管理员,则缓存里只用存管理员一个角色即可,默认拥有所有权限。
  • 同时了解到springboot和redis整合的使用:@Cacheable + redis +#p0

[scode type="blue"]2020年8月27日——jpa_mp添加新模块tools[/scode]

  • 之后开始转化user接口。也是基本上没有太大的难度。
  • jpa_mp分支新加api_tools模块,用于文件上传和微信处理。

[scode type="blue"]2020年8月28日——mp分支转化剩余接口[/scode]

  • 上午先处理昨天写了user接口之后,项目启动失败的问题。报错原因是userServiceImpl动态代理注入失败的问题:

    because it is a JDK dynamic proxy that implements
  • 具体愿意不知道为什么,反正我一注入UserServiceImpl就报这个错误,最后的解决方法是在springboot启动类的@EnableTransactionManagement加上参数:(改为GGlib基于类代理,而不是基于接口代理,在yml配置文件中设置aop.proxy无效

    @EnableTransactionManagement(proxyTargetClass = true)
  • 之后添加api_tools模块,初始化文件上传接口合微信第三方接口。
  • 下午继续转换job和role接口。基本上没有什么难的地方。

[scode type="blue"]2020年8月29日——修改接口bug[/scode]

  • 修改user和role接口的获取不到数据的bug。(数据库查非空数据使用的是 is null 而并非 = null)。

[scode type="blue"]2020年8月30日——重写文件上传[/scode]

  • 根据昨天讨论的文件上传的功能,发现原有的eladmin的功能不能实现本次业务需求,而且很多冗余方法,只得从新写,就开始看eladmin的文件上传源码再结合之前club的上传源码。
  • 下午开始写文件上传模块,并删除之前的文件上传模块。重构数据库,用mp实现上传业务。
  • 主要是两个接口,一个是单文件上传,一个是文件下载。

[scode type="green"]有关jpa_mp分支的更新就到8月底了,剩下的优化和修复都在新院统战项目中进行了,本来这个分支就是过渡分支。纯mp分支由于在小组内部仓库,这里不做展示,后期都整合到了SMPE框架里。[/scode]

[scode type="green"]之后jpa_mp版框架成功应用于新院统战、平安科院、科研管理系统三个项目中,至此,小组框架第一版的搭建到此结束[/scode]


[scode type="yellow"]2020年11月12日——讨论第一版框架的问题,更新第二版[/scode]

讨论内容总结:

el-admin通用环境(marchsoft_api)问题

  1. mybatis @one、@many是否使用?
  2. mybatis的缓存和mp的分页插件有问题,mapper层加注解pageSize等信息有问题,service没问题。
  3. 系统用户查询相关比较复杂?
  4. 请求返回格式不统一
  5. 第三方依赖引入比较乱(重复引入,最小引入)
  6. 第三方以子库形式引入我们的主仓库,第三方维护文档
  7. 微信小程序和公众号分开
  8. 第三方服务不应该以接口的形式出现
  9. 框架缺少日志处理

平安科院后续:
星星:

  1. 缓存机制不清晰
    a. 存的什么?
    b. 什么时候存的?
  2. 持久层选择(jpa,mybatis)
  3. 部分功能使用复杂
  4. 直接修改数据库,有redis缓存,数据会存在问题(没走缓存)
  5. token签名验证太死了,不好做扩展

晓珊问题:

  1. 注释
  2. 框架使用手册,对于新手来说很难入手
  3. 没有搭框架,学到的东西很少

讨论问题结果:

  1. mybatis @one、@many是否使用?
    讨论结果:不建议使用
    ● join查询:查询时候可以使用join连接查询,支持最多3张表join查询
    ● 业务组装:将多张表的信息返回到业务层,然后利用for循环语句组装数据,效率比@One,@many要快
    ● 利用缓存:可以使用@one和@many,第一次查询时效率慢些,但对接下来查询,会直接从缓存中查询,不用走数据库
  2. mybatis的缓存和mp的分页插件有问题,mapper层加注解pageSize等信息有问题,service没问题。
    讨论结果:
    ● 不用mybatis-plus 的分页插件,找其他插件。
    ● 小组自己开发分页插件
    调研结论:
  3. 分页插件没有问题
  4. 默认业务mapper类加二级缓存,指定Radis
  5. 默认业务service不再添加Radis缓存
  6. 对应mapper开二级缓存,允许使用@one/@many
  7. 系统用户查询相关比较复杂?
    讨论结果:暂时未定
  8. 请求返回格式不统一?
    讨论结果:
    ● 返回的状态码用枚举,返回值不定死
  9. 第三方依赖引入比较乱(重复引入,最小引入)
    讨论结果:
  10. 不随意引用第三方模块插件、引用前需大家确人 (note by lqc)
  11. 去掉现有重复引用,保留安全的
  12. 放置位置
    a. 在common文件下放置与业务无关的工具类,通用方法封装
    b. 在tools文件下放置与业务相关的工具类,如:短信工具类,封装接口工具类(hik API)
  13. 需要有使用说明手册
  14. 第三方以子库形式引入我们的主仓库,第三方维护文档
    讨论结果:
  15. 第三方库需要维护使用文档
  16. 我们的第三方围绕着(基于其项目结构)eladmin开发,服务以模块形式存在
  17. 微信公众号模块
    a. 消息队列分离到项目业务,公众号模块只对外提供使用接口
  18. 三方服务不应该以接口的形式出现
    讨论结果:
  19. 对外需不需要提供服务接口,如果不需要,封装成业务工具类放在tools下
  20. 微信小程序和公众号分开
  21. 造成配置信息混乱的解决方法
    a. 在配置属性前加 前缀

    wx:
      #微信公众号
      mp:
      #微信小程序
      miniapp:
  22. 框架缺少日志处理
    框架日志侧重对敏感业务日志进行收集。
    讨论结果:
  23. 日志位置
    a. 失败出(必)
    b. 敏感操作,增删改
  24. 信息(内容)
    a. 不输出无用信息,主(谁)谓(动词)宾(对谁)状补(干了什么,怎么样了)
    b. 输出信息中包含自己的唯一信息(邮箱、名字缩写如lqc)
    c. 本地调试可以打印SQL结果,上线不允许打印,但可打印执行的SQL语句
  25. 格式待定……
  26. 等级
    a. 框架中常用日志等级(从低到高): Debug->Info->warning->Error
    b. 各日志等级使用

     i. Debug: 在本地开发中使用,可打印任何打印信息
     ii. Info:打印业务日志
     iii. Error:报错,业务预期/非预期错误,站在业务角度:需要关注的程序异常都用此等级打印

    c.

  27. 缓存机制不清晰(存的什么?什么时候存的?)
    讨论结果:
  28. 存放缓存的地方需说明,维护一个文档
  29. 缓存集中放在一处(redis)
  30. 修改数据库要在群中通知一下大家, 这个规定放在维护文档中
  31. 使框架业务不依赖与redis,部分可依赖(登录、排行榜)
    问题遗留:
  32. redis和springboot环境中有两份缓存,找出两份的原因(内存机制中,mybatis,redis)
  33. 持久层选择(jpa,mybatis)
    讨论结果:改成完全 mybatis plus
  34. 部分功能使用复杂
    由于jpa和mybatis共存原因引起,后期改成mybatis plus可缓解。
  35. 直接修改数据库,有redis缓存,数据会存在问题(没走缓存)
    同问题 10
  36. token签名验证太死了,不好做扩展
    token只提供了读取方法,未提供设置方法,想对其修改比较麻烦,如果有个设置的方法会更好(更方便)。
  37. 注释
    讨论结果:
  38. Controller层有swagger注释的可不加注释
  39. 类、接口、方法至少需要注明:作者、时间、日期,描述功能
  40. 在必要处,如分支等地方
  41. 在改别人代码时,在注释中加入自己修改的名字和修改日期
  42. 框架使用手册,对于新手来说很难入手
    讨论结果:基本的文档是必须的
  43. 没有搭框架,学到的东西很少
    尝试着去搭一下,先会用然后再搭建;
    多多向下传承,搭建过整合过的带带新人;
  44. 项目单元测试
    之前没有进行,之后需要规范。
    单元测试目前统一是测试业务层
  45. 内置角色
    系统中固定不能删除的角色
  46. 数据加密
    如果后端负责全部的加密解密工作可能不好做,把解密放在前端会好点,和前台约定
  47. 测试问题
  48. 需要在开发时使用相应的测试号进行测试
  49. 没有单元测试(同问题18)
  50. 代码规范问题
    a. 对报错的警告也要处理
    b. 推荐使用阿里巴巴java插件对代码检查
  51. 第二版框架整合安排
  52. 把一版框架改成mybatis plus(花费1~2天),近期有项目用这个环境
  53. 第二版改成mybatis plus的,并解决以上出现的问题
  54. 框架搭建完毕,经过测试没有问题,把咱们的环境放到github上

[scode type="red"]这次讨论之后便是确定了框架第二版的更新方向,但是由于up主要于12月26日参加2021考研,所以这次便没有参与第二版的开发,交接给组内另一位大佬管理,并正式命名为SMPE框架[/scode]


[scode type="share"]博主考研结束后,于2021年1月10日继续参与后端框架的更新中,主要处理缓存问题[/scode]
[scode type="blue"]2021年1月10日,讨论SMPE框架目前遗留的问题[/scode]

  • 目前框架仍然遗留的大问题就是缓存问题,晚上和星星讨论的结果就是 重新实现@One与@Many方法,在开发效率和之前保持一致的同时又可以使用springboot的缓存。

[scode type="blue"]2021年1月11日~12日,开发新注解@Query[/scode]
[scode type="blue"]2021年1月13日~14日,讨论缓存维护并整合SMPE[/scode]

当前页面是本站的「Baidu MIP」版。发表评论请点击:完整版 »