发布 v3.0.0

This commit is contained in:
疯狂的狮子li
2021-08-18 11:45:51 +08:00
parent 3294390407
commit c206f938ba
225 changed files with 6115 additions and 4259 deletions

View File

@ -1,165 +0,0 @@
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;
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靠右
*/
Align align() default Align.AUTO;
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,30 @@
package com.ruoyi.common.annotation;
import java.lang.annotation.*;
/**
* 字典格式化
*
* @author Lion Li
*/
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface ExcelDictFormat {
/**
* 如果是字典类型请设置字典的type值 (如: sys_user_sex)
*/
String dictType() default "";
/**
* 读取内容转表达式 (如: 0=男,1=女,2=未知)
*/
String readConverterExp() default "";
/**
* 分隔符,读取字符串组内容
*/
String separator() default ",";
}

View File

@ -1,18 +0,0 @@
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
{
Excel[] value();
}

View File

@ -0,0 +1,40 @@
package com.ruoyi.common.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.enums.LimitType;
/**
* 限流注解
*
* @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

@ -6,18 +6,24 @@ import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.concurrent.TimeUnit;
/**
* 自定义注解防止表单重复提交
*
* @author ruoyi
*
* @author Lion Li
*/
@Inherited
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RepeatSubmit
{
public @interface RepeatSubmit {
/**
* 默认使用全局配置
*/
int intervalTime() default 0;
TimeUnit timeUnit() default TimeUnit.MILLISECONDS;
}

View File

@ -9,7 +9,7 @@ import org.springframework.stereotype.Component;
/**
* 读取项目相关配置
*
*
* @author ruoyi
*/
@ -32,45 +32,13 @@ public class RuoYiConfig
/** 实例演示开关 */
private boolean demoEnabled;
/** 上传路径 */
@Getter
private static String profile;
/** 获取地址开关 */
@Getter
private static boolean addressEnabled;
public void setProfile(String profile)
{
RuoYiConfig.profile = profile;
}
public void setAddressEnabled(boolean addressEnabled)
{
RuoYiConfig.addressEnabled = addressEnabled;
}
/**
* 获取头像上传路径
*/
public static String getAvatarPath()
{
return getProfile() + "/avatar";
}
/**
* 获取下载路径
*/
public static String getDownloadPath()
{
return getProfile() + "/download/";
}
/**
* 获取上传路径
*/
public static String getUploadPath()
{
return getProfile() + "/upload";
}
}

View File

@ -1,5 +1,7 @@
package com.ruoyi.common.constant;
import io.jsonwebtoken.Claims;
/**
* 通用常量信息
*
@ -47,6 +49,11 @@ public class Constants
*/
public static final String LOGOUT = "Logout";
/**
* 注册
*/
public static final String REGISTER = "Register";
/**
* 登录失败
*/
@ -67,6 +74,11 @@ public class Constants
*/
public static final String REPEAT_SUBMIT_KEY = "repeat_submit:";
/**
* 限流 redis key
*/
public static final String RATE_LIMIT_KEY = "rate_limit:";
/**
* 验证码有效期(分钟)
*/
@ -95,7 +107,7 @@ public class Constants
/**
* 用户名称
*/
public static final String JWT_USERNAME = "sub";
public static final String JWT_USERNAME = Claims.SUBJECT;
/**
* 用户头像
@ -122,18 +134,9 @@ public class Constants
*/
public static final String SYS_DICT_KEY = "sys_dict:";
/**
* 资源映射路径 前缀
*/
public static final String RESOURCE_PREFIX = "/profile";
/**
* RMI 远程方法调用
*/
public static final String LOOKUP_RMI = "rmi://";
/**
* 资源映射路径 前缀
*/
public static final String REDIS_LOCK_KEY = "redis_lock:";
}

View File

@ -63,4 +63,16 @@ public class UserConstants
/** 校验返回结果码 */
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,69 @@
package com.ruoyi.common.convert;
import cn.hutool.core.annotation.AnnotationUtil;
import cn.hutool.core.convert.Convert;
import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.GlobalConfiguration;
import com.alibaba.excel.metadata.property.ExcelContentProperty;
import com.ruoyi.common.annotation.ExcelDictFormat;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import lombok.extern.slf4j.Slf4j;
import java.lang.reflect.Field;
/**
* 字典格式化转换处理
*
* @author Lion Li
*/
@Slf4j
public class ExcelDictConvert implements Converter<Object> {
@Override
public Class<Object> supportJavaTypeKey() {
return Object.class;
}
@Override
public CellDataTypeEnum supportExcelTypeKey() {
return null;
}
@Override
public Object convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) {
ExcelDictFormat anno = getAnnotation(contentProperty.getField());
String type = anno.dictType();
String label = cellData.getStringValue();
String value;
if (StringUtils.isBlank(type)) {
value = ExcelUtil.reverseByExp(label, anno.readConverterExp(), anno.separator());
} else {
value = ExcelUtil.reverseDictByExp(label, type, anno.separator());
}
return Convert.convert(contentProperty.getField().getType(), value);
}
@Override
public CellData<String> convertToExcelData(Object object, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) {
if (StringUtils.isNull(object)) {
return new CellData<>("");
}
ExcelDictFormat anno = getAnnotation(contentProperty.getField());
String type = anno.dictType();
String value = Convert.toStr(object);
String label;
if (StringUtils.isBlank(type)) {
label = ExcelUtil.convertByExp(value, anno.readConverterExp(), anno.separator());
} else {
label = ExcelUtil.convertDictByExp(value, type, anno.separator());
}
return new CellData<>(label);
}
private ExcelDictFormat getAnnotation(Field field) {
return AnnotationUtil.getAnnotation(field, ExcelDictFormat.class);
}
}

View File

@ -1,7 +1,9 @@
package com.ruoyi.common.core.controller;
import cn.hutool.core.util.StrUtil;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -73,6 +75,38 @@ public class BaseController
*/
public String redirect(String url)
{
return StrUtil.format("redirect:{}", url);
return StringUtils.format("redirect:{}", url);
}
/**
* 获取用户缓存信息
*/
public LoginUser getLoginUser()
{
return SecurityUtils.getLoginUser();
}
/**
* 获取登录用户id
*/
public Long getUserId()
{
return getLoginUser().getUserId();
}
/**
* 获取登录部门id
*/
public Long getDeptId()
{
return getLoginUser().getDeptId();
}
/**
* 获取登录用户名
*/
public String getUsername()
{
return getLoginUser().getUsername();
}
}

View File

@ -1,5 +1,6 @@
package com.ruoyi.common.core.domain;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
@ -18,29 +19,50 @@ import java.util.Map;
@Data
@NoArgsConstructor
@Accessors(chain = true)
public class BaseEntity implements Serializable
{
private static final long serialVersionUID = 1L;
public class BaseEntity implements Serializable {
/** 搜索值 */
private String searchValue;
private static final long serialVersionUID = 1L;
/** 创建者 */
private String createBy;
/**
* 搜索值
*/
@ApiModelProperty(value = "搜索值")
private String searchValue;
/** 创建时间 */
private Date createTime;
/**
* 创建者
*/
@ApiModelProperty(value = "创建者")
private String createBy;
/** 更新者 */
private String updateBy;
/**
* 创建时间
*/
@ApiModelProperty(value = "创建时间")
private Date createTime;
/** 更新时间 */
private Date updateTime;
/**
* 更新者
*/
@ApiModelProperty(value = "更新者")
private String updateBy;
/** 备注 */
private String remark;
/**
* 更新时间
*/
@ApiModelProperty(value = "更新时间")
private Date updateTime;
/** 请求参数 */
private Map<String, Object> params = new HashMap<>();
/**
* 备注
*/
@ApiModelProperty(value = "备注")
private String remark;
/**
* 请求参数
*/
@ApiModelProperty(value = "请求参数")
private Map<String, Object> params = new HashMap<>();
}

View File

@ -1,6 +1,9 @@
package com.ruoyi.common.core.domain;
import lombok.*;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import java.util.ArrayList;
@ -8,7 +11,7 @@ import java.util.List;
/**
* Tree基类
*
*
* @author ruoyi
*/
@ -16,23 +19,38 @@ import java.util.List;
@Data
@NoArgsConstructor
@Accessors(chain = true)
public class TreeEntity extends BaseEntity
{
private static final long serialVersionUID = 1L;
public class TreeEntity extends BaseEntity {
/** 父菜单名称 */
private String parentName;
private static final long serialVersionUID = 1L;
/** 父菜单ID */
private Long parentId;
/**
* 父菜单名称
*/
@ApiModelProperty(value = "父菜单名称")
private String parentName;
/** 显示顺序 */
private Integer orderNum;
/**
* 父菜单ID
*/
@ApiModelProperty(value = "父菜单ID")
private Long parentId;
/** 祖级列表 */
private String ancestors;
/**
* 显示顺序
*/
@ApiModelProperty(value = "显示顺序")
private Integer orderNum;
/** 子部门 */
private List<?> children = new ArrayList<>();
/**
* 祖级列表
*/
@ApiModelProperty(value = "祖级列表")
private String ancestors;
/**
* 子部门
*/
@ApiModelProperty(value = "子部门")
private List<?> children = new ArrayList<>();
}

View File

@ -1,7 +1,6 @@
package com.ruoyi.common.core.domain.entity;
import com.baomidou.mybatisplus.annotation.*;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
@ -14,7 +13,7 @@ import java.util.*;
/**
* 部门表 sys_dept
*
*
* @author ruoyi
*/
@ -22,78 +21,107 @@ import java.util.*;
@NoArgsConstructor
@Accessors(chain = true)
@TableName("sys_dept")
public class SysDept implements Serializable
{
private static final long serialVersionUID = 1L;
public class SysDept implements Serializable {
private static final long serialVersionUID = 1L;
/** 部门ID */
@TableId(value = "dept_id",type = IdType.AUTO)
private Long deptId;
/**
* 部门ID
*/
@TableId(value = "dept_id", type = IdType.AUTO)
private Long deptId;
/** 父部门ID */
private Long parentId;
/**
* 父部门ID
*/
private Long parentId;
/** 祖级列表 */
private String ancestors;
/**
* 祖级列表
*/
private String ancestors;
/** 部门名称 */
@NotBlank(message = "部门名称不能为空")
@Size(min = 0, max = 30, message = "部门名称长度不能超过30个字符")
private String deptName;
/**
* 部门名称
*/
@NotBlank(message = "部门名称不能为空")
@Size(min = 0, max = 30, message = "部门名称长度不能超过30个字符")
private String deptName;
/** 显示顺序 */
@NotBlank(message = "显示顺序不能为空")
private String orderNum;
/**
* 显示顺序
*/
@NotBlank(message = "显示顺序不能为空")
private String orderNum;
/** 负责人 */
private String leader;
/**
* 负责人
*/
private String leader;
/** 联系电话 */
@Size(min = 0, max = 11, message = "联系电话长度不能超过11个字符")
private String phone;
/**
* 联系电话
*/
@Size(min = 0, max = 11, message = "联系电话长度不能超过11个字符")
private String phone;
/** 邮箱 */
@Email(message = "邮箱格式不正确")
@Size(min = 0, max = 50, message = "邮箱长度不能超过50个字符")
private String email;
/**
* 邮箱
*/
@Email(message = "邮箱格式不正确")
@Size(min = 0, max = 50, message = "邮箱长度不能超过50个字符")
private String email;
/** 部门状态:0正常,1停用 */
private String status;
/**
* 部门状态:0正常,1停用
*/
private String status;
/** 删除标志0代表存在 2代表删除 */
@TableLogic
private String delFlag;
/**
* 删除标志0代表存在 2代表删除
*/
@TableLogic
private String delFlag;
/** 父部门名称 */
@TableField(exist = false)
private String parentName;
/**
* 父部门名称
*/
@TableField(exist = false)
private String parentName;
/** 创建者 */
@TableField(fill = FieldFill.INSERT)
private String createBy;
/**
* 创建者
*/
@TableField(fill = FieldFill.INSERT)
private String createBy;
/** 创建时间 */
@TableField(fill = FieldFill.INSERT)
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
/**
* 创建时间
*/
@TableField(fill = FieldFill.INSERT)
private Date createTime;
/** 更新者 */
@TableField(fill = FieldFill.INSERT_UPDATE)
private String updateBy;
/**
* 更新者
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
private String updateBy;
/** 更新时间 */
@TableField(fill = FieldFill.INSERT_UPDATE)
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date updateTime;
/** 子部门 */
@TableField(exist = false)
private List<SysDept> children = new ArrayList<SysDept>();
/**
* 更新时间
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date updateTime;
/**
* 请求参数
*/
@TableField(exist = false)
private Map<String, Object> params = new HashMap<>();
/**
* 子部门
*/
@TableField(exist = false)
private List<SysDept> children = new ArrayList<SysDept>();
/**
* 请求参数
*/
@TableField(exist = false)
private Map<String, Object> params = new HashMap<>();
}

View File

@ -1,10 +1,11 @@
package com.ruoyi.common.core.domain.entity;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import com.baomidou.mybatisplus.annotation.*;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.annotation.Excel.ColumnType;
import com.ruoyi.common.annotation.ExcelDictFormat;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.convert.ExcelDictConvert;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
@ -18,7 +19,7 @@ import java.util.Map;
/**
* 字典数据表 sys_dict_data
*
*
* @author ruoyi
*/
@ -26,82 +27,109 @@ import java.util.Map;
@NoArgsConstructor
@Accessors(chain = true)
@TableName("sys_dict_data")
public class SysDictData implements Serializable
{
private static final long serialVersionUID = 1L;
@ExcelIgnoreUnannotated
public class SysDictData implements Serializable {
private static final long serialVersionUID = 1L;
/** 字典编码 */
@Excel(name = "字典编码", cellType = ColumnType.NUMERIC)
@TableId(value = "dict_code",type = IdType.AUTO)
private Long dictCode;
/**
* 字典编码
*/
@ExcelProperty(value = "字典编码")
@TableId(value = "dict_code", type = IdType.AUTO)
private Long dictCode;
/** 字典排序 */
@Excel(name = "字典排序", cellType = ColumnType.NUMERIC)
private Long dictSort;
/**
* 字典排序
*/
@ExcelProperty(value = "字典排序")
private Long dictSort;
/** 字典标签 */
@Excel(name = "字典标签")
@NotBlank(message = "字典标签不能为空")
@Size(min = 0, max = 100, message = "字典标签长度不能超过100个字符")
private String dictLabel;
/**
* 字典标签
*/
@ExcelProperty(value = "字典标签")
@NotBlank(message = "字典标签不能为空")
@Size(min = 0, max = 100, message = "字典标签长度不能超过100个字符")
private String dictLabel;
/** 字典键值 */
@Excel(name = "字典键值")
@NotBlank(message = "字典键值不能为空")
@Size(min = 0, max = 100, message = "字典键值长度不能超过100个字符")
private String dictValue;
/**
* 字典键值
*/
@ExcelProperty(value = "字典键值")
@NotBlank(message = "字典键值不能为空")
@Size(min = 0, max = 100, message = "字典键值长度不能超过100个字符")
private String dictValue;
/** 字典类型 */
@Excel(name = "字典类型")
@NotBlank(message = "字典类型不能为空")
@Size(min = 0, max = 100, message = "字典类型长度不能超过100个字符")
private String dictType;
/**
* 字典类型
*/
@ExcelProperty(value = "字典类型")
@NotBlank(message = "字典类型不能为空")
@Size(min = 0, max = 100, message = "字典类型长度不能超过100个字符")
private String dictType;
/** 样式属性(其他样式扩展) */
@Size(min = 0, max = 100, message = "样式属性长度不能超过100个字符")
private String cssClass;
/**
* 样式属性(其他样式扩展)
*/
@Size(min = 0, max = 100, message = "样式属性长度不能超过100个字符")
private String cssClass;
/** 表格字典样式 */
private String listClass;
/**
* 表格字典样式
*/
private String listClass;
/** 是否默认Y是 N否 */
@Excel(name = "是否默认", readConverterExp = "Y=是,N=否")
private String isDefault;
/**
* 是否默认Y是 N否
*/
@ExcelProperty(value = "是否默认", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = "sys_yes_no")
private String isDefault;
/** 状态0正常 1停用 */
@Excel(name = "状态", readConverterExp = "0=正常,1=停用")
private String status;
/**
* 状态0正常 1停用
*/
@ExcelProperty(value = "状态", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = "sys_common_status")
private String status;
/** 创建者 */
@TableField(fill = FieldFill.INSERT)
private String createBy;
/**
* 创建者
*/
@TableField(fill = FieldFill.INSERT)
private String createBy;
/** 创建时间 */
@TableField(fill = FieldFill.INSERT)
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
/**
* 创建时间
*/
@TableField(fill = FieldFill.INSERT)
private Date createTime;
/** 更新者 */
@TableField(fill = FieldFill.INSERT_UPDATE)
private String updateBy;
/**
* 更新者
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
private String updateBy;
/** 更新时间 */
@TableField(fill = FieldFill.INSERT_UPDATE)
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date updateTime;
/**
* 更新时间
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date updateTime;
/** 备注 */
private String remark;
/**
* 备注
*/
private String remark;
/**
* 请求参数
*/
@TableField(exist = false)
private Map<String, Object> params = new HashMap<>();
/**
* 请求参数
*/
@TableField(exist = false)
private Map<String, Object> params = new HashMap<>();
public boolean getDefault()
{
return UserConstants.YES.equals(this.isDefault) ? true : false;
}
public boolean getDefault() {
return UserConstants.YES.equals(this.isDefault) ? true : false;
}
}

View File

@ -1,9 +1,10 @@
package com.ruoyi.common.core.domain.entity;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import com.baomidou.mybatisplus.annotation.*;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.annotation.Excel.ColumnType;
import com.ruoyi.common.annotation.ExcelDictFormat;
import com.ruoyi.common.convert.ExcelDictConvert;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
@ -17,7 +18,7 @@ import java.util.Map;
/**
* 字典类型表 sys_dict_type
*
*
* @author ruoyi
*/
@ -25,56 +26,73 @@ import java.util.Map;
@NoArgsConstructor
@Accessors(chain = true)
@TableName("sys_dict_type")
public class SysDictType implements Serializable
{
private static final long serialVersionUID = 1L;
@ExcelIgnoreUnannotated
public class SysDictType implements Serializable {
private static final long serialVersionUID = 1L;
/** 字典主键 */
@Excel(name = "字典主键", cellType = ColumnType.NUMERIC)
@TableId(value = "dict_id",type = IdType.AUTO)
private Long dictId;
/**
* 字典主键
*/
@ExcelProperty(value = "字典主键")
@TableId(value = "dict_id", type = IdType.AUTO)
private Long dictId;
/** 字典名称 */
@Excel(name = "字典名称")
@NotBlank(message = "字典名称不能为空")
@Size(min = 0, max = 100, message = "字典类型名称长度不能超过100个字符")
private String dictName;
/**
* 字典名称
*/
@ExcelProperty(value = "字典名称")
@NotBlank(message = "字典名称不能为空")
@Size(min = 0, max = 100, message = "字典类型名称长度不能超过100个字符")
private String dictName;
/** 字典类型 */
@Excel(name = "字典类型")
@NotBlank(message = "字典类型不能为空")
@Size(min = 0, max = 100, message = "字典类型类型长度不能超过100个字符")
private String dictType;
/**
* 字典类型
*/
@ExcelProperty(value = "字典类型")
@NotBlank(message = "字典类型不能为空")
@Size(min = 0, max = 100, message = "字典类型类型长度不能超过100个字符")
private String dictType;
/** 状态0正常 1停用 */
@Excel(name = "状态", readConverterExp = "0=正常,1=停用")
private String status;
/**
* 状态0正常 1停用
*/
@ExcelProperty(value = "状态", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = "sys_common_status")
private String status;
/** 创建者 */
@TableField(fill = FieldFill.INSERT)
private String createBy;
/**
* 创建者
*/
@TableField(fill = FieldFill.INSERT)
private String createBy;
/** 创建时间 */
@TableField(fill = FieldFill.INSERT)
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
/**
* 创建时间
*/
@TableField(fill = FieldFill.INSERT)
private Date createTime;
/** 更新者 */
@TableField(fill = FieldFill.INSERT_UPDATE)
private String updateBy;
/**
* 更新者
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
private String updateBy;
/** 更新时间 */
@TableField(fill = FieldFill.INSERT_UPDATE)
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date updateTime;
/**
* 更新时间
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date updateTime;
/** 备注 */
private String remark;
/**
* 备注
*/
private String remark;
/**
* 请求参数
*/
@TableField(exist = false)
private Map<String, Object> params = new HashMap<>();
/**
* 请求参数
*/
@TableField(exist = false)
private Map<String, Object> params = new HashMap<>();
}

View File

@ -13,7 +13,7 @@ import java.util.*;
/**
* 菜单权限表 sys_menu
*
*
* @author ruoyi
*/
@ -21,88 +21,129 @@ import java.util.*;
@NoArgsConstructor
@Accessors(chain = true)
@TableName("sys_menu")
public class SysMenu implements Serializable
{
private static final long serialVersionUID = 1L;
public class SysMenu implements Serializable {
private static final long serialVersionUID = 1L;
/** 菜单ID */
@TableId(value = "menu_id",type = IdType.AUTO)
private Long menuId;
/**
* 菜单ID
*/
@TableId(value = "menu_id", type = IdType.AUTO)
private Long menuId;
/** 菜单名称 */
@NotBlank(message = "菜单名称不能为空")
@Size(min = 0, max = 50, message = "菜单名称长度不能超过50个字符")
private String menuName;
/**
* 菜单名称
*/
@NotBlank(message = "菜单名称不能为空")
@Size(min = 0, max = 50, message = "菜单名称长度不能超过50个字符")
private String menuName;
/** 父菜单名称 */
@TableField(exist = false)
private String parentName;
/**
* 父菜单名称
*/
@TableField(exist = false)
private String parentName;
/** 父菜单ID */
private Long parentId;
/**
* 父菜单ID
*/
private Long parentId;
/** 显示顺序 */
@NotBlank(message = "显示顺序不能为空")
private String orderNum;
/**
* 显示顺序
*/
@NotBlank(message = "显示顺序不能为空")
private String orderNum;
/** 路由地址 */
@Size(min = 0, max = 200, message = "路由地址不能超过200个字符")
private String path;
/**
* 路由地址
*/
@Size(min = 0, max = 200, message = "路由地址不能超过200个字符")
private String path;
/** 组件路径 */
@Size(min = 0, max = 200, message = "组件路径不能超过255个字符")
private String component;
/**
* 组件路径
*/
@Size(min = 0, max = 200, message = "组件路径不能超过255个字符")
private String component;
/** 是否为外链0是 1否 */
private String isFrame;
/**
* 是否为外链0是 1否
*/
private String isFrame;
/** 是否缓存0缓存 1不缓存 */
private String isCache;
/**
* 是否缓存0缓存 1不缓存
*/
private String isCache;
/** 类型M目录 C菜单 F按钮 */
@NotBlank(message = "菜单类型不能为空")
private String menuType;
/**
* 类型M目录 C菜单 F按钮
*/
@NotBlank(message = "菜单类型不能为空")
private String menuType;
/** 显示状态0显示 1隐藏 */
private String visible;
/** 菜单状态0显示 1隐藏 */
private String status;
/**
* 显示状态0显示 1隐藏
*/
private String visible;
/** 权限字符串 */
@Size(min = 0, max = 100, message = "权限标识长度不能超过100个字符")
private String perms;
/**
* 菜单状态0显示 1隐藏
*/
private String status;
/** 菜单图标 */
private String icon;
/**
* 权限字符串
*/
@Size(min = 0, max = 100, message = "权限标识长度不能超过100个字符")
private String perms;
/** 创建者 */
@TableField(fill = FieldFill.INSERT)
private String createBy;
/**
* 菜单图标
*/
private String icon;
/** 创建时间 */
@TableField(fill = FieldFill.INSERT)
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
/**
* 创建者
*/
@TableField(fill = FieldFill.INSERT)
private String createBy;
/** 更新者 */
@TableField(fill = FieldFill.INSERT_UPDATE)
private String updateBy;
/**
* 创建时间
*/
@TableField(fill = FieldFill.INSERT)
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
/** 更新时间 */
@TableField(fill = FieldFill.INSERT_UPDATE)
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date updateTime;
/**
* 更新者
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
private String updateBy;
/** 备注 */
private String remark;
/**
* 更新时间
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date updateTime;
/** 请求参数 */
@TableField(exist = false)
private Map<String, Object> params = new HashMap<>();
/**
* 备注
*/
private String remark;
/** 子菜单 */
@TableField(exist = false)
private List<SysMenu> children = new ArrayList<SysMenu>();
/**
* 请求参数
*/
@TableField(exist = false)
private Map<String, Object> params = new HashMap<>();
/**
* 子菜单
*/
@TableField(exist = false)
private List<SysMenu> children = new ArrayList<SysMenu>();
}

View File

@ -1,9 +1,10 @@
package com.ruoyi.common.core.domain.entity;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import com.baomidou.mybatisplus.annotation.*;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.annotation.Excel.ColumnType;
import com.ruoyi.common.annotation.ExcelDictFormat;
import com.ruoyi.common.convert.ExcelDictConvert;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
@ -25,102 +26,133 @@ import java.util.Map;
@NoArgsConstructor
@Accessors(chain = true)
@TableName("sys_role")
public class SysRole implements Serializable
{
private static final long serialVersionUID = 1L;
@ExcelIgnoreUnannotated
public class SysRole implements Serializable {
private static final long serialVersionUID = 1L;
/** 角色ID */
@Excel(name = "角色序号", cellType = ColumnType.NUMERIC)
@TableId(value = "role_id",type = IdType.AUTO)
private Long roleId;
/**
* 角色ID
*/
@ExcelProperty(value = "角色序号")
@TableId(value = "role_id", type = IdType.AUTO)
private Long roleId;
/** 角色名称 */
@Excel(name = "角色名称")
@NotBlank(message = "角色名称不能为空")
@Size(min = 0, max = 30, message = "角色名称长度不能超过30个字符")
private String roleName;
/**
* 角色名称
*/
@ExcelProperty(value = "角色名称")
@NotBlank(message = "角色名称不能为空")
@Size(min = 0, max = 30, message = "角色名称长度不能超过30个字符")
private String roleName;
/** 角色权限 */
@Excel(name = "角色权限")
@NotBlank(message = "权限字符不能为空")
@Size(min = 0, max = 100, message = "权限字符长度不能超过100个字符")
private String roleKey;
/**
* 角色权限
*/
@ExcelProperty(value = "角色权限")
@NotBlank(message = "权限字符不能为空")
@Size(min = 0, max = 100, message = "权限字符长度不能超过100个字符")
private String roleKey;
/** 角色排序 */
@Excel(name = "角色排序")
@NotBlank(message = "显示顺序不能为空")
private String roleSort;
/**
* 角色排序
*/
@ExcelProperty(value = "角色排序")
@NotBlank(message = "显示顺序不能为空")
private String roleSort;
/** 数据范围1所有数据权限2自定义数据权限3本部门数据权限4本部门及以下数据权限5仅本人数据权限 */
@Excel(name = "数据范围", readConverterExp = "1=所有数据权限,2=自定义数据权限,3=本部门数据权限,4=本部门及以下数据权限,5=仅本人数据权限")
private String dataScope;
/**
* 数据范围1所有数据权限2自定义数据权限3本部门数据权限4本部门及以下数据权限5仅本人数据权限
*/
@ExcelProperty(value = "数据范围", converter = ExcelDictConvert.class)
@ExcelDictFormat(readConverterExp = "1=所有数据权限,2=自定义数据权限,3=本部门数据权限,4=本部门及以下数据权限,5=仅本人数据权限")
private String dataScope;
/** 菜单树选择项是否关联显示( 0父子不互相关联显示 1父子互相关联显示 */
private boolean menuCheckStrictly;
/**
* 菜单树选择项是否关联显示( 0父子不互相关联显示 1父子互相关联显示
*/
private boolean menuCheckStrictly;
/** 部门树选择项是否关联显示0父子不互相关联显示 1父子互相关联显示 */
private boolean deptCheckStrictly;
/**
* 部门树选择项是否关联显示0父子不互相关联显示 1父子互相关联显示
*/
private boolean deptCheckStrictly;
/** 角色状态0正常 1停用 */
@Excel(name = "角色状态", readConverterExp = "0=正常,1=停用")
private String status;
/**
* 角色状态0正常 1停用
*/
@ExcelProperty(value = "角色状态", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = "sys_common_status")
private String status;
/** 删除标志0代表存在 2代表删除 */
@TableLogic
private String delFlag;
/**
* 删除标志0代表存在 2代表删除
*/
@TableLogic
private String delFlag;
/** 创建者 */
@TableField(fill = FieldFill.INSERT)
private String createBy;
/**
* 创建者
*/
@TableField(fill = FieldFill.INSERT)
private String createBy;
/** 创建时间 */
@TableField(fill = FieldFill.INSERT)
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
/**
* 创建时间
*/
@TableField(fill = FieldFill.INSERT)
private Date createTime;
/** 更新者 */
@TableField(fill = FieldFill.INSERT_UPDATE)
private String updateBy;
/**
* 更新者
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
private String updateBy;
/** 更新时间 */
@TableField(fill = FieldFill.INSERT_UPDATE)
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date updateTime;
/**
* 更新时间
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date updateTime;
/** 备注 */
private String remark;
/**
* 备注
*/
private String remark;
/**
* 请求参数
*/
@TableField(exist = false)
private Map<String, Object> params = new HashMap<>();
/**
* 请求参数
*/
@TableField(exist = false)
private Map<String, Object> params = new HashMap<>();
/** 用户是否存在此角色标识 默认不存在 */
@TableField(exist = false)
private boolean flag = false;
/**
* 用户是否存在此角色标识 默认不存在
*/
@TableField(exist = false)
private boolean flag = false;
/** 菜单组 */
@TableField(exist = false)
private Long[] menuIds;
/**
* 菜单组
*/
@TableField(exist = false)
private Long[] menuIds;
/** 部门组(数据权限) */
@TableField(exist = false)
private Long[] deptIds;
/**
* 部门组(数据权限)
*/
@TableField(exist = false)
private Long[] deptIds;
public SysRole(Long roleId)
{
this.roleId = roleId;
}
public SysRole(Long roleId) {
this.roleId = roleId;
}
public boolean isAdmin()
{
return isAdmin(this.roleId);
}
public boolean isAdmin() {
return isAdmin(this.roleId);
}
public static boolean isAdmin(Long roleId)
{
return roleId != null && 1L == roleId;
}
public static boolean isAdmin(Long roleId) {
return roleId != null && 1L == roleId;
}
}

View File

@ -1,13 +1,8 @@
package com.ruoyi.common.core.domain.entity;
import com.baomidou.mybatisplus.annotation.*;
import com.fasterxml.jackson.annotation.JsonFormat;
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 lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
@ -31,140 +26,167 @@ import java.util.Map;
@NoArgsConstructor
@Accessors(chain = true)
@TableName("sys_user")
public class SysUser implements Serializable
{
private static final long serialVersionUID = 1L;
public class SysUser implements Serializable {
private static final long serialVersionUID = 1L;
/** 用户ID */
@Excel(name = "用户序号", cellType = ColumnType.NUMERIC, prompt = "用户编号")
@TableId(value = "user_id",type = IdType.AUTO)
private Long userId;
/**
* 用户ID
*/
@TableId(value = "user_id", type = IdType.AUTO)
private Long userId;
/** 部门ID */
@Excel(name = "部门编号", type = Type.IMPORT)
private Long deptId;
/**
* 部门ID
*/
private Long deptId;
/** 用户账号 */
@NotBlank(message = "用户账号不能为空")
@Size(min = 0, max = 30, message = "用户账号长度不能超过30个字符")
@Excel(name = "登录名称")
private String userName;
/**
* 用户账号
*/
@NotBlank(message = "用户账号不能为空")
@Size(min = 0, max = 30, message = "用户账号长度不能超过30个字符")
private String userName;
/** 用户昵称 */
@Size(min = 0, max = 30, message = "用户昵称长度不能超过30个字符")
@Excel(name = "用户名称")
private String nickName;
/**
* 用户昵称
*/
@Size(min = 0, max = 30, message = "用户昵称长度不能超过30个字符")
private String nickName;
/** 用户邮箱 */
@Email(message = "邮箱格式不正确")
@Size(min = 0, max = 50, message = "邮箱长度不能超过50个字符")
@Excel(name = "用户邮箱")
private String email;
/**
* 用户邮箱
*/
@Email(message = "邮箱格式不正确")
@Size(min = 0, max = 50, message = "邮箱长度不能超过50个字符")
private String email;
/** 手机号码 */
@Size(min = 0, max = 11, message = "手机号码长度不能超过11个字符")
@Excel(name = "手机号码")
private String phonenumber;
/**
* 手机号码
*/
private String phonenumber;
/** 用户性别 */
@Excel(name = "用户性别", readConverterExp = "0=男,1=女,2=未知")
private String sex;
/**
* 用户性别
*/
private String sex;
/** 用户头像 */
private String avatar;
/**
* 用户头像
*/
private String avatar;
/** 密码 */
private String password;
/**
* 密码
*/
private String password;
@JsonIgnore
@JsonProperty
public String getPassword() {
return password;
}
@JsonIgnore
@JsonProperty
public String getPassword() {
return password;
}
/** 盐加密 */
private String salt;
/**
* 盐加密
*/
private String salt;
/** 帐号状态0正常 1停用 */
@Excel(name = "帐号状态", readConverterExp = "0=正常,1=停用")
private String status;
/**
* 帐号状态0正常 1停用
*/
private String status;
/** 删除标志0代表存在 2代表删除 */
@TableLogic
private String delFlag;
/**
* 删除标志0代表存在 2代表删除
*/
@TableLogic
private String delFlag;
/** 最后登录IP */
@Excel(name = "最后登录IP", type = Type.EXPORT)
private String loginIp;
/**
* 最后登录IP
*/
private String loginIp;
/** 最后登录时间 */
@Excel(name = "最后登录时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss", type = Type.EXPORT)
private Date loginDate;
/**
* 最后登录时间
*/
private Date loginDate;
/** 创建者 */
@TableField(fill = FieldFill.INSERT)
private String createBy;
/**
* 创建者
*/
@TableField(fill = FieldFill.INSERT)
private String createBy;
/** 创建时间 */
@TableField(fill = FieldFill.INSERT)
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
/**
* 创建时间
*/
@TableField(fill = FieldFill.INSERT)
private Date createTime;
/** 更新者 */
@TableField(fill = FieldFill.INSERT_UPDATE)
private String updateBy;
/**
* 更新者
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
private String updateBy;
/** 更新时间 */
@TableField(fill = FieldFill.INSERT_UPDATE)
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date updateTime;
/**
* 更新时间
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date updateTime;
/** 备注 */
private String remark;
/**
* 备注
*/
private String remark;
/**
* 请求参数
*/
@TableField(exist = false)
private Map<String, Object> params = new HashMap<>();
/**
* 请求参数
*/
@TableField(exist = false)
private Map<String, Object> params = new HashMap<>();
/** 部门对象 */
@Excels({
@Excel(name = "部门名称", targetAttr = "deptName", type = Type.EXPORT),
@Excel(name = "部门负责人", targetAttr = "leader", type = Type.EXPORT)
})
@TableField(exist = false)
private SysDept dept;
/**
* 部门对象
*/
@TableField(exist = false)
private SysDept dept;
/** 角色对象 */
@TableField(exist = false)
private List<SysRole> roles;
/**
* 角色对象
*/
@TableField(exist = false)
private List<SysRole> roles;
/** 角色组 */
@TableField(exist = false)
private Long[] roleIds;
/**
* 角色组
*/
@TableField(exist = false)
private Long[] roleIds;
/** 岗位组 */
@TableField(exist = false)
private Long[] postIds;
/**
* 岗位组
*/
@TableField(exist = false)
private Long[] postIds;
/** 角色ID */
/**
* 角色ID
*/
@TableField(exist = false)
private Long roleId;
public SysUser(Long userId)
{
this.userId = userId;
}
public SysUser(Long userId) {
this.userId = userId;
}
public boolean isAdmin()
{
return isAdmin(this.userId);
}
public boolean isAdmin() {
return isAdmin(this.userId);
}
public static boolean isAdmin(Long userId)
{
return userId != null && 1L == userId;
}
public static boolean isAdmin(Long userId) {
return userId != null && 1L == userId;
}
}

View File

@ -23,6 +23,16 @@ public class LoginUser implements UserDetails
{
private static final long serialVersionUID = 1L;
/**
* 用户ID
*/
private Long userId;
/**
* 部门ID
*/
private Long deptId;
/**
* 用户唯一标识
*/
@ -74,6 +84,14 @@ public class LoginUser implements UserDetails
this.permissions = permissions;
}
public LoginUser(Long userId, Long deptId, SysUser user, Set<String> permissions)
{
this.userId = userId;
this.deptId = deptId;
this.user = user;
this.permissions = permissions;
}
@JsonIgnore
@Override
public String getPassword()
@ -81,7 +99,6 @@ public class LoginUser implements UserDetails
return user.getPassword();
}
@JsonIgnore
@Override
public String getUsername()
{
@ -134,7 +151,6 @@ public class LoginUser implements UserDetails
return true;
}
@JsonIgnore
@Override
public Collection<? extends GrantedAuthority> getAuthorities()
{

View File

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

View File

@ -93,6 +93,10 @@ public class ServicePlusImpl<M extends BaseMapperPlus<T>, T, K> extends ServiceI
return super.updateBatchById(entityList, batchSize);
}
/**
* 单sql批量插入( 全量填充 无视数据库默认值 )
* 适用于无脑插入
*/
@Override
public boolean saveBatch(Collection<T> entityList) {
return saveBatch(entityList, DEFAULT_BATCH_SIZE);

View File

@ -1,11 +1,10 @@
package com.ruoyi.common.core.mybatisplus.methods;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.core.enums.SqlMethod;
import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
import com.ruoyi.common.utils.StringUtils;
import org.apache.ibatis.executor.keygen.Jdbc3KeyGenerator;
import org.apache.ibatis.executor.keygen.KeyGenerator;
import org.apache.ibatis.executor.keygen.NoKeyGenerator;
@ -25,11 +24,11 @@ public class InsertAll extends AbstractMethod {
final String fieldSql = prepareFieldSql(tableInfo);
final String valueSql = prepareValuesSqlForMysqlBatch(tableInfo);
KeyGenerator keyGenerator = new NoKeyGenerator();
SqlMethod sqlMethod = SqlMethod.INSERT_ONE;
String sqlMethod = "insertAll";
String keyProperty = null;
String keyColumn = null;
// 表包含主键处理逻辑,如果不包含主键当普通字段处理
if (StrUtil.isNotBlank(tableInfo.getKeyProperty())) {
if (StringUtils.isNotBlank(tableInfo.getKeyProperty())) {
if (tableInfo.getIdType() == IdType.AUTO) {
/** 自增主键 */
keyGenerator = new Jdbc3KeyGenerator();
@ -37,7 +36,7 @@ public class InsertAll extends AbstractMethod {
keyColumn = tableInfo.getKeyColumn();
} else {
if (null != tableInfo.getKeySequence()) {
keyGenerator = TableInfoHelper.genKeyGenerator(getMethod(sqlMethod), tableInfo, builderAssistant);
keyGenerator = TableInfoHelper.genKeyGenerator(sqlMethod, tableInfo, builderAssistant);
keyProperty = tableInfo.getKeyProperty();
keyColumn = tableInfo.getKeyColumn();
}
@ -45,12 +44,12 @@ public class InsertAll extends AbstractMethod {
}
final String sqlResult = String.format(sql, tableInfo.getTableName(), fieldSql, valueSql);
SqlSource sqlSource = languageDriver.createSqlSource(configuration, sqlResult, modelClass);
return this.addInsertMappedStatement(mapperClass, modelClass, "insertAll", sqlSource, keyGenerator, keyProperty, keyColumn);
return this.addInsertMappedStatement(mapperClass, modelClass, sqlMethod, sqlSource, keyGenerator, keyProperty, keyColumn);
}
private String prepareFieldSql(TableInfo tableInfo) {
StringBuilder fieldSql = new StringBuilder();
if (StrUtil.isNotBlank(tableInfo.getKeyColumn())) {
if (StringUtils.isNotBlank(tableInfo.getKeyColumn())) {
fieldSql.append(tableInfo.getKeyColumn()).append(",");
}
tableInfo.getFieldList().forEach(x -> fieldSql.append(x.getColumn()).append(","));
@ -63,7 +62,7 @@ public class InsertAll extends AbstractMethod {
private String prepareValuesSqlForMysqlBatch(TableInfo tableInfo) {
final StringBuilder valueSql = new StringBuilder();
valueSql.append("<foreach collection=\"list\" item=\"item\" index=\"index\" open=\"(\" separator=\"),(\" close=\")\">");
if (StrUtil.isNotBlank(tableInfo.getKeyColumn())) {
if (StringUtils.isNotBlank(tableInfo.getKeyColumn())) {
valueSql.append("#{item.").append(tableInfo.getKeyProperty()).append("},");
}
tableInfo.getFieldList().forEach(x -> valueSql.append("#{item.").append(x.getProperty()).append("},"));

View File

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

View File

@ -1,43 +0,0 @@
package com.ruoyi.common.exception;
/**
* 自定义异常
*
* @author ruoyi
*/
public class CustomException extends RuntimeException
{
private static final long serialVersionUID = 1L;
private Integer code;
private String message;
public CustomException(String message)
{
this.message = message;
}
public CustomException(String message, Integer code)
{
this.message = message;
this.code = code;
}
public CustomException(String message, Throwable e)
{
super(message, e);
this.message = message;
}
@Override
public String getMessage()
{
return message;
}
public Integer getCode()
{
return code;
}
}

View File

@ -0,0 +1,58 @@
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;
}
public String getMessage()
{
return message;
}
public GlobalException setMessage(String message)
{
this.message = message;
return this;
}
}

View File

@ -0,0 +1,73 @@
package com.ruoyi.common.exception;
/**
* 业务异常
*
* @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;
}
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;
}
}

View File

@ -1,11 +1,11 @@
package com.ruoyi.common.exception;
package com.ruoyi.common.exception.base;
import cn.hutool.core.lang.Validator;
import com.ruoyi.common.utils.MessageUtils;
import com.ruoyi.common.utils.StringUtils;
/**
* 基础异常
*
*
* @author ruoyi
*/
public class BaseException extends RuntimeException
@ -64,7 +64,7 @@ public class BaseException extends RuntimeException
public String getMessage()
{
String message = null;
if (!Validator.isEmpty(code))
if (!StringUtils.isEmpty(code))
{
message = MessageUtils.message(code, args);
}

View File

@ -1,10 +1,10 @@
package com.ruoyi.common.exception.file;
import com.ruoyi.common.exception.BaseException;
import com.ruoyi.common.exception.base.BaseException;
/**
* 文件信息异常类
*
*
* @author ruoyi
*/
public class FileException extends BaseException

View File

@ -1,10 +1,10 @@
package com.ruoyi.common.exception.user;
import com.ruoyi.common.exception.BaseException;
import com.ruoyi.common.exception.base.BaseException;
/**
* 用户信息异常类
*
*
* @author ruoyi
*/
public class UserException extends BaseException

View File

@ -1,6 +1,6 @@
package com.ruoyi.common.filter;
import cn.hutool.core.util.StrUtil;
import com.ruoyi.common.utils.StringUtils;
import org.springframework.http.MediaType;
import javax.servlet.*;
@ -9,7 +9,7 @@ import java.io.IOException;
/**
* Repeatable 过滤器
*
*
* @author ruoyi
*/
public class RepeatableFilter implements Filter
@ -26,7 +26,7 @@ public class RepeatableFilter implements Filter
{
ServletRequest requestWrapper = null;
if (request instanceof HttpServletRequest
&& StrUtil.startWithIgnoreCase(request.getContentType(), MediaType.APPLICATION_JSON_VALUE))
&& StringUtils.startsWithIgnoreCase(request.getContentType(), MediaType.APPLICATION_JSON_VALUE))
{
requestWrapper = new RepeatedlyRequestWrapper((HttpServletRequest) request, response);
}

View File

@ -1,6 +1,6 @@
package com.ruoyi.common.filter;
import cn.hutool.core.util.StrUtil;
import com.ruoyi.common.utils.StringUtils;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
@ -8,12 +8,10 @@ import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* 防止XSS攻击的过滤器
*
*
* @author ruoyi
*/
public class XssFilter implements Filter
@ -23,17 +21,11 @@ public class XssFilter implements Filter
*/
public List<String> excludes = new ArrayList<>();
/**
* xss过滤开关
*/
public boolean enabled = false;
@Override
public void init(FilterConfig filterConfig) throws ServletException
{
String tempExcludes = filterConfig.getInitParameter("excludes");
String tempEnabled = filterConfig.getInitParameter("enabled");
if (StrUtil.isNotEmpty(tempExcludes))
if (StringUtils.isNotEmpty(tempExcludes))
{
String[] url = tempExcludes.split(",");
for (int i = 0; url != null && i < url.length; i++)
@ -41,10 +33,6 @@ public class XssFilter implements Filter
excludes.add(url[i]);
}
}
if (StrUtil.isNotEmpty(tempEnabled))
{
enabled = Boolean.valueOf(tempEnabled);
}
}
@Override
@ -64,25 +52,14 @@ public class XssFilter implements Filter
private boolean handleExcludeURL(HttpServletRequest request, HttpServletResponse response)
{
if (!enabled)
String url = request.getServletPath();
String method = request.getMethod();
// GET DELETE 不过滤
if (method == null || method.matches("GET") || method.matches("DELETE"))
{
return true;
}
if (excludes == null || excludes.isEmpty())
{
return false;
}
String url = request.getServletPath();
for (String pattern : excludes)
{
Pattern p = Pattern.compile("^" + pattern);
Matcher m = p.matcher(url);
if (m.find())
{
return true;
}
}
return false;
return StringUtils.matches(url, excludes);
}
@Override
@ -90,4 +67,4 @@ public class XssFilter implements Filter
{
}
}
}

View File

@ -1,9 +1,8 @@
package com.ruoyi.common.filter;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HtmlUtil;
import com.ruoyi.common.utils.StringUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
@ -59,7 +58,7 @@ public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper
// 为空,直接返回
String json = IoUtil.read(super.getInputStream(), StandardCharsets.UTF_8);
if (Validator.isEmpty(json))
if (StringUtils.isEmpty(json))
{
return super.getInputStream();
}
@ -103,6 +102,6 @@ public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper
public boolean isJsonRequest()
{
String header = super.getHeader(HttpHeaders.CONTENT_TYPE);
return StrUtil.startWithIgnoreCase(header, MediaType.APPLICATION_JSON_VALUE);
return StringUtils.startsWithIgnoreCase(header, MediaType.APPLICATION_JSON_VALUE);
}
}

View File

@ -1,8 +1,6 @@
package com.ruoyi.common.utils;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.StrUtil;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.entity.SysDictData;
import com.ruoyi.common.core.redis.RedisCache;
@ -13,7 +11,7 @@ import java.util.List;
/**
* 字典工具类
*
*
* @author ruoyi
*/
public class DictUtils
@ -25,7 +23,7 @@ public class DictUtils
/**
* 设置字典缓存
*
*
* @param key 参数键
* @param dictDatas 字典数据列表
*/
@ -36,14 +34,14 @@ public class DictUtils
/**
* 获取字典缓存
*
*
* @param key 参数键
* @return dictDatas 字典数据列表
*/
public static List<SysDictData> getDictCache(String key)
{
Object cacheObj = SpringUtils.getBean(RedisCache.class).getCacheObject(getCacheKey(key));
if (Validator.isNotNull(cacheObj))
if (StringUtils.isNotNull(cacheObj))
{
List<SysDictData> dictDatas = (List<SysDictData>)cacheObj;
return dictDatas;
@ -53,7 +51,7 @@ public class DictUtils
/**
* 根据字典类型和字典值获取字典标签
*
*
* @param dictType 字典类型
* @param dictValue 字典值
* @return 字典标签
@ -65,7 +63,7 @@ public class DictUtils
/**
* 根据字典类型和字典标签获取字典值
*
*
* @param dictType 字典类型
* @param dictLabel 字典标签
* @return 字典值
@ -77,7 +75,7 @@ public class DictUtils
/**
* 根据字典类型和字典值获取字典标签
*
*
* @param dictType 字典类型
* @param dictValue 字典值
* @param separator 分隔符
@ -88,7 +86,7 @@ public class DictUtils
StringBuilder propertyString = new StringBuilder();
List<SysDictData> datas = getDictCache(dictType);
if (StrUtil.containsAny(dictValue, separator) && CollUtil.isNotEmpty(datas))
if (StringUtils.containsAny(dictValue, separator) && CollUtil.isNotEmpty(datas))
{
for (SysDictData dict : datas)
{
@ -112,12 +110,12 @@ public class DictUtils
}
}
}
return StrUtil.strip(propertyString.toString(), null, separator);
return StringUtils.stripEnd(propertyString.toString(), separator);
}
/**
* 根据字典类型和字典标签获取字典值
*
*
* @param dictType 字典类型
* @param dictLabel 字典标签
* @param separator 分隔符
@ -128,7 +126,7 @@ public class DictUtils
StringBuilder propertyString = new StringBuilder();
List<SysDictData> datas = getDictCache(dictType);
if (StrUtil.containsAny(dictLabel, separator) && CollUtil.isNotEmpty(datas))
if (StringUtils.containsAny(dictLabel, separator) && CollUtil.isNotEmpty(datas))
{
for (SysDictData dict : datas)
{
@ -152,12 +150,12 @@ public class DictUtils
}
}
}
return StrUtil.strip(propertyString.toString(), null, separator);
return StringUtils.stripEnd(propertyString.toString(), separator);
}
/**
* 删除指定字典缓存
*
*
* @param key 字典键
*/
public static void removeDictCache(String key)
@ -176,7 +174,7 @@ public class DictUtils
/**
* 设置cache key
*
*
* @param configKey 参数键
* @return 缓存键key
*/

View File

@ -1,8 +1,6 @@
package com.ruoyi.common.utils;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
@ -33,7 +31,7 @@ public class JsonUtils {
}
public static String toJsonString(Object object) {
if (Validator.isEmpty(object)) {
if (StringUtils.isNull(object)) {
return null;
}
try {
@ -44,7 +42,7 @@ public class JsonUtils {
}
public static <T> T parseObject(String text, Class<T> clazz) {
if (StrUtil.isEmpty(text)) {
if (StringUtils.isEmpty(text)) {
return null;
}
try {
@ -66,7 +64,7 @@ public class JsonUtils {
}
public static <T> T parseObject(String text, TypeReference<T> typeReference) {
if (StrUtil.isBlank(text)) {
if (StringUtils.isBlank(text)) {
return null;
}
try {
@ -77,7 +75,7 @@ public class JsonUtils {
}
public static <T> Map<String, T> parseMap(String text) {
if (StrUtil.isBlank(text)) {
if (StringUtils.isBlank(text)) {
return null;
}
try {
@ -88,7 +86,7 @@ public class JsonUtils {
}
public static <T> List<T> parseArray(String text, Class<T> clazz) {
if (StrUtil.isEmpty(text)) {
if (StringUtils.isEmpty(text)) {
return new ArrayList<>();
}
try {

View File

@ -1,6 +1,5 @@
package com.ruoyi.common.utils;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpStatus;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
@ -59,7 +58,7 @@ public class PageUtils {
String orderByColumn = ServletUtils.getParameter(ORDER_BY_COLUMN);
String isAsc = ServletUtils.getParameter(IS_ASC);
PagePlus<T, K> page = new PagePlus<>(pageNum, pageSize);
if (StrUtil.isNotBlank(orderByColumn)) {
if (StringUtils.isNotBlank(orderByColumn)) {
String orderBy = SqlUtil.escapeOrderBySql(orderByColumn);
if ("asc".equals(isAsc)) {
page.addOrder(OrderItem.asc(orderBy));
@ -91,9 +90,9 @@ public class PageUtils {
isAsc = "desc";
}
Page<T> page = new Page<>(pageNum, pageSize);
if (StrUtil.isNotBlank(orderByColumn)) {
if (StringUtils.isNotBlank(orderByColumn)) {
String orderBy = SqlUtil.escapeOrderBySql(orderByColumn);
orderBy = StrUtil.toUnderlineCase(orderBy);
orderBy = StringUtils.toUnderScoreCase(orderBy);
if ("asc".equals(isAsc)) {
page.addOrder(OrderItem.asc(orderBy));
} else if ("desc".equals(isAsc)) {

View File

@ -5,15 +5,45 @@ import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.exception.CustomException;
import com.ruoyi.common.exception.ServiceException;
/**
* 安全服务工具类
*
*
* @author ruoyi
*/
public class SecurityUtils
{
/**
* 用户ID
**/
public static Long getUserId()
{
try
{
return getLoginUser().getUserId();
}
catch (Exception e)
{
throw new ServiceException("获取用户ID异常", HttpStatus.HTTP_UNAUTHORIZED);
}
}
/**
* 获取部门ID
**/
public static Long getDeptId()
{
try
{
return getLoginUser().getDeptId();
}
catch (Exception e)
{
throw new ServiceException("获取部门ID异常", HttpStatus.HTTP_UNAUTHORIZED);
}
}
/**
* 获取用户账户
**/
@ -25,7 +55,7 @@ public class SecurityUtils
}
catch (Exception e)
{
throw new CustomException("获取用户账户异常", HttpStatus.HTTP_UNAUTHORIZED);
throw new ServiceException("获取用户账户异常", HttpStatus.HTTP_UNAUTHORIZED);
}
}
@ -40,7 +70,7 @@ public class SecurityUtils
}
catch (Exception e)
{
throw new CustomException("获取用户信息异常", HttpStatus.HTTP_UNAUTHORIZED);
throw new ServiceException("获取用户信息异常", HttpStatus.HTTP_UNAUTHORIZED);
}
}
@ -79,7 +109,7 @@ public class SecurityUtils
/**
* 是否为管理员
*
*
* @param userId 用户ID
* @return 结果
*/

View File

@ -1,7 +1,6 @@
package com.ruoyi.common.utils;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.servlet.ServletUtil;
import cn.hutool.http.HttpStatus;
import org.springframework.http.MediaType;
@ -112,12 +111,12 @@ public class ServletUtils extends ServletUtil {
}
String uri = request.getRequestURI();
if (StrUtil.equalsAnyIgnoreCase(uri, ".json", ".xml")) {
if (StringUtils.equalsAnyIgnoreCase(uri, ".json", ".xml")) {
return true;
}
String ajax = request.getParameter("__ajax");
if (StrUtil.equalsAnyIgnoreCase(ajax, "json", "xml")) {
if (StringUtils.equalsAnyIgnoreCase(ajax, "json", "xml")) {
return true;
}
return false;

View File

@ -0,0 +1,354 @@
package com.ruoyi.common.utils;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.ReUtil;
import cn.hutool.core.util.StrUtil;
import java.util.*;
/**
* 字符串工具类
*
* @author ruoyi
*/
public class StringUtils extends org.apache.commons.lang3.StringUtils {
/**
* 获取参数不为空值
*
* @param value defaultValue 要判断的value
* @return value 返回值
*/
public static <T> T nvl(T value, T defaultValue) {
return ObjectUtil.defaultIfNull(value, defaultValue);
}
/**
* 获取参数不为空值
*
* @param str defaultValue 要判断的value
* @return value 返回值
*/
public static String blankToDefault(String str, String defaultValue) {
return StrUtil.blankToDefault(str, defaultValue);
}
/**
* * 判断一个Collection是否为空 包含ListSetQueue
*
* @param coll 要判断的Collection
* @return true为空 false非空
*/
public static boolean isEmpty(Collection<?> coll) {
return CollUtil.isEmpty(coll);
}
/**
* * 判断一个Collection是否非空包含ListSetQueue
*
* @param coll 要判断的Collection
* @return true非空 false
*/
public static boolean isNotEmpty(Collection<?> coll) {
return !isEmpty(coll);
}
/**
* * 判断一个对象数组是否为空
*
* @param objects 要判断的对象数组
* * @return true为空 false非空
*/
public static boolean isEmpty(Object[] objects) {
return ArrayUtil.isEmpty(objects);
}
/**
* * 判断一个对象数组是否非空
*
* @param objects 要判断的对象数组
* @return true非空 false
*/
public static boolean isNotEmpty(Object[] objects) {
return !isEmpty(objects);
}
/**
* * 判断一个对象是否为空
*
* @param object 要判断的对象数组
* * @return true为空 false非空
*/
public static boolean isEmpty(Object object) {
return ObjectUtil.isEmpty(object);
}
/**
* * 判断一个对象是否非空
*
* @param object 要判断的对象数组
* @return true非空 false
*/
public static boolean isNotEmpty(Object object) {
return !isEmpty(object);
}
/**
* * 判断一个Map是否为空
*
* @param map 要判断的Map
* @return true为空 false非空
*/
public static boolean isEmpty(Map<?, ?> map) {
return MapUtil.isEmpty(map);
}
/**
* * 判断一个Map是否为空
*
* @param map 要判断的Map
* @return true非空 false
*/
public static boolean isNotEmpty(Map<?, ?> map) {
return !isEmpty(map);
}
/**
* * 判断一个字符串是否为空串
*
* @param str String
* @return true为空 false非空
*/
public static boolean isEmpty(String str) {
return StrUtil.isEmpty(str);
}
/**
* * 判断一个字符串是否为非空串
*
* @param str String
* @return true非空串 false空串
*/
public static boolean isNotEmpty(String str) {
return !isEmpty(str);
}
/**
* * 判断一个对象是否为空
*
* @param object Object
* @return true为空 false非空
*/
public static boolean isNull(Object object) {
return ObjectUtil.isNull(object);
}
/**
* * 判断一个对象是否非空
*
* @param object Object
* @return true非空 false
*/
public static boolean isNotNull(Object object) {
return !isNull(object);
}
/**
* * 判断一个对象是否是数组类型Java基本型别的数组
*
* @param object 对象
* @return true是数组 false不是数组
*/
public static boolean isArray(Object object) {
return ArrayUtil.isArray(object);
}
/**
* 去空格
*/
public static String trim(String str) {
return StrUtil.trim(str);
}
/**
* 截取字符串
*
* @param str 字符串
* @param start 开始
* @return 结果
*/
public static String substring(final String str, int start) {
return substring(str, start, str.length());
}
/**
* 截取字符串
*
* @param str 字符串
* @param start 开始
* @param end 结束
* @return 结果
*/
public static String substring(final String str, int start, int end) {
return StrUtil.sub(str, start, 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 template 文本模板,被替换的部分用 {} 表示
* @param params 参数值
* @return 格式化后的文本
*/
public static String format(String template, Object... params) {
return StrUtil.format(template, params);
}
/**
* 是否为http(s)://开头
*
* @param link 链接
* @return 结果
*/
public static boolean ishttp(String link) {
return Validator.isUrl(link);
}
/**
* 字符串转set
*
* @param str 字符串
* @param sep 分隔符
* @return set集合
*/
public static Set<String> str2Set(String str, String sep) {
return new HashSet<>(str2List(str, sep, true, false));
}
/**
* 字符串转list
*
* @param str 字符串
* @param sep 分隔符
* @param filterBlank 过滤纯空白
* @param trim 去掉首尾空白
* @return list集合
*/
public static List<String> str2List(String str, String sep, boolean filterBlank, boolean trim) {
List<String> list = new ArrayList<>();
if (isEmpty(str)) {
return list;
}
// 过滤空白字符串
if (filterBlank && isBlank(str)) {
return list;
}
String[] split = str.split(sep);
for (String string : split) {
if (filterBlank && isBlank(string)) {
continue;
}
if (trim) {
string = trim(string);
}
list.add(string);
}
return list;
}
/**
* 查找指定字符串是否包含指定字符串列表中的任意一个字符串同时串忽略大小写
*
* @param cs 指定字符串
* @param searchCharSequences 需要检查的字符串数组
* @return 是否包含任意一个字符串
*/
public static boolean containsAnyIgnoreCase(CharSequence cs, CharSequence... searchCharSequences) {
return StrUtil.containsAnyIgnoreCase(cs, searchCharSequences);
}
/**
* 驼峰转下划线命名
*/
public static String toUnderScoreCase(String str) {
return StrUtil.toUnderlineCase(str);
}
/**
* 是否包含字符串
*
* @param str 验证字符串
* @param strs 字符串组
* @return 包含返回true
*/
public static boolean inStringIgnoreCase(String str, String... strs) {
return StrUtil.equalsAnyIgnoreCase(str, strs);
}
/**
* 将下划线大写方式命名的字符串转换为驼峰式。如果转换前的下划线大写方式命名的字符串为空,则返回空字符串。 例如HELLO_WORLD->HelloWorld
*
* @param name 转换前的下划线大写方式命名的字符串
* @return 转换后的驼峰式命名的字符串
*/
public static String convertToCamelCase(String name) {
return StrUtil.upperFirst(StrUtil.toCamelCase(name));
}
/**
* 驼峰式命名法 例如user_name->userName
*/
public static String toCamelCase(String s) {
return StrUtil.toCamelCase(s);
}
/**
* 查找指定字符串是否匹配指定字符串列表中的任意一个字符串
*
* @param str 指定字符串
* @param strs 需要检查的字符串数组
* @return 是否匹配
*/
public static boolean matches(String str, List<String> strs) {
if (isEmpty(str) || isEmpty(strs)) {
return false;
}
for (String pattern : strs) {
if (isMatch(pattern, str)) {
return true;
}
}
return false;
}
/**
* 判断url是否与规则配置:
* ? 表示单个字符;
* * 表示一层路径内的任意字符串,不可跨层级;
* ** 表示任意层路径;
*
* @param pattern 匹配规则
* @param url 需要匹配的url
* @return
*/
public static boolean isMatch(String pattern, String url) {
return ReUtil.isMatch(pattern, url);
}
@SuppressWarnings("unchecked")
public static <T> T cast(Object obj) {
return (T) obj;
}
}

View File

@ -1,76 +0,0 @@
package com.ruoyi.common.utils.file;
import java.io.File;
import org.apache.commons.lang3.StringUtils;
/**
* 文件类型工具类
*
* @author ruoyi
*/
public class FileTypeUtils
{
/**
* 获取文件类型
* <p>
* 例如: ruoyi.txt, 返回: txt
*
* @param file 文件名
* @return 后缀(不含".")
*/
public static String getFileType(File file)
{
if (null == file)
{
return StringUtils.EMPTY;
}
return getFileType(file.getName());
}
/**
* 获取文件类型
* <p>
* 例如: ruoyi.txt, 返回: txt
*
* @param fileName 文件名
* @return 后缀(不含".")
*/
public static String getFileType(String fileName)
{
int separatorIndex = fileName.lastIndexOf(".");
if (separatorIndex < 0)
{
return "";
}
return fileName.substring(separatorIndex + 1).toLowerCase();
}
/**
* 获取文件类型
*
* @param photoByte 文件字节码
* @return 后缀(不含".")
*/
public static String getFileExtendName(byte[] photoByte)
{
String strFileExtendName = "JPG";
if ((photoByte[0] == 71) && (photoByte[1] == 73) && (photoByte[2] == 70) && (photoByte[3] == 56)
&& ((photoByte[4] == 55) || (photoByte[4] == 57)) && (photoByte[5] == 97))
{
strFileExtendName = "GIF";
}
else if ((photoByte[6] == 74) && (photoByte[7] == 70) && (photoByte[8] == 73) && (photoByte[9] == 70))
{
strFileExtendName = "JPG";
}
else if ((photoByte[0] == 66) && (photoByte[1] == 77))
{
strFileExtendName = "BMP";
}
else if ((photoByte[1] == 80) && (photoByte[2] == 78) && (photoByte[3] == 71))
{
strFileExtendName = "PNG";
}
return strFileExtendName;
}
}

View File

@ -1,239 +0,0 @@
package com.ruoyi.common.utils.file;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.exception.file.FileNameLengthLimitExceededException;
import com.ruoyi.common.exception.file.FileSizeLimitExceededException;
import com.ruoyi.common.exception.file.InvalidExtensionException;
import com.ruoyi.common.utils.DateUtils;
import org.apache.commons.io.FilenameUtils;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
/**
* 文件上传工具类
*
* @author ruoyi
*/
public class FileUploadUtils
{
/**
* 默认大小 50M
*/
public static final long DEFAULT_MAX_SIZE = 50 * 1024 * 1024;
/**
* 默认的文件名最大长度 100
*/
public static final int DEFAULT_FILE_NAME_LENGTH = 100;
/**
* 默认上传的地址
*/
private static String defaultBaseDir = RuoYiConfig.getProfile();
public static void setDefaultBaseDir(String defaultBaseDir)
{
FileUploadUtils.defaultBaseDir = defaultBaseDir;
}
public static String getDefaultBaseDir()
{
return defaultBaseDir;
}
/**
* 以默认配置进行文件上传
*
* @param file 上传的文件
* @return 文件名称
* @throws Exception
*/
public static final String upload(MultipartFile file) throws IOException
{
try
{
return upload(getDefaultBaseDir(), file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION);
}
catch (Exception e)
{
throw new IOException(e.getMessage(), e);
}
}
/**
* 根据文件路径上传
*
* @param baseDir 相对应用的基目录
* @param file 上传的文件
* @return 文件名称
* @throws IOException
*/
public static final String upload(String baseDir, MultipartFile file) throws IOException
{
try
{
return upload(baseDir, file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION);
}
catch (Exception e)
{
throw new IOException(e.getMessage(), e);
}
}
/**
* 文件上传
*
* @param baseDir 相对应用的基目录
* @param file 上传的文件
* @param allowedExtension 上传文件类型
* @return 返回上传成功的文件名
* @throws FileSizeLimitExceededException 如果超出最大大小
* @throws FileNameLengthLimitExceededException 文件名太长
* @throws IOException 比如读写文件出错时
* @throws InvalidExtensionException 文件校验异常
*/
public static final String upload(String baseDir, MultipartFile file, String[] allowedExtension)
throws FileSizeLimitExceededException, IOException, FileNameLengthLimitExceededException,
InvalidExtensionException
{
int fileNamelength = file.getOriginalFilename().length();
if (fileNamelength > FileUploadUtils.DEFAULT_FILE_NAME_LENGTH)
{
throw new FileNameLengthLimitExceededException(FileUploadUtils.DEFAULT_FILE_NAME_LENGTH);
}
assertAllowed(file, allowedExtension);
String fileName = extractFilename(file);
File desc = getAbsoluteFile(baseDir, fileName);
desc = FileUtil.touch(desc);
FileUtil.writeFromStream(file.getInputStream(), desc);
String pathFileName = getPathFileName(baseDir, fileName);
return pathFileName;
}
/**
* 编码文件名
*/
public static final String extractFilename(MultipartFile file)
{
String fileName = file.getOriginalFilename();
String extension = getExtension(file);
fileName = DateUtils.datePath() + "/" + IdUtil.fastUUID() + "." + extension;
return fileName;
}
private static final File getAbsoluteFile(String uploadDir, String fileName) throws IOException
{
File desc = new File(uploadDir + File.separator + fileName);
if (!desc.exists())
{
if (!desc.getParentFile().exists())
{
desc.getParentFile().mkdirs();
}
}
return desc;
}
private static final String getPathFileName(String uploadDir, String fileName) throws IOException
{
int dirLastIndex = RuoYiConfig.getProfile().length() + 1;
String currentDir = StrUtil.subSuf(uploadDir, dirLastIndex);
String pathFileName = Constants.RESOURCE_PREFIX + "/" + currentDir + "/" + fileName;
return pathFileName;
}
/**
* 文件大小校验
*
* @param file 上传的文件
* @return
* @throws FileSizeLimitExceededException 如果超出最大大小
* @throws InvalidExtensionException
*/
public static final void assertAllowed(MultipartFile file, String[] allowedExtension)
throws FileSizeLimitExceededException, InvalidExtensionException
{
long size = file.getSize();
if (DEFAULT_MAX_SIZE != -1 && size > DEFAULT_MAX_SIZE)
{
throw new FileSizeLimitExceededException(DEFAULT_MAX_SIZE / 1024 / 1024);
}
String fileName = file.getOriginalFilename();
String extension = getExtension(file);
if (allowedExtension != null && !isAllowedExtension(extension, allowedExtension))
{
if (allowedExtension == MimeTypeUtils.IMAGE_EXTENSION)
{
throw new InvalidExtensionException.InvalidImageExtensionException(allowedExtension, extension,
fileName);
}
else if (allowedExtension == MimeTypeUtils.FLASH_EXTENSION)
{
throw new InvalidExtensionException.InvalidFlashExtensionException(allowedExtension, extension,
fileName);
}
else if (allowedExtension == MimeTypeUtils.MEDIA_EXTENSION)
{
throw new InvalidExtensionException.InvalidMediaExtensionException(allowedExtension, extension,
fileName);
}
else if (allowedExtension == MimeTypeUtils.VIDEO_EXTENSION)
{
throw new InvalidExtensionException.InvalidVideoExtensionException(allowedExtension, extension,
fileName);
}
else
{
throw new InvalidExtensionException(allowedExtension, extension, fileName);
}
}
}
/**
* 判断MIME类型是否是允许的MIME类型
*
* @param extension
* @param allowedExtension
* @return
*/
public static final boolean isAllowedExtension(String extension, String[] allowedExtension)
{
for (String str : allowedExtension)
{
if (str.equalsIgnoreCase(extension))
{
return true;
}
}
return false;
}
/**
* 获取文件名的后缀
*
* @param file 表单文件
* @return 后缀名
*/
public static final String getExtension(MultipartFile file)
{
String extension = FilenameUtils.getExtension(file.getOriginalFilename());
if (Validator.isEmpty(extension))
{
extension = MimeTypeUtils.getExtension(file.getContentType());
}
return extension;
}
}

View File

@ -1,12 +1,9 @@
package com.ruoyi.common.utils.file;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
@ -17,77 +14,6 @@ import java.nio.charset.StandardCharsets;
*/
public class FileUtils extends FileUtil
{
public static String FILENAME_PATTERN = "[a-zA-Z0-9_\\-\\|\\.\\u4e00-\\u9fa5]+";
/**
* 文件名称验证
*
* @param filename 文件名称
* @return true 正常 false 非法
*/
public static boolean isValidFilename(String filename)
{
return filename.matches(FILENAME_PATTERN);
}
/**
* 检查文件是否可下载
*
* @param resource 需要下载的文件
* @return true 正常 false 非法
*/
public static boolean checkAllowDownload(String resource)
{
// 禁止目录上跳级别
if (StrUtil.contains(resource, ".."))
{
return false;
}
// 检查允许下载的文件规则
if (ArrayUtil.contains(MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION, FileTypeUtils.getFileType(resource)))
{
return true;
}
// 不在允许下载的文件规则
return false;
}
/**
* 下载文件名重新编码
*
* @param request 请求对象
* @param fileName 文件名
* @return 编码后的文件名
*/
public static String setFileDownloadHeader(HttpServletRequest request, String fileName) throws UnsupportedEncodingException
{
final String agent = request.getHeader("USER-AGENT");
String filename = fileName;
if (agent.contains("MSIE"))
{
// IE浏览器
filename = URLEncoder.encode(filename, StandardCharsets.UTF_8.toString());
filename = filename.replace("+", " ");
}
else if (agent.contains("Firefox"))
{
// 火狐浏览器
filename = new String(fileName.getBytes(), "ISO8859-1");
}
else if (agent.contains("Chrome"))
{
// google浏览器
filename = URLEncoder.encode(filename, StandardCharsets.UTF_8.toString());
}
else
{
// 其它浏览器
filename = URLEncoder.encode(filename, StandardCharsets.UTF_8.toString());
}
return filename;
}
/**
* 下载文件名重新编码

View File

@ -1,102 +0,0 @@
package com.ruoyi.common.utils.file;
import cn.hutool.core.util.StrUtil;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.constant.Constants;
import org.apache.poi.util.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.Arrays;
/**
* 图片处理工具类
*
* @author ruoyi
*/
public class ImageUtils
{
private static final Logger log = LoggerFactory.getLogger(ImageUtils.class);
public static byte[] getImage(String imagePath)
{
InputStream is = getFile(imagePath);
try
{
return IOUtils.toByteArray(is);
}
catch (Exception e)
{
log.error("图片加载异常 {}", e);
return null;
}
finally
{
IOUtils.closeQuietly(is);
}
}
public static InputStream getFile(String imagePath)
{
try
{
byte[] result = readFile(imagePath);
result = Arrays.copyOf(result, result.length);
return new ByteArrayInputStream(result);
}
catch (Exception e)
{
log.error("获取图片异常 {}", e);
}
return null;
}
/**
* 读取文件为字节数据
*
* @param key 地址
* @return 字节数据
*/
public static byte[] readFile(String url)
{
InputStream in = null;
ByteArrayOutputStream baos = null;
try
{
if (url.startsWith("http"))
{
// 网络地址
URL urlObj = new URL(url);
URLConnection urlConnection = urlObj.openConnection();
urlConnection.setConnectTimeout(30 * 1000);
urlConnection.setReadTimeout(60 * 1000);
urlConnection.setDoInput(true);
in = urlConnection.getInputStream();
}
else
{
// 本机地址
String localPath = RuoYiConfig.getProfile();
String downloadPath = localPath + StrUtil.subAfter(url, Constants.RESOURCE_PREFIX,false);
in = new FileInputStream(downloadPath);
}
return IOUtils.toByteArray(in);
}
catch (Exception e)
{
log.error("获取文件路径异常 {}", e);
return null;
}
finally
{
IOUtils.closeQuietly(in);
IOUtils.closeQuietly(baos);
}
}
}

View File

@ -1,59 +0,0 @@
package com.ruoyi.common.utils.file;
/**
* 媒体类型工具类
*
* @author ruoyi
*/
public class MimeTypeUtils
{
public static final String IMAGE_PNG = "image/png";
public static final String IMAGE_JPG = "image/jpg";
public static final String IMAGE_JPEG = "image/jpeg";
public static final String IMAGE_BMP = "image/bmp";
public static final String IMAGE_GIF = "image/gif";
public static final String[] IMAGE_EXTENSION = { "bmp", "gif", "jpg", "jpeg", "png" };
public static final String[] FLASH_EXTENSION = { "swf", "flv" };
public static final String[] MEDIA_EXTENSION = { "swf", "flv", "mp3", "wav", "wma", "wmv", "mid", "avi", "mpg",
"asf", "rm", "rmvb" };
public static final String[] VIDEO_EXTENSION = { "mp4", "avi", "rmvb" };
public static final String[] DEFAULT_ALLOWED_EXTENSION = {
// 图片
"bmp", "gif", "jpg", "jpeg", "png",
// word excel powerpoint
"doc", "docx", "xls", "xlsx", "ppt", "pptx", "html", "htm", "txt",
// 压缩文件
"rar", "zip", "gz", "bz2",
// 视频格式
"mp4", "avi", "rmvb",
// pdf
"pdf" };
public static String getExtension(String prefix)
{
switch (prefix)
{
case IMAGE_PNG:
return "png";
case IMAGE_JPG:
return "jpg";
case IMAGE_JPEG:
return "jpeg";
case IMAGE_BMP:
return "bmp";
case IMAGE_GIF:
return "gif";
default:
return "";
}
}
}

View File

@ -1,12 +1,12 @@
package com.ruoyi.common.utils.ip;
import cn.hutool.core.net.NetUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HtmlUtil;
import cn.hutool.http.HttpUtil;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.utils.JsonUtils;
import com.ruoyi.common.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import java.util.Map;
@ -38,7 +38,7 @@ public class AddressUtils {
.body("ip=" + ip + "&json=true", Constants.GBK)
.execute()
.body();
if (StrUtil.isEmpty(rspStr)) {
if (StringUtils.isEmpty(rspStr)) {
log.error("获取地理位置异常 {}", ip);
return UNKNOWN;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,10 +1,9 @@
package com.ruoyi.common.utils.reflect;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import com.ruoyi.common.utils.StringUtils;
import java.lang.reflect.Method;
import java.util.List;
/**
* 反射工具类. 提供调用getter/setter方法, 访问私有变量, 调用私有方法, 获取泛型类型Class, 被AOP过的真实类等工具函数.
@ -25,8 +24,8 @@ public class ReflectUtils extends ReflectUtil {
@SuppressWarnings("unchecked")
public static <E> E invokeGetter(Object obj, String propertyName) {
Object object = obj;
for (String name : StrUtil.split(propertyName, ".")) {
String getterMethodName = GETTER_PREFIX + StrUtil.upperFirst(name);
for (String name : StringUtils.split(propertyName, ".")) {
String getterMethodName = GETTER_PREFIX + StringUtils.capitalize(name);
object = invoke(object, getterMethodName);
}
return (E) object;
@ -38,13 +37,13 @@ public class ReflectUtils extends ReflectUtil {
*/
public static <E> void invokeSetter(Object obj, String propertyName, E value) {
Object object = obj;
List<String> names = StrUtil.split(propertyName, ".");
for (int i = 0; i < names.size(); i++) {
if (i < names.size() - 1) {
String getterMethodName = GETTER_PREFIX + StrUtil.upperFirst(names.get(i));
String[] names = StringUtils.split(propertyName, ".");
for (int i = 0; i < names.length; i++) {
if (i < names.length - 1) {
String getterMethodName = GETTER_PREFIX + StringUtils.capitalize(names[i]);
object = invoke(object, getterMethodName);
} else {
String setterMethodName = SETTER_PREFIX + StrUtil.upperFirst(names.get(i));
String setterMethodName = SETTER_PREFIX + StringUtils.capitalize(names[i]);
Method method = getMethodByName(object.getClass(), setterMethodName);
invoke(object, method, value);
}

View File

@ -1,11 +1,11 @@
package com.ruoyi.common.utils.sql;
import cn.hutool.core.lang.Validator;
import com.ruoyi.common.exception.BaseException;
import com.ruoyi.common.exception.UtilException;
import com.ruoyi.common.utils.StringUtils;
/**
* sql操作工具类
*
*
* @author ruoyi
*/
public class SqlUtil
@ -20,9 +20,9 @@ public class SqlUtil
*/
public static String escapeOrderBySql(String value)
{
if (Validator.isNotEmpty(value) && !isValidOrderBySql(value))
if (StringUtils.isNotEmpty(value) && !isValidOrderBySql(value))
{
throw new BaseException("参数不符合规范,不能进行查询");
throw new UtilException("参数不符合规范,不能进行查询");
}
return value;
}

View File

@ -5,6 +5,8 @@ import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.demo.domain.TestDemo;
import com.ruoyi.demo.service.ITestDemoService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
@ -21,6 +23,7 @@ import java.util.List;
* @author Lion Li
* @date 2021-05-30
*/
@Api(value = "测试批量方法", tags = {"测试批量方法"})
@RequiredArgsConstructor(onConstructor_ = @Autowired)
@RestController
@RequestMapping("/demo/batch")
@ -31,7 +34,9 @@ public class TestBatchController extends BaseController {
/**
* 新增批量方法 ( 全量覆盖填充 )
*/
@ApiOperation(value = "新增批量方法")
@PostMapping()
// @DataSource(DataSourceType.SLAVE)
public AjaxResult<Void> add() {
List<TestDemo> list = new ArrayList<>();
for (int i = 0; i < 1000; i++) {
@ -41,10 +46,12 @@ public class TestBatchController extends BaseController {
}
/**
* 修改批量方法
* 删除批量方法
*/
@ApiOperation(value = "删除批量方法")
@DeleteMapping()
public AjaxResult<Void> edit() {
// @DataSource(DataSourceType.SLAVE)
public AjaxResult<Void> remove() {
return toAjax(iTestDemoService.remove(new LambdaQueryWrapper<TestDemo>()
.eq(TestDemo::getOrderNum, -1L)) ? 1 : 0);
}

View File

@ -20,10 +20,12 @@ import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;
/**
* 测试单表Controller
@ -67,10 +69,9 @@ public class TestDemoController extends BaseController {
@PreAuthorize("@ss.hasPermi('demo:demo:export')")
@Log(title = "测试单表", businessType = BusinessType.EXPORT)
@GetMapping("/export")
public AjaxResult<TestDemoVo> export(@Validated TestDemoBo bo) {
public void export(@Validated TestDemoBo bo, HttpServletResponse response) {
List<TestDemoVo> list = iTestDemoService.queryList(bo);
ExcelUtil<TestDemoVo> util = new ExcelUtil<TestDemoVo>(TestDemoVo.class);
return util.exportExcel(list, "测试单表");
ExcelUtil.exportExcel(list, "测试单表", TestDemoVo.class, response);
}
/**
@ -90,7 +91,7 @@ public class TestDemoController extends BaseController {
@ApiOperation("新增测试单表")
@PreAuthorize("@ss.hasPermi('demo:demo:add')")
@Log(title = "测试单表", businessType = BusinessType.INSERT)
@RepeatSubmit
@RepeatSubmit(intervalTime = 2, timeUnit = TimeUnit.SECONDS)
@PostMapping()
public AjaxResult<Void> add(@Validated(AddGroup.class) @RequestBody TestDemoBo bo) {
return toAjax(iTestDemoService.insertByBo(bo) ? 1 : 0);

View File

@ -0,0 +1,29 @@
package com.ruoyi.demo.controller;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.MessageUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 测试国际化
*
* @author Lion Li
*/
@RestController
@RequestMapping("/demo/i18n")
public class TestI18nController {
/**
* 通过code获取国际化内容
* code为 messages.properties 中的 key
*
* 测试使用 user.register.success
*/
@GetMapping()
public AjaxResult<Void> get(String code) {
return AjaxResult.success(MessageUtils.message(code));
}
}

View File

@ -19,6 +19,7 @@ import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.Arrays;
@ -57,10 +58,9 @@ public class TestTreeController extends BaseController {
@PreAuthorize("@ss.hasPermi('demo:tree:export')")
@Log(title = "测试树表", businessType = BusinessType.EXPORT)
@GetMapping("/export")
public AjaxResult<TestTreeVo> export(@Validated TestTreeBo bo) {
public void export(@Validated TestTreeBo bo, HttpServletResponse response) {
List<TestTreeVo> list = iTestTreeService.queryList(bo);
ExcelUtil<TestTreeVo> util = new ExcelUtil<TestTreeVo>(TestTreeVo.class);
return util.exportExcel(list, "测试树表");
ExcelUtil.exportExcel(list, "测试树表", TestTreeVo.class, response);
}
/**

View File

@ -1,9 +1,11 @@
package com.ruoyi.demo.domain.vo;
import com.ruoyi.common.annotation.Excel;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Date;
@ -16,6 +18,7 @@ import java.util.Date;
*/
@Data
@ApiModel("测试单表视图对象")
@ExcelIgnoreUnannotated
public class TestDemoVo {
private static final long serialVersionUID = 1L;
@ -29,63 +32,63 @@ public class TestDemoVo {
/**
* 部门id
*/
@Excel(name = "部门id")
@ExcelProperty(value = "部门id")
@ApiModelProperty("部门id")
private Long deptId;
/**
* 用户id
*/
@Excel(name = "用户id")
@ExcelProperty(value = "用户id")
@ApiModelProperty("用户id")
private Long userId;
/**
* 排序号
*/
@Excel(name = "排序号")
@ExcelProperty(value = "排序号")
@ApiModelProperty("排序号")
private Long orderNum;
/**
* key键
*/
@Excel(name = "key键")
@ExcelProperty(value = "key键")
@ApiModelProperty("key键")
private String testKey;
/**
* 值
*/
@Excel(name = "")
@ExcelProperty(value = "")
@ApiModelProperty("")
private String value;
/**
* 创建时间
*/
@Excel(name = "创建时间" , width = 30, dateFormat = "yyyy-MM-dd")
@ExcelProperty(value = "创建时间")
@ApiModelProperty("创建时间")
private Date createTime;
/**
* 创建人
*/
@Excel(name = "创建人")
@ExcelProperty(value = "创建人")
@ApiModelProperty("创建人")
private String createBy;
/**
* 更新时间
*/
@Excel(name = "更新时间" , width = 30, dateFormat = "yyyy-MM-dd")
@ExcelProperty(value = "更新时间")
@ApiModelProperty("更新时间")
private Date updateTime;
/**
* 更新人
*/
@Excel(name = "更新人")
@ExcelProperty(value = "更新人")
@ApiModelProperty("更新人")
private String updateBy;

View File

@ -1,9 +1,11 @@
package com.ruoyi.demo.domain.vo;
import com.ruoyi.common.annotation.Excel;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Date;
@ -16,6 +18,7 @@ import java.util.Date;
*/
@Data
@ApiModel("测试树表视图对象")
@ExcelIgnoreUnannotated
public class TestTreeVo {
private static final long serialVersionUID = 1L;
@ -29,35 +32,35 @@ public class TestTreeVo {
/**
* 父id
*/
@Excel(name = "父id")
@ExcelProperty(value = "父id")
@ApiModelProperty("父id")
private Long parentId;
/**
* 部门id
*/
@Excel(name = "部门id")
@ExcelProperty(value = "部门id")
@ApiModelProperty("部门id")
private Long deptId;
/**
* 用户id
*/
@Excel(name = "用户id")
@ExcelProperty(value = "用户id")
@ApiModelProperty("用户id")
private Long userId;
/**
* 树节点名
*/
@Excel(name = "树节点名")
@ExcelProperty(value = "树节点名")
@ApiModelProperty("树节点名")
private String treeName;
/**
* 创建时间
*/
@Excel(name = "创建时间" , width = 30, dateFormat = "yyyy-MM-dd")
@ExcelProperty(value = "创建时间")
@ApiModelProperty("创建时间")
private Date createTime;

View File

@ -1,7 +1,7 @@
package com.ruoyi.demo.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.ruoyi.common.utils.StringUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
@ -62,11 +62,11 @@ public class TestDemoServiceImpl extends ServicePlusImpl<TestDemoMapper, TestDem
Map<String, Object> params = bo.getParams();
Object dataScope = params.get("dataScope");
LambdaQueryWrapper<TestDemo> lqw = Wrappers.lambdaQuery();
lqw.like(StrUtil.isNotBlank(bo.getTestKey()), TestDemo::getTestKey, bo.getTestKey());
lqw.eq(StrUtil.isNotBlank(bo.getValue()), TestDemo::getValue, bo.getValue());
lqw.like(StringUtils.isNotBlank(bo.getTestKey()), TestDemo::getTestKey, bo.getTestKey());
lqw.eq(StringUtils.isNotBlank(bo.getValue()), TestDemo::getValue, bo.getValue());
lqw.between(params.get("beginCreateTime") != null && params.get("endCreateTime") != null,
TestDemo::getCreateTime, params.get("beginCreateTime"), params.get("endCreateTime"));
lqw.apply(dataScope != null && StrUtil.isNotBlank(dataScope.toString()),
lqw.apply(dataScope != null && StringUtils.isNotBlank(dataScope.toString()),
dataScope != null ? dataScope.toString() : null);
return lqw;
}

View File

@ -1,7 +1,7 @@
package com.ruoyi.demo.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.ruoyi.common.utils.StringUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.common.annotation.DataScope;
@ -42,10 +42,10 @@ public class TestTreeServiceImpl extends ServicePlusImpl<TestTreeMapper, TestTre
Map<String, Object> params = bo.getParams();
Object dataScope = params.get("dataScope");
LambdaQueryWrapper<TestTree> lqw = Wrappers.lambdaQuery();
lqw.like(StrUtil.isNotBlank(bo.getTreeName()), TestTree::getTreeName, bo.getTreeName());
lqw.like(StringUtils.isNotBlank(bo.getTreeName()), TestTree::getTreeName, bo.getTreeName());
lqw.between(params.get("beginCreateTime") != null && params.get("endCreateTime") != null,
TestTree::getCreateTime, params.get("beginCreateTime"), params.get("endCreateTime"));
lqw.apply(dataScope != null && StrUtil.isNotBlank(dataScope.toString()),
lqw.apply(dataScope != null && StringUtils.isNotBlank(dataScope.toString()),
dataScope != null ? dataScope.toString() : null);
return lqw;
}

View File

@ -1,13 +1,12 @@
package com.ruoyi.framework.aspectj;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.StrUtil;
import com.ruoyi.common.annotation.DataScope;
import com.ruoyi.common.core.domain.BaseEntity;
import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.reflect.ReflectUtils;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.framework.web.service.TokenService;
@ -80,10 +79,10 @@ public class DataScopeAspect {
}
// 获取当前的用户
LoginUser loginUser = SpringUtils.getBean(TokenService.class).getLoginUser(ServletUtils.getRequest());
if (Validator.isNotNull(loginUser)) {
if (StringUtils.isNotNull(loginUser)) {
SysUser currentUser = loginUser.getUser();
// 如果是超级管理员,则不过滤数据
if (Validator.isNotNull(currentUser) && !currentUser.isAdmin()) {
if (StringUtils.isNotNull(currentUser) && !currentUser.isAdmin()) {
dataScopeFilter(joinPoint, currentUser, controllerDataScope.deptAlias(),
controllerDataScope.userAlias(), controllerDataScope.isUser());
}
@ -101,8 +100,8 @@ public class DataScopeAspect {
StringBuilder sqlString = new StringBuilder();
// 将 "." 提取出,不写别名为单表查询,写别名为多表查询
deptAlias = StrUtil.isNotBlank(deptAlias) ? deptAlias + "." : "";
userAlias = StrUtil.isNotBlank(userAlias) ? userAlias + "." : "";
deptAlias = StringUtils.isNotBlank(deptAlias) ? deptAlias + "." : "";
userAlias = StringUtils.isNotBlank(userAlias) ? userAlias + "." : "";
for (SysRole role : user.getRoles()) {
String dataScope = role.getDataScope();
@ -110,19 +109,19 @@ public class DataScopeAspect {
sqlString = new StringBuilder();
break;
} else if (DATA_SCOPE_CUSTOM.equals(dataScope)) {
sqlString.append(StrUtil.format(
sqlString.append(StringUtils.format(
" OR {}dept_id IN ( SELECT dept_id FROM sys_role_dept WHERE role_id = {} ) ",
deptAlias, role.getRoleId()));
} else if (DATA_SCOPE_DEPT.equals(dataScope)) {
sqlString.append(StrUtil.format(" OR {}dept_id = {} ",
sqlString.append(StringUtils.format(" OR {}dept_id = {} ",
deptAlias, user.getDeptId()));
} else if (DATA_SCOPE_DEPT_AND_CHILD.equals(dataScope)) {
sqlString.append(StrUtil.format(
sqlString.append(StringUtils.format(
" OR {}dept_id IN ( SELECT dept_id FROM sys_dept WHERE dept_id = {} or find_in_set( {} , ancestors ) )",
deptAlias, user.getDeptId(), user.getDeptId()));
} else if (DATA_SCOPE_SELF.equals(dataScope)) {
if (isUser) {
sqlString.append(StrUtil.format(" OR {}user_id = {} ",
sqlString.append(StringUtils.format(" OR {}user_id = {} ",
userAlias, user.getUserId()));
} else {
// 数据权限为仅本人且没有userAlias别名不查询任何数据
@ -131,7 +130,7 @@ public class DataScopeAspect {
}
}
if (StrUtil.isNotBlank(sqlString.toString())) {
if (StringUtils.isNotBlank(sqlString.toString())) {
putDataScope(joinPoint, sqlString.substring(4));
}
}
@ -155,14 +154,14 @@ public class DataScopeAspect {
*/
private void clearDataScope(final JoinPoint joinPoint) {
Object params = joinPoint.getArgs()[0];
if (Validator.isNotNull(params)) {
if (StringUtils.isNotNull(params)) {
putDataScope(joinPoint, "");
}
}
private static void putDataScope(JoinPoint joinPoint, String sql) {
Object params = joinPoint.getArgs()[0];
if (Validator.isNotNull(params)) {
if (StringUtils.isNotNull(params)) {
if (params instanceof BaseEntity) {
BaseEntity baseEntity = (BaseEntity) params;
baseEntity.getParams().put(DATA_SCOPE, sql);

View File

@ -1,8 +1,8 @@
package com.ruoyi.framework.aspectj;
import cn.hutool.core.lang.Validator;
import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
import com.ruoyi.common.annotation.DataSource;
import com.ruoyi.common.utils.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
@ -33,7 +33,7 @@ public class DataSourceAspect {
public Object around(ProceedingJoinPoint point) throws Throwable {
DataSource dataSource = getDataSource(point);
if (Validator.isNotNull(dataSource)) {
if (StringUtils.isNotNull(dataSource)) {
DynamicDataSourceContextHolder.poll();
String source = dataSource.value().getSource();
DynamicDataSourceContextHolder.push(source);

View File

@ -1,13 +1,12 @@
package com.ruoyi.framework.aspectj;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.StrUtil;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.enums.BusinessStatus;
import com.ruoyi.common.enums.HttpMethod;
import com.ruoyi.common.utils.JsonUtils;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.framework.web.service.AsyncService;
import com.ruoyi.framework.web.service.TokenService;
@ -104,7 +103,7 @@ public class LogAspect
if (e != null)
{
operLog.setStatus(BusinessStatus.FAIL.ordinal());
operLog.setErrorMsg(StrUtil.sub(e.getMessage(), 0, 2000));
operLog.setErrorMsg(StringUtils.substring(e.getMessage(), 0, 2000));
}
// 设置方法名称
String className = joinPoint.getTarget().getClass().getName();
@ -161,12 +160,12 @@ public class LogAspect
if (HttpMethod.PUT.name().equals(requestMethod) || HttpMethod.POST.name().equals(requestMethod))
{
String params = argsArrayToString(joinPoint.getArgs());
operLog.setOperParam(StrUtil.sub(params, 0, 2000));
operLog.setOperParam(StringUtils.substring(params, 0, 2000));
}
else
{
Map<?, ?> paramsMap = (Map<?, ?>) ServletUtils.getRequest().getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);
operLog.setOperParam(StrUtil.sub(paramsMap.toString(), 0, 2000));
operLog.setOperParam(StringUtils.substring(paramsMap.toString(), 0, 2000));
}
}
@ -195,7 +194,7 @@ public class LogAspect
if (paramsArray != null && paramsArray.length > 0)
{
for (Object o : paramsArray) {
if (Validator.isNotNull(o) && !isFilterObject(o)) {
if (StringUtils.isNotNull(o) && !isFilterObject(o)) {
params.append(JsonUtils.toJsonString(o)).append(" ");
}
}

View File

@ -0,0 +1,116 @@
package com.ruoyi.framework.aspectj;
import com.ruoyi.common.annotation.RateLimiter;
import com.ruoyi.common.enums.LimitType;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.common.utils.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.RedisScript;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.List;
/**
* 限流处理
*
* @author ruoyi
*/
@Aspect
@Component
public class RateLimiterAspect
{
private static final Logger log = LoggerFactory.getLogger(RateLimiterAspect.class);
private RedisTemplate<Object, Object> redisTemplate;
private RedisScript<Long> limitScript;
@Autowired
public void setRedisTemplate1(RedisTemplate<Object, Object> redisTemplate)
{
this.redisTemplate = redisTemplate;
}
@Autowired
public void setLimitScript(RedisScript<Long> limitScript)
{
this.limitScript = limitScript;
}
// 配置织入点
@Pointcut("@annotation(com.ruoyi.common.annotation.RateLimiter)")
public void rateLimiterPointCut()
{
}
@Before("rateLimiterPointCut()")
public void doBefore(JoinPoint point) throws Throwable
{
RateLimiter rateLimiter = getAnnotationRateLimiter(point);
String key = rateLimiter.key();
int time = rateLimiter.time();
int count = rateLimiter.count();
String combineKey = getCombineKey(rateLimiter, point);
List<Object> keys = Collections.singletonList(combineKey);
try
{
Long number = redisTemplate.execute(limitScript, keys, count, time);
if (StringUtils.isNull(number) || number.intValue() > count)
{
throw new ServiceException("访问过于频繁,请稍后再试");
}
log.info("限制请求'{}',当前请求'{}',缓存key'{}'", count, number.intValue(), key);
}
catch (ServiceException e)
{
throw e;
}
catch (Exception e)
{
throw new RuntimeException("服务器限流异常,请稍后再试");
}
}
/**
* 是否存在注解,如果存在就获取
*/
private RateLimiter getAnnotationRateLimiter(JoinPoint joinPoint)
{
Signature signature = joinPoint.getSignature();
MethodSignature methodSignature = (MethodSignature) signature;
Method method = methodSignature.getMethod();
if (method != null)
{
return method.getAnnotation(RateLimiter.class);
}
return null;
}
public String getCombineKey(RateLimiter rateLimiter, JoinPoint point)
{
StringBuffer stringBuffer = new StringBuffer(rateLimiter.key());
if (rateLimiter.limitType() == LimitType.IP)
{
stringBuffer.append(ServletUtils.getClientIP());
}
MethodSignature signature = (MethodSignature) point.getSignature();
Method method = signature.getMethod();
Class<?> targetClass = method.getDeclaringClass();
stringBuffer.append("-").append(targetClass.getName()).append("- ").append(method.getName());
return stringBuffer.toString();
}
}

View File

@ -4,7 +4,7 @@ import cn.hutool.captcha.generator.CodeGenerator;
import cn.hutool.core.math.Calculator;
import cn.hutool.core.util.CharUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.ruoyi.common.utils.StringUtils;
/**
* 无符号计算生成器
@ -45,8 +45,8 @@ public class UnsignedMathGenerator implements CodeGenerator {
int max = RandomUtil.randomInt(min, limit);
String number1 = Integer.toString(max);
String number2 = Integer.toString(min);
number1 = StrUtil.padAfter(number1, this.numberLength, CharUtil.SPACE);
number2 = StrUtil.padAfter(number2, this.numberLength, CharUtil.SPACE);
number1 = StringUtils.rightPad(number1, this.numberLength, CharUtil.SPACE);
number2 = StringUtils.rightPad(number2, this.numberLength, CharUtil.SPACE);
return number1 + RandomUtil.randomChar(operators) + number2 + '=';
}
@ -80,6 +80,6 @@ public class UnsignedMathGenerator implements CodeGenerator {
* @return 最大值
*/
private int getLimit() {
return Integer.parseInt("1" + StrUtil.repeat('0', this.numberLength));
return Integer.parseInt("1" + StringUtils.repeat('0', this.numberLength));
}
}

View File

@ -1,12 +1,8 @@
package com.ruoyi.framework.config;
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import java.util.TimeZone;
/**
* 程序注解配置
*
@ -16,11 +12,5 @@ import java.util.TimeZone;
// 表示通过aop框架暴露该代理对象,AopContext能够访问
@EnableAspectJAutoProxy(exposeProxy = true)
public class ApplicationConfig {
/**
* 时区配置
*/
@Bean
public Jackson2ObjectMapperBuilderCustomizer jacksonObjectMapperCustomization() {
return jacksonObjectMapperBuilder -> jacksonObjectMapperBuilder.timeZone(TimeZone.getDefault());
}
}

View File

@ -1,6 +1,6 @@
package com.ruoyi.framework.config;
import com.ruoyi.common.exception.CustomException;
import com.ruoyi.common.exception.ServiceException;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
@ -41,7 +41,7 @@ public class AsyncConfig extends AsyncConfigurerSupport {
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return (throwable, method, objects) -> {
throwable.printStackTrace();
throw new CustomException(
throw new ServiceException(
"Exception message - " + throwable.getMessage()
+ ", Method name - " + method.getName()
+ ", Parameter value - " + Arrays.toString(objects));

View File

@ -1,10 +1,11 @@
package com.ruoyi.framework.config;
import cn.hutool.core.util.StrUtil;
import com.ruoyi.common.filter.RepeatableFilter;
import com.ruoyi.common.filter.XssFilter;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.config.properties.XssProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@ -19,6 +20,7 @@ import java.util.Map;
* @author Lion Li
*/
@Configuration
@ConditionalOnProperty(value = "xss.enabled", havingValue = "true")
public class FilterConfig {
@Autowired
@ -30,12 +32,11 @@ public class FilterConfig {
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setDispatcherTypes(DispatcherType.REQUEST);
registration.setFilter(new XssFilter());
registration.addUrlPatterns(StrUtil.splitToArray(xssProperties.getUrlPatterns(), ","));
registration.addUrlPatterns(StringUtils.split(xssProperties.getUrlPatterns(), ","));
registration.setName("xssFilter");
registration.setOrder(FilterRegistrationBean.HIGHEST_PRECEDENCE);
Map<String, String> initParameters = new HashMap<String, String>();
initParameters.put("excludes", xssProperties.getExcludes());
initParameters.put("enabled", xssProperties.getEnabled());
registration.setInitParameters(initParameters);
return registration;
}

View File

@ -0,0 +1,48 @@
package com.ruoyi.framework.config;
import cn.hutool.core.util.StrUtil;
import org.jetbrains.annotations.NotNull;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.LocaleResolver;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Locale;
/**
* 国际化配置
*
* @author Lion Li
*/
@Configuration
public class I18nConfig {
@Bean
public LocaleResolver localeResolver() {
return new I18nLocaleResolver();
}
/**
* 获取请求头国际化信息
*/
static class I18nLocaleResolver implements LocaleResolver {
@NotNull
@Override
public Locale resolveLocale(HttpServletRequest httpServletRequest) {
String language = httpServletRequest.getHeader("content-language");
Locale locale = Locale.getDefault();
if (StrUtil.isNotBlank(language)) {
String[] split = language.split("_");
locale = new Locale(split[0], split[1]);
}
return locale;
}
@Override
public void setLocale(@NotNull HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Locale locale) {
}
}
}

View File

@ -2,15 +2,19 @@ package com.ruoyi.framework.config;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.ruoyi.common.utils.JsonUtils;
import com.ruoyi.framework.jackson.BigNumberSerializer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.time.LocalDateTime;
import java.util.TimeZone;
@ -34,6 +38,10 @@ public class JacksonConfig {
ObjectMapper objectMapper = (ObjectMapper) bean;
// 全局配置序列化返回 JSON 处理
SimpleModule simpleModule = new SimpleModule();
simpleModule.addSerializer(Long.class, BigNumberSerializer.INSTANCE);
simpleModule.addSerializer(Long.TYPE, BigNumberSerializer.INSTANCE);
simpleModule.addSerializer(BigInteger.class, BigNumberSerializer.INSTANCE);
simpleModule.addSerializer(BigDecimal.class, ToStringSerializer.instance);
simpleModule.addSerializer(LocalDateTime.class, LocalDateTimeSerializer.INSTANCE);
simpleModule.addDeserializer(LocalDateTime.class, LocalDateTimeDeserializer.INSTANCE);
objectMapper.registerModule(simpleModule);

View File

@ -1,6 +1,7 @@
package com.ruoyi.framework.config;
import cn.hutool.core.util.StrUtil;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.config.properties.RedissonProperties;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
@ -16,6 +17,7 @@ import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.io.IOException;
import java.util.HashMap;
@ -59,7 +61,7 @@ public class RedisConfig extends CachingConfigurerSupport {
.setAddress(prefix + redisProperties.getHost() + ":" + redisProperties.getPort())
.setConnectTimeout(((Long) redisProperties.getTimeout().toMillis()).intValue())
.setDatabase(redisProperties.getDatabase())
.setPassword(StrUtil.isNotBlank(redisProperties.getPassword()) ? redisProperties.getPassword() : null)
.setPassword(StringUtils.isNotBlank(redisProperties.getPassword()) ? redisProperties.getPassword() : null)
.setTimeout(singleServerConfig.getTimeout())
.setRetryAttempts(singleServerConfig.getRetryAttempts())
.setRetryInterval(singleServerConfig.getRetryInterval())
@ -89,4 +91,32 @@ public class RedisConfig extends CachingConfigurerSupport {
return new RedissonSpringCacheManager(redissonClient, config, JsonJacksonCodec.INSTANCE);
}
@Bean
public DefaultRedisScript<Long> limitScript() {
DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>();
redisScript.setScriptText(limitScriptText());
redisScript.setResultType(Long.class);
return redisScript;
}
/**
* 限流脚本
*/
private String limitScriptText() {
return StrUtil.builder()
.append("local key = KEYS[1]\n")
.append("local count = tonumber(ARGV[1])\n")
.append("local time = tonumber(ARGV[2])\n")
.append("local current = redis.call('get', key);\n")
.append("if current and tonumber(current) > count then\n")
.append(" return current;\n")
.append("end\n")
.append("current = redis.call('incr', key)\n")
.append("if tonumber(current) == 1 then\n")
.append(" redis.call('expire', key, time)\n")
.append("end\n")
.append("return current;")
.toString();
}
}

View File

@ -1,5 +1,6 @@
package com.ruoyi.framework.config;
import com.ruoyi.framework.interceptor.RepeatSubmitInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@ -9,9 +10,6 @@ import org.springframework.web.filter.CorsFilter;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.framework.interceptor.RepeatSubmitInterceptor;
/**
* 通用配置
@ -27,8 +25,6 @@ public class ResourcesConfig implements WebMvcConfigurer
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry)
{
/** 本地文件上传路径 */
registry.addResourceHandler(Constants.RESOURCE_PREFIX + "/**").addResourceLocations("file:" + RuoYiConfig.getProfile() + "/");
}
/**

View File

@ -96,19 +96,16 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
// 过滤请求
.authorizeRequests()
// 对于登录login 验证码captchaImage 允许匿名访问
.antMatchers("/login", "/captchaImage").anonymous()
// 对于登录login 注册register 验证码captchaImage 允许匿名访问
.antMatchers("/login", "/register", "/captchaImage").anonymous()
.antMatchers(
HttpMethod.GET,
"/",
"/*.html",
"/**/*.html",
"/**/*.css",
"/**/*.js",
"/profile/**"
"/**/*.js"
).permitAll()
.antMatchers("/common/download**").anonymous()
.antMatchers("/common/download/resource**").anonymous()
.antMatchers("/doc.html").anonymous()
.antMatchers("/swagger-resources/**").anonymous()
.antMatchers("/webjars/**").anonymous()
@ -129,7 +126,6 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
httpSecurity.addFilterBefore(corsFilter, LogoutFilter.class);
}
/**
* 强散列哈希加密实现
*/

View File

@ -0,0 +1,22 @@
package com.ruoyi.framework.config.properties;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 重复提交 配置属性
*
* @author Lion Li
*/
@Data
@Component
@ConfigurationProperties(prefix = "repeat-submit")
public class RepeatSubmitProperties {
/**
* 间隔时间(毫秒)
*/
private int intervalTime;
}

View File

@ -6,7 +6,7 @@ import com.ruoyi.common.utils.JsonUtils;
import com.ruoyi.common.utils.ServletUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@ -15,42 +15,36 @@ import java.lang.reflect.Method;
/**
* 防止重复提交拦截器
*
* @author ruoyi
* 移除继承 HandlerInterceptorAdapter 过期类
* 改为实现 HandlerInterceptor 接口(官方推荐写法)
*
* @author Lion Li
*/
@Component
public abstract class RepeatSubmitInterceptor extends HandlerInterceptorAdapter
{
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception
{
if (handler instanceof HandlerMethod)
{
HandlerMethod handlerMethod = (HandlerMethod) handler;
Method method = handlerMethod.getMethod();
RepeatSubmit annotation = method.getAnnotation(RepeatSubmit.class);
if (annotation != null)
{
if (this.isRepeatSubmit(request))
{
AjaxResult ajaxResult = AjaxResult.error("不允许重复提交,请稍后再试");
ServletUtils.renderString(response, JsonUtils.toJsonString(ajaxResult));
return false;
}
}
return true;
}
else
{
return super.preHandle(request, response, handler);
}
}
public abstract class RepeatSubmitInterceptor implements HandlerInterceptor {
/**
* 验证是否重复提交由子类实现具体的防重复提交的规则
*
* @param request
* @return
* @throws Exception
*/
public abstract boolean isRepeatSubmit(HttpServletRequest request);
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
if (handler instanceof HandlerMethod) {
HandlerMethod handlerMethod = (HandlerMethod) handler;
Method method = handlerMethod.getMethod();
RepeatSubmit annotation = method.getAnnotation(RepeatSubmit.class);
if (annotation != null) {
if (this.isRepeatSubmit(annotation, request)) {
AjaxResult ajaxResult = AjaxResult.error("不允许重复提交,请稍后再试");
ServletUtils.renderString(response, JsonUtils.toJsonString(ajaxResult));
return false;
}
}
return true;
} else {
return HandlerInterceptor.super.preHandle(request, response, handler);
}
}
/**
* 验证是否重复提交由子类实现具体的防重复提交的规则
*/
public abstract boolean isRepeatSubmit(RepeatSubmit annotation, HttpServletRequest request);
}

View File

@ -1,15 +1,19 @@
package com.ruoyi.framework.interceptor.impl;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.lang.Validator;
import com.ruoyi.common.annotation.RepeatSubmit;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.filter.RepeatedlyRequestWrapper;
import com.ruoyi.common.utils.JsonUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.config.properties.RepeatSubmitProperties;
import com.ruoyi.framework.config.properties.TokenProperties;
import com.ruoyi.framework.interceptor.RepeatSubmitInterceptor;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
@ -20,45 +24,34 @@ import java.util.concurrent.TimeUnit;
/**
* 判断请求url和数据是否和上一次相同
* 如果和上次相同,则是重复提交表单。 有效时间为10秒内。
* 如果和上次相同,则是重复提交表单。
*
* @author ruoyi
* @author Lion Li
*/
@Slf4j
@RequiredArgsConstructor(onConstructor_ = @Autowired)
@Component
public class SameUrlDataInterceptor extends RepeatSubmitInterceptor
{
public final String REPEAT_PARAMS = "repeatParams";
public class SameUrlDataInterceptor extends RepeatSubmitInterceptor {
public final String REPEAT_PARAMS = "repeatParams";
public final String REPEAT_TIME = "repeatTime";
public final String REPEAT_TIME = "repeatTime";
// 令牌自定义标识
@Value("${token.header}")
private String header;
private final TokenProperties tokenProperties;
private final RepeatSubmitProperties repeatSubmitProperties;
private final RedisCache redisCache;
@Autowired
private RedisCache redisCache;
/**
* 间隔时间,单位:秒 默认10秒
*
* 两次相同参数的请求,如果间隔时间大于该参数,系统不会认定为重复提交的数据
*/
private int intervalTime = 10;
public void setIntervalTime(int intervalTime)
{
this.intervalTime = intervalTime;
}
@SuppressWarnings("unchecked")
@Override
public boolean isRepeatSubmit(HttpServletRequest request)
{
String nowParams = "";
if (request instanceof RepeatedlyRequestWrapper)
{
RepeatedlyRequestWrapper repeatedlyRequest = (RepeatedlyRequestWrapper) request;
@SuppressWarnings("unchecked")
@Override
public boolean isRepeatSubmit(RepeatSubmit repeatSubmit, HttpServletRequest request) {
// 如果注解不为0 则使用注解数值
long intervalTime = repeatSubmitProperties.getIntervalTime();
if (repeatSubmit.intervalTime() > 0) {
intervalTime = repeatSubmit.timeUnit().toMillis(repeatSubmit.intervalTime());
}
String nowParams = "";
if (request instanceof RepeatedlyRequestWrapper) {
RepeatedlyRequestWrapper repeatedlyRequest = (RepeatedlyRequestWrapper) request;
try {
nowParams = IoUtil.readUtf8(repeatedlyRequest.getInputStream());
} catch (IOException e) {
@ -66,68 +59,57 @@ public class SameUrlDataInterceptor extends RepeatSubmitInterceptor
}
}
// body参数为空获取Parameter的数据
if (Validator.isEmpty(nowParams))
{
nowParams = JsonUtils.toJsonString(request.getParameterMap());
}
Map<String, Object> nowDataMap = new HashMap<String, Object>();
nowDataMap.put(REPEAT_PARAMS, nowParams);
nowDataMap.put(REPEAT_TIME, System.currentTimeMillis());
// body参数为空获取Parameter的数据
if (StringUtils.isEmpty(nowParams)) {
nowParams = JsonUtils.toJsonString(request.getParameterMap());
}
Map<String, Object> nowDataMap = new HashMap<String, Object>();
nowDataMap.put(REPEAT_PARAMS, nowParams);
nowDataMap.put(REPEAT_TIME, System.currentTimeMillis());
// 请求地址作为存放cache的key值
String url = request.getRequestURI();
// 请求地址作为存放cache的key值
String url = request.getRequestURI();
// 唯一值(没有消息头则使用请求地址)
String submitKey = request.getHeader(header);
if (Validator.isEmpty(submitKey))
{
submitKey = url;
}
// 唯一值(没有消息头则使用请求地址)
String submitKey = request.getHeader(tokenProperties.getHeader());
if (StringUtils.isEmpty(submitKey)) {
submitKey = url;
}
// 唯一标识指定key + 消息头)
String cacheRepeatKey = Constants.REPEAT_SUBMIT_KEY + submitKey;
// 唯一标识指定key + 消息头)
String cacheRepeatKey = Constants.REPEAT_SUBMIT_KEY + submitKey;
Object sessionObj = redisCache.getCacheObject(cacheRepeatKey);
if (sessionObj != null)
{
Map<String, Object> sessionMap = (Map<String, Object>) sessionObj;
if (sessionMap.containsKey(url))
{
Map<String, Object> preDataMap = (Map<String, Object>) sessionMap.get(url);
if (compareParams(nowDataMap, preDataMap) && compareTime(nowDataMap, preDataMap))
{
return true;
}
}
}
Map<String, Object> cacheMap = new HashMap<String, Object>();
cacheMap.put(url, nowDataMap);
redisCache.setCacheObject(cacheRepeatKey, cacheMap, intervalTime, TimeUnit.SECONDS);
return false;
}
Object sessionObj = redisCache.getCacheObject(cacheRepeatKey);
if (sessionObj != null) {
Map<String, Object> sessionMap = (Map<String, Object>) sessionObj;
if (sessionMap.containsKey(url)) {
Map<String, Object> preDataMap = (Map<String, Object>) sessionMap.get(url);
if (compareParams(nowDataMap, preDataMap) && compareTime(nowDataMap, preDataMap, intervalTime)) {
return true;
}
}
}
Map<String, Object> cacheMap = new HashMap<String, Object>();
cacheMap.put(url, nowDataMap);
redisCache.setCacheObject(cacheRepeatKey, cacheMap, Convert.toInt(intervalTime), TimeUnit.MILLISECONDS);
return false;
}
/**
* 判断参数是否相同
*/
private boolean compareParams(Map<String, Object> nowMap, Map<String, Object> preMap)
{
String nowParams = (String) nowMap.get(REPEAT_PARAMS);
String preParams = (String) preMap.get(REPEAT_PARAMS);
return nowParams.equals(preParams);
}
/**
* 判断参数是否相同
*/
private boolean compareParams(Map<String, Object> nowMap, Map<String, Object> preMap) {
String nowParams = (String) nowMap.get(REPEAT_PARAMS);
String preParams = (String) preMap.get(REPEAT_PARAMS);
return nowParams.equals(preParams);
}
/**
* 判断两次间隔时间
*/
private boolean compareTime(Map<String, Object> nowMap, Map<String, Object> preMap)
{
long time1 = (Long) nowMap.get(REPEAT_TIME);
long time2 = (Long) preMap.get(REPEAT_TIME);
if ((time1 - time2) < (this.intervalTime * 1000))
{
return true;
}
return false;
}
/**
* 判断两次间隔时间
*/
private boolean compareTime(Map<String, Object> nowMap, Map<String, Object> preMap, long intervalTime) {
long time1 = (Long) nowMap.get(REPEAT_TIME);
long time2 = (Long) preMap.get(REPEAT_TIME);
return (time1 - time2) < intervalTime;
}
}

View File

@ -0,0 +1,42 @@
package com.ruoyi.framework.jackson;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.annotation.JacksonStdImpl;
import com.fasterxml.jackson.databind.ser.std.NumberSerializer;
import java.io.IOException;
/**
* 超出 JS 最大最小值 处理
*
* @author Lion Li
*/
@JacksonStdImpl
public class BigNumberSerializer extends NumberSerializer {
/**
* 根据 JS Number.MAX_SAFE_INTEGER 与 Number.MIN_SAFE_INTEGER 得来
*/
private static final long MAX_SAFE_INTEGER = 9007199254740991L;
private static final long MIN_SAFE_INTEGER = -9007199254740991L;
/**
* 提供实例
*/
public static final BigNumberSerializer INSTANCE = new BigNumberSerializer(Number.class);
public BigNumberSerializer(Class<? extends Number> rawType) {
super(rawType);
}
@Override
public void serialize(Number value, JsonGenerator gen, SerializerProvider provider) throws IOException {
// 超出范围 序列化位字符串
if (value.longValue() > MIN_SAFE_INTEGER && value.longValue() < MAX_SAFE_INTEGER) {
super.serialize(value, gen, provider);
} else {
gen.writeString(value.toString());
}
}
}

View File

@ -2,8 +2,10 @@ package com.ruoyi.framework.mybatisplus;
import cn.hutool.http.HttpStatus;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import com.ruoyi.common.exception.CustomException;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.SecurityUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;
import java.util.Date;
@ -14,6 +16,7 @@ import java.util.Date;
* @author Lion Li
* @date 2021/4/25
*/
@Slf4j
public class CreateAndUpdateMetaObjectHandler implements MetaObjectHandler {
@Override
@ -21,36 +24,43 @@ public class CreateAndUpdateMetaObjectHandler implements MetaObjectHandler {
try {
//根据属性名字设置要填充的值
if (metaObject.hasGetter("createTime")) {
if (metaObject.getValue("createTime") == null) {
this.setFieldValByName("createTime", new Date(), metaObject);
}
this.setFieldValByName("createTime", new Date(), metaObject);
}
if (metaObject.hasGetter("createBy")) {
if (metaObject.getValue("createBy") == null) {
this.setFieldValByName("createBy", SecurityUtils.getUsername(), metaObject);
}
this.setFieldValByName("createBy", getLoginUsername(), metaObject);
}
} catch (Exception e) {
throw new CustomException("自动注入异常 => " + e.getMessage(), HttpStatus.HTTP_UNAUTHORIZED);
throw new ServiceException("自动注入异常 => " + e.getMessage(), HttpStatus.HTTP_UNAUTHORIZED);
}
updateFill(metaObject);
}
@Override
public void updateFill(MetaObject metaObject) {
try {
if (metaObject.hasGetter("updateBy")) {
if (metaObject.getValue("updateBy") == null) {
this.setFieldValByName("updateBy", SecurityUtils.getUsername(), metaObject);
}
this.setFieldValByName("updateBy", getLoginUsername(), metaObject);
}
if (metaObject.hasGetter("updateTime")) {
if (metaObject.getValue("updateTime") == null) {
this.setFieldValByName("updateTime", new Date(), metaObject);
}
this.setFieldValByName("updateTime", new Date(), metaObject);
}
} catch (Exception e) {
throw new CustomException("自动注入异常 => " + e.getMessage(), HttpStatus.HTTP_UNAUTHORIZED);
throw new ServiceException("自动注入异常 => " + e.getMessage(), HttpStatus.HTTP_UNAUTHORIZED);
}
}
/**
* 获取登录用户名
*/
private String getLoginUsername() {
LoginUser loginUser;
try {
loginUser = SecurityUtils.getLoginUser();
} catch (Exception e) {
log.error("自动注入警告 => 用户未登录");
return null;
}
return loginUser.getUsername();
}
}

View File

@ -1,8 +1,8 @@
package com.ruoyi.framework.security.filter;
import cn.hutool.core.lang.Validator;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.web.service.TokenService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
@ -19,7 +19,7 @@ import java.io.IOException;
/**
* token过滤器 验证token有效性
*
*
* @author ruoyi
*/
@Component
@ -33,7 +33,7 @@ public class JwtAuthenticationTokenFilter extends OncePerRequestFilter
throws ServletException, IOException
{
LoginUser loginUser = tokenService.getLoginUser(request);
if (Validator.isNotNull(loginUser) && Validator.isNull(SecurityUtils.getAuthentication()))
if (StringUtils.isNotNull(loginUser) && StringUtils.isNull(SecurityUtils.getAuthentication()))
{
tokenService.verifyToken(loginUser);
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginUser, null, loginUser.getAuthorities());

View File

@ -1,6 +1,6 @@
package com.ruoyi.framework.security.handle;
import cn.hutool.core.util.StrUtil;
import com.ruoyi.common.utils.StringUtils;
import cn.hutool.http.HttpStatus;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.JsonUtils;
@ -29,7 +29,7 @@ public class AuthenticationEntryPointImpl implements AuthenticationEntryPoint, S
throws IOException
{
int code = HttpStatus.HTTP_UNAUTHORIZED;
String msg = StrUtil.format("请求访问:{},认证失败,无法访问系统资源", request.getRequestURI());
String msg = StringUtils.format("请求访问:{},认证失败,无法访问系统资源", request.getRequestURI());
ServletUtils.renderString(response, JsonUtils.toJsonString(AjaxResult.error(code, msg)));
}
}

View File

@ -1,12 +1,12 @@
package com.ruoyi.framework.security.handle;
import cn.hutool.core.lang.Validator;
import cn.hutool.http.HttpStatus;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.utils.JsonUtils;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.web.service.AsyncService;
import com.ruoyi.framework.web.service.TokenService;
import org.springframework.beans.factory.annotation.Autowired;
@ -40,7 +40,7 @@ public class LogoutSuccessHandlerImpl implements LogoutSuccessHandler {
public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication)
throws IOException, ServletException {
LoginUser loginUser = tokenService.getLoginUser(request);
if (Validator.isNotNull(loginUser)) {
if (StringUtils.isNotNull(loginUser)) {
String userName = loginUser.getUsername();
// 删除用户缓存记录
tokenService.delLoginUser(loginUser.getToken());

View File

@ -1,27 +1,25 @@
package com.ruoyi.framework.web.exception;
import cn.hutool.core.lang.Validator;
import cn.hutool.http.HttpStatus;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.exception.BaseException;
import com.ruoyi.common.exception.CustomException;
import com.ruoyi.common.exception.DemoModeException;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.authentication.AccountExpiredException;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.validation.BindException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.NoHandlerFoundException;
import javax.servlet.http.HttpServletRequest;
import javax.validation.ConstraintViolationException;
/**
* 全局异常处理器
*
*
* @author ruoyi
*/
@RestControllerAdvice
@ -30,59 +28,58 @@ public class GlobalExceptionHandler
private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);
/**
* 基础异常
* 权限校验异常
*/
@ExceptionHandler(BaseException.class)
public AjaxResult baseException(BaseException e)
@ExceptionHandler(AccessDeniedException.class)
public AjaxResult handleAccessDeniedException(AccessDeniedException e, HttpServletRequest request)
{
String requestURI = request.getRequestURI();
log.error("请求地址'{}',权限校验失败'{}'", requestURI, e.getMessage());
return AjaxResult.error(HttpStatus.HTTP_FORBIDDEN, "没有权限,请联系管理员授权");
}
/**
* 请求方式不支持
*/
@ExceptionHandler(HttpRequestMethodNotSupportedException.class)
public AjaxResult handleHttpRequestMethodNotSupported(HttpRequestMethodNotSupportedException e,
HttpServletRequest request)
{
String requestURI = request.getRequestURI();
log.error("请求地址'{}',不支持'{}'请求", requestURI, e.getMethod());
return AjaxResult.error(e.getMessage());
}
/**
* 业务异常
*/
@ExceptionHandler(CustomException.class)
public AjaxResult businessException(CustomException e)
{
if (Validator.isNull(e.getCode()))
{
return AjaxResult.error(e.getMessage());
}
return AjaxResult.error(e.getCode(), e.getMessage());
}
@ExceptionHandler(NoHandlerFoundException.class)
public AjaxResult handlerNoFoundException(Exception e)
@ExceptionHandler(ServiceException.class)
public AjaxResult handleServiceException(ServiceException e, HttpServletRequest request)
{
log.error(e.getMessage(), e);
return AjaxResult.error(HttpStatus.HTTP_NOT_FOUND, "路径不存在,请检查路径是否正确");
Integer code = e.getCode();
return StringUtils.isNotNull(code) ? AjaxResult.error(code, e.getMessage()) : AjaxResult.error(e.getMessage());
}
@ExceptionHandler(AccessDeniedException.class)
public AjaxResult handleAuthorizationException(AccessDeniedException e)
/**
* 拦截未知的运行时异常
*/
@ExceptionHandler(RuntimeException.class)
public AjaxResult handleRuntimeException(RuntimeException e, HttpServletRequest request)
{
log.error(e.getMessage());
return AjaxResult.error(HttpStatus.HTTP_FORBIDDEN, "没有权限,请联系管理员授权");
}
@ExceptionHandler(AccountExpiredException.class)
public AjaxResult handleAccountExpiredException(AccountExpiredException e)
{
log.error(e.getMessage(), e);
return AjaxResult.error(e.getMessage());
}
@ExceptionHandler(UsernameNotFoundException.class)
public AjaxResult handleUsernameNotFoundException(UsernameNotFoundException e)
{
log.error(e.getMessage(), e);
String requestURI = request.getRequestURI();
log.error("请求地址'{}',发生未知异常.", requestURI, e);
return AjaxResult.error(e.getMessage());
}
/**
* 系统异常
*/
@ExceptionHandler(Exception.class)
public AjaxResult handleException(Exception e)
public AjaxResult handleException(Exception e, HttpServletRequest request)
{
log.error(e.getMessage(), e);
String requestURI = request.getRequestURI();
log.error("请求地址'{}',发生系统异常.", requestURI, e);
return AjaxResult.error(e.getMessage());
}
@ -90,7 +87,7 @@ public class GlobalExceptionHandler
* 自定义验证异常
*/
@ExceptionHandler(BindException.class)
public AjaxResult validatedBindException(BindException e)
public AjaxResult handleBindException(BindException e)
{
log.error(e.getMessage(), e);
String message = e.getAllErrors().get(0).getDefaultMessage();
@ -111,7 +108,7 @@ public class GlobalExceptionHandler
* 自定义验证异常
*/
@ExceptionHandler(MethodArgumentNotValidException.class)
public Object validExceptionHandler(MethodArgumentNotValidException e)
public Object handleMethodArgumentNotValidException(MethodArgumentNotValidException e)
{
log.error(e.getMessage(), e);
String message = e.getBindingResult().getFieldError().getDefaultMessage();
@ -122,7 +119,7 @@ public class GlobalExceptionHandler
* 演示模式异常
*/
@ExceptionHandler(DemoModeException.class)
public AjaxResult demoModeException(DemoModeException e)
public AjaxResult handleDemoModeException(DemoModeException e)
{
return AjaxResult.error("演示模式,不允许操作");
}

View File

@ -1,5 +1,6 @@
package com.ruoyi.framework.web.service;
import com.ruoyi.common.utils.StringUtils;
import cn.hutool.http.useragent.UserAgent;
import cn.hutool.http.useragent.UserAgentUtil;
import com.ruoyi.common.constant.Constants;
@ -67,7 +68,7 @@ public class AsyncService {
logininfor.setOs(os);
logininfor.setMsg(message);
// 日志状态
if (Constants.LOGIN_SUCCESS.equals(status) || Constants.LOGOUT.equals(status)) {
if (StringUtils.equalsAny(status, Constants.LOGIN_SUCCESS, Constants.LOGOUT, Constants.REGISTER)) {
logininfor.setStatus(Constants.SUCCESS);
} else if (Constants.LOGIN_FAIL.equals(status)) {
logininfor.setStatus(Constants.FAIL);

View File

@ -1,18 +1,18 @@
package com.ruoyi.framework.web.service;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.StrUtil;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.utils.ServletUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.util.Set;
/**
* RuoYi首创 自定义权限实现ss取自SpringSecurity首字母
*
*
* @author ruoyi
*/
@Service("ss")
@ -33,18 +33,18 @@ public class PermissionService
/**
* 验证用户是否具备某权限
*
*
* @param permission 权限字符串
* @return 用户是否具备某权限
*/
public boolean hasPermi(String permission)
{
if (Validator.isEmpty(permission))
if (StringUtils.isEmpty(permission))
{
return false;
}
LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
if (Validator.isNull(loginUser) || Validator.isEmpty(loginUser.getPermissions()))
if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getPermissions()))
{
return false;
}
@ -70,12 +70,12 @@ public class PermissionService
*/
public boolean hasAnyPermi(String permissions)
{
if (Validator.isEmpty(permissions))
if (StringUtils.isEmpty(permissions))
{
return false;
}
LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
if (Validator.isNull(loginUser) || Validator.isEmpty(loginUser.getPermissions()))
if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getPermissions()))
{
return false;
}
@ -92,25 +92,25 @@ public class PermissionService
/**
* 判断用户是否拥有某个角色
*
*
* @param role 角色字符串
* @return 用户是否具备某角色
*/
public boolean hasRole(String role)
{
if (Validator.isEmpty(role))
if (StringUtils.isEmpty(role))
{
return false;
}
LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
if (Validator.isNull(loginUser) || Validator.isEmpty(loginUser.getUser().getRoles()))
if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getUser().getRoles()))
{
return false;
}
for (SysRole sysRole : loginUser.getUser().getRoles())
{
String roleKey = sysRole.getRoleKey();
if (SUPER_ADMIN.equals(roleKey) || roleKey.equals(StrUtil.trim(role)))
if (SUPER_ADMIN.equals(roleKey) || roleKey.equals(StringUtils.trim(role)))
{
return true;
}
@ -137,12 +137,12 @@ public class PermissionService
*/
public boolean hasAnyRoles(String roles)
{
if (Validator.isEmpty(roles))
if (StringUtils.isEmpty(roles))
{
return false;
}
LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
if (Validator.isNull(loginUser) || Validator.isEmpty(loginUser.getUser().getRoles()))
if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getUser().getRoles()))
{
return false;
}
@ -158,13 +158,13 @@ public class PermissionService
/**
* 判断是否包含权限
*
*
* @param permissions 权限列表
* @param permission 权限字符串
* @return 用户是否具备某权限
*/
private boolean hasPermissions(Set<String> permissions, String permission)
{
return permissions.contains(ALL_PERMISSION) || permissions.contains(StrUtil.trim(permission));
return permissions.contains(ALL_PERMISSION) || permissions.contains(StringUtils.trim(permission));
}
}

View File

@ -4,7 +4,7 @@ import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.exception.CustomException;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.exception.user.CaptchaException;
import com.ruoyi.common.exception.user.CaptchaExpireException;
import com.ruoyi.common.exception.user.UserPasswordNotMatchException;
@ -85,7 +85,7 @@ public class SysLoginService
else
{
asyncService.recordLogininfor(username, Constants.LOGIN_FAIL, e.getMessage(), request);
throw new CustomException(e.getMessage());
throw new ServiceException(e.getMessage());
}
}
asyncService.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"), request);

View File

@ -0,0 +1,117 @@
package com.ruoyi.framework.web.service;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.RegisterBody;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.exception.user.CaptchaException;
import com.ruoyi.common.exception.user.CaptchaExpireException;
import com.ruoyi.common.utils.MessageUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.service.ISysConfigService;
import com.ruoyi.system.service.ISysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* 注册校验方法
*
* @author ruoyi
*/
@Component
public class SysRegisterService
{
@Autowired
private ISysUserService userService;
@Autowired
private ISysConfigService configService;
@Autowired
private RedisCache redisCache;
@Autowired
private AsyncService asyncService;
/**
* 注册
*/
public String register(RegisterBody registerBody)
{
String msg = "", username = registerBody.getUsername(), password = registerBody.getPassword();
boolean captchaOnOff = configService.selectCaptchaOnOff();
// 验证码开关
if (captchaOnOff)
{
validateCaptcha(username, registerBody.getCode(), registerBody.getUuid());
}
if (StringUtils.isEmpty(username))
{
msg = "用户名不能为空";
}
else if (StringUtils.isEmpty(password))
{
msg = "用户密码不能为空";
}
else if (username.length() < UserConstants.USERNAME_MIN_LENGTH
|| username.length() > UserConstants.USERNAME_MAX_LENGTH)
{
msg = "账户长度必须在2到20个字符之间";
}
else if (password.length() < UserConstants.PASSWORD_MIN_LENGTH
|| password.length() > UserConstants.PASSWORD_MAX_LENGTH)
{
msg = "密码长度必须在5到20个字符之间";
}
else if (UserConstants.NOT_UNIQUE.equals(userService.checkUserNameUnique(username)))
{
msg = "保存用户'" + username + "'失败,注册账号已存在";
}
else
{
SysUser sysUser = new SysUser();
sysUser.setUserName(username);
sysUser.setNickName(username);
sysUser.setPassword(SecurityUtils.encryptPassword(registerBody.getPassword()));
boolean regFlag = userService.registerUser(sysUser);
if (!regFlag)
{
msg = "注册失败,请联系系统管理人员";
}
else
{
asyncService.recordLogininfor(username, Constants.REGISTER,
MessageUtils.message("user.register.success"), ServletUtils.getRequest());
}
}
return msg;
}
/**
* 校验验证码
*
* @param username 用户名
* @param code 验证码
* @param uuid 唯一标识
* @return 结果
*/
public void validateCaptcha(String username, String code, String uuid)
{
String verifyKey = Constants.CAPTCHA_CODE_KEY + uuid;
String captcha = redisCache.getCacheObject(verifyKey);
redisCache.deleteObject(verifyKey);
if (captcha == null)
{
throw new CaptchaExpireException();
}
if (!code.equalsIgnoreCase(captcha))
{
throw new CaptchaException();
}
}
}

View File

@ -1,6 +1,5 @@
package com.ruoyi.framework.web.service;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.IdUtil;
import cn.hutool.http.useragent.UserAgent;
import cn.hutool.http.useragent.UserAgentUtil;
@ -8,6 +7,7 @@ import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.ip.AddressUtils;
import com.ruoyi.framework.config.properties.TokenProperties;
import io.jsonwebtoken.Claims;
@ -49,13 +49,17 @@ public class TokenService {
public LoginUser getLoginUser(HttpServletRequest request) {
// 获取请求携带的令牌
String token = getToken(request);
if (Validator.isNotEmpty(token)) {
Claims claims = parseToken(token);
// 解析对应的权限以及用户信息
String uuid = (String) claims.get(Constants.LOGIN_USER_KEY);
String userKey = getTokenKey(uuid);
LoginUser user = redisCache.getCacheObject(userKey);
return user;
if (StringUtils.isNotEmpty(token)) {
try {
Claims claims = parseToken(token);
// 解析对应的权限以及用户信息
String uuid = (String) claims.get(Constants.LOGIN_USER_KEY);
String userKey = getTokenKey(uuid);
LoginUser user = redisCache.getCacheObject(userKey);
return user;
} catch (Exception e) {
}
}
return null;
}
@ -64,7 +68,7 @@ public class TokenService {
* 设置用户身份信息
*/
public void setLoginUser(LoginUser loginUser) {
if (Validator.isNotNull(loginUser) && Validator.isNotEmpty(loginUser.getToken())) {
if (StringUtils.isNotNull(loginUser) && StringUtils.isNotEmpty(loginUser.getToken())) {
refreshToken(loginUser);
}
}
@ -73,7 +77,7 @@ public class TokenService {
* 删除用户身份信息
*/
public void delLoginUser(String token) {
if (Validator.isNotEmpty(token)) {
if (StringUtils.isNotEmpty(token)) {
String userKey = getTokenKey(token);
redisCache.deleteObject(userKey);
}
@ -182,7 +186,7 @@ public class TokenService {
*/
private String getToken(HttpServletRequest request) {
String token = request.getHeader(tokenProperties.getHeader());
if (Validator.isNotEmpty(token) && token.startsWith(Constants.TOKEN_PREFIX)) {
if (StringUtils.isNotEmpty(token) && token.startsWith(Constants.TOKEN_PREFIX)) {
token = token.replace(Constants.TOKEN_PREFIX, "");
}
return token;

View File

@ -1,11 +1,5 @@
package com.ruoyi.framework.web.service;
import cn.hutool.core.lang.Validator;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.enums.UserStatus;
import com.ruoyi.common.exception.BaseException;
import com.ruoyi.system.service.ISysUserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@ -13,6 +7,12 @@ import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.enums.UserStatus;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.service.ISysUserService;
/**
* 用户验证处理
@ -34,20 +34,20 @@ public class UserDetailsServiceImpl implements UserDetailsService
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException
{
SysUser user = userService.selectUserByUserName(username);
if (Validator.isNull(user))
if (StringUtils.isNull(user))
{
log.info("登录用户:{} 不存在.", username);
throw new UsernameNotFoundException("登录用户:" + username + " 不存在");
throw new ServiceException("登录用户:" + username + " 不存在");
}
else if (UserStatus.DELETED.getCode().equals(user.getDelFlag()))
{
log.info("登录用户:{} 已被删除.", username);
throw new BaseException("对不起,您的账号:" + username + " 已被删除");
throw new ServiceException("对不起,您的账号:" + username + " 已被删除");
}
else if (UserStatus.DISABLE.getCode().equals(user.getStatus()))
{
log.info("登录用户:{} 已被停用.", username);
throw new BaseException("对不起,您的账号:" + username + " 已停用");
throw new ServiceException("对不起,您的账号:" + username + " 已停用");
}
return createLoginUser(user);
@ -55,6 +55,6 @@ public class UserDetailsServiceImpl implements UserDetailsService
public UserDetails createLoginUser(SysUser user)
{
return new LoginUser(user, permissionService.getMenuPermission(user));
return new LoginUser(user.getUserId(), user.getDeptId(), user, permissionService.getMenuPermission(user));
}
}

View File

@ -1,6 +1,6 @@
package com.ruoyi.generator.domain;
import cn.hutool.core.util.StrUtil;
import com.ruoyi.common.utils.StringUtils;
import com.baomidou.mybatisplus.annotation.*;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.common.constant.GenConstants;
@ -204,7 +204,7 @@ public class GenTable implements Serializable {
}
public static boolean isSub(String tplCategory) {
return tplCategory != null && StrUtil.equals(GenConstants.TPL_SUB, tplCategory);
return tplCategory != null && StringUtils.equals(GenConstants.TPL_SUB, tplCategory);
}
public boolean isTree() {
@ -212,7 +212,7 @@ public class GenTable implements Serializable {
}
public static boolean isTree(String tplCategory) {
return tplCategory != null && StrUtil.equals(GenConstants.TPL_TREE, tplCategory);
return tplCategory != null && StringUtils.equals(GenConstants.TPL_TREE, tplCategory);
}
public boolean isCrud() {
@ -220,7 +220,7 @@ public class GenTable implements Serializable {
}
public static boolean isCrud(String tplCategory) {
return tplCategory != null && StrUtil.equals(GenConstants.TPL_CRUD, tplCategory);
return tplCategory != null && StringUtils.equals(GenConstants.TPL_CRUD, tplCategory);
}
public boolean isSuperColumn(String javaField) {
@ -229,9 +229,9 @@ public class GenTable implements Serializable {
public static boolean isSuperColumn(String tplCategory, String javaField) {
if (isTree(tplCategory)) {
return StrUtil.equalsAnyIgnoreCase(javaField,
return StringUtils.equalsAnyIgnoreCase(javaField,
ArrayUtils.addAll(GenConstants.TREE_ENTITY, GenConstants.BASE_ENTITY));
}
return StrUtil.equalsAnyIgnoreCase(javaField, GenConstants.BASE_ENTITY);
return StringUtils.equalsAnyIgnoreCase(javaField, GenConstants.BASE_ENTITY);
}
}
}

View File

@ -1,6 +1,6 @@
package com.ruoyi.generator.domain;
import cn.hutool.core.util.StrUtil;
import com.ruoyi.common.utils.StringUtils;
import com.baomidou.mybatisplus.annotation.*;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.*;
@ -150,7 +150,7 @@ public class GenTableColumn implements Serializable {
private Map<String, Object> params = new HashMap<>();
public String getCapJavaField() {
return StrUtil.upperFirst(javaField);
return StringUtils.uncapitalize(javaField);
}
public boolean isPk() {
@ -158,7 +158,7 @@ public class GenTableColumn implements Serializable {
}
public boolean isPk(String isPk) {
return isPk != null && StrUtil.equals("1", isPk);
return isPk != null && StringUtils.equals("1", isPk);
}
public boolean isIncrement() {
@ -166,7 +166,7 @@ public class GenTableColumn implements Serializable {
}
public boolean isIncrement(String isIncrement) {
return isIncrement != null && StrUtil.equals("1", isIncrement);
return isIncrement != null && StringUtils.equals("1", isIncrement);
}
public boolean isRequired() {
@ -174,7 +174,7 @@ public class GenTableColumn implements Serializable {
}
public boolean isRequired(String isRequired) {
return isRequired != null && StrUtil.equals("1", isRequired);
return isRequired != null && StringUtils.equals("1", isRequired);
}
public boolean isInsert() {
@ -182,7 +182,7 @@ public class GenTableColumn implements Serializable {
}
public boolean isInsert(String isInsert) {
return isInsert != null && StrUtil.equals("1", isInsert);
return isInsert != null && StringUtils.equals("1", isInsert);
}
public boolean isEdit() {
@ -190,7 +190,7 @@ public class GenTableColumn implements Serializable {
}
public boolean isEdit(String isEdit) {
return isEdit != null && StrUtil.equals("1", isEdit);
return isEdit != null && StringUtils.equals("1", isEdit);
}
public boolean isList() {
@ -198,7 +198,7 @@ public class GenTableColumn implements Serializable {
}
public boolean isList(String isList) {
return isList != null && StrUtil.equals("1", isList);
return isList != null && StringUtils.equals("1", isList);
}
public boolean isQuery() {
@ -206,7 +206,7 @@ public class GenTableColumn implements Serializable {
}
public boolean isQuery(String isQuery) {
return isQuery != null && StrUtil.equals("1", isQuery);
return isQuery != null && StringUtils.equals("1", isQuery);
}
public boolean isSuperColumn() {
@ -214,7 +214,7 @@ public class GenTableColumn implements Serializable {
}
public static boolean isSuperColumn(String javaField) {
return StrUtil.equalsAnyIgnoreCase(javaField,
return StringUtils.equalsAnyIgnoreCase(javaField,
// BaseEntity
"createBy", "createTime", "updateBy", "updateTime", "remark",
// TreeEntity
@ -227,15 +227,15 @@ public class GenTableColumn implements Serializable {
public static boolean isUsableColumn(String javaField) {
// isSuperColumn()中的名单用于避免生成多余Domain属性若某些属性在生成页面时需要用到不能忽略则放在此处白名单
return StrUtil.equalsAnyIgnoreCase(javaField, "parentId", "orderNum", "remark");
return StringUtils.equalsAnyIgnoreCase(javaField, "parentId", "orderNum", "remark");
}
public String readConverterExp() {
String remarks = StrUtil.subBetween(this.columnComment, "", "");
String remarks = StringUtils.substringBetween(this.columnComment, "", "");
StringBuffer sb = new StringBuffer();
if (StrUtil.isNotEmpty(remarks)) {
if (StringUtils.isNotEmpty(remarks)) {
for (String value : remarks.split(" ")) {
if (StrUtil.isNotEmpty(value)) {
if (StringUtils.isNotEmpty(value)) {
Object startStr = value.subSequence(0, 1);
String endStr = value.substring(1);
sb.append("").append(startStr).append("=").append(endStr).append(",");

View File

@ -2,15 +2,14 @@ package com.ruoyi.generator.service;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.StrUtil;
import com.ruoyi.common.utils.StringUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.constant.GenConstants;
import com.ruoyi.common.core.mybatisplus.core.ServicePlusImpl;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.exception.CustomException;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.JsonUtils;
import com.ruoyi.common.utils.PageUtils;
import com.ruoyi.common.utils.SecurityUtils;
@ -137,15 +136,15 @@ public class GenTableServiceImpl extends ServicePlusImpl<GenTableMapper, GenTabl
for (GenTableColumn cenTableColumn : genTable.getColumns()) {
genTableColumnMapper.update(cenTableColumn,
new LambdaUpdateWrapper<GenTableColumn>()
.set(StrUtil.isBlank(cenTableColumn.getColumnComment()), GenTableColumn::getColumnComment, null)
.set(StrUtil.isBlank(cenTableColumn.getIsPk()), GenTableColumn::getIsPk, null)
.set(StrUtil.isBlank(cenTableColumn.getIsIncrement()), GenTableColumn::getIsIncrement, null)
.set(StrUtil.isBlank(cenTableColumn.getIsInsert()), GenTableColumn::getIsInsert, null)
.set(StrUtil.isBlank(cenTableColumn.getIsEdit()), GenTableColumn::getIsEdit, null)
.set(StrUtil.isBlank(cenTableColumn.getIsList()), GenTableColumn::getIsList, null)
.set(StrUtil.isBlank(cenTableColumn.getIsQuery()), GenTableColumn::getIsQuery, null)
.set(StrUtil.isBlank(cenTableColumn.getIsRequired()), GenTableColumn::getIsRequired, null)
.set(StrUtil.isBlank(cenTableColumn.getDictType()), GenTableColumn::getDictType, "")
.set(StringUtils.isBlank(cenTableColumn.getColumnComment()), GenTableColumn::getColumnComment, null)
.set(StringUtils.isBlank(cenTableColumn.getIsPk()), GenTableColumn::getIsPk, null)
.set(StringUtils.isBlank(cenTableColumn.getIsIncrement()), GenTableColumn::getIsIncrement, null)
.set(StringUtils.isBlank(cenTableColumn.getIsInsert()), GenTableColumn::getIsInsert, null)
.set(StringUtils.isBlank(cenTableColumn.getIsEdit()), GenTableColumn::getIsEdit, null)
.set(StringUtils.isBlank(cenTableColumn.getIsList()), GenTableColumn::getIsList, null)
.set(StringUtils.isBlank(cenTableColumn.getIsQuery()), GenTableColumn::getIsQuery, null)
.set(StringUtils.isBlank(cenTableColumn.getIsRequired()), GenTableColumn::getIsRequired, null)
.set(StringUtils.isBlank(cenTableColumn.getDictType()), GenTableColumn::getDictType, "")
.eq(GenTableColumn::getColumnId,cenTableColumn.getColumnId()));
}
}
@ -189,7 +188,7 @@ public class GenTableServiceImpl extends ServicePlusImpl<GenTableMapper, GenTabl
}
}
} catch (Exception e) {
throw new CustomException("导入失败:" + e.getMessage());
throw new ServiceException("导入失败:" + e.getMessage());
}
}
@ -260,13 +259,17 @@ public class GenTableServiceImpl extends ServicePlusImpl<GenTableMapper, GenTabl
// 获取模板列表
List<String> templates = VelocityUtils.getTemplateList(table.getTplCategory());
for (String template : templates) {
if (!StrUtil.containsAny("sql.vm", "api.js.vm", "index.vue.vm", "index-tree.vue.vm", template)) {
if (!StringUtils.containsAny(template, "sql.vm", "api.js.vm", "index.vue.vm", "index-tree.vue.vm")) {
// 渲染模板
StringWriter sw = new StringWriter();
Template tpl = Velocity.getTemplate(template, Constants.UTF8);
tpl.merge(context, sw);
String path = getGenPath(table, template);
FileUtils.writeUtf8String(sw.toString(), path);
try {
String path = getGenPath(table, template);
FileUtils.writeUtf8String(sw.toString(), path);
} catch (Exception e) {
throw new ServiceException("渲染模板失败,表名:" + table.getTableName());
}
}
}
}
@ -284,8 +287,8 @@ public class GenTableServiceImpl extends ServicePlusImpl<GenTableMapper, GenTabl
List<String> tableColumnNames = tableColumns.stream().map(GenTableColumn::getColumnName).collect(Collectors.toList());
List<GenTableColumn> dbTableColumns = genTableColumnMapper.selectDbTableColumnsByName(tableName);
if (Validator.isEmpty(dbTableColumns)) {
throw new CustomException("同步数据失败,原表结构不存在");
if (StringUtils.isEmpty(dbTableColumns)) {
throw new ServiceException("同步数据失败,原表结构不存在");
}
List<String> dbTableColumnNames = dbTableColumns.stream().map(GenTableColumn::getColumnName).collect(Collectors.toList());
@ -364,17 +367,17 @@ public class GenTableServiceImpl extends ServicePlusImpl<GenTableMapper, GenTabl
public void validateEdit(GenTable genTable) {
if (GenConstants.TPL_TREE.equals(genTable.getTplCategory())) {
Map<String, Object> paramsObj = genTable.getParams();
if (Validator.isEmpty(paramsObj.get(GenConstants.TREE_CODE))) {
throw new CustomException("树编码字段不能为空");
} else if (Validator.isEmpty(paramsObj.get(GenConstants.TREE_PARENT_CODE))) {
throw new CustomException("树父编码字段不能为空");
} else if (Validator.isEmpty(paramsObj.get(GenConstants.TREE_NAME))) {
throw new CustomException("树名称字段不能为空");
if (StringUtils.isEmpty(paramsObj.get(GenConstants.TREE_CODE))) {
throw new ServiceException("树编码字段不能为空");
} else if (StringUtils.isEmpty(paramsObj.get(GenConstants.TREE_PARENT_CODE))) {
throw new ServiceException("树父编码字段不能为空");
} else if (StringUtils.isEmpty(paramsObj.get(GenConstants.TREE_NAME))) {
throw new ServiceException("树名称字段不能为空");
} else if (GenConstants.TPL_SUB.equals(genTable.getTplCategory())) {
if (Validator.isEmpty(genTable.getSubTableName())) {
throw new CustomException("关联子表的表名不能为空");
} else if (Validator.isEmpty(genTable.getSubTableFkName())) {
throw new CustomException("子表关联的外键名不能为空");
if (StringUtils.isEmpty(genTable.getSubTableName())) {
throw new ServiceException("关联子表的表名不能为空");
} else if (StringUtils.isEmpty(genTable.getSubTableFkName())) {
throw new ServiceException("子表关联的外键名不能为空");
}
}
}
@ -392,7 +395,7 @@ public class GenTableServiceImpl extends ServicePlusImpl<GenTableMapper, GenTabl
break;
}
}
if (Validator.isNull(table.getPkColumn())) {
if (StringUtils.isNull(table.getPkColumn())) {
table.setPkColumn(table.getColumns().get(0));
}
if (GenConstants.TPL_SUB.equals(table.getTplCategory())) {
@ -402,7 +405,7 @@ public class GenTableServiceImpl extends ServicePlusImpl<GenTableMapper, GenTabl
break;
}
}
if (Validator.isNull(table.getSubTable().getPkColumn())) {
if (StringUtils.isNull(table.getSubTable().getPkColumn())) {
table.getSubTable().setPkColumn(table.getSubTable().getColumns().get(0));
}
}
@ -415,7 +418,7 @@ public class GenTableServiceImpl extends ServicePlusImpl<GenTableMapper, GenTabl
*/
public void setSubTable(GenTable table) {
String subTableName = table.getSubTableName();
if (Validator.isNotEmpty(subTableName)) {
if (StringUtils.isNotEmpty(subTableName)) {
table.setSubTable(baseMapper.selectGenTableByName(subTableName));
}
}
@ -427,7 +430,7 @@ public class GenTableServiceImpl extends ServicePlusImpl<GenTableMapper, GenTabl
*/
public void setTableFromOptions(GenTable genTable) {
Map<String, Object> paramsObj = JsonUtils.parseMap(genTable.getOptions());
if (Validator.isNotNull(paramsObj)) {
if (StringUtils.isNotNull(paramsObj)) {
String treeCode = Convert.toStr(paramsObj.get(GenConstants.TREE_CODE));
String treeParentCode = Convert.toStr(paramsObj.get(GenConstants.TREE_PARENT_CODE));
String treeName = Convert.toStr(paramsObj.get(GenConstants.TREE_NAME));
@ -451,7 +454,7 @@ public class GenTableServiceImpl extends ServicePlusImpl<GenTableMapper, GenTabl
*/
public static String getGenPath(GenTable table, String template) {
String genPath = table.getGenPath();
if (StrUtil.equals(genPath, "/")) {
if (StringUtils.equals(genPath, "/")) {
return System.getProperty("user.dir") + File.separator + "src" + File.separator + VelocityUtils.getFileName(template, table);
}
return genPath + File.separator + VelocityUtils.getFileName(template, table);

View File

@ -1,6 +1,6 @@
package com.ruoyi.generator.util;
import cn.hutool.core.util.StrUtil;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.constant.GenConstants;
import com.ruoyi.generator.config.GenConfig;
import com.ruoyi.generator.domain.GenTable;
@ -40,7 +40,7 @@ public class GenUtils
column.setTableId(table.getTableId());
column.setCreateBy(table.getCreateBy());
// 设置java字段名
column.setJavaField(StrUtil.toCamelCase(columnName));
column.setJavaField(StringUtils.toCamelCase(columnName));
// 设置默认类型
column.setJavaType(GenConstants.TYPE_STRING);
@ -61,7 +61,7 @@ public class GenUtils
column.setHtmlType(GenConstants.HTML_INPUT);
// 如果是浮点型 统一用BigDecimal
String[] str = StrUtil.splitToArray(StrUtil.subBetween(column.getColumnType(), "(", ")"), ",");
String[] str = StringUtils.split(StringUtils.substringBetween(column.getColumnType(), "(", ")"), ",");
if (str != null && str.length == 2 && Integer.parseInt(str[1]) > 0)
{
column.setJavaType(GenConstants.TYPE_BIGDECIMAL);
@ -98,33 +98,33 @@ public class GenUtils
}
// 查询字段类型
if (StrUtil.endWithIgnoreCase(columnName, "name"))
if (StringUtils.endsWithIgnoreCase(columnName, "name"))
{
column.setQueryType(GenConstants.QUERY_LIKE);
}
// 状态字段设置单选框
if (StrUtil.endWithIgnoreCase(columnName, "status"))
if (StringUtils.endsWithIgnoreCase(columnName, "status"))
{
column.setHtmlType(GenConstants.HTML_RADIO);
}
// 类型&性别字段设置下拉框
else if (StrUtil.endWithIgnoreCase(columnName, "type")
|| StrUtil.endWithIgnoreCase(columnName, "sex"))
else if (StringUtils.endsWithIgnoreCase(columnName, "type")
|| StringUtils.endsWithIgnoreCase(columnName, "sex"))
{
column.setHtmlType(GenConstants.HTML_SELECT);
}
// 图片字段设置图片上传控件
else if (StrUtil.endWithIgnoreCase(columnName, "image"))
else if (StringUtils.endsWithIgnoreCase(columnName, "image"))
{
column.setHtmlType(GenConstants.HTML_IMAGE_UPLOAD);
}
// 文件字段设置文件上传控件
else if (StrUtil.endWithIgnoreCase(columnName, "file"))
else if (StringUtils.endsWithIgnoreCase(columnName, "file"))
{
column.setHtmlType(GenConstants.HTML_FILE_UPLOAD);
}
// 内容字段设置富文本控件
else if (StrUtil.endWithIgnoreCase(columnName, "content"))
else if (StringUtils.endsWithIgnoreCase(columnName, "content"))
{
column.setHtmlType(GenConstants.HTML_EDITOR);
}
@ -152,7 +152,7 @@ public class GenUtils
{
int lastIndex = packageName.lastIndexOf(".");
int nameLength = packageName.length();
String moduleName = StrUtil.sub(packageName, lastIndex + 1, nameLength);
String moduleName = StringUtils.substring(packageName, lastIndex + 1, nameLength);
return moduleName;
}
@ -166,7 +166,7 @@ public class GenUtils
{
int lastIndex = tableName.lastIndexOf("_");
int nameLength = tableName.length();
String businessName = StrUtil.sub(tableName, lastIndex + 1, nameLength);
String businessName = StringUtils.substring(tableName, lastIndex + 1, nameLength);
return businessName;
}
@ -180,12 +180,12 @@ public class GenUtils
{
boolean autoRemovePre = GenConfig.getAutoRemovePre();
String tablePrefix = GenConfig.getTablePrefix();
if (autoRemovePre && StrUtil.isNotEmpty(tablePrefix))
if (autoRemovePre && StringUtils.isNotEmpty(tablePrefix))
{
String[] searchList = StrUtil.splitToArray(tablePrefix, ",");
String[] searchList = StringUtils.split(tablePrefix, ",");
tableName = replaceFirst(tableName, searchList);
}
return StrUtil.upperFirst(StrUtil.toCamelCase(tableName));
return StringUtils.convertToCamelCase(tableName);
}
/**
@ -228,9 +228,9 @@ public class GenUtils
*/
public static String getDbType(String columnType)
{
if (StrUtil.indexOf(columnType, '(') > 0)
if (StringUtils.indexOf(columnType, '(') > 0)
{
return StrUtil.subBefore(columnType, "(",false);
return StringUtils.substringBefore(columnType, "(");
}
else
{
@ -246,9 +246,9 @@ public class GenUtils
*/
public static Integer getColumnLength(String columnType)
{
if (StrUtil.indexOf(columnType, '(') > 0)
if (StringUtils.indexOf(columnType, '(') > 0)
{
String length = StrUtil.subBetween(columnType, "(", ")");
String length = StringUtils.substringBetween(columnType, "(", ")");
return Integer.valueOf(length);
}
else

View File

@ -1,11 +1,10 @@
package com.ruoyi.generator.util;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.StrUtil;
import com.ruoyi.common.constant.GenConstants;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.JsonUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.generator.domain.GenTable;
import com.ruoyi.generator.domain.GenTableColumn;
import org.apache.velocity.VelocityContext;
@ -47,11 +46,11 @@ public class VelocityUtils
VelocityContext velocityContext = new VelocityContext();
velocityContext.put("tplCategory", genTable.getTplCategory());
velocityContext.put("tableName", genTable.getTableName());
velocityContext.put("functionName", StrUtil.isNotEmpty(functionName) ? functionName : "【请填写功能名称】");
velocityContext.put("functionName", StringUtils.isNotEmpty(functionName) ? functionName : "【请填写功能名称】");
velocityContext.put("ClassName", genTable.getClassName());
velocityContext.put("className", StrUtil.lowerFirst(genTable.getClassName()));
velocityContext.put("className", StringUtils.uncapitalize(genTable.getClassName()));
velocityContext.put("moduleName", genTable.getModuleName());
velocityContext.put("BusinessName", StrUtil.upperFirst(genTable.getBusinessName()));
velocityContext.put("BusinessName", StringUtils.capitalize(genTable.getBusinessName()));
velocityContext.put("businessName", genTable.getBusinessName());
velocityContext.put("basePackage", getPackagePrefix(packageName));
velocityContext.put("packageName", packageName);
@ -110,15 +109,15 @@ public class VelocityUtils
String subTableName = genTable.getSubTableName();
String subTableFkName = genTable.getSubTableFkName();
String subClassName = genTable.getSubTable().getClassName();
String subTableFkClassName = StrUtil.toCamelCase(subTableFkName);
String subTableFkClassName = StringUtils.convertToCamelCase(subTableFkName);
context.put("subTable", subTable);
context.put("subTableName", subTableName);
context.put("subTableFkName", subTableFkName);
context.put("subTableFkClassName", subTableFkClassName);
context.put("subTableFkclassName", StrUtil.lowerFirst(subTableFkClassName));
context.put("subTableFkclassName", StringUtils.uncapitalize(subTableFkClassName));
context.put("subClassName", subClassName);
context.put("subclassName", StrUtil.lowerFirst(subClassName));
context.put("subclassName", StringUtils.uncapitalize(subClassName));
context.put("subImportList", getImportList(genTable.getSubTable()));
}
@ -172,45 +171,45 @@ public class VelocityUtils
// 业务名称
String businessName = genTable.getBusinessName();
String javaPath = PROJECT_PATH + "/" + StrUtil.replace(packageName, ".", "/");
String javaPath = PROJECT_PATH + "/" + StringUtils.replace(packageName, ".", "/");
String mybatisPath = MYBATIS_PATH + "/" + moduleName;
String vuePath = "vue";
if (template.contains("domain.java.vm"))
{
fileName = StrUtil.format("{}/domain/{}.java", javaPath, className);
fileName = StringUtils.format("{}/domain/{}.java", javaPath, className);
}
if (template.contains("vo.java.vm"))
{
fileName = StrUtil.format("{}/domain/vo/{}Vo.java", javaPath, className);
fileName = StringUtils.format("{}/domain/vo/{}Vo.java", javaPath, className);
}
if (template.contains("bo.java.vm"))
{
fileName = StrUtil.format("{}/domain/bo/{}Bo.java", javaPath, className);
fileName = StringUtils.format("{}/domain/bo/{}Bo.java", javaPath, className);
}
if (template.contains("sub-domain.java.vm") && StrUtil.equals(GenConstants.TPL_SUB, genTable.getTplCategory()))
if (template.contains("sub-domain.java.vm") && StringUtils.equals(GenConstants.TPL_SUB, genTable.getTplCategory()))
{
fileName = StrUtil.format("{}/domain/{}.java", javaPath, genTable.getSubTable().getClassName());
fileName = StringUtils.format("{}/domain/{}.java", javaPath, genTable.getSubTable().getClassName());
}
else if (template.contains("mapper.java.vm"))
{
fileName = StrUtil.format("{}/mapper/{}Mapper.java", javaPath, className);
fileName = StringUtils.format("{}/mapper/{}Mapper.java", javaPath, className);
}
else if (template.contains("service.java.vm"))
{
fileName = StrUtil.format("{}/service/I{}Service.java", javaPath, className);
fileName = StringUtils.format("{}/service/I{}Service.java", javaPath, className);
}
else if (template.contains("serviceImpl.java.vm"))
{
fileName = StrUtil.format("{}/service/impl/{}ServiceImpl.java", javaPath, className);
fileName = StringUtils.format("{}/service/impl/{}ServiceImpl.java", javaPath, className);
}
else if (template.contains("controller.java.vm"))
{
fileName = StrUtil.format("{}/controller/{}Controller.java", javaPath, className);
fileName = StringUtils.format("{}/controller/{}Controller.java", javaPath, className);
}
else if (template.contains("mapper.xml.vm"))
{
fileName = StrUtil.format("{}/{}Mapper.xml", mybatisPath, className);
fileName = StringUtils.format("{}/{}Mapper.xml", mybatisPath, className);
}
else if (template.contains("sql.vm"))
{
@ -218,15 +217,15 @@ public class VelocityUtils
}
else if (template.contains("api.js.vm"))
{
fileName = StrUtil.format("{}/api/{}/{}.js", vuePath, moduleName, businessName);
fileName = StringUtils.format("{}/api/{}/{}.js", vuePath, moduleName, businessName);
}
else if (template.contains("index.vue.vm"))
{
fileName = StrUtil.format("{}/views/{}/{}/index.vue", vuePath, moduleName, businessName);
fileName = StringUtils.format("{}/views/{}/{}/index.vue", vuePath, moduleName, businessName);
}
else if (template.contains("index-tree.vue.vm"))
{
fileName = StrUtil.format("{}/views/{}/{}/index.vue", vuePath, moduleName, businessName);
fileName = StringUtils.format("{}/views/{}/{}/index.vue", vuePath, moduleName, businessName);
}
return fileName;
}
@ -240,7 +239,7 @@ public class VelocityUtils
public static String getPackagePrefix(String packageName)
{
int lastIndex = packageName.lastIndexOf(".");
String basePackage = StrUtil.sub(packageName, 0, lastIndex);
String basePackage = StringUtils.substring(packageName, 0, lastIndex);
return basePackage;
}
@ -255,7 +254,7 @@ public class VelocityUtils
List<GenTableColumn> columns = genTable.getColumns();
GenTable subGenTable = genTable.getSubTable();
HashSet<String> importList = new HashSet<String>();
if (Validator.isNotNull(subGenTable))
if (StringUtils.isNotNull(subGenTable))
{
importList.add("java.util.List");
}
@ -283,7 +282,7 @@ public class VelocityUtils
*/
public static String getPermissionPrefix(String moduleName, String businessName)
{
return StrUtil.format("{}:{}", moduleName, businessName);
return StringUtils.format("{}:{}", moduleName, businessName);
}
/**
@ -294,7 +293,8 @@ public class VelocityUtils
*/
public static String getParentMenuId(Map<String, Object> paramsObj)
{
if (Validator.isNotEmpty(paramsObj) && paramsObj.containsKey(GenConstants.PARENT_MENU_ID))
if (StringUtils.isNotEmpty(paramsObj) && paramsObj.containsKey(GenConstants.PARENT_MENU_ID)
&& StringUtils.isNotEmpty(Convert.toStr(paramsObj.get(GenConstants.PARENT_MENU_ID))))
{
return Convert.toStr(paramsObj.get(GenConstants.PARENT_MENU_ID));
}
@ -309,11 +309,11 @@ public class VelocityUtils
*/
public static String getTreecode(Map<String, Object> paramsObj)
{
if (Validator.isNotEmpty(paramsObj) && paramsObj.containsKey(GenConstants.TREE_CODE))
if (StringUtils.isNotEmpty(paramsObj) && paramsObj.containsKey(GenConstants.TREE_CODE))
{
return StrUtil.toCamelCase(Convert.toStr(paramsObj.get(GenConstants.TREE_CODE)));
return StringUtils.toCamelCase(Convert.toStr(paramsObj.get(GenConstants.TREE_CODE)));
}
return StrUtil.EMPTY;
return StringUtils.EMPTY;
}
/**
@ -324,11 +324,11 @@ public class VelocityUtils
*/
public static String getTreeParentCode(Map<String, Object> paramsObj)
{
if (Validator.isNotEmpty(paramsObj) && paramsObj.containsKey(GenConstants.TREE_PARENT_CODE))
if (StringUtils.isNotEmpty(paramsObj) && paramsObj.containsKey(GenConstants.TREE_PARENT_CODE))
{
return StrUtil.toCamelCase(Convert.toStr(paramsObj.get(GenConstants.TREE_PARENT_CODE)));
return StringUtils.toCamelCase(Convert.toStr(paramsObj.get(GenConstants.TREE_PARENT_CODE)));
}
return StrUtil.EMPTY;
return StringUtils.EMPTY;
}
/**
@ -339,11 +339,11 @@ public class VelocityUtils
*/
public static String getTreeName(Map<String, Object> paramsObj)
{
if (Validator.isNotEmpty(paramsObj) && paramsObj.containsKey(GenConstants.TREE_NAME))
if (StringUtils.isNotEmpty(paramsObj) && paramsObj.containsKey(GenConstants.TREE_NAME))
{
return StrUtil.toCamelCase(Convert.toStr(paramsObj.get(GenConstants.TREE_NAME)));
return StringUtils.toCamelCase(Convert.toStr(paramsObj.get(GenConstants.TREE_NAME)));
}
return StrUtil.EMPTY;
return StringUtils.EMPTY;
}
/**

View File

@ -1,5 +1,8 @@
package com.ruoyi.oss.constant;
import java.util.Arrays;
import java.util.List;
/**
* 云存储常量
*
@ -7,14 +10,29 @@ package com.ruoyi.oss.constant;
*/
public class CloudConstant {
/**
* OSS模块KEY
*/
public static final String SYS_OSS_KEY = "sys_oss:";
/**
* 云存储配置KEY
*/
public final static String CLOUD_STORAGE_CONFIG_KEY = "sys.oss.cloudStorageService";
public static final String CLOUD_STORAGE_CONFIG_KEY = "CloudStorageConfig";
/**
* 缓存配置KEY
*/
public static final String CACHE_CONFIG_KEY = SYS_OSS_KEY + CLOUD_STORAGE_CONFIG_KEY;
/**
* 预览列表资源开关Key
*/
public final static String PEREVIEW_LIST_RESOURCE_KEY = "sys.oss.previewListResource";
public static final String PEREVIEW_LIST_RESOURCE_KEY = "sys.oss.previewListResource";
/**
* 系统数据ids
*/
public static final List<Integer> SYSTEM_DATA_IDS = Arrays.asList(1, 2, 3, 4);
}

View File

@ -1,9 +1,10 @@
package com.ruoyi.oss.enumd;
import com.ruoyi.oss.service.impl.AliyunCloudStorageServiceImpl;
import com.ruoyi.oss.service.impl.MinioCloudStorageServiceImpl;
import com.ruoyi.oss.service.impl.QcloudCloudStorageServiceImpl;
import com.ruoyi.oss.service.impl.QiniuCloudStorageServiceImpl;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.oss.service.impl.AliyunCloudStorageStrategy;
import com.ruoyi.oss.service.impl.MinioCloudStorageStrategy;
import com.ruoyi.oss.service.impl.QcloudCloudStorageStrategy;
import com.ruoyi.oss.service.impl.QiniuCloudStorageStrategy;
import lombok.AllArgsConstructor;
import lombok.Getter;
@ -19,22 +20,22 @@ public enum CloudServiceEnumd {
/**
* 七牛云
*/
QINIU("qiniu", QiniuCloudStorageServiceImpl.class),
QINIU("qiniu", QiniuCloudStorageStrategy.class),
/**
* 阿里云
*/
ALIYUN("aliyun", AliyunCloudStorageServiceImpl.class),
ALIYUN("aliyun", AliyunCloudStorageStrategy.class),
/**
* 腾讯云
*/
QCLOUD("qcloud", QcloudCloudStorageServiceImpl.class),
QCLOUD("qcloud", QcloudCloudStorageStrategy.class),
/**
* minio
*/
MINIO("minio", MinioCloudStorageServiceImpl.class);
MINIO("minio", MinioCloudStorageStrategy.class);
private final String value;
@ -48,4 +49,15 @@ public enum CloudServiceEnumd {
}
return null;
}
public static String getServiceName(String value) {
for (CloudServiceEnumd clazz : values()) {
if (clazz.getValue().equals(value)) {
return StringUtils.uncapitalize(clazz.getServiceClass().getSimpleName());
}
}
return null;
}
}

View File

@ -1,12 +1,18 @@
package com.ruoyi.oss.factory;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.convert.Convert;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.JsonUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.reflect.ReflectUtils;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.oss.constant.CloudConstant;
import com.ruoyi.oss.enumd.CloudServiceEnumd;
import com.ruoyi.oss.service.ICloudStorageService;
import com.ruoyi.system.service.ISysConfigService;
import com.ruoyi.oss.exception.OssException;
import com.ruoyi.oss.properties.CloudStorageProperties;
import com.ruoyi.oss.service.ICloudStorageStrategy;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@ -17,29 +23,55 @@ import java.util.concurrent.ConcurrentHashMap;
*/
public class OssFactory {
private static ISysConfigService sysConfigService;
private static RedisCache redisCache;
static {
OssFactory.sysConfigService = SpringUtils.getBean(ISysConfigService.class);
OssFactory.redisCache = SpringUtils.getBean(RedisCache.class);
}
private static final Map<String, ICloudStorageService> SERVICES = new ConcurrentHashMap<>();
/**
* 服务实例缓存
*/
private static final Map<String, ICloudStorageStrategy> SERVICES = new ConcurrentHashMap<>();
public static ICloudStorageService instance() {
String type = sysConfigService.selectConfigByKey(CloudConstant.CLOUD_STORAGE_CONFIG_KEY);
/**
* 服务配置更新时间缓存
*/
private static final Map<String, Date> SERVICES_UPDATE_TIME = new ConcurrentHashMap<>();
/**
* 获取默认实例
*/
public static ICloudStorageStrategy instance() {
// 获取redis 默认类型
String type = Convert.toStr(redisCache.getCacheObject(CloudConstant.CACHE_CONFIG_KEY));
if (StringUtils.isEmpty(type)) {
throw new OssException("文件存储服务类型无法找到!");
}
return instance(type);
}
public static ICloudStorageService instance(String type) {
ICloudStorageService service = SERVICES.get(type);
if (service == null) {
service = (ICloudStorageService) SpringUtils.getBean(CloudServiceEnumd.getServiceClass(type));
/**
* 根据类型获取实例
*/
public static ICloudStorageStrategy instance(String type) {
ICloudStorageStrategy service = SERVICES.get(type);
Date oldDate = SERVICES_UPDATE_TIME.get(type);
Object json = redisCache.getCacheObject(CloudConstant.SYS_OSS_KEY + type);
CloudStorageProperties properties = JsonUtils.parseObject(json.toString(), CloudStorageProperties.class);
if (properties == null) {
throw new OssException("系统异常, '" + type + "'配置信息不存在!");
}
Date nowDate = properties.getUpdateTime();
// 服务存在并更新时间相同则返回(使用更新时间确保配置最终一致性)
if (service != null && oldDate.equals(nowDate)) {
return service;
}
// 获取redis配置信息 创建对象 并缓存
service = (ICloudStorageStrategy) ReflectUtils.newInstance(CloudServiceEnumd.getServiceClass(type), properties);
SERVICES.put(type, service);
SERVICES_UPDATE_TIME.put(type, nowDate);
return service;
}
public static void register(String type, ICloudStorageService iCloudStorageService) {
Assert.notNull(type, "type can't be null");
SERVICES.put(type, iCloudStorageService);
}
}

View File

@ -1,9 +1,8 @@
package com.ruoyi.oss.properties;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.util.Date;
/**
* OSS云存储 配置属性
@ -11,177 +10,46 @@ import org.springframework.stereotype.Component;
* @author Lion Li
*/
@Data
@Component
@ConfigurationProperties(prefix = "cloud-storage")
public class CloudStorageProperties {
private Boolean previewListImage;
private QiniuProperties qiniu;
private AliyunProperties aliyun;
private QcloudProperties qcloud;
private MinioProperties minio;
/**
* 域名
*/
private String endpoint;
/**
* 阿里云 配置属性
*
* @author Lion Li
* 前缀
*/
@Data
@NoArgsConstructor
public static class AliyunProperties {
/**
* 阿里云绑定的域名
*/
private String endpoint;
/**
* 阿里云路径前缀
*/
private String prefix;
/**
* 阿里云AccessKeyId
*/
private String accessKeyId;
/**
* 阿里云AccessKeySecret
*/
private String accessKeySecret;
/**
* 阿里云BucketName
*/
private String bucketName;
}
private String prefix;
/**
* Minio 配置属性
*
* @author Lion Li
* ACCESS_KEY
*/
@Data
@NoArgsConstructor
public static class MinioProperties {
/**
* minio域名
*/
private String endpoint;
/**
* minio ACCESS_KEY
*/
private String accessKey;
/**
* minio SECRET_KEY
*/
private String secretKey;
/**
* minio 存储空间名
*/
private String bucketName;
}
private String accessKey;
/**
* 腾讯云COS 配置属性
*
* @author Lion Li
* SECRET_KEY
*/
@Data
@NoArgsConstructor
public static class QcloudProperties {
/**
* 腾讯云绑定的域名
*/
private String endpoint;
/**
* 腾讯云路径前缀
*/
private String prefix;
/**
* 腾讯云SecretId
*/
private String secretId;
/**
* 腾讯云SecretKey
*/
private String secretKey;
/**
* 腾讯云BucketName
*/
private String bucketName;
/**
* 七牛是否使用https
*/
private Boolean isHttps;
/**
* 腾讯云COS所属地区
*/
private String region;
}
private String secretKey;
/**
* 七牛云 配置属性
*
* @author Lion Li
* 存储空间名
*/
@Data
@NoArgsConstructor
public static class QiniuProperties {
private String bucketName;
/**
* 七牛绑定的域名
*/
private String domain;
/**
* 存储区域
*/
private String region;
/**
* 七牛路径前缀
*/
private String prefix;
/**
* 是否httpsY=是,N=否)
*/
private String isHttps;
/**
* 七牛ACCESS_KEY
*/
private String accessKey;
/**
* 七牛SECRET_KEY
*/
private String secretKey;
/**
* 七牛存储空间名
*/
private String bucketName;
/**
* 七牛存储区域
*/
private String region;
/**
* 七牛是否使用https
*/
private Boolean isHttps;
}
/**
* 更新时间
*/
private Date updateTime;
}

View File

@ -5,11 +5,11 @@ import com.ruoyi.oss.entity.UploadResult;
import java.io.InputStream;
/**
* 云存储服务接口
* 云存储策略
*
* @author Lion Li
*/
public interface ICloudStorageService {
public interface ICloudStorageStrategy {
void createBucket();
@ -70,5 +70,5 @@ public interface ICloudStorageService {
*/
UploadResult uploadSuffix(InputStream inputStream, String suffix, String contentType);
String getEndpointLink();
String getEndpointLink();
}

View File

@ -3,20 +3,22 @@ package com.ruoyi.oss.service.abstractd;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.oss.entity.UploadResult;
import com.ruoyi.oss.service.ICloudStorageService;
import org.springframework.beans.factory.InitializingBean;
import com.ruoyi.oss.properties.CloudStorageProperties;
import com.ruoyi.oss.service.ICloudStorageStrategy;
import java.io.InputStream;
import java.util.Date;
/**
* 云存储(支持七牛阿里云腾讯云minio)
* 云存储策略(支持七牛阿里云腾讯云minio)
*
* @author Lion Li
*/
public abstract class AbstractCloudStorageService implements ICloudStorageService, InitializingBean {
public abstract class AbstractCloudStorageStrategy implements ICloudStorageStrategy {
protected CloudStorageProperties properties;
@Override
public abstract void createBucket();
@ -30,7 +32,7 @@ public abstract class AbstractCloudStorageService implements ICloudStorageServic
String uuid = IdUtil.fastSimpleUUID();
// 文件路径
String path = DateUtil.format(new Date(), "yyyyMMdd") + "/" + uuid;
if (StrUtil.isNotBlank(prefix)) {
if (StringUtils.isNotBlank(prefix)) {
path = prefix + "/" + path;
}
return path + suffix;
@ -54,9 +56,6 @@ public abstract class AbstractCloudStorageService implements ICloudStorageServic
@Override
public abstract UploadResult uploadSuffix(InputStream inputStream, String suffix, String contentType);
@Override
public abstract void afterPropertiesSet() throws Exception;
@Override
public abstract String getEndpointLink();
}

View File

@ -1,6 +1,5 @@
package com.ruoyi.oss.service.impl;
import cn.hutool.core.util.StrUtil;
import com.aliyun.oss.ClientConfiguration;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.common.auth.DefaultCredentialProvider;
@ -8,42 +7,32 @@ import com.aliyun.oss.model.CannedAccessControlList;
import com.aliyun.oss.model.CreateBucketRequest;
import com.aliyun.oss.model.ObjectMetadata;
import com.aliyun.oss.model.PutObjectRequest;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.oss.entity.UploadResult;
import com.ruoyi.oss.enumd.CloudServiceEnumd;
import com.ruoyi.oss.exception.OssException;
import com.ruoyi.oss.factory.OssFactory;
import com.ruoyi.oss.properties.CloudStorageProperties;
import com.ruoyi.oss.properties.CloudStorageProperties.AliyunProperties;
import com.ruoyi.oss.service.abstractd.AbstractCloudStorageService;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import com.ruoyi.oss.service.abstractd.AbstractCloudStorageStrategy;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
/**
* 阿里云存储
* 阿里云存储策略
*
* @author Lion Li
*/
@Lazy
@Service
public class AliyunCloudStorageServiceImpl extends AbstractCloudStorageService implements InitializingBean {
public class AliyunCloudStorageStrategy extends AbstractCloudStorageStrategy {
private final OSSClient client;
private final AliyunProperties properties;
@Autowired
public AliyunCloudStorageServiceImpl(CloudStorageProperties properties) {
this.properties = properties.getAliyun();
public AliyunCloudStorageStrategy(CloudStorageProperties cloudStorageProperties) {
properties = cloudStorageProperties;
try {
ClientConfiguration configuration = new ClientConfiguration();
DefaultCredentialProvider credentialProvider = new DefaultCredentialProvider(
this.properties.getAccessKeyId(),
this.properties.getAccessKeySecret());
client = new OSSClient(this.properties.getEndpoint(), credentialProvider, configuration);
properties.getAccessKey(), properties.getSecretKey());
client = new OSSClient(properties.getEndpoint(), credentialProvider, configuration);
createBucket();
} catch (Exception e) {
throw new IllegalArgumentException("阿里云存储配置错误! 请检查系统配置!");
@ -107,18 +96,13 @@ public class AliyunCloudStorageServiceImpl extends AbstractCloudStorageService i
return upload(inputStream, getPath(properties.getPrefix(), suffix), contentType);
}
@Override
public void afterPropertiesSet() throws Exception {
OssFactory.register(getServiceType(), this);
}
@Override
public String getEndpointLink() {
String endpoint = properties.getEndpoint();
StringBuilder sb = new StringBuilder(endpoint);
if (StrUtil.containsAnyIgnoreCase(endpoint, "http://")) {
if (StringUtils.containsAnyIgnoreCase(endpoint, "http://")) {
sb.insert(7, properties.getBucketName() + ".");
} else if (StrUtil.containsAnyIgnoreCase(endpoint, "https://")) {
} else if (StringUtils.containsAnyIgnoreCase(endpoint, "https://")) {
sb.insert(8, properties.getBucketName() + ".");
} else {
throw new OssException("Endpoint配置错误");

View File

@ -1,43 +1,33 @@
package com.ruoyi.oss.service.impl;
import cn.hutool.core.util.StrUtil;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.oss.entity.UploadResult;
import com.ruoyi.oss.enumd.CloudServiceEnumd;
import com.ruoyi.oss.enumd.PolicyType;
import com.ruoyi.oss.exception.OssException;
import com.ruoyi.oss.factory.OssFactory;
import com.ruoyi.oss.properties.CloudStorageProperties;
import com.ruoyi.oss.properties.CloudStorageProperties.MinioProperties;
import com.ruoyi.oss.service.abstractd.AbstractCloudStorageService;
import com.ruoyi.oss.service.abstractd.AbstractCloudStorageStrategy;
import io.minio.*;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
/**
* minio存储
* minio存储策略
*
* @author Lion Li
*/
@Lazy
@Service
public class MinioCloudStorageServiceImpl extends AbstractCloudStorageService implements InitializingBean {
public class MinioCloudStorageStrategy extends AbstractCloudStorageStrategy {
private final MinioClient minioClient;
private final MinioProperties properties;
@Autowired
public MinioCloudStorageServiceImpl(CloudStorageProperties properties) {
this.properties = properties.getMinio();
public MinioCloudStorageStrategy(CloudStorageProperties cloudStorageProperties) {
properties = cloudStorageProperties;
try {
minioClient = MinioClient.builder()
.endpoint(this.properties.getEndpoint())
.credentials(this.properties.getAccessKey(), this.properties.getSecretKey())
.endpoint(properties.getEndpoint())
.credentials(properties.getAccessKey(), properties.getSecretKey())
.build();
createBucket();
} catch (Exception e) {
@ -80,7 +70,7 @@ public class MinioCloudStorageServiceImpl extends AbstractCloudStorageService im
minioClient.putObject(PutObjectArgs.builder()
.bucket(properties.getBucketName())
.object(path)
.contentType(StrUtil.blankToDefault(contentType, MediaType.APPLICATION_OCTET_STREAM_VALUE))
.contentType(StringUtils.blankToDefault(contentType, MediaType.APPLICATION_OCTET_STREAM_VALUE))
.stream(inputStream, inputStream.available(), -1)
.build());
} catch (Exception e) {
@ -112,11 +102,6 @@ public class MinioCloudStorageServiceImpl extends AbstractCloudStorageService im
return upload(inputStream, getPath("", suffix), contentType);
}
@Override
public void afterPropertiesSet() throws Exception {
OssFactory.register(getServiceType(), this);
}
@Override
public String getEndpointLink() {
return properties.getEndpoint() + "/" + properties.getBucketName();

View File

@ -1,6 +1,5 @@
package com.ruoyi.oss.service.impl;
import cn.hutool.core.util.StrUtil;
import com.qcloud.cos.COSClient;
import com.qcloud.cos.ClientConfig;
import com.qcloud.cos.auth.BasicCOSCredentials;
@ -8,45 +7,35 @@ import com.qcloud.cos.auth.COSCredentials;
import com.qcloud.cos.http.HttpProtocol;
import com.qcloud.cos.model.*;
import com.qcloud.cos.region.Region;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.oss.entity.UploadResult;
import com.ruoyi.oss.enumd.CloudServiceEnumd;
import com.ruoyi.oss.exception.OssException;
import com.ruoyi.oss.factory.OssFactory;
import com.ruoyi.oss.properties.CloudStorageProperties;
import com.ruoyi.oss.properties.CloudStorageProperties.QcloudProperties;
import com.ruoyi.oss.service.abstractd.AbstractCloudStorageService;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import com.ruoyi.oss.service.abstractd.AbstractCloudStorageStrategy;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
/**
* 腾讯云存储
* 腾讯云存储策略
*
* @author Lion Li
*/
@Lazy
@Service
public class QcloudCloudStorageServiceImpl extends AbstractCloudStorageService implements InitializingBean {
public class QcloudCloudStorageStrategy extends AbstractCloudStorageStrategy {
private final COSClient client;
private final QcloudProperties properties;
@Autowired
public QcloudCloudStorageServiceImpl(CloudStorageProperties properties) {
this.properties = properties.getQcloud();
public QcloudCloudStorageStrategy(CloudStorageProperties cloudStorageProperties) {
properties = cloudStorageProperties;
try {
COSCredentials credentials = new BasicCOSCredentials(
this.properties.getSecretId(),
this.properties.getSecretKey());
properties.getAccessKey(), properties.getSecretKey());
// 初始化客户端配置
ClientConfig clientConfig = new ClientConfig();
// 设置bucket所在的区域华南gz 华北tj 华东sh
clientConfig.setRegion(new Region(this.properties.getRegion()));
if (this.properties.getIsHttps()) {
clientConfig.setRegion(new Region(properties.getRegion()));
if ("Y".equals(properties.getIsHttps())) {
clientConfig.setHttpProtocol(HttpProtocol.https);
} else {
clientConfig.setHttpProtocol(HttpProtocol.http);
@ -115,18 +104,13 @@ public class QcloudCloudStorageServiceImpl extends AbstractCloudStorageService i
return upload(inputStream, getPath(properties.getPrefix(), suffix), contentType);
}
@Override
public void afterPropertiesSet() throws Exception {
OssFactory.register(getServiceType(),this);
}
@Override
public String getEndpointLink() {
String endpoint = properties.getEndpoint();
StringBuilder sb = new StringBuilder(endpoint);
if (StrUtil.containsAnyIgnoreCase(endpoint, "http://")) {
if (StringUtils.containsAnyIgnoreCase(endpoint, "http://")) {
sb.insert(7, properties.getBucketName() + ".");
} else if (StrUtil.containsAnyIgnoreCase(endpoint, "https://")) {
} else if (StringUtils.containsAnyIgnoreCase(endpoint, "https://")) {
sb.insert(8, properties.getBucketName() + ".");
} else {
throw new OssException("Endpoint配置错误");

View File

@ -10,51 +10,37 @@ import com.qiniu.util.Auth;
import com.ruoyi.oss.entity.UploadResult;
import com.ruoyi.oss.enumd.CloudServiceEnumd;
import com.ruoyi.oss.exception.OssException;
import com.ruoyi.oss.factory.OssFactory;
import com.ruoyi.oss.properties.CloudStorageProperties;
import com.ruoyi.oss.properties.CloudStorageProperties.QiniuProperties;
import com.ruoyi.oss.service.abstractd.AbstractCloudStorageService;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import com.ruoyi.oss.service.abstractd.AbstractCloudStorageStrategy;
import java.io.InputStream;
/**
* 七牛云存储
* 七牛云存储策略
*
* @author Lion Li
*/
@Lazy
@Service
public class QiniuCloudStorageServiceImpl extends AbstractCloudStorageService implements InitializingBean {
public class QiniuCloudStorageStrategy extends AbstractCloudStorageStrategy {
private final UploadManager uploadManager;
private final BucketManager bucketManager;
private final String token;
private final QiniuProperties properties;
@Autowired
public QiniuCloudStorageServiceImpl(CloudStorageProperties properties) {
this.properties = properties.getQiniu();
public QiniuCloudStorageStrategy(CloudStorageProperties cloudStorageProperties) {
properties = cloudStorageProperties;
try {
Configuration config = new Configuration(getRegion(this.properties.getRegion()));
Configuration config = new Configuration(getRegion(properties.getRegion()));
// https设置
config.useHttpsDomains = false;
if (this.properties.getIsHttps() != null) {
config.useHttpsDomains = this.properties.getIsHttps();
}
config.useHttpsDomains = "Y".equals(properties.getIsHttps());
uploadManager = new UploadManager(config);
Auth auth = Auth.create(
this.properties.getAccessKey(),
this.properties.getSecretKey());
String bucketName = this.properties.getBucketName();
Auth auth = Auth.create(properties.getAccessKey(), properties.getSecretKey());
String bucketName = properties.getBucketName();
token = auth.uploadToken(bucketName);
bucketManager = new BucketManager(auth, config);
if (!ArrayUtil.contains(bucketManager.buckets(), bucketName)) {
bucketManager.createBucket(bucketName, this.properties.getRegion());
bucketManager.createBucket(bucketName, properties.getRegion());
}
} catch (Exception e) {
throw new IllegalArgumentException("七牛云存储配置错误! 请检查系统配置!");
@ -115,14 +101,9 @@ public class QiniuCloudStorageServiceImpl extends AbstractCloudStorageService im
return upload(inputStream, getPath(properties.getPrefix(), suffix), contentType);
}
@Override
public void afterPropertiesSet() throws Exception {
OssFactory.register(getServiceType(),this);
}
@Override
public String getEndpointLink() {
return properties.getDomain();
return properties.getEndpoint();
}
private Region getRegion(String region) {

View File

@ -1,6 +1,5 @@
package com.ruoyi.quartz.controller;
import cn.hutool.core.util.StrUtil;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.controller.BaseController;
@ -8,7 +7,7 @@ import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.exception.job.TaskException;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.quartz.domain.SysJob;
import com.ruoyi.quartz.service.ISysJobService;
@ -18,6 +17,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
/**
@ -48,11 +48,10 @@ public class SysJobController extends BaseController
@PreAuthorize("@ss.hasPermi('monitor:job:export')")
@Log(title = "定时任务", businessType = BusinessType.EXPORT)
@GetMapping("/export")
public AjaxResult export(SysJob sysJob)
public void export(SysJob sysJob, HttpServletResponse response)
{
List<SysJob> list = jobService.selectJobList(sysJob);
ExcelUtil<SysJob> util = new ExcelUtil<SysJob>(SysJob.class);
return util.exportExcel(list, "定时任务");
ExcelUtil.exportExcel(list, "定时任务", SysJob.class, response);
}
/**
@ -71,18 +70,22 @@ public class SysJobController extends BaseController
@PreAuthorize("@ss.hasPermi('monitor:job:add')")
@Log(title = "定时任务", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody SysJob sysJob) throws SchedulerException, TaskException
public AjaxResult add(@RequestBody SysJob job) throws SchedulerException, TaskException
{
if (!CronUtils.isValid(sysJob.getCronExpression()))
if (!CronUtils.isValid(job.getCronExpression()))
{
return AjaxResult.error("新增任务'" + sysJob.getJobName() + "'失败Cron表达式不正确");
return error("新增任务'" + job.getJobName() + "'失败Cron表达式不正确");
}
else if (StrUtil.containsIgnoreCase(sysJob.getInvokeTarget(), Constants.LOOKUP_RMI))
else if (StringUtils.containsIgnoreCase(job.getInvokeTarget(), Constants.LOOKUP_RMI))
{
return AjaxResult.error("新增任务'" + sysJob.getJobName() + "'失败,目标字符串不允许'rmi://'调用");
return error("新增任务'" + job.getJobName() + "'失败,目标字符串不允许'rmi://'调用");
}
sysJob.setCreateBy(SecurityUtils.getUsername());
return toAjax(jobService.insertJob(sysJob));
else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), new String[] { Constants.HTTP, Constants.HTTPS }))
{
return error("新增任务'" + job.getJobName() + "'失败,目标字符串不允许'http(s)//'调用");
}
job.setCreateBy(getUsername());
return toAjax(jobService.insertJob(job));
}
/**
@ -91,18 +94,22 @@ public class SysJobController extends BaseController
@PreAuthorize("@ss.hasPermi('monitor:job:edit')")
@Log(title = "定时任务", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody SysJob sysJob) throws SchedulerException, TaskException
public AjaxResult edit(@RequestBody SysJob job) throws SchedulerException, TaskException
{
if (!CronUtils.isValid(sysJob.getCronExpression()))
if (!CronUtils.isValid(job.getCronExpression()))
{
return AjaxResult.error("修改任务'" + sysJob.getJobName() + "'失败Cron表达式不正确");
return error("修改任务'" + job.getJobName() + "'失败Cron表达式不正确");
}
else if (StrUtil.containsIgnoreCase(sysJob.getInvokeTarget(), Constants.LOOKUP_RMI))
else if (StringUtils.containsIgnoreCase(job.getInvokeTarget(), Constants.LOOKUP_RMI))
{
return AjaxResult.error("修改任务'" + sysJob.getJobName() + "'失败,目标字符串不允许'rmi://'调用");
return error("修改任务'" + job.getJobName() + "'失败,目标字符串不允许'rmi://'调用");
}
sysJob.setUpdateBy(SecurityUtils.getUsername());
return toAjax(jobService.updateJob(sysJob));
else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), new String[] { Constants.HTTP, Constants.HTTPS }))
{
return error("修改任务'" + job.getJobName() + "'失败,目标字符串不允许'http(s)//'调用");
}
job.setUpdateBy(getUsername());
return toAjax(jobService.updateJob(job));
}
/**

View File

@ -12,11 +12,12 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
/**
* 调度日志操作处理
*
*
* @author ruoyi
*/
@RestController
@ -42,13 +43,12 @@ public class SysJobLogController extends BaseController
@PreAuthorize("@ss.hasPermi('monitor:job:export')")
@Log(title = "任务调度日志", businessType = BusinessType.EXPORT)
@GetMapping("/export")
public AjaxResult export(SysJobLog sysJobLog)
public void export(SysJobLog sysJobLog, HttpServletResponse response)
{
List<SysJobLog> list = jobLogService.selectJobLogList(sysJobLog);
ExcelUtil<SysJobLog> util = new ExcelUtil<SysJobLog>(SysJobLog.class);
return util.exportExcel(list, "调度日志");
ExcelUtil.exportExcel(list, "调度日志", SysJobLog.class, response);
}
/**
* 根据调度编号获取详细信息
*/

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