共计 2439 个字符,预计需要花费 7 分钟才能阅读完成。
1. 字典表(sys_dict)
作用:用于存放多组值不变的基础数据, 只对系统提供查询功能.
*记录的新增、更新、删除都是通过手动进行操作.
*其中 dict_code 为 dict_title 的编码, 相同 dict_title 的记录为同一组基础数据, 每组基础数据下又有多对 dict_value 与 dict_name.
*每组基础数据可以根据实际的业务需求在程序中创建对应的枚举类(value 和 name 属性).
2. 系统配置表(sys_config)
作用:用于存放系统的配置项, 某些业务逻辑需要根据配置项的值来做出相应的处理.
*记录的新增、删除都是通过手动进行操作.
*在系统配置页面中查询配置项并修改配置项的值.
*在某些业务逻辑中需根据模块 ID 和配置代码查询配置项, 根据不同的配置值做出相应的处理.
*可以创建一个枚举类存放模块 ID, 创建常量类存放 config_code.
3. 地域表(sys_area)
作用:用于存放省市区地域数据, 一般只对系统提供查询功能.
*记录的新增、更新、删除都是通过手动进行操作.
*在 页面中通过多级联动选择地域, 调用根据父编码查询记录的 API(首次查询父编码为 0 的记录表示顶层节点)
4.RBAC
用户表(sys_user)
角色表(sys_role)
菜单表(sys_menu)
*若使用 Shiro 安全管理框架, 则在实现 Realm 的 doGetAuthorizationInfo()方法中, 通过用户的 Principal 查询用户拥有的 Role 以及 Permission 各存放到 Set 集合中返回给 SecurityManager, 在 Controller 中通过注解或 XML 配置的方式设置资源必须拥有指定的 role 或 permission 时才能访问.
*登录接口校验成功后需要返回用户的个人信息以及拥有的角色给前端进行页面元素的控制.
用户角色关联表(sys_user_role)
*其中 user_id 和 role_id 为联合主键, 可以保证一个用户不会存在相同的角色.
*当在页面查看用户拥有的角色时, 调用后台 API 通过用户 ID 查询用户拥有的角色以及系统所有的角色, 后台进行双重遍历, 当用户拥有目标角色时 flag 设置为 ture, 供前端 checkbox 渲染.
*当在页面为用户新增或移除角色时, 调用后台 API 传递选中的角色实体, 后台可以删除用户拥有的所有角色再进行批量入库或者相对当前用户判断新增和删除了哪些角色再进行分步 SQL 操作.
角色菜单关联表(sys_role_menu)
*其中 role_id 和 menu_id 为联合主键, 可以保证一个角色不会存在相同的权限.
*当在页面查看角色拥有的权限时, 调用后台 API 通过角色 ID 查询角色拥有的权限以及系统所有的权限, 后台进行双重遍历, 当角色拥有目标权限时 flag 设置为 ture, 供前端 checkbox 渲染.
*当在页面为角色新增或移除权限时, 调用后台 API 传递选中的权限实体, 后台可以删除角色拥有的所有权限再进行批量入库或者相对当前角色判断新增和删除了哪些权限再进行分步 SQL 操作.
5. 机构表(sys_office)
作用:用于存放公司的组织架构关系(适用于集团)
*新增记录时前端需要传递新增的机构信息以及父机构 ID, 后台将会根据父 ID 查询机构实体, 获取其所有的父 ID, 构造本次新增机构实体的所有父 ID, 最终进行入库操作.
*删除记录时前端需要传递要删除的机构 ID, 后台将删除本机构及其所有子机构, 只要所有的父 ID 中包含要删除的机构 ID 则也应被删除.
6. 系统操作日志(sys_log)
作用:用于记录用户在系统中的操作行为.
*系统操作日志功能一般会进行日志的输出以及数据的入库.
*系统操作日志表由于数据量众多, 因此需要在查询参数中添加索引.
*利用拦截器的 afterCompletion 方法实现系统操作日志(在请求被响应之后调用)
1. 通过 afterCompletion 方法的 handler 参数获取访问控制层对应方法的 Method 对象, 通过反射获取标注在控制层方法的 @RequirePermissions 注解中的 value 属性, 再通过此属性从菜单表中获取对应的操作名称.
2. 通过 afterCompletion 方法的 HttpServletRequest 参数的 getRemoteAddress()方法获取客户端远程 IP、getHeader()方法获取 HTTP 请求头中的 user-agent 参数、getRequestURI()方法获取请求 URL、getParameterMap()方法获取请求体中的参数、getMethod()方法获取 HTTP 请求方法.
3. 通过判断 afterCompletion 方法的 Exception 参数是否为空来确定此处请求是否成功, 若 Exception 参数不为空则获取异常中的信息保存进库中.
*afterCompletion 方法中应使用异步的方式新建一个线程进行日志的记录.
*使用拦截器实现系统操作日志功能的好处是可以通过 HttpServletReqeust 实体获取更多关于客户端的信息, 缺点是不易扩展, 只能通过键值对的形式获取请求参数.
*利用 Spring AOP 的环绕通知实现系统操作日志.
1. 切入点为 Service 层中的业务方法。
2. 当 Service 层中的方法执行前将会进入切面中的环绕通知方法, 可以通过 ProceedingJoinPoint 的 getArgs()方法获取连接点的参数集, 在此时可以根据记录 ID 查询数据库中变更前的记录实体。
3. 执行 ProceedingJoinPoint 的 process()方法调用连接点, 方法的返回值为连接点的返回值, 若执行成功且无异常则可以判断变更前和变更后哪些属性发生了变化, 最后进行入库操作。
*可以直接在连接点的前后简单的把入参和返回值进行打印。
*使用 AOP 实现日志的好处是不影响原有的代码结构、可以很容易的得到方法执行的参数和返回值、易扩展,可以配置不同的切入点来做不同的逻辑处理, 缺点是不能获取更多关于客户端的信息。
: