Merge pull request #19 from hiparker/development

v 2.0
pull/33/head
Parker 3 years ago committed by GitHub
commit 786a530b8b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -186,7 +186,7 @@
same "printed page" as the copyright notice for easier same "printed page" as the copyright notice for easier
identification within third-party archives. identification within third-party archives.
Copyright [yyyy] [name of copyright owner] Copyright [2020] [OPSLI 快速开发平台 https://www.opsli.com]
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.

@ -1,4 +1,4 @@
# OPSLI 快速开发平台 (已开源) # OPSLI 快速开发平台 (v2.0)
<div align="center"> <div align="center">
<img width="500" src="https://gitee.com/hiparker/opsli-ui/raw/master/repository-images/logo.png"/> <img width="500" src="https://gitee.com/hiparker/opsli-ui/raw/master/repository-images/logo.png"/>
<br/> <br/> <br/> <br/>
@ -31,15 +31,15 @@
> 单机版 > 单机版
| 名称 | 版本号 | | 名称 | 版本号 | | 名称 | 版本号 | | 名称 | 版本号 |
| ---------------- | ------- | ---- | -------------- | -------------- | | ---------------- |---| ---- | -------------- |--------------|
| jdk版本 | ^1.8 | | springboot版本 | ^2.3.3.RELEASE | | jdk版本 | 1.8 | | springboot版本 | 2.5.6 |
| mybatis-plus版本 | ^3.4.0 | | pagehelper版本 | ^1.1.0 | | mybatis-plus版本 | 3.5.2 | | pagehelper版本 | 1.3.0 |
| druid版本 | ^1.1.17 | | dynamic版本 | ^2.5.4 | | druid版本 | 1.1.17 | | dynamic版本 | 2.5.4 |
| shiro-redis版本 | ^3.3.1 | | jwt版本 | ^3.10.3 | | fastjson版本 | 1.2.83 | | transmittable版本 | 2.12.5 |
| ehcache版本 | ^3.9.0 | | easyexcel版本 | ^2.2.6 | | ehcache版本 | 3.9.0 | | easyexcel版本 | 2.2.6 |
| kaptcha版本 | ^0.0.9 | | guava版本 | ^29.0-jre | | captcha版本 | 1.6.2 | | guava版本 | 30.0-android |
| enjoy版本 | ^4.9.03 | | hutool版本 | ^5.7.14 | | enjoy版本 | 4.9.06 | | hutool版本 | 5.7.14 |
## 在线演示 ## 在线演示
@ -100,8 +100,6 @@
│ │ │ │ │ ├── exception 公共模块 - 异常类 │ │ │ │ │ ├── exception 公共模块 - 异常类
│ │ │ │ │ ├── msg 公共模块 - 信息 │ │ │ │ │ ├── msg 公共模块 - 信息
│ │ │ │ │ ├── thread 公共模块 - 线程相关 │ │ │ │ │ ├── thread 公共模块 - 线程相关
│ │ │ │ │ │ ├── refuse 拒绝策略线程池
│ │ │ │ │ │ └── wait 等待线程池
│ │ │ │ │ └── utils 公共模块 - 工具类 │ │ │ │ │ └── utils 公共模块 - 工具类
│ │ │ │ │ │ │ │ │ │
│ └── opsli-core 基础 - 核心模块 │ └── opsli-core 基础 - 核心模块
@ -110,27 +108,33 @@
│ │ │ ├── java │ │ │ ├── java
│ │ │ │ └── org │ │ │ │ └── org
│ │ │ │ └── opsli │ │ │ │ └── opsli
│ │ │ │ └── core │ │ │ │ ├── core 核心
│ │ │ │ ├── api 核心模块 - API接口相关登录Token缓存 │ │ │ │ │ ├── api 核心模块 - API接口相关登录Token缓存
│ │ │ │ ├── autoconfigure 核心模块 - 自动配置 │ │ │ │ │ ├── autoconfigure 核心模块 - 自动配置
│ │ │ │ │ ├── conf 自动装配 │ │ │ │ │ │ ├── conf 自动装配
│ │ │ │ │ └── properties 配置文件注入 │ │ │ │ │ │ └── properties 配置文件注入
│ │ │ │ ├── base 核心模块 - 基础类 Entity Service │ │ │ │ │ ├── base 核心模块 - 基础类 Entity Service
│ │ │ │ ├── cache 核心模块 - 缓存处理 │ │ │ │ │ ├── cache 核心模块 - 缓存处理
│ │ │ │ ├── filters 核心模块 - 过滤器 │ │ │ │ │ ├── eventbus 核心模块 - 消息事件
│ │ │ │ │ ├── aspect AOP切面 │ │ │ │ │ ├── filters 核心模块 - 过滤器
│ │ │ │ │ └── interceptor Spring拦截器 │ │ │ │ │ │ ├── aspect AOP切面
│ │ │ │ ├── conf 核心模块 - 全局统一自动装配 │ │ │ │ │ │ └── interceptor Spring拦截器
│ │ │ │ ├── general 核心模块 - 打印信息 │ │ │ │ │ ├── general 核心模块 - 其他处理器
│ │ │ │ ├── handler 核心模块 - 异常拦截处理 │ │ │ │ │ ├── handler 核心模块 - 异常拦截处理
│ │ │ │ ├── listener 核心模块 - 系统监听器 │ │ │ │ │ ├── holder 核心模块 - 上下文数据
│ │ │ │ ├── msg 核心模块 - 信息 │ │ │ │ │ ├── listener 核心模块 - 系统监听器
│ │ │ │ ├── persistence 核心模块 - 查询条件构造器 │ │ │ │ │ ├── log 核心模块 - 日志处理
│ │ │ │ │ └── querybuilder │ │ │ │ │ ├── msg 核心模块 - 信息
│ │ │ │ │ └── chain 核心模块 - 查询条件构造器 - 责任链(例: 租户处理) │ │ │ │ │ ├── options 核心模块 - 系统参数
│ │ │ │ ├── security 核心模块 - 权限验证 │ │ │ │ │ ├── persistence 核心模块 - 查询条件构造器
│ │ │ │ │ └── shiro Shiro权限校验 │ │ │ │ │ │ └── querybuilder
│ │ │ │ └── utils 核心模块 - 工具类 │ │ │ │ │ │ └── chain 核心模块 - 查询条件构造器 - 责任链(例: 租户处理)
│ │ │ │ │ ├── security 核心模块 - 权限验证
│ │ │ │ │ │ ├── filter 拦截器
│ │ │ │ │ │ └── service 获取用户的Service
│ │ │ │ │ └── utils 核心模块 - 工具类
│ │ │ │ └── pligins 插件
│ │ │ │ └── oss 插件模块 - OSS文件存储
│ │ │ │ │ │ │ │
├── opsli-modulars 业务 ├── opsli-modulars 业务
│ ├── opsli-modulars-generator 代码生成器 │ ├── opsli-modulars-generator 代码生成器
@ -166,6 +170,11 @@
│ │ │ │ │ ├── area 系统模块 - 地域 │ │ │ │ │ ├── area 系统模块 - 地域
│ │ │ │ │ ├── dict 系统模块 - 字典 │ │ │ │ │ ├── dict 系统模块 - 字典
│ │ │ │ │ ├── login 系统模块 - 登录 │ │ │ │ │ ├── login 系统模块 - 登录
│ │ │ │ │ │ ├── dto 系统模块 - 登录 - DTO
│ │ │ │ │ │ ├── event 系统模块 - 登录 - 消息事件
│ │ │ │ │ │ ├── handler 系统模块 - 登录 - 前置、成功、失败处理器
│ │ │ │ │ │ ├── vo 系统模块 - 登录 - 返回数据
│ │ │ │ │ │ └──web 系统模块 - 登录 - 接口控制器
│ │ │ │ │ ├── logs 系统模块 - 日志 │ │ │ │ │ ├── logs 系统模块 - 日志
│ │ │ │ │ ├── menu 系统模块 - 菜单 │ │ │ │ │ ├── menu 系统模块 - 菜单
│ │ │ │ │ ├── monitor 系统模块 - 系统监控 │ │ │ │ │ ├── monitor 系统模块 - 系统监控
@ -176,11 +185,29 @@
│ │ │ │ │ └── user 系统模块 - 用户 │ │ │ │ │ └── user 系统模块 - 用户
│ │ │ │ │ │ │ │ │ │
│ │ │ │ └── tools 工具包 │ │ │ │ └── tools 工具包
│ │ │ │ ├── searchhis 工具包 - 搜索历史 │ │ │ │ ├── api 工具包 - 版本控制API测试类
│ │ │ │ └── email 工具包 - 邮件包 │ │ │ │ ├── common 工具包 - 公共服务
│ │ │ │ ├── email 工具包 - 邮件包
│ │ │ │ ├── oss 工具包 - 文件存储
│ │ │ │ └── searchhis 工具包 - 搜索历史
│ │ │ │ │ │ │ │
├── opsli-plugins 插件 ├── opsli-plugins 插件
│ ├── opsli-plugins-ehcache Ehcache缓存插件 (二级缓存) │ ├── opsli-plugins-crypto 加解密插件包
│ │ ├── src
│ │ │ ├── main
│ │ │ │ ├── java
│ │ │ │ │ └── org
│ │ │ │ │ └── opsli
│ │ │ │ │ └── plugins
│ │ │ │ │ └── crypto
│ │ │ │ │ ├── enums 加解密插件包 - 枚举
│ │ │ │ │ ├── exception 加解密插件包 - 异常处理类
│ │ │ │ │ ├── model 加解密插件包 - 模型
│ │ │ │ │ ├── msg 加解密插件包 - 异常消息
│ │ │ │ │ ├── spring 加解密插件包 - Spring集成相关内容
│ │ │ │ │ └── strategy 加解密插件包 - 加解密策略 包含 对称、非对称等等
│ │ │ │ │
│ ├── opsli-plugins-ehcache Ehcache缓存插件 (二级缓存)
│ │ ├── src │ │ ├── src
│ │ │ ├── main │ │ │ ├── main
│ │ │ │ ├── java │ │ │ │ ├── java
@ -192,7 +219,21 @@
│ │ │ │ │ ├── msg Ehcache缓存插件 - 信息 │ │ │ │ │ ├── msg Ehcache缓存插件 - 信息
│ │ │ │ │ └── service Ehcache缓存插件 - 服务 │ │ │ │ │ └── service Ehcache缓存插件 - 服务
│ │ │ │ │ │ │ │ │ │
│ ├── opsli-plugins-excel Excel插件 │ ├── opsli-plugins-email 邮件插件包
│ │ ├── src
│ │ │ ├── main
│ │ │ │ ├── java
│ │ │ │ │ └── org
│ │ │ │ │ └── opsli
│ │ │ │ │ └── plugins
│ │ │ │ │ └── email
│ │ │ │ │ ├── conf 邮件插件包 - 配置文件
│ │ │ │ │ ├── exception 邮件插件包 - 异常处理类
│ │ │ │ │ ├── msg 邮件插件包 - 异常消息
│ │ │ │ │ ├── service 邮件插件包 - 处理类
│ │ │ │ │ └── wrapper 邮件插件包 - 包装器
│ │ │ │ │
│ ├── opsli-plugins-excel Excel插件
│ │ ├── src │ │ ├── src
│ │ │ ├── main │ │ │ ├── main
│ │ │ │ ├── java │ │ │ │ ├── java
@ -206,7 +247,7 @@
│ │ │ │ │ ├── listener Excel插件 - 监听器 │ │ │ │ │ ├── listener Excel插件 - 监听器
│ │ │ │ │ └── msg Excel插件 - 信息 │ │ │ │ │ └── msg Excel插件 - 信息
│ │ │ │ │ │ │ │ │ │
│ └── opsli-plugins-redis Redis缓存插件(一级缓存) │ └── opsli-plugins-redis Redis缓存插件(一级缓存)
│ │ ├── src │ │ ├── src
│ │ │ ├── main │ │ │ ├── main
│ │ │ │ ├── java │ │ │ │ ├── java
@ -216,6 +257,7 @@
│ │ │ │ │ └── redis │ │ │ │ │ └── redis
│ │ │ │ │ ├── conf Redis缓存插件 - 自动装配 │ │ │ │ │ ├── conf Redis缓存插件 - 自动装配
│ │ │ │ │ ├── exception Redis缓存插件 - 异常类 │ │ │ │ │ ├── exception Redis缓存插件 - 异常类
│ │ │ │ │ ├── jsonserializer Redis缓存插件 - json特殊处理器
│ │ │ │ │ ├── lock Redis缓存插件 - 分布式锁 │ │ │ │ │ ├── lock Redis缓存插件 - 分布式锁
│ │ │ │ │ ├── msg Redis缓存插件 - 信息 │ │ │ │ │ ├── msg Redis缓存插件 - 信息
│ │ │ │ │ ├── pushsub Redis缓存插件 - 消息订阅 │ │ │ │ │ ├── pushsub Redis缓存插件 - 消息订阅
@ -223,7 +265,7 @@
│ │ │ │ └── resources │ │ │ │ └── resources
│ │ │ │ │ └── lua Redis缓存插件 - Lua脚本 │ │ │ │ │ └── lua Redis缓存插件 - Lua脚本
│ │ │ │ │ │ │ │ │ │
│ └── opsli-plugins-redisson Redisson分布式锁 │ └── opsli-plugins-redisson Redisson分布式锁
│ │ ├── src │ │ ├── src
│ │ │ ├── main │ │ │ ├── main
│ │ │ │ ├── java │ │ │ │ ├── java
@ -238,7 +280,41 @@
│ │ │ │ │ ├── properties Redisson分布式锁 - 配置类 │ │ │ │ │ ├── properties Redisson分布式锁 - 配置类
│ │ │ │ │ └── strategy Redisson分布式锁 - 策略 │ │ │ │ │ └── strategy Redisson分布式锁 - 策略
│ │ │ │ │ │ │ │ │ │
│ └── opsli-plugins-waf Waf软防火墙 │ ├── opsli-plugins-security 安全认证插件包
│ │ ├── src
│ │ │ ├── main
│ │ │ │ ├── java
│ │ │ │ │ └── org
│ │ │ │ │ └── opsli
│ │ │ │ │ └── plugins
│ │ │ │ │ └── security
│ │ │ │ │ ├── authentication 安全认证插件包 - 识别器
│ │ │ │ │ ├── checker 安全认证插件包 - 检查器
│ │ │ │ │ ├── eventbus 安全认证插件包 - 消息事件
│ │ │ │ │ ├── eventdto 安全认证插件包 - 消息事件DTO
│ │ │ │ │ ├── exception 安全认证插件包 - 异常
│ │ │ │ │ ├── handler 安全认证插件包 - 登陆处理器
│ │ │ │ │ ├── properties 安全认证插件包 - 配置文件
│ │ │ │ │ ├── provider 安全认证插件包 - Security认证器
│ │ │ │ │ ├── service 安全认证插件包 - 加载用户信息抽象Service
│ │ │ │ │ ├── utils 安全认证插件包 - 工具包
│ │ │ │ │ └── vo 安全认证插件包 - VO
│ │ │ │ │
│ ├── opsli-plugins-sms 短信插件包
│ │ ├── src
│ │ │ ├── main
│ │ │ │ ├── java
│ │ │ │ │ └── org
│ │ │ │ │ └── opsli
│ │ │ │ │ └── plugins
│ │ │ │ │ └── sms
│ │ │ │ │ ├── enums 短信插件包 - 配置文件
│ │ │ │ │ ├── exception 短信插件包 - 异常处理类
│ │ │ │ │ ├── model 短信插件包 - 模型
│ │ │ │ │ ├── msg 短信插件包 - 异常消息
│ │ │ │ │ └── service 短信插件包 - 服务处理
│ │ │ │ │
│ └── opsli-plugins-waf Waf软防火墙
│ ├── src │ ├── src
│ │ ├── main │ │ ├── main
│ │ │ ├── java │ │ │ ├── java

File diff suppressed because one or more lines are too long

@ -0,0 +1,14 @@
FROM mysql:8.0.19
MAINTAINER opsli.com
LABEL version=V1.3.3
LABEL description=OPSLI-快速开发平台
LABEL qqGroup=724850675
ENV TZ=Asia/Shanghai
# 切换为上海时区
RUN ln -sf /usr/share/zoneinfo/$TZ /etc/localtime \
&& echo $TZ > /etc/timezone
COPY ./opsli-boot.sql /docker-entrypoint-initdb.d

File diff suppressed because one or more lines are too long

@ -2,7 +2,7 @@ version: '3.3'
services: services:
# 构建 MySQL数据库 这里不指定数据库文件 防止误操作 等隐患问题 # 构建 MySQL数据库 这里不指定数据库文件 防止误操作 等隐患问题
opsli-boot-mysql: opsli-boot-mysql:
build: ./db-file build: ./db-file/2.0版本
image: opsli-boot-mysql image: opsli-boot-mysql
restart: always restart: always
environment: environment:
@ -57,4 +57,4 @@ services:
volumes: volumes:
- /www/wwwroot/demo.opsli.bedebug.com/backend/run:/usr/local/opsli/opsli-boot #挂载目录 - /www/wwwroot/demo.opsli.bedebug.com/backend/run:/usr/local/opsli/opsli-boot #挂载目录
ports: ports:
- "7000:7000" - "7000:7000"

@ -10,7 +10,7 @@ import java.io.Serializable;
/** /**
* *
* *
* @author * @author Parker
* @date 2021-01-24 12:48 * @date 2021-01-24 12:48
**/ **/
@Data @Data

@ -0,0 +1,42 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.api.base.encrypt;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.opsli.common.annotation.validator.Validator;
import org.opsli.common.annotation.validator.ValidatorLenMax;
import org.opsli.common.enums.ValidatorType;
import java.io.Serializable;
/**
*
*
* @author Parker
* @date 2021-01-24 12:48
**/
@Data
public class EncryptModel implements Serializable {
private static final long serialVersionUID = 1L;
@Validator({ValidatorType.IS_NOT_NULL})
@ValidatorLenMax(2000)
@ApiModelProperty(value = "加密数据")
private String encryptData;
}

@ -1,207 +0,0 @@
package org.opsli.api.base.result;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.http.HttpStatus;
import java.io.Serializable;
/**
* API
* Feign
* @JsonProperty null
*
* @date 202051510:40:54
* @author Parker
*/
@Data
@ApiModel(value="视图层返回Api对象",
description="视图层返回Api对象 success:成功状态 code:编号 msg:信息 timestamp:时间戳 data:数据")
public class ResultVo<T> implements Serializable {
private static final long serialVersionUID = 1L;
/** 默认成功信息 */
public static final String DEF_SUCCESS_MSG = "操作成功!";
/** 默认失败信息 */
public static final String DEF_ERROR_MSG = "操作失败!";
/** 成功状态 */
@ApiModelProperty(value = "成功状态")
@JsonProperty("success")
private boolean success;
/** 消息 */
@ApiModelProperty(value = "消息")
@JsonProperty("msg")
private String msg;
/** 状态码 */
@ApiModelProperty(value = "状态码")
@JsonProperty("code")
private Integer code;
/** 时间戳 */
@ApiModelProperty(value = "时间戳")
@JsonProperty("timestamp")
private Long timestamp;
/** 数据对象 */
@ApiModelProperty(value = "数据")
@JsonProperty("data")
private T data;
public T getData() {
return data;
}
public ResultVo<T> setData(T data) {
this.data = data;
return this;
}
/**
* Json
* @return String
*/
public String toJsonStr(){
return JSONObject.toJSONString(this);
}
// ===========================================
/**
*
*/
public ResultVo() {
// 初始化值
this.success = true;
this.msg = DEF_SUCCESS_MSG;
this.code = HttpStatus.OK.value();
this.timestamp = System.currentTimeMillis();
}
// ================================== 静态方法 ===================================
/**
*
* @return ResultVo<Object>
*/
@JsonIgnore
public static ResultVo<Object> success() {
return new ResultVo<>();
}
/**
*
* @param msg
* @return ResultVo<Object>
*/
@JsonIgnore
public static ResultVo<Object> success(String msg) {
ResultVo<Object> ret = new ResultVo<>();
ret.setMsg(msg);
return ret;
}
/**
*
* @param data
* @param <T>
* @return ResultVo<T>
*/
@JsonIgnore
public static <T> ResultVo<T> success(T data) {
ResultVo<T> ret = new ResultVo<>();
ret.setData(data);
return ret;
}
/**
*
* @param msg
* @param data
* @param <T>
* @return ResultVo<T>
*/
@JsonIgnore
public static <T> ResultVo<T> success(String msg, T data) {
ResultVo<T> ret = new ResultVo<>();
ret.setMsg(msg);
ret.setData(data);
return ret;
}
/**
*
* @param msg
* @param data
* @param <T>
* @return ResultVo<T>
*/
@JsonIgnore
public static <T> ResultVo<T> success(Integer code, String msg, T data) {
ResultVo<T> ret = new ResultVo<>();
ret.setCode(code);
ret.setMsg(msg);
ret.setData(data);
return ret;
}
/**
*
* @return ResultVo<Object>
*/
@JsonIgnore
public static ResultVo<Object> error() {
return ResultVo.error(
HttpStatus.INTERNAL_SERVER_ERROR.value()
, DEF_ERROR_MSG, null);
}
/**
*
* @param msg
* @return ResultVo<Object>
*/
@JsonIgnore
public static ResultVo<Object> error(String msg) {
return ResultVo.error(
HttpStatus.INTERNAL_SERVER_ERROR.value()
, msg, null);
}
/**
*
* @param code
* @param msg
* @return ResultVo<T>
*/
@JsonIgnore
public static ResultVo<Object> error(Integer code, String msg) {
return ResultVo.error(code, msg, null);
}
/**
*
* @param code
* @param data
* @param <T>
* @return ResultVo<T>
*/
@JsonIgnore
public static <T> ResultVo<T> error(Integer code, String msg, T data) {
ResultVo<T> ret = new ResultVo<>();
ret.setMsg(msg);
ret.setCode(code);
ret.setData(data);
ret.setSuccess(false);
return ret;
}
}

@ -0,0 +1,263 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.api.base.result;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.*;
import lombok.experimental.Accessors;
import org.opsli.common.base.msg.BaseMsg;
import java.io.Serializable;
/**
*
*
* @author Parker
* @date 2021123015:31:41
*/
@Data
@Builder
@Accessors(chain = true)
@AllArgsConstructor
@NoArgsConstructor
@ApiModel(value = "基础返回实体",
description="视图层返回Api对象 code:编号 msg:信息 timestamp:时间戳 data:数据")
public class ResultWrapper<T> implements Serializable {
private static final long serialVersionUID = 1L;
/**
*
*/
@ApiModelProperty(name = "msg", dataType = "string", value = "响应信息")
private String msg;
/**
* 0-1
*/
@ApiModelProperty(name = "code", dataType = "int", value = "响应码")
private int code;
/**
*
*/
@ApiModelProperty(name = "data", dataType = "object", value = "数据内容")
private T data;
/**
*
*/
@ApiModelProperty(name = "timestamp", dataType = "long", value = "时间戳")
private long timestamp;
/**
* ,
* {@link StateCodeEnum#SUCCESS}
* @param <T>
* @return ResultWrapper<T>
*/
public static <T> ResultWrapper<T> getSuccessResultWrapperByMsg(String msg) {
return ResultWrapper.<T>builder()
.code(StateCodeEnum.SUCCESS.getCode())
.msg(msg)
.timestamp(System.currentTimeMillis())
.build();
}
/**
* ,
* {@link StateCodeEnum#SUCCESS}
* @param <T>
* @return ResultWrapper<T>
*/
public static <T> ResultWrapper<T> getSuccessResultWrapper() {
return getSuccessResultWrapper(null);
}
/**
* ,
* {@link StateCodeEnum#SUCCESS}
* @param data
* @param <T>
* @return ResultWrapper<T>
*/
public static <T> ResultWrapper<T> getSuccessResultWrapper(T data) {
return ResultWrapper.<T>builder()
.code(StateCodeEnum.SUCCESS.getCode())
.msg(StateCodeEnum.SUCCESS.getMsg())
.data(data)
.timestamp(System.currentTimeMillis())
.build();
}
/**
*
* {@link StateCodeEnum#ERROR}
* @param <T>
* @return ResultWrapper<T>
*/
public static <T> ResultWrapper<T> getErrorResultWrapper() {
return getErrorResultWrapper(null);
}
/**
*
* {@link StateCodeEnum#ERROR}
* @param data
* @param <T>
* @return ResultWrapper<T>
*/
public static <T> ResultWrapper<T> getErrorResultWrapper(T data) {
return ResultWrapper.<T>builder()
.code(StateCodeEnum.ERROR.getCode())
.msg(StateCodeEnum.ERROR.getMsg())
.data(data)
.timestamp(System.currentTimeMillis())
.build();
}
/**
* 便
* @param stateCode
* @param <T>
* @return ResultWrapper<T>
*/
public static <T> ResultWrapper<T> getCustomResultWrapper(StateCodeEnum stateCode) {
return getCustomResultWrapper(null, stateCode);
}
/**
* 便
* @param data
* @param stateCode
* @param <T>
* @return ResultWrapper<T>
*/
public static <T> ResultWrapper<T> getCustomResultWrapper(T data, StateCodeEnum stateCode) {
return ResultWrapper.<T>builder()
.code(stateCode.getCode())
.msg(stateCode.getMsg())
.data(data)
.timestamp(System.currentTimeMillis())
.build();
}
/**
* 便
* @param baseMsg
* @param <T>
* @return ResultWrapper<T>
*/
public static <T> ResultWrapper<T> getCustomResultWrapper(BaseMsg baseMsg) {
return getCustomResultWrapper(null, baseMsg);
}
/**
* 便
* @param data
* @param baseMsg
* @param <T>
* @return ResultWrapper<T>
*/
public static <T> ResultWrapper<T> getCustomResultWrapper(T data, BaseMsg baseMsg) {
return ResultWrapper.<T>builder()
.code(baseMsg.getCode())
.msg(baseMsg.getMessage())
.data(data)
.timestamp(System.currentTimeMillis())
.build();
}
/**
* 便
* {@link StateCodeEnum#SUCCESS}
* @param data
* @param code
* @param msg
* @param <T>
* @return ResultWrapper<T>
*/
public static <T> ResultWrapper<T> getCustomResultWrapper(T data, int code, String msg) {
return ResultWrapper.<T>builder()
.code(code)
.msg(msg)
.data(data)
.timestamp(System.currentTimeMillis())
.build();
}
/**
* 便
* {@link StateCodeEnum#SUCCESS}
* @param code
* @param msg
* @param <T>
* @return ResultWrapper<T>
*/
public static <T> ResultWrapper<T> getCustomResultWrapper(int code, String msg) {
return ResultWrapper.<T>builder()
.code(code)
.msg(msg)
.data(null)
.timestamp(System.currentTimeMillis())
.build();
}
/**
* ,
* @param resultWrapper
* @param <T>
* @return boolean
*/
public static <T> boolean isSuccess(ResultWrapper<T> resultWrapper) {
if(null == resultWrapper){
return false;
}
return StateCodeEnum.SUCCESS.getCode() == resultWrapper.getCode();
}
/**
*
*
* @author Parker
* @date 2021123015:29:29
*/
@Getter
@AllArgsConstructor
public enum StateCodeEnum {
/** 请求状态枚举 */
SUCCESS(0, "请求成功"),
FAILURE(-1, "操作失败"),
ERROR(-1, "服务器异常");
private final int code;
private final String msg;
}
}

@ -15,7 +15,7 @@
*/ */
package org.opsli.api.web.gentest.carinfo; package org.opsli.api.web.gentest.carinfo;
import org.opsli.api.base.result.ResultVo; import org.opsli.api.base.result.ResultWrapper;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartHttpServletRequest; import org.springframework.web.multipart.MultipartHttpServletRequest;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
@ -25,7 +25,7 @@ import org.opsli.api.wrapper.gentest.carinfo.TestCarModel;
/** /**
* * Api
* *
* API @GetMapping @PostMapping * API @GetMapping @PostMapping
* Mapping Controller * Mapping Controller
@ -33,98 +33,97 @@ import org.opsli.api.wrapper.gentest.carinfo.TestCarModel;
* *
* *
* @author Parker * @author Parker
* @date 2020-12-20 20:12:57 * @date 2022-08-06 23:53:30
*/ */
public interface TestCarRestApi { public interface TestCarRestApi {
/** 标题 */ /** 标题 */
String TITLE = "汽车信息管理"; String TITLE = "测试汽车";
/** 子标题 */ /** 子标题 */
String SUB_TITLE = "汽车信息"; String SUB_TITLE = "测试汽车";
/** /**
* *
* @param model * @param model
* @return ResultVo * @return ResultWrapper
*/ */
@GetMapping("/get") @GetMapping("/get")
ResultVo<TestCarModel> get(TestCarModel model); ResultWrapper<TestCarModel> get(TestCarModel model);
/** /**
* *
* @param pageNo * @param pageNo
* @param pageSize * @param pageSize
* @param request request * @param request request
* @return ResultVo * @return ResultWrapper
*/ */
@GetMapping("/findPage") @GetMapping("/findPage")
ResultVo<?> findPage( ResultWrapper<?> findPage(
@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo, @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
HttpServletRequest request HttpServletRequest request
); );
/** /**
* *
* @param model * @param model
* @return ResultVo * @return ResultWrapper
*/ */
@PostMapping("/insert") @PostMapping("/insert")
ResultVo<?> insert(@RequestBody TestCarModel model); ResultWrapper<?> insert(@RequestBody TestCarModel model);
/** /**
* *
* @param model * @param model
* @return ResultVo * @return ResultWrapper
*/ */
@PostMapping("/update") @PostMapping("/update")
ResultVo<?> update(@RequestBody TestCarModel model); ResultWrapper<?> update(@RequestBody TestCarModel model);
/** /**
* *
* @param id ID * @param id ID
* @return ResultVo * @return ResultWrapper
*/ */
@PostMapping("/del") @PostMapping("/del")
ResultVo<?> del(String id); ResultWrapper<?> del(String id);
/** /**
* *
* @param ids ID * @param ids ID
* @return ResultVo * @return ResultWrapper
*/ */
@PostMapping("/delAll") @PostMapping("/delAll")
ResultVo<?> delAll(String ids); ResultWrapper<?> delAll(String ids);
/** /**
* Excel * Excel
* *
* Token * @param type
* * @param request request
* 使2 */
* @GetMapping("/excel/auth/{type}")
* socketJava ResultWrapper<String> exportExcelAuth(
* response javascript alert @PathVariable("type") String type,
* HttpServletRequest request);
* @param request request
* @param response response
*/
@GetMapping("/exportExcel")
void exportExcel(HttpServletRequest request, HttpServletResponse response);
/** /**
* Excel * Excel
* @param request request *
* @return ResultVo * @param certificate
*/ * @param response response
@PostMapping("/importExcel") */
ResultVo<?> importExcel(MultipartHttpServletRequest request); @GetMapping("/excel/export/{certificate}")
void exportExcel(
@PathVariable("certificate") String certificate,
HttpServletResponse response);
/** /**
* Excel * Excel
* @param response response * @param request request
* @return ResultWrapper
*/ */
@GetMapping("/importExcel/template") @PostMapping("/importExcel")
void importTemplate(HttpServletResponse response); ResultWrapper<?> importExcel(MultipartHttpServletRequest request);
} }

@ -15,11 +15,8 @@
*/ */
package org.opsli.api.web.gentest.user; package org.opsli.api.web.gentest.user;
import org.opsli.api.base.result.ResultVo; import org.opsli.api.base.result.ResultWrapper;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartHttpServletRequest; import org.springframework.web.multipart.MultipartHttpServletRequest;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
@ -48,20 +45,20 @@ public interface TestUserRestApi {
/** /**
* *
* @param model * @param model
* @return ResultVo * @return ResultWrapper
*/ */
@GetMapping("/get") @GetMapping("/get")
ResultVo<TestUserModel> get(TestUserModel model); ResultWrapper<TestUserModel> get(TestUserModel model);
/** /**
* *
* @param pageNo * @param pageNo
* @param pageSize * @param pageSize
* @param request request * @param request request
* @return ResultVo * @return ResultWrapper
*/ */
@GetMapping("/findPage") @GetMapping("/findPage")
ResultVo<?> findPage( ResultWrapper<?> findPage(
@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo, @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
HttpServletRequest request HttpServletRequest request
@ -70,56 +67,64 @@ public interface TestUserRestApi {
/** /**
* *
* @param model * @param model
* @return ResultVo * @return ResultWrapper
*/ */
@PostMapping("/insert") @PostMapping("/insert")
ResultVo<?> insert(@RequestBody TestUserModel model); ResultWrapper<?> insert(@RequestBody TestUserModel model);
/** /**
* *
* @param model * @param model
* @return ResultVo * @return ResultWrapper
*/ */
@PostMapping("/update") @PostMapping("/update")
ResultVo<?> update(@RequestBody TestUserModel model); ResultWrapper<?> update(@RequestBody TestUserModel model);
/** /**
* *
* @param id ID * @param id ID
* @return ResultVo * @return ResultWrapper
*/ */
@PostMapping("/del") @PostMapping("/del")
ResultVo<?> del(String id); ResultWrapper<?> del(String id);
/** /**
* *
* @param ids ID * @param ids ID
* @return ResultVo * @return ResultWrapper
*/ */
@PostMapping("/delAll") @PostMapping("/delAll")
ResultVo<?> delAll(String ids); ResultWrapper<?> delAll(String ids);
/** /**
* Excel * Excel
* @param request request *
* @param response response * @param type
*/ * @param request request
@GetMapping("/exportExcel") */
void exportExcel(HttpServletRequest request, HttpServletResponse response); @GetMapping("/excel/auth/{type}")
ResultWrapper<String> exportExcelAuth(
@PathVariable("type") String type,
HttpServletRequest request);
/**
* Excel
*
* @param certificate
* @param response response
*/
@GetMapping("/excel/export/{certificate}")
void exportExcel(
@PathVariable("certificate") String certificate,
HttpServletResponse response);
/** /**
* Excel * Excel
* @param request request * @param request request
* @return ResultVo * @return ResultWrapper
*/ */
@PostMapping("/importExcel") @PostMapping("/importExcel")
ResultVo<?> importExcel(MultipartHttpServletRequest request); ResultWrapper<?> importExcel(MultipartHttpServletRequest request);
/**
* Excel
* @param response response
*/
@GetMapping("/importExcel/template")
void importTemplate(HttpServletResponse response);
} }

@ -15,7 +15,7 @@
*/ */
package org.opsli.api.web.system.area; package org.opsli.api.web.system.area;
import org.opsli.api.base.result.ResultVo; import org.opsli.api.base.result.ResultWrapper;
import org.opsli.api.wrapper.system.area.SysAreaModel; import org.opsli.api.wrapper.system.area.SysAreaModel;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
@ -48,80 +48,57 @@ public interface SysAreaRestApi {
/** /**
* *
* @param model * @param model
* @return ResultVo * @return ResultWrapper
*/ */
@GetMapping("/get") @GetMapping("/get")
ResultVo<SysAreaModel> get(SysAreaModel model); ResultWrapper<SysAreaModel> get(SysAreaModel model);
/** /**
* *
* @param parentId ID * @param parentId ID
* @return ResultVo * @return ResultWrapper
*/ */
@GetMapping("/findTree") @GetMapping("/findTree")
ResultVo<?> findTree(String parentId); ResultWrapper<?> findTree(String parentId);
/** /**
* *
* @param deep * @param deep
* @return ResultVo * @return ResultWrapper
*/ */
@GetMapping("/findTreeAll") @GetMapping("/findTreeAll")
ResultVo<?> findTreeAll(@RequestParam(name = "deep", defaultValue = "3", required = false) Integer deep); ResultWrapper<?> findTreeAll(@RequestParam(name = "deep", defaultValue = "3", required = false) Integer deep);
/** /**
* *
* @param model * @param model
* @return ResultVo * @return ResultWrapper
*/ */
@PostMapping("/insert") @PostMapping("/insert")
ResultVo<?> insert(@RequestBody SysAreaModel model); ResultWrapper<?> insert(@RequestBody SysAreaModel model);
/** /**
* *
* @param model * @param model
* @return ResultVo * @return ResultWrapper
*/ */
@PostMapping("/update") @PostMapping("/update")
ResultVo<?> update(@RequestBody SysAreaModel model); ResultWrapper<?> update(@RequestBody SysAreaModel model);
/** /**
* *
* @param id ID * @param id ID
* @return ResultVo * @return ResultWrapper
*/ */
@PostMapping("/del") @PostMapping("/del")
ResultVo<?> del(String id); ResultWrapper<?> del(String id);
/** /**
* *
* @param ids ID * @param ids ID
* @return ResultVo * @return ResultWrapper
*/ */
@PostMapping("/delAll") @PostMapping("/delAll")
ResultVo<?> delAll(String ids); ResultWrapper<?> delAll(String ids);
/**
* Excel
* @param request request
* @param response response
*/
@GetMapping("/exportExcel")
void exportExcel(HttpServletRequest request, HttpServletResponse response);
/**
* Excel
* @param request request
* @return ResultVo
*/
@PostMapping("/importExcel")
ResultVo<?> importExcel(MultipartHttpServletRequest request);
/**
* Excel
* @param response response
*/
@GetMapping("/importExcel/template")
void importTemplate(HttpServletResponse response);
} }

@ -15,7 +15,7 @@
*/ */
package org.opsli.api.web.system.dict; package org.opsli.api.web.system.dict;
import org.opsli.api.base.result.ResultVo; import org.opsli.api.base.result.ResultWrapper;
import org.opsli.api.wrapper.system.dict.DictModel; import org.opsli.api.wrapper.system.dict.DictModel;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
@ -48,20 +48,20 @@ public interface DictApi {
/** /**
* *
* @param model * @param model
* @return ResultVo * @return ResultWrapper
*/ */
@GetMapping("/get") @GetMapping("/get")
ResultVo<DictModel> get(DictModel model); ResultWrapper<DictModel> get(DictModel model);
/** /**
* *
* @param pageNo * @param pageNo
* @param pageSize * @param pageSize
* @param request request * @param request request
* @return ResultVo * @return ResultWrapper
*/ */
@GetMapping("/findPage") @GetMapping("/findPage")
ResultVo<?> findPage( ResultWrapper<?> findPage(
@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo, @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
HttpServletRequest request HttpServletRequest request
@ -70,65 +70,42 @@ public interface DictApi {
/** /**
* *
* @param model * @param model
* @return ResultVo * @return ResultWrapper
*/ */
@PostMapping("/insert") @PostMapping("/insert")
ResultVo<?> insert(@RequestBody DictModel model); ResultWrapper<?> insert(@RequestBody DictModel model);
/** /**
* *
* @param model * @param model
* @return ResultVo * @return ResultWrapper
*/ */
@PostMapping("/update") @PostMapping("/update")
ResultVo<?> update(@RequestBody DictModel model); ResultWrapper<?> update(@RequestBody DictModel model);
/** /**
* *
* @param id ID * @param id ID
* @return ResultVo * @return ResultWrapper
*/ */
@PostMapping("/del") @PostMapping("/del")
ResultVo<?> del(String id); ResultWrapper<?> del(String id);
/** /**
* *
* @param ids ID * @param ids ID
* @return ResultVo * @return ResultWrapper
*/ */
@PostMapping("/delAll") @PostMapping("/delAll")
ResultVo<?> delAll(String ids); ResultWrapper<?> delAll(String ids);
/**
* Excel
* @param request request
* @param response response
*/
@GetMapping("/exportExcel")
void exportExcel(HttpServletRequest request, HttpServletResponse response);
/**
* Excel
* @param request request
* @return ResultVo
*/
@PostMapping("/importExcel")
ResultVo<?> importExcel(MultipartHttpServletRequest request);
/**
* Excel
* @param response response
*/
@GetMapping("/importExcel/template")
void importTemplate(HttpServletResponse response);
/** /**
* *
* *
* @param typeCode * @param typeCode
* @return ResultVo * @return ResultWrapper
*/ */
@GetMapping("/getDictListByCode") @GetMapping("/getDictListByCode")
ResultVo<?> getDictListByCode(String typeCode); ResultWrapper<?> getDictListByCode(String typeCode);
} }

@ -15,7 +15,7 @@
*/ */
package org.opsli.api.web.system.dict; package org.opsli.api.web.system.dict;
import org.opsli.api.base.result.ResultVo; import org.opsli.api.base.result.ResultWrapper;
import org.opsli.api.wrapper.system.dict.DictDetailModel; import org.opsli.api.wrapper.system.dict.DictDetailModel;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
@ -49,20 +49,20 @@ public interface DictDetailApi {
/** /**
* *
* @param model * @param model
* @return ResultVo * @return ResultWrapper
*/ */
@GetMapping("/get") @GetMapping("/get")
ResultVo<DictDetailModel> get(DictDetailModel model); ResultWrapper<DictDetailModel> get(DictDetailModel model);
/** /**
* *
* @param pageNo * @param pageNo
* @param pageSize * @param pageSize
* @param request request * @param request request
* @return ResultVo * @return ResultWrapper
*/ */
@GetMapping("/findPage") @GetMapping("/findPage")
ResultVo<?> findPage( ResultWrapper<?> findPage(
@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo, @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
HttpServletRequest request HttpServletRequest request
@ -71,57 +71,34 @@ public interface DictDetailApi {
/** /**
* *
* @param model * @param model
* @return ResultVo * @return ResultWrapper
*/ */
@PostMapping("/insert") @PostMapping("/insert")
ResultVo<?> insert(@RequestBody DictDetailModel model); ResultWrapper<?> insert(@RequestBody DictDetailModel model);
/** /**
* *
* @param model * @param model
* @return ResultVo * @return ResultWrapper
*/ */
@PostMapping("/update") @PostMapping("/update")
ResultVo<?> update(@RequestBody DictDetailModel model); ResultWrapper<?> update(@RequestBody DictDetailModel model);
/** /**
* *
* @param id ID * @param id ID
* @return ResultVo * @return ResultWrapper
*/ */
@PostMapping("/del") @PostMapping("/del")
ResultVo<?> del(String id); ResultWrapper<?> del(String id);
/** /**
* *
* @param ids ID * @param ids ID
* @return ResultVo * @return ResultWrapper
*/ */
@PostMapping("/delAll") @PostMapping("/delAll")
ResultVo<?> delAll(String ids); ResultWrapper<?> delAll(String ids);
/**
* Excel
* @param request request
* @param response response
*/
@GetMapping("/exportExcel")
void exportExcel(HttpServletRequest request, HttpServletResponse response);
/**
* Excel
* @param request request
* @return ResultVo
*/
@PostMapping("/importExcel")
ResultVo<?> importExcel(MultipartHttpServletRequest request);
/**
* Excel
* @param response response
*/
@GetMapping("/importExcel/template")
void importTemplate(HttpServletResponse response);
// ================================ // ================================
@ -130,9 +107,9 @@ public interface DictDetailApi {
* *
* *
* @param typeCode * @param typeCode
* @return ResultVo * @return ResultWrapper
*/ */
@GetMapping("/findListByTypeCode") @GetMapping("/findListByTypeCode")
ResultVo<List<DictDetailModel>> findListByTypeCode(String typeCode); ResultWrapper<List<DictDetailModel>> findListByTypeCode(String typeCode);
} }

@ -15,7 +15,7 @@
*/ */
package org.opsli.api.web.system.logs; package org.opsli.api.web.system.logs;
import org.opsli.api.base.result.ResultVo; import org.opsli.api.base.result.ResultWrapper;
import org.opsli.api.wrapper.system.logs.LogsModel; import org.opsli.api.wrapper.system.logs.LogsModel;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
@ -48,10 +48,10 @@ public interface LoginLogsApi {
* @param pageNo * @param pageNo
* @param pageSize * @param pageSize
* @param request request * @param request request
* @return ResultVo * @return ResultWrapper
*/ */
@GetMapping("/findPage") @GetMapping("/findPage")
ResultVo<?> findPage( ResultWrapper<?> findPage(
@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo, @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
HttpServletRequest request HttpServletRequest request

@ -15,7 +15,7 @@
*/ */
package org.opsli.api.web.system.logs; package org.opsli.api.web.system.logs;
import org.opsli.api.base.result.ResultVo; import org.opsli.api.base.result.ResultWrapper;
import org.opsli.api.wrapper.system.logs.LogsModel; import org.opsli.api.wrapper.system.logs.LogsModel;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
@ -45,20 +45,20 @@ public interface LogsApi {
/** /**
* *
* @param model * @param model
* @return ResultVo * @return ResultWrapper
*/ */
@GetMapping("/get") @GetMapping("/get")
ResultVo<LogsModel> get(LogsModel model); ResultWrapper<LogsModel> get(LogsModel model);
/** /**
* *
* @param pageNo * @param pageNo
* @param pageSize * @param pageSize
* @param request request * @param request request
* @return ResultVo * @return ResultWrapper
*/ */
@GetMapping("/findPage") @GetMapping("/findPage")
ResultVo<?> findPage( ResultWrapper<?> findPage(
@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo, @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
HttpServletRequest request HttpServletRequest request
@ -68,8 +68,8 @@ public interface LogsApi {
/** /**
* *
* @param model * @param model
* @return ResultVo * @return ResultWrapper
*/ */
ResultVo<?> insert(LogsModel model); ResultWrapper<?> insert(LogsModel model);
} }

@ -0,0 +1,92 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.api.web.system.logs;
import org.opsli.api.base.result.ResultWrapper;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.opsli.api.wrapper.system.logs.OperationLogModel;
/**
* Api
*
* API @GetMapping @PostMapping
* Mapping Controller
*
*
*
* @author Parker
* @date 2022-07-26 19:21:57
*/
public interface OperationLogRestApi {
/** 标题 */
String TITLE = "行为日志";
/** 子标题 */
String SUB_TITLE = "行为日志";
/**
*
* @param model
* @return ResultWrapper
*/
@GetMapping("/get")
ResultWrapper<OperationLogModel> get(OperationLogModel model);
/**
*
* @param pageNo
* @param pageSize
* @param request request
* @return ResultWrapper
*/
@GetMapping("/findPage")
ResultWrapper<?> findPage(
@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
HttpServletRequest request
);
/**
* Excel
*
* @param type
* @param request request
*/
@GetMapping("/excel/auth/{type}")
ResultWrapper<String> exportExcelAuth(
@PathVariable("type") String type,
HttpServletRequest request);
/**
* Excel
*
* @param certificate
* @param response response
*/
@GetMapping("/excel/export/{certificate}")
void exportExcel(
@PathVariable("certificate") String certificate,
HttpServletResponse response);
}

@ -15,7 +15,7 @@
*/ */
package org.opsli.api.web.system.menu; package org.opsli.api.web.system.menu;
import org.opsli.api.base.result.ResultVo; import org.opsli.api.base.result.ResultWrapper;
import org.opsli.api.wrapper.system.menu.MenuFullModel; import org.opsli.api.wrapper.system.menu.MenuFullModel;
import org.opsli.api.wrapper.system.menu.MenuModel; import org.opsli.api.wrapper.system.menu.MenuModel;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
@ -52,71 +52,71 @@ public interface MenuApi {
* *
* *
* @param request request * @param request request
* @return ResultVo * @return ResultWrapper
*/ */
@GetMapping("/findMenuTreePage") @GetMapping("/findMenuTreePage")
ResultVo<?> findMenuTreePage(HttpServletRequest request); ResultWrapper<?> findMenuTreePage(HttpServletRequest request);
/** /**
* *
* *
* @param parentId ID * @param parentId ID
* @return ResultVo * @return ResultWrapper
*/ */
@GetMapping("/findMenuTreePageByLazy") @GetMapping("/findMenuTreePageByLazy")
ResultVo<?> findMenuTreePageByLazy(String parentId); ResultWrapper<?> findMenuTreePageByLazy(String parentId);
/** /**
* *
* @param parentId ID * @param parentId ID
* @param id ID * @param id ID
* @return ResultVo * @return ResultWrapper
*/ */
@GetMapping("/findMenuTreeByLazy") @GetMapping("/findMenuTreeByLazy")
ResultVo<?> findMenuTreeByLazy(String parentId, String id); ResultWrapper<?> findMenuTreeByLazy(String parentId, String id);
/** /**
* *
* @return ResultVo * @return ResultWrapper
*/ */
@PostMapping("/findMenuTree") @PostMapping("/findMenuTree")
ResultVo<?> findMenuTree(); ResultWrapper<?> findMenuTree();
/** /**
* - * -
* *
* @param label * @param label
* @return ResultVo * @return ResultWrapper
*/ */
@GetMapping("/getMenuAndPermsTree") @GetMapping("/getMenuAndPermsTree")
ResultVo<?> getMenuAndPermsTree(String label); ResultWrapper<?> getMenuAndPermsTree(String label);
/** /**
* *
* @return ResultVo * @return ResultWrapper
*/ */
@GetMapping("/findList") @GetMapping("/findList")
ResultVo<List<MenuModel>> findList(); ResultWrapper<List<MenuModel>> findList();
/** /**
* *
* @param model * @param model
* @return ResultVo * @return ResultWrapper
*/ */
@GetMapping("/get") @GetMapping("/get")
ResultVo<MenuModel> get(MenuModel model); ResultWrapper<MenuModel> get(MenuModel model);
/** /**
* *
* @param pageNo * @param pageNo
* @param pageSize * @param pageSize
* @param request request * @param request request
* @return ResultVo * @return ResultWrapper
*/ */
@GetMapping("/findPage") @GetMapping("/findPage")
ResultVo<?> findPage( ResultWrapper<?> findPage(
@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo, @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
HttpServletRequest request HttpServletRequest request
@ -125,58 +125,34 @@ public interface MenuApi {
/** /**
* *
* @param model * @param model
* @return ResultVo * @return ResultWrapper
*/ */
@PostMapping("/insert") @PostMapping("/insert")
ResultVo<?> insert(@RequestBody MenuModel model); ResultWrapper<?> insert(@RequestBody MenuModel model);
/** /**
* *
* @param model * @param model
* @return ResultVo * @return ResultWrapper
*/ */
@PostMapping("/update") @PostMapping("/update")
ResultVo<?> update(@RequestBody MenuModel model); ResultWrapper<?> update(@RequestBody MenuModel model);
/** /**
* *
* @param id ID * @param id ID
* @return ResultVo * @return ResultWrapper
*/ */
@PostMapping("/del") @PostMapping("/del")
ResultVo<?> del(String id); ResultWrapper<?> del(String id);
/** /**
* *
* @param ids ID * @param ids ID
* @return ResultVo * @return ResultWrapper
*/ */
@PostMapping("/delAll") @PostMapping("/delAll")
ResultVo<?> delAll(String ids); ResultWrapper<?> delAll(String ids);
/**
* Excel
* @param request request
* @param response response
*/
@GetMapping("/exportExcel")
void exportExcel(HttpServletRequest request, HttpServletResponse response);
/**
* Excel
* @param request request
* @return ResultVo
*/
@PostMapping("/importExcel")
ResultVo<?> importExcel(MultipartHttpServletRequest request);
/**
* Excel
* @param response response
*/
@GetMapping("/importExcel/template")
void importTemplate(HttpServletResponse response);
// ================= 普通 // ================= 普通
@ -184,14 +160,14 @@ public interface MenuApi {
/** /**
* *
* @param permissions * @param permissions
* @return ResultVo * @return ResultWrapper
*/ */
ResultVo<MenuModel> getByPermissions(String permissions); ResultWrapper<MenuModel> getByPermissions(String permissions);
/** /**
* *
* @param menuFullModel * @param menuFullModel
* @return ResultVo * @return ResultWrapper
*/ */
ResultVo<?> saveMenuByFull(@RequestBody MenuFullModel menuFullModel); ResultWrapper<?> saveMenuByFull(@RequestBody MenuFullModel menuFullModel);
} }

@ -17,11 +17,8 @@
package org.opsli.api.web.system.options; package org.opsli.api.web.system.options;
import org.opsli.api.base.result.ResultVo; import org.opsli.api.base.result.ResultWrapper;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartHttpServletRequest; import org.springframework.web.multipart.MultipartHttpServletRequest;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
@ -55,20 +52,20 @@ public interface OptionsApi {
/** /**
* *
* @param model * @param model
* @return ResultVo * @return ResultWrapper
*/ */
@GetMapping("/get") @GetMapping("/get")
ResultVo<OptionsModel> get(OptionsModel model); ResultWrapper<OptionsModel> get(OptionsModel model);
/** /**
* *
* @param pageNo * @param pageNo
* @param pageSize * @param pageSize
* @param request request * @param request request
* @return ResultVo * @return ResultWrapper
*/ */
@GetMapping("/findPage") @GetMapping("/findPage")
ResultVo<?> findPage( ResultWrapper<?> findPage(
@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo, @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
HttpServletRequest request HttpServletRequest request
@ -77,108 +74,105 @@ public interface OptionsApi {
/** /**
* *
* @param model * @param model
* @return ResultVo * @return ResultWrapper
*/ */
@PostMapping("/insert") @PostMapping("/insert")
ResultVo<?> insert(@RequestBody OptionsModel model); ResultWrapper<?> insert(@RequestBody OptionsModel model);
/** /**
* *
* @param model * @param model
* @return ResultVo * @return ResultWrapper
*/ */
@PostMapping("/update") @PostMapping("/update")
ResultVo<?> update(@RequestBody OptionsModel model); ResultWrapper<?> update(@RequestBody OptionsModel model);
/** /**
* *
* @param params Map * @param params Map
* @return ResultVo * @return ResultWrapper
*/ */
@PostMapping("/updateOptions") @PostMapping("/updateOptions")
ResultVo<?> updateOptions(@RequestBody Map<String, String> params); ResultWrapper<?> updateOptions(@RequestBody Map<String, String> params);
/** /**
* *
* @param id ID * @param id ID
* @return ResultVo * @return ResultWrapper
*/ */
@PostMapping("/del") @PostMapping("/del")
ResultVo<?> del(String id); ResultWrapper<?> del(String id);
/** /**
* *
* @param ids ID * @param ids ID
* @return ResultVo * @return ResultWrapper
*/ */
@PostMapping("/delAll") @PostMapping("/delAll")
ResultVo<?> delAll(String ids); ResultWrapper<?> delAll(String ids);
/** /**
* Excel * Excel
* *
* Token * @param type
* * @param request request
* 使2 */
* @GetMapping("/excel/auth/{type}")
* socketJava ResultWrapper<String> exportExcelAuth(
* response javascript alert @PathVariable("type") String type,
* HttpServletRequest request);
* @param request request
* @param response response /**
* @return ResultVo * Excel
*/ *
@GetMapping("/exportExcel") * @param certificate
void exportExcel(HttpServletRequest request, HttpServletResponse response); * @param response response
*/
@GetMapping("/excel/export/{certificate}")
void exportExcel(
@PathVariable("certificate") String certificate,
HttpServletResponse response);
/** /**
* Excel * Excel
* @param request request * @param request request
* @return ResultVo * @return ResultWrapper
*/ */
@PostMapping("/importExcel") @PostMapping("/importExcel")
ResultVo<?> importExcel(MultipartHttpServletRequest request); ResultWrapper<?> importExcel(MultipartHttpServletRequest request);
/**
* Excel
* @param response response
* @return ResultVo
*/
@GetMapping("/importExcel/template")
void importTemplate(HttpServletResponse response);
// ========================== // ==========================
/** /**
* *
* @param optionCode * @param optionCode
* @return ResultVo * @return ResultWrapper
*/ */
@GetMapping("/getByCode") //@GetMapping("/getByCode")
ResultVo<OptionsModel> getByCode(String optionCode); ResultWrapper<OptionsModel> getByCode(String optionCode);
/** /**
* *
* @return ResultVo * @return ResultWrapper
*/ */
@GetMapping("/findAllOptions") @GetMapping("/findAllOptions")
ResultVo<Map<String, OptionsModel>> findAllOptions(); ResultWrapper<Map<String, OptionsModel>> findAllOptions();
/** /**
* *
* @return ResultVo * @return ResultWrapper
*/ */
@GetMapping("/findAll") //@GetMapping("/findAll")
ResultVo<List<OptionsModel>> findAll(); ResultWrapper<List<OptionsModel>> findAll();
/** /**
* *
* *
* @param type * @param type
* @return ResultVo * @return ResultWrapper
*/ */
@PostMapping("/createCrypto") @PostMapping("/createCrypto")
ResultVo<?> createCrypto(String type); ResultWrapper<?> createCrypto(String type);
} }

@ -15,11 +15,8 @@
*/ */
package org.opsli.api.web.system.org; package org.opsli.api.web.system.org;
import org.opsli.api.base.result.ResultVo; import org.opsli.api.base.result.ResultWrapper;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartHttpServletRequest; import org.springframework.web.multipart.MultipartHttpServletRequest;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
@ -50,90 +47,67 @@ public interface SysOrgRestApi {
* *
* @param parentId ID * @param parentId ID
* @param id ID * @param id ID
* @return ResultVo * @return ResultWrapper
*/ */
@GetMapping("/findTreeLazy") @GetMapping("/findTreeLazy")
ResultVo<?> findTreeLazy(String parentId, String id); ResultWrapper<?> findTreeLazy(String parentId, String id);
/** /**
* *
* @param isGen * @param isGen
* @param id ID * @param id ID
* @return ResultVo * @return ResultWrapper
*/ */
@GetMapping("/findTreeByDef") @GetMapping("/findTreeByDef")
ResultVo<?> findTreeByDef(boolean isGen, String id); ResultWrapper<?> findTreeByDef(boolean isGen, String id);
/** /**
* *
* @return ResultVo * @return ResultWrapper
*/ */
@GetMapping("/findTreeByDefWithUserToLike") @GetMapping("/findTreeByDefWithUserToLike")
ResultVo<?> findTreeByDefWithUserToLike(); ResultWrapper<?> findTreeByDefWithUserToLike();
// ================ // ================
/** /**
* *
* @param model * @param model
* @return ResultVo * @return ResultWrapper
*/ */
@GetMapping("/get") @GetMapping("/get")
ResultVo<SysOrgModel> get(SysOrgModel model); ResultWrapper<SysOrgModel> get(SysOrgModel model);
/** /**
* *
* @param model * @param model
* @return ResultVo * @return ResultWrapper
*/ */
@PostMapping("/insert") @PostMapping("/insert")
ResultVo<?> insert(@RequestBody SysOrgModel model); ResultWrapper<?> insert(@RequestBody SysOrgModel model);
/** /**
* *
* @param model * @param model
* @return ResultVo * @return ResultWrapper
*/ */
@PostMapping("/update") @PostMapping("/update")
ResultVo<?> update(@RequestBody SysOrgModel model); ResultWrapper<?> update(@RequestBody SysOrgModel model);
/** /**
* *
* @param id ID * @param id ID
* @return ResultVo * @return ResultWrapper
*/ */
@PostMapping("/del") @PostMapping("/del")
ResultVo<?> del(String id); ResultWrapper<?> del(String id);
/** /**
* *
* @param ids ID * @param ids ID
* @return ResultVo * @return ResultWrapper
*/ */
@PostMapping("/delAll") @PostMapping("/delAll")
ResultVo<?> delAll(String ids); ResultWrapper<?> delAll(String ids);
/**
* Excel
* @param request request
* @param response response
*/
@GetMapping("/exportExcel")
void exportExcel(HttpServletRequest request, HttpServletResponse response);
/**
* Excel
* @param request request
* @return ResultVo
*/
@PostMapping("/importExcel")
ResultVo<?> importExcel(MultipartHttpServletRequest request);
/**
* Excel
* @param response response
*/
@GetMapping("/importExcel/template")
void importTemplate(HttpServletResponse response);
} }

@ -15,12 +15,9 @@
*/ */
package org.opsli.api.web.system.role; package org.opsli.api.web.system.role;
import org.opsli.api.base.result.ResultVo; import org.opsli.api.base.result.ResultWrapper;
import org.opsli.api.wrapper.system.role.RoleModel; import org.opsli.api.wrapper.system.role.RoleModel;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartHttpServletRequest; import org.springframework.web.multipart.MultipartHttpServletRequest;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
@ -48,20 +45,20 @@ public interface RoleApi {
/** /**
* *
* @param model * @param model
* @return ResultVo * @return ResultWrapper
*/ */
@GetMapping("/get") @GetMapping("/get")
ResultVo<RoleModel> get(RoleModel model); ResultWrapper<RoleModel> get(RoleModel model);
/** /**
* *
* @param pageNo * @param pageNo
* @param pageSize * @param pageSize
* @param request request * @param request request
* @return ResultVo * @return ResultWrapper
*/ */
@GetMapping("/findPage") @GetMapping("/findPage")
ResultVo<?> findPage( ResultWrapper<?> findPage(
@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo, @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
HttpServletRequest request HttpServletRequest request
@ -70,56 +67,63 @@ public interface RoleApi {
/** /**
* *
* @param model * @param model
* @return ResultVo * @return ResultWrapper
*/ */
@PostMapping("/insert") @PostMapping("/insert")
ResultVo<?> insert(@RequestBody RoleModel model); ResultWrapper<?> insert(@RequestBody RoleModel model);
/** /**
* *
* @param model * @param model
* @return ResultVo * @return ResultWrapper
*/ */
@PostMapping("/update") @PostMapping("/update")
ResultVo<?> update(@RequestBody RoleModel model); ResultWrapper<?> update(@RequestBody RoleModel model);
/** /**
* *
* @param id ID * @param id ID
* @return ResultVo * @return ResultWrapper
*/ */
@PostMapping("/del") @PostMapping("/del")
ResultVo<?> del(String id); ResultWrapper<?> del(String id);
/** /**
* *
* @param ids ID * @param ids ID
* @return ResultVo * @return ResultWrapper
*/ */
@PostMapping("/delAll") @PostMapping("/delAll")
ResultVo<?> delAll(String ids); ResultWrapper<?> delAll(String ids);
/** /**
* Excel * Excel
*
* @param type
* @param request request * @param request request
*/
@GetMapping("/excel/auth/{type}")
ResultWrapper<String> exportExcelAuth(
@PathVariable("type") String type,
HttpServletRequest request);
/**
* Excel
*
* @param certificate
* @param response response * @param response response
*/ */
@GetMapping("/exportExcel") @GetMapping("/excel/export/{certificate}")
void exportExcel(HttpServletRequest request, HttpServletResponse response); void exportExcel(
@PathVariable("certificate") String certificate,
HttpServletResponse response);
/** /**
* Excel * Excel
* @param request request * @param request request
* @return ResultVo * @return ResultWrapper
*/ */
@PostMapping("/importExcel") @PostMapping("/importExcel")
ResultVo<?> importExcel(MultipartHttpServletRequest request); ResultWrapper<?> importExcel(MultipartHttpServletRequest request);
/**
* Excel
* @param response response
*/
@GetMapping("/importExcel/template")
void importTemplate(HttpServletResponse response);
} }

@ -15,7 +15,7 @@
*/ */
package org.opsli.api.web.system.role; package org.opsli.api.web.system.role;
import org.opsli.api.base.result.ResultVo; import org.opsli.api.base.result.ResultWrapper;
import org.opsli.api.wrapper.system.role.RoleMenuRefModel; import org.opsli.api.wrapper.system.role.RoleMenuRefModel;
import org.opsli.api.wrapper.system.role.RoleModel; import org.opsli.api.wrapper.system.role.RoleModel;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
@ -49,18 +49,18 @@ public interface RoleMenuRefApi {
/** /**
* *
* @param model Id * @param model Id
* @return ResultVo * @return ResultWrapper
*/ */
@GetMapping("/getPerms") @GetMapping("/getPerms")
ResultVo<?> getPerms(RoleMenuRefModel model); ResultWrapper<?> getPerms(RoleMenuRefModel model);
/** /**
* *
* @param model roleId Id * @param model roleId Id
* @param model permsIds Id * @param model permsIds Id
* @return ResultVo * @return ResultWrapper
*/ */
@PostMapping("/setPerms") @PostMapping("/setPerms")
ResultVo<?> setPerms(@RequestBody RoleMenuRefModel model); ResultWrapper<?> setPerms(@RequestBody RoleMenuRefModel model);
} }

@ -15,12 +15,9 @@
*/ */
package org.opsli.api.web.system.tenant; package org.opsli.api.web.system.tenant;
import org.opsli.api.base.result.ResultVo; import org.opsli.api.base.result.ResultWrapper;
import org.opsli.api.wrapper.system.tenant.TenantModel; import org.opsli.api.wrapper.system.tenant.TenantModel;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartHttpServletRequest; import org.springframework.web.multipart.MultipartHttpServletRequest;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
@ -48,20 +45,20 @@ public interface TenantApi {
/** /**
* *
* @param model * @param model
* @return ResultVo * @return ResultWrapper
*/ */
@GetMapping("/get") @GetMapping("/get")
ResultVo<TenantModel> get(TenantModel model); ResultWrapper<TenantModel> get(TenantModel model);
/** /**
* *
* @param pageNo * @param pageNo
* @param pageSize * @param pageSize
* @param request request * @param request request
* @return ResultVo * @return ResultWrapper
*/ */
@GetMapping("/findPage") @GetMapping("/findPage")
ResultVo<?> findPage( ResultWrapper<?> findPage(
@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo, @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
HttpServletRequest request HttpServletRequest request
@ -70,57 +67,65 @@ public interface TenantApi {
/** /**
* *
* @param model * @param model
* @return ResultVo * @return ResultWrapper
*/ */
@PostMapping("/insert") @PostMapping("/insert")
ResultVo<?> insert(@RequestBody TenantModel model); ResultWrapper<?> insert(@RequestBody TenantModel model);
/** /**
* *
* @param model * @param model
* @return ResultVo * @return ResultWrapper
*/ */
@PostMapping("/update") @PostMapping("/update")
ResultVo<?> update(@RequestBody TenantModel model); ResultWrapper<?> update(@RequestBody TenantModel model);
/** /**
* *
* @param id ID * @param id ID
* @return ResultVo * @return ResultWrapper
*/ */
@PostMapping("/del") @PostMapping("/del")
ResultVo<?> del(String id); ResultWrapper<?> del(String id);
/** /**
* *
* @param ids ID * @param ids ID
* @return ResultVo * @return ResultWrapper
*/ */
@PostMapping("/delAll") @PostMapping("/delAll")
ResultVo<?> delAll(String ids); ResultWrapper<?> delAll(String ids);
/** /**
* Excel * Excel
*
* @param type
* @param request request * @param request request
*/
@GetMapping("/excel/auth/{type}")
ResultWrapper<String> exportExcelAuth(
@PathVariable("type") String type,
HttpServletRequest request);
/**
* Excel
*
* @param certificate
* @param response response * @param response response
*/ */
@GetMapping("/exportExcel") @GetMapping("/excel/export/{certificate}")
void exportExcel(HttpServletRequest request, HttpServletResponse response); void exportExcel(
@PathVariable("certificate") String certificate,
HttpServletResponse response);
/** /**
* Excel * Excel
* @param request request * @param request request
* @return ResultVo * @return ResultWrapper
*/ */
@PostMapping("/importExcel") @PostMapping("/importExcel")
ResultVo<?> importExcel(MultipartHttpServletRequest request); ResultWrapper<?> importExcel(MultipartHttpServletRequest request);
/**
* Excel
* @param response response
*/
@GetMapping("/importExcel/template")
void importTemplate(HttpServletResponse response);
/** /**
@ -128,18 +133,18 @@ public interface TenantApi {
* *
* @param tenantId ID * @param tenantId ID
* @param enable * @param enable
* @return ResultVo * @return ResultWrapper
*/ */
@PostMapping("/enableTenant") @PostMapping("/enableTenant")
ResultVo<?> enableTenant(String tenantId, String enable); ResultWrapper<?> enableTenant(String tenantId, String enable);
// ========================= // =========================
/** /**
* *
* @param tenantId * @param tenantId
* @return ResultVo * @return ResultWrapper
*/ */
@GetMapping("/getTenantByUsable") @GetMapping("/getTenantByUsable")
ResultVo<TenantModel> getTenantByUsable(String tenantId); ResultWrapper<TenantModel> getTenantByUsable(String tenantId);
} }

@ -15,14 +15,12 @@
*/ */
package org.opsli.api.web.system.user; package org.opsli.api.web.system.user;
import org.opsli.api.base.result.ResultVo; import org.opsli.api.base.encrypt.EncryptModel;
import org.opsli.api.base.result.ResultWrapper;
import org.opsli.api.wrapper.system.menu.MenuModel; import org.opsli.api.wrapper.system.menu.MenuModel;
import org.opsli.api.wrapper.system.role.RoleModel; import org.opsli.api.wrapper.system.role.RoleModel;
import org.opsli.api.wrapper.system.user.*; import org.opsli.api.wrapper.system.user.*;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartHttpServletRequest; import org.springframework.web.multipart.MultipartHttpServletRequest;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
@ -51,97 +49,123 @@ public interface UserApi {
/** /**
* *
* @param request request * @param request request
* @return ResultVo * @return ResultWrapper
*/ */
@GetMapping("/getInfo") @GetMapping("/getInfo")
ResultVo<UserInfo> getInfo(HttpServletRequest request); ResultWrapper<UserInfo> getInfo(HttpServletRequest request);
/** /**
* *
* *
* @param userId ID * @param userId ID
* @return ResultVo * @return ResultWrapper
*/ */
@GetMapping("/getInfoById") @GetMapping("/getInfoById")
ResultVo<UserInfo> getInfoById(String userId); ResultWrapper<UserInfo> getInfoById(String userId);
/** /**
* *
* @return ResultVo * @return ResultWrapper
*/ */
@GetMapping("/getOrg") @GetMapping("/getOrg")
ResultVo<?> getOrg(); ResultWrapper<?> getOrg();
/** /**
* *
* *
* @param userId ID * @param userId ID
* @return ResultVo * @return ResultWrapper
*/ */
@GetMapping("/getOrgByUserId") @GetMapping("/getOrgByUserId")
ResultVo<?> getOrgByUserId(String userId); ResultWrapper<?> getOrgByUserId(String userId);
/** /**
* userId Id * userId Id
* @param userId Id * @param userId Id
* @return ResultVo * @return ResultWrapper
*/ */
@GetMapping("/getRoleIdsByUserId") @GetMapping("/getRoleIdsByUserId")
ResultVo<List<String>> getRoleIdsByUserId(String userId); ResultWrapper<List<String>> getRoleIdsByUserId(String userId);
/**
* ID
*
* @param encryptModel
* @return ResultVo
*/
@PostMapping("/updatePasswordById")
ResultWrapper<?> updatePasswordById(@RequestBody EncryptModel encryptModel);
/** /**
* *
* @param userPassword * @param encryptModel
* @return ResultVo * @return ResultWrapper
*/ */
@PostMapping("/updatePassword") @PostMapping("/updatePassword")
ResultVo<?> updatePassword(@RequestBody UserPassword userPassword); ResultWrapper<?> updatePassword(@RequestBody EncryptModel encryptModel);
/** /**
* ID *
* * @param encryptModel
* @param userPassword * @return ResultWrapper
* @return ResultVo
*/ */
@PostMapping("/updatePasswordById") @PostMapping("/updateEmail")
ResultVo<?> updatePasswordById(@RequestBody ToUserPassword userPassword); ResultWrapper<?> updateEmail(@RequestBody EncryptModel encryptModel);
/**
*
* @param encryptModel
* @return ResultWrapper
*/
@PostMapping("/updateMobile")
ResultWrapper<?> updateMobile(@RequestBody EncryptModel encryptModel);
/** /**
* ID * ID
* *
* @param userId ID * @param encryptModel ID
* @return ResultVo * @return ResultWrapper
*/ */
@PostMapping("/resetPasswordById") @PostMapping("/resetPasswordById")
ResultVo<?> resetPasswordById(String userId); ResultWrapper<?> resetPasswordById(@RequestBody EncryptModel encryptModel);
/** /**
* *
* *
* @param userId ID * @param encryptModel EnableUserModel
* @param enable * @return ResultWrapper
* @return ResultVo
*/ */
@PostMapping("/enableAccount") @PostMapping("/enableAccount")
ResultVo<?> enableAccount(String userId, String enable); ResultWrapper<?> enableAccount(@RequestBody EncryptModel encryptModel);
/**
*
*
* @param encryptModel
* @return ResultWrapper
*/
@PostMapping("/updatePasswordByForget")
ResultWrapper<?> updatePasswordByForget(@RequestBody EncryptModel encryptModel);
/** /**
* *
* @param userAvatarModel * @param userAvatarModel
* @return ResultVo * @return ResultWrapper
*/ */
@PostMapping("/updateAvatar") @PostMapping("/updateAvatar")
ResultVo<?> updateAvatar(@RequestBody UserAvatarModel userAvatarModel); ResultWrapper<?> updateAvatar(@RequestBody UserAvatarModel userAvatarModel);
/** /**
* *
* @param model * @param model
* @return ResultVo * @return ResultWrapper
*/ */
@GetMapping("/get") @GetMapping("/get")
ResultVo<UserModel> get(UserModel model); ResultWrapper<UserModel> get(UserModel model);
/** /**
* *
@ -149,10 +173,10 @@ public interface UserApi {
* @param pageSize * @param pageSize
* @param orgIdGroup ID * @param orgIdGroup ID
* @param request request * @param request request
* @return ResultVo * @return ResultWrapper
*/ */
@GetMapping("/findPage") @GetMapping("/findPage")
ResultVo<?> findPage( ResultWrapper<?> findPage(
@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo, @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
@RequestParam(name = "orgIdGroup") String orgIdGroup, @RequestParam(name = "orgIdGroup") String orgIdGroup,
@ -164,10 +188,10 @@ public interface UserApi {
* @param pageNo * @param pageNo
* @param pageSize * @param pageSize
* @param request request * @param request request
* @return ResultVo * @return ResultWrapper
*/ */
@GetMapping("/findPageByTenant") @GetMapping("/findPageByTenant")
ResultVo<?> findPageByTenant( ResultWrapper<?> findPageByTenant(
@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo, @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
HttpServletRequest request HttpServletRequest request
@ -178,91 +202,114 @@ public interface UserApi {
/** /**
* *
* @param model * @param model
* @return ResultVo * @return ResultWrapper
*/ */
@PostMapping("/insert") @PostMapping("/insert")
ResultVo<?> insert(@RequestBody UserModel model); ResultWrapper<?> insert(@RequestBody UserModel model);
/** /**
* *
* @param model * @param model
* @return ResultVo * @return ResultWrapper
*/ */
@PostMapping("/update") @PostMapping("/update")
ResultVo<?> update(@RequestBody UserModel model); ResultWrapper<?> update(@RequestBody UserModel model);
/** /**
* *
* @param model * @param model
* @return ResultVo * @return ResultWrapper
*/ */
@PostMapping("/updateSelf") @PostMapping("/updateSelf")
ResultVo<?> updateSelf(@RequestBody UserModel model); ResultWrapper<?> updateSelf(@RequestBody UserModel model);
/** /**
* *
* @param id ID * @param encryptModel id ID
* @return ResultVo * @return ResultWrapper
*/ */
@PostMapping("/del") @PostMapping("/del")
ResultVo<?> del(String id); ResultWrapper<?> del(@RequestBody EncryptModel encryptModel);
/** /**
* *
* @param ids ID * @param encryptModel ids ID
* @return ResultVo * @return ResultWrapper
*/ */
@PostMapping("/delAll") @PostMapping("/delAll")
ResultVo<?> delAll(String ids); ResultWrapper<?> delAll(@RequestBody EncryptModel encryptModel);
/** /**
* Excel * Excel
*
* @param type
* @param request request * @param request request
*/
@GetMapping("/excel/auth/{type}")
ResultWrapper<String> exportExcelAuth(
@PathVariable("type") String type,
HttpServletRequest request);
/**
* Excel
*
* @param certificate
* @param response response * @param response response
*/ */
@GetMapping("/exportExcel") @GetMapping("/excel/export/{certificate}")
void exportExcel(HttpServletRequest request, HttpServletResponse response); void exportExcel(
@PathVariable("certificate") String certificate,
HttpServletResponse response);
/** /**
* Excel * Excel
* @param request request * @param request request
* @return ResultVo * @return ResultWrapper
*/ */
@PostMapping("/importExcel") @PostMapping("/importExcel")
ResultVo<?> importExcel(MultipartHttpServletRequest request); ResultWrapper<?> importExcel(MultipartHttpServletRequest request);
/**
* Excel
* @param response response
*/
@GetMapping("/importExcel/template")
void importTemplate(HttpServletResponse response);
/** /**
* *
* @param tenantId ID * @param tenantId ID
* @return ResultVo * @return ResultWrapper
*/ */
@PostMapping("/switchTenant") @PostMapping("/switchTenant")
ResultVo<?> switchTenant(String tenantId); ResultWrapper<?> switchTenant(String tenantId);
/** /**
* *
* @return ResultVo * @return ResultWrapper
*/ */
@PostMapping("/switchOneself") @PostMapping("/switchOneself")
ResultVo<?> switchOneself(); ResultWrapper<?> switchOneself();
/** /**
* username * username
* @param username * @param username
* @return ResultVo * @return ResultWrapper
*/ */
//@GetMapping("/getUserByUsername") //@GetMapping("/getUserByUsername")
ResultVo<UserModel> getUserByUsername(String username); ResultWrapper<UserModel> getUserByUsername(String username);
/**
*
* @param mobile
* @return ResultWrapper
*/
ResultWrapper<UserModel> getUserByMobile(String mobile);
/**
*
* @param email
* @return ResultWrapper
*/
ResultWrapper<UserModel> getUserByEmail(String email);

@ -15,7 +15,7 @@
*/ */
package org.opsli.api.web.system.user; package org.opsli.api.web.system.user;
import org.opsli.api.base.result.ResultVo; import org.opsli.api.base.result.ResultWrapper;
import org.opsli.api.wrapper.system.org.SysOrgModel; import org.opsli.api.wrapper.system.org.SysOrgModel;
import org.opsli.api.wrapper.system.user.UserOrgRefModel; import org.opsli.api.wrapper.system.user.UserOrgRefModel;
import org.opsli.api.wrapper.system.user.UserOrgRefWebModel; import org.opsli.api.wrapper.system.user.UserOrgRefWebModel;
@ -47,25 +47,25 @@ public interface UserOrgRefApi {
/** /**
* *
* @param model * @param model
* @return ResultVo * @return ResultWrapper
*/ */
@PostMapping("/setOrg") @PostMapping("/setOrg")
ResultVo<?> setOrg(@RequestBody UserOrgRefWebModel model); ResultWrapper<?> setOrg(@RequestBody UserOrgRefWebModel model);
/** /**
* ID * ID
* @param userId ID * @param userId ID
* @return List * @return List
*/ */
ResultVo<List<UserOrgRefModel>> findListByUserId(String userId); ResultWrapper<List<UserOrgRefModel>> findListByUserId(String userId);
/** /**
* userId * userId
* @param userId Id * @param userId Id
* @return ResultVo * @return ResultWrapper
*/ */
//@GetMapping("/getRolesByUserId") //@GetMapping("/getRolesByUserId")
ResultVo<UserOrgRefModel> getDefOrgByUserId(String userId); ResultWrapper<UserOrgRefModel> getDefOrgByUserId(String userId);
} }

@ -15,7 +15,7 @@
*/ */
package org.opsli.api.web.system.user; package org.opsli.api.web.system.user;
import org.opsli.api.base.result.ResultVo; import org.opsli.api.base.result.ResultWrapper;
import org.opsli.api.wrapper.system.menu.MenuModel; import org.opsli.api.wrapper.system.menu.MenuModel;
import org.opsli.api.wrapper.system.role.RoleMenuRefModel; import org.opsli.api.wrapper.system.role.RoleMenuRefModel;
import org.opsli.api.wrapper.system.role.RoleModel; import org.opsli.api.wrapper.system.role.RoleModel;
@ -48,50 +48,50 @@ public interface UserRoleRefApi {
/** /**
* *
* @param userId ID * @param userId ID
* @return ResultVo * @return ResultWrapper
*/ */
@GetMapping("/getRoles") @GetMapping("/getRoles")
ResultVo<?> getRoles(String userId); ResultWrapper<?> getRoles(String userId);
/** /**
* *
* @param model * @param model
* @return ResultVo * @return ResultWrapper
*/ */
@PostMapping("/setRoles") @PostMapping("/setRoles")
ResultVo<?> setRoles(@RequestBody UserRoleRefModel model); ResultWrapper<?> setRoles(@RequestBody UserRoleRefModel model);
/** /**
* userId * userId
* @param userId Id * @param userId Id
* @return ResultVo * @return ResultWrapper
*/ */
//@GetMapping("/getRolesByUserId") //@GetMapping("/getRolesByUserId")
ResultVo<List<String>> getRolesByUserId(String userId); ResultWrapper<List<String>> getRolesByUserId(String userId);
/** /**
* userId * userId
* @param userId Id * @param userId Id
* @return ResultVo * @return ResultWrapper
*/ */
//@GetMapping("/getRolesByUserId") //@GetMapping("/getRolesByUserId")
ResultVo<RoleModel> getDefRoleByUserId(String userId); ResultWrapper<RoleModel> getDefRoleByUserId(String userId);
/** /**
* userId * userId
* @param userId Id * @param userId Id
* @return ResultVo * @return ResultWrapper
*/ */
//@GetMapping("/queryAllPerms") //@GetMapping("/queryAllPerms")
ResultVo<List<String>> getAllPerms(String userId); ResultWrapper<List<String>> getAllPerms(String userId);
/** /**
* userId * userId
* @param userId Id * @param userId Id
* @return ResultVo * @return ResultWrapper
*/ */
//@GetMapping("/queryAllPerms") //@GetMapping("/queryAllPerms")
ResultVo<List<MenuModel>> getMenuListByUserId(String userId); ResultWrapper<List<MenuModel>> getMenuListByUserId(String userId);
} }

@ -1,8 +1,9 @@
package org.opsli.api.web.test; package org.opsli.api.web.test;
import org.opsli.api.base.result.ResultVo; import org.opsli.api.base.result.ResultWrapper;
import org.opsli.api.wrapper.test.TestModel; import org.opsli.api.wrapper.test.TestModel;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartHttpServletRequest; import org.springframework.web.multipart.MultipartHttpServletRequest;
@ -28,93 +29,93 @@ public interface TestApi {
/** /**
* *
* @return ResultVo * @return ResultWrapper
*/ */
@GetMapping("/sendMail") @GetMapping("/sendMail")
ResultVo<?> sendMail(); ResultWrapper<?> sendMail();
/** /**
* Redis * Redis
* @return ResultVo * @return ResultWrapper
*/ */
@GetMapping("/sendMsg") @GetMapping("/sendMsg")
ResultVo<?> sendMsg(); ResultWrapper<?> sendMsg();
/** /**
* Redis * Redis
* @return ResultVo * @return ResultWrapper
*/ */
@GetMapping("/redisTest") @GetMapping("/redisTest")
ResultVo<?> redisTest(); ResultWrapper<?> redisTest();
/** /**
* Redis * Redis
* @return ResultVo * @return ResultWrapper
*/ */
@GetMapping("/testLock") @GetMapping("/testLock")
ResultVo<?> testLock(); ResultWrapper<?> testLock();
/** /**
* *
* @param entity entity * @param entity entity
* @return ResultVo * @return ResultWrapper
*/ */
@GetMapping("/insert") @GetMapping("/insert")
ResultVo<TestModel> insert(TestModel entity); ResultWrapper<TestModel> insert(TestModel entity);
/** /**
* *
* @param entity entity * @param entity entity
* @return ResultVo * @return ResultWrapper
*/ */
@GetMapping("/update") @GetMapping("/update")
ResultVo<TestModel> update(TestModel entity); ResultWrapper<TestModel> update(TestModel entity);
/** /**
* *
* @param entity entity * @param entity entity
* @return ResultVo * @return ResultWrapper
*/ */
@GetMapping("/get") @GetMapping("/get")
ResultVo<TestModel> get(TestModel entity); ResultWrapper<TestModel> get(TestModel entity);
/** /**
* *
* @param id id * @param id id
* @return ResultVo * @return ResultWrapper
*/ */
@GetMapping("/del") @GetMapping("/del")
ResultVo<?> del(String id); ResultWrapper<?> del(String id);
/** /**
* *
* @return ResultVo * @return ResultWrapper
*/ */
@GetMapping("/delAll") @GetMapping("/delAll")
ResultVo<?> delAll(); ResultWrapper<?> delAll();
/** /**
* *
* @param request request * @param request request
* @return ResultVo * @return ResultWrapper
*/ */
@GetMapping("/findList") @GetMapping("/findList")
ResultVo<List<TestModel>> findList(HttpServletRequest request); ResultWrapper<List<TestModel>> findList(HttpServletRequest request);
/** /**
* *
* @return ResultVo * @return ResultWrapper
*/ */
@GetMapping("/findAllList") @GetMapping("/findAllList")
ResultVo<List<TestModel>> findAllList(); ResultWrapper<List<TestModel>> findAllList();
/** /**
@ -123,10 +124,10 @@ public interface TestApi {
* @param pageNo * @param pageNo
* @param pageSize * @param pageSize
* @param request request * @param request request
* @return ResultVo * @return ResultWrapper
*/ */
@GetMapping("/findPage") @GetMapping("/findPage")
ResultVo<?> findPage( ResultWrapper<?> findPage(
@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo, @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
HttpServletRequest request HttpServletRequest request
@ -134,29 +135,36 @@ public interface TestApi {
/** /**
* Excel * Excel
* *
* @param type
* @param request request * @param request request
*/
@GetMapping("/excel/auth/{type}")
ResultWrapper<String> exportExcelAuth(
@PathVariable("type") String type,
HttpServletRequest request);
/**
* Excel
*
* @param certificate
* @param response response * @param response response
*/ */
@GetMapping("/exportExcel") @GetMapping("/excel/export/{certificate}")
void exportExcel(HttpServletRequest request, HttpServletResponse response); void exportExcel(
@PathVariable("certificate") String certificate,
HttpServletResponse response);
/** /**
* Excel * Excel
* *
* @param request request * @param request request
* @return ResultVo * @return ResultWrapper
*/ */
@PostMapping("/importExcel") @PostMapping("/importExcel")
ResultVo<?> importExcel(MultipartHttpServletRequest request); ResultWrapper<?> importExcel(MultipartHttpServletRequest request);
/**
* Excel
*
* @param response response
*/
@GetMapping("/importExcel/template")
void importTemplate(HttpServletResponse response);
} }

@ -15,12 +15,9 @@
*/ */
package org.opsli.api.web.test; package org.opsli.api.web.test;
import org.opsli.api.base.result.ResultVo; import org.opsli.api.base.result.ResultWrapper;
import org.opsli.api.wrapper.test.TestModel; import org.opsli.api.wrapper.test.TestModel;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartHttpServletRequest; import org.springframework.web.multipart.MultipartHttpServletRequest;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
@ -48,20 +45,20 @@ public interface TestRestApi {
/** /**
* *
* @param model * @param model
* @return ResultVo * @return ResultWrapper
*/ */
@GetMapping("/get") @GetMapping("/get")
ResultVo<TestModel> get(TestModel model); ResultWrapper<TestModel> get(TestModel model);
/** /**
* *
* @param pageNo * @param pageNo
* @param pageSize * @param pageSize
* @param request request * @param request request
* @return ResultVo * @return ResultWrapper
*/ */
@GetMapping("/findPage") @GetMapping("/findPage")
ResultVo<?> findPage( ResultWrapper<?> findPage(
@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo, @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
HttpServletRequest request HttpServletRequest request
@ -70,56 +67,65 @@ public interface TestRestApi {
/** /**
* *
* @param model * @param model
* @return ResultVo * @return ResultWrapper
*/ */
@PostMapping("/insert") @PostMapping("/insert")
ResultVo<?> insert(@RequestBody TestModel model); ResultWrapper<?> insert(@RequestBody TestModel model);
/** /**
* *
* @param model * @param model
* @return ResultVo * @return ResultWrapper
*/ */
@PostMapping("/update") @PostMapping("/update")
ResultVo<?> update(@RequestBody TestModel model); ResultWrapper<?> update(@RequestBody TestModel model);
/** /**
* *
* @param id ID * @param id ID
* @return ResultVo * @return ResultWrapper
*/ */
@PostMapping("/del") @PostMapping("/del")
ResultVo<?> del(String id); ResultWrapper<?> del(String id);
/** /**
* *
* @param ids ID * @param ids ID
* @return ResultVo * @return ResultWrapper
*/ */
@PostMapping("/delAll") @PostMapping("/delAll")
ResultVo<?> delAll(String ids); ResultWrapper<?> delAll(String ids);
/** /**
* Excel * Excel
*
* @param type
* @param request request * @param request request
*/
@GetMapping("/excel/auth/{type}")
ResultWrapper<String> exportExcelAuth(
@PathVariable("type") String type,
HttpServletRequest request);
/**
* Excel
*
* @param certificate
* @param response response * @param response response
*/ */
@GetMapping("/exportExcel") @GetMapping("/excel/export/{certificate}")
void exportExcel(HttpServletRequest request, HttpServletResponse response); void exportExcel(
@PathVariable("certificate") String certificate,
HttpServletResponse response);
/** /**
* Excel * Excel
* @param request request * @param request request
* @return ResultVo * @return ResultWrapper
*/ */
@PostMapping("/importExcel") @PostMapping("/importExcel")
ResultVo<?> importExcel(MultipartHttpServletRequest request); ResultWrapper<?> importExcel(MultipartHttpServletRequest request);
/**
* Excel
* @param response response
*/
@GetMapping("/importExcel/template")
void importTemplate(HttpServletResponse response);
} }

@ -15,6 +15,7 @@
*/ */
package org.opsli.api.wrapper.gentest.carinfo; package org.opsli.api.wrapper.gentest.carinfo;
import java.math.BigDecimal;
import java.util.Date; import java.util.Date;
import com.alibaba.excel.annotation.ExcelProperty; import com.alibaba.excel.annotation.ExcelProperty;
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty;
@ -23,17 +24,18 @@ import lombok.EqualsAndHashCode;
import org.opsli.api.base.warpper.ApiWrapper; import org.opsli.api.base.warpper.ApiWrapper;
import org.opsli.common.annotation.validator.Validator; import org.opsli.common.annotation.validator.Validator;
import org.opsli.common.annotation.validator.ValidatorLenMax; import org.opsli.common.annotation.validator.ValidatorLenMax;
import org.opsli.common.annotation.validator.ValidatorLenMin;
import org.opsli.common.enums.ValidatorType; import org.opsli.common.enums.ValidatorType;
import org.opsli.plugins.excel.annotation.ExcelInfo; import org.opsli.plugins.excel.annotation.ExcelInfo;
import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonFormat;
import org.springframework.format.annotation.DateTimeFormat; import org.springframework.format.annotation.DateTimeFormat;
/** /**
* * Model
* *
* @author Parker * @author Parker
* @date 2020-12-20 20:12:57 * @date 2022-08-06 23:53:30
*/ */
@Data @Data
@EqualsAndHashCode(callSuper = false) @EqualsAndHashCode(callSuper = false)
public class TestCarModel extends ApiWrapper { public class TestCarModel extends ApiWrapper {
@ -42,7 +44,10 @@ public class TestCarModel extends ApiWrapper {
@ApiModelProperty(value = "汽车名称") @ApiModelProperty(value = "汽车名称")
@ExcelProperty(value = "汽车名称", order = 1) @ExcelProperty(value = "汽车名称", order = 1)
@ExcelInfo @ExcelInfo
@Validator({ValidatorType.IS_NOT_NULL, ValidatorType.IS_GENERAL_WITH_CHINESE}) @Validator({
ValidatorType.IS_GENERAL_WITH_CHINESE,
ValidatorType.IS_NOT_NULL
})
@ValidatorLenMax(20) @ValidatorLenMax(20)
private String carName; private String carName;
@ -50,7 +55,10 @@ public class TestCarModel extends ApiWrapper {
@ApiModelProperty(value = "汽车类型") @ApiModelProperty(value = "汽车类型")
@ExcelProperty(value = "汽车类型", order = 2) @ExcelProperty(value = "汽车类型", order = 2)
@ExcelInfo @ExcelInfo
@Validator({ValidatorType.IS_NOT_NULL, ValidatorType.IS_GENERAL_WITH_CHINESE}) @Validator({
ValidatorType.IS_GENERAL_WITH_CHINESE,
ValidatorType.IS_NOT_NULL
})
@ValidatorLenMax(20) @ValidatorLenMax(20)
private String carType; private String carType;
@ -58,7 +66,9 @@ public class TestCarModel extends ApiWrapper {
@ApiModelProperty(value = "汽车品牌") @ApiModelProperty(value = "汽车品牌")
@ExcelProperty(value = "汽车品牌", order = 3) @ExcelProperty(value = "汽车品牌", order = 3)
@ExcelInfo @ExcelInfo
@Validator({ValidatorType.IS_GENERAL_WITH_CHINESE}) @Validator({
ValidatorType.IS_GENERAL_WITH_CHINESE
})
@ValidatorLenMax(50) @ValidatorLenMax(50)
private String carBrand; private String carBrand;
@ -66,6 +76,9 @@ public class TestCarModel extends ApiWrapper {
@ApiModelProperty(value = "生产日期") @ApiModelProperty(value = "生产日期")
@ExcelProperty(value = "生产日期", order = 4) @ExcelProperty(value = "生产日期", order = 4)
@ExcelInfo @ExcelInfo
@Validator({
ValidatorType.IS_NOT_NULL
})
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd") @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd")
@DateTimeFormat(pattern = "yyyy-MM-dd") @DateTimeFormat(pattern = "yyyy-MM-dd")
private Date produceData; private Date produceData;
@ -74,9 +87,12 @@ public class TestCarModel extends ApiWrapper {
@ApiModelProperty(value = "是否启用") @ApiModelProperty(value = "是否启用")
@ExcelProperty(value = "是否启用", order = 5) @ExcelProperty(value = "是否启用", order = 5)
@ExcelInfo( dictType = "no_yes" ) @ExcelInfo( dictType = "no_yes" )
@Validator({
ValidatorType.IS_NOT_NULL
})
@ValidatorLenMax(1) @ValidatorLenMax(1)
private String izUsable; private String izUsable;
} }

@ -71,4 +71,10 @@ public class LoginLogsModel extends ApiWrapper {
@ApiModelProperty(value = "用户代理") @ApiModelProperty(value = "用户代理")
private String userAgent; private String userAgent;
/**
*
*/
@ApiModelProperty(value = "登陆来源")
private String loginFrom;
} }

@ -0,0 +1,132 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.api.wrapper.system.logs;
import java.math.BigDecimal;
import java.util.Date;
import com.alibaba.excel.annotation.ExcelProperty;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.opsli.api.base.warpper.ApiWrapper;
import org.opsli.common.annotation.validator.Validator;
import org.opsli.common.annotation.validator.ValidatorLenMax;
import org.opsli.common.annotation.validator.ValidatorLenMin;
import org.opsli.common.enums.ValidatorType;
import org.opsli.plugins.excel.annotation.ExcelInfo;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.springframework.format.annotation.DateTimeFormat;
/**
* Model
*
* @author Parker
* @date 2022-07-26 19:21:57
*/
@Data
@EqualsAndHashCode(callSuper = false)
public class OperationLogModel extends ApiWrapper {
/** 多租户字段 */
private String tenantId;
/** 日志等级 */
@ApiModelProperty(value = "日志等级")
@ExcelProperty(value = "日志等级", order = 1)
@ExcelInfo( dictType = "log_level" )
@ValidatorLenMax(8)
private String level;
/** 被操作的系统模块 */
@ApiModelProperty(value = "被操作的系统模块")
@ExcelProperty(value = "被操作的系统模块", order = 2)
@ExcelInfo( dictType = "log_model_type" )
@ValidatorLenMax(20)
private String moduleId;
/** 方法名 */
@ApiModelProperty(value = "方法名")
@ExcelProperty(value = "方法名", order = 3)
@ExcelInfo
@ValidatorLenMax(100)
private String method;
/** 参数 */
@ApiModelProperty(value = "参数")
@ExcelProperty(value = "参数", order = 4)
@ExcelInfo
@ValidatorLenMax(20000)
private String args;
/** 操作人id */
@ApiModelProperty(value = "操作人id")
@ExcelProperty(value = "操作人id", order = 5)
@ExcelInfo
@ValidatorLenMax(19)
private String userId;
/** 操作账号 */
@ApiModelProperty(value = "操作账号")
@ExcelProperty(value = "操作账号", order = 6)
@ExcelInfo
@ValidatorLenMax(32)
private String username;
/** 操作人真实名称 */
@ApiModelProperty(value = "操作人真实名称")
@ExcelProperty(value = "操作人真实名称", order = 7)
@ExcelInfo
@ValidatorLenMax(50)
private String realName;
/** 日志描述 */
@ApiModelProperty(value = "日志描述")
@ExcelProperty(value = "日志描述", order = 8)
@ExcelInfo
@ValidatorLenMax(255)
private String description;
/** 操作类型 */
@ApiModelProperty(value = "操作类型")
@ExcelProperty(value = "操作类型", order = 9)
@ExcelInfo( dictType = "log_operation_type" )
@ValidatorLenMax(20)
private String operationType;
/** 方法运行时间 */
@ApiModelProperty(value = "方法运行时间")
@ExcelProperty(value = "方法运行时间", order = 10)
@ExcelInfo
@ValidatorLenMax(19)
private String runTime;
/** 方法返回值 */
@ApiModelProperty(value = "方法返回值")
@ExcelProperty(value = "方法返回值", order = 11)
@ExcelInfo
@ValidatorLenMax(20000)
private String returnValue;
/** 日志请求类型 */
@ApiModelProperty(value = "日志请求类型")
@ExcelProperty(value = "日志请求类型", order = 12)
@ExcelInfo( dictType = "log_type" )
@ValidatorLenMax(8)
private String logType;
}

@ -38,8 +38,8 @@ import org.opsli.plugins.excel.annotation.ExcelInfo;
@EqualsAndHashCode(callSuper = false) @EqualsAndHashCode(callSuper = false)
public class OptionsModel extends ApiWrapper { public class OptionsModel extends ApiWrapper {
/** 参数编号 */ /** 参数编号 */
@ApiModelProperty(value = "参数编号") @ApiModelProperty(value = "参数编号")
@ExcelProperty(value = "参数编号", order = 1) @ExcelProperty(value = "参数编号", order = 1)
@ -57,21 +57,21 @@ public class OptionsModel extends ApiWrapper {
/** 参数值 */ /** 参数值 */
@ApiModelProperty(value = "参数值") @ApiModelProperty(value = "参数值")
@ExcelProperty(value = "参数值", order = 3) @ExcelProperty(value = "参数值", order = 4)
@ExcelInfo @ExcelInfo
@ValidatorLenMax(10000) @ValidatorLenMax(10000)
private String optionValue; private String optionValue;
/** 是否内置数据 0否 1是*/ /** 是否内置数据 0否 1是*/
@ApiModelProperty(value = "是否内置数据 0否 1是") @ApiModelProperty(value = "是否内置数据 0否 1是")
@ExcelProperty(value = "是否内置数据", order = 4) @ExcelProperty(value = "是否内置数据", order = 5)
@ExcelInfo(dictType = "no_yes") @ExcelInfo(dictType = "no_yes")
@ValidatorLenMax(1) @ValidatorLenMax(1)
private String izLock; private String izLock;
/** 备注 */ /** 备注 */
@ApiModelProperty(value = "备注") @ApiModelProperty(value = "备注")
@ExcelProperty(value = "备注", order = 5) @ExcelProperty(value = "备注", order = 6)
@ExcelInfo @ExcelInfo
@ValidatorLenMax(255) @ValidatorLenMax(255)
private String remark; private String remark;

@ -0,0 +1,42 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.api.wrapper.system.user;
import lombok.Data;
import org.opsli.common.annotation.validator.Validator;
import org.opsli.common.annotation.validator.ValidatorLenMax;
import org.opsli.common.enums.ValidatorType;
/**
*
*
* @author Parker
* @date 2022-07-16 8:14 PM
**/
@Data
public class EnableUserModel {
/** 主键 */
@Validator({ValidatorType.IS_NOT_NULL})
@ValidatorLenMax(50)
private String userId;
/** 是否启用 */
@Validator({ValidatorType.IS_NOT_NULL})
@ValidatorLenMax(10)
private String enabled;
}

@ -51,12 +51,6 @@ public class ToUserPassword implements Serializable {
@ValidatorLenMax(50) @ValidatorLenMax(50)
private String newPassword; private String newPassword;
/** 盐值,密码秘钥 前端不可改*/
@ApiModelProperty(value = "盐值,密码秘钥 前端不可改")
@ExcelIgnore
@ValidatorLenMax(50)
private String salt;
/** 登录密码强度 前端不可改 */ /** 登录密码强度 前端不可改 */
@ApiModelProperty(value = "登录密码强度 前端不可改") @ApiModelProperty(value = "登录密码强度 前端不可改")
@ExcelIgnore @ExcelIgnore

@ -0,0 +1,46 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.api.wrapper.system.user;
import lombok.Data;
import org.opsli.common.annotation.validator.Validator;
import org.opsli.common.annotation.validator.ValidatorLenMax;
import org.opsli.common.enums.ValidatorType;
/**
*
*
* @author Parker
* @date 2022-07-16 8:14 PM
**/
@Data
public class UpdateUserEmailModel {
/** 主键 */
@Validator({ValidatorType.IS_NOT_NULL, ValidatorType.IS_EMAIL})
@ValidatorLenMax(50)
private String email;
/** 验证码 */
@Validator({ValidatorType.IS_NOT_NULL})
@ValidatorLenMax(20)
private String verificationCode;
/** 凭证 */
@Validator({ValidatorType.IS_NOT_NULL})
private String certificate;
}

@ -0,0 +1,46 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.api.wrapper.system.user;
import lombok.Data;
import org.opsli.common.annotation.validator.Validator;
import org.opsli.common.annotation.validator.ValidatorLenMax;
import org.opsli.common.enums.ValidatorType;
/**
*
*
* @author Parker
* @date 2022-07-16 8:14 PM
**/
@Data
public class UpdateUserMobileModel {
/** 主键 */
@Validator({ValidatorType.IS_NOT_NULL, ValidatorType.IS_MOBILE})
@ValidatorLenMax(50)
private String mobile;
/** 验证码 */
@Validator({ValidatorType.IS_NOT_NULL})
@ValidatorLenMax(20)
private String verificationCode;
/** 凭证 */
@Validator({ValidatorType.IS_NOT_NULL})
private String certificate;
}

@ -0,0 +1,53 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.api.wrapper.system.user;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.opsli.common.annotation.validator.Validator;
import org.opsli.common.annotation.validator.ValidatorLenMax;
import org.opsli.common.annotation.validator.ValidatorLenMin;
import org.opsli.common.enums.ValidatorType;
import java.io.Serializable;
/**
*
*
* @author Parker
* @date 2020-09-16 17:33
*/
@Data
@EqualsAndHashCode(callSuper = false)
@ExcelIgnoreUnannotated
public class UpdateUserPasswordByForgetModel implements Serializable {
private static final long serialVersionUID = 1L;
/** 新密码 */
@ApiModelProperty(value = "新密码")
@Validator({ValidatorType.IS_NOT_NULL, ValidatorType.IS_SECURITY_PASSWORD})
@ValidatorLenMin(6)
@ValidatorLenMax(50)
private String newPassword;
/** 凭证 */
@Validator({ValidatorType.IS_NOT_NULL})
private String certificate;
}

@ -56,12 +56,12 @@ public class UserInfo extends ApiWrapper {
/** 手机 */ /** 手机 */
@ApiModelProperty(value = "手机") @ApiModelProperty(value = "手机")
@Validator({ValidatorType.IS_MOBILE}) @Validator({ValidatorType.IS_NOT_NULL, ValidatorType.IS_MOBILE})
private String mobile; private String mobile;
/** 邮箱 */ /** 邮箱 */
@ApiModelProperty(value = "邮箱") @ApiModelProperty(value = "邮箱")
@Validator({ValidatorType.IS_EMAIL}) @Validator({ValidatorType.IS_NOT_NULL, ValidatorType.IS_EMAIL})
private String email; private String email;
/** 工号 */ /** 工号 */

@ -60,12 +60,6 @@ public class UserModel extends ApiWrapper {
@ValidatorLenMax(1) @ValidatorLenMax(1)
private String passwordLevel; private String passwordLevel;
/** 盐值,密码秘钥 */
@ApiModelProperty(value = "盐值,密码秘钥")
@ExcelIgnore
@ValidatorLenMax(50)
private String secretKey;
/** 是否启用 */ /** 是否启用 */
@ApiModelProperty(value = "是否启用") @ApiModelProperty(value = "是否启用")
@ExcelIgnore @ExcelIgnore
@ -84,14 +78,14 @@ public class UserModel extends ApiWrapper {
@ApiModelProperty(value = "手机") @ApiModelProperty(value = "手机")
@ExcelProperty(value = "手机", order = 2) @ExcelProperty(value = "手机", order = 2)
@ExcelInfo @ExcelInfo
@Validator({ValidatorType.IS_MOBILE}) @Validator({ValidatorType.IS_NOT_NULL, ValidatorType.IS_MOBILE})
private String mobile; private String mobile;
/** 邮箱 */ /** 邮箱 */
@ApiModelProperty(value = "邮箱") @ApiModelProperty(value = "邮箱")
@ExcelProperty(value = "邮箱", order = 3) @ExcelProperty(value = "邮箱", order = 3)
@ExcelInfo @ExcelInfo
@Validator({ValidatorType.IS_EMAIL}) @Validator({ValidatorType.IS_NOT_NULL, ValidatorType.IS_EMAIL})
@ValidatorLenMax(100) @ValidatorLenMax(100)
private String email; private String email;

@ -58,12 +58,6 @@ public class UserPassword implements Serializable {
@ValidatorLenMax(50) @ValidatorLenMax(50)
private String newPassword; private String newPassword;
/** 盐值,密码秘钥 前端不可改*/
@ApiModelProperty(value = "盐值,密码秘钥 前端不可改")
@ExcelIgnore
@ValidatorLenMax(50)
private String salt;
/** 登录密码强度 前端不可改 */ /** 登录密码强度 前端不可改 */
@ApiModelProperty(value = "登录密码强度 前端不可改") @ApiModelProperty(value = "登录密码强度 前端不可改")
@ExcelIgnore @ExcelIgnore

@ -64,12 +64,6 @@ public class UserWebModel extends ApiWrapper {
@ValidatorLenMax(1) @ValidatorLenMax(1)
private String passwordLevel; private String passwordLevel;
/** 盐值,密码秘钥 */
@ApiModelProperty(value = "盐值,密码秘钥")
@ExcelIgnore
@ValidatorLenMax(50)
private String secretKey;
/** 启用状态 */ /** 启用状态 */
@ApiModelProperty(value = "启用状态") @ApiModelProperty(value = "启用状态")
@ExcelIgnore @ExcelIgnore

@ -22,4 +22,4 @@
</dependencies> </dependencies>
</project> </project>

@ -70,13 +70,20 @@ public class ResultVoMap extends HashMap<String,Object> implements Serializable
// ------------------------------------------- // -------------------------------------------
@JsonIgnore//返回对象时忽略此属性 /**
*
*/
@JsonIgnore
public static ResultVoMap success(String msg) { public static ResultVoMap success(String msg) {
ResultVoMap j = new ResultVoMap(); ResultVoMap j = new ResultVoMap();
j.setMsg(msg); j.setMsg(msg);
return j; return j;
} }
@JsonIgnore//返回对象时忽略此属性
/**
*
*/
@JsonIgnore//
public static ResultVoMap error(String msg) { public static ResultVoMap error(String msg) {
ResultVoMap j = new ResultVoMap(); ResultVoMap j = new ResultVoMap();
j.setSuccess(false); j.setSuccess(false);
@ -84,14 +91,20 @@ public class ResultVoMap extends HashMap<String,Object> implements Serializable
return j; return j;
} }
@JsonIgnore//返回对象时忽略此属性 /**
*
*/
@JsonIgnore
public static ResultVoMap success(Map<String, Object> map) { public static ResultVoMap success(Map<String, Object> map) {
ResultVoMap restResponse = new ResultVoMap(); ResultVoMap restResponse = new ResultVoMap();
restResponse.putAll(map); restResponse.putAll(map);
return restResponse; return restResponse;
} }
@JsonIgnore//返回对象时忽略此属性 /**
*
*/
@JsonIgnore
public static ResultVoMap success() { public static ResultVoMap success() {
return new ResultVoMap(); return new ResultVoMap();
} }

@ -3,7 +3,7 @@ package org.opsli.common.constants;
/** /**
* Redis * Redis
* {} * {}
* @author * @author Parker
* @date 2021/12/10 19:52 * @date 2021/12/10 19:52
*/ */
public final class RedisConstants { public final class RedisConstants {
@ -47,9 +47,12 @@ public final class RedisConstants {
/** 用户ID 和 菜单 */ /** 用户ID 和 菜单 */
public static final String PREFIX_USER_ID_MENUS = "kv#{}:user_id:menus:"; public static final String PREFIX_USER_ID_MENUS = "kv#{}:user_id:menus:";
/** 用户名 */ /** 用户名 + 用户ID */
public static final String PREFIX_USERNAME = "kv#{}:username:"; public static final String PREFIX_USER_USERNAME = "kv#{}:user:username_id:";
/** 手机号 + 用户ID */
public static final String PREFIX_USER_MOBILE = "kv#{}:user:mobile_id:";
/** 邮箱 + 用户ID */
public static final String PREFIX_USER_EMAIL = "kv#{}:user:email_id:";
/** 票据 */ /** 票据 */
@ -61,8 +64,21 @@ public final class RedisConstants {
/** 账号失败锁定KEY */ /** 账号失败锁定KEY */
public static final String PREFIX_ACCOUNT_SLIP_LOCK = "kv#{}:account:slip:lock:"; public static final String PREFIX_ACCOUNT_SLIP_LOCK = "kv#{}:account:slip:lock:";
/** 临时邮箱验证码 */
public static final String PREFIX_TMP_EMAIL_CODE_NAME = "kv#{}:verification:email:code:";
/** 临时手机验证码 */
public static final String PREFIX_TMP_MOBILE_CODE_NAME = "kv#{}:verification:mobile:code:";
/** 验证码凭证 用于验证码二次校验(唯一流水号 increment) */
public static final String PREFIX_TMP_VERIFICATION_CERTIFICATE_NUM_NAME = "kv#{}:verification:certificate-num";
/** 验证码凭证 用于验证码二次校验 */
public static final String PREFIX_TMP_VERIFICATION_CERTIFICATE_NAME = "kv#{}:verification:certificate:";
/** Excel 导出(唯一流水号 increment) */
public static final String PREFIX_TMP_EXCEL_EXPORT_NUM_NAME = "kv#{}:excel-export-num";
/** Excel 导出 凭证 */
public static final String PREFIX_TMP_EXCEL_EXPORT_NAME = "kv#{}:excel-export:";
private RedisConstants(){} private RedisConstants(){}
} }

@ -17,6 +17,9 @@ public final class SignConstants {
/** 租户ID */ /** 租户ID */
public static final String TENANT_ID = "tenantId"; public static final String TENANT_ID = "tenantId";
/** 登陆来源 */
public static final String LOGIN_FROM = "loginFrom";
/** 时间戳 */ /** 时间戳 */
public static final String TIMESTAMP = "timestamp"; public static final String TIMESTAMP = "timestamp";

@ -19,7 +19,7 @@ package org.opsli.common.enums;
/** /**
* *
* *
* @author : * @author : Parker
* @date : 2020-09-17 23:40 * @date : 2020-09-17 23:40
*/ */
public enum DictType { public enum DictType {

@ -0,0 +1,77 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.common.enums;
import cn.hutool.core.bean.BeanUtil;
import java.util.Arrays;
/**
*
*
* @author
* @date 2020-09-17 23:40
*/
public enum LoginFromEnum {
/** 账号 */
PC("0"),
/** APP - 安卓 */
APP_ANDROID("1"),
/** APP - 苹果 */
APP_IOS("2"),
/** 微信小程序 */
WX_APPLET("3"),
/** h5 */
H5("4"),
/** 未知 */
UNKNOWN("-1"),
;
private final static String FILED_NAME = "loginFrom";
/***/
private final String type;
LoginFromEnum(String type){
this.type = type;
}
public String getType() {
return this.type;
}
public static LoginFromEnum getByCode(String code){
return Arrays.stream(LoginFromEnum.values())
.filter(value -> value.getType().equals(code))
.findFirst().orElse(LoginFromEnum.UNKNOWN);
}
public static LoginFromEnum getByBean(Object bean){
if(null == bean || !BeanUtil.isBean(bean.getClass())){
return LoginFromEnum.UNKNOWN;
}
Object fieldValue = BeanUtil.getFieldValue(bean, FILED_NAME);
if(null == fieldValue){
return LoginFromEnum.UNKNOWN;
}
return getByCode((String) fieldValue);
}
}

@ -0,0 +1,61 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.common.enums;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.StrUtil;
/**
*
*
* @author Parker
* @date 2022-07-21 2:07 PM
**/
public enum LoginModelType {
/** 未知 */
UNKNOWN,
/** 账号 */
ACCOUNT,
/** 手机 */
MOBILE,
/** 邮箱 */
EMAIL
;
public static LoginModelType getTypeByStr(String principal){
if(StrUtil.isBlank(principal)){
return UNKNOWN;
}
// 手机号
if(Validator.isMobile(principal)){
return MOBILE;
}
// 邮箱
else if(Validator.isEmail(principal)){
return EMAIL;
}
// 默认账号
return ACCOUNT;
}
}

@ -0,0 +1,53 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.common.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Optional;
/**
*
*
* @author
* @date 2022-08-01 12:49 PM
**/
@AllArgsConstructor
@Getter
public enum VerificationTypeEnum {
/** 类型 */
LOGIN("0"),
AUTH("1")
;
/** 类型 */
private final String type;
public static Optional<VerificationTypeEnum> getEnumByType(String type){
VerificationTypeEnum[] types = values();
for (VerificationTypeEnum typeEnum : types) {
if(typeEnum.type.equals(type)){
return Optional.of(typeEnum);
}
}
return Optional.empty();
}
}

@ -32,7 +32,7 @@ import java.util.concurrent.atomic.AtomicInteger;
* 线线 * 线线
* 202111214:07:54 线 * 202111214:07:54 线
* *
* @author * @author Parker
* @date 2020-12-10 10:36 * @date 2020-12-10 10:36
*/ */
@Slf4j @Slf4j

@ -31,7 +31,7 @@ import java.util.concurrent.atomic.AtomicInteger;
* 线 * 线
* 线线 * 线线
* *
* @author * @author Parker
* @date 2020-12-10 10:36 * @date 2020-12-10 10:36
*/ */
@Slf4j @Slf4j

@ -1,3 +1,18 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.common.thread; package org.opsli.common.thread;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
@ -14,7 +29,7 @@ import java.util.function.Function;
/** /**
* 线 - 线 * 线 - 线
* *
* @author * @author Parker
* @date 2020-10-08 10:24 * @date 2020-10-08 10:24
*/ */
@Slf4j @Slf4j

@ -1,3 +1,18 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.common.thread; package org.opsli.common.thread;
import cn.hutool.core.thread.ThreadUtil; import cn.hutool.core.thread.ThreadUtil;
@ -11,7 +26,7 @@ import java.util.concurrent.ExecutorService;
/** /**
* 线 * 线
* *
* @author * @author Parker
* @date 2021/8/27 17:00 * @date 2021/8/27 17:00
*/ */
@Slf4j @Slf4j

@ -0,0 +1,388 @@
package org.opsli.common.utils;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Hashids designed for Generating short hashes from numbers (like YouTube and Bitly), obfuscate
* database IDs, use them as forgotten password hashes, invitation codes, store shard numbers.
* <p>
* This is implementation of http://hashids.org v1.0.0 version.
*
* This implementation is immutable, thread-safe, no lock is necessary.
*
* @author <a href="mailto:fanweixiao@gmail.com">fanweixiao</a>
* @author <a href="mailto:terciofilho@gmail.com">Tercio Gaudencio Filho</a>
* @since 0.3.3
*/
public class HashIdsUtil {
/**
* Max number that can be encoded with Hashids.
*/
public static final long MAX_NUMBER = 9007199254740992L;
private static final String DEFAULT_ALPHABET = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
private static final String DEFAULT_SEPS = "cfhistuCFHISTU";
private static final String DEFAULT_SALT = "";
private static final int DEFAULT_MIN_HASH_LENGTH = 0;
private static final int MIN_ALPHABET_LENGTH = 16;
private static final double SEP_DIV = 3.5;
private static final int GUARD_DIV = 12;
private final String salt;
private final int minHashLength;
private final String alphabet;
private final String seps;
private final String guards;
public HashIdsUtil() {
this(DEFAULT_SALT);
}
public HashIdsUtil(String salt) {
this(salt, 0);
}
public HashIdsUtil(String salt, int minHashLength) {
this(salt, minHashLength, DEFAULT_ALPHABET);
}
public HashIdsUtil(String salt, int minHashLength, String alphabet) {
this.salt = salt != null ? salt : DEFAULT_SALT;
this.minHashLength = minHashLength > 0 ? minHashLength : DEFAULT_MIN_HASH_LENGTH;
final StringBuilder uniqueAlphabet = new StringBuilder();
for (int i = 0; i < alphabet.length(); i++) {
if (uniqueAlphabet.indexOf(String.valueOf(alphabet.charAt(i))) == -1) {
uniqueAlphabet.append(alphabet.charAt(i));
}
}
alphabet = uniqueAlphabet.toString();
if (alphabet.length() < MIN_ALPHABET_LENGTH) {
throw new IllegalArgumentException(
"alphabet must contain at least " + MIN_ALPHABET_LENGTH + " unique characters");
}
if (alphabet.contains(" ")) {
throw new IllegalArgumentException("alphabet cannot contains spaces");
}
// seps should contain only characters present in alphabet;
// alphabet should not contains seps
String seps = DEFAULT_SEPS;
for (int i = 0; i < seps.length(); i++) {
final int j = alphabet.indexOf(seps.charAt(i));
if (j == -1) {
seps = seps.substring(0, i) + " " + seps.substring(i + 1);
} else {
alphabet = alphabet.substring(0, j) + " " + alphabet.substring(j + 1);
}
}
alphabet = alphabet.replaceAll("\\s+", "");
seps = seps.replaceAll("\\s+", "");
seps = HashIdsUtil.consistentShuffle(seps, this.salt);
if ((seps.isEmpty()) || (((float) alphabet.length() / seps.length()) > SEP_DIV)) {
int seps_len = (int) Math.ceil(alphabet.length() / SEP_DIV);
if (seps_len == 1) {
seps_len++;
}
if (seps_len > seps.length()) {
final int diff = seps_len - seps.length();
seps += alphabet.substring(0, diff);
alphabet = alphabet.substring(diff);
} else {
seps = seps.substring(0, seps_len);
}
}
alphabet = HashIdsUtil.consistentShuffle(alphabet, this.salt);
// use double to round up
final int guardCount = (int) Math.ceil((double) alphabet.length() / GUARD_DIV);
String guards;
if (alphabet.length() < 3) {
guards = seps.substring(0, guardCount);
seps = seps.substring(guardCount);
} else {
guards = alphabet.substring(0, guardCount);
alphabet = alphabet.substring(guardCount);
}
this.guards = guards;
this.alphabet = alphabet;
this.seps = seps;
}
/**
* Encrypt numbers to string
*
* @param numbers
* the numbers to encrypt
* @return the encrypt string
*/
public String encode(long... numbers) {
if (numbers.length == 0) {
return "";
}
for (final long number : numbers) {
if (number < 0) {
return "";
}
if (number > MAX_NUMBER) {
throw new IllegalArgumentException("number can not be greater than " + MAX_NUMBER + "L");
}
}
return this._encode(numbers);
}
/**
* Decrypt string to numbers
*
* @param hash
* the encrypt string
* @return decryped numbers
*/
public long[] decode(String hash) {
if (hash.isEmpty()) {
return new long[0];
}
String validChars = this.alphabet + this.guards + this.seps;
for (int i = 0; i < hash.length(); i++) {
if(validChars.indexOf(hash.charAt(i)) == -1) {
return new long[0];
}
}
return this._decode(hash, this.alphabet);
}
/**
* Encrypt hexa to string
*
* @param hexa
* the hexa to encrypt
* @return the encrypt string
*/
public String encodeHex(String hexa) {
if (!hexa.matches("^[0-9a-fA-F]+$")) {
return "";
}
final List<Long> matched = new ArrayList<Long>();
final Matcher matcher = Pattern.compile("[\\w\\W]{1,12}").matcher(hexa);
while (matcher.find()) {
matched.add(Long.parseLong("1" + matcher.group(), 16));
}
// conversion
final long[] result = new long[matched.size()];
for (int i = 0; i < matched.size(); i++) {
result[i] = matched.get(i);
}
return this.encode(result);
}
/**
* Decrypt string to numbers
*
* @param hash
* the encrypt string
* @return decryped numbers
*/
public String decodeHex(String hash) {
final StringBuilder result = new StringBuilder();
final long[] numbers = this.decode(hash);
for (final long number : numbers) {
result.append(Long.toHexString(number).substring(1));
}
return result.toString();
}
public static int checkedCast(long value) {
final int result = (int) value;
if (result != value) {
// don't use checkArgument here, to avoid boxing
throw new IllegalArgumentException("Out of range: " + value);
}
return result;
}
/* Private methods */
private String _encode(long... numbers) {
long numberHashInt = 0;
for (int i = 0; i < numbers.length; i++) {
numberHashInt += (numbers[i] % (i + 100));
}
String alphabet = this.alphabet;
final char ret = alphabet.charAt((int) (numberHashInt % alphabet.length()));
long num;
long sepsIndex, guardIndex;
String buffer;
final StringBuilder ret_strB = new StringBuilder(this.minHashLength);
ret_strB.append(ret);
char guard;
for (int i = 0; i < numbers.length; i++) {
num = numbers[i];
buffer = ret + this.salt + alphabet;
alphabet = HashIdsUtil.consistentShuffle(alphabet, buffer.substring(0, alphabet.length()));
final String last = HashIdsUtil.hash(num, alphabet);
ret_strB.append(last);
if (i + 1 < numbers.length) {
if (last.length() > 0) {
num %= (last.charAt(0) + i);
sepsIndex = (int) (num % this.seps.length());
} else {
sepsIndex = 0;
}
ret_strB.append(this.seps.charAt((int) sepsIndex));
}
}
String ret_str = ret_strB.toString();
if (ret_str.length() < this.minHashLength) {
guardIndex = (numberHashInt + (ret_str.charAt(0))) % this.guards.length();
guard = this.guards.charAt((int) guardIndex);
ret_str = guard + ret_str;
if (ret_str.length() < this.minHashLength) {
guardIndex = (numberHashInt + (ret_str.charAt(2))) % this.guards.length();
guard = this.guards.charAt((int) guardIndex);
ret_str += guard;
}
}
final int halfLen = alphabet.length() / 2;
while (ret_str.length() < this.minHashLength) {
alphabet = HashIdsUtil.consistentShuffle(alphabet, alphabet);
ret_str = alphabet.substring(halfLen) + ret_str + alphabet.substring(0, halfLen);
final int excess = ret_str.length() - this.minHashLength;
if (excess > 0) {
final int start_pos = excess / 2;
ret_str = ret_str.substring(start_pos, start_pos + this.minHashLength);
}
}
return ret_str;
}
private long[] _decode(String hash, String alphabet) {
final ArrayList<Long> ret = new ArrayList<Long>();
int i = 0;
final String regexp = "[" + this.guards + "]";
String hashBreakdown = hash.replaceAll(regexp, " ");
String[] hashArray = hashBreakdown.split(" ");
if (hashArray.length == 3 || hashArray.length == 2) {
i = 1;
}
if (hashArray.length > 0) {
hashBreakdown = hashArray[i];
if (!hashBreakdown.isEmpty()) {
final char lottery = hashBreakdown.charAt(0);
hashBreakdown = hashBreakdown.substring(1);
hashBreakdown = hashBreakdown.replaceAll("[" + this.seps + "]", " ");
hashArray = hashBreakdown.split(" ");
String subHash, buffer;
for (final String aHashArray : hashArray) {
subHash = aHashArray;
buffer = lottery + this.salt + alphabet;
alphabet = HashIdsUtil.consistentShuffle(alphabet, buffer.substring(0, alphabet.length()));
ret.add(HashIdsUtil.unhash(subHash, alphabet));
}
}
}
// transform from List<Long> to long[]
long[] arr = new long[ret.size()];
for (int k = 0; k < arr.length; k++) {
arr[k] = ret.get(k);
}
if (!this.encode(arr).equals(hash)) {
arr = new long[0];
}
return arr;
}
private static String consistentShuffle(String alphabet, String salt) {
if (salt.length() <= 0) {
return alphabet;
}
int asc_val, j;
final char[] tmpArr = alphabet.toCharArray();
for (int i = tmpArr.length - 1, v = 0, p = 0; i > 0; i--, v++) {
v %= salt.length();
asc_val = salt.charAt(v);
p += asc_val;
j = (asc_val + v + p) % i;
final char tmp = tmpArr[j];
tmpArr[j] = tmpArr[i];
tmpArr[i] = tmp;
}
return new String(tmpArr);
}
private static String hash(long input, String alphabet) {
String hash = "";
final int alphabetLen = alphabet.length();
do {
final int index = (int) (input % alphabetLen);
if (index >= 0 && index < alphabet.length()) {
hash = alphabet.charAt(index) + hash;
}
input /= alphabetLen;
} while (input > 0);
return hash;
}
private static Long unhash(String input, String alphabet) {
long number = 0, pos;
for (int i = 0; i < input.length(); i++) {
pos = alphabet.indexOf(input.charAt(i));
number = number * alphabet.length() + pos;
}
return number;
}
/**
* Get Hashid algorithm version.
*
* @return Hashids algorithm version implemented.
*/
public String getVersion() {
return "1.0.0";
}
}

@ -15,6 +15,8 @@
*/ */
package org.opsli.common.utils; package org.opsli.common.utils;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.StrUtil;
import com.google.common.cache.Cache; import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheBuilder;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
@ -25,7 +27,6 @@ import org.opsli.common.thread.AsyncProcessExecutor;
import org.opsli.common.thread.AsyncProcessExecutorFactory; import org.opsli.common.thread.AsyncProcessExecutorFactory;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import java.time.Duration;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -39,6 +40,8 @@ import java.util.concurrent.TimeUnit;
@Slf4j @Slf4j
public final class RateLimiterUtil { public final class RateLimiterUtil {
/** 默认IP */
public static final String DEFAULT_IP = "unknown";
/** 默认QPS */ /** 默认QPS */
public static final double DEFAULT_QPS = 10d; public static final double DEFAULT_QPS = 10d;
/** 默认缓存个数 超出后流量自动清理 */ /** 默认缓存个数 超出后流量自动清理 */
@ -46,7 +49,7 @@ public final class RateLimiterUtil {
/** 默认缓存时效 超出后自动清理 */ /** 默认缓存时效 超出后自动清理 */
private static final int DEFAULT_CACHE_TIME = 5; private static final int DEFAULT_CACHE_TIME = 5;
/** 默认等待时长 */ /** 默认等待时长 */
private static final int DEFAULT_WAIT = 5000; private static final int DEFAULT_WAIT = 500;
/** 限流器单机缓存 */ /** 限流器单机缓存 */
private static final Cache<String, Map<String, RateLimiterUtil.RateLimiterInner> > LFU_CACHE; private static final Cache<String, Map<String, RateLimiterUtil.RateLimiterInner> > LFU_CACHE;
@ -108,6 +111,11 @@ public final class RateLimiterUtil {
*/ */
@SuppressWarnings("UnstableApiUsage") @SuppressWarnings("UnstableApiUsage")
public static boolean enter(String clientIpAddress, String resource, Double dfQps) { public static boolean enter(String clientIpAddress, String resource, Double dfQps) {
// IP 为空补偿器
if(StrUtil.isBlank(clientIpAddress)){
clientIpAddress = DEFAULT_IP;
}
// 计时器 // 计时器
long t1 = System.currentTimeMillis(); long t1 = System.currentTimeMillis();
@ -152,7 +160,7 @@ public final class RateLimiterUtil {
RateLimiter rateLimiter = rateLimiterObj.getRateLimiter(); RateLimiter rateLimiter = rateLimiterObj.getRateLimiter();
//非阻塞 //非阻塞
if (!rateLimiter.tryAcquire(Duration.ofMillis(DEFAULT_WAIT))) { if (!rateLimiter.tryAcquire(DEFAULT_WAIT, TimeUnit.MILLISECONDS)) {
//限速中,提示用户 //限速中,提示用户
log.error("限流器 - 访问频繁 耗时: "+ (System.currentTimeMillis() - t1) + "ms, IP地址: " + clientIpAddress + ", URI: " + resource); log.error("限流器 - 访问频繁 耗时: "+ (System.currentTimeMillis() - t1) + "ms, IP地址: " + clientIpAddress + ", URI: " + resource);
return false; return false;
@ -183,18 +191,40 @@ public final class RateLimiterUtil {
public static void main(String[] args) { public static void main(String[] args) {
int count = 500; // int count = 500;
RateLimiterUtil.removeIp("127.0.0.1"); // RateLimiterUtil.removeIp("127.0.0.1");
AsyncProcessExecutor normalExecutor = AsyncProcessExecutorFactory.createNormalExecutor(); // AsyncProcessExecutor normalExecutor = AsyncProcessExecutorFactory.createNormalExecutor();
for (int i = 0; i < count; i++) { // for (int i = 0; i < count; i++) {
normalExecutor.put(()->{ // normalExecutor.put(()->{
boolean enter = RateLimiterUtil.enter("127.0.0.1","/api/v1", 2d); // RateLimiter rateLimiter = RateLimiter.create(1);
System.out.println(enter); //
}); //
// boolean enter = RateLimiterUtil.enter("127.0.0.1","/api/v1", 2d);
// System.out.println(enter);
// });
// }
// normalExecutor.execute();
int count = 3;
RateLimiter rateLimiter = RateLimiter.create(count);
AsyncProcessExecutor normalExecutor = AsyncProcessExecutorFactory.createWaitExecutor();
int num = 0;
while (true){
System.out.println("------------"+ (++num) +"------------");
for (int i = 0; i < count+1; i++) {
normalExecutor.put(()->{
boolean tryAcquire = rateLimiter.tryAcquire(500, TimeUnit.MILLISECONDS);
System.out.println(tryAcquire);
});
}
normalExecutor.execute();
ThreadUtil.sleep(1100);
} }
normalExecutor.execute();
} }
} }

@ -0,0 +1,48 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.common.utils;
import cn.hutool.core.util.RandomUtil;
/**
*
* <a href="https://huzb.me/2018/03/23/%E7%AE%80%E5%8D%95%E7%9A%84%E5%AF%86%E7%A0%81%E5%AD%A6%E7%94%9F%E6%88%90%E5%94%AF%E4%B8%80%E9%82%80%E8%AF%B7%E7%A0%81">...</a>
*
* @author Parker
* @date 20220711 14:07
*/
public final class UniqueStrGeneratorUtils {
private static final String BEGIN_SALT = "opsli_2022_begin";
private static final String END_SALT = "opsli_2022_end";
private static final String CONTENT_SALT = "opsli_2022";
private static final HashIdsUtil DISTURB_HASH_ID_BEGIN = new HashIdsUtil(BEGIN_SALT, 2);
private static final HashIdsUtil DISTURB_HASH_ID_END = new HashIdsUtil(END_SALT, 3);
private static final HashIdsUtil CONTENT_HASH_ID = new HashIdsUtil(CONTENT_SALT, 7);
/** 生成 */
public static String generator(long i) {
int begin = RandomUtil.randomInt(0, 10);
int end = RandomUtil.randomInt(10, 100);
String disturbHashIdBeginStr = DISTURB_HASH_ID_BEGIN.encode(begin);
String disturbHashIdEndStr = DISTURB_HASH_ID_END.encode(end);
String contentHashIdStr = CONTENT_HASH_ID.encode(i);
return disturbHashIdBeginStr + contentHashIdStr + disturbHashIdEndStr;
}
}

@ -48,6 +48,13 @@
<version>${plugins.version}</version> <version>${plugins.version}</version>
</dependency> </dependency>
<!-- 引入短信插件 -->
<dependency>
<groupId>org.opsliframework.boot</groupId>
<artifactId>opsli-plugins-sms</artifactId>
<version>${plugins.version}</version>
</dependency>
<!-- 引入Redis插件 --> <!-- 引入Redis插件 -->
<dependency> <dependency>
<groupId>org.opsliframework.boot</groupId> <groupId>org.opsliframework.boot</groupId>
@ -55,6 +62,13 @@
<version>${plugins.version}</version> <version>${plugins.version}</version>
</dependency> </dependency>
<!-- 引入Security插件 -->
<dependency>
<groupId>org.opsliframework.boot</groupId>
<artifactId>opsli-plugins-security</artifactId>
<version>${plugins.version}</version>
</dependency>
<!-- 引入Redisson插件 --> <!-- 引入Redisson插件 -->
<dependency> <dependency>
<groupId>org.opsliframework.boot</groupId> <groupId>org.opsliframework.boot</groupId>
@ -78,12 +92,6 @@
<!-- ———————————————————— 集成Shiro鉴权安全认证 - 开始 ———————————————————— --> <!-- ———————————————————— 集成Shiro鉴权安全认证 - 开始 ———————————————————— -->
<!-- ShiroRedis包 -->
<dependency>
<groupId>org.crazycake</groupId>
<artifactId>shiro-redis-spring-boot-starter</artifactId>
</dependency>
<!-- captcha 验证码 --> <!-- captcha 验证码 -->
<dependency> <dependency>
<groupId>com.github.whvcse</groupId> <groupId>com.github.whvcse</groupId>
@ -96,6 +104,11 @@
<artifactId>java-jwt</artifactId> <artifactId>java-jwt</artifactId>
</dependency> </dependency>
<dependency>
<groupId>com.jfinal</groupId>
<artifactId>enjoy</artifactId>
</dependency>
<!-- ———————————————————— 集成Shiro鉴权安全认证 - 结束 ———————————————————— --> <!-- ———————————————————— 集成Shiro鉴权安全认证 - 结束 ———————————————————— -->
<!-- ———————————————————— 集成数据库相关配置 - 开始 ———————————————————— --> <!-- ———————————————————— 集成数据库相关配置 - 开始 ———————————————————— -->
@ -127,7 +140,20 @@
<dependency> <dependency>
<groupId>mysql</groupId> <groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId> <artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
<scope>runtime</scope> <scope>runtime</scope>
<exclusions>
<!-- 修复 CVE-2021-22569 -->
<exclusion>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- 修复 CVE-2021-22569 -->
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
</dependency> </dependency>
<!-- sqlserver--> <!-- sqlserver-->
@ -149,6 +175,7 @@
<groupId>org.postgresql</groupId> <groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId> <artifactId>postgresql</artifactId>
<scope>runtime</scope> <scope>runtime</scope>
<version>${postgresql.version}</version>
</dependency> </dependency>
<!-- ———————————————————— 集成数据库相关配置 - 结束 ———————————————————— --> <!-- ———————————————————— 集成数据库相关配置 - 结束 ———————————————————— -->

@ -0,0 +1,46 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.core.autoconfigure.conf;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* Cors
*
* @author Parker
* @date 2022071412:57:33
**/
@Configuration
public class CorsConfig implements WebMvcConfigurer {
/**
*
*
* @param registry registry
*/
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOriginPatterns("*")
.allowedMethods("GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS")
.allowedHeaders("*")
.allowCredentials(true)
.maxAge(7200);
}
}

@ -15,7 +15,8 @@
*/ */
package org.opsli.core.autoconfigure.conf; package org.opsli.core.autoconfigure.conf;
import com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor; import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactory;
import org.opsli.core.filters.interceptor.MybatisAutoFillInterceptor; import org.opsli.core.filters.interceptor.MybatisAutoFillInterceptor;
@ -35,13 +36,20 @@ import org.springframework.transaction.annotation.EnableTransactionManagement;
@Configuration @Configuration
public class MyBatisPlusConfig { public class MyBatisPlusConfig {
/*** /**
* *
* @return
*/ */
@Bean @Bean
public OptimisticLockerInterceptor optimisticLockerInterceptor(){ public MybatisPlusInterceptor mybatisPlusInterceptor() {
return new OptimisticLockerInterceptor(); MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
// 乐观锁
mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
// 防止全表更新与删除插件
//mybatisPlusInterceptor.addInnerInterceptor(new BlockAttackInnerInterceptor());
return mybatisPlusInterceptor;
} }
/** /**

@ -0,0 +1,141 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.core.autoconfigure.conf;
import cn.hutool.extra.spring.SpringUtil;
import com.google.common.collect.Lists;
import lombok.AllArgsConstructor;
import org.opsli.core.security.filter.JwtAuthenticationTokenFilter;
import org.opsli.core.security.service.UidUserDetailDetailServiceImpl;
import org.opsli.plugins.security.exception.handler.AccessDeniedHandlerImpl;
import org.opsli.plugins.security.exception.handler.AuthenticationEntryPointImpl;
import org.opsli.plugins.security.properties.AuthProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import java.util.List;
import java.util.Map;
/**
* Security
*
* @author Parker
* @date 2022071412:57:33
**/
@AllArgsConstructor
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled=true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private final AuthProperties authProperties;
private final AccessDeniedHandlerImpl accessDeniedHandler;
private final AuthenticationEntryPointImpl authenticationEntryPoint;
private final UidUserDetailDetailServiceImpl uidUserDetailDetailService;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.headers()
// 默认关闭 Security 的 xss防护与系统本身的 xss防护冲突
.xssProtection().disable()
// 允许Iframe加载
.frameOptions().disable()
.and()
// 关闭csrf token认证不需要csrf防护
.csrf().disable();
// 初始化 initAuthorizeRequests
this.initAuthorizeRequests(http);
}
/**
* URL
* @param http http
*/
private void initAuthorizeRequests(HttpSecurity http) throws Exception {
// 设置URL 未登陆前可访问URL
List<String> anonymousList = authProperties.getUrlExclusion().getAnonymous();
if(null != anonymousList){
String[] urlExclusionArray = anonymousList.toArray(new String[0]);
http.authorizeRequests()
// URL 未登陆前可访问
.antMatchers(urlExclusionArray).anonymous();
}
// 设置URL白名单
List<String> permitAll = authProperties.getUrlExclusion().getPermitAll();
if(null != permitAll){
String[] urlExclusionArray = permitAll.toArray(new String[0]);
http.authorizeRequests()
// URL 白名单
.antMatchers(urlExclusionArray).permitAll();
}
// 除上面外的所有请求全部需要鉴权认证
http.authorizeRequests()
.anyRequest().authenticated();
// 添加过滤器
// 注意 自定义 Filter 不要交给 Spring管理
http.addFilterBefore(new JwtAuthenticationTokenFilter(uidUserDetailDetailService),
UsernamePasswordAuthenticationFilter.class);
// 异常处理
http.exceptionHandling()
.accessDeniedHandler(accessDeniedHandler)
.authenticationEntryPoint(authenticationEntryPoint);
}
/**
*
*/
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Override
protected AuthenticationManager authenticationManager() {
// 设置 多Provider
Map<String, AuthenticationProvider> providerMap =
SpringUtil.getBeansOfType(AuthenticationProvider.class);
List<AuthenticationProvider> authenticationProviderList =
Lists.newArrayListWithCapacity(providerMap.size());
for (Map.Entry<String, AuthenticationProvider> providerEntry : providerMap.entrySet()) {
authenticationProviderList.add(providerEntry.getValue());
}
ProviderManager authenticationManager = new ProviderManager(authenticationProviderList);
//不擦除认证密码擦除会导致TokenBasedRememberMeServices因为找不到Credentials再调用UserDetailsService而抛出UsernameNotFoundException
authenticationManager.setEraseCredentialsAfterAuthentication(false);
return authenticationManager;
}
}

@ -1,198 +0,0 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.core.autoconfigure.conf;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ClassUtil;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.apache.shiro.authc.pam.AtLeastOneSuccessfulStrategy;
import org.apache.shiro.authc.pam.ModularRealmAuthenticator;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.opsli.core.autoconfigure.properties.ApiPathProperties;
import org.opsli.core.autoconfigure.properties.GlobalProperties;
import org.opsli.core.security.shiro.authenticator.CustomModularRealmAuthenticator;
import org.opsli.core.security.shiro.filter.CustomShiroFilter;
import org.opsli.core.security.shiro.realm.FlagRealm;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import javax.servlet.Filter;
import java.lang.reflect.Modifier;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Shiro
*
* token -
*
* @author Parker
* @date 2017-04-20 18:33
*/
@Configuration
public class ShiroConfig {
/**
* filer
* @param securityManager
* @return ShiroFilterFactoryBean
*/
@Bean("shiroFilter")
public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager,
GlobalProperties globalProperties, ApiPathProperties apiPathProperties) {
ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();
shiroFilter.setSecurityManager(securityManager);
//oauth过滤
Map<String, Filter> filters = Maps.newHashMapWithExpectedSize(1);
filters.put("last_filter", new CustomShiroFilter());
shiroFilter.setFilters(filters);
Map<String, String> filterMap = Maps.newLinkedHashMap();
// 加载排除URL
if(globalProperties.getAuth() != null &&
globalProperties.getAuth().getToken() != null){
Set<String> urlExclusion = globalProperties.getAuth().getToken().getUrlExclusion();
if(CollUtil.isNotEmpty(urlExclusion)){
for (String excUrl : urlExclusion) {
filterMap.put(excUrl, "anon");
}
}
}
// 登录接口拦截
filterMap.put("/system/login", "anon");
filterMap.put("/system/publicKey", "anon");
filterMap.put("/system/slipCount", "anon");
filterMap.put("/captcha*", "anon");
// 导出Excel\模版 不做自动拦截 手动拦截
filterMap.put(apiPathProperties.getGlobalPrefix() + "/**/exportExcel", "anon");
filterMap.put(apiPathProperties.getGlobalPrefix() + "/**/importExcel/template", "anon");
filterMap.put("/webjars/**", "anon");
filterMap.put("/druid/**", "anon");
filterMap.put("/app/**", "anon");
filterMap.put("/swagger/**", "anon");
filterMap.put("/v2/api-docs", "anon");
filterMap.put("/doc.html", "anon");
filterMap.put("/swagger-ui.html", "anon");
filterMap.put("/swagger-resources/**", "anon");
filterMap.put("/**", "last_filter");
shiroFilter.setFilterChainDefinitionMap(filterMap);
return shiroFilter;
}
@Bean("sessionManager")
public SessionManager sessionManager(){
DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
sessionManager.setSessionValidationSchedulerEnabled(true);
sessionManager.setSessionIdCookieEnabled(true);
return sessionManager;
}
@Bean("securityManager")
public DefaultWebSecurityManager securityManager(SessionManager sessionManager) {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setSessionManager(sessionManager);
// 设置验证器为自定义验证器
securityManager.setAuthenticator(modularRealmAuthenticator());
List<Realm> realms = Lists.newArrayList();
// 拿到state包下 实现了 FlagRealm 接口的,所有子类
Set<Class<?>> clazzSet = ClassUtil.scanPackageBySuper(
FlagRealm.class.getPackage().getName(),
FlagRealm.class
);
for (Class<?> aClass : clazzSet) {
// 位运算 去除抽象类
if((aClass.getModifiers() & Modifier.ABSTRACT) != 0){
continue;
}
try {
realms.add((Realm) aClass.newInstance());
} catch (Exception ignored){ }
}
if(CollUtil.isNotEmpty(realms)){
// 追加 Realms
securityManager.setRealms(realms);
}
return securityManager;
}
/**
* Realm使
*/
@Bean("modularRealmAuthenticator")
public ModularRealmAuthenticator modularRealmAuthenticator(){
CustomModularRealmAuthenticator authenticator = new CustomModularRealmAuthenticator();
authenticator.setAuthenticationStrategy(new AtLeastOneSuccessfulStrategy());
return authenticator;
}
// ===================== 固定三板斧 =====================
// 其实 没有 Spring Security 配置起来简单
//
@Bean("lifecycleBeanPostProcessor")
public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
return new LifecycleBeanPostProcessor();
}
@Bean("defaultAdvisorAutoProxyCreator")
@DependsOn("lifecycleBeanPostProcessor")
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
DefaultAdvisorAutoProxyCreator proxyCreator = new DefaultAdvisorAutoProxyCreator();
proxyCreator.setProxyTargetClass(true);
proxyCreator.setUsePrefix(true);
proxyCreator.setAdvisorBeanNamePrefix("_no_advisor");
return proxyCreator;
}
/**
* shiro
* @param securityManager
* @return AuthorizationAttributeSourceAdvisor
*/
@Bean("authorizationAttributeSourceAdvisor")
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
advisor.setSecurityManager(securityManager);
return advisor;
}
}

@ -26,6 +26,7 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource; import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter; import org.springframework.web.filter.CorsFilter;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer; import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@ -67,23 +68,18 @@ public class SpringWebMvcConfig implements WebMvcConfigurer, WebMvcRegistrations
/** /**
* *
* @return CorsFilter *
* @param registry registry
*/ */
@Bean // @Override
public CorsFilter corsFilter() { // public void addCorsMappings(CorsRegistry registry) {
final UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new UrlBasedCorsConfigurationSource(); // registry.addMapping("/**")
final CorsConfiguration corsConfiguration = new CorsConfiguration(); // .allowedOriginPatterns("*")
/* 是否允许请求带有验证信息 */ // .allowedMethods("GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS")
corsConfiguration.setAllowCredentials(true); // .allowedHeaders("*")
/* 允许访问的客户端域名 */ // .allowCredentials(true)
corsConfiguration.addAllowedOrigin("*"); // .maxAge(7200);
/* 允许服务端访问的客户端请求头 */ // }
corsConfiguration.addAllowedHeader("*");
/* 允许访问的方法名,GET POST等 */
corsConfiguration.addAllowedMethod("*");
urlBasedCorsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration);
return new CorsFilter(urlBasedCorsConfigurationSource);
}
@Override @Override
public void addInterceptors(InterceptorRegistry registry) { public void addInterceptors(InterceptorRegistry registry) {

@ -18,6 +18,7 @@ package org.opsli.core.autoconfigure.properties;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
/** /**
@ -26,7 +27,7 @@ import org.springframework.stereotype.Component;
* @author Parker * @author Parker
* @date 2020-09-15 * @date 2020-09-15
*/ */
@Component @Configuration
@ConfigurationProperties(prefix = ApiPathProperties.PROP_PREFIX) @ConfigurationProperties(prefix = ApiPathProperties.PROP_PREFIX)
@Data @Data
@EqualsAndHashCode(callSuper = false) @EqualsAndHashCode(callSuper = false)

@ -18,6 +18,7 @@ package org.opsli.core.autoconfigure.properties;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
/** /**
@ -26,7 +27,7 @@ import org.springframework.stereotype.Component;
* @author Parker * @author Parker
* @date 2020-09-15 * @date 2020-09-15
*/ */
@Component @Configuration
@ConfigurationProperties(prefix = CacheProperties.PROP_PREFIX) @ConfigurationProperties(prefix = CacheProperties.PROP_PREFIX)
@Data @Data
@EqualsAndHashCode(callSuper = false) @EqualsAndHashCode(callSuper = false)

@ -0,0 +1,25 @@
package org.opsli.core.autoconfigure.properties;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
/**
*
*
* @author Parker
* @date 2022-08-07
*/
@Configuration
@ConfigurationProperties(prefix = EncryptProperties.PROP_PREFIX)
@Data
@EqualsAndHashCode(callSuper = false)
public class EncryptProperties {
public static final String PROP_PREFIX = "opsli.data-encrypt";
/** 秘钥 */
private String key;
}

@ -90,9 +90,6 @@ public class GlobalProperties {
/** 有效时间 (分钟)*/ /** 有效时间 (分钟)*/
private Integer effectiveTime; private Integer effectiveTime;
/** 排除URL*/
private Set<String> urlExclusion;
} }
/** /**

@ -0,0 +1,44 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.core.autoconfigure.properties;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
/**
* Token
*
* @author Parker
* @date 2020-09-15
*/
@Configuration
@ConfigurationProperties(prefix = TokenProperties.PROP_PREFIX)
@Data
@EqualsAndHashCode(callSuper = false)
public class TokenProperties {
public static final String PROP_PREFIX = "opsli.auth.token";
/** 盐 */
private String secret;
/** 有效时间 */
private int effectiveTime;
}

@ -16,7 +16,6 @@
package org.opsli.core.base.controller; package org.opsli.core.base.controller;
import cn.hutool.core.annotation.AnnotationUtil;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil; import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.convert.Convert; import cn.hutool.core.convert.Convert;
@ -24,36 +23,42 @@ import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.TimeInterval; import cn.hutool.core.date.TimeInterval;
import cn.hutool.core.lang.tree.Tree; import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.alibaba.excel.support.ExcelTypeEnum; import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.excel.util.CollectionUtils; import com.alibaba.excel.util.CollectionUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.opsli.api.base.result.ResultVo; import org.opsli.api.base.result.ResultWrapper;
import org.opsli.api.base.warpper.ApiWrapper; import org.opsli.api.base.warpper.ApiWrapper;
import org.opsli.api.wrapper.system.user.UserModel; import org.opsli.api.wrapper.system.user.UserModel;
import org.opsli.common.annotation.RequiresPermissionsCus; import org.opsli.common.constants.RedisConstants;
import org.opsli.common.annotation.hotdata.EnableHotData;
import org.opsli.common.constants.TreeConstants; import org.opsli.common.constants.TreeConstants;
import org.opsli.common.enums.ExcelOperate; import org.opsli.common.enums.ExcelOperate;
import org.opsli.common.exception.ServiceException; import org.opsli.common.exception.ServiceException;
import org.opsli.common.exception.TokenException; import org.opsli.common.utils.UniqueStrGeneratorUtils;
import org.opsli.common.utils.OutputStreamUtil;
import org.opsli.common.utils.WrapperUtil; import org.opsli.common.utils.WrapperUtil;
import org.opsli.core.autoconfigure.properties.GlobalProperties; import org.opsli.core.autoconfigure.properties.GlobalProperties;
import org.opsli.core.base.entity.BaseEntity; import org.opsli.core.base.entity.BaseEntity;
import org.opsli.core.base.entity.HasChildren; import org.opsli.core.base.entity.HasChildren;
import org.opsli.core.base.service.interfaces.CrudServiceInterface; import org.opsli.core.base.service.interfaces.CrudServiceInterface;
import org.opsli.core.cache.CacheUtil;
import org.opsli.core.msg.CoreMsg; import org.opsli.core.msg.CoreMsg;
import org.opsli.core.msg.TokenMsg; import org.opsli.core.persistence.querybuilder.QueryBuilder;
import org.opsli.core.security.shiro.realm.JwtRealm; import org.opsli.core.persistence.querybuilder.WebQueryBuilder;
import org.opsli.core.utils.ExcelUtil; import org.opsli.core.utils.ExcelUtil;
import org.opsli.core.utils.UserUtil; import org.opsli.core.utils.UserUtil;
import org.opsli.plugins.excel.exception.ExcelPluginException; import org.opsli.plugins.excel.exception.ExcelPluginException;
import org.opsli.plugins.excel.listener.BatchExcelListener; import org.opsli.plugins.excel.listener.BatchExcelListener;
import org.opsli.plugins.redis.RedisPlugin;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestParam;
@ -61,10 +66,11 @@ import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest; import org.springframework.web.multipart.MultipartHttpServletRequest;
import javax.annotation.PostConstruct; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method; import java.io.Serializable;
import java.util.*; import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.function.Function; import java.util.function.Function;
/** /**
@ -77,14 +83,8 @@ import java.util.function.Function;
@RestController @RestController
public abstract class BaseRestController <T extends BaseEntity, E extends ApiWrapper, S extends CrudServiceInterface<T,E>>{ public abstract class BaseRestController <T extends BaseEntity, E extends ApiWrapper, S extends CrudServiceInterface<T,E>>{
/** 开启热点数据状态 */ /** 凭证 10分钟失效 */
protected boolean hotDataFlag = false; private static final int CERTIFICATE_EXPIRED_MINUTE = 10;
/** Entity Clazz 类 */
protected Class<T> entityClazz;
/** Model Clazz 类 */
protected Class<E> modelClazz;
/** 配置类 */ /** 配置类 */
@Autowired @Autowired
@ -94,6 +94,10 @@ public abstract class BaseRestController <T extends BaseEntity, E extends ApiWra
@Autowired(required = false) @Autowired(required = false)
protected S IService; protected S IService;
/** Redis 类 */
@Autowired
private RedisPlugin redisPlugin;
/** /**
* *
* id * id
@ -103,15 +107,18 @@ public abstract class BaseRestController <T extends BaseEntity, E extends ApiWra
*/ */
@ModelAttribute @ModelAttribute
public E get(@RequestParam(required=false) String id) { public E get(@RequestParam(required=false) String id) {
if(StrUtil.isEmpty(id)){
return null;
}
return IService.get(id); return IService.get(id);
} }
/** /**
* Excel * Excel
* @param request request * @param request request
* @return ResultVo * @return ResultWrapper
*/ */
protected ResultVo<?> importExcel(MultipartHttpServletRequest request){ protected ResultWrapper<?> importExcel(MultipartHttpServletRequest request){
// 计时器 // 计时器
TimeInterval timer = DateUtil.timer(); TimeInterval timer = DateUtil.timer();
Iterator<String> itr = request.getFileNames(); Iterator<String> itr = request.getFileNames();
@ -119,21 +126,20 @@ public abstract class BaseRestController <T extends BaseEntity, E extends ApiWra
List<MultipartFile> files = request.getFiles(uploadedFile); List<MultipartFile> files = request.getFiles(uploadedFile);
if (CollectionUtils.isEmpty(files)) { if (CollectionUtils.isEmpty(files)) {
// 请选择文件 // 请选择文件
return ResultVo.error(CoreMsg.EXCEL_FILE_NULL.getCode(), return ResultWrapper.getCustomResultWrapper(CoreMsg.EXCEL_FILE_NULL);
CoreMsg.EXCEL_FILE_NULL.getMessage());
} }
ResultVo<?> resultVo ; ResultWrapper<?> resultVo ;
String msgInfo; String msgInfo;
try { try {
UserModel user = UserUtil.getUser(); UserModel user = UserUtil.getUser();
Date currDate = DateUtil.date(); Date currDate = DateUtil.date();
// 导入优化为 监听器 模式 超过一定阈值直接释放资源 防止导入数据导致系统 OOM // 导入优化为 监听器 模式 超过一定阈值直接释放资源 防止导入数据导致系统 OOM
ExcelUtil.getInstance().readExcelByListener(files.get(0), modelClazz, new BatchExcelListener<E>() { ExcelUtil.getInstance().readExcelByListener(files.get(0), IService.getModelClass(), new BatchExcelListener<E>() {
@Override @Override
public void saveData(List<E> dataList) { public void saveData(List<E> dataList) {
// 处理字典数据 // 处理字典数据
List<E> disposeData = ExcelUtil.getInstance().handleDatas(dataList, modelClazz, ExcelOperate.READ); List<E> disposeData = ExcelUtil.getInstance().handleDatas(dataList, IService.getModelClass(), ExcelOperate.READ);
// 手动赋值 必要数据 防止频繁开启Redis网络IO // 手动赋值 必要数据 防止频繁开启Redis网络IO
for (E model : disposeData) { for (E model : disposeData) {
model.setIzManual(true); model.setIzManual(true);
@ -152,7 +158,7 @@ public abstract class BaseRestController <T extends BaseEntity, E extends ApiWra
// 提示信息 // 提示信息
msgInfo = StrUtil.format(CoreMsg.EXCEL_IMPORT_SUCCESS.getMessage(), DateUtil.formatBetween(timerCount)); msgInfo = StrUtil.format(CoreMsg.EXCEL_IMPORT_SUCCESS.getMessage(), DateUtil.formatBetween(timerCount));
// 导出成功 // 导出成功
resultVo = ResultVo.success(msgInfo); resultVo = ResultWrapper.getSuccessResultWrapper(msgInfo);
resultVo.setCode(CoreMsg.EXCEL_IMPORT_SUCCESS.getCode()); resultVo.setCode(CoreMsg.EXCEL_IMPORT_SUCCESS.getCode());
} catch (ExcelPluginException e) { } catch (ExcelPluginException e) {
@ -162,7 +168,8 @@ public abstract class BaseRestController <T extends BaseEntity, E extends ApiWra
msgInfo = StrUtil.format(CoreMsg.EXCEL_IMPORT_ERROR.getMessage(), DateUtil.formatBetween(timerCount), msgInfo = StrUtil.format(CoreMsg.EXCEL_IMPORT_ERROR.getMessage(), DateUtil.formatBetween(timerCount),
e.getMessage()); e.getMessage());
// 导入失败 // 导入失败
resultVo = ResultVo.error(CoreMsg.EXCEL_IMPORT_ERROR.getCode(), msgInfo); resultVo = ResultWrapper.getCustomResultWrapper(
CoreMsg.EXCEL_IMPORT_ERROR.getCode(), msgInfo);
} }
// 记录导出日志 // 记录导出日志
log.info(msgInfo); log.info(msgInfo);
@ -170,108 +177,113 @@ public abstract class BaseRestController <T extends BaseEntity, E extends ApiWra
} }
/** /**
* * Excel
* @param fileName *
* @param response response * @param type ExcelExcel
* @param subName
* @param request request
* @return Optional<String>
*/ */
protected void importTemplate(String fileName, HttpServletResponse response, Method method){ protected Optional<String> excelExportAuth(String type, String subName, HttpServletRequest request){
this.excelExport(fileName + " 模版 ",null, response, method); // 封装缓存数据
ExcelExportCache exportCache;
if(ExcelExportCache.EXCEL_EXPORT.equals(type)){
// 异常检测
QueryBuilder<T> queryBuilder = new WebQueryBuilder<>(IService.getEntityClass(), request.getParameterMap());
QueryWrapper<T> queryWrapper = queryBuilder.build();
// 导出数量限制 -1 为无限制
Integer exportMaxCount = globalProperties.getExcel().getExportMaxCount();
if(exportMaxCount != null && exportMaxCount > -1){
// 获得数量 大于 阈值 禁止导出, 防止OOM
long count = IService.count(queryWrapper);
if(count > exportMaxCount){
String maxError = StrUtil.format(CoreMsg.EXCEL_HANDLE_MAX.getMessage(), count,
exportMaxCount);
// 超出最大导出数量
throw new ExcelPluginException(CoreMsg.EXCEL_HANDLE_MAX.getCode(), maxError);
}
}
// 封装缓存数据
exportCache = ExcelExportCache.builder()
.subName(subName)
.parameterMapStr(JSONUtil.toJsonStr(request.getParameterMap()))
.type(type)
.build();
}else if(ExcelExportCache.EXCEL_IMPORT_TEMPLATE_EXPORT.equals(type)){
// 封装缓存数据
exportCache = ExcelExportCache.builder()
.subName(subName+ " 模版 ")
.parameterMapStr(JSONUtil.toJsonStr(request.getParameterMap()))
.type(type)
.build();
}else {
return Optional.empty();
}
// 缓存Key
Long increment = redisPlugin
.increment(CacheUtil.formatKey(RedisConstants.PREFIX_TMP_EXCEL_EXPORT_NUM_NAME));
String certificate = UniqueStrGeneratorUtils.generator(increment);
// 缓存Key
String certificateCacheKeyTmp = CacheUtil.formatKey(
RedisConstants.PREFIX_TMP_EXCEL_EXPORT_NAME + certificate);
redisPlugin.put(certificateCacheKeyTmp, exportCache, CERTIFICATE_EXPIRED_MINUTE, TimeUnit.MINUTES);
return Optional.of(certificate);
} }
/** /**
* * Excel
* *
* Token
*
* 使2
*
* socketJava
* response javascript alert
*
* @param fileName
* @param queryWrapper
* @param response response * @param response response
*/ */
protected void excelExport(String fileName, QueryWrapper<T> queryWrapper, HttpServletResponse response, protected void excelExport(String certificate, HttpServletResponse response){
Method method){ // 缓存Key
// 权限认证 String certificateCacheKeyTmp = CacheUtil.formatKey(
try { RedisConstants.PREFIX_TMP_EXCEL_EXPORT_NAME + certificate);
if(method == null){ Object cacheObj = redisPlugin.get(certificateCacheKeyTmp);
// 无权访问该方法 ExcelExportCache cache = Convert.convert(ExcelExportCache.class, cacheObj);
throw new TokenException(TokenMsg.EXCEPTION_NOT_AUTH); if(cache == null){
return;
}
} // 主题名称
String subName = cache.getSubName();
// Token 认证 List<E> modelList = null;
JwtRealm.authToken();
RequiresPermissionsCus permissionsCus = method.getAnnotation(RequiresPermissionsCus.class); // 如果导出Excel 需要查询数据
if(permissionsCus != null){ if(ExcelExportCache.EXCEL_EXPORT.equals(cache.getType())){
// 方法权限认证 // 参数Map
JwtRealm.authPerms(permissionsCus.value()); Map<String, String[]> parameterMap = new HashMap<>();
} JSONObject jsonObject = JSONUtil.parseObj(cache.getParameterMapStr());
}catch (TokenException e){ jsonObject.forEach((k, v) -> {
// 推送错误信息 JSONArray values = (JSONArray) v;
OutputStreamUtil.exceptionResponse(e.getMessage(), response); String[] parameters = (String[]) values.toArray(String.class);
return; parameterMap.put(k, parameters);
} });
// 计时器 QueryBuilder<T> queryBuilder = new WebQueryBuilder<>(IService.getEntityClass(), parameterMap);
TimeInterval timer = DateUtil.timer(); QueryWrapper<T> queryWrapper = queryBuilder.build();
String msgInfo;
ResultVo<?> resultVo;
List<E> modelList = Lists.newArrayList();
try {
if(queryWrapper != null){
// 导出数量限制 -1 为无限制
Integer exportMaxCount = globalProperties.getExcel().getExportMaxCount();
if(exportMaxCount != null && exportMaxCount > -1){
// 获得数量 大于 阈值 禁止导出, 防止OOM
int count = IService.count(queryWrapper);
if(count > exportMaxCount){
String maxError = StrUtil.format(CoreMsg.EXCEL_HANDLE_MAX.getMessage(), count,
exportMaxCount);
// 超出最大导出数量
throw new ExcelPluginException(CoreMsg.EXCEL_HANDLE_MAX.getCode(), maxError);
}
}
List<T> entityList = IService.findList(queryWrapper);
// 转化类型
modelList = WrapperUtil.transformInstance(entityList, IService.getModelClass());
List<T> entityList = IService.findList(queryWrapper);
// 转化类型
modelList = WrapperUtil.transformInstance(entityList, modelClazz);
}
// 导出Excel
ExcelUtil.getInstance().writeExcel(response, modelList ,fileName,"sheet", modelClazz ,ExcelTypeEnum.XLSX);
// 花费毫秒数
long timerCount = timer.interval();
// 提示信息
msgInfo = StrUtil.format(CoreMsg.EXCEL_EXPORT_SUCCESS.getMessage(), modelList.size(),
DateUtil.formatBetween(timerCount));
// 导出成功
resultVo = ResultVo.success(msgInfo);
resultVo.setCode(CoreMsg.EXCEL_EXPORT_SUCCESS.getCode());
} catch (ExcelPluginException e) {
// 花费毫秒数
long timerCount = timer.interval();
// 提示信息
msgInfo = StrUtil.format(CoreMsg.EXCEL_EXPORT_ERROR.getMessage(), DateUtil.formatBetween(timerCount), e.getMessage());
// 导出失败
resultVo = ResultVo.error(CoreMsg.EXCEL_EXPORT_ERROR.getCode(), msgInfo);
}finally {
// 清空list
modelList.clear();
} }
// 记录导出日志
log.info(msgInfo);
// 导出异常 // 导出Excel
if(!resultVo.isSuccess()){ ExcelUtil.getInstance().writeExcel(
// 无权访问该方法 response, modelList, subName,"sheet", IService.getModelClass() ,ExcelTypeEnum.XLSX);
OutputStreamUtil.exceptionResponse(resultVo.getMsg(), response);
} // 删除凭证
redisPlugin.del(certificateCacheKeyTmp);
} }
/** /**
* *
*/ */
@ -347,34 +359,28 @@ public abstract class BaseRestController <T extends BaseEntity, E extends ApiWra
// ================================================= // =================================================
@PostConstruct
public void init(){
try {
this.modelClazz = IService.getModelClazz();
this.entityClazz = IService.getEntityClazz();
if(IService != null){
// 判断Service 是否包含 热数据注解
this.hotDataFlag = AnnotationUtil.hasAnnotation(IService.getServiceClazz(),
EnableHotData.class);
}
}catch (Exception e){
log.error(e.getMessage(),e);
}
}
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Data
public static class ExcelExportCache implements Serializable {
/** private static final long serialVersionUID = 1L;
*
* @return E
*/
private E createModel() {
try {
Class<E> modelClazz = this.modelClazz;
return modelClazz.newInstance();
} catch (Exception e) {
log.error(e.getMessage(),e);
}
return null;
}
public final static String EXCEL_IMPORT_TEMPLATE_EXPORT = "import-template-export";
public final static String EXCEL_EXPORT = "export";
/** 主题名 */
private String subName;
/** 类型 */
private String type;
/** 请求参数Map */
private String parameterMapStr;
}
} }

@ -0,0 +1,62 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.core.base.dto;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/**
*
*
* @author Parker
* @date 2021122216:22:37
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class LoginUserDto implements Serializable {
private static final long serialVersionUID = 1L;
/** 用户ID */
private String uid;
/** 用户名 */
private String username;
/** 用户昵称 */
private String nickname;
/** 租户ID */
private String tenantId;
/** 手机 */
private String mobile;
/** 邮箱 */
private String email;
/** 登录来源: 0:PC端1:APP-安卓 2:APP-IOS 3:小程序 */
private String loginFrom;
/** 登录ip */
private String loginIp;
}

@ -16,10 +16,14 @@
package org.opsli.core.base.service.impl; package org.opsli.core.base.service.impl;
import cn.hutool.core.convert.Convert; import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.TypeUtil; import cn.hutool.core.util.TypeUtil;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.toolkit.ReflectionKit;
import com.baomidou.mybatisplus.core.toolkit.reflect.SpringReflectionHelper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageInfo; import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@ -35,6 +39,7 @@ import org.opsli.core.persistence.querybuilder.QueryBuilder;
import org.opsli.core.persistence.querybuilder.chain.QueryDataPermsHandler; import org.opsli.core.persistence.querybuilder.chain.QueryDataPermsHandler;
import org.opsli.core.persistence.querybuilder.chain.QueryTenantHandler; import org.opsli.core.persistence.querybuilder.chain.QueryTenantHandler;
import org.opsli.core.persistence.querybuilder.conf.WebQueryConf; import org.opsli.core.persistence.querybuilder.conf.WebQueryConf;
import org.springframework.core.GenericTypeResolver;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import javax.annotation.PostConstruct; import javax.annotation.PostConstruct;
@ -64,12 +69,8 @@ import java.util.Map;
public abstract class CrudServiceImpl<M extends BaseMapper<T>, T extends BaseEntity, E extends ApiWrapper> public abstract class CrudServiceImpl<M extends BaseMapper<T>, T extends BaseEntity, E extends ApiWrapper>
extends BaseService<M, T> implements CrudServiceInterface<T,E> { extends BaseService<M, T> implements CrudServiceInterface<T,E> {
/** JSON tmp */
private static final String JSON_TMP = "{\"id\":\"1\"}";
/** Entity Clazz 类 */
protected Class<T> entityClazz;
/** Model Clazz 类 */ /** Model Clazz 类 */
protected Class<E> modelClazz; protected Class<E> modelClazz = getInnerModelClazz();
@Override @Override
public E get(String id) { public E get(String id) {
@ -213,7 +214,7 @@ public abstract class CrudServiceImpl<M extends BaseMapper<T>, T extends BaseEnt
@Override @Override
public List<T> findList(QueryWrapper<T> queryWrapper) { public List<T> findList(QueryWrapper<T> queryWrapper) {
// 数据处理责任链 // 数据处理责任链
QueryWrapper<T> qWrapper = this.addHandler(entityClazz, queryWrapper); QueryWrapper<T> qWrapper = this.addHandler(this.getEntityClass(), queryWrapper);
return super.list(qWrapper); return super.list(qWrapper);
} }
@ -221,7 +222,7 @@ public abstract class CrudServiceImpl<M extends BaseMapper<T>, T extends BaseEnt
@Override @Override
public List<T> findAllList() { public List<T> findAllList() {
// 数据处理责任链 // 数据处理责任链
QueryWrapper<T> qWrapper = this.addHandler(entityClazz); QueryWrapper<T> qWrapper = this.addHandler(this.getEntityClass());
return super.list(qWrapper); return super.list(qWrapper);
} }
@ -229,7 +230,7 @@ public abstract class CrudServiceImpl<M extends BaseMapper<T>, T extends BaseEnt
@Override @Override
public Page<T,E> findPage(Page<T,E> page) { public Page<T,E> findPage(Page<T,E> page) {
// 数据处理责任链 // 数据处理责任链
QueryWrapper<T> qWrapper = this.addHandler(entityClazz, page.getQueryWrapper()); QueryWrapper<T> qWrapper = this.addHandler(this.getEntityClass(), page.getQueryWrapper());
page.pageHelperBegin(); page.pageHelperBegin();
try{ try{
List<T> list = super.list(qWrapper); List<T> list = super.list(qWrapper);
@ -245,7 +246,7 @@ public abstract class CrudServiceImpl<M extends BaseMapper<T>, T extends BaseEnt
@Override @Override
public Page<T,E> findPageNotCount(Page<T,E> page) { public Page<T,E> findPageNotCount(Page<T,E> page) {
// 数据处理责任链 // 数据处理责任链
QueryWrapper<T> qWrapper = this.addHandler(entityClazz, page.getQueryWrapper()); QueryWrapper<T> qWrapper = this.addHandler(this.getEntityClass(), page.getQueryWrapper());
page.pageHelperBegin(false); page.pageHelperBegin(false);
try{ try{
List<T> list = super.list(qWrapper); List<T> list = super.list(qWrapper);
@ -286,7 +287,7 @@ public abstract class CrudServiceImpl<M extends BaseMapper<T>, T extends BaseEnt
* @return T * @return T
*/ */
protected T transformM2T(E model){ protected T transformM2T(E model){
return WrapperUtil.transformInstance(model, entityClazz); return WrapperUtil.transformInstance(model, this.getEntityClass());
} }
/** /**
@ -296,7 +297,7 @@ public abstract class CrudServiceImpl<M extends BaseMapper<T>, T extends BaseEnt
* @return List<T> * @return List<T>
*/ */
protected List<T> transformMs2Ts(List<E> models){ protected List<T> transformMs2Ts(List<E> models){
return WrapperUtil.transformInstance(models, entityClazz); return WrapperUtil.transformInstance(models, this.getEntityClass());
} }
/** /**
@ -342,26 +343,8 @@ public abstract class CrudServiceImpl<M extends BaseMapper<T>, T extends BaseEnt
// ======================== 初始化 ======================== // ======================== 初始化 ========================
/**
*
*/
@PostConstruct
public void init(){
try {
this.modelClazz = this.getInnerModelClazz();
this.entityClazz = this.getInnerEntityClazz();
}catch (Exception e){
log.error(e.getMessage(),e);
}
}
@Override @Override
public Class<T> getEntityClazz() { public Class<E> getModelClass() {
return entityClazz;
}
@Override
public Class<E> getModelClazz() {
return modelClazz; return modelClazz;
} }
@ -371,56 +354,8 @@ public abstract class CrudServiceImpl<M extends BaseMapper<T>, T extends BaseEnt
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public Class<E> getInnerModelClazz(){ public Class<E> getInnerModelClazz(){
String typeName = "E"; Class<?>[] typeArguments = GenericTypeResolver.resolveTypeArguments(this.getClass(), CrudServiceImpl.class);
Class<E> tClass = null; return null == typeArguments ? null : (Class<E>) typeArguments[2];
Map<Type, Type> typeMap = TypeUtil.getTypeMap(this.getClass());
for (Map.Entry<Type, Type> typeTypeEntry : typeMap.entrySet()) {
Type entryKey = typeTypeEntry.getKey();
Type entryValue = typeTypeEntry.getValue();
// 如果等于当前类型名称则进入
if(entryKey != null && entryValue != null){
if(StringUtils.equals(typeName, entryKey.getTypeName())){
// 小技巧 json 转换 obj 然后 转换成 type对象
Object convert = Convert.convert(entryValue, JSONObject.parse(JSON_TMP));
if(convert instanceof ApiWrapper) {
tClass = (Class<E>) entryValue;
break;
}
}
}
}
return tClass;
}
/**
* Entity Clazz
* @return Class<T>
*/
@SuppressWarnings("unchecked")
private Class<T> getInnerEntityClazz(){
String typeName = "T";
Class<T> tClass = null;
Map<Type, Type> typeMap = TypeUtil.getTypeMap(this.getClass());
for (Map.Entry<Type, Type> typeTypeEntry : typeMap.entrySet()) {
Type entryKey = typeTypeEntry.getKey();
Type entryValue = typeTypeEntry.getValue();
// 如果等于当前类型名称则进入
if(entryKey != null && entryValue != null){
if(StringUtils.equals(typeName, entryKey.getTypeName())){
// 小技巧 json 转换 obj 然后 转换成 type对象
Object convert = Convert.convert(entryValue, JSONObject.parse(JSON_TMP));
if(convert instanceof ApiWrapper) {
tClass = (Class<T>) entryValue;
break;
}
}
}
}
return tClass;
} }
} }

@ -44,6 +44,13 @@ import java.util.List;
public interface CrudServiceInterface<T extends BaseEntity, E extends ApiWrapper> extends BaseServiceInterface<T> { public interface CrudServiceInterface<T extends BaseEntity, E extends ApiWrapper> extends BaseServiceInterface<T> {
/**
* Model Class
* @return Class<E>
*/
Class<E> getModelClass();
/** /**
* *
* *
@ -201,19 +208,7 @@ public interface CrudServiceInterface<T extends BaseEntity, E extends ApiWrapper
* @return Page<T> * @return Page<T>
*/ */
Page<T,E> findPageNotCount(Page<T,E> page); Page<T,E> findPageNotCount(Page<T,E> page);
/**
* Model Clazz
* @return Class
*/
Class<E> getModelClazz();
/**
* Entity Clazz
* @return Class
*/
Class<T> getEntityClazz();
} }

@ -25,7 +25,9 @@ import com.google.common.util.concurrent.Striped;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.RedisTemplate;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.Lock;
@ -37,6 +39,8 @@ import java.util.function.Function;
* 使 * 使
* *
* Redis String Hash * Redis String Hash
*
* RedisTemplate LRU cache 穿 N
* *
* @author Parker * @author Parker
* @date 2021/12/10 12:39 * @date 2021/12/10 12:39
@ -95,6 +99,11 @@ public final class SecurityCache {
throw new RuntimeException("入参[redisTemplate,key,callbackSource]必填"); throw new RuntimeException("入参[redisTemplate,key,callbackSource]必填");
} }
// 先判断本地缓存是否存在 默认为存在(类似于伪布隆过滤)
if(isNonExist(key)){
return null;
}
// 缓存 Object 对象 // 缓存 Object 对象
Object cache = getCacheObject(redisTemplate, key); Object cache = getCacheObject(redisTemplate, key);
// 如果缓存不为空 则直接返回 // 如果缓存不为空 则直接返回
@ -109,6 +118,11 @@ public final class SecurityCache {
try { try {
// 尝试获得锁 // 尝试获得锁
if(lock.tryLock(DEFAULT_LOCK_TIME, TimeUnit.SECONDS)){ if(lock.tryLock(DEFAULT_LOCK_TIME, TimeUnit.SECONDS)){
// 先判断本地缓存是否存在 默认为存在(类似于伪布隆过滤)
if(isNonExist(key)){
return null;
}
// 梅开二度 如果查到后 直接返回 // 梅开二度 如果查到后 直接返回
cache = getCacheObject(redisTemplate, key); cache = getCacheObject(redisTemplate, key);
// 如果缓存不为空 则直接返回 // 如果缓存不为空 则直接返回
@ -135,6 +149,68 @@ public final class SecurityCache {
return cache; return cache;
} }
/**
* TTL
* @param redisTemplate redisTemplate
* @param key
* @param callbackSource
* @return Object
*/
public static Object getByTtl(
final RedisTemplate<String, Object> redisTemplate,
final String key, final Function<String, Object> callbackSource, final int ttl){
if(null == redisTemplate || null == key || null == callbackSource){
throw new RuntimeException("入参[redisTemplate,key,callbackSource]必填");
}
// 先判断本地缓存是否存在 默认为存在(类似于伪布隆过滤)
if(isNonExist(key)){
return null;
}
// 缓存 Object 对象
Object cache = getCacheObject(redisTemplate, key);
// 如果缓存不为空 则直接返回
if(null != cache){
return cache;
}
// 如果还没查到缓存 则需要 穿透到 源数据查询
// 开启本地锁
@SuppressWarnings("UnstableApiUsage")
Lock lock = STRIPED.get(key);
try {
// 尝试获得锁
if(lock.tryLock(DEFAULT_LOCK_TIME, TimeUnit.SECONDS)){
// 先判断本地缓存是否存在 默认为存在(类似于伪布隆过滤)
if(isNonExist(key)){
return null;
}
// 梅开二度 如果查到后 直接返回
cache = getCacheObject(redisTemplate, key);
// 如果缓存不为空 则直接返回
if(null != cache){
return cache;
}
// 如果这时候还没有 则查询源数据
cache = callbackSource.apply(key);
if(null == cache){
// 存储缓存状态
LFU_NULL_CACHE.put(key, CacheStatus.NOT_EXIST);
return null;
}
// 存入 Redis缓存
put(redisTemplate, key, cache, ttl);
}
}catch (Exception e){
log.error(e.getMessage(), e);
}finally {
lock.unlock();
}
return cache;
}
/** /**
* *
* @param redisTemplate redisTemplate * @param redisTemplate redisTemplate
@ -189,7 +265,33 @@ public final class SecurityCache {
LFU_NULL_CACHE.invalidate(key); LFU_NULL_CACHE.invalidate(key);
} }
/**
*
* @param redisTemplate redisTemplate
* @param key
* @param val
* @param seconds
*/
public static void put(
final RedisTemplate<String, Object> redisTemplate,
final String key, final Object val, final Integer seconds) {
if (null == redisTemplate || null == key || null == val) {
throw new RuntimeException("入参[redisTemplate,key,val]必填");
}
String cacheKey = StrUtil.addPrefixIfNot(key, CACHE_PREFIX_KV);
redisTemplate.opsForValue()
.set(
cacheKey,
val,
seconds,
TimeUnit.SECONDS
);
// 清除本地记录
LFU_NULL_CACHE.invalidate(key);
}
/** /**
* Hash * Hash
@ -208,6 +310,10 @@ public final class SecurityCache {
final String tempKey = key + "_" + field; final String tempKey = key + "_" + field;
// 先判断本地缓存是否存在 默认为存在(类似于伪布隆过滤)
if(isNonExist(tempKey)){
return null;
}
// 缓存 Object 对象 // 缓存 Object 对象
Object cache = getHashCacheObject(redisTemplate, key, field); Object cache = getHashCacheObject(redisTemplate, key, field);
// 如果缓存不为空 则直接返回 // 如果缓存不为空 则直接返回
@ -222,6 +328,11 @@ public final class SecurityCache {
try { try {
// 尝试获得锁 // 尝试获得锁
if(lock.tryLock(DEFAULT_LOCK_TIME, TimeUnit.SECONDS)){ if(lock.tryLock(DEFAULT_LOCK_TIME, TimeUnit.SECONDS)){
// 先判断本地缓存是否存在 默认为存在(类似于伪布隆过滤)
if(isNonExist(tempKey)){
return null;
}
// 梅开二度 如果查到后 直接返回 // 梅开二度 如果查到后 直接返回
cache = getHashCacheObject(redisTemplate, key, field); cache = getHashCacheObject(redisTemplate, key, field);
// 如果缓存不为空 则直接返回 // 如果缓存不为空 则直接返回
@ -266,6 +377,10 @@ public final class SecurityCache {
throw new RuntimeException("入参[redisTemplate,key,callbackSource]必填"); throw new RuntimeException("入参[redisTemplate,key,callbackSource]必填");
} }
// 先判断本地缓存是否存在 默认为存在(类似于伪布隆过滤)
if(isNonExist(key)){
return null;
}
// 缓存 Object 对象 // 缓存 Object 对象
Map<String, Object> cache = getAllHashCacheObject(redisTemplate, key, null); Map<String, Object> cache = getAllHashCacheObject(redisTemplate, key, null);
// 如果缓存不为空 则直接返回 // 如果缓存不为空 则直接返回
@ -280,6 +395,11 @@ public final class SecurityCache {
try { try {
// 尝试获得锁 // 尝试获得锁
if(lock.tryLock(DEFAULT_LOCK_TIME, TimeUnit.SECONDS)){ if(lock.tryLock(DEFAULT_LOCK_TIME, TimeUnit.SECONDS)){
// 先判断本地缓存是否存在 默认为存在(类似于伪布隆过滤)
if(isNonExist(key)){
return null;
}
// 梅开二度 如果查到后 直接返回 // 梅开二度 如果查到后 直接返回
cache = getAllHashCacheObject(redisTemplate, key, null); cache = getAllHashCacheObject(redisTemplate, key, null);
// 如果缓存不为空 则直接返回 // 如果缓存不为空 则直接返回
@ -324,6 +444,10 @@ public final class SecurityCache {
throw new RuntimeException("入参[redisTemplate,key,callbackSourceCount,callbackSource]必填"); throw new RuntimeException("入参[redisTemplate,key,callbackSourceCount,callbackSource]必填");
} }
// 先判断本地缓存是否存在 默认为存在(类似于伪布隆过滤)
if(isNonExist(key)){
return null;
}
// 缓存 Object 对象 // 缓存 Object 对象
Map<String, Object> cache = getAllHashCacheObject(redisTemplate, key, callbackSourceCount); Map<String, Object> cache = getAllHashCacheObject(redisTemplate, key, callbackSourceCount);
// 如果缓存不为空 则直接返回 // 如果缓存不为空 则直接返回
@ -338,6 +462,11 @@ public final class SecurityCache {
try { try {
// 尝试获得锁 // 尝试获得锁
if(lock.tryLock(DEFAULT_LOCK_TIME, TimeUnit.SECONDS)){ if(lock.tryLock(DEFAULT_LOCK_TIME, TimeUnit.SECONDS)){
// 先判断本地缓存是否存在 默认为存在(类似于伪布隆过滤)
if(isNonExist(key)){
return null;
}
// 梅开二度 如果查到后 直接返回 // 梅开二度 如果查到后 直接返回
cache = getAllHashCacheObject(redisTemplate, key, callbackSourceCount); cache = getAllHashCacheObject(redisTemplate, key, callbackSourceCount);
// 如果缓存不为空 则直接返回 // 如果缓存不为空 则直接返回
@ -472,48 +601,28 @@ public final class SecurityCache {
/** /**
* *
* @param redisTemplate redisTemplate * @param redisTemplate redisTemplate
* @param keys * @param keys
*/ */
public static boolean removeMore( public static boolean remove(
final RedisTemplate<String, Object> redisTemplate, final RedisTemplate<String, Object> redisTemplate,
final String... keys) { final String... keys) {
if (null == redisTemplate || null == keys) { if (null == redisTemplate || null == keys) {
throw new RuntimeException("入参[redisTemplate,keys]必填"); throw new RuntimeException("入参[redisTemplate,key]必填");
} }
int count = keys.length; List<String> removeKeyList = new ArrayList<>();
for (String key : keys) { for (String key : keys) {
boolean isRemove = remove(redisTemplate, key); // 清除本地记录
if(isRemove){ LFU_NULL_CACHE.invalidate(key);
count--;
}
}
return 0 == count;
}
/** removeKeyList.add(StrUtil.addPrefixIfNot(key, CACHE_PREFIX_KV));
* removeKeyList.add(StrUtil.addPrefixIfNot(key, CACHE_PREFIX_HASH));
* @param redisTemplate redisTemplate
* @param key
*/
public static boolean remove(
final RedisTemplate<String, Object> redisTemplate,
final String key) {
if (null == redisTemplate || null == key) {
throw new RuntimeException("入参[redisTemplate,key]必填");
} }
// 清除本地记录
LFU_NULL_CACHE.invalidate(key);
String cacheKeyByKv = StrUtil.addPrefixIfNot(key, CACHE_PREFIX_KV);
String cacheKeyByHash = StrUtil.addPrefixIfNot(key, CACHE_PREFIX_HASH);
// 清除缓存 // 清除缓存
redisTemplate.delete(cacheKeyByKv); redisTemplate.delete(removeKeyList);
redisTemplate.delete(cacheKeyByHash);
return true; return true;
} }
@ -529,13 +638,6 @@ public final class SecurityCache {
private static Object getCacheObject(RedisTemplate<String, Object> redisTemplate, String key) { private static Object getCacheObject(RedisTemplate<String, Object> redisTemplate, String key) {
Object cache = null; Object cache = null;
try { try {
// 先判断本地缓存是否存在 默认为存在(类似于伪布隆过滤)
CacheStatus cacheStatus = LFU_NULL_CACHE.get(key, () -> CacheStatus.EXIST);
// 如果不存在 则直接返回空
if(CacheStatus.NOT_EXIST.equals(cacheStatus)){
return null;
}
String cacheKey = StrUtil.addPrefixIfNot(key, CACHE_PREFIX_KV); String cacheKey = StrUtil.addPrefixIfNot(key, CACHE_PREFIX_KV);
// 从 缓存回调查询数据 // 从 缓存回调查询数据
@ -555,15 +657,6 @@ public final class SecurityCache {
private static Object getHashCacheObject(RedisTemplate<String, Object> redisTemplate, String key, String field) { private static Object getHashCacheObject(RedisTemplate<String, Object> redisTemplate, String key, String field) {
Object cache = null; Object cache = null;
try { try {
final String tempKey = key + "_" + field;
// 先判断本地缓存是否存在 默认为存在(类似于伪布隆过滤)
CacheStatus cacheStatus = LFU_NULL_CACHE.get(tempKey, () -> CacheStatus.EXIST);
// 如果不存在 则直接返回空
if(CacheStatus.NOT_EXIST.equals(cacheStatus)){
return null;
}
String cacheKeyByHash = StrUtil.addPrefixIfNot(key, CACHE_PREFIX_HASH); String cacheKeyByHash = StrUtil.addPrefixIfNot(key, CACHE_PREFIX_HASH);
// 从 缓存回调查询数据 // 从 缓存回调查询数据
@ -586,13 +679,6 @@ public final class SecurityCache {
final Function<String, Integer> callbackSourceCount) { final Function<String, Integer> callbackSourceCount) {
Map<String, Object> cache = null; Map<String, Object> cache = null;
try { try {
// 先判断本地缓存是否存在 默认为存在(类似于伪布隆过滤)
CacheStatus cacheStatus = LFU_NULL_CACHE.get(key, () -> CacheStatus.EXIST);
// 如果不存在 则直接返回空
if(CacheStatus.NOT_EXIST.equals(cacheStatus)){
return null;
}
String cacheKeyByHash = StrUtil.addPrefixIfNot(key, CACHE_PREFIX_HASH); String cacheKeyByHash = StrUtil.addPrefixIfNot(key, CACHE_PREFIX_HASH);
// 从 缓存回调查询数据 // 从 缓存回调查询数据
@ -619,6 +705,23 @@ public final class SecurityCache {
return cache; return cache;
} }
/**
*
* @param key key
* @return boolean
*/
private static boolean isNonExist(String key){
try {
// 先判断本地缓存是否存在 默认为存在(类似于伪布隆过滤)
CacheStatus cacheStatus = LFU_NULL_CACHE.get(key, () -> CacheStatus.EXIST);
// 如果不存在 则直接返回空
return CacheStatus.NOT_EXIST.equals(cacheStatus);
}catch (Exception e){
log.error(e.getMessage(), e);
}
return false;
}
/** /**
* *
*/ */

@ -0,0 +1,43 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.core.eventbus;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
/**
* EventBus Spring
*
* @author Parker
* @date 202112710:39:16
*/
public abstract class AbstractSpringEventBus implements IEventBus, ApplicationContextAware {
private ApplicationContext context;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.context = applicationContext;
this.scanConsumer(null);
}
@Override
public void scanConsumer(String packageName) {
context.getBeansOfType(IEventConsumer.class).forEach((k,v)->{
this.addConsumer(v);
});
}
}

@ -0,0 +1,48 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.core.eventbus;
/**
* EventBus
*
* @author Parker
* @date 202112710:38:24
*/
public interface IEventBus {
/**
*
* @param event
*/
void post(Object event);
/**
*
* @param obj classkey
*/
void addConsumer(Object obj);
/**
*
* @param obj classkey
*/
void removeConsumer(Object obj);
/**
*
* @param packageName
*/
void scanConsumer(String packageName);
}

@ -1,5 +1,5 @@
/** /**
* Copyright 2018 http://www.renren.io * Copyright 2020 OPSLI https://www.opsli.com
* <p> * <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not * Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of * use this file except in compliance with the License. You may obtain a copy of
@ -13,22 +13,20 @@
* License for the specific language governing permissions and limitations under * License for the specific language governing permissions and limitations under
* the License. * the License.
*/ */
package org.opsli.core.eventbus;
package org.opsli.core.security.shiro.utils;
/** /**
* RedisKeys * EventBus
* *
* @author Mark sunlightcs@gmail.com * @author Parker
* @since 3.0.0 2017-07-18 * @date 2020/9/25 12:19
*/ */
public class RedisKeys { public interface IEventConsumer<T> {
public static String getSysConfigKey(String key){ /**
return "system:config:" + key; *
} * @param event
*/
void consumer(T event);
public static String getShiroSessionKey(String key){
return "sessionid:" + key;
}
} }

@ -43,7 +43,7 @@ import static org.opsli.common.constants.OrderConstants.LIMITER_AOP_SORT;
/** /**
* *
* *
* @author * @author Parker
* @date 2020-09-16 * @date 2020-09-16
*/ */
@Slf4j @Slf4j

@ -1,75 +0,0 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.core.filters.aspect;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.TimeInterval;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.opsli.core.utils.LogUtil;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import static org.opsli.common.constants.OrderConstants.TOKEN_AOP_SORT;
/**
*
*
* @author parker
* @date 2020-09-16
*/
@Slf4j
@Order(TOKEN_AOP_SORT)
@Aspect
@Component
public class LogAop {
@Pointcut("execution(public * org.opsli..*.*Controller*.*(..))")
public void requestMapping() {
}
/**
* post
* @param point point
*/
@Around("requestMapping()")
public Object tokenAop(ProceedingJoinPoint point) throws Throwable {
// 计时器
TimeInterval timer = DateUtil.timer();
// 执行
Exception exception = null;
// 防止线程抛异常 线程变量不回收 导致oom
Object returnValue;
try {
// 执行正常操作
returnValue = point.proceed();
}catch (Exception e){
exception = e;
throw e;
} finally {
// 花费毫秒数
long timerCount = timer.interval();
//保存日志
LogUtil.saveLog(point, exception, timerCount);
}
return returnValue;
}
}

@ -1,190 +0,0 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.core.filters.aspect;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.TypeUtil;
import lombok.extern.slf4j.Slf4j;
import opsli.plugins.crypto.CryptoPlugin;
import opsli.plugins.crypto.enums.CryptoSymmetricType;
import opsli.plugins.crypto.model.CryptoAsymmetric;
import opsli.plugins.crypto.model.CryptoSymmetric;
import opsli.plugins.crypto.strategy.CryptoAsymmetricService;
import opsli.plugins.crypto.strategy.CryptoSymmetricService;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.opsli.api.base.encrypt.BaseEncrypt;
import org.opsli.api.base.result.ResultVo;
import org.opsli.common.annotation.LoginCrypto;
import org.opsli.common.exception.ServiceException;
import org.opsli.core.msg.CoreMsg;
import org.opsli.core.options.CryptoConfigFactory;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.Map;
import static org.opsli.common.constants.OrderConstants.ENCRYPT_ADN_DECRYPT_AOP_SORT;
/**
*
*
* @author parker
* @date 2021-01-23
*/
@Slf4j
@Order(ENCRYPT_ADN_DECRYPT_AOP_SORT)
@Aspect
@Component
public class LoginCryptoAop {
@Pointcut("@annotation(org.opsli.common.annotation.LoginCrypto)")
public void encryptAndDecrypt() {
}
/**
* post
* @param point point
*/
@Around("encryptAndDecrypt()")
public Object encryptAndDecryptHandle(ProceedingJoinPoint point) throws Throwable {
// 获得请求参数
Object[] args = point.getArgs();
// 返回结果
Object returnValue;
MethodSignature signature = (MethodSignature) point.getSignature();
// 获得 方法
Method method = signature.getMethod();
// 获得方法注解
LoginCrypto annotation =
method.getAnnotation(LoginCrypto.class);
// 获得非对称加解密 执行器
CryptoAsymmetricService asymmetric = null;
// 非对称加解密模型
CryptoAsymmetric cryptoAsymmetric = null;
if(annotation != null && annotation.enable()){
asymmetric = CryptoPlugin.getAsymmetric();
cryptoAsymmetric = CryptoConfigFactory.INSTANCE.getCryptoAsymmetric();
}
// 1. 请求解密
if(annotation != null && annotation.enable()){
if(cryptoAsymmetric != null){
enterDecrypt(args, method, asymmetric, cryptoAsymmetric);
}
}
// 2. 执行方法
returnValue = point.proceed(args);
// 3. 返回加密 返回加密为对称加密
if(annotation != null && annotation.enable()){
if(cryptoAsymmetric != null){
CryptoSymmetricService symmetric = CryptoPlugin.getSymmetric();
CryptoSymmetric symmetricModel = symmetric.createNilModel();
symmetricModel.setCryptoType(CryptoSymmetricType.DES);
symmetricModel.setPrivateKey(cryptoAsymmetric.getPublicKey());
// 执行加密操作
returnValue = resultEncrypt(returnValue, symmetric, symmetricModel);
}
}
return returnValue;
}
/**
*
* @param args
* @param method
* @param asymmetric
* @param cryptoModel
*/
private void enterDecrypt(Object[] args, Method method, CryptoAsymmetricService asymmetric, CryptoAsymmetric cryptoModel) {
for (int i = 0; i < args.length; i++) {
Object arg = args[i];
// 参数校验
if(arg instanceof BaseEncrypt){
// 获得加密数据
BaseEncrypt baseEncrypt = (BaseEncrypt) arg;
String encryptData = baseEncrypt.getEncryptData();
// 解密对象
Object dataToObj = asymmetric.decryptToObj(cryptoModel, encryptData);
// 根据方法类型转化对象
Type type = TypeUtil.getParamType(method, i);
Object obj = Convert.convert(type, dataToObj);
// 修改缓存中设备数据 空值不覆盖
Map<String, Object> modelBeanMap = BeanUtil.beanToMap(obj);
modelBeanMap.entrySet().removeIf(entry -> entry.getValue() == null);
// 反射赋值
Field[] fields = ReflectUtil.getFields(arg.getClass());
for (Field f : fields) {
Object val = modelBeanMap.get(f.getName());
if(val == null){
continue;
}
//根据需要,将相关属性赋上默认值
BeanUtil.setProperty(arg, f.getName(), val);
}
}
}
}
/**
*
* @param returnValue
* @param symmetric
* @param cryptoModel
* @return Object
*/
@SuppressWarnings("unchecked")
private Object resultEncrypt(Object returnValue, CryptoSymmetricService symmetric, CryptoSymmetric cryptoModel) {
if(returnValue != null){
try {
// 执行加密过程
if(returnValue instanceof ResultVo){
// 重新赋值 data
ResultVo<Object> ret = (ResultVo<Object>) returnValue;
ret.setData(
symmetric.encrypt(cryptoModel, ret.getData())
);
}else {
returnValue = symmetric.encrypt(cryptoModel, returnValue);
}
}catch (Exception e){
// 非对称加密失败
throw new ServiceException(CoreMsg.OTHER_EXCEPTION_CRYPTO_EN);
}
}
return returnValue;
}
}

@ -38,7 +38,7 @@ import static org.opsli.common.constants.OrderConstants.SEARCH_HIS_AOP_SORT;
/** /**
* AOP * AOP
* *
* @author * @author Parker
* @date 2020-09-16 * @date 2020-09-16
*/ */
@Slf4j @Slf4j

@ -0,0 +1,336 @@
package org.opsli.core.filters.interceptor;
import cn.hutool.core.util.StrUtil;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import opsli.plugins.crypto.spring.annotation.CryptoMapperField;
import opsli.plugins.crypto.spring.crypto.ICrypto;
import opsli.plugins.crypto.spring.enums.CryptoType;
import org.apache.ibatis.cache.CacheKey;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.opsli.core.autoconfigure.properties.EncryptProperties;
import org.springframework.stereotype.Component;
import java.lang.reflect.*;
import java.time.chrono.ChronoLocalDate;
import java.util.*;
/**
* Mybatis
* <p>
* Signature:
* Signature.type: ExecutorParameterHandlerStatementHandlerResultSetHandler
* Signature.method:
* Signature.args:JAVA
*
* @author Parker
* @date 2022-08-07
*/
@Slf4j
@AllArgsConstructor
@Component
@Intercepts(
{
@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}),
@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class, CacheKey.class, BoundSql.class}),
@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class}),
}
)
public class MybatisCryptoInterceptor implements Interceptor {
private final EncryptProperties encryptProperties;
/**
* @param invocation
* @return
* @throws Throwable
*/
@Override
public Object intercept(Invocation invocation) throws Throwable {
Method method = invocation.getMethod();
switch (method.getName()) {
case "update":
return updateHandle(invocation);
case "query":
return selectHandle(invocation);
default:
return invocation.proceed();
}
}
/**
*
*
* @param invocation
* @return
* @throws Throwable
*/
private Object selectHandle(Invocation invocation) throws Throwable {
Object[] args = invocation.getArgs();
MappedStatement ms = (MappedStatement) args[0];
Object parameter = args[1];
RowBounds rowBounds = (RowBounds) args[2];
ResultHandler<Object> resultHandler = (ResultHandler) args[3];
Executor executor = (Executor) invocation.getTarget();
CacheKey cacheKey;
BoundSql boundSql;
//处理参数作为条件查询需要加密
handleParameterOrResult(parameter, CryptoType.ENCRYPT);
//由于逻辑关系,只会进入一次
if (args.length == 4) {
//4 个参数时
boundSql = ms.getBoundSql(parameter);
cacheKey = executor.createCacheKey(ms, parameter, rowBounds, boundSql);
} else {
//6 个参数时
cacheKey = (CacheKey) args[4];
boundSql = (BoundSql) args[5];
}
List<Object> resultList = executor.query(ms, parameter, rowBounds, resultHandler, cacheKey, boundSql);
for (Object o : resultList) {
handleParameterOrResult(o, CryptoType.DECRYPT);
}
return resultList;
}
/**
*
*
* @param invocation
* @return
* @throws Throwable
*/
private Object updateHandle(Invocation invocation) throws Throwable {
//处理参数
handleParameterOrResult(invocation.getArgs()[1], CryptoType.ENCRYPT);
return invocation.proceed();
}
/**
*
*
* @param object
* @param cryptoType
* @throws IllegalAccessException
*/
private void handleParameterOrResult(Object object, CryptoType cryptoType) throws IllegalAccessException {
HashMap<Field, Object> fieldObjectHashMap = new HashMap<>();
//多个参数
if (object instanceof Map) {
Map paramMap = (Map) object;
Set keySet = paramMap.keySet();
for (Object key : keySet) {
Object o = paramMap.get(key);
if (o != null) {
handleObject(o, o.getClass(), fieldObjectHashMap);
}
}
} else {
if (object != null) {
handleObject(object, object.getClass(), fieldObjectHashMap);
}
}
//统一修改加密解密值
fieldObjectHashMap.keySet().forEach(key -> {
try {
handleString(key, fieldObjectHashMap.get(key), cryptoType);
} catch (Exception e) {
e.printStackTrace();
}
});
}
/**
*
*
* @param type
* @return
*/
private boolean isBase(Type type) {
return boolean.class.equals(type) ||
char.class.equals(type) ||
long.class.equals(type) ||
int.class.equals(type) ||
byte.class.equals(type) ||
short.class.equals(type) ||
double.class.equals(type) ||
float.class.equals(type);
}
/**
*
*
* @param object
* @return
*/
private boolean isFilter(Object object) {
return object == null || object instanceof CharSequence || object instanceof Number || object instanceof Collection || object instanceof Date || object instanceof ChronoLocalDate;
}
/**
*
*
* @param oClass
* @param fields
* @return
*/
private List<Field> mergeField(Class<?> oClass, List<Field> fields) {
if (fields == null) {
fields = new ArrayList<>();
}
Class<?> superclass = oClass.getSuperclass();
if (superclass != null && !superclass.equals(Object.class) && superclass.getDeclaredFields().length > 0) {
mergeField(superclass, fields);
}
for (Field declaredField : oClass.getDeclaredFields()) {
int modifiers = declaredField.getModifiers();
if (Modifier.isStatic(modifiers) || Modifier.isFinal(modifiers) || Modifier.isVolatile(modifiers) || Modifier.isSynchronized(modifiers)) {
continue;
}
fields.add(declaredField);
}
return fields;
}
/**
* Object
*
* @param obj
* @param oClass
* @throws IllegalAccessException
*/
private void handleObject(Object obj, Class<?> oClass, HashMap<Field, Object> fieldObjectHashMap) throws IllegalAccessException {
//过滤
if (isFilter(obj)) {
return;
}
List<Field> fields = mergeField(oClass, null);
for (Field declaredField : fields) {
//静态属性直接跳过
if (Modifier.isStatic(declaredField.getModifiers())) {
continue;
}
boolean accessible = declaredField.isAccessible();
declaredField.setAccessible(true);
Object value = declaredField.get(obj);
declaredField.setAccessible(accessible);
if (value == null) {
// TODO
continue;
} else if (value instanceof Number) {
// TODO
continue;
} else if (value instanceof String) {
CryptoMapperField annotation = declaredField.getAnnotation(CryptoMapperField.class);
if (annotation != null) {
fieldObjectHashMap.put(declaredField, obj);
}
} else if (value instanceof Collection) {
Collection coll = (Collection) value;
for (Object o : coll) {
if (isFilter(o)) {
//默认集合内类型一致
break;
}
handleObject(o, o.getClass(), fieldObjectHashMap);
}
} else {
handleObject(value, value.getClass(), fieldObjectHashMap);
}
}
}
/**
*
*
* @param field
* @param object
* @param cryptoType
* @throws IllegalAccessException
* @throws InstantiationException
* @throws NoSuchMethodException
* @throws InvocationTargetException
*/
private void handleString(Field field, Object object, CryptoType cryptoType) throws Exception {
boolean accessible = field.isAccessible();
field.setAccessible(true);
Object value = field.get(object);
CryptoMapperField annotation = field.getAnnotation(CryptoMapperField.class);
if (annotation != null) {
String key;
//全局配置的key
String propertiesKey = encryptProperties.getKey();
log.debug("全局key是" + propertiesKey);
//属性上的key
String annotationKey = annotation.key();
log.debug("注解key是" + annotationKey);
if (StrUtil.isNotBlank(annotationKey)) {
key = annotationKey;
} else {
key = propertiesKey;
}
Class<? extends ICrypto> iCryptoImpl = annotation.iCrypto();
ICrypto iCrypto = iCryptoImpl.newInstance();
//解密后的值
String valueResult;
if (cryptoType.equals(CryptoType.DECRYPT)) {
valueResult = iCrypto.decrypt(String.valueOf(value), key);
} else {
valueResult = iCrypto.encrypt(String.valueOf(value), key);
}
log.debug("原值:" + value);
log.debug("现在:" + valueResult);
field.set(object, String.valueOf(valueResult));
field.setAccessible(accessible);
}
}
/**
*
*
* @param target
* @return
*/
@Override
public Object plugin(Object target) {
return Plugin.wrap(target, this);
}
@Override
public void setProperties(Properties properties) {
}
}

@ -27,7 +27,7 @@ import javax.servlet.http.HttpServletResponse;
/** /**
* , jwt token * , jwt token
* *
* @author * @author Parker
* @date 2021122216:35:20 * @date 2021122216:35:20
*/ */
@Slf4j @Slf4j

@ -20,6 +20,7 @@ import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Console; import cn.hutool.core.lang.Console;
import cn.hutool.core.net.NetUtil; import cn.hutool.core.net.NetUtil;
import cn.hutool.core.thread.ThreadUtil; import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.opsli.core.autoconfigure.properties.GlobalProperties; import org.opsli.core.autoconfigure.properties.GlobalProperties;
@ -98,7 +99,8 @@ public class StartPrint {
* @return String * @return String
*/ */
public String getBasePath(){ public String getBasePath(){
return NetUtil.getLocalhostStr() + ":" + serverPort + serverContextPath; return NetUtil.getLocalhostStr() + ":" + serverPort
+ StrUtil.addPrefixIfNot(serverContextPath, "/");
} }
/** /**
@ -107,7 +109,8 @@ public class StartPrint {
*/ */
public String getRunTime(){ public String getRunTime(){
//Level.MINUTE表示精确到分 //Level.MINUTE表示精确到分
return DateUtil.formatBetween(DateUtil.parseDateTime(starterDate), DateUtil.date(), BetweenFormatter.Level.MINUTE); return DateUtil.formatBetween(DateUtil.parseDateTime(starterDate),
DateUtil.date(), BetweenFormatter.Level.MINUTE);
} }
// ====================== // ======================

@ -18,14 +18,9 @@ package org.opsli.core.handler;
import cn.hutool.core.text.StrFormatter; import cn.hutool.core.text.StrFormatter;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authc.IncorrectCredentialsException; import org.opsli.api.base.result.ResultWrapper;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.pam.UnsupportedTokenException;
import org.apache.shiro.authz.AuthorizationException;
import org.opsli.api.base.result.ResultVo;
import org.opsli.common.exception.*; import org.opsli.common.exception.*;
import org.opsli.core.msg.CoreMsg; import org.opsli.core.msg.CoreMsg;
import org.opsli.core.msg.TokenMsg;
import org.springframework.core.annotation.Order; import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
@ -86,9 +81,9 @@ public class GlobalExceptionHandler {
@ExceptionHandler(ServiceException.class) @ExceptionHandler(ServiceException.class)
@ResponseStatus(HttpStatus.OK) @ResponseStatus(HttpStatus.OK)
@ResponseBody @ResponseBody
public ResultVo<?> businessException(ServiceException e) { public ResultWrapper<?> businessException(ServiceException e) {
log.warn("业务异常 - 异常编号:{} - 异常信息:{}",e.getCode(),e.getMessage()); log.warn("业务异常 - 异常编号:{} - 异常信息:{}",e.getCode(),e.getMessage());
return ResultVo.error(e.getCode(), e.getMessage()); return ResultWrapper.getCustomResultWrapper(e.getCode(), e.getMessage());
} }
/** /**
@ -97,8 +92,8 @@ public class GlobalExceptionHandler {
@ExceptionHandler(EmptyException.class) @ExceptionHandler(EmptyException.class)
@ResponseStatus(HttpStatus.OK) @ResponseStatus(HttpStatus.OK)
@ResponseBody @ResponseBody
public ResultVo<?> emptyException(EmptyException e) { public ResultWrapper<?> emptyException(EmptyException e) {
return ResultVo.error(e.getCode(), e.getMessage()); return ResultWrapper.getCustomResultWrapper(e.getCode(), e.getMessage());
} }
/** /**
@ -107,68 +102,19 @@ public class GlobalExceptionHandler {
@ExceptionHandler(JwtException.class) @ExceptionHandler(JwtException.class)
@ResponseStatus(HttpStatus.OK) @ResponseStatus(HttpStatus.OK)
@ResponseBody @ResponseBody
public ResultVo<?> jwtException(JwtException e) { public ResultWrapper<?> jwtException(JwtException e) {
return ResultVo.error(e.getCode(), e.getMessage()); return ResultWrapper.getCustomResultWrapper(e.getCode(), e.getMessage());
} }
/**
* Shiro
*/
@ExceptionHandler(IncorrectCredentialsException.class)
@ResponseStatus(HttpStatus.UNAUTHORIZED)
@ResponseBody
public ResultVo<?> incorrectCredentialsException(IncorrectCredentialsException e) {
// token失效请重新登录
return ResultVo.error(e.getMessage());
}
/**
* Shiro
*/
@ExceptionHandler(LockedAccountException.class)
@ResponseStatus(HttpStatus.OK)
@ResponseBody
public ResultVo<?> lockedAccountException(LockedAccountException e) {
// 账号已被锁定,请联系管理员
return ResultVo.error(e.getMessage());
}
/**
* Shiro
*/
@ExceptionHandler(AuthorizationException.class)
@ResponseStatus(HttpStatus.OK)
@ResponseBody
public ResultVo<?> authorizationException(AuthorizationException e) {
// 无权访问该方法
return ResultVo.error(TokenMsg.EXCEPTION_NOT_AUTH.getCode(),
TokenMsg.EXCEPTION_NOT_AUTH.getMessage()
);
}
/**
* Shiro
*/
@ExceptionHandler(UnsupportedTokenException.class)
@ResponseStatus(HttpStatus.OK)
@ResponseBody
public ResultVo<?> unsupportedTokenException(UnsupportedTokenException e) {
// 找不到认证授权器
return ResultVo.error(TokenMsg.EXCEPTION_NOT_REALM.getCode(),
TokenMsg.EXCEPTION_NOT_REALM.getMessage()
);
}
/** /**
* Token * Token
*/ */
@ExceptionHandler(TokenException.class) @ExceptionHandler(TokenException.class)
@ResponseStatus(HttpStatus.OK) @ResponseStatus(HttpStatus.OK)
@ResponseBody @ResponseBody
public ResultVo<?> tokenException(TokenException e) { public ResultWrapper<?> tokenException(TokenException e) {
// Token 异常 // Token 异常
return ResultVo.error(e.getCode(), e.getMessage()); return ResultWrapper.getCustomResultWrapper(e.getCode(), e.getMessage());
} }
/** /**
@ -177,8 +123,8 @@ public class GlobalExceptionHandler {
@ExceptionHandler(WafException.class) @ExceptionHandler(WafException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST) @ResponseStatus(HttpStatus.BAD_REQUEST)
@ResponseBody @ResponseBody
public ResultVo<?> wafException(WafException e) { public ResultWrapper<?> wafException(WafException e) {
return ResultVo.error(e.getCode(), e.getMessage()); return ResultWrapper.getCustomResultWrapper(e.getCode(), e.getMessage());
} }
// ============================ // ============================
@ -189,9 +135,9 @@ public class GlobalExceptionHandler {
@ExceptionHandler(NullPointerException.class) @ExceptionHandler(NullPointerException.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ResponseBody @ResponseBody
public ResultVo<?> nullPointerException(NullPointerException e) { public ResultWrapper<?> nullPointerException(NullPointerException e) {
log.error("空指针异常:{}",e.getMessage(),e); log.error("空指针异常:{}",e.getMessage(),e);
return ResultVo.error(e.getMessage()); return ResultWrapper.getErrorResultWrapper();
} }
@ -201,9 +147,9 @@ public class GlobalExceptionHandler {
@ExceptionHandler(SQLIntegrityConstraintViolationException.class) @ExceptionHandler(SQLIntegrityConstraintViolationException.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ResponseBody @ResponseBody
public ResultVo<?> sqlIntegrityConstraintViolationException(EmptyException e) { public ResultWrapper<?> sqlIntegrityConstraintViolationException(EmptyException e) {
log.error("数据异常:{}",e.getMessage(),e); log.error("数据异常:{}",e.getMessage(),e);
return ResultVo.error(e.getCode(), CoreMsg.SQL_EXCEPTION_INTEGRITY_CONSTRAINT_VIOLATION.getMessage()); return ResultWrapper.getCustomResultWrapper(e.getCode(), CoreMsg.SQL_EXCEPTION_INTEGRITY_CONSTRAINT_VIOLATION.getMessage());
} }
/** /**
@ -212,17 +158,17 @@ public class GlobalExceptionHandler {
@ExceptionHandler(SQLException.class) @ExceptionHandler(SQLException.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ResponseBody @ResponseBody
public ResultVo<?> sqlException(SQLException e) { public ResultWrapper<?> sqlException(SQLException e) {
//log.error("数据异常:{}",e.getMessage(),e); //log.error("数据异常:{}",e.getMessage(),e);
// 默认值异常 // 默认值异常
if(StringUtils.contains(e.getMessage(),SQL_EXCEPTION)){ if(StringUtils.contains(e.getMessage(),SQL_EXCEPTION)){
String field = e.getMessage().replaceAll("Field '","") String field = e.getMessage().replaceAll("Field '","")
.replaceAll("' doesn't have a default value",""); .replaceAll("' doesn't have a default value","");
String msg = StrFormatter.format(CoreMsg.SQL_EXCEPTION_NOT_HAVE_DEFAULT_VALUE.getMessage(), field); String msg = StrFormatter.format(CoreMsg.SQL_EXCEPTION_NOT_HAVE_DEFAULT_VALUE.getMessage(), field);
return ResultVo.error(CoreMsg.SQL_EXCEPTION_NOT_HAVE_DEFAULT_VALUE.getCode(), msg); return ResultWrapper.getCustomResultWrapper(CoreMsg.SQL_EXCEPTION_NOT_HAVE_DEFAULT_VALUE.getCode(), msg);
} }
String msg = StrFormatter.format(CoreMsg.SQL_EXCEPTION_UNKNOWN.getMessage(), e.getMessage()); String msg = StrFormatter.format(CoreMsg.SQL_EXCEPTION_UNKNOWN.getMessage(), e.getMessage());
return ResultVo.error(CoreMsg.SQL_EXCEPTION_UNKNOWN.getCode(), msg); return ResultWrapper.getCustomResultWrapper(CoreMsg.SQL_EXCEPTION_UNKNOWN.getCode(), msg);
} }
} }

@ -28,7 +28,7 @@ import java.util.Optional;
/** /**
* *
* *
* @author * @author Parker
* @date 2021122216:22:59 * @date 2021122216:22:59
*/ */
public final class UserContextHolder { public final class UserContextHolder {

@ -0,0 +1,84 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.core.log.annotation;
import org.opsli.core.log.enums.*;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
*
*
* @author Parker
* @date 202171520:28:24
*/
@Target({ElementType.METHOD}) //注解作用于方法级别
@Retention(RetentionPolicy.RUNTIME) //运行时起作用
public @interface OperateLogger {
/**
*
*/
boolean loggable() default true;
/**
*
* 使: ${tel}
*/
String description() default "";
/**
*
*/
ModuleEnum module() default ModuleEnum.MODULE_COMMON;
/**
* (enum): select,insert,update,delete
*/
OperationTypeEnum operationType() default OperationTypeEnum.UNKNOWN;
/**
*
*/
LogTypeEnum type() default LogTypeEnum.BACKEND;
/**
*
*/
LogLevelEnum level() default LogLevelEnum.INFO;
/**
* ,
* ALL-, BEFORE-, AFTER-
*/
LogScopeEnum scope() default LogScopeEnum.ALL;
/**
*
*/
boolean db() default false;
/**
*
*/
boolean console() default true;
}

@ -0,0 +1,220 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.core.log.aspect;
import cn.hutool.json.JSONUtil;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.opsli.common.utils.MessUtil;
import org.opsli.core.base.dto.LoginUserDto;
import org.opsli.core.holder.UserContextHolder;
import org.opsli.core.log.annotation.OperateLogger;
import org.opsli.core.log.bean.OperationLog;
import org.opsli.core.log.bus.OperationLogEventBus;
import org.opsli.core.log.enums.LogLevelEnum;
import org.opsli.core.log.enums.LogScopeEnum;
import org.opsli.core.utils.UserTokenUtil;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
/**
*
*
* @author Parker
* @date 202171520:28:24
*/
@Slf4j
@Aspect
@Component
@Order(50)
public class OperateLogAspect {
/** 替换条件 */
private static final String RE = "\\$\\{([\\w\\.\\-\\/\\+\\$\\#\\@\\!\\^\\&\\(\\)]+)\\}";
@Resource
private OperationLogEventBus operationLogEventBus;
@Pointcut("@annotation(org.opsli.core.log.annotation.OperateLogger)")
public void operationLog(){}
/**
* MethodInterceptor
*/
@Around("operationLog()")
public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
Object result = null;
long time = System.currentTimeMillis();
try {
result = joinPoint.proceed();
return result;
} finally {
time = System.currentTimeMillis() - time;
try {
// 方法执行完成后增加日志
addOperationLog(joinPoint, result, time);
}catch (Exception e){
log.error("LogAspect 操作失败:{}" + e.getMessage());
e.printStackTrace();
}
}
}
/**
*
* @param joinPoint point
* @param result
* @param time
*/
private void addOperationLog(JoinPoint joinPoint, Object result, long time){
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
OperateLogger annotation = signature.getMethod()
.getAnnotation(OperateLogger.class);
if(annotation == null || !annotation.loggable()){
return;
}
OperationLog operationLog = new OperationLog();
// 参数
String argsStr = null;
try {
argsStr = JSONUtil.toJsonStr(joinPoint.getArgs());
}catch (Exception ignored){}
// 结果
String resultStr = null;
try {
resultStr = JSONUtil.toJsonStr(result);
}catch (Exception ignored){}
if(LogScopeEnum.REQUEST.equals(annotation.scope())){
operationLog.setArgs(argsStr);
} else if(LogScopeEnum.RESPONSE.equals(annotation.scope())){
operationLog.setReturnValue(resultStr);
} else if(LogScopeEnum.ALL.equals(annotation.scope())){
operationLog.setArgs(argsStr);
operationLog.setReturnValue(resultStr);
}
operationLog.setId(UUID.randomUUID().toString());
operationLog.setRunTime(time);
operationLog.setCreateTime(System.currentTimeMillis());
operationLog.setMethod(signature.getDeclaringTypeName() + "." + signature.getName());
operationLog.setLevel(annotation.level().getValue());
operationLog.setDescription(
// 对当前登录用户和占位符处理
getDetail(
((MethodSignature) joinPoint.getSignature()).getParameterNames(),
joinPoint.getArgs(),
annotation)
);
operationLog.setOperationType(annotation.operationType().getValue());
operationLog.setLogType(annotation.type().getValue());
operationLog.setModuleId(annotation.module().getId());
// 当前Token
Optional<String> tokenOptional = UserContextHolder.getToken();
if(tokenOptional.isPresent()){
LoginUserDto loginUserDto = UserTokenUtil.getLoginUserDto(tokenOptional.get()).orElse(null);
if(null != loginUserDto){
operationLog.setUserId(String.valueOf(loginUserDto.getUid()));
operationLog.setUsername(loginUserDto.getUsername());
operationLog.setRealName(loginUserDto.getNickname());
operationLog.setTenantId(loginUserDto.getTenantId());
}
}
// 输出控制台
if(annotation.console()){
printToConsole(annotation.level(), operationLog);
}
// 存入数据库
if(annotation.db()){
operationLogEventBus.post(operationLog);
}
}
/**
*
* @param level
* @param operationLog
*/
private void printToConsole(LogLevelEnum level, OperationLog operationLog){
switch (level){
case INFO:
log.info("记录日志:{}" , operationLog);
break;
case DEBUG:
log.debug("记录日志:{}" , operationLog);
break;
case WARN:
log.warn("记录日志:{}" , operationLog);
break;
case ERROR:
log.error("记录日志:{}" , operationLog);
break;
case TRACE:
log.trace("记录日志:{}" , operationLog);
break;
default:
break;
}
}
/**
*
* @param argNames
* @param args
* @param annotation
* @return
*/
private String getDetail(String[] argNames, Object[] args, OperateLogger annotation){
Map<String, Object> map = Maps.newHashMap();
for(int i = 0;i < argNames.length;i++){
map.put(argNames[i], args[i]);
}
String description = annotation.description();
try {
// 当前用户信息
Optional<String> tokenOptional = UserContextHolder.getToken();
if(tokenOptional.isPresent()){
LoginUserDto loginUserDto = UserTokenUtil.getLoginUserDto(tokenOptional.get()).orElse(null);
if(null != loginUserDto){
description = "'" + loginUserDto.getNickname() + "'=> " + annotation.description();
}
}
description = MessUtil.getMes(description, RE, "${", "}", map);
}catch (Exception e){
e.printStackTrace();
}
return description;
}
}

@ -0,0 +1,82 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.core.log.bean;
import lombok.Data;
import lombok.ToString;
import java.io.Serializable;
/**
*
*
* @author Parker
* @date 202171520:28:24
*/
@Data
@ToString
public class OperationLog implements Serializable {
private static final long serialVersionUID = 1L;
/** 日志ID */
private String id;
/** 创建时间 */
private long createTime;
/** 日志等级 */
private String level;
/** 被操作的系统模块 */
private String moduleId;
/** 方法名 */
private String method;
/** 参数 */
private String args;
/** 操作人id */
private String userId;
/** 操作人用户名 */
private String username;
/** 真实姓名 */
private String realName;
/** 日志描述 */
private String description;
/** 操作类型 */
private String operationType;
/** 方法运行时间 */
private Long runTime;
/** 方法返回值 */
private String returnValue;
/** 租户ID */
private String tenantId;
/**
*
*/
private String logType;
}

@ -0,0 +1,72 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.core.log.bus;
import com.google.common.eventbus.AsyncEventBus;
import com.google.common.eventbus.EventBus;
import com.google.common.eventbus.SubscriberExceptionContext;
import com.google.common.eventbus.SubscriberExceptionHandler;
import lombok.extern.slf4j.Slf4j;
import org.opsli.common.thread.ThreadPoolFactory;
import org.opsli.core.eventbus.AbstractSpringEventBus;
import org.springframework.stereotype.Component;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* 线
* @author
* @date 202112710:42:39
*/
@Component
@Slf4j
public class OperationLogEventBus extends AbstractSpringEventBus implements SubscriberExceptionHandler {
private final EventBus eventBus;
public OperationLogEventBus() {
// 异步事件配置线程池
eventBus = new AsyncEventBus(
ThreadPoolFactory.createInitThreadPool(5, 10, 60, TimeUnit.SECONDS,
1024, "Operation-Log-Event-Bus",
new ThreadPoolExecutor.CallerRunsPolicy()
)
, this
);
}
@Override
public void post(Object event) {
eventBus.post(event);
}
@Override
public void addConsumer(Object obj) {
eventBus.register(obj);
}
@Override
public void removeConsumer(Object obj) {
eventBus.unregister(obj);
}
@Override
public void handleException(Throwable exception, SubscriberExceptionContext context) {
log.error("user event handler exception", exception);
}
}

@ -13,23 +13,29 @@
* License for the specific language governing permissions and limitations under * License for the specific language governing permissions and limitations under
* the License. * the License.
*/ */
package org.opsli.common.annotation; package org.opsli.core.log.enums;
import java.lang.annotation.ElementType; import lombok.AllArgsConstructor;
import java.lang.annotation.Retention; import lombok.Getter;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/** /**
* *
* *
* @author Parker * @author Parker
* @date 2020-09-22 17:07 * @date 202171520:28:24
*/ */
@Target({ElementType.TYPE, ElementType.METHOD}) @Getter
@Retention(RetentionPolicy.RUNTIME) @AllArgsConstructor
public @interface RequiresPermissionsCus { public enum LogLevelEnum {
String[] value(); /**
*
*/
DEBUG("-1"),
INFO("0"),
WARN("1"),
ERROR("2"),
TRACE("3");
private final String value;
} }

@ -13,25 +13,31 @@
* License for the specific language governing permissions and limitations under * License for the specific language governing permissions and limitations under
* the License. * the License.
*/ */
package org.opsli.common.annotation; package org.opsli.core.log.enums;
import java.lang.annotation.*;
/** /**
* *
*
*
* *
* @author Parker * @author Parker
* @date 202151814:46:02 * @date 202171520:28:24
*/ */
@Target(ElementType.METHOD) public enum LogScopeEnum {
@Retention(RetentionPolicy.RUNTIME)
@Documented /**
public @interface LoginCrypto { *
*/
ALL(0),
REQUEST(1),
RESPONSE(2)
;
private final int value;
/** 加密启用状态 */ public int getValue() {
boolean enable() default true; return value;
}
LogScopeEnum(int value) {
this.value = value;
}
} }

@ -13,25 +13,36 @@
* License for the specific language governing permissions and limitations under * License for the specific language governing permissions and limitations under
* the License. * the License.
*/ */
package org.opsli.common.annotation; package org.opsli.core.log.enums;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/** /**
* *
* @author parker *
* @date 2020-09-12 * @author Parker
* @date 202171520:28:24
*/ */
@Target(ElementType.METHOD) public enum LogTypeEnum {
@Retention(RetentionPolicy.RUNTIME)
@Documented /** WEB */
public @interface EnableLog { WEB("0"),
/** 客户端 */
CLIENT("1"),
/** 后端 */
BACKEND("2"),
/** 程序自动 */
AUTO("3")
;
private final String value;
/** 标题 */ public String getValue() {
String title() default ""; return value;
}
LogTypeEnum(String value) {
this.value = value;
}
} }

@ -0,0 +1,66 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.core.log.enums;
/**
*
*
* @author Parker
* @date 202171520:19:27
*/
public enum ModuleEnum {
/** 模块 */
MODULE_UNKNOWN("-1", "未知(请配置模块)"),
MODULE_COMMON("00", "公共模块"),
MODULE_USER("01", "用户模块"),
MODULE_ROLE("02", "角色模块"),
MODULE_MENU("03", "菜单模块"),
MODULE_ORG("04", "组织模块"),
MODULE_DICT("05", "字典模块"),
MODULE_TENANT("06", "租户模块"),
MODULE_AREA("07", "地区模块"),
MODULE_MONITOR("08", "监控模块"),
MODULE_GENERATOR("09", "代码生成器"),
MODULE_OPERATION("11", "行为日志"),
MODULE_TEST("100", "测试模块"),
MODULE_TEST_USER("101", "测试用户模块"),
MODULE_TEST_CAR("102", "测试汽车模块"),
;
private final String id;
private final String name;
ModuleEnum(String id, String name) {
this.id = id;
this.name = name;
}
public String getId() {
return id;
}
public String getName() {
return name;
}
}

@ -0,0 +1,48 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.core.log.enums;
/**
*
*
* @author Parker
* @date 202171520:27:27
*/
public enum OperationTypeEnum {
/**
*
*/
UNKNOWN("unknown"),
DELETE("delete"),
SELECT("select"),
UPDATE("update"),
INSERT("insert");
private String value;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
OperationTypeEnum(String s) {
this.value = s;
}
}

@ -30,14 +30,20 @@ public enum TokenMsg implements BaseMsg {
*/ */
EXCEPTION_TOKEN_CREATE_ERROR(12000,"生成Token失败"), EXCEPTION_TOKEN_CREATE_ERROR(12000,"生成Token失败"),
EXCEPTION_TOKEN_CREATE_LIMIT_ERROR(12001,"您的账号已在其他设备登录"), EXCEPTION_TOKEN_CREATE_LIMIT_ERROR(12001,"您的账号已在其他设备登录"),
EXCEPTION_TOKEN_LOSE_EFFICACY(401,"Token失效请重新登录"), EXCEPTION_TOKEN_LOSE_EFFICACY(401,"凭证已过期,请重新登陆"),
AUTH_CREDENTIALS_INVALID(100208, "凭证已过期,请重新登陆"),
AUTH_AUTH_INVALID(100209, "认证失败,请重新登陆"),
/** /**
* *
*/ */
EXCEPTION_CAPTCHA_CERTIFICATE_ERROR(12097, "凭证验证失败,请刷新重试"),
EXCEPTION_CAPTCHA_ARGS_NULL(12098, "参数异常"),
EXCEPTION_CAPTCHA_OFTEN(12099, "已获取验证码,请勿频繁获取"),
EXCEPTION_CAPTCHA_ERROR(12100,"验证码不正确!"), EXCEPTION_CAPTCHA_ERROR(12100,"验证码不正确!"),
EXCEPTION_CAPTCHA_NULL(12201, "验证码已失效"), EXCEPTION_CAPTCHA_NULL(12201, "验证码已失效, 请重新生成"),
EXCEPTION_CAPTCHA_UUID_NULL(12202, "验证码UUID为空"), EXCEPTION_CAPTCHA_UUID_NULL(12202, "验证码UUID为空"),
EXCEPTION_CAPTCHA_CODE_NULL(12203, "验证码为空"), EXCEPTION_CAPTCHA_CODE_NULL(12203, "验证码为空"),
EXCEPTION_LOGIN_ACCOUNT_NO(12101,"账号或密码不正确!"), EXCEPTION_LOGIN_ACCOUNT_NO(12101,"账号或密码不正确!"),

@ -0,0 +1,81 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.core.options;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.opsli.common.annotation.OptionDict;
import org.opsli.common.annotation.validator.Validator;
import org.opsli.common.enums.ValidatorType;
import org.opsli.core.utils.OptionsUtil;
import org.opsli.core.utils.ValidatorUtil;
import java.io.Serializable;
/**
* -
*
* @author Parker
* @date 2020-09-19 20:03
*/
public enum SmsAliYunCaptchaConfigFactory {
/** 实例对象 */
INSTANCE;
/**
*
* @return LocalConfig
*/
public SmsAliYunCaptchaConfigOption getConfig() {
SmsAliYunCaptchaConfigOption option = new SmsAliYunCaptchaConfigOption();
// 获得缓存参数配置
OptionsUtil.getOptionByBean(option);
// 验证配置
ValidatorUtil.verify(option);
// 转化对象
return option;
}
// =======================
/**
*
*
* @author Parker
*/
@Data
public static class SmsAliYunCaptchaConfigOption implements Serializable {
private static final long serialVersionUID = 1L;
/** 模版编码 */
@ApiModelProperty(value = "模版编码")
@Validator({ValidatorType.IS_NOT_NULL})
@OptionDict("sms_aliyun_captcha_template_code")
private String templateCode;
/** 签名 */
@ApiModelProperty(value = "签名")
@Validator({ValidatorType.IS_NOT_NULL})
@OptionDict("sms_aliyun_captcha_sign")
private String sign;
}
}

@ -0,0 +1,81 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.core.options;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.opsli.common.annotation.OptionDict;
import org.opsli.common.annotation.validator.Validator;
import org.opsli.common.enums.ValidatorType;
import org.opsli.core.utils.OptionsUtil;
import org.opsli.core.utils.ValidatorUtil;
import java.io.Serializable;
/**
*
*
* @author Parker
* @date 2020-09-19 20:03
*/
public enum SmsAliYunConfigFactory {
/** 实例对象 */
INSTANCE;
/**
*
* @return LocalConfig
*/
public SmsAliYunConfigOption getConfig() {
SmsAliYunConfigOption option = new SmsAliYunConfigOption();
// 获得缓存参数配置
OptionsUtil.getOptionByBean(option);
// 验证配置
ValidatorUtil.verify(option);
// 转化对象
return option;
}
// =======================
/**
*
*
* @author Parker
*/
@Data
public static class SmsAliYunConfigOption implements Serializable {
private static final long serialVersionUID = 1L;
/** access_key */
@ApiModelProperty(value = "阿里云AccessKey")
@Validator({ValidatorType.IS_NOT_NULL})
@OptionDict("sms_aliyun_access_key")
private String accessKey;
/** access_key_secret */
@ApiModelProperty(value = "阿里云AccessKeySecret")
@Validator({ValidatorType.IS_NOT_NULL})
@OptionDict("sms_aliyun_access_key_secret")
private String accessKeySecret;
}
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save