This commit is contained in:
清晨
2025-04-08 16:37:17 +08:00
commit 0c9d340a05
1659 changed files with 170293 additions and 0 deletions

View File

@@ -0,0 +1,261 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>ruoyi-base-support</artifactId>
<groupId>com.ruoyi</groupId>
<version>3.7.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>ruoyi-common</artifactId>
<description>
common通用工具
</description>
<dependencies>
<!-- Spring框架基本的核心工具 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
</dependency>
<!-- SpringWeb模块 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</dependency>
<!-- spring security 安全认证 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- pagehelper 分页插件 -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
</dependency>
<!-- mybatis-plus -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-extension</artifactId>
</dependency>
<!-- 自定义验证注解 -->
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
</dependency>
<!--常用工具类 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<!-- JSON工具类 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<!-- 阿里JSON解析器 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</dependency>
<!-- io常用工具类 -->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
</dependency>
<!-- 文件上传工具类 -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
</dependency>
<!-- excel工具 -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
</dependency>
<!-- yml解析器 -->
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
</dependency>
<!--Token生成与解析-->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
</dependency>
<!-- redis 缓存操作 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- pool 对象池 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
<!-- 解析客户端操作系统、浏览器等 -->
<dependency>
<groupId>eu.bitwalker</groupId>
<artifactId>UserAgentUtils</artifactId>
</dependency>
<!-- servlet包 -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-core</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.3.7</version>
</dependency>
<dependency>
<groupId>com.documents4j</groupId>
<artifactId>documents4j-local</artifactId>
<version>1.0.3</version>
</dependency>
<dependency>
<groupId>com.documents4j</groupId>
<artifactId>documents4j-transformer-msoffice-word</artifactId>
<version>1.0.3</version>
</dependency>
<!-- word转图工具 -->
<dependency>
<groupId>com.deepoove</groupId>
<artifactId>poi-tl</artifactId>
<version>1.8.0</version>
</dependency>
<dependency>
<groupId>org.jodconverter</groupId>
<artifactId>jodconverter-core</artifactId>
<version>4.1.0</version>
</dependency>
<dependency>
<groupId>org.jodconverter</groupId>
<artifactId>jodconverter-local</artifactId>
<version>4.1.0</version>
</dependency>
<dependency>
<groupId>org.jodconverter</groupId>
<artifactId>jodconverter-spring-boot-starter</artifactId>
<version>4.1.0</version>
</dependency>
<dependency>
<groupId>org.libreoffice</groupId>
<artifactId>juh</artifactId>
<version>5.4.2</version>
</dependency>
<dependency>
<groupId>org.libreoffice</groupId>
<artifactId>jurt</artifactId>
<version>5.4.2</version>
</dependency>
<dependency>
<groupId>org.libreoffice</groupId>
<artifactId>ridl</artifactId>
<version>5.4.2</version>
</dependency>
<dependency>
<groupId>org.libreoffice</groupId>
<artifactId>unoil</artifactId>
<version>5.4.2</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.2</version>
</dependency>
<dependency>
<groupId>com.tencentcloudapi</groupId>
<artifactId>tencentcloud-sdk-java</artifactId>
<version>3.1.1065</version>
</dependency>
<dependency>
<groupId>com.aspose</groupId>
<artifactId>aspose-words</artifactId>
<version>15.8.0-jdk16</version>
</dependency>
<!--goeasy——sdk-->
<dependency>
<groupId>io.goeasy</groupId>
<artifactId>goeasy-sdk</artifactId>
<version>0.4.2</version>
</dependency>
<dependency>
<groupId>com.qcloud</groupId>
<artifactId>cos-sts_api</artifactId>
<version>3.1.0</version>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,17 @@
package com.ruoyi.common.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 自动设置创建人
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
public @interface CreateBy {
String value() default "";
}

View File

@@ -0,0 +1,16 @@
package com.ruoyi.common.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 自动设置创建时间
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
public @interface CreateTime {
String value() default "";
}

View File

@@ -0,0 +1,24 @@
package com.ruoyi.common.annotation;
import java.lang.annotation.*;
/**
* 数据权限过滤注解
*
* @author ruoyi
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DataScope
{
/**
* 部门表的别名
*/
public String deptAlias() default "";
/**
* 用户表的别名
*/
public String userAlias() default "";
}

View File

@@ -0,0 +1,24 @@
package com.ruoyi.common.annotation;
import com.ruoyi.common.enums.DataSourceType;
import java.lang.annotation.*;
/**
* 自定义多数据源切换注解
*
* 优先级:先方法,后类,如果方法覆盖了类上的数据源类型,以方法的为准,否则以类上的为准
*
* @author ruoyi
*/
@Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface DataSource
{
/**
* 切换数据源名称
*/
public DataSourceType value() default DataSourceType.MASTER;
}

View File

@@ -0,0 +1,177 @@
package com.ruoyi.common.annotation;
import com.ruoyi.common.utils.poi.ExcelHandlerAdapter;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.math.BigDecimal;
/**
* 自定义导出Excel数据注解
*
* @author ruoyi
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Excel
{
/**
* 导出时在excel中排序
*/
public int sort() default Integer.MAX_VALUE;
/**
* 导出到Excel中的名字.
*/
public String name() default "";
/**
* 日期格式, 如: yyyy-MM-dd
*/
public String dateFormat() default "";
/**
* 如果是字典类型请设置字典的type值 (如: sys_user_sex)
*/
public String dictType() default "";
/**
* 读取内容转表达式 (如: 0=男,1=女,2=未知)
*/
public String readConverterExp() default "";
/**
* 分隔符,读取字符串组内容
*/
public String separator() default ",";
/**
* BigDecimal 精度 默认:-1(默认不开启BigDecimal格式化)
*/
public int scale() default -1;
/**
* BigDecimal 舍入规则 默认:BigDecimal.ROUND_HALF_EVEN
*/
public int roundingMode() default BigDecimal.ROUND_HALF_EVEN;
/**
* 导出类型0数字 1字符串
*/
public ColumnType cellType() default ColumnType.STRING;
/**
* 导出时在excel中每个列的高度 单位为字符
*/
public double height() default 14;
/**
* 导出时在excel中每个列的宽 单位为字符
*/
public double width() default 16;
/**
* 文字后缀,如% 90 变成90%
*/
public String suffix() default "";
/**
* 当值为空时,字段的默认值
*/
public String defaultValue() default "";
/**
* 提示信息
*/
public String prompt() default "";
/**
* 设置只能选择不能输入的列内容.
*/
public String[] combo() default {};
/**
* 是否导出数据,应对需求:有时我们需要导出一份模板,这是标题需要但内容需要用户手工填写.
*/
public boolean isExport() default true;
/**
* 另一个类中的属性名称,支持多级获取,以小数点隔开
*/
public String targetAttr() default "";
/**
* 是否自动统计数据,在最后追加一行统计数据总和
*/
public boolean isStatistics() default false;
/**
* 导出字段对齐方式0默认1靠左2居中3靠右
*/
public Align align() default Align.AUTO;
/**
* 自定义数据处理器
*/
public Class<?> handler() default ExcelHandlerAdapter.class;
/**
* 自定义数据处理器参数
*/
public String[] args() default {};
public enum Align
{
AUTO(0), LEFT(1), CENTER(2), RIGHT(3);
private final int value;
Align(int value)
{
this.value = value;
}
public int value()
{
return this.value;
}
}
/**
* 字段类型0导出导入1仅导出2仅导入
*/
Type type() default Type.ALL;
public enum Type
{
ALL(0), EXPORT(1), IMPORT(2);
private final int value;
Type(int value)
{
this.value = value;
}
public int value()
{
return this.value;
}
}
public enum ColumnType
{
NUMERIC(0), STRING(1), IMAGE(2);
private final int value;
ColumnType(int value)
{
this.value = value;
}
public int value()
{
return this.value;
}
}
}

View File

@@ -0,0 +1,18 @@
package com.ruoyi.common.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Excel注解集
*
* @author ruoyi
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Excels
{
public Excel[] value();
}

View File

@@ -0,0 +1,43 @@
package com.ruoyi.common.annotation;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.enums.OperatorType;
import java.lang.annotation.*;
/**
* 自定义操作日志记录注解
*
* @author ruoyi
*
*/
@Target({ ElementType.PARAMETER, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Log
{
/**
* 模块
*/
public String title() default "";
/**
* 功能
*/
public BusinessType businessType() default BusinessType.OTHER;
/**
* 操作人类别
*/
public OperatorType operatorType() default OperatorType.MANAGE;
/**
* 是否保存请求的参数
*/
public boolean isSaveRequestData() default true;
/**
* 是否保存响应的参数
*/
public boolean isSaveResponseData() default true;
}

View File

@@ -0,0 +1,37 @@
package com.ruoyi.common.annotation;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.enums.LimitType;
import java.lang.annotation.*;
/**
* 限流注解
*
* @author ruoyi
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RateLimiter
{
/**
* 限流key
*/
public String key() default Constants.RATE_LIMIT_KEY;
/**
* 限流时间,单位秒
*/
public int time() default 60;
/**
* 限流次数
*/
public int count() default 100;
/**
* 限流类型
*/
public LimitType limitType() default LimitType.DEFAULT;
}

View File

@@ -0,0 +1,26 @@
package com.ruoyi.common.annotation;
import java.lang.annotation.*;
/**
* 自定义注解防止表单重复提交
*
* @author ruoyi
*
*/
@Inherited
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RepeatSubmit
{
/**
* 间隔时间(ms),小于此时间视为重复提交
*/
public int interval() default 5000;
/**
* 提示消息
*/
public String message() default "不允许重复提交,请稍后再试";
}

View File

@@ -0,0 +1,16 @@
package com.ruoyi.common.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 自动设置修改人
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
public @interface UpdateBy {
String value() default "";
}

View File

@@ -0,0 +1,16 @@
package com.ruoyi.common.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 自动设置修改时间
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
public @interface UpdateTime {
String value() default "";
}

View File

@@ -0,0 +1,124 @@
package com.ruoyi.common.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 读取项目相关配置
*
* @author ruoyi
*/
@Component
@ConfigurationProperties(prefix = "ruoyi")
public class RuoYiConfig
{
/** 项目名称 */
private String name;
/** 版本 */
private String version;
/** 版权年份 */
private String copyrightYear;
/** 实例演示开关 */
private boolean demoEnabled;
/** 上传路径 */
private static String profile;
/** 获取地址开关 */
private static boolean addressEnabled;
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public String getVersion()
{
return version;
}
public void setVersion(String version)
{
this.version = version;
}
public String getCopyrightYear()
{
return copyrightYear;
}
public void setCopyrightYear(String copyrightYear)
{
this.copyrightYear = copyrightYear;
}
public boolean isDemoEnabled()
{
return demoEnabled;
}
public void setDemoEnabled(boolean demoEnabled)
{
this.demoEnabled = demoEnabled;
}
public static String getProfile()
{
return profile;
}
public void setProfile(String profile)
{
RuoYiConfig.profile = profile;
}
public static boolean isAddressEnabled()
{
return addressEnabled;
}
public void setAddressEnabled(boolean addressEnabled)
{
RuoYiConfig.addressEnabled = addressEnabled;
}
/**
* 获取导入上传路径
*/
public static String getImportPath()
{
return getProfile() + "/import";
}
/**
* 获取头像上传路径
*/
public static String getAvatarPath()
{
return getProfile() + "/avatar";
}
/**
* 获取下载路径
*/
public static String getDownloadPath()
{
return getProfile() + "/download/";
}
/**
* 获取上传路径
*/
public static String getUploadPath()
{
return getProfile() + "/upload";
}
}

View File

@@ -0,0 +1,151 @@
package com.ruoyi.common.constant;
import io.jsonwebtoken.Claims;
/**
* 通用常量信息
*
* @author ruoyi
*/
public class Constants
{
/**
* UTF-8 字符集
*/
public static final String UTF8 = "UTF-8";
/**
* GBK 字符集
*/
public static final String GBK = "GBK";
/**
* http请求
*/
public static final String HTTP = "http://";
/**
* https请求
*/
public static final String HTTPS = "https://";
/**
* 通用成功标识
*/
public static final String SUCCESS = "0";
/**
* 通用失败标识
*/
public static final String FAIL = "1";
/**
* 登录成功
*/
public static final String LOGIN_SUCCESS = "Success";
/**
* 注销
*/
public static final String LOGOUT = "Logout";
/**
* 注册
*/
public static final String REGISTER = "Register";
/**
* 登录失败
*/
public static final String LOGIN_FAIL = "Error";
/**
* 验证码 redis key
*/
public static final String CAPTCHA_CODE_KEY = "captcha_codes:";
/**
* 登录用户 redis key
*/
public static final String LOGIN_TOKEN_KEY = "login_tokens:";
/**
* 防重提交 redis key
*/
public static final String REPEAT_SUBMIT_KEY = "repeat_submit:";
/**
* 限流 redis key
*/
public static final String RATE_LIMIT_KEY = "rate_limit:";
/**
* 验证码有效期(分钟)
*/
public static final Integer CAPTCHA_EXPIRATION = 2;
/**
* 令牌
*/
public static final String TOKEN = "token";
/**
* 令牌前缀
*/
public static final String TOKEN_PREFIX = "Bearer ";
/**
* 令牌前缀
*/
public static final String LOGIN_USER_KEY = "login_user_key";
/**
* 用户ID
*/
public static final String JWT_USERID = "userid";
/**
* 用户名称
*/
public static final String JWT_USERNAME = Claims.SUBJECT;
/**
* 用户头像
*/
public static final String JWT_AVATAR = "avatar";
/**
* 创建时间
*/
public static final String JWT_CREATED = "created";
/**
* 用户权限
*/
public static final String JWT_AUTHORITIES = "authorities";
/**
* 参数管理 cache key
*/
public static final String SYS_CONFIG_KEY = "sys_config:";
/**
* 字典管理 cache key
*/
public static final String SYS_DICT_KEY = "sys_dict:";
/**
* 资源映射路径 前缀
*/
public static final String RESOURCE_PREFIX = "/profile";
/**
* RMI 远程方法调用
*/
public static final String LOOKUP_RMI = "rmi://";
/**
* LDAP 远程方法调用
*/
public static final String LOOKUP_LDAP = "ldap://";
}

View File

@@ -0,0 +1,117 @@
package com.ruoyi.common.constant;
/**
* 代码生成通用常量
*
* @author ruoyi
*/
public class GenConstants
{
/** 单表(增删改查) */
public static final String TPL_CRUD = "crud";
/** 树表(增删改查) */
public static final String TPL_TREE = "tree";
/** 主子表(增删改查) */
public static final String TPL_SUB = "sub";
/** 树编码字段 */
public static final String TREE_CODE = "treeCode";
/** 树父编码字段 */
public static final String TREE_PARENT_CODE = "treeParentCode";
/** 树名称字段 */
public static final String TREE_NAME = "treeName";
/** 上级菜单ID字段 */
public static final String PARENT_MENU_ID = "parentMenuId";
/** 上级菜单名称字段 */
public static final String PARENT_MENU_NAME = "parentMenuName";
/** 数据库字符串类型 */
public static final String[] COLUMNTYPE_STR = { "char", "varchar", "nvarchar", "varchar2" };
/** 数据库文本类型 */
public static final String[] COLUMNTYPE_TEXT = { "tinytext", "text", "mediumtext", "longtext" };
/** 数据库时间类型 */
public static final String[] COLUMNTYPE_TIME = { "datetime", "time", "date", "timestamp" };
/** 数据库数字类型 */
public static final String[] COLUMNTYPE_NUMBER = { "tinyint", "smallint", "mediumint", "int", "number", "integer",
"bit", "bigint", "float", "double", "decimal" };
/** 数据库数字类型 */
public static final String[] COLUMNTYPE_INT = { "tinyint", "smallint", "mediumint", "int", "number", "integer"};
/** 页面不需要编辑字段 */
public static final String[] COLUMNNAME_NOT_EDIT = { "id", "create_by", "create_time", "del_flag" };
/** 页面不需要显示的列表字段 */
public static final String[] COLUMNNAME_NOT_LIST = { "id", "create_by", "create_time", "del_flag", "update_by",
"update_time" };
/** 页面不需要查询字段 */
public static final String[] COLUMNNAME_NOT_QUERY = { "id", "create_by", "create_time", "del_flag", "update_by",
"update_time", "remark" };
/** Entity基类字段 */
public static final String[] BASE_ENTITY = { "createBy", "createTime", "updateBy", "updateTime", "remark" };
/** Tree基类字段 */
public static final String[] TREE_ENTITY = { "parentName", "parentId", "orderNum", "ancestors", "children" };
/** 文本框 */
public static final String HTML_INPUT = "input";
/** 文本域 */
public static final String HTML_TEXTAREA = "textarea";
/** 下拉框 */
public static final String HTML_SELECT = "select";
/** 单选框 */
public static final String HTML_RADIO = "radio";
/** 复选框 */
public static final String HTML_CHECKBOX = "checkbox";
/** 日期控件 */
public static final String HTML_DATETIME = "datetime";
/** 图片上传控件 */
public static final String HTML_IMAGE_UPLOAD = "imageUpload";
/** 文件上传控件 */
public static final String HTML_FILE_UPLOAD = "fileUpload";
/** 富文本控件 */
public static final String HTML_EDITOR = "editor";
/** 字符串类型 */
public static final String TYPE_STRING = "String";
/** 整型 */
public static final String TYPE_INTEGER = "Integer";
/** 长整型 */
public static final String TYPE_LONG = "Long";
/** 浮点型 */
public static final String TYPE_DOUBLE = "Double";
/** 高精度计算类型 */
public static final String TYPE_BIGDECIMAL = "BigDecimal";
/** 时间类型 */
public static final String TYPE_DATE = "Date";
/** 模糊查询 */
public static final String QUERY_LIKE = "LIKE";
/** 需要 */
public static final String REQUIRE = "1";
}

View File

@@ -0,0 +1,89 @@
package com.ruoyi.common.constant;
/**
* 返回状态码
*
* @author ruoyi
*/
public class HttpStatus
{
/**
* 操作成功
*/
public static final int SUCCESS = 200;
/**
* 对象创建成功
*/
public static final int CREATED = 201;
/**
* 请求已经被接受
*/
public static final int ACCEPTED = 202;
/**
* 操作已经执行成功,但是没有返回数据
*/
public static final int NO_CONTENT = 204;
/**
* 资源已被移除
*/
public static final int MOVED_PERM = 301;
/**
* 重定向
*/
public static final int SEE_OTHER = 303;
/**
* 资源没有被修改
*/
public static final int NOT_MODIFIED = 304;
/**
* 参数列表错误(缺少,格式不匹配)
*/
public static final int BAD_REQUEST = 400;
/**
* 未授权
*/
public static final int UNAUTHORIZED = 401;
/**
* 访问受限,授权过期
*/
public static final int FORBIDDEN = 403;
/**
* 资源,服务未找到
*/
public static final int NOT_FOUND = 404;
/**
* 不允许的http方法
*/
public static final int BAD_METHOD = 405;
/**
* 资源冲突,或者资源被锁
*/
public static final int CONFLICT = 409;
/**
* 不支持的数据,媒体类型
*/
public static final int UNSUPPORTED_TYPE = 415;
/**
* 系统内部错误
*/
public static final int ERROR = 500;
/**
* 接口未实现
*/
public static final int NOT_IMPLEMENTED = 501;
}

View File

@@ -0,0 +1,50 @@
package com.ruoyi.common.constant;
/**
* 任务调度通用常量
*
* @author ruoyi
*/
public class ScheduleConstants
{
public static final String TASK_CLASS_NAME = "TASK_CLASS_NAME";
/** 执行目标key */
public static final String TASK_PROPERTIES = "TASK_PROPERTIES";
/** 默认 */
public static final String MISFIRE_DEFAULT = "0";
/** 立即触发执行 */
public static final String MISFIRE_IGNORE_MISFIRES = "1";
/** 触发一次执行 */
public static final String MISFIRE_FIRE_AND_PROCEED = "2";
/** 不触发立即执行 */
public static final String MISFIRE_DO_NOTHING = "3";
public enum Status
{
/**
* 正常
*/
NORMAL("0"),
/**
* 暂停
*/
PAUSE("1");
private String value;
private Status(String value)
{
this.value = value;
}
public String getValue()
{
return value;
}
}
}

View File

@@ -0,0 +1,78 @@
package com.ruoyi.common.constant;
/**
* 用户常量信息
*
* @author ruoyi
*/
public class UserConstants
{
/**
* 平台内系统用户的唯一标志
*/
public static final String SYS_USER = "SYS_USER";
/** 正常状态 */
public static final String NORMAL = "0";
/** 异常状态 */
public static final String EXCEPTION = "1";
/** 用户封禁状态 */
public static final String USER_DISABLE = "1";
/** 角色封禁状态 */
public static final String ROLE_DISABLE = "1";
/** 部门正常状态 */
public static final String DEPT_NORMAL = "0";
/** 部门停用状态 */
public static final String DEPT_DISABLE = "1";
/** 字典正常状态 */
public static final String DICT_NORMAL = "0";
/** 是否为系统默认(是) */
public static final String YES = "Y";
/** 是否菜单外链(是) */
public static final String YES_FRAME = "0";
/** 是否菜单外链(否) */
public static final String NO_FRAME = "1";
/** 菜单类型(目录) */
public static final String TYPE_DIR = "M";
/** 菜单类型(菜单) */
public static final String TYPE_MENU = "C";
/** 菜单类型(按钮) */
public static final String TYPE_BUTTON = "F";
/** Layout组件标识 */
public final static String LAYOUT = "Layout";
/** ParentView组件标识 */
public final static String PARENT_VIEW = "ParentView";
/** InnerLink组件标识 */
public final static String INNER_LINK = "InnerLink";
/** 校验返回结果码 */
public final static String UNIQUE = "0";
public final static String NOT_UNIQUE = "1";
/**
* 用户名长度限制
*/
public static final int USERNAME_MIN_LENGTH = 2;
public static final int USERNAME_MAX_LENGTH = 20;
/**
* 密码长度限制
*/
public static final int PASSWORD_MIN_LENGTH = 5;
public static final int PASSWORD_MAX_LENGTH = 20;
}

View File

@@ -0,0 +1,209 @@
package com.ruoyi.common.core.controller;
import java.beans.PropertyEditorSupport;
import java.util.Date;
import java.util.List;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.common.core.domain.AjaxResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.ruoyi.common.constant.HttpStatus;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.page.PageDomain;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.page.TableSupport;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.sql.SqlUtil;
/**
* web层通用数据处理
*
* @author ruoyi
*/
public class BaseController
{
protected final Logger logger = LoggerFactory.getLogger(this.getClass());
/**
* 将前台传递过来的日期格式的字符串自动转化为Date类型
*/
@InitBinder
public void initBinder(WebDataBinder binder)
{
// Date 类型转换
binder.registerCustomEditor(Date.class, new PropertyEditorSupport()
{
@Override
public void setAsText(String text)
{
setValue(DateUtils.parseDate(text));
}
});
}
/**
* 设置请求分页数据
*/
protected void startPage()
{
PageDomain pageDomain = TableSupport.buildPageRequest();
Integer pageNum = pageDomain.getPageNum();
Integer pageSize = pageDomain.getPageSize();
if (StringUtils.isNotNull(pageNum) && StringUtils.isNotNull(pageSize))
{
String orderBy = SqlUtil.escapeOrderBySql(pageDomain.getOrderBy());
Boolean reasonable = pageDomain.getReasonable();
PageHelper.startPage(pageNum, pageSize, orderBy).setReasonable(reasonable);
}
}
/**
* 设置请求排序数据
*/
protected void startOrderBy()
{
PageDomain pageDomain = TableSupport.buildPageRequest();
if (StringUtils.isNotEmpty(pageDomain.getOrderBy()))
{
String orderBy = SqlUtil.escapeOrderBySql(pageDomain.getOrderBy());
PageHelper.orderBy(orderBy);
}
}
/**
* 响应请求分页数据
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
protected TableDataInfo getDataTable(List<?> list)
{
TableDataInfo rspData = new TableDataInfo();
rspData.setCode(HttpStatus.SUCCESS);
rspData.setMsg("查询成功");
rspData.setRows(list);
Long total = new PageInfo(list).getTotal();
rspData.setTotal(total.intValue());
return rspData;
}
protected TableDataInfo getDataTable(Page<?> page)
{
TableDataInfo rspData = new TableDataInfo();
rspData.setCode(HttpStatus.SUCCESS);
rspData.setMsg("查询成功");
rspData.setRows(page.getRecords());
Long total = new PageInfo(page.getRecords()).getTotal();
rspData.setTotal(total.intValue());
return rspData;
}
/**
* 返回成功
*/
public AjaxResult success()
{
return AjaxResult.success();
}
/**
* 返回失败消息
*/
public AjaxResult error()
{
return AjaxResult.error();
}
/**
* 返回成功消息
*/
public AjaxResult success(String message)
{
return AjaxResult.success(message);
}
/**
* 返回失败消息
*/
public AjaxResult error(String message)
{
return AjaxResult.error(message);
}
/**
* 响应返回结果
*
* @param rows 影响行数
* @return 操作结果
*/
protected AjaxResult toAjax(int rows)
{
return rows > 0 ? AjaxResult.success() : AjaxResult.error();
}
/**
* 响应返回结果
*
* @param result 结果
* @return 操作结果
*/
protected AjaxResult toAjax(boolean result)
{
return result ? success() : error();
}
/**
* 页面跳转
*/
public String redirect(String url)
{
return StringUtils.format("redirect:{}", url);
}
/**
* 获取用户缓存信息
*/
public LoginUser getLoginUser()
{
return SecurityUtils.getLoginUser();
}
/**
* 获取登录用户id
*/
public Long getUserId()
{
return getLoginUser().getUserId();
}
/**
* 获取登录部门id
*/
public String getDeptId()
{
return getLoginUser().getDeptId();
}
/**
* 获取登录用户名
*/
public String getUsername()
{
return getLoginUser().getUsername();
}
/**
* 获取登录用户名
*/
public Page getPage() {
PageDomain pageDomain = TableSupport.buildPageRequest();
Integer pageNum = pageDomain.getPageNum();
Integer pageSize = pageDomain.getPageSize();
return new Page(pageNum, pageSize);
}
}

View File

@@ -0,0 +1,160 @@
package com.ruoyi.common.core.domain;
import java.util.Date;
import java.util.HashMap;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.common.constant.HttpStatus;
import com.ruoyi.common.utils.StringUtils;
import lombok.Data;
/**
* 操作消息提醒
*
* @author ruoyi
*/
@Data
public class AjaxResult<T>
{
private static final long serialVersionUID = 1L;
/**
* 响应状态码
*/
private Integer code;
/**
* 响应信息
*/
private String msg;
/**
* 响应对象
*/
private T data;
private Date currentTime = new Date();
/**
* 初始化一个新创建的 AjaxResult 对象,使其表示一个空消息。
*/
public AjaxResult()
{
}
/**
* 初始化一个新创建的 AjaxResult 对象
*
* @param code 状态码
* @param msg 返回内容
*/
public AjaxResult(int code, String msg)
{
this.code = code;
this.msg = msg;
this.currentTime = new Date();
}
/**
* 初始化一个新创建的 AjaxResult 对象
*
* @param code 状态码
* @param msg 返回内容
* @param data 数据对象
*/
public AjaxResult(int code, String msg, T data)
{
this.code = code;
this.msg = msg;
this.data = data;
this.currentTime = new Date();
}
/**
* 返回成功消息
*
* @return 成功消息
*/
public static AjaxResult success()
{
return AjaxResult.success("操作成功");
}
/**
* 返回成功数据
*
* @return 成功消息
*/
public static AjaxResult success(Object data)
{
return AjaxResult.success("操作成功", data);
}
/**
* 返回成功消息
*
* @param msg 返回内容
* @return 成功消息
*/
public static AjaxResult success(String msg)
{
return AjaxResult.success(msg, null);
}
/**
* 返回成功消息
*
* @param msg 返回内容
* @param data 数据对象
* @return 成功消息
*/
public static AjaxResult success(String msg, Object data)
{
return new AjaxResult(HttpStatus.SUCCESS, msg, data);
}
/**
* 返回错误消息
*
* @return
*/
public static AjaxResult error()
{
return AjaxResult.error("操作失败");
}
/**
* 返回错误消息
*
* @param msg 返回内容
* @return 警告消息
*/
public static AjaxResult error(String msg)
{
return AjaxResult.error(msg, null);
}
/**
* 返回错误消息
*
* @param msg 返回内容
* @param data 数据对象
* @return 警告消息
*/
public static AjaxResult error(String msg, Object data)
{
return new AjaxResult(HttpStatus.ERROR, msg, data);
}
/**
* 返回错误消息
*
* @param code 状态码
* @param msg 返回内容
* @return 警告消息
*/
public static AjaxResult error(int code, String msg)
{
return new AjaxResult(code, msg, null);
}
}

View File

@@ -0,0 +1,149 @@
package com.ruoyi.common.core.domain;
import com.ruoyi.common.constant.HttpStatus;
import com.ruoyi.common.utils.StringUtils;
import java.util.HashMap;
/**
* 操作消息提醒
*
* @author ruoyi
*/
public class AjaxResultMap<T> extends HashMap<String, Object>
{
private static final long serialVersionUID = 1L;
/** 状态码 */
public static final String CODE_TAG = "code";
/** 返回内容 */
public static final String MSG_TAG = "msg";
/** 数据对象 */
public static final String DATA_TAG = "data";
/**
* 初始化一个新创建的 AjaxResult 对象,使其表示一个空消息。
*/
public AjaxResultMap()
{
}
/**
* 初始化一个新创建的 AjaxResult 对象
*
* @param code 状态码
* @param msg 返回内容
*/
public AjaxResultMap(int code, String msg)
{
super.put(CODE_TAG, code);
super.put(MSG_TAG, msg);
}
/**
* 初始化一个新创建的 AjaxResult 对象
*
* @param code 状态码
* @param msg 返回内容
* @param data 数据对象
*/
public AjaxResultMap(int code, String msg, T data)
{
super.put(CODE_TAG, code);
super.put(MSG_TAG, msg);
if (StringUtils.isNotNull(data))
{
super.put(DATA_TAG, data);
}
}
/**
* 返回成功消息
*
* @return 成功消息
*/
public static AjaxResultMap success()
{
return AjaxResultMap.success("操作成功");
}
/**
* 返回成功数据
*
* @return 成功消息
*/
public static AjaxResultMap success(Object data)
{
return AjaxResultMap.success("操作成功", data);
}
/**
* 返回成功消息
*
* @param msg 返回内容
* @return 成功消息
*/
public static AjaxResultMap success(String msg)
{
return AjaxResultMap.success(msg, null);
}
/**
* 返回成功消息
*
* @param msg 返回内容
* @param data 数据对象
* @return 成功消息
*/
public static AjaxResultMap success(String msg, Object data)
{
return new AjaxResultMap(HttpStatus.SUCCESS, msg, data);
}
/**
* 返回错误消息
*
* @return
*/
public static AjaxResultMap error()
{
return AjaxResultMap.error("操作失败");
}
/**
* 返回错误消息
*
* @param msg 返回内容
* @return 警告消息
*/
public static AjaxResultMap error(String msg)
{
return AjaxResultMap.error(msg, null);
}
/**
* 返回错误消息
*
* @param msg 返回内容
* @param data 数据对象
* @return 警告消息
*/
public static AjaxResultMap error(String msg, Object data)
{
return new AjaxResultMap(HttpStatus.ERROR, msg, data);
}
/**
* 返回错误消息
*
* @param code 状态码
* @param msg 返回内容
* @return 警告消息
*/
public static AjaxResultMap error(int code, String msg)
{
return new AjaxResultMap(code, msg, null);
}
}

View File

@@ -0,0 +1,80 @@
package com.ruoyi.common.core.domain;
import java.io.Serializable;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import com.baomidou.mybatisplus.annotation.TableField;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.common.annotation.CreateBy;
import com.ruoyi.common.annotation.CreateTime;
import com.ruoyi.common.annotation.UpdateBy;
import com.ruoyi.common.annotation.UpdateTime;
import com.ruoyi.common.utils.SecurityUtils;
import lombok.Data;
import lombok.experimental.Accessors;
/**
* Entity基类
*
* @author ruoyi
*/
@Data
@Accessors(chain = true)
public class BaseEntity implements Serializable
{
private static final long serialVersionUID = 1L;
/** 搜索值 */
@TableField(exist = false)
private String searchValue;
/** 创建者 */
@CreateBy
private String createBy;
/** 创建时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@CreateTime
private Date createTime;
/** 更新者 */
@UpdateBy
private String updateBy;
/** 更新时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@UpdateTime
private Date updateTime;
/** 备注 */
@TableField(exist = false)
private String remark;
/** 请求参数 */
@TableField(exist = false)
private Map<String, Object> params;
public Map<String, Object> getParams()
{
if (params == null)
{
params = new HashMap<>();
}
return params;
}
public void setCreateData()
{
this.createBy = SecurityUtils.getUserId().toString();
this.createTime = new Date();
}
public void setUpdateData()
{
this.updateBy = SecurityUtils.getUserId().toString();
this.updateTime = new Date();
}
}

View File

@@ -0,0 +1,37 @@
package com.ruoyi.common.core.domain;
import com.baomidou.mybatisplus.annotation.TableField;
import com.ruoyi.common.utils.StringUtils;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.ArrayList;
import java.util.List;
/**
* Tree基类
*
* @author ruoyi
*/
@EqualsAndHashCode(callSuper = true)
@Data
public abstract class TreeEntity extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 父部门ID */
protected String parentId = "0";
/** 祖级列表 */
protected String ancestors = "0,";
public abstract String getId();
public String makeSelfAsNewParentIds() {
if (StringUtils.isEmpty(getAncestors())) {
return getId() + ",";
}
return getAncestors() + getId() + ",";
}
}

View File

@@ -0,0 +1,79 @@
package com.ruoyi.common.core.domain;
import java.io.Serializable;
import java.util.List;
import java.util.stream.Collectors;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.domain.entity.SysMenu;
import lombok.Data;
/**
* Treeselect树结构实体类
*
* @author ruoyi
*/
@Data
public class TreeSelect implements Serializable
{
private static final long serialVersionUID = 1L;
/** 节点ID */
private String id;
/** 节点名称 */
private String label;
/** 子节点 */
@JsonInclude(JsonInclude.Include.NON_EMPTY)
private List<TreeSelect> children;
public TreeSelect()
{
}
public TreeSelect(SysDept dept)
{
this.id = dept.getDeptId();
this.label = dept.getDeptName();
this.children = dept.getChildren().stream().map(TreeSelect::new).collect(Collectors.toList());
}
public TreeSelect(SysMenu menu)
{
this.id = menu.getMenuId().toString();
this.label = menu.getMenuName();
this.children = menu.getChildren().stream().map(TreeSelect::new).collect(Collectors.toList());
}
public String getId()
{
return id;
}
public void setId(String id)
{
this.id = id;
}
public String getLabel()
{
return label;
}
public void setLabel(String label)
{
this.label = label;
}
public List<TreeSelect> getChildren()
{
return children;
}
public void setChildren(List<TreeSelect> children)
{
this.children = children;
}
}

View File

@@ -0,0 +1,55 @@
package com.ruoyi.common.core.domain.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.ruoyi.common.core.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* All rights Reserved, Designed By www.sunseagear.com
*
* @version V1.0
* @package sys
* @title: 数据权限表控制器
* @description: 数据权限表控制器
* @author: 未知
* @date: 2019-11-29 06:05:01
* @copyright: www.sunseagear.com Inc. All rights reserved.
*/
@EqualsAndHashCode(callSuper = true)
@Data
@TableName("sys_data_rule")
@SuppressWarnings("serial")
public class SysDataRule extends BaseEntity {
@TableId(value = "id", type = IdType.AUTO)
private String id; //id
@TableField(value = "resource_code")
private String resourceCode; //资源编号
@TableField(value = "scope_name")
private String scopeName; //数据权限名称
@TableField(value = "scope_field")
private String scopeField; //数据权限字段
@TableField(value = "scope_class")
private String scopeClass; //数据权限类名
@TableField(value = "scope_column")
private String scopeColumn; //数据权限字段
@TableField(value = "table_name")
private String tableName; //数据权限关联表名
@TableField(value = "scope_type")
private String scopeType; //数据权限类型
@TableField(value = "scope_value")
private String scopeValue; //数据权限值域
@TableField(value = "user_column")
private String userColumn; //用户表对应字段
@TableField(value = "user_entity_field")
private String userEntityField; //用户实体类对应字段
@TableField(exist = false)
private boolean select; //是否选择
}

View File

@@ -0,0 +1,112 @@
package com.ruoyi.common.core.domain.entity;
import com.ruoyi.common.core.domain.TreeEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;
import java.util.ArrayList;
import java.util.List;
/**
* 部门表 sys_dept
*
* @author ruoyi
*/
@EqualsAndHashCode(callSuper = true)
@Data
public class SysDept extends TreeEntity
{
private static final long serialVersionUID = 1L;
/** 部门ID */
private String deptId;
/** 部门名称 */
private String deptName;
/** 显示顺序 */
private String orderNum;
/** 负责人 */
private String leader;
/** 联系电话 */
private String phone;
/** 邮箱 */
private String email;
/** 部门状态:0正常,1停用 */
private String status;
/** 删除标志0代表存在 2代表删除 */
private String delFlag;
/** 父部门名称 */
private String parentName;
/** 租户ID */
private String tenantId;
/** 子部门 */
private List<SysDept> children = new ArrayList<SysDept>();
@NotBlank(message = "部门名称不能为空")
@Size(min = 0, max = 30, message = "部门名称长度不能超过30个字符")
public String getDeptName()
{
return deptName;
}
@NotBlank(message = "显示顺序不能为空")
public String getOrderNum()
{
return orderNum;
}
@Size(min = 0, max = 11, message = "联系电话长度不能超过11个字符")
public String getPhone()
{
return phone;
}
@Email(message = "邮箱格式不正确")
@Size(min = 0, max = 50, message = "邮箱长度不能超过50个字符")
public String getEmail()
{
return email;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("deptId", getDeptId())
.append("parentId", getParentId())
.append("ancestors", getAncestors())
.append("deptName", getDeptName())
.append("orderNum", getOrderNum())
.append("leader", getLeader())
.append("phone", getPhone())
.append("email", getEmail())
.append("status", getStatus())
.append("delFlag", getDelFlag())
.append("createBy", getCreateBy())
.append("createTime", getCreateTime())
.append("updateBy", getUpdateBy())
.append("updateTime", getUpdateTime())
.toString();
}
@Override
public String getId() {
return getDeptId();
}
}

View File

@@ -0,0 +1,200 @@
package com.ruoyi.common.core.domain.entity;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.annotation.Excel.ColumnType;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.domain.BaseEntity;
import java.util.List;
/**
* 字典数据表 sys_dict_data
*
* @author ruoyi
*/
public class SysDictData extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 字典编码 */
@Excel(name = "字典编码", cellType = ColumnType.NUMERIC)
private Long dictCode;
/** 字典排序 */
@Excel(name = "字典排序", cellType = ColumnType.NUMERIC)
private Long dictSort;
/** 字典标签 */
@Excel(name = "字典标签")
private String dictLabel;
/** 字典键值 */
@Excel(name = "字典键值")
private String dictValue;
/** 字典类型 */
@Excel(name = "字典类型")
private String dictType;
/** 样式属性(其他样式扩展) */
private String cssClass;
/** 表格字典样式 */
private String listClass;
/** 是否默认Y是 N否 */
@Excel(name = "是否默认", readConverterExp = "Y=是,N=否")
private String isDefault;
/** 状态0正常 1停用 */
@Excel(name = "状态", readConverterExp = "0=正常,1=停用")
private String status;
/**字典编码唯一*/
private String code;
/**图片*/
private String images;
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getImages() {
return images;
}
public void setImages(String images) {
this.images = images;
}
public Long getDictCode()
{
return dictCode;
}
public void setDictCode(Long dictCode)
{
this.dictCode = dictCode;
}
public Long getDictSort()
{
return dictSort;
}
public void setDictSort(Long dictSort)
{
this.dictSort = dictSort;
}
@NotBlank(message = "字典标签不能为空")
@Size(min = 0, max = 1000, message = "字典标签长度不能超过1000个字符")
public String getDictLabel()
{
return dictLabel;
}
public void setDictLabel(String dictLabel)
{
this.dictLabel = dictLabel;
}
@NotBlank(message = "字典键值不能为空")
@Size(min = 0, max = 1000, message = "字典键值长度不能超过1000个字符")
public String getDictValue()
{
return dictValue;
}
public void setDictValue(String dictValue)
{
this.dictValue = dictValue;
}
@NotBlank(message = "字典类型不能为空")
@Size(min = 0, max = 1000, message = "字典类型长度不能超过1000个字符")
public String getDictType()
{
return dictType;
}
public void setDictType(String dictType)
{
this.dictType = dictType;
}
@Size(min = 0, max = 100, message = "样式属性长度不能超过100个字符")
public String getCssClass()
{
return cssClass;
}
public void setCssClass(String cssClass)
{
this.cssClass = cssClass;
}
public String getListClass()
{
return listClass;
}
public void setListClass(String listClass)
{
this.listClass = listClass;
}
public boolean getDefault()
{
return UserConstants.YES.equals(this.isDefault) ? true : false;
}
public String getIsDefault()
{
return isDefault;
}
public void setIsDefault(String isDefault)
{
this.isDefault = isDefault;
}
public String getStatus()
{
return status;
}
public void setStatus(String status)
{
this.status = status;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("dictCode", getDictCode())
.append("dictSort", getDictSort())
.append("dictLabel", getDictLabel())
.append("dictValue", getDictValue())
.append("dictType", getDictType())
.append("cssClass", getCssClass())
.append("listClass", getListClass())
.append("isDefault", getIsDefault())
.append("status", getStatus())
.append("createBy", getCreateBy())
.append("createTime", getCreateTime())
.append("updateBy", getUpdateBy())
.append("updateTime", getUpdateTime())
.append("remark", getRemark())
.toString();
}
}

View File

@@ -0,0 +1,94 @@
package com.ruoyi.common.core.domain.entity;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.annotation.Excel.ColumnType;
import com.ruoyi.common.core.domain.BaseEntity;
/**
* 字典类型表 sys_dict_type
*
* @author ruoyi
*/
public class SysDictType extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 字典主键 */
@Excel(name = "字典主键", cellType = ColumnType.NUMERIC)
private Long dictId;
/** 字典名称 */
@Excel(name = "字典名称")
private String dictName;
/** 字典类型 */
@Excel(name = "字典类型")
private String dictType;
/** 状态0正常 1停用 */
@Excel(name = "状态", readConverterExp = "0=正常,1=停用")
private String status;
public Long getDictId()
{
return dictId;
}
public void setDictId(Long dictId)
{
this.dictId = dictId;
}
@NotBlank(message = "字典名称不能为空")
@Size(min = 0, max = 100, message = "字典类型名称长度不能超过100个字符")
public String getDictName()
{
return dictName;
}
public void setDictName(String dictName)
{
this.dictName = dictName;
}
@NotBlank(message = "字典类型不能为空")
@Size(min = 0, max = 100, message = "字典类型类型长度不能超过100个字符")
public String getDictType()
{
return dictType;
}
public void setDictType(String dictType)
{
this.dictType = dictType;
}
public String getStatus()
{
return status;
}
public void setStatus(String status)
{
this.status = status;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("dictId", getDictId())
.append("dictName", getDictName())
.append("dictType", getDictType())
.append("status", getStatus())
.append("createBy", getCreateBy())
.append("createTime", getCreateTime())
.append("updateBy", getUpdateBy())
.append("updateTime", getUpdateTime())
.append("remark", getRemark())
.toString();
}
}

View File

@@ -0,0 +1,267 @@
package com.ruoyi.common.core.domain.entity;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.common.core.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;
import java.util.ArrayList;
import java.util.List;
/**
* 菜单权限表 sys_menu
*
* @author ruoyi
*/
@EqualsAndHashCode(callSuper = true)
@Data
public class SysMenu extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 菜单ID */
private Long menuId;
/** 菜单名称 */
private String menuName;
/** 父菜单名称 */
private String parentName;
/** 父菜单ID */
private Long parentId;
/** 显示顺序 */
private String orderNum;
/** 路由地址 */
private String path;
/** 组件路径 */
private String component;
/** 路由参数 */
private String query;
/** 是否为外链0是 1否 */
private String isFrame;
/** 是否缓存0缓存 1不缓存 */
private String isCache;
/** 类型M目录 C菜单 F按钮 */
private String menuType;
/** 显示状态0显示 1隐藏 */
private String visible;
/** 菜单状态0显示 1隐藏 */
private String status;
/** 权限字符串 */
private String perms;
/** 菜单图标 */
private String icon;
private String tenantId;
/** 子菜单 */
private List<SysMenu> children = new ArrayList<SysMenu>();
@JsonFormat(shape = JsonFormat.Shape.STRING)
public Long getMenuId()
{
return menuId;
}
public void setMenuId(Long menuId)
{
this.menuId = menuId;
}
@NotBlank(message = "菜单名称不能为空")
@Size(min = 0, max = 50, message = "菜单名称长度不能超过50个字符")
public String getMenuName()
{
return menuName;
}
public void setMenuName(String menuName)
{
this.menuName = menuName;
}
public String getParentName()
{
return parentName;
}
public void setParentName(String parentName)
{
this.parentName = parentName;
}
public Long getParentId()
{
return parentId;
}
public void setParentId(Long parentId)
{
this.parentId = parentId;
}
@NotBlank(message = "显示顺序不能为空")
public String getOrderNum()
{
return orderNum;
}
public void setOrderNum(String orderNum)
{
this.orderNum = orderNum;
}
@Size(min = 0, max = 200, message = "路由地址不能超过200个字符")
public String getPath()
{
return path;
}
public void setPath(String path)
{
this.path = path;
}
@Size(min = 0, max = 200, message = "组件路径不能超过255个字符")
public String getComponent()
{
return component;
}
public void setComponent(String component)
{
this.component = component;
}
public String getQuery()
{
return query;
}
public void setQuery(String query)
{
this.query = query;
}
public String getIsFrame()
{
return isFrame;
}
public void setIsFrame(String isFrame)
{
this.isFrame = isFrame;
}
public String getIsCache()
{
return isCache;
}
public void setIsCache(String isCache)
{
this.isCache = isCache;
}
@NotBlank(message = "菜单类型不能为空")
public String getMenuType()
{
return menuType;
}
public void setMenuType(String menuType)
{
this.menuType = menuType;
}
public String getVisible()
{
return visible;
}
public void setVisible(String visible)
{
this.visible = visible;
}
public String getStatus()
{
return status;
}
public void setStatus(String status)
{
this.status = status;
}
@Size(min = 0, max = 100, message = "权限标识长度不能超过100个字符")
public String getPerms()
{
return perms;
}
public void setPerms(String perms)
{
this.perms = perms;
}
public String getIcon()
{
return icon;
}
public void setIcon(String icon)
{
this.icon = icon;
}
public List<SysMenu> getChildren()
{
return children;
}
public void setChildren(List<SysMenu> children)
{
this.children = children;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("menuId", getMenuId())
.append("menuName", getMenuName())
.append("parentId", getParentId())
.append("orderNum", getOrderNum())
.append("path", getPath())
.append("component", getComponent())
.append("isFrame", getIsFrame())
.append("IsCache", getIsCache())
.append("menuType", getMenuType())
.append("visible", getVisible())
.append("status ", getStatus())
.append("perms", getPerms())
.append("icon", getIcon())
.append("createBy", getCreateBy())
.append("createTime", getCreateTime())
.append("updateBy", getUpdateBy())
.append("updateTime", getUpdateTime())
.append("remark", getRemark())
.toString();
}
}

View File

@@ -0,0 +1,235 @@
package com.ruoyi.common.core.domain.entity;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.annotation.Excel.ColumnType;
import com.ruoyi.common.core.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;
/**
* 角色表 sys_role
*
* @author ruoyi
*/
@EqualsAndHashCode(callSuper = true)
@Data
@Accessors(chain = true)
public class SysRole extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 角色ID */
@Excel(name = "角色序号", cellType = ColumnType.NUMERIC)
private Long roleId;
/** 角色名称 */
@Excel(name = "角色名称")
private String roleName;
/** 角色权限 */
@Excel(name = "角色权限")
private String roleKey;
/** 角色排序 */
@Excel(name = "角色排序")
private String roleSort;
/** 数据范围1所有数据权限2自定义数据权限3本部门数据权限4本部门及以下数据权限5仅本人数据权限 */
@Excel(name = "数据范围", readConverterExp = "1=所有数据权限,2=自定义数据权限,3=本部门数据权限,4=本部门及以下数据权限,5=仅本人数据权限")
private String dataScope;
/** 菜单树选择项是否关联显示( 0父子不互相关联显示 1父子互相关联显示 */
private boolean menuCheckStrictly;
/** 部门树选择项是否关联显示0父子不互相关联显示 1父子互相关联显示 */
private boolean deptCheckStrictly;
/** 角色状态0正常 1停用 */
@Excel(name = "角色状态", readConverterExp = "0=正常,1=停用")
private String status;
/** 删除标志0代表存在 2代表删除 */
private String delFlag;
/** 用户是否存在此角色标识 默认不存在 */
private boolean flag = false;
private String tenantId;
/** 菜单组 */
private Long[] menuIds;
/** 部门组(数据权限) */
private Long[] deptIds;
public SysRole()
{
}
public SysRole(Long roleId)
{
this.roleId = roleId;
}
public Long getRoleId()
{
return roleId;
}
public void setRoleId(Long roleId)
{
this.roleId = roleId;
}
public boolean isAdmin()
{
return isAdmin(this.roleId);
}
public static boolean isAdmin(Long roleId)
{
return roleId != null && 1L == roleId;
}
@NotBlank(message = "角色名称不能为空")
@Size(min = 0, max = 30, message = "角色名称长度不能超过30个字符")
public String getRoleName()
{
return roleName;
}
public void setRoleName(String roleName)
{
this.roleName = roleName;
}
@NotBlank(message = "权限字符不能为空")
@Size(min = 0, max = 100, message = "权限字符长度不能超过100个字符")
public String getRoleKey()
{
return roleKey;
}
public void setRoleKey(String roleKey)
{
this.roleKey = roleKey;
}
@NotBlank(message = "显示顺序不能为空")
public String getRoleSort()
{
return roleSort;
}
public void setRoleSort(String roleSort)
{
this.roleSort = roleSort;
}
public String getDataScope()
{
return dataScope;
}
public void setDataScope(String dataScope)
{
this.dataScope = dataScope;
}
public boolean isMenuCheckStrictly()
{
return menuCheckStrictly;
}
public void setMenuCheckStrictly(boolean menuCheckStrictly)
{
this.menuCheckStrictly = menuCheckStrictly;
}
public boolean isDeptCheckStrictly()
{
return deptCheckStrictly;
}
public void setDeptCheckStrictly(boolean deptCheckStrictly)
{
this.deptCheckStrictly = deptCheckStrictly;
}
public String getStatus()
{
return status;
}
public void setStatus(String status)
{
this.status = status;
}
public String getDelFlag()
{
return delFlag;
}
public void setDelFlag(String delFlag)
{
this.delFlag = delFlag;
}
public boolean isFlag()
{
return flag;
}
public void setFlag(boolean flag)
{
this.flag = flag;
}
public Long[] getMenuIds()
{
return menuIds;
}
public void setMenuIds(Long[] menuIds)
{
this.menuIds = menuIds;
}
public Long[] getDeptIds()
{
return deptIds;
}
public void setDeptIds(Long[] deptIds)
{
this.deptIds = deptIds;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("roleId", getRoleId())
.append("roleName", getRoleName())
.append("roleKey", getRoleKey())
.append("roleSort", getRoleSort())
.append("dataScope", getDataScope())
.append("menuCheckStrictly", isMenuCheckStrictly())
.append("deptCheckStrictly", isDeptCheckStrictly())
.append("status", getStatus())
.append("delFlag", getDelFlag())
.append("createBy", getCreateBy())
.append("createTime", getCreateTime())
.append("updateBy", getUpdateBy())
.append("updateTime", getUpdateTime())
.append("remark", getRemark())
.toString();
}
}

View File

@@ -0,0 +1,44 @@
package com.ruoyi.common.core.domain.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.ruoyi.common.core.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* All rights Reserved, Designed By www.sunseagear.com
*
* @version V1.0
* @package sys
* @title: 租户管理控制器
* @description: 租户管理控制器
* @author: 未知
* @date: 2019-11-28 06:24:52
* @copyright: www.sunseagear.com Inc. All rights reserved.
*/
@EqualsAndHashCode(callSuper = true)
@Data
@TableName("sys_tenant")
public class SysTenant extends BaseEntity {
private static final long serialVersionUID = 1L;
@TableId(value = "id", type = IdType.AUTO)
private Long id; //id
@TableField(value = "contact")
private String contact; //联系人
@TableField(value = "phone")
private String phone; //电话
@TableField(value = "name")
private String name; //租户名称
@TableField(value = "tenant_id")
private String tenantId;
@TableField(value = "user_id")
private Long userId;
@TableField(exist = false)
private String userName;
}

View File

@@ -0,0 +1,211 @@
package com.ruoyi.common.core.domain.entity;
import java.util.Date;
import java.util.List;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.annotation.Excel.ColumnType;
import com.ruoyi.common.annotation.Excel.Type;
import com.ruoyi.common.annotation.Excels;
import com.ruoyi.common.core.domain.BaseEntity;
/**
* 用户对象 sys_user
*
* @author ruoyi
*/
@EqualsAndHashCode(callSuper = true)
@Data
public class SysUser extends BaseEntity {
private static final long serialVersionUID = 1L;
/**
* 用户ID
*/
@Excel(name = "用户序号", cellType = ColumnType.NUMERIC, prompt = "用户编号")
private Long userId;
private String userType;
/**
* 部门ID
*/
@Excel(name = "部门编号", type = Type.IMPORT)
private String deptId;
/**
* 用户账号
*/
@Excel(name = "登录名称")
@NotBlank(message = "用户账号不能为空")
@Size(min = 0, max = 30, message = "用户账号长度不能超过30个字符")
private String userName;
/**
* 用户昵称
*/
@Excel(name = "用户名称")
@Size(min = 0, max = 30, message = "用户昵称长度不能超过30个字符")
private String nickName;
/**
* 用户邮箱
*/
@Excel(name = "用户邮箱")
private String email;
/**
* 手机号码
*/
@Excel(name = "手机号码")
private String phonenumber;
/**
* 用户性别
*/
@Excel(name = "用户性别", readConverterExp = "0=男,1=女,2=未知")
private String sex;
/**
* 用户头像
*/
private String avatar;
/**
* 密码
*/
private String password;
/**
* 盐加密
*/
private String salt;
/**
* 帐号状态0正常 1停用
*/
@Excel(name = "帐号状态", readConverterExp = "0=正常,1=停用")
private String status;
/**
* 删除标志0代表存在 2代表删除
*/
private String delFlag;
/**
* 最后登录IP
*/
@Excel(name = "最后登录IP", type = Type.EXPORT)
private String loginIp;
/**
* 最后登录时间
*/
@Excel(name = "最后登录时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss", type = Type.EXPORT)
private Date loginDate;
/**
* 部门对象
*/
@Excels({
@Excel(name = "部门名称", targetAttr = "deptName", type = Type.EXPORT),
@Excel(name = "部门负责人", targetAttr = "leader", type = Type.EXPORT)
})
private SysDept dept;
/**
* 角色对象
*/
private List<SysRole> roles;
/**
* 角色组
*/
private Long[] roleIds;
/**
* 岗位组
*/
private Long[] postIds;
/**
* 角色ID
*/
private Long roleId;
/**
* 租户ID
*/
private String tenantId;
public SysUser() {
}
public SysUser(Long userId) {
this.userId = userId;
}
public boolean isAdmin() {
return isAdmin(this.userId);
}
public static boolean isAdmin(Long userId) {
return userId != null && 1L == userId;
}
@Email(message = "邮箱格式不正确")
@Size(min = 0, max = 50, message = "邮箱长度不能超过50个字符")
public String getEmail() {
return email;
}
@Size(min = 0, max = 11, message = "手机号码长度不能超过11个字符")
public String getPhonenumber() {
return phonenumber;
}
@JsonIgnore
@JsonProperty
public String getPassword() {
return password;
}
@Override
public String toString() {
return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
.append("userId", getUserId())
.append("deptId", getDeptId())
.append("userName", getUserName())
.append("nickName", getNickName())
.append("email", getEmail())
.append("phonenumber", getPhonenumber())
.append("sex", getSex())
.append("avatar", getAvatar())
.append("password", getPassword())
.append("salt", getSalt())
.append("status", getStatus())
.append("delFlag", getDelFlag())
.append("loginIp", getLoginIp())
.append("loginDate", getLoginDate())
.append("createBy", getCreateBy())
.append("createTime", getCreateTime())
.append("updateBy", getUpdateBy())
.append("updateTime", getUpdateTime())
.append("remark", getRemark())
.append("dept", getDept())
.toString();
}
}

View File

@@ -0,0 +1,82 @@
package com.ruoyi.common.core.domain.model;
/**
* 用户登录对象
*
* @author ruoyi
*/
public class LoginBody
{
/**
* 登入端口
*/
private String loginType = "00";
/**
* 用户名
*/
private String username;
/**
* 用户密码
*/
private String password;
/**
* 验证码
*/
private String code;
/**
* 唯一标识
*/
private String uuid = "";
public String getUsername()
{
return username;
}
public void setUsername(String username)
{
this.username = username;
}
public String getPassword()
{
return password;
}
public void setPassword(String password)
{
this.password = password;
}
public String getCode()
{
return code;
}
public void setCode(String code)
{
this.code = code;
}
public String getUuid()
{
return uuid;
}
public void setUuid(String uuid)
{
this.uuid = uuid;
}
public String getLoginType() {
return loginType;
}
public void setLoginType(String loginType) {
this.loginType = loginType;
}
}

View File

@@ -0,0 +1,151 @@
package com.ruoyi.common.core.domain.model;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.ruoyi.common.core.domain.entity.SysUser;
import lombok.Data;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import java.util.Collection;
import java.util.Set;
/**
* 登录用户身份权限
*
* @author ruoyi
*/
@Data
public class LoginUser implements UserDetails {
private static final long serialVersionUID = 1L;
/**
* 用户ID
*/
private Long userId;
/**
* 部门ID
*/
private String deptId;
/**
* 用户唯一标识
*/
private String token;
/**
* 登录时间
*/
private Long loginTime;
/**
* 过期时间
*/
private Long expireTime;
/**
* 登录IP地址
*/
private String ipaddr;
/**
* 登录地点
*/
private String loginLocation;
/**
* 浏览器类型
*/
private String browser;
/**
* 操作系统
*/
private String os;
/**
* 权限列表
*/
private Set<String> permissions;
/**
* 租户ID
*/
private String tenantId;
/**
* 用户信息
*/
private SysUser user;
public LoginUser() {
}
public LoginUser(SysUser user, Set<String> permissions) {
this.user = user;
this.permissions = permissions;
this.userId = user.getUserId();
this.deptId = user.getDeptId();
this.tenantId = user.getTenantId();
}
@JsonIgnore
@Override
public String getPassword() {
return user.getPassword();
}
@Override
public String getUsername() {
return user.getUserName();
}
/**
* 账户是否未过期,过期无法验证
*/
@JsonIgnore
@Override
public boolean isAccountNonExpired() {
return true;
}
/**
* 指定用户是否解锁,锁定的用户无法进行身份验证
*
* @return
*/
@JsonIgnore
@Override
public boolean isAccountNonLocked() {
return true;
}
/**
* 指示是否已过期的用户的凭据(密码),过期的凭据防止认证
*
* @return
*/
@JsonIgnore
@Override
public boolean isCredentialsNonExpired() {
return true;
}
/**
* 是否可用 ,禁用的用户不能身份验证
*
* @return
*/
@JsonIgnore
@Override
public boolean isEnabled() {
return true;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return null;
}
}

View File

@@ -0,0 +1,11 @@
package com.ruoyi.common.core.domain.model;
/**
* 用户注册对象
*
* @author ruoyi
*/
public class RegisterBody extends LoginBody
{
}

View File

@@ -0,0 +1,47 @@
package com.ruoyi.common.core.mapper;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Param;
import java.io.Serializable;
import java.util.List;
public interface BaseTreeMapper<T> extends BaseMapper<T> {
/**
* @param id
* @return
* @title: selectByPrimaryKey
* @description: 查找主键
* @return: Menu
*/
T selectByTreeId(Serializable id);
/**
* @param wrapper
* @return
* @title: selectTreeList
* @description: 查找列表
* @return: List<T>
*/
List<T> selectTreeList(@Param("ew") Wrapper<T> wrapper);
/**
* @param newParentIds
* @param oldParentIds
* @title: updateSunTreeParentId
* @description: 更新ParentIds
* @return: void
*/
void updateSunTreeParentIds(@Param("newParentIds") String newParentIds, @Param("oldParentIds") String oldParentIds);
/**
* @param parentIds
* @return
* @title: selectTreeList
* @description: 查找列表
* @return: List<T>
*/
void deleteSunTree(String parentIds);
}

View File

@@ -0,0 +1,101 @@
package com.ruoyi.common.core.page;
import com.ruoyi.common.utils.StringUtils;
/**
* 分页数据
*
* @author ruoyi
*/
public class PageDomain {
/**
* 当前记录起始索引
*/
private Integer pageNum;
/**
* 每页显示记录数
*/
private Integer pageSize;
/**
* 排序列
*/
private String orderByColumn;
/**
* 排序的方向desc或者asc
*/
private String isAsc = "asc";
/**
* 分页参数合理化
*/
private Boolean reasonable = true;
public String getOrderBy() {
if (StringUtils.isEmpty(orderByColumn)) {
return "";
}
return StringUtils.toUnderScoreCase(orderByColumn) + " " + isAsc;
}
public Integer getPageNum() {
return pageNum;
}
public void setPageNum(Integer pageNum) {
// if (pageNum == null) {
// this.pageNum = 10;
// return;
// }
this.pageNum = pageNum;
}
public Integer getPageSize() {
return pageSize;
}
public void setPageSize(Integer pageSize) {
// if (pageSize == null) {
// this.pageSize = 1;
// return;
// }
this.pageSize = pageSize;
}
public String getOrderByColumn() {
return orderByColumn;
}
public void setOrderByColumn(String orderByColumn) {
this.orderByColumn = orderByColumn;
}
public String getIsAsc() {
return isAsc;
}
public void setIsAsc(String isAsc) {
if (StringUtils.isNotEmpty(isAsc)) {
// 兼容前端排序类型
if ("ascending".equals(isAsc)) {
isAsc = "asc";
} else if ("descending".equals(isAsc)) {
isAsc = "desc";
}
this.isAsc = isAsc;
}
}
public Boolean getReasonable() {
if (StringUtils.isNull(reasonable)) {
return Boolean.TRUE;
}
return reasonable;
}
public void setReasonable(Boolean reasonable) {
this.reasonable = reasonable;
}
}

View File

@@ -0,0 +1,85 @@
package com.ruoyi.common.core.page;
import java.io.Serializable;
import java.util.List;
/**
* 表格分页数据对象
*
* @author ruoyi
*/
public class TableDataInfo<T> implements Serializable
{
private static final long serialVersionUID = 1L;
/** 总记录数 */
private Integer total;
/** 列表数据 */
private List<T> rows;
/** 消息状态码 */
private int code;
/** 消息内容 */
private String msg;
/**
* 表格数据对象
*/
public TableDataInfo()
{
}
/**
* 分页
*
* @param list 列表数据
* @param total 总记录数
*/
public TableDataInfo(List<T> list, Integer total)
{
this.rows = list;
this.total = total;
}
public long getTotal()
{
return total;
}
public void setTotal(Integer total)
{
this.total = total;
}
public List getRows()
{
return rows;
}
public void setRows(List<T> rows)
{
this.rows = rows;
}
public int getCode()
{
return code;
}
public void setCode(int code)
{
this.code = code;
}
public String getMsg()
{
return msg;
}
public void setMsg(String msg)
{
this.msg = msg;
}
}

View File

@@ -0,0 +1,55 @@
package com.ruoyi.common.core.page;
import com.ruoyi.common.utils.ServletUtils;
/**
* 表格数据处理
*
* @author ruoyi
*/
public class TableSupport
{
/**
* 当前记录起始索引
*/
public static final String PAGE_NUM = "pageNum";
/**
* 每页显示记录数
*/
public static final String PAGE_SIZE = "pageSize";
/**
* 排序列
*/
public static final String ORDER_BY_COLUMN = "orderByColumn";
/**
* 排序的方向 "desc" 或者 "asc".
*/
public static final String IS_ASC = "isAsc";
/**
* 分页参数合理化
*/
public static final String REASONABLE = "reasonable";
/**
* 封装分页对象
*/
public static PageDomain getPageDomain()
{
PageDomain pageDomain = new PageDomain();
pageDomain.setPageNum(ServletUtils.getParameterToInt(PAGE_NUM));
pageDomain.setPageSize(ServletUtils.getParameterToInt(PAGE_SIZE));
pageDomain.setOrderByColumn(ServletUtils.getParameter(ORDER_BY_COLUMN));
pageDomain.setIsAsc(ServletUtils.getParameter(IS_ASC));
pageDomain.setReasonable(ServletUtils.getParameterToBool(REASONABLE));
return pageDomain;
}
public static PageDomain buildPageRequest()
{
return getPageDomain();
}
}

View File

@@ -0,0 +1,231 @@
package com.ruoyi.common.core.redis;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundSetOperations;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Component;
import java.util.*;
import java.util.concurrent.TimeUnit;
/**
* spring redis 工具类
*
* @author ruoyi
**/
@SuppressWarnings(value = { "unchecked", "rawtypes" })
@Component
public class RedisCache
{
@Autowired
public RedisTemplate redisTemplate;
/**
* 缓存基本的对象Integer、String、实体类等
*
* @param key 缓存的键值
* @param value 缓存的值
*/
public <T> void setCacheObject(final String key, final T value)
{
redisTemplate.opsForValue().set(key, value);
}
/**
* 缓存基本的对象Integer、String、实体类等
*
* @param key 缓存的键值
* @param value 缓存的值
* @param timeout 时间
* @param timeUnit 时间颗粒度
*/
public <T> void setCacheObject(final String key, final T value, final Integer timeout, final TimeUnit timeUnit)
{
redisTemplate.opsForValue().set(key, value, timeout, timeUnit);
}
/**
* 设置有效时间
*
* @param key Redis键
* @param timeout 超时时间
* @return true=设置成功false=设置失败
*/
public boolean expire(final String key, final long timeout)
{
return expire(key, timeout, TimeUnit.SECONDS);
}
/**
* 设置有效时间
*
* @param key Redis键
* @param timeout 超时时间
* @param unit 时间单位
* @return true=设置成功false=设置失败
*/
public boolean expire(final String key, final long timeout, final TimeUnit unit)
{
return redisTemplate.expire(key, timeout, unit);
}
/**
* 获得缓存的基本对象。
*
* @param key 缓存键值
* @return 缓存键值对应的数据
*/
public <T> T getCacheObject(final String key)
{
ValueOperations<String, T> operation = redisTemplate.opsForValue();
return operation.get(key);
}
/**
* 删除单个对象
*
* @param key
*/
public boolean deleteObject(final String key)
{
return redisTemplate.delete(key);
}
/**
* 删除集合对象
*
* @param collection 多个对象
* @return
*/
public long deleteObject(final Collection collection)
{
return redisTemplate.delete(collection);
}
/**
* 缓存List数据
*
* @param key 缓存的键值
* @param dataList 待缓存的List数据
* @return 缓存的对象
*/
public <T> long setCacheList(final String key, final List<T> dataList)
{
Long count = redisTemplate.opsForList().rightPushAll(key, dataList);
return count == null ? 0 : count;
}
/**
* 获得缓存的list对象
*
* @param key 缓存的键值
* @return 缓存键值对应的数据
*/
public <T> List<T> getCacheList(final String key)
{
return redisTemplate.opsForList().range(key, 0, -1);
}
/**
* 缓存Set
*
* @param key 缓存键值
* @param dataSet 缓存的数据
* @return 缓存数据的对象
*/
public <T> BoundSetOperations<String, T> setCacheSet(final String key, final Set<T> dataSet)
{
BoundSetOperations<String, T> setOperation = redisTemplate.boundSetOps(key);
Iterator<T> it = dataSet.iterator();
while (it.hasNext())
{
setOperation.add(it.next());
}
return setOperation;
}
/**
* 获得缓存的set
*
* @param key
* @return
*/
public <T> Set<T> getCacheSet(final String key)
{
return redisTemplate.opsForSet().members(key);
}
/**
* 缓存Map
*
* @param key
* @param dataMap
*/
public <T> void setCacheMap(final String key, final Map<String, T> dataMap)
{
if (dataMap != null) {
redisTemplate.opsForHash().putAll(key, dataMap);
}
}
/**
* 获得缓存的Map
*
* @param key
* @return
*/
public <T> Map<String, T> getCacheMap(final String key)
{
return redisTemplate.opsForHash().entries(key);
}
/**
* 往Hash中存入数据
*
* @param key Redis键
* @param hKey Hash键
* @param value 值
*/
public <T> void setCacheMapValue(final String key, final String hKey, final T value)
{
redisTemplate.opsForHash().put(key, hKey, value);
}
/**
* 获取Hash中的数据
*
* @param key Redis键
* @param hKey Hash键
* @return Hash中的对象
*/
public <T> T getCacheMapValue(final String key, final String hKey)
{
HashOperations<String, String, T> opsForHash = redisTemplate.opsForHash();
return opsForHash.get(key, hKey);
}
/**
* 获取多个Hash中的数据
*
* @param key Redis键
* @param hKeys Hash键集合
* @return Hash对象集合
*/
public <T> List<T> getMultiCacheMapValue(final String key, final Collection<Object> hKeys)
{
return redisTemplate.opsForHash().multiGet(key, hKeys);
}
/**
* 获得缓存的基本对象列表
*
* @param pattern 字符串前缀
* @return 对象列表
*/
public Collection<String> keys(final String pattern)
{
return redisTemplate.keys(pattern);
}
}

View File

@@ -0,0 +1,231 @@
package com.ruoyi.common.core.redis;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundSetOperations;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Component;
import java.util.*;
import java.util.concurrent.TimeUnit;
/**
* spring redis 工具类
*
* @author ruoyi
**/
@SuppressWarnings(value = { "unchecked", "rawtypes" })
@Component
public class RedisService
{
@Autowired
public RedisTemplate redisTemplate;
/**
* 缓存基本的对象Integer、String、实体类等
*
* @param key 缓存的键值
* @param value 缓存的值
*/
public <T> void setCacheObject(final String key, final T value)
{
redisTemplate.opsForValue().set(key, value);
}
/**
* 缓存基本的对象Integer、String、实体类等
*
* @param key 缓存的键值
* @param value 缓存的值
* @param timeout 时间
* @param timeUnit 时间颗粒度
*/
public <T> void setCacheObject(final String key, final T value, final Integer timeout, final TimeUnit timeUnit)
{
redisTemplate.opsForValue().set(key, value, timeout, timeUnit);
}
/**
* 设置有效时间
*
* @param key Redis键
* @param timeout 超时时间
* @return true=设置成功false=设置失败
*/
public boolean expire(final String key, final long timeout)
{
return expire(key, timeout, TimeUnit.SECONDS);
}
/**
* 设置有效时间
*
* @param key Redis键
* @param timeout 超时时间
* @param unit 时间单位
* @return true=设置成功false=设置失败
*/
public boolean expire(final String key, final long timeout, final TimeUnit unit)
{
return redisTemplate.expire(key, timeout, unit);
}
/**
* 获得缓存的基本对象。
*
* @param key 缓存键值
* @return 缓存键值对应的数据
*/
public <T> T getCacheObject(final String key)
{
ValueOperations<String, T> operation = redisTemplate.opsForValue();
return operation.get(key);
}
/**
* 删除单个对象
*
* @param key
*/
public boolean deleteObject(final String key)
{
return redisTemplate.delete(key);
}
/**
* 删除集合对象
*
* @param collection 多个对象
* @return
*/
public long deleteObject(final Collection collection)
{
return redisTemplate.delete(collection);
}
/**
* 缓存List数据
*
* @param key 缓存的键值
* @param dataList 待缓存的List数据
* @return 缓存的对象
*/
public <T> long setCacheList(final String key, final List<T> dataList)
{
Long count = redisTemplate.opsForList().rightPushAll(key, dataList);
return count == null ? 0 : count;
}
/**
* 获得缓存的list对象
*
* @param key 缓存的键值
* @return 缓存键值对应的数据
*/
public <T> List<T> getCacheList(final String key)
{
return redisTemplate.opsForList().range(key, 0, -1);
}
/**
* 缓存Set
*
* @param key 缓存键值
* @param dataSet 缓存的数据
* @return 缓存数据的对象
*/
public <T> BoundSetOperations<String, T> setCacheSet(final String key, final Set<T> dataSet)
{
BoundSetOperations<String, T> setOperation = redisTemplate.boundSetOps(key);
Iterator<T> it = dataSet.iterator();
while (it.hasNext())
{
setOperation.add(it.next());
}
return setOperation;
}
/**
* 获得缓存的set
*
* @param key
* @return
*/
public <T> Set<T> getCacheSet(final String key)
{
return redisTemplate.opsForSet().members(key);
}
/**
* 缓存Map
*
* @param key
* @param dataMap
*/
public <T> void setCacheMap(final String key, final Map<String, T> dataMap)
{
if (dataMap != null) {
redisTemplate.opsForHash().putAll(key, dataMap);
}
}
/**
* 获得缓存的Map
*
* @param key
* @return
*/
public <T> Map<String, T> getCacheMap(final String key)
{
return redisTemplate.opsForHash().entries(key);
}
/**
* 往Hash中存入数据
*
* @param key Redis键
* @param hKey Hash键
* @param value 值
*/
public <T> void setCacheMapValue(final String key, final String hKey, final T value)
{
redisTemplate.opsForHash().put(key, hKey, value);
}
/**
* 获取Hash中的数据
*
* @param key Redis键
* @param hKey Hash键
* @return Hash中的对象
*/
public <T> T getCacheMapValue(final String key, final String hKey)
{
HashOperations<String, String, T> opsForHash = redisTemplate.opsForHash();
return opsForHash.get(key, hKey);
}
/**
* 获取多个Hash中的数据
*
* @param key Redis键
* @param hKeys Hash键集合
* @return Hash对象集合
*/
public <T> List<T> getMultiCacheMapValue(final String key, final Collection<Object> hKeys)
{
return redisTemplate.opsForHash().multiGet(key, hKeys);
}
/**
* 获得缓存的基本对象列表
*
* @param pattern 字符串前缀
* @return 对象列表
*/
public Collection<String> keys(final String pattern)
{
return redisTemplate.keys(pattern);
}
}

View File

@@ -0,0 +1,13 @@
package com.ruoyi.common.core.service;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.common.core.domain.TreeEntity;
import java.util.List;
public interface ITreeCommonService<T extends TreeEntity>
extends IService<T> {
public List<T> selectTreeList(Wrapper<T> wrapper);
}

View File

@@ -0,0 +1,83 @@
package com.ruoyi.common.core.service.impl;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.core.domain.TreeEntity;
import com.ruoyi.common.core.mapper.BaseTreeMapper;
import com.ruoyi.common.core.service.ITreeCommonService;
import com.ruoyi.common.utils.StringUtils;
import org.springframework.transaction.annotation.Transactional;
import java.io.Serializable;
import java.util.Collection;
import java.util.List;
@Transactional
public class TreeCommonServiceImpl<M extends BaseTreeMapper<T>, T extends TreeEntity>
extends ServiceImpl<M, T> implements ITreeCommonService<T> {
@Override
public T getById(Serializable id) {
return baseMapper.selectByTreeId(id);
}
@Override
public List<T> selectTreeList(Wrapper<T> wrapper) {
List<T> content = baseMapper.selectTreeList(wrapper);
return content;
}
@Override
public boolean save(T entity) {
if (!StringUtils.isEmpty(entity.getParentId()) && !"0".equals(entity.getParentId())) {
T parent = getById(entity.getParentId());
entity.setParentId(parent.getId());
entity.setAncestors(parent.makeSelfAsNewParentIds());
} else {
entity.setParentId(null);
}
return super.save(entity);
}
@Override
public boolean updateById(T entity) {
if (!StringUtils.isEmpty(entity.getParentId()) && !"0".equals(entity.getParentId())) {
T parent = getById(entity.getParentId());
updateSelftAndChild(entity, parent.getId(), parent.makeSelfAsNewParentIds());
} else {
entity.setParentId(null);
updateSelftAndChild(entity, "0", "0,");
}
return true;
}
private void updateSelftAndChild(T entity, String newParentId, String newParentIds) {
T oldEntity = getById(entity.getId());
String oldChildrenParentIds = oldEntity.makeSelfAsNewParentIds();
entity.setParentId(newParentId);
entity.setAncestors(newParentIds);
super.updateById(entity);
String newChildrenParentIds = entity.makeSelfAsNewParentIds();
baseMapper.updateSunTreeParentIds(newChildrenParentIds, oldChildrenParentIds);
}
@Override
public boolean removeById(Serializable id) {
T entity = getById(id);
baseMapper.deleteSunTree(entity.makeSelfAsNewParentIds());
return super.removeById(id);
}
@Override
public boolean removeByIds(Collection<? extends Serializable> idList) {
for (Serializable treeId: idList) {
removeById(treeId);
}
return true;
}
}

View File

@@ -0,0 +1,87 @@
package com.ruoyi.common.core.text;
import com.ruoyi.common.utils.StringUtils;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
/**
* 字符集工具类
*
* @author ruoyi
*/
public class CharsetKit
{
/** ISO-8859-1 */
public static final String ISO_8859_1 = "ISO-8859-1";
/** UTF-8 */
public static final String UTF_8 = "UTF-8";
/** GBK */
public static final String GBK = "GBK";
/** ISO-8859-1 */
public static final Charset CHARSET_ISO_8859_1 = Charset.forName(ISO_8859_1);
/** UTF-8 */
public static final Charset CHARSET_UTF_8 = Charset.forName(UTF_8);
/** GBK */
public static final Charset CHARSET_GBK = Charset.forName(GBK);
/**
* 转换为Charset对象
*
* @param charset 字符集,为空则返回默认字符集
* @return Charset
*/
public static Charset charset(String charset)
{
return StringUtils.isEmpty(charset) ? Charset.defaultCharset() : Charset.forName(charset);
}
/**
* 转换字符串的字符集编码
*
* @param source 字符串
* @param srcCharset 源字符集默认ISO-8859-1
* @param destCharset 目标字符集默认UTF-8
* @return 转换后的字符集
*/
public static String convert(String source, String srcCharset, String destCharset)
{
return convert(source, Charset.forName(srcCharset), Charset.forName(destCharset));
}
/**
* 转换字符串的字符集编码
*
* @param source 字符串
* @param srcCharset 源字符集默认ISO-8859-1
* @param destCharset 目标字符集默认UTF-8
* @return 转换后的字符集
*/
public static String convert(String source, Charset srcCharset, Charset destCharset)
{
if (null == srcCharset)
{
srcCharset = StandardCharsets.ISO_8859_1;
}
if (null == destCharset)
{
destCharset = StandardCharsets.UTF_8;
}
if (StringUtils.isEmpty(source) || srcCharset.equals(destCharset))
{
return source;
}
return new String(source.getBytes(srcCharset), destCharset);
}
/**
* @return 系统字符集编码
*/
public static String systemCharset()
{
return Charset.defaultCharset().name();
}
}

View File

@@ -0,0 +1,92 @@
package com.ruoyi.common.core.text;
import com.ruoyi.common.utils.StringUtils;
/**
* 字符串格式化
*
* @author ruoyi
*/
public class StrFormatter
{
public static final String EMPTY_JSON = "{}";
public static final char C_BACKSLASH = '\\';
public static final char C_DELIM_START = '{';
public static final char C_DELIM_END = '}';
/**
* 格式化字符串<br>
* 此方法只是简单将占位符 {} 按照顺序替换为参数<br>
* 如果想输出 {} 使用 \\转义 { 即可,如果想输出 {} 之前的 \ 使用双转义符 \\\\ 即可<br>
* 例:<br>
* 通常使用format("this is {} for {}", "a", "b") -> this is a for b<br>
* 转义{} format("this is \\{} for {}", "a", "b") -> this is \{} for a<br>
* 转义\ format("this is \\\\{} for {}", "a", "b") -> this is \a for b<br>
*
* @param strPattern 字符串模板
* @param argArray 参数列表
* @return 结果
*/
public static String format(final String strPattern, final Object... argArray)
{
if (StringUtils.isEmpty(strPattern) || StringUtils.isEmpty(argArray))
{
return strPattern;
}
final int strPatternLength = strPattern.length();
// 初始化定义好的长度以获得更好的性能
StringBuilder sbuf = new StringBuilder(strPatternLength + 50);
int handledPosition = 0;
int delimIndex;// 占位符所在位置
for (int argIndex = 0; argIndex < argArray.length; argIndex++)
{
delimIndex = strPattern.indexOf(EMPTY_JSON, handledPosition);
if (delimIndex == -1)
{
if (handledPosition == 0)
{
return strPattern;
}
else
{ // 字符串模板剩余部分不再包含占位符,加入剩余部分后返回结果
sbuf.append(strPattern, handledPosition, strPatternLength);
return sbuf.toString();
}
}
else
{
if (delimIndex > 0 && strPattern.charAt(delimIndex - 1) == C_BACKSLASH)
{
if (delimIndex > 1 && strPattern.charAt(delimIndex - 2) == C_BACKSLASH)
{
// 转义符之前还有一个转义符,占位符依旧有效
sbuf.append(strPattern, handledPosition, delimIndex - 1);
sbuf.append(Convert.utf8Str(argArray[argIndex]));
handledPosition = delimIndex + 2;
}
else
{
// 占位符被转义
argIndex--;
sbuf.append(strPattern, handledPosition, delimIndex - 1);
sbuf.append(C_DELIM_START);
handledPosition = delimIndex + 1;
}
}
else
{
// 正常占位符
sbuf.append(strPattern, handledPosition, delimIndex);
sbuf.append(Convert.utf8Str(argArray[argIndex]));
handledPosition = delimIndex + 2;
}
}
}
// 加入最后一个占位符后所有的字符
sbuf.append(strPattern, handledPosition, strPattern.length());
return sbuf.toString();
}
}

View File

@@ -0,0 +1,135 @@
package com.ruoyi.common.cos;
import com.ruoyi.common.cos.auth.COSSigner;
import com.ruoyi.common.cos.utils.VersionInfoUtils;
import org.apache.commons.codec.binary.Base64;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class PostObjectDemo {
public static void main(String[] args) throws Exception {
PostObjectUploadDemo();
}
private static void PostObjectUploadDemo() throws Exception {
String bucketName = "ddht-1324395003";
String endpoint = "cos.ap-shanghai.myqcloud.com";
String key = "images/test.png";
String filename = "test.png";
String inputFilePath = "C:\\Users\\admin\\Desktop\\1721376479165.jpg";
String contentType = "image/jpeg";
String secretId = "AKIDSBQuX5mAZvHa2jNwSzWE0lNvNuMjA9gC";
String seretKey = "VXZWQPYaedvMC6vovAU3gJ1ogXXdvO1n";
long startTimestamp = System.currentTimeMillis() / 1000;
long endTimestamp = startTimestamp + 30 * 60;
String endTimestampStr = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'").
format(endTimestamp * 1000);
String keyTime = startTimestamp + ";" + endTimestamp;
String boundary = "----WebKitFormBoundaryZBPbaoYE2gqeB21N";
// 设置表单的body字段值
Map<String, String> formFields = new HashMap<>();
formFields.put("q-sign-algorithm", "sha1");
formFields.put("key", key);
formFields.put("q-ak", secretId);
formFields.put("q-key-time", keyTime);
// 构造policy参考文档: https://cloud.tencent.com/document/product/436/14690
String policy = "{\n" +
" \"expiration\": \"" + endTimestampStr + "\",\n" +
" \"conditions\": [\n" +
" { \"bucket\": \"" + bucketName + "\" },\n" +
" { \"q-sign-algorithm\": \"sha1\" },\n" +
" { \"q-ak\": \"" + secretId + "\" },\n" +
" { \"q-sign-time\":\"" + keyTime + "\" }\n" +
" ]\n" +
"}";
// policy需要base64后算放入表单中
String encodedPolicy = new String(Base64.encodeBase64(policy.getBytes()));
// 设置policy
formFields.put("policy", encodedPolicy);
// 根据编码后的policy和secretKey计算签名
COSSigner cosSigner = new COSSigner();
String signature = cosSigner.buildPostObjectSignature(seretKey,
keyTime, policy);
// 设置签名
formFields.put("q-signature", signature);
// 根据以上表单参数构造最开始的body部分
String formBody = buildPostObjectBody(boundary, formFields,
filename, contentType);
HttpURLConnection conn = null;
try {
String urlStr = "http://" + bucketName + "." + endpoint;
URL url = new URL(urlStr);
conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setRequestProperty("User-Agent", VersionInfoUtils.getUserAgent());
conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
conn.setDoOutput(true);
conn.setDoInput(true);
OutputStream out = new DataOutputStream(conn.getOutputStream());
// 写入表单的最开始部分
out.write(formBody.getBytes());
// 将文件内容写入到输出流中
File file = new File(inputFilePath);
DataInputStream in = new DataInputStream(new FileInputStream(file));
int readBytes;
byte[] bytes = new byte[4096];
while ((readBytes = in.read(bytes)) != -1) {
out.write(bytes, 0, readBytes);
}
in.close();
// 添加最后一个分割符,行首和行尾都是--
byte[] endData = ("\r\n--" + boundary + "--\r\n").getBytes();
out.write(endData);
out.flush();
out.close();
// 读取响应头部
for (Map.Entry<String, List<String>> entries : conn.getHeaderFields().entrySet()) {
String values = "";
for (String value : entries.getValue()) {
values += value + ",";
}
if(entries.getKey() == null) {
System.out.println("reponse line:" + values );
} else {
System.out.println(entries.getKey() + ":" + values );
}
}
} catch (Exception e) {
e.printStackTrace();
throw e;
} finally {
if (conn != null) {
conn.disconnect();
}
}
}
public static String buildPostObjectBody(String boundary, Map<String, String> formFields,
String filename, String contentType) {
StringBuffer stringBuffer = new StringBuffer();
for(Map.Entry entry: formFields.entrySet()) {
// 添加boundary行,行首以--开头
stringBuffer.append("--").append(boundary).append("\r\n");
// 字段名
stringBuffer.append("Content-Disposition: form-data; name=\""
+ entry.getKey() + "\"\r\n\r\n");
// 字段值
stringBuffer.append(entry.getValue() + "\r\n");
}
// 添加boundary行,行首以--开头
stringBuffer.append("--").append(boundary).append("\r\n");
// 文件名
stringBuffer.append("Content-Disposition: form-data; name=\"file\"; "
+ "filename=\"" + filename + "\"\r\n");
// 文件类型
stringBuffer.append("Content-Type: " + contentType + "\r\n\r\n");
return stringBuffer.toString();
}
}

View File

@@ -0,0 +1,172 @@
package com.ruoyi.common.cos;
import com.alibaba.fastjson.JSONObject;
import okhttp3.*;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
public class TxApiHttpUtils {
public static void main(String[] args) throws IOException, NoSuchAlgorithmException, InvalidKeyException {
/*String secretId = "AKIDBG9FF8rkglmaSDnBMRdmtBSr7OVYP3Me";
String secretKey = "IUVOQPIFY2fH0njq3BEGD5vkV9hEj9Vz";
String token = "";
String service = "tms";
String version = "2020-12-29";
String action = "TextModeration";
String body = "{\"Content\":\"5L2g5aW9\"}";
String region = "ap-shanghai";
String resp = doRequest(secretId, secretKey, service, version, action, body, region, token);
System.out.println(resp);*/
System.out.printf(checkContext("你好").toString());
}
public static JSONObject checkContext(String content) {
String secretId = "AKIDBG9FF8rkglmaSDnBMRdmtBSr7OVYP3Me";
String secretKey = "IUVOQPIFY2fH0njq3BEGD5vkV9hEj9Vz";
String token = "";
String service = "tms";
String version = "2020-12-29";
String action = "TextModeration";
String body = "{\"Content\":\"5L2g5aW9\"}";
String region = "ap-shanghai";
String resp = null;
try {
resp = doRequest(secretId, secretKey, service, version, action, body, region, token);
return JSONObject.parseObject(resp);
} catch (IOException e) {
throw new RuntimeException(e);
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
} catch (InvalidKeyException e) {
throw new RuntimeException(e);
}
}
// singleton client for connection reuse and better performance
private static final OkHttpClient client = new OkHttpClient();
public static String doRequest(
String secretId, String secretKey,
String service, String version, String action,
String body, String region, String token
) throws IOException, NoSuchAlgorithmException, InvalidKeyException {
Request request = buildRequest(secretId, secretKey, service, version, action, body, region, token);
System.out.println(request.method() + " " + request.url());
System.out.println(request.headers());
System.out.println(body);
Response response = client.newCall(request).execute();
return response.body().string();
}
public static Request buildRequest(
String secretId, String secretKey,
String service, String version, String action,
String body, String region, String token
) throws NoSuchAlgorithmException, InvalidKeyException {
String host = "tms.ap-shanghai.tencentcloudapi.com";
String endpoint = "https://" + host;
String contentType = "application/json; charset=utf-8";
String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
String auth = getAuth(secretId, secretKey, host, contentType, timestamp, body);
return new Request.Builder()
.header("Host", host)
.header("X-TC-Timestamp", timestamp)
.header("X-TC-Version", version)
.header("X-TC-Action", action)
.header("X-TC-Region", region)
.header("X-TC-Token", token)
.header("X-TC-RequestClient", "SDK_JAVA_BAREBONE")
.header("Authorization", auth)
.url(endpoint)
.post(RequestBody.create(MediaType.parse(contentType), body))
.build();
}
private static String getAuth(
String secretId, String secretKey, String host, String contentType,
String timestamp, String body
) throws NoSuchAlgorithmException, InvalidKeyException {
String canonicalUri = "/";
String canonicalQueryString = "";
String canonicalHeaders = "content-type:" + contentType + "\nhost:" + host + "\n";
String signedHeaders = "content-type;host";
String hashedRequestPayload = sha256Hex(body.getBytes(StandardCharsets.UTF_8));
String canonicalRequest = "POST"
+ "\n"
+ canonicalUri
+ "\n"
+ canonicalQueryString
+ "\n"
+ canonicalHeaders
+ "\n"
+ signedHeaders
+ "\n"
+ hashedRequestPayload;
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
String date = sdf.format(new Date(Long.valueOf(timestamp + "000")));
String service = host.split("\\.")[0];
String credentialScope = date + "/" + service + "/" + "tc3_request";
String hashedCanonicalRequest =
sha256Hex(canonicalRequest.getBytes(StandardCharsets.UTF_8));
String stringToSign =
"TC3-HMAC-SHA256\n" + timestamp + "\n" + credentialScope + "\n" + hashedCanonicalRequest;
byte[] secretDate = hmac256(("TC3" + secretKey).getBytes(StandardCharsets.UTF_8), date);
byte[] secretService = hmac256(secretDate, service);
byte[] secretSigning = hmac256(secretService, "tc3_request");
String signature =
printHexBinary(hmac256(secretSigning, stringToSign)).toLowerCase();
return "TC3-HMAC-SHA256 "
+ "Credential="
+ secretId
+ "/"
+ credentialScope
+ ", "
+ "SignedHeaders="
+ signedHeaders
+ ", "
+ "Signature="
+ signature;
}
public static String sha256Hex(byte[] b) throws NoSuchAlgorithmException {
MessageDigest md;
md = MessageDigest.getInstance("SHA-256");
byte[] d = md.digest(b);
return printHexBinary(d).toLowerCase();
}
private static final char[] hexCode = "0123456789ABCDEF".toCharArray();
public static String printHexBinary(byte[] data) {
StringBuilder r = new StringBuilder(data.length * 2);
for (byte b : data) {
r.append(hexCode[(b >> 4) & 0xF]);
r.append(hexCode[(b & 0xF)]);
}
return r.toString();
}
public static byte[] hmac256(byte[] key, String msg) throws NoSuchAlgorithmException, InvalidKeyException {
Mac mac = Mac.getInstance("HmacSHA256");
SecretKeySpec secretKeySpec = new SecretKeySpec(key, mac.getAlgorithm());
mac.init(secretKeySpec);
return mac.doFinal(msg.getBytes(StandardCharsets.UTF_8));
}
}

View File

@@ -0,0 +1,251 @@
package com.ruoyi.common.cos;
import cn.hutool.core.codec.Base64;
import com.alibaba.fastjson.JSONObject;
import com.tencent.cloud.CosStsClient;
import com.tencent.cloud.Policy;
import com.tencent.cloud.Response;
import com.tencent.cloud.Statement;
import com.tencent.cloud.cos.util.Jackson;
import com.tencentcloudapi.common.AbstractModel;
import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.common.profile.ClientProfile;
import com.tencentcloudapi.common.profile.HttpProfile;
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
import com.tencentcloudapi.ims.v20201229.ImsClient;
import com.tencentcloudapi.ims.v20201229.models.ImageModerationRequest;
import com.tencentcloudapi.ims.v20201229.models.ImageModerationResponse;
import com.tencentcloudapi.sms.v20210111.SmsClient;
import com.tencentcloudapi.sms.v20210111.models.SendSmsRequest;
import com.tencentcloudapi.sms.v20210111.models.SendSmsResponse;
import com.tencentcloudapi.tms.v20201229.TmsClient;
import com.tencentcloudapi.tms.v20201229.models.TextModerationRequest;
import com.tencentcloudapi.tms.v20201229.models.TextModerationResponse;
import java.util.TreeMap;
public class TxApiSdkUtils
{
public static void main(String [] args) {
// System.out.printf(checkContext("你好").toString());
// System.out.printf(checkImages("https://xgtpt.oss-cn-hangzhou.aliyuncs.com/image/1708593052292148w_181&h_180.png").toString());
// sendSmsMsg("18225698628","256896");
}
/**
* 获取上传临时密钥
*/
public void getCredential() {
TreeMap<String, Object> config = new TreeMap<String, Object>();
try {
//这里的 SecretId 和 SecretKey 代表了用于申请临时密钥的永久身份(主账号、子账号等),子账号需要具有操作存储桶的权限。
String secretId = System.getenv("AKIDMcmoeNr64nIpicWBYeU6TaR8h280uyAF");//用户的 SecretId建议使用子账号密钥授权遵循最小权限指引降低使用风险。子账号密钥获取可参见 https://cloud.tencent.com/document/product/598/37140
String secretKey = System.getenv("yg8JEzVmriLjtqZ3KURUIrDRQ9euxmbI");//用户的 SecretKey建议使用子账号密钥授权遵循最小权限指引降低使用风险。子账号密钥获取可参见 https://cloud.tencent.com/document/product/598/37140
// 替换为您的云 api 密钥 SecretId
config.put("secretId", secretId);
// 替换为您的云 api 密钥 SecretKey
config.put("secretKey", secretKey);
// 初始化 policy
Policy policy = new Policy();
// 设置域名:
// 如果您使用了腾讯云 cvm可以设置内部域名
//config.put("host", "sts.internal.tencentcloudapi.com");
// 临时密钥有效时长,单位是秒,默认 1800 秒,目前主账号最长 2 小时(即 7200 秒),子账号最长 36 小时(即 129600
config.put("durationSeconds", 1800);
// 换成您的 bucket
config.put("bucket", "examplebucket-1250000000");
// 换成 bucket 所在地区
config.put("region", "ap-shanghai");
// 开始构建一条 statement
Statement statement = new Statement();
// 声明设置的结果是允许操作
statement.setEffect("allow");
/**
* 密钥的权限列表。必须在这里指定本次临时密钥所需要的权限。
* 权限列表请参见 https://cloud.tencent.com/document/product/436/31923
* 规则为 {project}:{interfaceName}
* project : 产品缩写 cos相关授权为值为cos,数据万象(数据处理)相关授权值为ci
* 授权所有接口用*表示,例如 cos:*,ci:*
* 添加一批操作权限 :
*/
statement.addActions(new String[]{
"cos:PutObject",
// 表单上传、小程序上传
"cos:PostObject",
// 分块上传
"cos:InitiateMultipartUpload",
"cos:ListMultipartUploads",
"cos:ListParts",
"cos:UploadPart",
"cos:CompleteMultipartUpload",
// 处理相关接口一般为数据万象产品 权限中以ci开头
// 创建媒体处理任务
"ci:CreateMediaJobs",
// 文件压缩
"ci:CreateFileProcessJobs"
});
/**
* 这里改成允许的路径前缀,可以根据自己网站的用户登录态判断允许上传的具体路径
* 资源表达式规则分对象存储(cos)和数据万象(ci)两种
* 数据处理、审核相关接口需要授予ci资源权限
* cos : qcs::cos:{region}:uid/{appid}:{bucket}/{path}
* ci : qcs::ci:{region}:uid/{appid}:bucket/{bucket}/{path}
* 列举几种典型的{path}授权场景:
* 1、允许访问所有对象"*"
* 2、允许访问指定的对象"a/a1.txt", "b/b1.txt"
* 3、允许访问指定前缀的对象"a*", "a/*", "b/*"
* 如果填写了“*”,将允许用户访问所有资源;除非业务需要,否则请按照最小权限原则授予用户相应的访问权限范围。
*
* 示例授权examplebucket-1250000000 bucket目录下的所有资源给cos和ci 授权两条Resource
*/
statement.addResources(new String[]{
"qcs::cos:ap-chongqing:uid/1250000000:examplebucket-1250000000/*",
"qcs::ci:ap-chongqing:uid/1250000000:bucket/examplebucket-1250000000/*"});
// 把一条 statement 添加到 policy
// 可以添加多条
policy.addStatement(statement);
// 将 Policy 示例转化成 String可以使用任何 json 转化方式,这里是本 SDK 自带的推荐方式
config.put("policy", Jackson.toJsonPrettyString(policy));
Response response = CosStsClient.getCredential(config);
System.out.println(response.credentials.tmpSecretId);
System.out.println(response.credentials.tmpSecretKey);
System.out.println(response.credentials.sessionToken);
} catch (Exception e) {
e.printStackTrace();
throw new IllegalArgumentException("no valid secret !");
}
}
/**
* 腾讯云文件安全检测
* @param content
* @return
*/
public static JSONObject checkContext(String content){
try{
// 实例化一个认证对象,入参需要传入腾讯云账户 SecretId 和 SecretKey此处还需注意密钥对的保密
// 代码泄露可能会导致 SecretId 和 SecretKey 泄露并威胁账号下所有资源的安全性。以下代码示例仅供参考建议采用更安全的方式来使用密钥请参见https://cloud.tencent.com/document/product/1278/85305
// 密钥可前往官网控制台 https://console.cloud.tencent.com/cam/capi 进行获取
Credential cred = new Credential("AKIDMcmoeNr64nIpicWBYeU6TaR8h280uyAF", "yg8JEzVmriLjtqZ3KURUIrDRQ9euxmbI");
// 实例化一个http选项可选的没有特殊需求可以跳过
HttpProfile httpProfile = new HttpProfile();
httpProfile.setEndpoint("tms.ap-shanghai.tencentcloudapi.com");
// 实例化一个client选项可选的没有特殊需求可以跳过
ClientProfile clientProfile = new ClientProfile();
clientProfile.setHttpProfile(httpProfile);
// 实例化要请求产品的client对象,clientProfile是可选的
TmsClient client = new TmsClient(cred, "ap-shanghai", clientProfile);
// 实例化一个请求对象,每个接口都会对应一个request对象
TextModerationRequest req = new TextModerationRequest();
String str = Base64.encode(content);
// System.out.printf(str);
req.setContent(str);
// 返回的resp是一个TextModerationResponse的实例与请求对象对应
TextModerationResponse resp = client.TextModeration(req);
// 输出json格式的字符串回包
String res = (AbstractModel.toJsonString(resp));
System.out.println(res);
return JSONObject.parseObject(res);
} catch (TencentCloudSDKException e) {
System.out.println(e.toString());
return null;
}
}
/**
* 腾讯云图片安全检测
* @param imgUrl
* @return
*/
public static JSONObject checkImages(String imgUrl){
try{
// 实例化一个认证对象,入参需要传入腾讯云账户 SecretId 和 SecretKey此处还需注意密钥对的保密
// 代码泄露可能会导致 SecretId 和 SecretKey 泄露并威胁账号下所有资源的安全性。以下代码示例仅供参考建议采用更安全的方式来使用密钥请参见https://cloud.tencent.com/document/product/1278/85305
// 密钥可前往官网控制台 https://console.cloud.tencent.com/cam/capi 进行获取
Credential cred = new Credential("AKIDMcmoeNr64nIpicWBYeU6TaR8h280uyAF", "yg8JEzVmriLjtqZ3KURUIrDRQ9euxmbI");
// 实例化一个http选项可选的没有特殊需求可以跳过
HttpProfile httpProfile = new HttpProfile();
httpProfile.setEndpoint("ims.ap-shanghai.tencentcloudapi.com");
// 实例化一个client选项可选的没有特殊需求可以跳过
ClientProfile clientProfile = new ClientProfile();
clientProfile.setHttpProfile(httpProfile);
// 实例化要请求产品的client对象,clientProfile是可选的
ImsClient client = new ImsClient(cred, "ap-shanghai", clientProfile);
// 实例化一个请求对象,每个接口都会对应一个request对象jkighjkhgkhgkhgjhghkjj
ImageModerationRequest req = new ImageModerationRequest();
req.setFileUrl(imgUrl);
// 返回的resp是一个ImageModerationResponse的实例与请求对象对应
ImageModerationResponse resp = client.ImageModeration(req);
// 输出json格式的字符串回包
String res = (AbstractModel.toJsonString(resp));
System.out.println(res);
return JSONObject.parseObject(res);
} catch (TencentCloudSDKException e) {
System.out.println(e.toString());
return null;
}
}
/**
* 腾讯云发送短信
* @param phoneNumber
* @param code
* @return
*/
public static JSONObject sendSmsMsg(String phoneNumber, String code){
try{
// 实例化一个认证对象,入参需要传入腾讯云账户 SecretId 和 SecretKey此处还需注意密钥对的保密
// 代码泄露可能会导致 SecretId 和 SecretKey 泄露并威胁账号下所有资源的安全性。以下代码示例仅供参考建议采用更安全的方式来使用密钥请参见https://cloud.tencent.com/document/product/1278/85305
// 密钥可前往官网控制台 https://console.cloud.tencent.com/cam/capi 进行获取
Credential cred = new Credential("AKIDMcmoeNr64nIpicWBYeU6TaR8h280uyAF", "yg8JEzVmriLjtqZ3KURUIrDRQ9euxmbI");
// 实例化一个http选项可选的没有特殊需求可以跳过
HttpProfile httpProfile = new HttpProfile();
httpProfile.setEndpoint("sms.tencentcloudapi.com");
// 实例化一个client选项可选的没有特殊需求可以跳过
ClientProfile clientProfile = new ClientProfile();
clientProfile.setHttpProfile(httpProfile);
// 实例化要请求产品的client对象,clientProfile是可选的
SmsClient client = new SmsClient(cred, "ap-nanjing", clientProfile);
// 实例化一个请求对象,每个接口都会对应一个request对象
SendSmsRequest req = new SendSmsRequest();
String[] phoneNumberSet1 = {phoneNumber};
req.setPhoneNumberSet(phoneNumberSet1);
req.setSmsSdkAppId("1400926380");
req.setTemplateId("2222045");
req.setSignName("合肥小图科技");
String[] templateParamSet1 = {code};
req.setTemplateParamSet(templateParamSet1);
// 返回的resp是一个SendSmsResponse的实例与请求对象对应
SendSmsResponse resp = client.SendSms(req);
// 输出json格式的字符串回包
String res = (AbstractModel.toJsonString(resp));
return JSONObject.parseObject(res);
} catch (TencentCloudSDKException e) {
System.out.println(e.toString());
return null;
}
}
}

View File

@@ -0,0 +1,104 @@
package com.ruoyi.common.cos.auth;
/*
* Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file 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.
* According to cos feature, we modify some classcomment, field name, etc.
*/
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.codec.digest.HmacUtils;
import java.util.Date;
import java.util.HashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
public class COSSigner {
private static Set<String> needSignedHeaderSet = new HashSet<>();
private Boolean isCIWorkflowRequest = false;
// Time offset between local and server
private int localTimeDelta = 0;
static {
needSignedHeaderSet.add("cache-control");
needSignedHeaderSet.add("content-disposition");
needSignedHeaderSet.add("content-encoding");
needSignedHeaderSet.add("content-length");
needSignedHeaderSet.add("content-md5");
needSignedHeaderSet.add("content-type");
needSignedHeaderSet.add("expect");
needSignedHeaderSet.add("expires");
needSignedHeaderSet.add("host");
needSignedHeaderSet.add("if-match");
needSignedHeaderSet.add("if-modified-since");
needSignedHeaderSet.add("if-none-match");
needSignedHeaderSet.add("if-unmodified-since");
needSignedHeaderSet.add("origin");
needSignedHeaderSet.add("range");
needSignedHeaderSet.add("transfer-encoding");
}
public String buildPostObjectSignature(String secretKey, String keyTime, String policy) {
String signKey = HmacUtils.hmacSha1Hex(secretKey, keyTime);
String stringToSign = DigestUtils.sha1Hex(policy);
return HmacUtils.hmacSha1Hex(signKey, stringToSign);
}
public boolean needSignedHeader(String header) {
return needSignedHeaderSet.contains(header) || header.startsWith("x-cos-");
}
private String buildSignMemberStr(Map<String, String> signHeaders) {
StringBuilder strBuilder = new StringBuilder();
boolean seenOne = false;
for (String key : signHeaders.keySet()) {
if (!seenOne) {
seenOne = true;
} else {
strBuilder.append(";");
}
strBuilder.append(key);
}
return strBuilder.toString();
}
private String formatMapToStr(Map<String, String> kVMap) {
StringBuilder strBuilder = new StringBuilder();
boolean seeOne = false;
for (Entry<String, String> entry : kVMap.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
if (!seeOne) {
seeOne = true;
} else {
strBuilder.append("&");
}
strBuilder.append(key).append("=").append(value);
}
return strBuilder.toString();
}
private String buildTimeStr(Date startTime, Date endTime) {
StringBuilder strBuilder = new StringBuilder();
long startTimestamp = startTime.getTime() / 1000 + localTimeDelta;
long endTimestamp = endTime.getTime() / 1000 + localTimeDelta;
strBuilder.append(startTimestamp).append(";").append(endTimestamp);
return strBuilder.toString();
}
}

View File

@@ -0,0 +1,126 @@
package com.ruoyi.common.cos.utils;
/*
* Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file 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.
* According to cos feature, we modify some classcomment, field name, etc.
*/
import java.io.InputStream;
import java.util.Properties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class VersionInfoUtils {
/** The COS SDK version info file with SDK versioning info */
static final String VERSION_INFO_FILE = "/versionInfo.properties";
/** SDK version info */
private static volatile String version;
/** SDK platform info */
private static volatile String platform;
/** User Agent info */
private static volatile String userAgent;
/** Shared logger for any issues while loading version information */
private static final Logger log = LoggerFactory.getLogger(VersionInfoUtils.class);
/**
* Returns the current version for the COS SDK in which this class is running. Version
* information is obtained from from the versionInfo.properties file which the COS Java SDK
* build process generates.
*
* @return The current version for the COS SDK, if known, otherwise returns a string indicating
* that the version information is not available.
*/
public static String getVersion() {
if (version == null) {
synchronized (VersionInfoUtils.class) {
if (version == null) {
initializeVersion();
}
}
}
return version;
}
/**
* Returns the current platform for the COS SDK in which this class is running. Version
* information is obtained from from the versionInfo.properties file which the COS Java SDK
* build process generates.
*
* @return The current platform for the COS SDK, if known, otherwise returns a string indicating
* that the platform information is not available.
*/
public static String getPlatform() {
if (platform == null) {
synchronized (VersionInfoUtils.class) {
if (platform == null) {
initializeVersion();
}
}
}
return platform;
}
/**
* @return Returns the User Agent string to be used when communicating with the COS services.
* The User Agent encapsulates SDK, Java, OS and region information.
*/
public static String getUserAgent() {
if (userAgent == null) {
synchronized(VersionInfoUtils.class) {
if (userAgent == null) {
userAgent = String.format("cos-java-sdk-v%s/%s/jdk-%s/%s",
getVersion(),
System.getProperty("os.name"),
System.getProperty("java.version"),
System.getProperty("java.vm.name"));
}
}
}
return userAgent;
}
/**
* Loads the versionInfo.properties file from the COS Java SDK and stores the information so
* that the file doesn't have to be read the next time the data is needed.
*/
private static void initializeVersion() {
InputStream inputStream = VersionInfoUtils.class.getResourceAsStream(VERSION_INFO_FILE);
Properties versionInfoProperties = new Properties();
try {
if (inputStream == null) {
throw new Exception(VERSION_INFO_FILE + " not found on classpath");
}
versionInfoProperties.load(inputStream);
version = versionInfoProperties.getProperty("version");
} catch (Exception e) {
log.info("Unable to load version information for the running SDK: " + e.getMessage());
version = "unknown-version";
platform = "java";
} finally {
try {
inputStream.close();
} catch (Exception e) {
}
}
}
}

View File

@@ -0,0 +1,20 @@
package com.ruoyi.common.enums;
/**
* 操作状态
*
* @author ruoyi
*
*/
public enum BusinessStatus
{
/**
* 成功
*/
SUCCESS,
/**
* 失败
*/
FAIL,
}

View File

@@ -0,0 +1,59 @@
package com.ruoyi.common.enums;
/**
* 业务操作类型
*
* @author ruoyi
*/
public enum BusinessType
{
/**
* 其它
*/
OTHER,
/**
* 新增
*/
INSERT,
/**
* 修改
*/
UPDATE,
/**
* 删除
*/
DELETE,
/**
* 授权
*/
GRANT,
/**
* 导出
*/
EXPORT,
/**
* 导入
*/
IMPORT,
/**
* 强退
*/
FORCE,
/**
* 生成代码
*/
GENCODE,
/**
* 清空数据
*/
CLEAN,
}

View File

@@ -0,0 +1,19 @@
package com.ruoyi.common.enums;
/**
* 数据源
*
* @author ruoyi
*/
public enum DataSourceType
{
/**
* 主库
*/
MASTER,
/**
* 从库
*/
SLAVE
}

View File

@@ -0,0 +1,36 @@
package com.ruoyi.common.enums;
import java.util.HashMap;
import java.util.Map;
import org.springframework.lang.Nullable;
/**
* 请求方式
*
* @author ruoyi
*/
public enum HttpMethod
{
GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE;
private static final Map<String, HttpMethod> mappings = new HashMap<>(16);
static
{
for (HttpMethod httpMethod : values())
{
mappings.put(httpMethod.name(), httpMethod);
}
}
@Nullable
public static HttpMethod resolve(@Nullable String method)
{
return (method != null ? mappings.get(method) : null);
}
public boolean matches(String method)
{
return (this == resolve(method));
}
}

View File

@@ -0,0 +1,20 @@
package com.ruoyi.common.enums;
/**
* 限流类型
*
* @author ruoyi
*/
public enum LimitType
{
/**
* 默认策略全局限流
*/
DEFAULT,
/**
* 根据请求者IP进行限流
*/
IP
}

View File

@@ -0,0 +1,24 @@
package com.ruoyi.common.enums;
/**
* 操作人类别
*
* @author ruoyi
*/
public enum OperatorType
{
/**
* 其它
*/
OTHER,
/**
* 后台用户
*/
MANAGE,
/**
* 手机端用户
*/
MOBILE
}

View File

@@ -0,0 +1,30 @@
package com.ruoyi.common.enums;
/**
* 用户状态
*
* @author ruoyi
*/
public enum UserStatus
{
OK("0", "正常"), DISABLE("1", "停用"), DELETED("2", "删除");
private final String code;
private final String info;
UserStatus(String code, String info)
{
this.code = code;
this.info = info;
}
public String getCode()
{
return code;
}
public String getInfo()
{
return info;
}
}

View File

@@ -0,0 +1,53 @@
package com.ruoyi.common.exception;
import com.ruoyi.common.exception.enums.abs.AbstractBaseExceptionEnum;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.ArrayList;
import java.util.List;
/**
* 业务异常
*
* @author xuyuxiang
* @date 2020/4/8 15:54
*/
@EqualsAndHashCode(callSuper = true)
@Data
public class CustomException extends RuntimeException {
private Integer code;
private String errorMessage;
private List objectList = new ArrayList();
public CustomException(Integer code, String errorMessage) {
super(errorMessage);
this.code = code;
this.errorMessage = errorMessage;
}
public CustomException(String errorMessage) {
super(errorMessage);
this.code = 500;
this.errorMessage = errorMessage;
}
public CustomException(AbstractBaseExceptionEnum exception) {
super(exception.getMessage());
this.code = exception.getCode();
this.errorMessage = exception.getMessage();
}
public CustomException(AbstractBaseExceptionEnum exception, List objectList) {
super(exception.getMessage());
this.code = exception.getCode();
this.errorMessage = exception.getMessage();
this.objectList = objectList;
}
}

View File

@@ -0,0 +1,15 @@
package com.ruoyi.common.exception;
/**
* 演示模式异常
*
* @author ruoyi
*/
public class DemoModeException extends RuntimeException
{
private static final long serialVersionUID = 1L;
public DemoModeException()
{
}
}

View File

@@ -0,0 +1,59 @@
package com.ruoyi.common.exception;
/**
* 全局异常
*
* @author ruoyi
*/
public class GlobalException extends RuntimeException
{
private static final long serialVersionUID = 1L;
/**
* 错误提示
*/
private String message;
/**
* 错误明细,内部调试错误
*
* 和 {@link CommonResult#getDetailMessage()} 一致的设计
*/
private String detailMessage;
/**
* 空构造方法,避免反序列化问题
*/
public GlobalException()
{
}
public GlobalException(String message)
{
this.message = message;
}
public String getDetailMessage()
{
return detailMessage;
}
public GlobalException setDetailMessage(String detailMessage)
{
this.detailMessage = detailMessage;
return this;
}
@Override
public String getMessage()
{
return message;
}
public GlobalException setMessage(String message)
{
this.message = message;
return this;
}
}

View File

@@ -0,0 +1,84 @@
package com.ruoyi.common.exception;
import com.ruoyi.common.exception.enums.abs.AbstractBaseExceptionEnum;
/**
* 业务异常
*
* @author ruoyi
*/
public final class ServiceException extends RuntimeException
{
private static final long serialVersionUID = 1L;
/**
* 错误码
*/
private Integer code;
/**
* 错误提示
*/
private String message;
/**
* 错误明细,内部调试错误
*
* 和 {@link CommonResult#getDetailMessage()} 一致的设计
*/
private String detailMessage;
/**
* 空构造方法,避免反序列化问题
*/
public ServiceException()
{
}
public ServiceException(String message)
{
this.message = message;
}
public ServiceException(String message, Integer code)
{
this.message = message;
this.code = code;
}
public String getDetailMessage()
{
return detailMessage;
}
@Override
public String getMessage()
{
return message;
}
public Integer getCode()
{
return code;
}
public ServiceException setMessage(String message)
{
this.message = message;
return this;
}
public ServiceException setDetailMessage(String detailMessage)
{
this.detailMessage = detailMessage;
return this;
}
public ServiceException(AbstractBaseExceptionEnum exception) {
super(exception.getMessage());
this.code = exception.getCode();
this.message = exception.getMessage();
}
}

View File

@@ -0,0 +1,26 @@
package com.ruoyi.common.exception;
/**
* 工具类异常
*
* @author ruoyi
*/
public class UtilException extends RuntimeException
{
private static final long serialVersionUID = 8247610319171014183L;
public UtilException(Throwable e)
{
super(e.getMessage(), e);
}
public UtilException(String message)
{
super(message);
}
public UtilException(String message, Throwable throwable)
{
super(message, throwable);
}
}

View File

@@ -0,0 +1,97 @@
package com.ruoyi.common.exception.base;
import com.ruoyi.common.utils.MessageUtils;
import com.ruoyi.common.utils.StringUtils;
/**
* 基础异常
*
* @author ruoyi
*/
public class BaseException extends RuntimeException
{
private static final long serialVersionUID = 1L;
/**
* 所属模块
*/
private String module;
/**
* 错误码
*/
private String code;
/**
* 错误码对应的参数
*/
private Object[] args;
/**
* 错误消息
*/
private String defaultMessage;
public BaseException(String module, String code, Object[] args, String defaultMessage)
{
this.module = module;
this.code = code;
this.args = args;
this.defaultMessage = defaultMessage;
}
public BaseException(String module, String code, Object[] args)
{
this(module, code, args, null);
}
public BaseException(String module, String defaultMessage)
{
this(module, null, null, defaultMessage);
}
public BaseException(String code, Object[] args)
{
this(null, code, args, null);
}
public BaseException(String defaultMessage)
{
this(null, null, null, defaultMessage);
}
@Override
public String getMessage()
{
String message = null;
if (!StringUtils.isEmpty(code))
{
message = MessageUtils.message(code, args);
}
if (message == null)
{
message = defaultMessage;
}
return message;
}
public String getModule()
{
return module;
}
public String getCode()
{
return code;
}
public Object[] getArgs()
{
return args;
}
public String getDefaultMessage()
{
return defaultMessage;
}
}

View File

@@ -0,0 +1,109 @@
/*
Copyright [2020] [https://www.stylefeng.cn]
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
http://www.apache.org/licenses/LICENSE-2.0
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.
Guns采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点:
1.请不要删除和修改根目录下的LICENSE文件。
2.请不要删除和修改Guns源码头部的版权声明。
3.请保留源码和相关描述文件的项目出处,作者声明等。
4.分发源码时候,请注明软件出处 https://gitee.com/stylefeng/guns-separation
5.在修改包名,模块名称,项目代码等时,请注明软件出处 https://gitee.com/stylefeng/guns-separation
6.若您的项目无法满足以上几点可申请商业授权获取Guns商业授权许可请在官网购买授权地址为 https://www.stylefeng.cn
*/
package com.ruoyi.common.exception.enums;
import com.ruoyi.common.exception.enums.abs.AbstractBaseExceptionEnum;
/**
* 认证相关的异常的枚举
* <p>
* 认证和鉴权的区别:
* <p>
* 认证可以证明你能登录系统认证的过程是校验token的过程
* 鉴权可以证明你有系统的哪些权限,鉴权的过程是校验角色是否包含某些接口的权限
*
* @author stylefeng
* @date 2019/7/18 22:22
*/
public enum AuthExceptionEnum implements AbstractBaseExceptionEnum {
/**
* 账号或密码为空
*/
ACCOUNT_PWD_EMPTY(1, "账号或密码为空"),
/**
* 账号密码错误
*/
ACCOUNT_PWD_ERROR(2, "账号或密码错误"),
/**
* 验证码错误
*/
VALID_CODE_ERROR(3, "验证码错误请检查captcha参数"),
/**
* 请求token为空
*/
REQUEST_TOKEN_EMPTY(700, "请求token为空"),
/**
* token格式不正确token请以Bearer开头
*/
NOT_VALID_TOKEN_TYPE(700, "token格式不正确token请以Bearer开头并且Bearer后边带一个空格"),
/**
* 请求token错误
*/
REQUEST_TOKEN_ERROR(700, "请求token错误"),
/**
* 账号被冻结
*/
ACCOUNT_FREEZE_ERROR(7, "账号被冻结,请联系管理员"),
/**
* 登录已过期
*/
LOGIN_EXPIRED(8, "登录已过期,请重新登录"),
/**
* 无登录用户
*/
NO_LOGIN_USER(9, "无登录用户");
private final Integer code;
private final String message;
AuthExceptionEnum(Integer code, String message) {
this.code = code;
this.message = message;
}
@Override
public Integer getCode() {
return code;
}
@Override
public String getMessage() {
return message;
}
}

View File

@@ -0,0 +1,138 @@
package com.ruoyi.common.exception.enums;
import com.ruoyi.common.exception.enums.abs.AbstractBaseExceptionEnum;
/**
* @author liwenlong
* @date 2021/11/1 19:34
*/
public enum CoreExceptionEnum implements AbstractBaseExceptionEnum {
/**
* 用户相关
*/
REGISTER_FAIL( "注册失败"),
PWD_ERROR( "密码错误"),
ACCOUNT_NOT_EXIST( "账号不存在"),
ACCOUNT_DISABLE( "账号被冻结"),
PHONE_NOT_EXIST( "手机号不存在"),
MOBILE_BIND_MAKE( "请使用绑定的手机号码"),
ACCOUNT_HAS_EXIST( "账号已存在,请重新输入"),
PHONE_HAS_EXIST( "手机号已存在,请重新输入"),
/**
* 邀请码
*/
REFEREE_CODE_ERROR( "邀请码错误"),
FIGURE_CODE_ERROR( "图形验证码错误"),
FIGURE_CODE_NOT_EXIST( "请先获取图形验证码"),
/**
* 短信
*/
SMS_SEND_FAIL( "短信发送失败"),
/**
* 参数
*/
ERROR_PARAM("参数错误"),
NOT_NULL_PARAM("参数不能为空"),
ERROR_DATA("数据错误"),
ERROR_FIELD_NAME("字段名称错误"),
/**
* 余额
*/
PRICE_ZERO(210, "支付金额为零"),
BALANCE_INSUFFICIENT (220, "余额不足"),
INTEGRAL_INSUFFICIENT (230, "积分不足"),
PAY_BALANCE_ERROR (240, "支付价格错误"),
EDIT_BALANCE_ERROR (250, "余额修改错误"),
/**
* 字典
*/
NO_DICTIONARIES( "未配置字典值"),
DICTIONARIES_ERROR( "字典值格式错误"),
/**
* 渲染
*/
WRITE_ERROR( "渲染界面错误"),
RESOURCES_NOT_EXIST("资源不存在"),
IO_ERROR("流读取异常"),
INVLIDE_DATE_STRING(400, "输入日期格式不对"),
FILE_READING_ERROR(400, "FILE_READING_ERROR!"),
FILE_NOT_FOUND(400, "FILE_NOT_FOUND!"),
PAGE_NULL(404, "请求页面不存在"),
REMOTE_SERVICE_NULL(404, "远程服务不存在"),
ERROR_TOKEN(520,"token异常"),
INPUT_PWD(530, "请输入支付密码"),
NO_PWD(540, "密码为空"),
UPDATE_PWD_ERROR("编辑密码错误"),
UPDATE_MOBILE_ERROR("编辑手机号错误"),
UPDATE_DATA(570, "数据更新错误"),
INSERT_DATA(580, "数据保存错误"),
ERROR_DICT_LACK(590,"字典表配置缺失"),
ENCRYPT_ERROR(600, "加解密错误"),
NO_CURRENT_USER(700, "当前没有登录的用户"),
FIELD_VALIDATE_ERROR(700, "数据库字段与实体字段不一致!"),
INIT_TABLE_EMPTY_PARAMS(701, "初始化数据库,存在为空的字段"),
ASYNC_ERROR(5000, "数据在被别人修改,请稍后重试"),
;
private Integer code;
private String message;
private CoreExceptionEnum(int code, String message) {
this.code = code;
this.message = message;
}
private CoreExceptionEnum(String message) {
this.code = 500;
this.message = message;
}
@Override
public Integer getCode() {
return this.code;
}
@Override
public String getMessage() {
return this.message;
}
}

View File

@@ -0,0 +1,61 @@
/*
Copyright [2020] [https://www.stylefeng.cn]
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
http://www.apache.org/licenses/LICENSE-2.0
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.
Guns采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点:
1.请不要删除和修改根目录下的LICENSE文件。
2.请不要删除和修改Guns源码头部的版权声明。
3.请保留源码和相关描述文件的项目出处,作者声明等。
4.分发源码时候,请注明软件出处 https://gitee.com/stylefeng/guns-separation
5.在修改包名,模块名称,项目代码等时,请注明软件出处 https://gitee.com/stylefeng/guns-separation
6.若您的项目无法满足以上几点可申请商业授权获取Guns商业授权许可请在官网购买授权地址为 https://www.stylefeng.cn
*/
package com.ruoyi.common.exception.enums;
import com.ruoyi.common.exception.enums.abs.AbstractBaseExceptionEnum;
/**
* 参数校验异常枚举
*
* @author xuyuxiang
* @date 2020/3/25 20:11
*/
public enum ParamExceptionEnum implements AbstractBaseExceptionEnum {
/**
* 参数错误
*/
PARAM_ERROR(1, "参数错误");
private final Integer code;
private final String message;
ParamExceptionEnum(Integer code, String message) {
this.code = code;
this.message = message;
}
@Override
public Integer getCode() {
return code;
}
@Override
public String getMessage() {
return message;
}
}

View File

@@ -0,0 +1,92 @@
/*
Copyright [2020] [https://www.stylefeng.cn]
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
http://www.apache.org/licenses/LICENSE-2.0
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.
Guns采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点:
1.请不要删除和修改根目录下的LICENSE文件。
2.请不要删除和修改Guns源码头部的版权声明。
3.请保留源码和相关描述文件的项目出处,作者声明等。
4.分发源码时候,请注明软件出处 https://gitee.com/stylefeng/guns-separation
5.在修改包名,模块名称,项目代码等时,请注明软件出处 https://gitee.com/stylefeng/guns-separation
6.若您的项目无法满足以上几点可申请商业授权获取Guns商业授权许可请在官网购买授权地址为 https://www.stylefeng.cn
*/
package com.ruoyi.common.exception.enums;
import com.ruoyi.common.exception.enums.abs.AbstractBaseExceptionEnum;
/**
* 授权和鉴权异常的枚举
* <p>
* 认证和鉴权的区别:
* <p>
* 认证可以证明你能登录系统认证的过程是校验token的过程
* 鉴权可以证明你有系统的哪些权限,鉴权的过程是校验角色是否包含某些接口的权限
*
* @author xuyuxiang
* @date 2020/3/12 10:14
*/
public enum PermissionExceptionEnum implements AbstractBaseExceptionEnum {
/**
* 资源路径不存在
*/
URL_NOT_EXIST(1, "资源路径不存在,请检查请求地址"),
/**
* 没有权限访问资源
*/
NO_PERMISSION(2, "没有权限访问资源,请联系管理员"),
/**
* 没有权限操作该数据
*/
NO_PERMISSION_OPERATE(3, "没有权限操作该数据,请联系管理员"),
/**
* 手机号已存在
*/
MOBILE_REPEAT(4, "手机号已存在"),
/**
* 账号已存在
*/
ACCOUNT_REPEAT(5, "账号已存在"),
/**
* 请指定接收数据的操作员
*/
NO_CHOOSE_OPERATOR(7, "请指定接收数据的操作员");
private final Integer code;
private final String message;
PermissionExceptionEnum(Integer code, String message) {
this.code = code;
this.message = message;
}
@Override
public Integer getCode() {
return code;
}
@Override
public String getMessage() {
return message;
}
}

View File

@@ -0,0 +1,67 @@
/*
Copyright [2020] [https://www.stylefeng.cn]
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
http://www.apache.org/licenses/LICENSE-2.0
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.
Guns采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点:
1.请不要删除和修改根目录下的LICENSE文件。
2.请不要删除和修改Guns源码头部的版权声明。
3.请保留源码和相关描述文件的项目出处,作者声明等。
4.分发源码时候,请注明软件出处 https://gitee.com/stylefeng/guns-separation
5.在修改包名,模块名称,项目代码等时,请注明软件出处 https://gitee.com/stylefeng/guns-separation
6.若您的项目无法满足以上几点可申请商业授权获取Guns商业授权许可请在官网购买授权地址为 https://www.stylefeng.cn
*/
package com.ruoyi.common.exception.enums;
import com.ruoyi.common.exception.enums.abs.AbstractBaseExceptionEnum;
/**
* 请求方法相关异常枚举
*
* @author xuyuxiang
* @date 2020/3/11 15:33
*/
public enum RequestMethodExceptionEnum implements AbstractBaseExceptionEnum {
/**
* 不支持该请求方法请求方法应为POST
*/
REQUEST_METHOD_IS_POST(1, "不支持该请求方法请求方法应为POST"),
/**
* 不支持该请求方法请求方法应为GET
*/
REQUEST_METHOD_IS_GET(2, "不支持该请求方法请求方法应为GET");
private final Integer code;
private final String message;
RequestMethodExceptionEnum(Integer code, String message) {
this.code = code;
this.message = message;
}
@Override
public Integer getCode() {
return code;
}
@Override
public String getMessage() {
return message;
}
}

View File

@@ -0,0 +1,67 @@
/*
Copyright [2020] [https://www.stylefeng.cn]
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
http://www.apache.org/licenses/LICENSE-2.0
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.
Guns采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点:
1.请不要删除和修改根目录下的LICENSE文件。
2.请不要删除和修改Guns源码头部的版权声明。
3.请保留源码和相关描述文件的项目出处,作者声明等。
4.分发源码时候,请注明软件出处 https://gitee.com/stylefeng/guns-separation
5.在修改包名,模块名称,项目代码等时,请注明软件出处 https://gitee.com/stylefeng/guns-separation
6.若您的项目无法满足以上几点可申请商业授权获取Guns商业授权许可请在官网购买授权地址为 https://www.stylefeng.cn
*/
package com.ruoyi.common.exception.enums;
import com.ruoyi.common.exception.enums.abs.AbstractBaseExceptionEnum;
/**
* 请求类型相关异常枚举
*
* @author xuyuxiang
* @date 2020/4/2 15:42
*/
public enum RequestTypeExceptionEnum implements AbstractBaseExceptionEnum {
/**
* 参数传递格式不支持
*/
REQUEST_TYPE_IS_JSON(1, "参数传递格式不支持请使用JSON格式传参"),
/**
* 请求JSON参数格式不正确
*/
REQUEST_JSON_ERROR(2, "请求JSON参数格式不正确请检查参数格式");
private final Integer code;
private final String message;
RequestTypeExceptionEnum(Integer code, String message) {
this.code = code;
this.message = message;
}
@Override
public Integer getCode() {
return code;
}
@Override
public String getMessage() {
return message;
}
}

View File

@@ -0,0 +1,65 @@
/**
* Copyright 2018-2020 stylefeng & fengshuonan (https://gitee.com/stylefeng)
* <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 com.ruoyi.common.exception.enums;
import com.ruoyi.common.exception.enums.abs.AbstractBaseExceptionEnum;
/**
* rest异常
*
* @author administrator
* @date 2016年11月12日 下午5:04:51
*/
public enum RestExceptionEnum implements AbstractBaseExceptionEnum {
/**
* token异常
*/
TOKEN_EXPIRED(700, "token过期"),
TOKEN_ERROR(700, "token验证失败"),
AUTH_EXCEPTION(700, "token过期");
RestExceptionEnum(int code, String message) {
this.code = code;
this.message = message;
}
private Integer code;
private String message;
@Override
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
@Override
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}

View File

@@ -0,0 +1,82 @@
/*
Copyright [2020] [https://www.stylefeng.cn]
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
http://www.apache.org/licenses/LICENSE-2.0
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.
Guns采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点:
1.请不要删除和修改根目录下的LICENSE文件。
2.请不要删除和修改Guns源码头部的版权声明。
3.请保留源码和相关描述文件的项目出处,作者声明等。
4.分发源码时候,请注明软件出处 https://gitee.com/stylefeng/guns-separation
5.在修改包名,模块名称,项目代码等时,请注明软件出处 https://gitee.com/stylefeng/guns-separation
6.若您的项目无法满足以上几点可申请商业授权获取Guns商业授权许可请在官网购买授权地址为 https://www.stylefeng.cn
*/
package com.ruoyi.common.exception.enums;
import com.ruoyi.common.exception.enums.abs.AbstractBaseExceptionEnum;
/**
* 服务器内部相关异常枚举
*
* @author xuyuxiang
* @date 2020/3/18 19:19
*/
public enum ServerExceptionEnum implements AbstractBaseExceptionEnum {
/**
* 当前请求参数为空或数据缺失
*/
REQUEST_EMPTY(1, "当前请求参数为空或数据缺失,请联系管理员"),
/**
* 加载中,请稍后……
*/
SERVER_ERROR(2, "程序异常,请联系管理员"),
/**
* 常量获取存在空值
*/
CONSTANT_EMPTY(3, "常量获取存在空值请检查sys_config中是否配置"),
/**
*
*/
COMMON_EXCEPTION(4, "编译异常"),
/**
* 请勿重复提交
*/
NO_REPEAT_REQUEST(5, "请勿重复提交");
private final Integer code;
private final String message;
ServerExceptionEnum(Integer code, String message) {
this.code = code;
this.message = message;
}
@Override
public Integer getCode() {
return code;
}
@Override
public String getMessage() {
return message;
}
}

View File

@@ -0,0 +1,81 @@
/*
Copyright [2020] [https://www.stylefeng.cn]
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
http://www.apache.org/licenses/LICENSE-2.0
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.
Guns采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点:
1.请不要删除和修改根目录下的LICENSE文件。
2.请不要删除和修改Guns源码头部的版权声明。
3.请保留源码和相关描述文件的项目出处,作者声明等。
4.分发源码时候,请注明软件出处 https://gitee.com/stylefeng/guns-separation
5.在修改包名,模块名称,项目代码等时,请注明软件出处 https://gitee.com/stylefeng/guns-separation
6.若您的项目无法满足以上几点可申请商业授权获取Guns商业授权许可请在官网购买授权地址为 https://www.stylefeng.cn
*/
package com.ruoyi.common.exception.enums;
import com.ruoyi.common.exception.enums.abs.AbstractBaseExceptionEnum;
/**
* 状态枚举
*
* @author stylefeng
* @date 2020/4/30 22:45
*/
public enum StatusExceptionEnum implements AbstractBaseExceptionEnum {
/**
* 请求状态值为空
*/
REQUEST_EMPTY(1, "请求状态值为空"),
/**
* 请求状值为非正确状态值
*/
NOT_WRITE_STATUS(2, "请求状态值不合法"),
/**
* 更新状态失败,试图更新被删除的记录
*/
UPDATE_STATUS_ERROR(3, "更新状态失败,您试图更新被删除的记录"),
/**
* 操作失败
*/
OPERATOR_FAIL(500, "操作失败"),;
private final Integer code;
private final String message;
StatusExceptionEnum(Integer code, String message) {
this.code = code;
this.message = message;
}
@Override
public Integer getCode() {
return code;
}
@Override
public String getMessage() {
return message;
}
public static void main(String[] args) {
System.out.println(StatusExceptionEnum.NOT_WRITE_STATUS.getCode());
}
}

View File

@@ -0,0 +1,72 @@
/*
Copyright [2020] [https://www.stylefeng.cn]
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
http://www.apache.org/licenses/LICENSE-2.0
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.
Guns采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点:
1.请不要删除和修改根目录下的LICENSE文件。
2.请不要删除和修改Guns源码头部的版权声明。
3.请保留源码和相关描述文件的项目出处,作者声明等。
4.分发源码时候,请注明软件出处 https://gitee.com/stylefeng/guns-separation
5.在修改包名,模块名称,项目代码等时,请注明软件出处 https://gitee.com/stylefeng/guns-separation
6.若您的项目无法满足以上几点可申请商业授权获取Guns商业授权许可请在官网购买授权地址为 https://www.stylefeng.cn
*/
package com.ruoyi.common.exception.enums;
import com.ruoyi.common.exception.enums.abs.AbstractBaseExceptionEnum;
/**
* 对象包装异常
*
* @author fengshuonan
* @date 2020/7/24 14:36
*/
public enum WrapperExceptionEnum implements AbstractBaseExceptionEnum {
/**
* 被包装的值不能是基本类型
*/
BASIC_TYPE_ERROR(1, "被包装的值不能是基本类型"),
/**
* 获取转化字段的值异常
*/
TRANSFER_FILED_VALUE_ERROR(2, "获取转化字段的值异常"),
/**
* 字段包装转化异常
*/
TRANSFER_ERROR(3, "字段包装转化异常");
private final Integer code;
private final String message;
WrapperExceptionEnum(Integer code, String message) {
this.code = code;
this.message = message;
}
@Override
public Integer getCode() {
return code;
}
@Override
public String getMessage() {
return message;
}
}

View File

@@ -0,0 +1,53 @@
/*
Copyright [2020] [https://www.stylefeng.cn]
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
http://www.apache.org/licenses/LICENSE-2.0
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.
Guns采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点:
1.请不要删除和修改根目录下的LICENSE文件。
2.请不要删除和修改Guns源码头部的版权声明。
3.请保留源码和相关描述文件的项目出处,作者声明等。
4.分发源码时候,请注明软件出处 https://gitee.com/stylefeng/guns-separation
5.在修改包名,模块名称,项目代码等时,请注明软件出处 https://gitee.com/stylefeng/guns-separation
6.若您的项目无法满足以上几点可申请商业授权获取Guns商业授权许可请在官网购买授权地址为 https://www.stylefeng.cn
*/
package com.ruoyi.common.exception.enums.abs;
/**
* 异常枚举格式规范
*
* @author stylefeng
* @date 2017/12/17 22:22
*/
public interface AbstractBaseExceptionEnum {
/**
* 获取异常的状态码
*
* @return 状态码
* @author stylefeng
* @date 2020/7/9 14:28
*/
Integer getCode();
/**
* 获取异常的提示信息
*
* @return 提示信息
* @author stylefeng
* @date 2020/7/9 14:28
*/
String getMessage();
}

View File

@@ -0,0 +1,19 @@
package com.ruoyi.common.exception.file;
import com.ruoyi.common.exception.base.BaseException;
/**
* 文件信息异常类
*
* @author ruoyi
*/
public class FileException extends BaseException
{
private static final long serialVersionUID = 1L;
public FileException(String code, Object[] args)
{
super("file", code, args, null);
}
}

View File

@@ -0,0 +1,16 @@
package com.ruoyi.common.exception.file;
/**
* 文件名称超长限制异常类
*
* @author ruoyi
*/
public class FileNameLengthLimitExceededException extends FileException
{
private static final long serialVersionUID = 1L;
public FileNameLengthLimitExceededException(int defaultFileNameLength)
{
super("upload.filename.exceed.length", new Object[] { defaultFileNameLength });
}
}

View File

@@ -0,0 +1,16 @@
package com.ruoyi.common.exception.file;
/**
* 文件名大小限制异常类
*
* @author ruoyi
*/
public class FileSizeLimitExceededException extends FileException
{
private static final long serialVersionUID = 1L;
public FileSizeLimitExceededException(long defaultMaxSize)
{
super("upload.exceed.maxSize", new Object[] { defaultMaxSize });
}
}

View File

@@ -0,0 +1,81 @@
package com.ruoyi.common.exception.file;
import java.util.Arrays;
import org.apache.commons.fileupload.FileUploadException;
/**
* 文件上传 误异常类
*
* @author ruoyi
*/
public class InvalidExtensionException extends FileUploadException
{
private static final long serialVersionUID = 1L;
private String[] allowedExtension;
private String extension;
private String filename;
public InvalidExtensionException(String[] allowedExtension, String extension, String filename)
{
super("filename : [" + filename + "], extension : [" + extension + "], allowed extension : [" + Arrays.toString(allowedExtension) + "]");
this.allowedExtension = allowedExtension;
this.extension = extension;
this.filename = filename;
}
public String[] getAllowedExtension()
{
return allowedExtension;
}
public String getExtension()
{
return extension;
}
public String getFilename()
{
return filename;
}
public static class InvalidImageExtensionException extends InvalidExtensionException
{
private static final long serialVersionUID = 1L;
public InvalidImageExtensionException(String[] allowedExtension, String extension, String filename)
{
super(allowedExtension, extension, filename);
}
}
public static class InvalidFlashExtensionException extends InvalidExtensionException
{
private static final long serialVersionUID = 1L;
public InvalidFlashExtensionException(String[] allowedExtension, String extension, String filename)
{
super(allowedExtension, extension, filename);
}
}
public static class InvalidMediaExtensionException extends InvalidExtensionException
{
private static final long serialVersionUID = 1L;
public InvalidMediaExtensionException(String[] allowedExtension, String extension, String filename)
{
super(allowedExtension, extension, filename);
}
}
public static class InvalidVideoExtensionException extends InvalidExtensionException
{
private static final long serialVersionUID = 1L;
public InvalidVideoExtensionException(String[] allowedExtension, String extension, String filename)
{
super(allowedExtension, extension, filename);
}
}
}

View File

@@ -0,0 +1,34 @@
package com.ruoyi.common.exception.job;
/**
* 计划策略异常
*
* @author ruoyi
*/
public class TaskException extends Exception
{
private static final long serialVersionUID = 1L;
private Code code;
public TaskException(String msg, Code code)
{
this(msg, code, null);
}
public TaskException(String msg, Code code, Exception nestedEx)
{
super(msg, nestedEx);
this.code = code;
}
public Code getCode()
{
return code;
}
public enum Code
{
TASK_EXISTS, NO_TASK_EXISTS, TASK_ALREADY_STARTED, UNKNOWN, CONFIG_ERROR, TASK_NODE_NOT_AVAILABLE
}
}

View File

@@ -0,0 +1,16 @@
package com.ruoyi.common.exception.user;
/**
* 验证码错误异常类
*
* @author ruoyi
*/
public class CaptchaException extends UserException
{
private static final long serialVersionUID = 1L;
public CaptchaException()
{
super("user.jcaptcha.error", null);
}
}

View File

@@ -0,0 +1,16 @@
package com.ruoyi.common.exception.user;
/**
* 验证码失效异常类
*
* @author ruoyi
*/
public class CaptchaExpireException extends UserException
{
private static final long serialVersionUID = 1L;
public CaptchaExpireException()
{
super("user.jcaptcha.expire", null);
}
}

View File

@@ -0,0 +1,18 @@
package com.ruoyi.common.exception.user;
import com.ruoyi.common.exception.base.BaseException;
/**
* 用户信息异常类
*
* @author ruoyi
*/
public class UserException extends BaseException
{
private static final long serialVersionUID = 1L;
public UserException(String code, Object[] args)
{
super("user", code, args, null);
}
}

View File

@@ -0,0 +1,16 @@
package com.ruoyi.common.exception.user;
/**
* 用户密码不正确或不符合规范异常类
*
* @author ruoyi
*/
public class UserPasswordNotMatchException extends UserException
{
private static final long serialVersionUID = 1L;
public UserPasswordNotMatchException()
{
super("user.password.not.match", null);
}
}

View File

@@ -0,0 +1,113 @@
package com.ruoyi.common.filter;
import com.ruoyi.common.annotation.CreateBy;
import com.ruoyi.common.annotation.CreateTime;
import com.ruoyi.common.annotation.UpdateBy;
import com.ruoyi.common.annotation.UpdateTime;
import com.ruoyi.common.core.domain.BaseEntity;
import com.ruoyi.common.utils.SecurityUtils;
import org.apache.ibatis.binding.MapperMethod;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Signature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import java.lang.reflect.Field;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* 自定义 Mybatis 插件,自动设置 createTime 和 updatTime 的值。
* 拦截 update 操作(添加和修改)
*/
@Component
@Intercepts({@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class})})
public class CustomInterceptor implements Interceptor {
private static final Logger logger = LoggerFactory.getLogger(CustomInterceptor.class);
@Override
public Object intercept(Invocation invocation) throws Throwable {
MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
// 获取 SQL 命令
SqlCommandType sqlCommandType = mappedStatement.getSqlCommandType();
//只判断新增和修改
if (SqlCommandType.INSERT.equals(sqlCommandType) || SqlCommandType.UPDATE.equals(sqlCommandType)) {
// 获取参数
Object parameter = invocation.getArgs()[1];
//批量操作时
if (parameter instanceof MapperMethod.ParamMap) {
MapperMethod.ParamMap map = (MapperMethod.ParamMap) parameter;
if (map.containsKey("list")) {
Object obj = map.get("list");
List<?> list = (List<?>) obj;
if (list != null) {
for (Object o : list) {
setParameter(o, sqlCommandType);
}
}
}
} else {
setParameter(parameter, sqlCommandType);
}
}
return invocation.proceed();
}
public void setParameter(Object parameter, SqlCommandType sqlCommandType) throws Throwable {
Class<?> aClass = parameter.getClass();
Field[] declaredFields;
//如果常用字段提取了公共类 BaseEntity
//判断BaseEntity是否是父类
if (BaseEntity.class.isAssignableFrom(aClass)) {
// 获取父类私有成员变量
declaredFields = aClass.getSuperclass().getDeclaredFields();
} else {
// 获取私有成员变量
declaredFields = aClass.getDeclaredFields();
}
for (Field field : declaredFields) {
if (SqlCommandType.INSERT.equals(sqlCommandType)) { // insert 语句插入 createBy
if (field.getAnnotation(CreateBy.class) != null) {
field.setAccessible(true);
try {
field.set(parameter, SecurityUtils.getUserId().toString());
}catch (Exception e){
field.set(parameter, "0");
continue;
}
}
if (field.getAnnotation(CreateTime.class) != null) { // insert 语句插入 createTime
field.setAccessible(true);
field.set(parameter, new Timestamp(System.currentTimeMillis()));
}
}
if (SqlCommandType.UPDATE.equals(sqlCommandType)) {
if (field.getAnnotation(UpdateTime.class) != null) { // update 语句插入 updateTime
field.setAccessible(true);
field.set(parameter, new Timestamp(System.currentTimeMillis()));
}
if (field.getAnnotation(UpdateBy.class) != null) { // update 语句插入 updateBy
field.setAccessible(true);
try {
field.set(parameter, SecurityUtils.getUserId().toString());
}catch (Exception e){
continue;
}
}
}
}
}
}

View File

@@ -0,0 +1,52 @@
package com.ruoyi.common.filter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import org.springframework.http.MediaType;
import com.ruoyi.common.utils.StringUtils;
/**
* Repeatable 过滤器
*
* @author ruoyi
*/
public class RepeatableFilter implements Filter
{
@Override
public void init(FilterConfig filterConfig) throws ServletException
{
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException
{
ServletRequest requestWrapper = null;
if (request instanceof HttpServletRequest
&& StringUtils.startsWithIgnoreCase(request.getContentType(), MediaType.APPLICATION_JSON_VALUE))
{
requestWrapper = new RepeatedlyRequestWrapper((HttpServletRequest) request, response);
}
if (null == requestWrapper)
{
chain.doFilter(request, response);
}
else
{
chain.doFilter(requestWrapper, response);
}
}
@Override
public void destroy()
{
}
}

View File

@@ -0,0 +1,75 @@
package com.ruoyi.common.filter;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import com.ruoyi.common.utils.http.HttpHelper;
/**
* 构建可重复读取inputStream的request
*
* @author ruoyi
*/
public class RepeatedlyRequestWrapper extends HttpServletRequestWrapper
{
private final byte[] body;
public RepeatedlyRequestWrapper(HttpServletRequest request, ServletResponse response) throws IOException
{
super(request);
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
body = HttpHelper.getBodyString(request).getBytes("UTF-8");
}
@Override
public BufferedReader getReader() throws IOException
{
return new BufferedReader(new InputStreamReader(getInputStream()));
}
@Override
public ServletInputStream getInputStream() throws IOException
{
final ByteArrayInputStream bais = new ByteArrayInputStream(body);
return new ServletInputStream()
{
@Override
public int read() throws IOException
{
return bais.read();
}
@Override
public int available() throws IOException
{
return body.length;
}
@Override
public boolean isFinished()
{
return false;
}
@Override
public boolean isReady()
{
return false;
}
@Override
public void setReadListener(ReadListener readListener)
{
}
};
}
}

View File

@@ -0,0 +1,74 @@
package com.ruoyi.common.filter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.ruoyi.common.utils.StringUtils;
/**
* 防止XSS攻击的过滤器
*
* @author ruoyi
*/
public class XssFilter implements Filter
{
/**
* 排除链接
*/
public List<String> excludes = new ArrayList<>();
@Override
public void init(FilterConfig filterConfig) throws ServletException
{
String tempExcludes = filterConfig.getInitParameter("excludes");
if (StringUtils.isNotEmpty(tempExcludes))
{
String[] url = tempExcludes.split(",");
for (int i = 0; url != null && i < url.length; i++)
{
excludes.add(url[i]);
}
}
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException
{
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse resp = (HttpServletResponse) response;
if (handleExcludeURL(req, resp))
{
chain.doFilter(request, response);
return;
}
XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper((HttpServletRequest) request);
chain.doFilter(xssRequest, response);
}
private boolean handleExcludeURL(HttpServletRequest request, HttpServletResponse response)
{
String url = request.getServletPath();
String method = request.getMethod();
// GET DELETE 不过滤
if (method == null || method.matches("GET") || method.matches("DELETE"))
{
return true;
}
return StringUtils.matches(url, excludes);
}
@Override
public void destroy()
{
}
}

View File

@@ -0,0 +1,111 @@
package com.ruoyi.common.filter;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import org.apache.commons.io.IOUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.html.EscapeUtil;
/**
* XSS过滤处理
*
* @author ruoyi
*/
public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper
{
/**
* @param request
*/
public XssHttpServletRequestWrapper(HttpServletRequest request)
{
super(request);
}
@Override
public String[] getParameterValues(String name)
{
String[] values = super.getParameterValues(name);
if (values != null)
{
int length = values.length;
String[] escapseValues = new String[length];
for (int i = 0; i < length; i++)
{
// 防xss攻击和过滤前后空格
escapseValues[i] = EscapeUtil.clean(values[i]).trim();
}
return escapseValues;
}
return super.getParameterValues(name);
}
@Override
public ServletInputStream getInputStream() throws IOException
{
// 非json类型直接返回
if (!isJsonRequest())
{
return super.getInputStream();
}
// 为空,直接返回
String json = IOUtils.toString(super.getInputStream(), "utf-8");
if (StringUtils.isEmpty(json))
{
return super.getInputStream();
}
// xss过滤
json = EscapeUtil.clean(json).trim();
byte[] jsonBytes = json.getBytes("utf-8");
final ByteArrayInputStream bis = new ByteArrayInputStream(jsonBytes);
return new ServletInputStream()
{
@Override
public boolean isFinished()
{
return true;
}
@Override
public boolean isReady()
{
return true;
}
@Override
public int available() throws IOException
{
return jsonBytes.length;
}
@Override
public void setReadListener(ReadListener readListener)
{
}
@Override
public int read() throws IOException
{
return bis.read();
}
};
}
/**
* 是否是Json请求
*
* @param request
*/
public boolean isJsonRequest()
{
String header = super.getHeader(HttpHeaders.CONTENT_TYPE);
return StringUtils.startsWithIgnoreCase(header, MediaType.APPLICATION_JSON_VALUE);
}
}

View File

@@ -0,0 +1,28 @@
package com.ruoyi.common.page;
import com.ruoyi.common.core.page.PageDomain;
import com.ruoyi.common.core.page.TableSupport;
import java.util.List;
/**
* 手动分页
*/
public class ManualPagination {
public static <T> List<T> getPage(List<T> dataList) {
PageDomain pageDomain = TableSupport.buildPageRequest();
Integer pageNum = pageDomain.getPageNum();
Integer pageSize = pageDomain.getPageSize();
int startIndex = (pageNum - 1) * pageSize;
int endIndex = Math.min(startIndex + pageSize, dataList.size());
List<T> pageData = dataList.subList(startIndex, endIndex);
return pageData;
}
public static void main(String[] args) {
}
}

View File

@@ -0,0 +1,119 @@
/*
Copyright [2020] [https://www.stylefeng.cn]
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
http://www.apache.org/licenses/LICENSE-2.0
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.
Guns采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点:
1.请不要删除和修改根目录下的LICENSE文件。
2.请不要删除和修改Guns源码头部的版权声明。
3.请保留源码和相关描述文件的项目出处,作者声明等。
4.分发源码时候,请注明软件出处 https://gitee.com/stylefeng/guns-separation
5.在修改包名,模块名称,项目代码等时,请注明软件出处 https://gitee.com/stylefeng/guns-separation
6.若您的项目无法满足以上几点可申请商业授权获取Guns商业授权许可请在官网购买授权地址为 https://www.stylefeng.cn
*/
package com.ruoyi.common.page;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.PageUtil;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
/**
* 分页结果集
*
* @author xuyuxiang
* @date 2020/3/30 15:44
*/
@Data
public class PageResult<T> implements Serializable {
private static final long serialVersionUID = -1L;
/**
* 默认分页彩虹展示数量
*/
public static final int RAINBOW_NUM = 5;
/**
* 第几页
*/
private Integer pageNo = 1;
/**
* 每页条数
*/
private Integer pageSize = 20;
/**
* 总页数
*/
private Integer totalPage = 0;
/**
* 总记录数
*/
private Integer totalRows = 0;
/**
* 结果集
*/
private List<T> rows;
/**
* 分页彩虹
*/
private int[] rainbow;
public PageResult() {
}
/**
* 将mybatis-plus的page转成自定义的PageResult扩展了totalPage总页数和rainBow彩虹条
*
* @author xuyuxiang
* @date 2020/4/8 19:20
*/
public PageResult(IPage<T> page) {
this.setRows(page.getRecords());
this.setTotalRows(Convert.toInt(page.getTotal()));
this.setPageNo(Convert.toInt(page.getCurrent()));
this.setPageSize(Convert.toInt(page.getSize()));
this.setTotalPage(PageUtil.totalPage(Convert.toInt(page.getTotal()),
Convert.toInt(page.getSize())));
this.setRainbow(PageUtil.rainbow(Convert.toInt(page.getCurrent()),
Convert.toInt(this.getTotalPage()), RAINBOW_NUM));
}
/**
* 将mybatis-plus的page转成自定义的PageResult扩展了totalPage总页数和rainBow彩虹条
* 可单独设置rows
*
* @author xuyuxiang
* @date 2020/4/14 20:55
*/
public PageResult(Page<T> page, List<T> t) {
this.setRows(t);
this.setTotalRows(Convert.toInt(page.getTotal()));
this.setPageNo(Convert.toInt(page.getCurrent()));
this.setPageSize(Convert.toInt(page.getSize()));
this.setTotalPage(PageUtil.totalPage(Convert.toInt(page.getTotal()),
Convert.toInt(page.getSize())));
this.setRainbow(PageUtil.rainbow(Convert.toInt(page.getCurrent()),
Convert.toInt(this.getTotalPage()), RAINBOW_NUM));
}
}

View File

@@ -0,0 +1,30 @@
package com.ruoyi.common.page;
import com.github.pagehelper.PageInfo;
import com.ruoyi.common.constant.HttpStatus;
import com.ruoyi.common.core.page.TableDataInfo;
import java.util.List;
public class PageUtil {
/**
*
* @param list 返回数据
* @param totalList 计算总数据量的数据
* @return
*/
public static TableDataInfo getTableDataInfo(List list, List totalList){
TableDataInfo rspData = new TableDataInfo();
rspData.setCode(HttpStatus.SUCCESS);
rspData.setRows(list);
rspData.setMsg("查询成功");
if(totalList==null){
rspData.setTotal(Integer.valueOf(new PageInfo(list).getTotal() + ""));
}else {
rspData.setTotal(Integer.valueOf(new PageInfo(totalList).getTotal()+""));
}
return rspData;
}
}

View File

@@ -0,0 +1,234 @@
package com.ruoyi.common.utils;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Base64Utils;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
/**
* AES加密工具类
*
* @author ACGkaka
* @since 2021-06-18 19:11:03
*/
public class AESUtil {
/**
* 日志相关
*/
private static final Logger LOGGER = LoggerFactory.getLogger(AESUtil.class);
/**
* 编码
*/
private static final String ENCODING = "UTF-8";
/**
* 算法定义
*/
private static final String AES_ALGORITHM = "AES";
/**
* 指定填充方式
*/
private static final String CIPHER_PADDING = "AES/ECB/PKCS5Padding";
private static final String CIPHER_CBC_PADDING = "AES/CBC/PKCS5Padding";
/**
* 偏移量(CBC中使用增强加密算法强度)
*/
private static final String IV_SEED = "1234567812345678";
/**
* AES加密
* @param content 待加密内容
* @param aesKey 密码
* @return
*/
public static String encrypt(String content, String aesKey){
if(StringUtils.isBlank(content)){
LOGGER.info("AES encrypt: the content is null!");
return null;
}
//判断秘钥是否为16位
if(StringUtils.isNotBlank(aesKey) && aesKey.length() == 16){
try {
//对密码进行编码
byte[] bytes = aesKey.getBytes(ENCODING);
//设置加密算法,生成秘钥
SecretKeySpec skeySpec = new SecretKeySpec(bytes, AES_ALGORITHM);
// "算法/模式/补码方式"
Cipher cipher = Cipher.getInstance(CIPHER_PADDING);
//选择加密
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
//根据待加密内容生成字节数组
byte[] encrypted = cipher.doFinal(content.getBytes(ENCODING));
//返回base64字符串
return Base64Utils.encodeToString(encrypted);
} catch (Exception e) {
LOGGER.info("AES encrypt exception:" + e.getMessage());
throw new RuntimeException(e);
}
}else {
LOGGER.info("AES encrypt: the aesKey is null or error!");
return null;
}
}
/**
* 解密
*
* @param content 待解密内容
* @param aesKey 密码
* @return
*/
public static String decrypt(String content, String aesKey){
if(StringUtils.isBlank(content)){
LOGGER.info("AES decrypt: the content is null!");
return null;
}
//判断秘钥是否为16位
if(StringUtils.isNotBlank(aesKey) && aesKey.length() == 16){
try {
//对密码进行编码
byte[] bytes = aesKey.getBytes(ENCODING);
//设置解密算法,生成秘钥
SecretKeySpec skeySpec = new SecretKeySpec(bytes, AES_ALGORITHM);
// "算法/模式/补码方式"
Cipher cipher = Cipher.getInstance(CIPHER_PADDING);
//选择解密
cipher.init(Cipher.DECRYPT_MODE, skeySpec);
//先进行Base64解码
byte[] decodeBase64 = Base64Utils.decodeFromString(content);
//根据待解密内容进行解密
byte[] decrypted = cipher.doFinal(decodeBase64);
//将字节数组转成字符串
return new String(decrypted, ENCODING);
} catch (Exception e) {
LOGGER.info("AES decrypt exception:" + e.getMessage());
throw new RuntimeException(e);
}
}else {
LOGGER.info("AES decrypt: the aesKey is null or error!");
return null;
}
}
/**
* AES_CBC加密
*
* @param content 待加密内容
* @param aesKey 密码
* @return
*/
public static String encryptCBC(String content, String aesKey){
if(StringUtils.isBlank(content)){
LOGGER.info("AES_CBC encrypt: the content is null!");
return null;
}
//判断秘钥是否为16位
if(StringUtils.isNotBlank(aesKey) && aesKey.length() == 16){
try {
//对密码进行编码
byte[] bytes = aesKey.getBytes(ENCODING);
//设置加密算法,生成秘钥
SecretKeySpec skeySpec = new SecretKeySpec(bytes, AES_ALGORITHM);
// "算法/模式/补码方式"
Cipher cipher = Cipher.getInstance(CIPHER_CBC_PADDING);
//偏移
IvParameterSpec iv = new IvParameterSpec(IV_SEED.getBytes(ENCODING));
//选择加密
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
//根据待加密内容生成字节数组
byte[] encrypted = cipher.doFinal(content.getBytes(ENCODING));
//返回base64字符串
return Base64Utils.encodeToString(encrypted);
} catch (Exception e) {
LOGGER.info("AES_CBC encrypt exception:" + e.getMessage());
throw new RuntimeException(e);
}
}else {
LOGGER.info("AES_CBC encrypt: the aesKey is null or error!");
return null;
}
}
/**
* AES_CBC解密
*
* @param content 待解密内容
* @param aesKey 密码
* @return
*/
public static String decryptCBC(String content, String aesKey){
if(StringUtils.isBlank(content)){
LOGGER.info("AES_CBC decrypt: the content is null!");
return null;
}
//判断秘钥是否为16位
if(StringUtils.isNotBlank(aesKey) && aesKey.length() == 16){
try {
//对密码进行编码
byte[] bytes = aesKey.getBytes(ENCODING);
//设置解密算法,生成秘钥
SecretKeySpec skeySpec = new SecretKeySpec(bytes, AES_ALGORITHM);
//偏移
IvParameterSpec iv = new IvParameterSpec(IV_SEED.getBytes(ENCODING));
// "算法/模式/补码方式"
Cipher cipher = Cipher.getInstance(CIPHER_CBC_PADDING);
//选择解密
cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
//先进行Base64解码
byte[] decodeBase64 = Base64Utils.decodeFromString(content);
//根据待解密内容进行解密
byte[] decrypted = cipher.doFinal(decodeBase64);
//将字节数组转成字符串
return new String(decrypted, ENCODING);
} catch (Exception e) {
LOGGER.info("AES_CBC decrypt exception:" + e.getMessage());
throw new RuntimeException(e);
}
}else {
LOGGER.info("AES_CBC decrypt: the aesKey is null or error!");
return null;
}
}
public static void main(String[] args) {
// AES支持三种长度的密钥128位、192位、256位。
// 代码中这种就是128位的加密密钥16字节 * 8位/字节 = 128位。
String random = RandomStringUtils.random(16, "abcdefghijklmnopqrstuvwxyz1234567890");
System.out.println("随机key:" + random);
System.out.println();
System.out.println("---------加密---------");
String aesResult = encrypt("测试AES加密12", "huitu@77387.uurh");
System.out.println("aes加密结果:" + aesResult);
System.out.println();
System.out.println("---------解密---------");
String decrypt = decrypt(aesResult, "huitu@77387.uurh");
System.out.println("aes解密结果:" + decrypt);
System.out.println();
System.out.println("--------AES_CBC加密解密---------");
String cbcResult = encryptCBC("测试AES加密12456", random);
System.out.println("aes_cbc加密结果:" + cbcResult);
System.out.println();
System.out.println("---------解密CBC---------");
String cbcDecrypt = decryptCBC(cbcResult, random);
System.out.println("aes解密结果:" + cbcDecrypt);
System.out.println();
}
}

View File

@@ -0,0 +1,114 @@
package com.ruoyi.common.utils;
import java.math.BigDecimal;
import java.math.RoundingMode;
/**
* 精确的浮点数运算
*
* @author ruoyi
*/
public class Arith
{
/** 默认除法运算精度 */
private static final int DEF_DIV_SCALE = 10;
/** 这个类不能实例化 */
private Arith()
{
}
/**
* 提供精确的加法运算。
* @param v1 被加数
* @param v2 加数
* @return 两个参数的和
*/
public static double add(double v1, double v2)
{
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.add(b2).doubleValue();
}
/**
* 提供精确的减法运算。
* @param v1 被减数
* @param v2 减数
* @return 两个参数的差
*/
public static double sub(double v1, double v2)
{
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.subtract(b2).doubleValue();
}
/**
* 提供精确的乘法运算。
* @param v1 被乘数
* @param v2 乘数
* @return 两个参数的积
*/
public static double mul(double v1, double v2)
{
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.multiply(b2).doubleValue();
}
/**
* 提供(相对)精确的除法运算,当发生除不尽的情况时,精确到
* 小数点以后10位以后的数字四舍五入。
* @param v1 被除数
* @param v2 除数
* @return 两个参数的商
*/
public static double div(double v1, double v2)
{
return div(v1, v2, DEF_DIV_SCALE);
}
/**
* 提供相对精确的除法运算。当发生除不尽的情况时由scale参数指
* 定精度,以后的数字四舍五入。
* @param v1 被除数
* @param v2 除数
* @param scale 表示表示需要精确到小数点以后几位。
* @return 两个参数的商
*/
public static double div(double v1, double v2, int scale)
{
if (scale < 0)
{
throw new IllegalArgumentException(
"The scale must be a positive integer or zero");
}
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
if (b1.compareTo(BigDecimal.ZERO) == 0)
{
return BigDecimal.ZERO.doubleValue();
}
return b1.divide(b2, scale, RoundingMode.HALF_UP).doubleValue();
}
/**
* 提供精确的小数位四舍五入处理。
* @param v 需要四舍五入的数字
* @param scale 小数点后保留几位
* @return 四舍五入后的结果
*/
public static double round(double v, int scale)
{
if (scale < 0)
{
throw new IllegalArgumentException(
"The scale must be a positive integer or zero");
}
BigDecimal b = new BigDecimal(Double.toString(v));
BigDecimal one = BigDecimal.ONE;
return b.divide(one, scale, RoundingMode.HALF_UP).doubleValue();
}
}

View File

@@ -0,0 +1,155 @@
package com.ruoyi.common.utils;
import java.lang.management.ManagementFactory;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.apache.commons.lang3.time.DateFormatUtils;
/**
* 时间工具类
*
* @author ruoyi
*/
public class DateUtils extends org.apache.commons.lang3.time.DateUtils
{
public static String YYYY = "yyyy";
public static String YYYY_MM = "yyyy-MM";
public static String YYYY_MM_DD = "yyyy-MM-dd";
public static String YYYYMMDDHHMMSS = "yyyyMMddHHmmss";
public static String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
private static String[] parsePatterns = {
"yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM",
"yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM",
"yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"};
/**
* 获取当前Date型日期
*
* @return Date() 当前日期
*/
public static Date getNowDate()
{
return new Date();
}
/**
* 获取当前日期, 默认格式为yyyy-MM-dd
*
* @return String
*/
public static String getDate()
{
return dateTimeNow(YYYY_MM_DD);
}
public static final String getTime()
{
return dateTimeNow(YYYY_MM_DD_HH_MM_SS);
}
public static final String dateTimeNow()
{
return dateTimeNow(YYYYMMDDHHMMSS);
}
public static final String dateTimeNow(final String format)
{
return parseDateToStr(format, new Date());
}
public static final String dateTime(final Date date)
{
return parseDateToStr(YYYY_MM_DD, date);
}
public static final String parseDateToStr(final String format, final Date date)
{
return new SimpleDateFormat(format).format(date);
}
public static final Date dateTime(final String format, final String ts)
{
try
{
return new SimpleDateFormat(format).parse(ts);
}
catch (ParseException e)
{
throw new RuntimeException(e);
}
}
/**
* 日期路径 即年/月/日 如2018/08/08
*/
public static final String datePath()
{
Date now = new Date();
return DateFormatUtils.format(now, "yyyy/MM/dd");
}
/**
* 日期路径 即年/月/日 如20180808
*/
public static final String dateTime()
{
Date now = new Date();
return DateFormatUtils.format(now, "yyyyMMdd");
}
/**
* 日期型字符串转化为日期 格式
*/
public static Date parseDate(Object str)
{
if (str == null)
{
return null;
}
try
{
return parseDate(str.toString(), parsePatterns);
}
catch (ParseException e)
{
return null;
}
}
/**
* 获取服务器启动时间
*/
public static Date getServerStartDate()
{
long time = ManagementFactory.getRuntimeMXBean().getStartTime();
return new Date(time);
}
/**
* 计算两个时间差
*/
public static String getDatePoor(Date endDate, Date nowDate)
{
long nd = 1000 * 24 * 60 * 60;
long nh = 1000 * 60 * 60;
long nm = 1000 * 60;
// long ns = 1000;
// 获得两个时间的毫秒时间差异
long diff = endDate.getTime() - nowDate.getTime();
// 计算差多少天
long day = diff / nd;
// 计算差多少小时
long hour = diff % nd / nh;
// 计算差多少分钟
long min = diff % nd % nh / nm;
// 计算差多少秒//输出结果
// long sec = diff % nd % nh % nm / ns;
return day + "" + hour + "小时" + min + "分钟";
}
}

View File

@@ -0,0 +1,183 @@
package com.ruoyi.common.utils;
import java.util.Collection;
import java.util.List;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.entity.SysDictData;
import com.ruoyi.common.core.redis.RedisService;
import com.ruoyi.common.utils.spring.SpringUtils;
/**
* 字典工具类
*
* @author ruoyi
*/
public class DictUtils
{
/**
* 分隔符
*/
public static final String SEPARATOR = ",";
/**
* 设置字典缓存
*
* @param key 参数键
* @param dictDatas 字典数据列表
*/
public static void setDictCache(String key, List<SysDictData> dictDatas)
{
SpringUtils.getBean(RedisService.class).setCacheObject(getCacheKey(key), dictDatas);
}
/**
* 获取字典缓存
*
* @param key 参数键
* @return dictDatas 字典数据列表
*/
public static List<SysDictData> getDictCache(String key)
{
Object cacheObj = SpringUtils.getBean(RedisService.class).getCacheObject(getCacheKey(key));
if (StringUtils.isNotNull(cacheObj))
{
List<SysDictData> dictDatas = StringUtils.cast(cacheObj);
return dictDatas;
}
return null;
}
/**
* 根据字典类型和字典值获取字典标签
*
* @param dictType 字典类型
* @param dictValue 字典值
* @return 字典标签
*/
public static String getDictLabel(String dictType, String dictValue)
{
return getDictLabel(dictType, dictValue, SEPARATOR);
}
/**
* 根据字典类型和字典标签获取字典值
*
* @param dictType 字典类型
* @param dictLabel 字典标签
* @return 字典值
*/
public static String getDictValue(String dictType, String dictLabel)
{
return getDictValue(dictType, dictLabel, SEPARATOR);
}
/**
* 根据字典类型和字典值获取字典标签
*
* @param dictType 字典类型
* @param dictValue 字典值
* @param separator 分隔符
* @return 字典标签
*/
public static String getDictLabel(String dictType, String dictValue, String separator)
{
StringBuilder propertyString = new StringBuilder();
List<SysDictData> datas = getDictCache(dictType);
if (StringUtils.containsAny(separator, dictValue) && StringUtils.isNotEmpty(datas))
{
for (SysDictData dict : datas)
{
for (String value : dictValue.split(separator))
{
if (value.equals(dict.getDictValue()))
{
propertyString.append(dict.getDictLabel() + separator);
break;
}
}
}
}
else
{
for (SysDictData dict : datas)
{
if (dictValue.equals(dict.getDictValue()))
{
return dict.getDictLabel();
}
}
}
return StringUtils.stripEnd(propertyString.toString(), separator);
}
/**
* 根据字典类型和字典标签获取字典值
*
* @param dictType 字典类型
* @param dictLabel 字典标签
* @param separator 分隔符
* @return 字典值
*/
public static String getDictValue(String dictType, String dictLabel, String separator)
{
StringBuilder propertyString = new StringBuilder();
List<SysDictData> datas = getDictCache(dictType);
if (StringUtils.containsAny(separator, dictLabel) && StringUtils.isNotEmpty(datas))
{
for (SysDictData dict : datas)
{
for (String label : dictLabel.split(separator))
{
if (label.equals(dict.getDictLabel()))
{
propertyString.append(dict.getDictValue() + separator);
break;
}
}
}
}
else
{
for (SysDictData dict : datas)
{
if (dictLabel.equals(dict.getDictLabel()))
{
return dict.getDictValue();
}
}
}
return StringUtils.stripEnd(propertyString.toString(), separator);
}
/**
* 删除指定字典缓存
*
* @param key 字典键
*/
public static void removeDictCache(String key)
{
SpringUtils.getBean(RedisService.class).deleteObject(getCacheKey(key));
}
/**
* 清空字典缓存
*/
public static void clearDictCache()
{
Collection<String> keys = SpringUtils.getBean(RedisService.class).keys(Constants.SYS_DICT_KEY + "*");
SpringUtils.getBean(RedisService.class).deleteObject(keys);
}
/**
* 设置cache key
*
* @param configKey 参数键
* @return 缓存键key
*/
public static String getCacheKey(String configKey)
{
return Constants.SYS_DICT_KEY + configKey;
}
}

View File

@@ -0,0 +1,40 @@
package com.ruoyi.common.utils;
import java.io.PrintWriter;
import java.io.StringWriter;
import org.apache.commons.lang3.exception.ExceptionUtils;
/**
* 错误信息处理类。
*
* @author ruoyi
*/
public class ExceptionUtil
{
/**
* 获取exception的详细错误信息。
*/
public static String getExceptionMessage(Throwable e)
{
StringWriter sw = new StringWriter();
e.printStackTrace(new PrintWriter(sw, true));
String str = sw.toString();
return str;
}
public static String getRootErrorMessage(Exception e)
{
Throwable root = ExceptionUtils.getRootCause(e);
root = (root == null ? e : root);
if (root == null)
{
return "";
}
String msg = root.getMessage();
if (msg == null)
{
return "null";
}
return StringUtils.defaultString(msg);
}
}

View File

@@ -0,0 +1,61 @@
package com.ruoyi.common.utils;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
public class ImageMerge {
public static void main(String[] args) throws Exception {
// 加载第一张图片
BufferedImage image1 = ImageIO.read(new File("G:\\download\\output.png"));
// 加载第二张图片
BufferedImage image2 = ImageIO.read(new File("G:\\download\\output2.png"));
List<String> list = new ArrayList<>();
list.add("G:\\download\\output.png");
list.add("G:\\download\\output2.png");
list.add("G:\\download\\output3.png");
mergeImages(list,null);
}
public static void mergeImages(List<String> imagePathList,String outputPath) throws Exception {
// 加载第一张图片
BufferedImage image1 = ImageIO.read(new File(imagePathList.get(0)));
Integer height = image1.getHeight();
Integer width = image1.getWidth();
for (int i = 0; i < imagePathList.size(); i++) {
if (i == 0) {
continue;
}
BufferedImage image = ImageIO.read(new File(imagePathList.get(i)));
height = height + image.getHeight();
}
// 创建一个新的图片用于合并
BufferedImage combinedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
// 合并第一张图片
Integer heightTemp = 0;
Graphics2D g = null;
for (int i = 0; i < imagePathList.size(); i++) {
BufferedImage image = ImageIO.read(new File(imagePathList.get(i)));
g = combinedImage.createGraphics();
if (i == 0) {
g.drawImage(image, 0, heightTemp, null);
} else {
g.drawImage(image, 0, heightTemp, null);
}
heightTemp = heightTemp + image.getHeight();
// 释放图形上下文
g.dispose();
}
// 保存合并后的图片
ImageIO.write(combinedImage, "PNG", new File(outputPath));
}
}

View File

@@ -0,0 +1,74 @@
package com.ruoyi.common.utils;
import com.ruoyi.common.utils.uuid.UUID;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
public class ImageRotator {
public static String rotate90DegreesCounterClockwise(String image, String path) {
// 读取原始图片
BufferedImage originalImage = null;
try {
originalImage = ImageIO.read(new File(image));
} catch (IOException e) {
throw new RuntimeException(e);
}
// 创建一个旋转后的图片,宽度和高度交换
BufferedImage rotatedImage = new BufferedImage(originalImage.getHeight(), originalImage.getWidth(), BufferedImage.TYPE_INT_ARGB);
// 创建Graphics2D对象用于绘制旋转后的图片
Graphics2D g2d = rotatedImage.createGraphics();
// 逆时针旋转90度
AffineTransform at = new AffineTransform();
at.translate(originalImage.getHeight(), 0);
at.rotate(Math.toRadians(90));
g2d.setTransform(at);
g2d.drawImage(originalImage, 0, 0, null);
g2d.dispose();
String outPath = path + UUID.randomUUID() + ".png";
// 保存旋转后的图片
try {
ImageIO.write(rotatedImage, "PNG", new File(outPath));
} catch (IOException e) {
throw new RuntimeException(e);
}
return outPath;
}
public static void main(String[] args) throws IOException {
String path = "G:\\download\\";
// 读取原始图片
BufferedImage originalImage = ImageIO.read(new File(path + "input.jpg"));
// 创建一个旋转后的图片,宽度和高度交换
BufferedImage rotatedImage = new BufferedImage(originalImage.getHeight(), originalImage.getWidth(), BufferedImage.TYPE_INT_ARGB);
// 创建Graphics2D对象用于绘制旋转后的图片
Graphics2D g2d = rotatedImage.createGraphics();
// 逆时针旋转90度
AffineTransform at = new AffineTransform();
at.translate(originalImage.getHeight(), 0);
at.rotate(Math.toRadians(90));
g2d.setTransform(at);
g2d.drawImage(originalImage, 0, 0, null);
g2d.dispose();
// 保存旋转后的图片
ImageIO.write(rotatedImage, "PNG", new File(path + "out.jpg"));
System.out.println("图片旋转完成。");
}
}

View File

@@ -0,0 +1,18 @@
package com.ruoyi.common.utils;
/**
* 处理并记录日志文件
*
* @author ruoyi
*/
public class LogUtils
{
public static String getBlock(Object msg)
{
if (msg == null)
{
msg = "";
}
return "[" + msg.toString() + "]";
}
}

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