开发文档.md 9.1 KB

基础框架

框架基于ruoyi-vue版本,做了部分优化改造,并命名为miaxis。

原ruoyi-vue提供了以下功能:

  1. 用户管理:用户是系统操作者,该功能主要完成系统用户配置。
  2. 部门管理:配置系统组织机构(公司、部门、小组),树结构展现支持数据权限。
  3. 岗位管理:配置系统用户所属担任职务。
  4. 菜单管理:配置系统菜单,操作权限,按钮权限标识等。
  5. 角色管理:角色菜单权限分配、设置角色按机构进行数据范围权限划分。
  6. 字典管理:对系统中经常使用的一些较为固定的数据进行维护。
  7. 参数管理:对系统动态配置常用参数。
  8. 通知公告:系统通知公告信息发布维护。
  9. 操作日志:系统正常操作日志记录和查询;系统异常信息日志记录和查询。
  10. 登录日志:系统登录日志记录查询包含登录异常。
  11. 在线用户:当前系统中活跃用户状态监控。
  12. 定时任务:在线(添加、修改、删除)任务调度包含执行结果日志。
  13. 代码生成:前后端代码的生成(java、html、xml、sql)支持CRUD下载 。
  14. 系统接口:根据业务代码自动生成相关的api接口文档。
  15. 服务监控:监视当前系统CPU、内存、磁盘、堆栈等相关信息。
  16. 在线构建器:拖动表单元素生成相应的HTML代码。
  17. 连接池监视:监视当前系统数据库连接池状态,可进行分析SQL找出系统性能瓶颈。

改造内容:

  • ORM框架 使用 Mybatis-Plus 简化CRUD
  • Bean简化 使用 Lombok 简化 get set toString 等等
  • 代码生成模板 改为适配 Mybatis-Plus 的代码,以及自带swagger标签
  • 集成swagger-bootstrap-ui 打开地址:http://localhost:8080/doc.html
  • 改造所有返回值AjaxResult为Response让Swagger的@ApiModel识别(因为swagger不支持返回的hashMap和Json形式
  • 项目修改为 maven多环境配置,打包时候自动配置
  • 新增登录方法(不含验证码) /login/noCode ,方便生成token用swagger登录Authorize授权测试
  • 新增非系统用户的登录方式,包含密码登录和手机验证码登录
  • ResponseEnum统一状态消息管理,方便排查问题
  • 修改打包方式为war包,方便部署远程tomcat

技术选型

  • 前端:Vue、Element UI
  • 后端:Spring Boot、Spring Security、Redis、Jwt、Swagger2 & Swagger-Bootstrap-UI、 Lombok、mybatis、mybatis-plus。

项目结构

com.miaxis 
├──project-admin              //web服务入口Controller管理模块(业务表生成的Controller层代码可以放在这里的project包下面)
│    │    └──project                //这里写你的项目业务代码Controller
│    │    └──system                 //系统自带Controller(不要随意修改)
│    │    └──启动类          //springboot项目启动类(默认启动地址http://localhost:8080)
│    │               
├──project-common             //通用模块(通用工具类等)
├──project-framework          //框架核心模块(包含redis,druid,Log等)
├──project-generator          //代码生成器模块
├──project-quartz             //定时任务模块
├──project-system             //系统模块 (不要随意修改)
├──project-xxx                //业务模块,除了controller 之外的都放在这边
├──doc                      //说明文档文件夹
├──sql                      //sql脚本文件夹 
│   └──create_db.sql                //生成数据库和用户
│   └──create_business.sql          //用于存放你们自己业务表的sql
│   └──quartz.sql                   //用于存放定时任务sql
│   └──ry_20201021.sql              //系统基本表自带的sql
├──pom.xml                  //项目整体依赖

后端开发流程

  1. 创建表,表结构规范参考
  2. 使用代码生成器 本次以sys_config举例,实际项目中不要去生成系统自带的sys开头的表,否则启动不了,因为代码模板不一样,有细微区别 打开后台管理系统,点击菜单——>系统工具——>代码生成

Image text Image text

如果生成之前要更改信息,可以点击编辑进入更改,注意要修改路径,模块名

Image text

可以点击预览查看代码生成的效果

Image text

勾选然后可以点击生成(如果数据库中配好了comment注释,和table注释可以直接生成注释文字)

Image text

解压后可以看到代码生产结果,然后拷贝到项目中对应的文件夹即可——main是java代码,vue是前端代码,deptMenu.sql是在菜单表中添加一条菜单数据,后端而言,可以直接复制整个main文件夹到我们项目模块src下,并且将controller 剪切到 admin 模块中

Image text

如果该表是实体表,在前端有相应的列表,则需要将xxxMenu.sql在数据库中执行,即可以把相应的菜单按钮权限等数据写入数据库(这样可以不用在后台管理系统中去手动添加)

到此,基本的增删改查代码已经生成。

  1. swagger文档使用

未登录授权前,接口无法调试

Image text

登录用法-用登录(免验证码)

Image text

然后保存

Image text

之后就能愉快的调试了

Image text

后端开发规范

  1. 命名规范
  2. 命名使用英文词组合,使用驼峰式,严禁使用中文拼音或拼音首字母组合命名(专有名词例外) 如: OrganizationTreeNode, OrganizationVO, OrganizationDTO, 常量应该用全大写,下划线命名,如: APP_SECRET
  3. Controller, Service, Mapper统一添加到对应分层目录
  4. 接口实现类添加Impl后缀标识
  5. 枚举类添加Enum后缀标识
  6. 接口api路径,使用restful风格命名规范,简单来说,url上不允许出现动词,只能使用名次,动作由请求方式来制定:GET-获取 POST-新增 PUT-更新 DELETE-删除(可以参考代码生成器生成的代码)

  7. 返回值类型Response ,泛型T一定要指定类型,否则swagger无法识别返回值具体数据格式以及注解,如

    @GetMapping(value = "/{id}")
    @ApiOperation("获取电子教学日志详细信息")
    public Response<TMClassRecordDetail> getInfo(
        @ApiParam(name = "id", value = "电子教学日志参数", required = true)
        @PathVariable("id") Long id
    ){
    return Response.success(tMClassRecordDetailService.getById(id));
    }
    
    

  8. 异常 Controller层,可直接使用Response.error ,重载了多个方法,根据具体情形使用

    @Log(title = "电子教学日志", businessType = BusinessTypeEnum.INSERT)
    @PostMapping
    @ApiOperation("新增电子教学日志")
    public Response<Integer> add(@RequestBody TMClassRecordDetail tMClassRecordDetail){
    if (tMClassRecordDetail == null){
        return Response.error();
    }
    return toResponse(tMClassRecordDetailService.save(tMClassRecordDetail) ? 1 : 0);
    }
    
    
    
  9. service层,若有运行时异常,无需捕获,直接抛出自定义异常,如业务异常:CustomException,统一由全局 异常处理器GlobalExceptionHandler 进行处理,例子如下:

    private void validateCode(String principal, String credential) {
        if (StringUtils.isEmpty(credential)){
            throw new CustomException("验证码不能为空");
        }
        String cacheCode = (String) redisTemplate.opsForValue().get(RedisPrefixUtils.getSmsKeyPrefix("login", principal));
        if (StringUtils.isEmpty(cacheCode)){
            throw new CustomException("验证码已过期,请重新发送");
        }else if (!credential.equals(cacheCode)){
            throw new CustomException("验证码不正确");
        }
    }
    
    
    1. 枚举类 原则上,代码中不应该出现魔法数字,比如下面代码

      if (type == 1){
      xxx
      }
      

      正确做法应该新建一个枚举类,如

      public enum UserStatusEnum
      {
      OK("0", "正常"), DISABLE("1", "停用"), DELETED("2", "删除");
      
      private final String code;
      private final String info;
      
      UserStatusEnum(String code, String info)
      {
          this.code = code;
          this.info = info;
      }
      
      public String getCode()
      {
          return code;
      }
      
      public String getInfo()
      {
          return info;
      }
      }
      

    使用的时候

    if (type == UserStatusEnum.OK.getCode()){
       xxx
    }
    
    1. 入参,出参 ,如果传入参数与实体字段相差较大,可以新建DTO对象,DTO 意思为数据传输对象,包含了出参,入参,如果为了区分,也可以把入参命名为DTO,返参命名为VO

      @PostMapping("/login")
      @ApiOperation("系统-登录方法")
      public Response<TokenDTO> login(@RequestBody LoginBody loginBody)
      {   TokenDTO tokenDTO = new TokenDTO();
      // 生成令牌
      String token = loginService.login(loginBody.getUsername(), loginBody.getPassword(), loginBody.getCode(),
              loginBody.getUuid());
      tokenDTO.setToken(token);
      return Response.success(tokenDTO);
      }