附上 API 地址:https://open.ys7.com/doc/zh/book/index/user.html

废话不多说直接上代码

/*** @ProjectName: aila* @Package: com.aila.fluorite.constnat* @ClassName: CameraConstnat* @Author: dujiayu* @Description:* @Date: 2022/1/18 11:48* @Version: 1.0*/
public class FluorConstant {/*** APP_KEY*/public static final String APP_KEY = "********************************";/*** SECRET*/public static final String SECRET = "********************************";/*** redis 存储accessToken 键*/public static final String REDIS_FLUOR_ACCESSTOKEN_KEY = "FLUOR_ACCESSTOKEN_KEY";/*** 缓存PC端选中查看过的监控设备序列号*/public static final String REDIS_FLUOR_VIDEO_LIST_KEY = "FLUOR_VIDEO_LIST_KEY";/*** 请求成功*/public static final String REQUEST_SUCCEESS = "200";/*** 重新获取accessToken*/public static final String TOKEN_EXPIRED = "10002";/*** 获取萤石开放平台AccessToken*/public static final String GETACCESSTOKEN_URL = "https://open.ys7.com/api/lapp/token/get";/*** 获取萤石IOT(物联网)AccessToken*/public static final String GETEZACCESSTOKEN_URL = "https://esopen.ys7.com/api/user/component-open/sso/oauth2/getEZAccessToken";/*** 获取用户下的设备列表*/public static final String DEVICE_SELECT_URL = "https://open.ys7.com/api/lapp/device/list";/*** 添加设备*/public static final String DEVICE_ADD_URL = "https://open.ys7.com/api/lapp/device/add";/*** 删除设备*/public static final String DEVICE_DELETE_URL = "https://open.ys7.com/api/lapp/device/delete";/*** 修改设备名称*/public static final String DEVICE_UPDATE_URL = "https://open.ys7.com/api/lapp/device/name/update";/*** 修改通道名称*/public static final String DEVICE_CAMERAUPDATE_URL = "https://open.ys7.com/api/lapp/camera/name/update";/*** 设备抓拍*/public static final String DEVICE_CAPTURE_URL = "https://open.ys7.com/api/lapp/device/capture";/*** 获取单个设备信息*/public static final String DEVICE_INFO_URL = "https://open.ys7.com/api/lapp/device/info";}
/*** @ProjectName: aila* @Package: com.aila.fluorite.common* @ClassName: AuthTool* @Author: dujiayu* @Description: 萤石授权* @Date: 2022/1/18 11:54* @Version: 1.0*/
@Slf4j
@Component
public class FluorAuthTool {@Autowiredprivate RestTemplate restTemplate;@Autowiredprivate RedisCache redisCache;/*** 获取萤石开放平台AccessToken** @param appKey* @param appSecret* @return*/public String getAccessToken(String appKey, String appSecret) throws FluorException {String accessToken = redisCache.getCacheObject(FluorConstant.REDIS_FLUOR_ACCESSTOKEN_KEY);if (StringUtils.isNotEmpty(accessToken)) {return accessToken;}HttpHeaders headers = new HttpHeaders();headers.set("Content-Type", "application/x-www-form-urlencoded");headers.set("Host", "open.ys7.com");log.info("获取萤石AccessToken入参======" + "appKey:" + appKey + " appSecret:" + appSecret);HttpEntity<String> request = new HttpEntity<String>(headers);AccessTokenDTO response = null;try {String url = FluorConstant.GETACCESSTOKEN_URL + "?appKey=" + appKey + "&appSecret=" + appSecret;response = restTemplate.postForObject(url, request, AccessTokenDTO.class);} catch (HttpClientErrorException e) {response = JSONObject.parseObject(e.getResponseBodyAsString(), AccessTokenDTO.class);}log.info("获取萤石AccessToken返回信息======" + JSON.toJSONString(response));if (FluorConstant.REQUEST_SUCCEESS.equals(response.getCode())) {accessToken = response.getData().getString("accessToken");Long expireTime = response.getData().getLong("expireTime");redisCache.setCacheObject(FluorConstant.REDIS_FLUOR_ACCESSTOKEN_KEY, accessToken, expireTime, TimeUnit.MILLISECONDS);} else {throw new FluorException(response.getMsg(), Integer.parseInt(response.getCode()));}return accessToken;}/*** 直接获取token* @param appKey* @param appSecret* @return* @throws FluorException*/public String getDirectAccessToken(String appKey, String appSecret) throws FluorException {String accessToken = "";HttpHeaders headers = new HttpHeaders();headers.set("Content-Type", "application/x-www-form-urlencoded");headers.set("Host", "open.ys7.com");log.info("获取萤石AccessToken入参======" + "appKey:" + appKey + " appSecret:" + appSecret);HttpEntity<String> request = new HttpEntity<String>(headers);AccessTokenDTO response = null;try {String url = FluorConstant.GETACCESSTOKEN_URL + "?appKey=" + appKey + "&appSecret=" + appSecret;response = restTemplate.postForObject(url, request, AccessTokenDTO.class);} catch (HttpClientErrorException e) {response = JSONObject.parseObject(e.getResponseBodyAsString(), AccessTokenDTO.class);}log.info("获取萤石AccessToken返回信息======" + JSON.toJSONString(response));if (FluorConstant.REQUEST_SUCCEESS.equals(response.getCode())) {accessToken = response.getData().getString("accessToken");Long expireTime = response.getData().getLong("expireTime");redisCache.setCacheObject(FluorConstant.REDIS_FLUOR_ACCESSTOKEN_KEY, accessToken, expireTime, TimeUnit.MILLISECONDS);} else {throw new FluorException(response.getMsg(), Integer.parseInt(response.getCode()));}return accessToken;}/*** 获取萤石IOT AccessToken(非物联网用不上)** @param accessToken* @return*/public String getEZAccessToken(String accessToken) {JSONObject object = new JSONObject();object.put("accessToken", accessToken);HttpHeaders headers = new HttpHeaders();headers.set("Content-Type", "application/json");log.info("获取萤石IOT AccessToken======" + object.toJSONString());HttpEntity<String> request = new HttpEntity<String>(object.toJSONString(),headers);JSONObject response = null;try {response = restTemplate.postForObject(FluorConstant.GETEZACCESSTOKEN_URL,request, JSONObject.class);} catch (HttpClientErrorException e) {response = JSONObject.parseObject(e.getResponseBodyAsString());}return response.toJSONString();}}
/*** @ProjectName: aila* @Package: com.aila.fluorite.camera* @ClassName: CameraTool* @Author: dujiayu* @Description: 萤石管理相关接口* @Date: 2022/1/18 11:47* @Version: 1.0*/
@Slf4j
@Component
public class FluorDeviceManageTool {@Autowiredprivate RestTemplate restTemplate;@Autowiredprivate FluorAuthTool fluorAuthTool;/*** 生成公用的请求头** @return*/private HttpEntity<String> getHttpEntity() {HttpHeaders headers = new HttpHeaders();headers.set("Content-Type", "application/x-www-form-urlencoded");headers.set("Host", "open.ys7.com");HttpEntity<String> request = new HttpEntity<String>(headers);return request;}/*** 添加设备** @param accessToken  授权过程获取的access_token* @param deviceSerial 设备序列号,存在英文字母的设备序列号,字母需为大写* @param validateCode 设备验证码* @return* @throws FluorException*/public boolean addDecvice(String accessToken, String deviceSerial, String validateCode) throws FluorException {log.info("添加设备入参======" + "accessToken:" + accessToken + " deviceSerial:" + deviceSerial + "validateCode:" + validateCode);HttpEntity<String> request = this.getHttpEntity();FluorResponseDTO response = null;try {String url = FluorConstant.DEVICE_ADD_URL + "?accessToken=" + accessToken + "&deviceSerial=" + deviceSerial + "&validateCode=" + validateCode;response = restTemplate.postForObject(url, request, FluorResponseDTO.class);} catch (HttpClientErrorException e) {response = JSONObject.parseObject(e.getResponseBodyAsString(), FluorResponseDTO.class);}log.info("添加设备返回信息======" + JSON.toJSONString(response));if (FluorConstant.TOKEN_EXPIRED.equals(response.getCode())) {accessToken = fluorAuthTool.getDirectAccessToken(FluorConstant.APP_KEY, FluorConstant.SECRET);return addDecvice(accessToken, deviceSerial, validateCode);}if (!FluorConstant.REQUEST_SUCCEESS.equals(response.getCode())) {throw new FluorException(response.getMsg(), Integer.parseInt(response.getCode()));}return true;}/*** 删除设备** @param accessToken  授权过程获取的access_token* @param deviceSerial 设备序列号,存在英文字母的设备序列号,字母需为大写* @return* @throws FluorException*/public boolean deleteDecvice(String accessToken, String deviceSerial) throws FluorException {log.info("删除设备入参======" + "accessToken:" + accessToken + " deviceSerial:" + deviceSerial);HttpEntity<String> request = this.getHttpEntity();FluorResponseDTO response = null;try {String url = FluorConstant.DEVICE_DELETE_URL + "?accessToken=" + accessToken + "&deviceSerial=" + deviceSerial;response = restTemplate.postForObject(url, request, FluorResponseDTO.class);} catch (HttpClientErrorException e) {response = JSONObject.parseObject(e.getResponseBodyAsString(), FluorResponseDTO.class);}log.info("删除设备返回信息======" + JSON.toJSONString(response));if (FluorConstant.TOKEN_EXPIRED.equals(response.getCode())) {accessToken = fluorAuthTool.getDirectAccessToken(FluorConstant.APP_KEY, FluorConstant.SECRET);return deleteDecvice(accessToken, deviceSerial);}if (!FluorConstant.REQUEST_SUCCEESS.equals(response.getCode())) {throw new FluorException(response.getMsg(), Integer.parseInt(response.getCode()));}return true;}/*** 修改设备名称** @param accessToken  授权过程获取的access_token* @param deviceSerial 设备序列号,存在英文字母的设备序列号,字母需为大写* @param deviceName   设备名称,长度不大于50字节,不能包含特殊字符* @return* @throws FluorException*/public boolean updateDecvice(String accessToken, String deviceSerial, String deviceName) throws FluorException {log.info("修改设备名称入参======" + "accessToken:" + accessToken + " deviceSerial:" + deviceSerial + "deviceName:" + deviceName);HttpEntity<String> request = this.getHttpEntity();FluorResponseDTO response = null;try {String url = FluorConstant.DEVICE_UPDATE_URL + "?accessToken=" + accessToken + "&deviceSerial=" + deviceSerial + "&deviceName=" + deviceName;response = restTemplate.postForObject(url, request, FluorResponseDTO.class);} catch (HttpClientErrorException e) {response = JSONObject.parseObject(e.getResponseBodyAsString(), FluorResponseDTO.class);}log.info("修改设备名称返回信息======" + JSON.toJSONString(response));if (FluorConstant.TOKEN_EXPIRED.equals(response.getCode())) {accessToken = fluorAuthTool.getDirectAccessToken(FluorConstant.APP_KEY, FluorConstant.SECRET);return updateDecvice(accessToken, deviceSerial, deviceName);}if (!FluorConstant.REQUEST_SUCCEESS.equals(response.getCode())) {throw new FluorException(response.getMsg(), Integer.parseInt(response.getCode()));}return true;}/*** 设备抓拍图片* 设备抓图能力有限,请勿频繁调用,建议每个摄像头调用的间隔4s以上。* 抓拍后的图片路径,图片保存有效期为2小时** @param accessToken  授权过程获取的access_token* @param deviceSerial 设备序列号,存在英文字母的设备序列号,字母需为大写* @param channelNo    通道号,IPC设备填写1* @return* @throws FluorException*/public FluorCaptureDeviceDTO captureDevice(String accessToken, String deviceSerial, Integer channelNo) throws FluorException {log.info("设备抓拍图片入参======" + "accessToken:" + accessToken + " deviceSerial:" + deviceSerial + "channelNo:" + channelNo);HttpEntity<String> request = this.getHttpEntity();FluorResponseDTO response = null;try {String url = FluorConstant.DEVICE_CAPTURE_URL + "?accessToken=" + accessToken + "&deviceSerial=" + deviceSerial + "&channelNo=" + channelNo;response = restTemplate.postForObject(url, request, FluorResponseDTO.class);} catch (HttpClientErrorException e) {response = JSONObject.parseObject(e.getResponseBodyAsString(), FluorResponseDTO.class);}log.info("设备抓拍图片返回信息======" + JSON.toJSONString(response));if (!FluorConstant.REQUEST_SUCCEESS.equals(response.getCode())) {throw new FluorException(response.getMsg(), Integer.parseInt(response.getCode()));}String jsonData = response.getData().toJSONString();FluorCaptureDeviceDTO data = JSONObject.parseObject(jsonData,FluorCaptureDeviceDTO.class);return data;}/*** 修改通道名称** @param accessToken  授权过程获取的access_token* @param deviceSerial 设备序列号,存在英文字母的设备序列号,字母需为大写* @param name         通道名称,长度不大于50字节,不能包含特殊字符* @param channelNo    非必选参数,不为空表示修改指定通道名称,为空表示修改通道1名称* @return* @throws FluorException*/public boolean updatePassageName(String accessToken, String deviceSerial, String name, Integer channelNo) throws FluorException {log.info("修改通道名称入参======" + "accessToken:" + accessToken + " deviceSerial:" + deviceSerial + "name:" + name+ "channelNo:" + channelNo);HttpEntity<String> request = this.getHttpEntity();FluorResponseDTO response = null;try {String url = FluorConstant.DEVICE_CAMERAUPDATE_URL + "?accessToken=" + accessToken + "&deviceSerial=" + deviceSerial + "&name=" + name+ "&channelNo=" + channelNo;response = restTemplate.postForObject(url, request, FluorResponseDTO.class);} catch (HttpClientErrorException e) {response = JSONObject.parseObject(e.getResponseBodyAsString(), FluorResponseDTO.class);}log.info("修改通道名称返回信息======" + JSON.toJSONString(response));if (!FluorConstant.REQUEST_SUCCEESS.equals(response.getCode())) {throw new FluorException(response.getMsg(), Integer.parseInt(response.getCode()));}return true;}}
/*** @ProjectName: aila* @Package: com.aila.fluor.device* @ClassName: FluorDeviceQueryTool* @Author: dujiayu* @Description: 萤石查询相关接口* @Date: 2022/1/19 15:45* @Version: 1.0*/
@Slf4j
@Component
public class FluorDeviceQueryTool {@Autowiredprivate RestTemplate restTemplate;@Autowiredprivate FluorAuthTool fluorAuthTool;/*** 生成公用的请求头** @return*/private HttpEntity<String> getHttpEntity() {HttpHeaders headers = new HttpHeaders();headers.set("Content-Type", "application/x-www-form-urlencoded");headers.set("Host", "open.ys7.com");HttpEntity<String> request = new HttpEntity<String>(headers);return request;}/*** 获取设备列表** @param accessToken 授权过程获取的access_token* @return* @throws FluorException*/public DeviceListDTO getDeviceList(String accessToken) throws FluorException {return this.getDeviceList(accessToken, null, null);}/*** 获取设备列表** @param accessToken 授权过程获取的access_token* @param pageStart   分页起始页,从0开始* @param pageSize    分页大小,默认为10,最大为50* @return* @throws FluorException*/public DeviceListDTO getDeviceList(String accessToken, Integer pageStart, Integer pageSize) throws FluorException {pageStart = null == pageStart ? 0 : pageStart;pageSize = null == pageSize ? 10 : pageSize;HttpEntity<String> request = this.getHttpEntity();log.info("获取设备列表入参======" + "accessToken:" + accessToken + " pageStart:" + pageStart + "pageSize:" + pageSize);DeviceListDTO response = null;try {String url = FluorConstant.DEVICE_SELECT_URL + "?accessToken=" + accessToken + "&pageStart=" + pageStart + "&pageSize=" + pageSize;response = restTemplate.postForObject(url, request, DeviceListDTO.class);} catch (HttpClientErrorException e) {response = JSONObject.parseObject(e.getResponseBodyAsString(), DeviceListDTO.class);}log.info("获取设备列表返回信息======" + JSON.toJSONString(response));if (FluorConstant.TOKEN_EXPIRED.equals(response.getCode())) {accessToken = fluorAuthTool.getDirectAccessToken(FluorConstant.APP_KEY, FluorConstant.SECRET);return getDeviceList(accessToken, pageStart, pageSize);}if (!FluorConstant.REQUEST_SUCCEESS.equals(response.getCode())) {throw new FluorException(response.getMsg(), Integer.parseInt(response.getCode()));}return response;}/*** 获取单个设备信息** @param accessToken  授权过程获取的access_token* @param deviceSerial 设备序列号,存在英文字母的设备序列号,字母需为大写*/public DeviceInfoResDTO getDeviceInfo(String accessToken, String deviceSerial) throws FluorException {HttpEntity<String> request = this.getHttpEntity();log.info("获取单个设备信息入参======" + "accessToken:" + accessToken + " deviceSerial:" + deviceSerial);FluorResponseDTO response = null;try {String url = FluorConstant.DEVICE_INFO_URL + "?accessToken=" + accessToken + "&deviceSerial=" + deviceSerial;response = restTemplate.postForObject(url, request, FluorResponseDTO.class);} catch (HttpClientErrorException e) {response = JSONObject.parseObject(e.getResponseBodyAsString(), FluorResponseDTO.class);}log.info("获取单个设备信息返回信息======" + JSON.toJSONString(response));if (FluorConstant.TOKEN_EXPIRED.equals(response.getCode())) {accessToken = fluorAuthTool.getDirectAccessToken(FluorConstant.APP_KEY, FluorConstant.SECRET);return getDeviceInfo(accessToken, deviceSerial);}if (!FluorConstant.REQUEST_SUCCEESS.equals(response.getCode())) {throw new FluorException(response.getMsg(), Integer.parseInt(response.getCode()));}String jsonData = response.getData().toJSONString();DeviceInfoResDTO data = JSONObject.parseObject(jsonData, DeviceInfoResDTO.class);return data;}//TODO  获取摄像头列表//TODO   获取设备状态信息
}
/*** @ProjectName: aila* @Package: com.aila.fluor.dto* @ClassName: AccessTokenDTO* @Author: dujiayu* @Description: AccessToken返回参数* @Date: 2022/1/18 13:57* @Version: 1.0*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class AccessTokenDTO {private JSONObject data;private String code;private String msg;
}
/*** @ProjectName: aila* @Package: com.aila.fluor.dto* @ClassName: DeviceInfoResDTO* @Author: dujiayu* @Description: 设备信息详情返回参数* @Date: 2022/1/19 16:23* @Version: 1.0*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class DeviceInfoResDTO {/*** 设备序列号*/private String deviceSerial;/*** 设备名称*/private String deviceName;/*** 设备型号,如CS-C2S-21WPFR-WX*/private String model;/*** 在线状态:0-不在线,1-在线*/private Integer status;/*** 具有防护能力的设备布撤防状态:0-睡眠,8-在家,16-外出,普通IPC布撤防状态:0-撤防,1-布防*/private Integer defence;/*** 是否加密:0-不加密,1-加密*/private Integer isEncrypt;/*** 告警声音模式:0-短叫,1-长叫,2-静音*/private Integer alarmSoundMode;/*** 设备下线是否通知:0-不通知 1-通知*/private Integer offlineNotify;/*** 设备大类*/private String category;/*** 网络类型,如有线连接wire*/private String netType;/*** 信号强度(%)*/private String signal;
}
/*** @ProjectName: aila* @Package: com.aila.fluor.dto* @ClassName: DeviceListDTO* @Author: dujiayu* @Description: 获取设备列表* @Date: 2022/1/19 10:21* @Version: 1.0*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class DeviceListDTO {/*** 分页信息对象*/private Page page;/*** 设备数据列表*/private List<DeviceListItemDTO> data;/*** 状态码*/private String code;/*** 状态信息*/private String msg;
}
/*** @ProjectName: aila* @Package: com.aila.fluor.dto* @ClassName: DeviceListItem* @Author: dujiayu* @Description: 设备列表子项数据* @Date: 2022/1/19 10:28* @Version: 1.0*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class DeviceListItemDTO {/*** 设备序列号,存在英文字母的设备序列号,字母需为大写*/private String deviceSerial;/*** 设备名称*/private String deviceName;/*** 设备类型*/private String deviceType;/*** 在线状态:0-不在线,1-在线*/private Integer status;/*** 具有防护能力的设备布撤防状态:0-睡眠,8-在家,16-外出,普通IPC布撤防状态:0-撤防,1-布防*/private Integer defence;/*** 设备版本号*/private String deviceVersion;
}
/*** @ProjectName: aila* @Package: com.aila.fluor.dto* @ClassName: FluorCaptureDeviceDTO* @Author: dujiayu* @Description: 设备抓拍* @Date: 2022/1/19 14:53* @Version: 1.0*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class FluorCaptureDeviceDTO {/*** 图片地址*/private String picUrl;}
/*** @ProjectName: aila* @Package: com.aila.fluor.dto* @ClassName: FluorResponseDTO* @Author: dujiayu* @Description: 萤石返回基本参数* @Date: 2022/1/19 13:52* @Version: 1.0*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class FluorResponseDTO {/*** 返回码*/private String code;/*** 返回消息*/private String msg;/*** 数据对象*/private JSONObject data;}
/*** @ProjectName: aila* @Package: com.aila.fluor.dto* @ClassName: Page* @Author: dujiayu* @Description: 分页数据* @Date: 2022/1/19 10:22* @Version: 1.0*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Page {/*** 总数*/private Integer total;/*** 当前页*/private Integer page;/*** 分页大小*/private Integer size;
}
/*** @ProjectName: aila* @Package: com.aila.fluor.exception* @ClassName: FluorException* @Author: dujiayu* @Description: 萤石抛出异常* @Date: 2022/1/19 10:51* @Version: 1.0*/
public class FluorException extends Exception {private static final long serialVersionUID = 1L;private Integer code;private final String message;public FluorException(String message) {this.message = message;}public FluorException(String message, Integer code) {this.message = message;this.code = code;}public FluorException(String message, Throwable e) {super(message, e);this.message = message;}@Overridepublic String getMessage() {return message;}public Integer getCode() {return code;}
}

springboot 调用萤石Saas平台相关推荐

  1. 基于SpringBoot+Mybatis的SaaS平台搭建

    SaaS平台是什么         英语Software-as-a-Service ,就是提供软件服务的平台.基于JavaWeb的思想,可以在线上部署一套程序,根据权限将租户逻辑上分离,让每个租户具有 ...

  2. 基于SpringBoot+Mybatis开发的前后端ERP系统Saas平台

    源码介绍 基于SpringBoot+Mybatis开发的前后端ERP系统Saas平台 ,专注于中小微企业的ERP软件.进销存系统,是一套基于SpringBoot2.2.0, Mybatis, JWT, ...

  3. 从零开始搭建公司大型SaaS 平台架构技术栈,这套架构绝了!

      大家好,我是宝哥! 当我们去搜索"架构",可以得到很多的架构图片,比如组织架构.业务架构.数据架构.技术架构.安全架构.产品架构.部署架构等. 什么是架构,通常大家说架构一般指 ...

  4. paas平台、saas平台争奇斗艳?PaaS化的低代码平台才是最终趋势

    编者按:本文介绍PaaS/SaaS之间的区别.通过比较分析PaaS平台的优势,并介绍国内首个中文PaaS开发平台如何为用户排忧解难,提高用户体验. PaaS/SaaS的区别 近年来低代码概念大火,国内 ...

  5. Spring Boot构建多租户SaaS平台核心技术指南

    点击上方蓝色"程序猿DD",选择"设为星标" 回复"资源"获取独家整理的学习资料! 作者 | 树下魅狐 来源 | oschina.net/r ...

  6. Spring Boot 构建多租户 SaaS 平台核心技术指南

    1. 概述 笔者从2014年开始接触SaaS(Software as a Service),即多租户(或多承租)软件应用平台:并一直从事相关领域的架构设计及研发工作.机缘巧合,在笔者本科毕业设计时完成 ...

  7. 万博智云上云 单机软件升级多并发SaaS平台

    云栖号案例库:[点击查看更多上云案例] 不知道怎么上云?看云栖号案例库,了解不同行业不同发展阶段的上云方案,助力你上云决策! 业务痛点 自2016年开发迁移工具主要面向私有云环境,但是随着公有云用户越 ...

  8. 权限系统设计学习总结(4)—— SaaS 平台多租户模式下权限设计

    一.RBAC模型 1.1.概念 权限设计最常见的就是基于 RBAC 模型.而 RBAC 模型又有 RBAC0.RBAC1.RBAC2.RBAC3 等几种常见的模式.RBAC(Role-Based Ac ...

  9. SaaS平台产品架构设计

    当我们去搜索"架构",可以得到很多的架构图片,比如组织架构.业务架构.数据架构.技术架构.安全架构.产品架构.部署架构等. 什么是架构,通常大家说架构一般指软件架构,架构是指软件的 ...

  10. springboot+调用支付宝第三方接口(沙箱环境)

    springboot+调用支付宝第三方接口(沙箱环境) 大神勿喷!! 网址:https://developers.alipay.com/platform/developerIndex.htm 沙箱环境 ...

最新文章

  1. 皮猜按下谷歌招聘暂停键,疫情之下,「紧日子」来了
  2. 水系影像分析_“天眼”助力 甘肃运用卫星影像精准研判灾情
  3. 给定2个字符串,如何计算变化(插入、删除、替换)?【levenshtein distance 算法】
  4. linux系统编程之使用C++(1)-打开关闭文件
  5. mvc4 利用filters特性来 实现自己的权限验证 之二
  6. oracle中dbms_如何在DBMS中找到关系的最高范式?
  7. 最优化学习笔记(十五)——拟牛顿法(1)
  8. 轻芒联合创始人、CTO 范怀宇亲述《使用小程序做交互的技巧》
  9. 用GDB调试程序(10)──查看运行时数据(1)-转
  10. 头衔的权威暗示影响力
  11. Bootstrap优秀模板-INSPINIA.2.9.2
  12. 吉特仓库管理系统- 斑马打印机 ZPL语言的腐朽和神奇
  13. 时差怎么理解_懂的人自然懂,不懂的人再多解释也有时差
  14. [BZOJ1984]月下“毛景树”(树链剖分)
  15. gom列表自动选择服务器,传奇服务器-传奇服务器端 GOM GEE(必看知识)
  16. Nginx配置及常用配置
  17. MATLAB虫害检测农业应用设计
  18. 校企共育数字化时代物联网技术应用人才基地建设方案
  19. 期末离散数学前三章关键知识点整理——应试。
  20. Encoder编码器、Decoder解码器

热门文章

  1. 测试过程之UT-IT-ST的区别
  2. PSV 2000 3.68降级3.60固化教程
  3. 企业微信管理员可以看到打卡位置吗
  4. DTCC大会归来感想
  5. 十大著名黑客-----凯文-米特尼克
  6. 第一届FME模板开发者大赛
  7. Acer 4750 安装黑苹果_黑苹果安装 你要知道的那些坑
  8. Photoshop学习笔记
  9. 磁盘精灵 4.5 版本
  10. 三个百分数相乘计算机,我的公考笔记:资料分析的三个速算技巧