• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    迪恩网络公众号

    cmdAdmin: cmdAdmin是基于Spring Cloud Alibaba体系微服务化分布式敏捷开发系统架构, ...

    原作者: [db:作者] 来自: 网络 收藏 邀请

    开源软件名称:

    cmdAdmin

    开源软件地址:

    https://gitee.com/cmdshare/cmdAdmin

    开源软件介绍:

    cmdAdmin

    QQ群:951379340

    介绍

    基于SpringBoot+SpringMVC+MybatisPlus分布式敏捷开发系统架构,默认支持SAAS化,努力为中小型企业打造全方位J2EE企业级开发解决方案。

    软件架构

    cmdAdmin是基于Spring Cloud Alibaba体系微服务化分布式敏捷开发系统架构,支持SAAS化,提供整套公共微服务服务模块,其中包含用户管理、资源权限管理等多个模块,作为后端服务的开发脚手架。代码简洁,架构清晰,适合学习和直接项目中使用。 核心技术采用Spring Boot 2.2.7以及Spring Cloud 相关核心组件,采用Nacos注册和配置中心,集成流量卫兵Sentinel,dubbo远程调用,集成Activiti工作流,动态表单+动态工作流,工作流下拉选择代理人,前端采用vue-element-admin组件。

    安装教程

    1. 安装redis jdk maven
    2. 安装Nacos 导入doc下文件 导入数据库sql
    3. 启动网关 admin log workflow 模块

    使用说明

    有问题请加QQ群: 951379340

    1. 超级管理员账号 13455555555/admin123 不参与业务只管理租户和菜单维护(操作哪些菜单租户可见)
    2. 租户管理1 13466666666/123456
    3. 租户管理2 13466666666/123456

    主要功能

    • 用户中心

      • 用户管理:提供用户的相关配置,新增用户后,默认密码为 cmd.c0m
      • 在线用户:统计登录用户
      • 角色管理:对权限与菜单进行分配,可根据部门设置角色的数据权限
      • 部门管理:可配置系统组织架构,树形表格展示
    • 系统中心

      • 菜单管理:已实现菜单动态路由,后端可配置化,支持多级菜单
      • 字典管理:可维护常用一些固定的数据,如:性别等
      • 存储管理: 上传附件记录
      • 表单配置:根据 form-generator 集成的表单拖拽
      • 数据管理: 动态表单的集中数据管理列表
    • 日志中心

      • 日志管理:记录用户操作日志与异常日志,方便开发人员定位排错
      • ELK 日志:未完成
    • 流程中心

      • 流程管理:手绘工作流模型
      • 待办任务:当前人审批任务
      • 请假申请:动态配置,阅读表单配置
      • 财务申请: 动态配置,阅读表单配置

    项目结构

    • cmdAdmin-common 为系统的公共模块,各种工具类,公共配置存在该模块

    • cmdAdmin-gateway 网关层,所有入库经过该服务

    • cmdAdmin-modules 为系统的应用模块

    • cmdAdmin-modules-admin 基础模块

    • cmdAdmin-modules-log 日志模块

    • cmdAdmin-modules-workflow 工作流模块

    • cmdAdmin-rpc 远程调用

    • cmdadmin-template 前端页面

    运行项目

    • 安装 Redis

    • 安装 Nacos

    • 创建 cmdadmin 数据库,导入 db 下的 sql 脚本

    • 打开 nacos,点开配置管理--配置列表 --导入配置 doc 下的 xxx.zip,会出现配置列表

    • 修改 cmdAdmin-modules-admin-dev.yml master 中的数据库配置,slave 是 enabled 是 false,如果需要开启也改一下数据库链接,其他模块类似,其他配置根据需求改动, registry.address 是 nacos 地址

      • 启动 cmdAdmin-gateway cmdAdmin-modules-admin 这 2 个启动就可以登录看基础功能了 日志和工作流根据需要启动
      • 启动 cmdadmin-template 前端 npm install , npm run dev

    输入图片说明输入图片说明输入图片说明输入图片说明输入图片说明输入图片说明输入图片说明输入图片说明输入图片说明输入图片说明输入图片说明

    环境配置

    具体安装问题自行百度

    运行环境准备

    • JDK1.8+
    • Redis
    • MYSQL5.6+
    • Maven3+
    • Nacos1.3+

    开发环境

    • IDEA、Eclipse、vscode
    • 开发插件
    • Lombok:节省时间必备
    • 阿里 JAVA 开发规约插件:P3C
    • JRebel:秒级热更新神器必备

    导入 SQl 文件

    • MySQL 数据库新建数据库,导入 doc 下的 sql 文件

    配置文件导入

    • 启动 nacos 后 导入 doc 下 zip 文件
    • 编辑对应配置文件 比如,数据库配置

    访问测试

    • 账号 cmdadmin/admin123

    开发手册

    当前用户

    获取当前登录用户对象

    OnlineUser user = securityAdmin.currentUser(token);例如:@GetMapping(value = "/menus")public ResponseEntity menus(HttpServletRequest request, @RequestHeader(value = Constants.TOKEN) String token)  {  CmdResponse response = new CmdResponse();  response.setData(loginService.listMenus(token));  return ResponseEntity.ok(response);}@Override	public List<MenuVO> listMenus(String token) {		OnlineUser user = securityAdmin.currentUser(token);		Map<String, Object> param = Maps.newHashMap();		List<MenuVO> vos = baseMapper.getMenus(param);		return vos;	}

    权限控制

    本系统权限控制采用 RBAC 思想。简单地说,一个用户拥有若干角色,每一个角色拥有若干个菜单,菜单中存在菜单权限与按钮权限, 这样,就构造成“用户-角色-菜单” 的授权模型。在这种模型中,用户与角色、角色与菜单之间构成了多对多的关系,如下图

    avatar

    权限控制

    本系统安全框架使用的是 Jwt Token, 访问后端接口需在请求头中携带 token 进行访问,请求头格式如下:

    Authorization: eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJ7XCJjcmVhdGVUaW1lXCI6MTU5ODE3OTc4NDAwMCxcImRlbGV0ZWRcIjp0cnVlLFwiZGVwdElkXCI6XCIwZjY4NjZiZTcwYTJmNjkwZTY3YWQyYjZiNzExMjZiYlwiLFwiZGVwdE5hbWVcIjpcIumZleilv1wiLFwiZW5hYmxlZFwiOnRydWUsXCJpZFwiOlwid3d3XCIsXCJuaWNrTmFtZVwiOlwiY21kYWRtaW5cIixcInBhc3N3b3JkXCI6XCIyMmJiZmM0NmZlNzEwOTlkMTM5ZTJjYWEwOGQ1NWJlN1wiLFwicGhvbmVcIjpcIjEzNDU1NTU1NTU1XCIsXCJzYWx0XCI6XCIxMTFcIixcInVwZGF0ZVRpbWVcIjoxNTk4MTc5Nzg2MDAwLFwidXNlck5hbWVcIjpcImNtZGFkbWluXCJ9IiwianRpIjoiN2UzNzU3ZjUtZmU0MC00NWRhLTk2OTctN2ZmNTk3NGE1Y2RjIn0.zM1UafO-UDVrnmsBTTtQPAThVOddR5cz0gDKvjCAlrSfqj5rw-lU4MQmYFvM4k5NNy6NbRQEw5YER3k19C1ARg

    avatar

    权限注解

    提供 EL 表达式,允许在定义接口访问的方法上面添加注解,来控制访问权限,常用的 EL 如下

    表达式描述
    @CmdAdmin({"user:list"})当前用户是否拥有指定角色。
    @CmdAdmin({"admin","user:list"})多个角色是一个以逗号进行分隔的字符串。如果当前用户拥有指定角色中的任意一个则返回 true。

    下面的接口表示用户拥有 admin、user:add、user:update create 如果方法不加@CmdAdmin 注解,意味着所有用户都需要带上有效的 token 后能访问 create 方法

    @Log("用户新增或编辑")@CmdAdmin({"admin","user:add","user:update"})@PutMappingpublic ResponseEntity<CmdResponse> create(@RequestBody User entity) throws Exception  {  userService.create(entity);  return ResponseEntity.ok(new CmdResponse());}

    由于每个接口都需要给超级管理员放行,而使用 CmdAdmin('admin','user:list') 每次都需要重复的添加 admin 权限

    匿名访问

    在我们使用的时候,有些接口是不需要验证权限的,这个时候就需要我们给接口放行,在网关配置中添加,使用方式如下

    cmd:  filter: #需要进行过滤的白名单    allowPaths:      - /admin/cmd/v1/auth/login      - /admin/cmd/v1/auth/code

    远程调用

    本系统使用的是Dubbo远程调用,当接口对外需要提供访问时候,在当前接口实现上加入dubbo注解

    例如:

    @Service@org.apache.dubbo.config.annotation.Service(version = "1.0.0")public class FwLogServiceImpl

    如果不对外提供访问,只是内部容器调用则只使用spring的 @Service 即可

    自动填充

    原理:

    • 实现元对象处理器接口:com.baomidou.mybatisplus.core.handlers.MetaObjectHandler

    • 注解填充字段 @TableField(.. fill = FieldFill.INSERT) 生成器策略部分也可以配置!

    /**  * 创建时间  */  // 注意!这里需要标记为填充字段@TableField(value = "create_time",fill = FieldFill.INSERT)private Date createTime;
    • 自定义实现类 MyMetaObjectHandler
    /** * 自动注入 * @author cmd * */@Componentpublic class BasicMetaObjectHandler implements MetaObjectHandler {	@Override	public void insertFill(MetaObject metaObject) {		this.fillStrategy(metaObject, "createTime", new Date());		this.fillStrategy(metaObject, "enabled", true);		this.fillStrategy(metaObject, "deleted", true);	}	@Override	public void updateFill(MetaObject metaObject) {			this.fillStrategy(metaObject, "updateTime", new Date());	}}
    • FieldFill类型
    public enum FieldFill {    /**     * 默认不处理     */    DEFAULT,    /**     * 插入填充字段     */    INSERT,    /**     * 更新填充字段     */    UPDATE,    /**     * 插入和更新填充字段     */    INSERT_UPDATE}

    字典翻译

    在后台字典管理中新增字典数据 参考前端代码views\system\menu\index.vue

    使用步骤:

    - import { getDic } from '@/utils/auth'- created() {    this.dicType = getDic('字典编码')  }- formatterType({ cellValue }) {      const item = this.dicType.find(item => item.code === cellValue)      return item ? item.value : ''  }-  <vxe-table-column field="type" title="菜单类型" :formatter="formatterType" />

    异常处理

    我们开发项目的时候,数据在请求过程中发生错误是非常常见的事情。

    如:权限不足、数据唯一异常、数据不能为空异常、义务异常等。 这些异常如果不经过处理会对前端开发人员和使用者造成不便,因此我们就需要统一处理他们。

    代码位置: cmdAdmin-common 工程中com.ninong.ker.common.exception包中处理异常在每个模块 conf 包 LogAspect

    异常封装

    异常实体

        /**    * 错误类    *    * @author cmd    * @date 2020年11月28日 下午11:16:13    */    @Data    public class CmdError {      private Integer status = 400;      @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")      private LocalDateTime timestamp;      private String message;      private CmdError() {        timestamp = LocalDateTime.now();      }      public static CmdError error(String message) {        CmdError apiError = new CmdError();        apiError.setMessage(message);        return apiError;      }      public static CmdError error(Integer status, String message) {        CmdError apiError = new CmdError();        apiError.setStatus(status);        apiError.setMessage(message);        return apiError;      }    }

    自定义异常

    通用异常

    封装了 CmdException,用于处理通用的异常

        /**    * @author cmd    * @date 2020-11-23 统一异常处理    */    @Getter    public class CmdException extends RuntimeException{        /**      *      */      private static final long serialVersionUID = 1L;      private Integer status = BAD_REQUEST.value();        public CmdException(String msg){            super(msg);        }        public CmdException(Integer status,String msg){            super(msg);            this.status = status;        }        public CmdException(BusinessEnum bus){          super(bus.getMsg());          this.status = bus.getStatus();        }    }

    全局异常拦截

    使用全局异常处理器 @RestControllerAdvice 处理请求发送的异常

    • @RestControllerAdvice:默认会扫描指定包中所有@RequestMapping 注解

    • @ExceptionHandler:通过@ExceptionHandler 的 value 属性可过滤拦截的条件

      /\*\*  - 异常处理类  -  - @author cmd  - @date 2020  11  28  下午 11:22:48    \*/  @Slf4j  @RestControllerAdvice  public class GlobalExceptionHandler {      /**      * 处理所有不可知的异常      */      @ExceptionHandler(Throwable.class)      public ResponseEntity<CmdError> handleException(Throwable e) {        // 打印堆栈信息        log.error(ThrowableUtil.getStackTrace(e));        return buildResponseEntity(CmdError.error(e.getMessage()));      }      /**      * 处理自定义异常      */      @ExceptionHandler(value = CmdException.class)      public ResponseEntity<CmdResponse> badRequestException(CmdException e) {        CmdResponse response = new CmdResponse();        response.setCode(e.getStatus());        response.setMessage(e.getMessage());        return ResponseEntity.ok(response);      }      /**        * 接口参数校验不通过异常        *        * @param e        * @return        */        @ExceptionHandler(value = MethodArgumentNotValidException.class)        public ResponseEntity<CmdResponse> methodArgumentNotValidException(MethodArgumentNotValidException e) {            List<FieldError> bindingResult = e.getBindingResult().getFieldErrors();            StringBuilder sb = new StringBuilder();            for (FieldError fieldError : bindingResult) {                sb.append(fieldError.getDefaultMessage()).append(";");            }            CmdResponse response = new CmdResponse();        response.setCode(100);        response.setMessage(sb.toString());            return ResponseEntity.ok(response);        }      /**      * 统一返回      */      private ResponseEntity<CmdError> buildResponseEntity(CmdError CmdError) {        return new ResponseEntity<>(CmdError, HttpStatus.valueOf(CmdError.getStatus()));      }    }

    具体使用

        // 通用异常    throw new CmdException("系统提醒");    // 通用异常,使用自定义状态码    throw new CmdException(402, "系统提醒");

    系统日志

    本系统使用 AOP 方式记录用户操作日志,只需要在 controller 的方法上使用 @Log("") 注解,就可以将用户操作记录到数据库模块具体使用如下:

    @Log("用户删除")@CmdAdmin({"admin","user:delete"})@DeleteMappingpublic ResponseEntity<CmdResponse> delete(@RequestBody String[] ids)  {  userService.delete(ids);  CmdResponse response = new CmdResponse();  response.setMessage(BusinessEnum.DELETE_SUCCESS.getMsg());  return ResponseEntity.ok(response);}

    页面日志中心可以看到 操作日志和异常日志

    输入图片说明输入图片说明输入图片说明输入图片说明输入图片说明输入图片说明输入图片说明输入图片说明输入图片说明输入图片说明


    鲜花

    握手

    雷人

    路过

    鸡蛋
    该文章已有0人参与评论

    请发表评论

    全部评论

    专题导读
    热门推荐
    阅读排行榜

    扫描微信二维码

    查看手机版网站

    随时了解更新最新资讯

    139-2527-9053

    在线客服(服务时间 9:00~18:00)

    在线QQ客服
    地址:深圳市南山区西丽大学城创智工业园
    电邮:jeky_zhao#qq.com
    移动电话:139-2527-9053

    Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap