修改系统
This commit is contained in:
		| @@ -0,0 +1,28 @@ | ||||
| package com.stdiet.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; | ||||
|  | ||||
| /** | ||||
|  * 数据权限过滤注解 | ||||
|  *  | ||||
|  * @author stdiet | ||||
|  */ | ||||
| @Target(ElementType.METHOD) | ||||
| @Retention(RetentionPolicy.RUNTIME) | ||||
| @Documented | ||||
| public @interface DataScope | ||||
| { | ||||
|     /** | ||||
|      * 部门表的别名 | ||||
|      */ | ||||
|     public String deptAlias() default ""; | ||||
|  | ||||
|     /** | ||||
|      * 用户表的别名 | ||||
|      */ | ||||
|     public String userAlias() default ""; | ||||
| } | ||||
| @@ -0,0 +1,28 @@ | ||||
| package com.stdiet.common.annotation; | ||||
|  | ||||
| import java.lang.annotation.Documented; | ||||
| import java.lang.annotation.ElementType; | ||||
| import java.lang.annotation.Inherited; | ||||
| import java.lang.annotation.Retention; | ||||
| import java.lang.annotation.RetentionPolicy; | ||||
| import java.lang.annotation.Target; | ||||
| import com.stdiet.common.enums.DataSourceType; | ||||
|  | ||||
| /** | ||||
|  * 自定义多数据源切换注解 | ||||
|  * | ||||
|  * 优先级:先方法,后类,如果方法覆盖了类上的数据源类型,以方法的为准,否则以类上的为准 | ||||
|  * | ||||
|  * @author stdiet | ||||
|  */ | ||||
| @Target({ ElementType.METHOD, ElementType.TYPE }) | ||||
| @Retention(RetentionPolicy.RUNTIME) | ||||
| @Documented | ||||
| @Inherited | ||||
| public @interface DataSource | ||||
| { | ||||
|     /** | ||||
|      * 切换数据源名称 | ||||
|      */ | ||||
|     public DataSourceType value() default DataSourceType.MASTER; | ||||
| } | ||||
| @@ -0,0 +1,144 @@ | ||||
| package com.stdiet.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 stdiet | ||||
|  */ | ||||
| @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:仅导入) | ||||
|      */ | ||||
|     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); | ||||
|         private final int value; | ||||
|  | ||||
|         ColumnType(int value) | ||||
|         { | ||||
|             this.value = value; | ||||
|         } | ||||
|  | ||||
|         public int value() | ||||
|         { | ||||
|             return this.value; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,18 @@ | ||||
| package com.stdiet.common.annotation; | ||||
|  | ||||
| import java.lang.annotation.ElementType; | ||||
| import java.lang.annotation.Retention; | ||||
| import java.lang.annotation.RetentionPolicy; | ||||
| import java.lang.annotation.Target; | ||||
|  | ||||
| /** | ||||
|  * Excel注解集 | ||||
|  *  | ||||
|  * @author stdiet | ||||
|  */ | ||||
| @Target(ElementType.FIELD) | ||||
| @Retention(RetentionPolicy.RUNTIME) | ||||
| public @interface Excels | ||||
| { | ||||
|     Excel[] value(); | ||||
| } | ||||
| @@ -0,0 +1,41 @@ | ||||
| package com.stdiet.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.stdiet.common.enums.BusinessType; | ||||
| import com.stdiet.common.enums.OperatorType; | ||||
|  | ||||
| /** | ||||
|  * 自定义操作日志记录注解 | ||||
|  *  | ||||
|  * @author stdiet | ||||
|  * | ||||
|  */ | ||||
| @Target({ ElementType.PARAMETER, ElementType.METHOD }) | ||||
| @Retention(RetentionPolicy.RUNTIME) | ||||
| @Documented | ||||
| public @interface Log | ||||
| { | ||||
|     /** | ||||
|      * 模块  | ||||
|      */ | ||||
|     public String title() default ""; | ||||
|  | ||||
|     /** | ||||
|      * 功能 | ||||
|      */ | ||||
|     public BusinessType businessType() default BusinessType.OTHER; | ||||
|  | ||||
|     /** | ||||
|      * 操作人类别 | ||||
|      */ | ||||
|     public OperatorType operatorType() default OperatorType.MANAGE; | ||||
|  | ||||
|     /** | ||||
|      * 是否保存请求的参数 | ||||
|      */ | ||||
|     public boolean isSaveRequestData() default true; | ||||
| } | ||||
| @@ -0,0 +1,23 @@ | ||||
| package com.stdiet.common.annotation; | ||||
|  | ||||
| import java.lang.annotation.Documented; | ||||
| import java.lang.annotation.ElementType; | ||||
| import java.lang.annotation.Inherited; | ||||
| import java.lang.annotation.Retention; | ||||
| import java.lang.annotation.RetentionPolicy; | ||||
| import java.lang.annotation.Target; | ||||
|  | ||||
| /** | ||||
|  * 自定义注解防止表单重复提交 | ||||
|  *  | ||||
|  * @author stdiet | ||||
|  * | ||||
|  */ | ||||
| @Inherited | ||||
| @Target(ElementType.METHOD) | ||||
| @Retention(RetentionPolicy.RUNTIME) | ||||
| @Documented | ||||
| public @interface RepeatSubmit | ||||
| { | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,116 @@ | ||||
| package com.stdiet.common.config; | ||||
|  | ||||
| import org.springframework.boot.context.properties.ConfigurationProperties; | ||||
| import org.springframework.stereotype.Component; | ||||
|  | ||||
| /** | ||||
|  * 读取项目相关配置 | ||||
|  *  | ||||
|  * @author stdiet | ||||
|  */ | ||||
| @Component | ||||
| @ConfigurationProperties(prefix = "stdiet") | ||||
| public class RuoYiConfig | ||||
| { | ||||
|     /** 项目名称 */ | ||||
|     private String name; | ||||
|  | ||||
|     /** 版本 */ | ||||
|     private String version; | ||||
|  | ||||
|     /** 版权年份 */ | ||||
|     private String copyrightYear; | ||||
|  | ||||
|     /** 实例演示开关 */ | ||||
|     private boolean demoEnabled; | ||||
|  | ||||
|     /** 上传路径 */ | ||||
|     private static String profile; | ||||
|  | ||||
|     /** 获取地址开关 */ | ||||
|     private static boolean addressEnabled; | ||||
|  | ||||
|     public String getName() | ||||
|     { | ||||
|         return name; | ||||
|     } | ||||
|  | ||||
|     public void setName(String name) | ||||
|     { | ||||
|         this.name = name; | ||||
|     } | ||||
|  | ||||
|     public String getVersion() | ||||
|     { | ||||
|         return version; | ||||
|     } | ||||
|  | ||||
|     public void setVersion(String version) | ||||
|     { | ||||
|         this.version = version; | ||||
|     } | ||||
|  | ||||
|     public String getCopyrightYear() | ||||
|     { | ||||
|         return copyrightYear; | ||||
|     } | ||||
|  | ||||
|     public void setCopyrightYear(String copyrightYear) | ||||
|     { | ||||
|         this.copyrightYear = copyrightYear; | ||||
|     } | ||||
|  | ||||
|     public boolean isDemoEnabled() | ||||
|     { | ||||
|         return demoEnabled; | ||||
|     } | ||||
|  | ||||
|     public void setDemoEnabled(boolean demoEnabled) | ||||
|     { | ||||
|         this.demoEnabled = demoEnabled; | ||||
|     } | ||||
|  | ||||
|     public static String getProfile() | ||||
|     { | ||||
|         return profile; | ||||
|     } | ||||
|  | ||||
|     public void setProfile(String profile) | ||||
|     { | ||||
|         RuoYiConfig.profile = profile; | ||||
|     } | ||||
|  | ||||
|     public static boolean isAddressEnabled() | ||||
|     { | ||||
|         return addressEnabled; | ||||
|     } | ||||
|  | ||||
|     public void setAddressEnabled(boolean addressEnabled) | ||||
|     { | ||||
|         RuoYiConfig.addressEnabled = addressEnabled; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 获取头像上传路径 | ||||
|      */ | ||||
|     public static String getAvatarPath() | ||||
|     { | ||||
|         return getProfile() + "/avatar"; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 获取下载路径 | ||||
|      */ | ||||
|     public static String getDownloadPath() | ||||
|     { | ||||
|         return getProfile() + "/download/"; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 获取上传路径 | ||||
|      */ | ||||
|     public static String getUploadPath() | ||||
|     { | ||||
|         return getProfile() + "/upload"; | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,129 @@ | ||||
| package com.stdiet.common.constant; | ||||
|  | ||||
| /** | ||||
|  * 通用常量信息 | ||||
|  *  | ||||
|  * @author stdiet | ||||
|  */ | ||||
| public class Constants | ||||
| { | ||||
|     /** | ||||
|      * UTF-8 字符集 | ||||
|      */ | ||||
|     public static final String UTF8 = "UTF-8"; | ||||
|  | ||||
|     /** | ||||
|      * GBK 字符集 | ||||
|      */ | ||||
|     public static final String GBK = "GBK"; | ||||
|  | ||||
|     /** | ||||
|      * http请求 | ||||
|      */ | ||||
|     public static final String HTTP = "http://"; | ||||
|  | ||||
|     /** | ||||
|      * https请求 | ||||
|      */ | ||||
|     public static final String HTTPS = "https://"; | ||||
|  | ||||
|     /** | ||||
|      * 通用成功标识 | ||||
|      */ | ||||
|     public static final String SUCCESS = "0"; | ||||
|  | ||||
|     /** | ||||
|      * 通用失败标识 | ||||
|      */ | ||||
|     public static final String FAIL = "1"; | ||||
|  | ||||
|     /** | ||||
|      * 登录成功 | ||||
|      */ | ||||
|     public static final String LOGIN_SUCCESS = "Success"; | ||||
|  | ||||
|     /** | ||||
|      * 注销 | ||||
|      */ | ||||
|     public static final String LOGOUT = "Logout"; | ||||
|  | ||||
|     /** | ||||
|      * 登录失败 | ||||
|      */ | ||||
|     public static final String LOGIN_FAIL = "Error"; | ||||
|  | ||||
|     /** | ||||
|      * 验证码 redis key | ||||
|      */ | ||||
|     public static final String CAPTCHA_CODE_KEY = "captcha_codes:"; | ||||
|  | ||||
|     /** | ||||
|      * 登录用户 redis key | ||||
|      */ | ||||
|     public static final String LOGIN_TOKEN_KEY = "login_tokens:"; | ||||
|      | ||||
|     /** | ||||
|      * 防重提交 redis key | ||||
|      */ | ||||
|     public static final String REPEAT_SUBMIT_KEY = "repeat_submit:"; | ||||
|  | ||||
|     /** | ||||
|      * 验证码有效期(分钟) | ||||
|      */ | ||||
|     public static final Integer CAPTCHA_EXPIRATION = 2; | ||||
|  | ||||
|     /** | ||||
|      * 令牌 | ||||
|      */ | ||||
|     public static final String TOKEN = "token"; | ||||
|  | ||||
|     /** | ||||
|      * 令牌前缀 | ||||
|      */ | ||||
|     public static final String TOKEN_PREFIX = "Bearer "; | ||||
|  | ||||
|     /** | ||||
|      * 令牌前缀 | ||||
|      */ | ||||
|     public static final String LOGIN_USER_KEY = "login_user_key"; | ||||
|  | ||||
|     /** | ||||
|      * 用户ID | ||||
|      */ | ||||
|     public static final String JWT_USERID = "userid"; | ||||
|  | ||||
|     /** | ||||
|      * 用户名称 | ||||
|      */ | ||||
|     public static final String JWT_USERNAME = "sub"; | ||||
|  | ||||
|     /** | ||||
|      * 用户头像 | ||||
|      */ | ||||
|     public static final String JWT_AVATAR = "avatar"; | ||||
|  | ||||
|     /** | ||||
|      * 创建时间 | ||||
|      */ | ||||
|     public static final String JWT_CREATED = "created"; | ||||
|  | ||||
|     /** | ||||
|      * 用户权限 | ||||
|      */ | ||||
|     public static final String JWT_AUTHORITIES = "authorities"; | ||||
|  | ||||
|     /** | ||||
|      * 参数管理 cache key | ||||
|      */ | ||||
|     public static final String SYS_CONFIG_KEY = "sys_config:"; | ||||
|  | ||||
|     /** | ||||
|      * 字典管理 cache key | ||||
|      */ | ||||
|     public static final String SYS_DICT_KEY = "sys_dict:"; | ||||
|  | ||||
|     /** | ||||
|      * 资源映射路径 前缀 | ||||
|      */ | ||||
|     public static final String RESOURCE_PREFIX = "/profile"; | ||||
| } | ||||
| @@ -0,0 +1,103 @@ | ||||
| package com.stdiet.common.constant; | ||||
|  | ||||
| /** | ||||
|  * 代码生成通用常量 | ||||
|  *  | ||||
|  * @author stdiet | ||||
|  */ | ||||
| public class GenConstants | ||||
| { | ||||
|     /** 单表(增删改查) */ | ||||
|     public static final String TPL_CRUD = "crud"; | ||||
|  | ||||
|     /** 树表(增删改查) */ | ||||
|     public static final String TPL_TREE = "tree"; | ||||
|  | ||||
|     /** 树编码字段 */ | ||||
|     public static final String TREE_CODE = "treeCode"; | ||||
|  | ||||
|     /** 树父编码字段 */ | ||||
|     public static final String TREE_PARENT_CODE = "treeParentCode"; | ||||
|  | ||||
|     /** 树名称字段 */ | ||||
|     public static final String TREE_NAME = "treeName"; | ||||
|  | ||||
|     /** 上级菜单ID字段 */ | ||||
|     public static final String PARENT_MENU_ID = "parentMenuId"; | ||||
|  | ||||
|     /** 上级菜单名称字段 */ | ||||
|     public static final String PARENT_MENU_NAME = "parentMenuName"; | ||||
|  | ||||
|     /** 数据库字符串类型 */ | ||||
|     public static final String[] COLUMNTYPE_STR = { "char", "varchar", "nvarchar", "varchar2", "tinytext", "text", | ||||
|             "mediumtext", "longtext" }; | ||||
|  | ||||
|     /** 数据库时间类型 */ | ||||
|     public static final String[] COLUMNTYPE_TIME = { "datetime", "time", "date", "timestamp" }; | ||||
|  | ||||
|     /** 数据库数字类型 */ | ||||
|     public static final String[] COLUMNTYPE_NUMBER = { "tinyint", "smallint", "mediumint", "int", "number", "integer", | ||||
|             "bigint", "float", "float", "double", "decimal" }; | ||||
|  | ||||
|     /** 页面不需要编辑字段 */ | ||||
|     public static final String[] COLUMNNAME_NOT_EDIT = { "id", "create_by", "create_time", "del_flag" }; | ||||
|  | ||||
|     /** 页面不需要显示的列表字段 */ | ||||
|     public static final String[] COLUMNNAME_NOT_LIST = { "id", "create_by", "create_time", "del_flag", "update_by", | ||||
|             "update_time" }; | ||||
|  | ||||
|     /** 页面不需要查询字段 */ | ||||
|     public static final String[] COLUMNNAME_NOT_QUERY = { "id", "create_by", "create_time", "del_flag", "update_by", | ||||
|             "update_time", "remark" }; | ||||
|  | ||||
|     /** Entity基类字段 */ | ||||
|     public static final String[] BASE_ENTITY = { "createBy", "createTime", "updateBy", "updateTime", "remark" }; | ||||
|  | ||||
|     /** Tree基类字段 */ | ||||
|     public static final String[] TREE_ENTITY = { "parentName", "parentId", "orderNum", "ancestors", "children" }; | ||||
|  | ||||
|     /** 文本框 */ | ||||
|     public static final String HTML_INPUT = "input"; | ||||
|  | ||||
|     /** 文本域 */ | ||||
|     public static final String HTML_TEXTAREA = "textarea"; | ||||
|  | ||||
|     /** 下拉框 */ | ||||
|     public static final String HTML_SELECT = "select"; | ||||
|  | ||||
|     /** 单选框 */ | ||||
|     public static final String HTML_RADIO = "radio"; | ||||
|  | ||||
|     /** 复选框 */ | ||||
|     public static final String HTML_CHECKBOX = "checkbox"; | ||||
|  | ||||
|     /** 日期控件 */ | ||||
|     public static final String HTML_DATETIME = "datetime"; | ||||
|  | ||||
|     /** 富文本控件 */ | ||||
|     public static final String HTML_EDITOR = "editor"; | ||||
|  | ||||
|     /** 字符串类型 */ | ||||
|     public static final String TYPE_STRING = "String"; | ||||
|  | ||||
|     /** 整型 */ | ||||
|     public static final String TYPE_INTEGER = "Integer"; | ||||
|  | ||||
|     /** 长整型 */ | ||||
|     public static final String TYPE_LONG = "Long"; | ||||
|  | ||||
|     /** 浮点型 */ | ||||
|     public static final String TYPE_DOUBLE = "Double"; | ||||
|  | ||||
|     /** 高精度计算类型 */ | ||||
|     public static final String TYPE_BIGDECIMAL = "BigDecimal"; | ||||
|  | ||||
|     /** 时间类型 */ | ||||
|     public static final String TYPE_DATE = "Date"; | ||||
|  | ||||
|     /** 模糊查询 */ | ||||
|     public static final String QUERY_LIKE = "LIKE"; | ||||
|  | ||||
|     /** 需要 */ | ||||
|     public static final String REQUIRE = "1"; | ||||
| } | ||||
| @@ -0,0 +1,89 @@ | ||||
| package com.stdiet.common.constant; | ||||
|  | ||||
| /** | ||||
|  * 返回状态码 | ||||
|  *  | ||||
|  * @author stdiet | ||||
|  */ | ||||
| public class HttpStatus | ||||
| { | ||||
|     /** | ||||
|      * 操作成功 | ||||
|      */ | ||||
|     public static final int SUCCESS = 200; | ||||
|  | ||||
|     /** | ||||
|      * 对象创建成功 | ||||
|      */ | ||||
|     public static final int CREATED = 201; | ||||
|  | ||||
|     /** | ||||
|      * 请求已经被接受 | ||||
|      */ | ||||
|     public static final int ACCEPTED = 202; | ||||
|  | ||||
|     /** | ||||
|      * 操作已经执行成功,但是没有返回数据 | ||||
|      */ | ||||
|     public static final int NO_CONTENT = 204; | ||||
|  | ||||
|     /** | ||||
|      * 资源已被移除 | ||||
|      */ | ||||
|     public static final int MOVED_PERM = 301; | ||||
|  | ||||
|     /** | ||||
|      * 重定向 | ||||
|      */ | ||||
|     public static final int SEE_OTHER = 303; | ||||
|  | ||||
|     /** | ||||
|      * 资源没有被修改 | ||||
|      */ | ||||
|     public static final int NOT_MODIFIED = 304; | ||||
|  | ||||
|     /** | ||||
|      * 参数列表错误(缺少,格式不匹配) | ||||
|      */ | ||||
|     public static final int BAD_REQUEST = 400; | ||||
|  | ||||
|     /** | ||||
|      * 未授权 | ||||
|      */ | ||||
|     public static final int UNAUTHORIZED = 401; | ||||
|  | ||||
|     /** | ||||
|      * 访问受限,授权过期 | ||||
|      */ | ||||
|     public static final int FORBIDDEN = 403; | ||||
|  | ||||
|     /** | ||||
|      * 资源,服务未找到 | ||||
|      */ | ||||
|     public static final int NOT_FOUND = 404; | ||||
|  | ||||
|     /** | ||||
|      * 不允许的http方法 | ||||
|      */ | ||||
|     public static final int BAD_METHOD = 405; | ||||
|  | ||||
|     /** | ||||
|      * 资源冲突,或者资源被锁 | ||||
|      */ | ||||
|     public static final int CONFLICT = 409; | ||||
|  | ||||
|     /** | ||||
|      * 不支持的数据,媒体类型 | ||||
|      */ | ||||
|     public static final int UNSUPPORTED_TYPE = 415; | ||||
|  | ||||
|     /** | ||||
|      * 系统内部错误 | ||||
|      */ | ||||
|     public static final int ERROR = 500; | ||||
|  | ||||
|     /** | ||||
|      * 接口未实现 | ||||
|      */ | ||||
|     public static final int NOT_IMPLEMENTED = 501; | ||||
| } | ||||
| @@ -0,0 +1,50 @@ | ||||
| package com.stdiet.common.constant; | ||||
|  | ||||
| /** | ||||
|  * 任务调度通用常量 | ||||
|  *  | ||||
|  * @author stdiet | ||||
|  */ | ||||
| public class ScheduleConstants | ||||
| { | ||||
|     public static final String TASK_CLASS_NAME = "TASK_CLASS_NAME"; | ||||
|  | ||||
|     /** 执行目标key */ | ||||
|     public static final String TASK_PROPERTIES = "TASK_PROPERTIES"; | ||||
|  | ||||
|     /** 默认 */ | ||||
|     public static final String MISFIRE_DEFAULT = "0"; | ||||
|  | ||||
|     /** 立即触发执行 */ | ||||
|     public static final String MISFIRE_IGNORE_MISFIRES = "1"; | ||||
|  | ||||
|     /** 触发一次执行 */ | ||||
|     public static final String MISFIRE_FIRE_AND_PROCEED = "2"; | ||||
|  | ||||
|     /** 不触发立即执行 */ | ||||
|     public static final String MISFIRE_DO_NOTHING = "3"; | ||||
|  | ||||
|     public enum Status | ||||
|     { | ||||
|         /** | ||||
|          * 正常 | ||||
|          */ | ||||
|         NORMAL("0"), | ||||
|         /** | ||||
|          * 暂停 | ||||
|          */ | ||||
|         PAUSE("1"); | ||||
|  | ||||
|         private String value; | ||||
|  | ||||
|         private Status(String value) | ||||
|         { | ||||
|             this.value = value; | ||||
|         } | ||||
|  | ||||
|         public String getValue() | ||||
|         { | ||||
|             return value; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,60 @@ | ||||
| package com.stdiet.common.constant; | ||||
|  | ||||
| /** | ||||
|  * 用户常量信息 | ||||
|  *  | ||||
|  * @author stdiet | ||||
|  */ | ||||
| public class UserConstants | ||||
| { | ||||
|     /** | ||||
|      * 平台内系统用户的唯一标志 | ||||
|      */ | ||||
|     public static final String SYS_USER = "SYS_USER"; | ||||
|  | ||||
|     /** 正常状态 */ | ||||
|     public static final String NORMAL = "0"; | ||||
|  | ||||
|     /** 异常状态 */ | ||||
|     public static final String EXCEPTION = "1"; | ||||
|  | ||||
|     /** 用户封禁状态 */ | ||||
|     public static final String USER_DISABLE = "1"; | ||||
|  | ||||
|     /** 角色封禁状态 */ | ||||
|     public static final String ROLE_DISABLE = "1"; | ||||
|  | ||||
|     /** 部门正常状态 */ | ||||
|     public static final String DEPT_NORMAL = "0"; | ||||
|  | ||||
|     /** 部门停用状态 */ | ||||
|     public static final String DEPT_DISABLE = "1"; | ||||
|  | ||||
|     /** 字典正常状态 */ | ||||
|     public static final String DICT_NORMAL = "0"; | ||||
|  | ||||
|     /** 是否为系统默认(是) */ | ||||
|     public static final String YES = "Y"; | ||||
|  | ||||
|     /** 是否菜单外链(是) */ | ||||
|     public static final String YES_FRAME = "0"; | ||||
|  | ||||
|     /** 是否菜单外链(否) */ | ||||
|     public static final String NO_FRAME = "1"; | ||||
|  | ||||
|     /** 菜单类型(目录) */ | ||||
|     public static final String TYPE_DIR = "M"; | ||||
|  | ||||
|     /** 菜单类型(菜单) */ | ||||
|     public static final String TYPE_MENU = "C"; | ||||
|  | ||||
|     /** 菜单类型(按钮) */ | ||||
|     public static final String TYPE_BUTTON = "F"; | ||||
|  | ||||
|     /** Layout组件标识 */ | ||||
|     public final static String LAYOUT = "Layout"; | ||||
|  | ||||
|     /** 校验返回结果码 */ | ||||
|     public final static String UNIQUE = "0"; | ||||
|     public final static String NOT_UNIQUE = "1"; | ||||
| } | ||||
| @@ -0,0 +1,94 @@ | ||||
| package com.stdiet.common.core.controller; | ||||
|  | ||||
| import java.beans.PropertyEditorSupport; | ||||
| import java.util.Date; | ||||
| import java.util.List; | ||||
| import org.slf4j.Logger; | ||||
| import org.slf4j.LoggerFactory; | ||||
| import org.springframework.web.bind.WebDataBinder; | ||||
| import org.springframework.web.bind.annotation.InitBinder; | ||||
| import com.github.pagehelper.PageHelper; | ||||
| import com.github.pagehelper.PageInfo; | ||||
| import com.stdiet.common.constant.HttpStatus; | ||||
| import com.stdiet.common.core.domain.AjaxResult; | ||||
| import com.stdiet.common.core.page.PageDomain; | ||||
| import com.stdiet.common.core.page.TableDataInfo; | ||||
| import com.stdiet.common.core.page.TableSupport; | ||||
| import com.stdiet.common.utils.DateUtils; | ||||
| import com.stdiet.common.utils.StringUtils; | ||||
| import com.stdiet.common.utils.sql.SqlUtil; | ||||
|  | ||||
| /** | ||||
|  * web层通用数据处理 | ||||
|  *  | ||||
|  * @author stdiet | ||||
|  */ | ||||
| public class BaseController | ||||
| { | ||||
|     protected final Logger logger = LoggerFactory.getLogger(BaseController.class); | ||||
|  | ||||
|     /** | ||||
|      * 将前台传递过来的日期格式的字符串,自动转化为Date类型 | ||||
|      */ | ||||
|     @InitBinder | ||||
|     public void initBinder(WebDataBinder binder) | ||||
|     { | ||||
|         // Date 类型转换 | ||||
|         binder.registerCustomEditor(Date.class, new PropertyEditorSupport() | ||||
|         { | ||||
|             @Override | ||||
|             public void setAsText(String text) | ||||
|             { | ||||
|                 setValue(DateUtils.parseDate(text)); | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 设置请求分页数据 | ||||
|      */ | ||||
|     protected void startPage() | ||||
|     { | ||||
|         PageDomain pageDomain = TableSupport.buildPageRequest(); | ||||
|         Integer pageNum = pageDomain.getPageNum(); | ||||
|         Integer pageSize = pageDomain.getPageSize(); | ||||
|         if (StringUtils.isNotNull(pageNum) && StringUtils.isNotNull(pageSize)) | ||||
|         { | ||||
|             String orderBy = SqlUtil.escapeOrderBySql(pageDomain.getOrderBy()); | ||||
|             PageHelper.startPage(pageNum, pageSize, orderBy); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 响应请求分页数据 | ||||
|      */ | ||||
|     @SuppressWarnings({ "rawtypes", "unchecked" }) | ||||
|     protected TableDataInfo getDataTable(List<?> list) | ||||
|     { | ||||
|         TableDataInfo rspData = new TableDataInfo(); | ||||
|         rspData.setCode(HttpStatus.SUCCESS); | ||||
|         rspData.setMsg("查询成功"); | ||||
|         rspData.setRows(list); | ||||
|         rspData.setTotal(new PageInfo(list).getTotal()); | ||||
|         return rspData; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 响应返回结果 | ||||
|      *  | ||||
|      * @param rows 影响行数 | ||||
|      * @return 操作结果 | ||||
|      */ | ||||
|     protected AjaxResult toAjax(int rows) | ||||
|     { | ||||
|         return rows > 0 ? AjaxResult.success() : AjaxResult.error(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 页面跳转 | ||||
|      */ | ||||
|     public String redirect(String url) | ||||
|     { | ||||
|         return StringUtils.format("redirect:{}", url); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,148 @@ | ||||
| package com.stdiet.common.core.domain; | ||||
|  | ||||
| import java.util.HashMap; | ||||
| import com.stdiet.common.constant.HttpStatus; | ||||
| import com.stdiet.common.utils.StringUtils; | ||||
|  | ||||
| /** | ||||
|  * 操作消息提醒 | ||||
|  *  | ||||
|  * @author stdiet | ||||
|  */ | ||||
| public class AjaxResult extends HashMap<String, Object> | ||||
| { | ||||
|     private static final long serialVersionUID = 1L; | ||||
|  | ||||
|     /** 状态码 */ | ||||
|     public static final String CODE_TAG = "code"; | ||||
|  | ||||
|     /** 返回内容 */ | ||||
|     public static final String MSG_TAG = "msg"; | ||||
|  | ||||
|     /** 数据对象 */ | ||||
|     public static final String DATA_TAG = "data"; | ||||
|  | ||||
|     /** | ||||
|      * 初始化一个新创建的 AjaxResult 对象,使其表示一个空消息。 | ||||
|      */ | ||||
|     public AjaxResult() | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 初始化一个新创建的 AjaxResult 对象 | ||||
|      *  | ||||
|      * @param code 状态码 | ||||
|      * @param msg 返回内容 | ||||
|      */ | ||||
|     public AjaxResult(int code, String msg) | ||||
|     { | ||||
|         super.put(CODE_TAG, code); | ||||
|         super.put(MSG_TAG, msg); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 初始化一个新创建的 AjaxResult 对象 | ||||
|      *  | ||||
|      * @param code 状态码 | ||||
|      * @param msg 返回内容 | ||||
|      * @param data 数据对象 | ||||
|      */ | ||||
|     public AjaxResult(int code, String msg, Object data) | ||||
|     { | ||||
|         super.put(CODE_TAG, code); | ||||
|         super.put(MSG_TAG, msg); | ||||
|         if (StringUtils.isNotNull(data)) | ||||
|         { | ||||
|             super.put(DATA_TAG, data); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 返回成功消息 | ||||
|      *  | ||||
|      * @return 成功消息 | ||||
|      */ | ||||
|     public static AjaxResult success() | ||||
|     { | ||||
|         return AjaxResult.success("操作成功"); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 返回成功数据 | ||||
|      *  | ||||
|      * @return 成功消息 | ||||
|      */ | ||||
|     public static AjaxResult success(Object data) | ||||
|     { | ||||
|         return AjaxResult.success("操作成功", data); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 返回成功消息 | ||||
|      *  | ||||
|      * @param msg 返回内容 | ||||
|      * @return 成功消息 | ||||
|      */ | ||||
|     public static AjaxResult success(String msg) | ||||
|     { | ||||
|         return AjaxResult.success(msg, null); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 返回成功消息 | ||||
|      *  | ||||
|      * @param msg 返回内容 | ||||
|      * @param data 数据对象 | ||||
|      * @return 成功消息 | ||||
|      */ | ||||
|     public static AjaxResult success(String msg, Object data) | ||||
|     { | ||||
|         return new AjaxResult(HttpStatus.SUCCESS, msg, data); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 返回错误消息 | ||||
|      *  | ||||
|      * @return | ||||
|      */ | ||||
|     public static AjaxResult error() | ||||
|     { | ||||
|         return AjaxResult.error("操作失败"); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 返回错误消息 | ||||
|      *  | ||||
|      * @param msg 返回内容 | ||||
|      * @return 警告消息 | ||||
|      */ | ||||
|     public static AjaxResult error(String msg) | ||||
|     { | ||||
|         return AjaxResult.error(msg, null); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 返回错误消息 | ||||
|      *  | ||||
|      * @param msg 返回内容 | ||||
|      * @param data 数据对象 | ||||
|      * @return 警告消息 | ||||
|      */ | ||||
|     public static AjaxResult error(String msg, Object data) | ||||
|     { | ||||
|         return new AjaxResult(HttpStatus.ERROR, msg, data); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 返回错误消息 | ||||
|      *  | ||||
|      * @param code 状态码 | ||||
|      * @param msg 返回内容 | ||||
|      * @return 警告消息 | ||||
|      */ | ||||
|     public static AjaxResult error(int code, String msg) | ||||
|     { | ||||
|         return new AjaxResult(code, msg, null); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,143 @@ | ||||
| package com.stdiet.common.core.domain; | ||||
|  | ||||
| import java.io.Serializable; | ||||
| import java.util.Date; | ||||
| import java.util.HashMap; | ||||
| import java.util.Map; | ||||
| import com.fasterxml.jackson.annotation.JsonFormat; | ||||
| import com.fasterxml.jackson.annotation.JsonIgnore; | ||||
|  | ||||
| /** | ||||
|  * Entity基类 | ||||
|  *  | ||||
|  * @author stdiet | ||||
|  */ | ||||
| public class BaseEntity implements Serializable | ||||
| { | ||||
|     private static final long serialVersionUID = 1L; | ||||
|  | ||||
|     /** 搜索值 */ | ||||
|     private String searchValue; | ||||
|  | ||||
|     /** 创建者 */ | ||||
|     private String createBy; | ||||
|  | ||||
|     /** 创建时间 */ | ||||
|     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") | ||||
|     private Date createTime; | ||||
|  | ||||
|     /** 更新者 */ | ||||
|     private String updateBy; | ||||
|  | ||||
|     /** 更新时间 */ | ||||
|     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") | ||||
|     private Date updateTime; | ||||
|  | ||||
|     /** 备注 */ | ||||
|     private String remark; | ||||
|  | ||||
|     /** 开始时间 */ | ||||
|     @JsonIgnore | ||||
|     private String beginTime; | ||||
|  | ||||
|     /** 结束时间 */ | ||||
|     @JsonIgnore | ||||
|     private String endTime; | ||||
|  | ||||
|     /** 请求参数 */ | ||||
|     private Map<String, Object> params; | ||||
|  | ||||
|     public String getSearchValue() | ||||
|     { | ||||
|         return searchValue; | ||||
|     } | ||||
|  | ||||
|     public void setSearchValue(String searchValue) | ||||
|     { | ||||
|         this.searchValue = searchValue; | ||||
|     } | ||||
|  | ||||
|     public String getCreateBy() | ||||
|     { | ||||
|         return createBy; | ||||
|     } | ||||
|  | ||||
|     public void setCreateBy(String createBy) | ||||
|     { | ||||
|         this.createBy = createBy; | ||||
|     } | ||||
|  | ||||
|     public Date getCreateTime() | ||||
|     { | ||||
|         return createTime; | ||||
|     } | ||||
|  | ||||
|     public void setCreateTime(Date createTime) | ||||
|     { | ||||
|         this.createTime = createTime; | ||||
|     } | ||||
|  | ||||
|     public String getUpdateBy() | ||||
|     { | ||||
|         return updateBy; | ||||
|     } | ||||
|  | ||||
|     public void setUpdateBy(String updateBy) | ||||
|     { | ||||
|         this.updateBy = updateBy; | ||||
|     } | ||||
|  | ||||
|     public Date getUpdateTime() | ||||
|     { | ||||
|         return updateTime; | ||||
|     } | ||||
|  | ||||
|     public void setUpdateTime(Date updateTime) | ||||
|     { | ||||
|         this.updateTime = updateTime; | ||||
|     } | ||||
|  | ||||
|     public String getRemark() | ||||
|     { | ||||
|         return remark; | ||||
|     } | ||||
|  | ||||
|     public void setRemark(String remark) | ||||
|     { | ||||
|         this.remark = remark; | ||||
|     } | ||||
|  | ||||
|     public String getBeginTime() | ||||
|     { | ||||
|         return beginTime; | ||||
|     } | ||||
|  | ||||
|     public void setBeginTime(String beginTime) | ||||
|     { | ||||
|         this.beginTime = beginTime; | ||||
|     } | ||||
|  | ||||
|     public String getEndTime() | ||||
|     { | ||||
|         return endTime; | ||||
|     } | ||||
|  | ||||
|     public void setEndTime(String endTime) | ||||
|     { | ||||
|         this.endTime = endTime; | ||||
|     } | ||||
|  | ||||
|     public Map<String, Object> getParams() | ||||
|     { | ||||
|         if (params == null) | ||||
|         { | ||||
|             params = new HashMap<>(); | ||||
|         } | ||||
|         return params; | ||||
|     } | ||||
|  | ||||
|     public void setParams(Map<String, Object> params) | ||||
|     { | ||||
|         this.params = params; | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,79 @@ | ||||
| package com.stdiet.common.core.domain; | ||||
|  | ||||
| import java.util.ArrayList; | ||||
| import java.util.List; | ||||
|  | ||||
| /** | ||||
|  * Tree基类 | ||||
|  *  | ||||
|  * @author stdiet | ||||
|  */ | ||||
| public class TreeEntity extends BaseEntity | ||||
| { | ||||
|     private static final long serialVersionUID = 1L; | ||||
|  | ||||
|     /** 父菜单名称 */ | ||||
|     private String parentName; | ||||
|  | ||||
|     /** 父菜单ID */ | ||||
|     private Long parentId; | ||||
|  | ||||
|     /** 显示顺序 */ | ||||
|     private Integer orderNum; | ||||
|  | ||||
|     /** 祖级列表 */ | ||||
|     private String ancestors; | ||||
|  | ||||
|     /** 子部门 */ | ||||
|     private List<?> children = new ArrayList<>(); | ||||
|  | ||||
|     public String getParentName() | ||||
|     { | ||||
|         return parentName; | ||||
|     } | ||||
|  | ||||
|     public void setParentName(String parentName) | ||||
|     { | ||||
|         this.parentName = parentName; | ||||
|     } | ||||
|  | ||||
|     public Long getParentId() | ||||
|     { | ||||
|         return parentId; | ||||
|     } | ||||
|  | ||||
|     public void setParentId(Long parentId) | ||||
|     { | ||||
|         this.parentId = parentId; | ||||
|     } | ||||
|  | ||||
|     public Integer getOrderNum() | ||||
|     { | ||||
|         return orderNum; | ||||
|     } | ||||
|  | ||||
|     public void setOrderNum(Integer orderNum) | ||||
|     { | ||||
|         this.orderNum = orderNum; | ||||
|     } | ||||
|  | ||||
|     public String getAncestors() | ||||
|     { | ||||
|         return ancestors; | ||||
|     } | ||||
|  | ||||
|     public void setAncestors(String ancestors) | ||||
|     { | ||||
|         this.ancestors = ancestors; | ||||
|     } | ||||
|  | ||||
|     public List<?> getChildren() | ||||
|     { | ||||
|         return children; | ||||
|     } | ||||
|  | ||||
|     public void setChildren(List<?> children) | ||||
|     { | ||||
|         this.children = children; | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,77 @@ | ||||
| package com.stdiet.common.core.domain; | ||||
|  | ||||
| import java.io.Serializable; | ||||
| import java.util.List; | ||||
| import java.util.stream.Collectors; | ||||
| import com.fasterxml.jackson.annotation.JsonInclude; | ||||
| import com.stdiet.common.core.domain.entity.SysDept; | ||||
| import com.stdiet.common.core.domain.entity.SysMenu; | ||||
|  | ||||
| /** | ||||
|  * Treeselect树结构实体类 | ||||
|  *  | ||||
|  * @author stdiet | ||||
|  */ | ||||
| public class TreeSelect implements Serializable | ||||
| { | ||||
|     private static final long serialVersionUID = 1L; | ||||
|  | ||||
|     /** 节点ID */ | ||||
|     private Long id; | ||||
|  | ||||
|     /** 节点名称 */ | ||||
|     private String label; | ||||
|  | ||||
|     /** 子节点 */ | ||||
|     @JsonInclude(JsonInclude.Include.NON_EMPTY) | ||||
|     private List<TreeSelect> children; | ||||
|  | ||||
|     public TreeSelect() | ||||
|     { | ||||
|  | ||||
|     } | ||||
|  | ||||
|     public TreeSelect(SysDept dept) | ||||
|     { | ||||
|         this.id = dept.getDeptId(); | ||||
|         this.label = dept.getDeptName(); | ||||
|         this.children = dept.getChildren().stream().map(TreeSelect::new).collect(Collectors.toList()); | ||||
|     } | ||||
|  | ||||
|     public TreeSelect(SysMenu menu) | ||||
|     { | ||||
|         this.id = menu.getMenuId(); | ||||
|         this.label = menu.getMenuName(); | ||||
|         this.children = menu.getChildren().stream().map(TreeSelect::new).collect(Collectors.toList()); | ||||
|     } | ||||
|  | ||||
|     public Long getId() | ||||
|     { | ||||
|         return id; | ||||
|     } | ||||
|  | ||||
|     public void setId(Long id) | ||||
|     { | ||||
|         this.id = id; | ||||
|     } | ||||
|  | ||||
|     public String getLabel() | ||||
|     { | ||||
|         return label; | ||||
|     } | ||||
|  | ||||
|     public void setLabel(String label) | ||||
|     { | ||||
|         this.label = label; | ||||
|     } | ||||
|  | ||||
|     public List<TreeSelect> getChildren() | ||||
|     { | ||||
|         return children; | ||||
|     } | ||||
|  | ||||
|     public void setChildren(List<TreeSelect> children) | ||||
|     { | ||||
|         this.children = children; | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,202 @@ | ||||
| package com.stdiet.common.core.domain.entity; | ||||
|  | ||||
| import java.util.ArrayList; | ||||
| import java.util.List; | ||||
| import javax.validation.constraints.Email; | ||||
| import javax.validation.constraints.NotBlank; | ||||
| import javax.validation.constraints.Size; | ||||
| import org.apache.commons.lang3.builder.ToStringBuilder; | ||||
| import org.apache.commons.lang3.builder.ToStringStyle; | ||||
| import com.stdiet.common.core.domain.BaseEntity; | ||||
|  | ||||
| /** | ||||
|  * 部门表 sys_dept | ||||
|  *  | ||||
|  * @author stdiet | ||||
|  */ | ||||
| public class SysDept extends BaseEntity | ||||
| { | ||||
|     private static final long serialVersionUID = 1L; | ||||
|  | ||||
|     /** 部门ID */ | ||||
|     private Long deptId; | ||||
|  | ||||
|     /** 父部门ID */ | ||||
|     private Long parentId; | ||||
|  | ||||
|     /** 祖级列表 */ | ||||
|     private String ancestors; | ||||
|  | ||||
|     /** 部门名称 */ | ||||
|     private String deptName; | ||||
|  | ||||
|     /** 显示顺序 */ | ||||
|     private String orderNum; | ||||
|  | ||||
|     /** 负责人 */ | ||||
|     private String leader; | ||||
|  | ||||
|     /** 联系电话 */ | ||||
|     private String phone; | ||||
|  | ||||
|     /** 邮箱 */ | ||||
|     private String email; | ||||
|  | ||||
|     /** 部门状态:0正常,1停用 */ | ||||
|     private String status; | ||||
|  | ||||
|     /** 删除标志(0代表存在 2代表删除) */ | ||||
|     private String delFlag; | ||||
|  | ||||
|     /** 父部门名称 */ | ||||
|     private String parentName; | ||||
|      | ||||
|     /** 子部门 */ | ||||
|     private List<SysDept> children = new ArrayList<SysDept>(); | ||||
|  | ||||
|     public Long getDeptId() | ||||
|     { | ||||
|         return deptId; | ||||
|     } | ||||
|  | ||||
|     public void setDeptId(Long deptId) | ||||
|     { | ||||
|         this.deptId = deptId; | ||||
|     } | ||||
|  | ||||
|     public Long getParentId() | ||||
|     { | ||||
|         return parentId; | ||||
|     } | ||||
|  | ||||
|     public void setParentId(Long parentId) | ||||
|     { | ||||
|         this.parentId = parentId; | ||||
|     } | ||||
|  | ||||
|     public String getAncestors() | ||||
|     { | ||||
|         return ancestors; | ||||
|     } | ||||
|  | ||||
|     public void setAncestors(String ancestors) | ||||
|     { | ||||
|         this.ancestors = ancestors; | ||||
|     } | ||||
|  | ||||
|     @NotBlank(message = "部门名称不能为空") | ||||
|     @Size(min = 0, max = 30, message = "部门名称长度不能超过30个字符") | ||||
|     public String getDeptName() | ||||
|     { | ||||
|         return deptName; | ||||
|     } | ||||
|  | ||||
|     public void setDeptName(String deptName) | ||||
|     { | ||||
|         this.deptName = deptName; | ||||
|     } | ||||
|  | ||||
|     @NotBlank(message = "显示顺序不能为空") | ||||
|     public String getOrderNum() | ||||
|     { | ||||
|         return orderNum; | ||||
|     } | ||||
|  | ||||
|     public void setOrderNum(String orderNum) | ||||
|     { | ||||
|         this.orderNum = orderNum; | ||||
|     } | ||||
|  | ||||
|     public String getLeader() | ||||
|     { | ||||
|         return leader; | ||||
|     } | ||||
|  | ||||
|     public void setLeader(String leader) | ||||
|     { | ||||
|         this.leader = leader; | ||||
|     } | ||||
|  | ||||
|     @Size(min = 0, max = 11, message = "联系电话长度不能超过11个字符") | ||||
|     public String getPhone() | ||||
|     { | ||||
|         return phone; | ||||
|     } | ||||
|  | ||||
|     public void setPhone(String phone) | ||||
|     { | ||||
|         this.phone = phone; | ||||
|     } | ||||
|  | ||||
|     @Email(message = "邮箱格式不正确") | ||||
|     @Size(min = 0, max = 50, message = "邮箱长度不能超过50个字符") | ||||
|     public String getEmail() | ||||
|     { | ||||
|         return email; | ||||
|     } | ||||
|  | ||||
|     public void setEmail(String email) | ||||
|     { | ||||
|         this.email = email; | ||||
|     } | ||||
|  | ||||
|     public String getStatus() | ||||
|     { | ||||
|         return status; | ||||
|     } | ||||
|  | ||||
|     public void setStatus(String status) | ||||
|     { | ||||
|         this.status = status; | ||||
|     } | ||||
|  | ||||
|     public String getDelFlag() | ||||
|     { | ||||
|         return delFlag; | ||||
|     } | ||||
|  | ||||
|     public void setDelFlag(String delFlag) | ||||
|     { | ||||
|         this.delFlag = delFlag; | ||||
|     } | ||||
|  | ||||
|     public String getParentName() | ||||
|     { | ||||
|         return parentName; | ||||
|     } | ||||
|  | ||||
|     public void setParentName(String parentName) | ||||
|     { | ||||
|         this.parentName = parentName; | ||||
|     } | ||||
|  | ||||
|     public List<SysDept> getChildren() | ||||
|     { | ||||
|         return children; | ||||
|     } | ||||
|  | ||||
|     public void setChildren(List<SysDept> children) | ||||
|     { | ||||
|         this.children = children; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public String toString() { | ||||
|         return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) | ||||
|             .append("deptId", getDeptId()) | ||||
|             .append("parentId", getParentId()) | ||||
|             .append("ancestors", getAncestors()) | ||||
|             .append("deptName", getDeptName()) | ||||
|             .append("orderNum", getOrderNum()) | ||||
|             .append("leader", getLeader()) | ||||
|             .append("phone", getPhone()) | ||||
|             .append("email", getEmail()) | ||||
|             .append("status", getStatus()) | ||||
|             .append("delFlag", getDelFlag()) | ||||
|             .append("createBy", getCreateBy()) | ||||
|             .append("createTime", getCreateTime()) | ||||
|             .append("updateBy", getUpdateBy()) | ||||
|             .append("updateTime", getUpdateTime()) | ||||
|             .toString(); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,176 @@ | ||||
| package com.stdiet.common.core.domain.entity; | ||||
|  | ||||
| import javax.validation.constraints.NotBlank; | ||||
| import javax.validation.constraints.Size; | ||||
| import org.apache.commons.lang3.builder.ToStringBuilder; | ||||
| import org.apache.commons.lang3.builder.ToStringStyle; | ||||
| import com.stdiet.common.annotation.Excel; | ||||
| import com.stdiet.common.annotation.Excel.ColumnType; | ||||
| import com.stdiet.common.constant.UserConstants; | ||||
| import com.stdiet.common.core.domain.BaseEntity; | ||||
|  | ||||
| /** | ||||
|  * 字典数据表 sys_dict_data | ||||
|  *  | ||||
|  * @author stdiet | ||||
|  */ | ||||
| public class SysDictData extends BaseEntity | ||||
| { | ||||
|     private static final long serialVersionUID = 1L; | ||||
|  | ||||
|     /** 字典编码 */ | ||||
|     @Excel(name = "字典编码", cellType = ColumnType.NUMERIC) | ||||
|     private Long dictCode; | ||||
|  | ||||
|     /** 字典排序 */ | ||||
|     @Excel(name = "字典排序", cellType = ColumnType.NUMERIC) | ||||
|     private Long dictSort; | ||||
|  | ||||
|     /** 字典标签 */ | ||||
|     @Excel(name = "字典标签") | ||||
|     private String dictLabel; | ||||
|  | ||||
|     /** 字典键值 */ | ||||
|     @Excel(name = "字典键值") | ||||
|     private String dictValue; | ||||
|  | ||||
|     /** 字典类型 */ | ||||
|     @Excel(name = "字典类型") | ||||
|     private String dictType; | ||||
|  | ||||
|     /** 样式属性(其他样式扩展) */ | ||||
|     private String cssClass; | ||||
|  | ||||
|     /** 表格字典样式 */ | ||||
|     private String listClass; | ||||
|  | ||||
|     /** 是否默认(Y是 N否) */ | ||||
|     @Excel(name = "是否默认", readConverterExp = "Y=是,N=否") | ||||
|     private String isDefault; | ||||
|  | ||||
|     /** 状态(0正常 1停用) */ | ||||
|     @Excel(name = "状态", readConverterExp = "0=正常,1=停用") | ||||
|     private String status; | ||||
|  | ||||
|     public Long getDictCode() | ||||
|     { | ||||
|         return dictCode; | ||||
|     } | ||||
|  | ||||
|     public void setDictCode(Long dictCode) | ||||
|     { | ||||
|         this.dictCode = dictCode; | ||||
|     } | ||||
|  | ||||
|     public Long getDictSort() | ||||
|     { | ||||
|         return dictSort; | ||||
|     } | ||||
|  | ||||
|     public void setDictSort(Long dictSort) | ||||
|     { | ||||
|         this.dictSort = dictSort; | ||||
|     } | ||||
|  | ||||
|     @NotBlank(message = "字典标签不能为空") | ||||
|     @Size(min = 0, max = 100, message = "字典标签长度不能超过100个字符") | ||||
|     public String getDictLabel() | ||||
|     { | ||||
|         return dictLabel; | ||||
|     } | ||||
|  | ||||
|     public void setDictLabel(String dictLabel) | ||||
|     { | ||||
|         this.dictLabel = dictLabel; | ||||
|     } | ||||
|  | ||||
|     @NotBlank(message = "字典键值不能为空") | ||||
|     @Size(min = 0, max = 100, message = "字典键值长度不能超过100个字符") | ||||
|     public String getDictValue() | ||||
|     { | ||||
|         return dictValue; | ||||
|     } | ||||
|  | ||||
|     public void setDictValue(String dictValue) | ||||
|     { | ||||
|         this.dictValue = dictValue; | ||||
|     } | ||||
|  | ||||
|     @NotBlank(message = "字典类型不能为空") | ||||
|     @Size(min = 0, max = 100, message = "字典类型长度不能超过100个字符") | ||||
|     public String getDictType() | ||||
|     { | ||||
|         return dictType; | ||||
|     } | ||||
|  | ||||
|     public void setDictType(String dictType) | ||||
|     { | ||||
|         this.dictType = dictType; | ||||
|     } | ||||
|  | ||||
|     @Size(min = 0, max = 100, message = "样式属性长度不能超过100个字符") | ||||
|     public String getCssClass() | ||||
|     { | ||||
|         return cssClass; | ||||
|     } | ||||
|  | ||||
|     public void setCssClass(String cssClass) | ||||
|     { | ||||
|         this.cssClass = cssClass; | ||||
|     } | ||||
|  | ||||
|     public String getListClass() | ||||
|     { | ||||
|         return listClass; | ||||
|     } | ||||
|  | ||||
|     public void setListClass(String listClass) | ||||
|     { | ||||
|         this.listClass = listClass; | ||||
|     } | ||||
|  | ||||
|     public boolean getDefault() | ||||
|     { | ||||
|         return UserConstants.YES.equals(this.isDefault) ? true : false; | ||||
|     } | ||||
|  | ||||
|     public String getIsDefault() | ||||
|     { | ||||
|         return isDefault; | ||||
|     } | ||||
|  | ||||
|     public void setIsDefault(String isDefault) | ||||
|     { | ||||
|         this.isDefault = isDefault; | ||||
|     } | ||||
|  | ||||
|     public String getStatus() | ||||
|     { | ||||
|         return status; | ||||
|     } | ||||
|  | ||||
|     public void setStatus(String status) | ||||
|     { | ||||
|         this.status = status; | ||||
|     } | ||||
|      | ||||
|     @Override | ||||
|     public String toString() { | ||||
|         return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) | ||||
|             .append("dictCode", getDictCode()) | ||||
|             .append("dictSort", getDictSort()) | ||||
|             .append("dictLabel", getDictLabel()) | ||||
|             .append("dictValue", getDictValue()) | ||||
|             .append("dictType", getDictType()) | ||||
|             .append("cssClass", getCssClass()) | ||||
|             .append("listClass", getListClass()) | ||||
|             .append("isDefault", getIsDefault()) | ||||
|             .append("status", getStatus()) | ||||
|             .append("createBy", getCreateBy()) | ||||
|             .append("createTime", getCreateTime()) | ||||
|             .append("updateBy", getUpdateBy()) | ||||
|             .append("updateTime", getUpdateTime()) | ||||
|             .append("remark", getRemark()) | ||||
|             .toString(); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,94 @@ | ||||
| package com.stdiet.common.core.domain.entity; | ||||
|  | ||||
| import javax.validation.constraints.NotBlank; | ||||
| import javax.validation.constraints.Size; | ||||
| import org.apache.commons.lang3.builder.ToStringBuilder; | ||||
| import org.apache.commons.lang3.builder.ToStringStyle; | ||||
| import com.stdiet.common.annotation.Excel; | ||||
| import com.stdiet.common.annotation.Excel.ColumnType; | ||||
| import com.stdiet.common.core.domain.BaseEntity; | ||||
|  | ||||
| /** | ||||
|  * 字典类型表 sys_dict_type | ||||
|  *  | ||||
|  * @author ruoyi | ||||
|  */ | ||||
| public class SysDictType extends BaseEntity | ||||
| { | ||||
|     private static final long serialVersionUID = 1L; | ||||
|  | ||||
|     /** 字典主键 */ | ||||
|     @Excel(name = "字典主键", cellType = ColumnType.NUMERIC) | ||||
|     private Long dictId; | ||||
|  | ||||
|     /** 字典名称 */ | ||||
|     @Excel(name = "字典名称") | ||||
|     private String dictName; | ||||
|  | ||||
|     /** 字典类型 */ | ||||
|     @Excel(name = "字典类型") | ||||
|     private String dictType; | ||||
|  | ||||
|     /** 状态(0正常 1停用) */ | ||||
|     @Excel(name = "状态", readConverterExp = "0=正常,1=停用") | ||||
|     private String status; | ||||
|  | ||||
|     public Long getDictId() | ||||
|     { | ||||
|         return dictId; | ||||
|     } | ||||
|  | ||||
|     public void setDictId(Long dictId) | ||||
|     { | ||||
|         this.dictId = dictId; | ||||
|     } | ||||
|  | ||||
|     @NotBlank(message = "字典名称不能为空") | ||||
|     @Size(min = 0, max = 100, message = "字典类型名称长度不能超过100个字符") | ||||
|     public String getDictName() | ||||
|     { | ||||
|         return dictName; | ||||
|     } | ||||
|  | ||||
|     public void setDictName(String dictName) | ||||
|     { | ||||
|         this.dictName = dictName; | ||||
|     } | ||||
|  | ||||
|     @NotBlank(message = "字典类型不能为空") | ||||
|     @Size(min = 0, max = 100, message = "字典类型类型长度不能超过100个字符") | ||||
|     public String getDictType() | ||||
|     { | ||||
|         return dictType; | ||||
|     } | ||||
|  | ||||
|     public void setDictType(String dictType) | ||||
|     { | ||||
|         this.dictType = dictType; | ||||
|     } | ||||
|  | ||||
|     public String getStatus() | ||||
|     { | ||||
|         return status; | ||||
|     } | ||||
|  | ||||
|     public void setStatus(String status) | ||||
|     { | ||||
|         this.status = status; | ||||
|     } | ||||
|      | ||||
|     @Override | ||||
|     public String toString() { | ||||
|         return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) | ||||
|             .append("dictId", getDictId()) | ||||
|             .append("dictName", getDictName()) | ||||
|             .append("dictType", getDictType()) | ||||
|             .append("status", getStatus()) | ||||
|             .append("createBy", getCreateBy()) | ||||
|             .append("createTime", getCreateTime()) | ||||
|             .append("updateBy", getUpdateBy()) | ||||
|             .append("updateTime", getUpdateTime()) | ||||
|             .append("remark", getRemark()) | ||||
|             .toString(); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,245 @@ | ||||
| package com.stdiet.common.core.domain.entity; | ||||
|  | ||||
| import java.util.ArrayList; | ||||
| import java.util.List; | ||||
| import javax.validation.constraints.NotBlank; | ||||
| import javax.validation.constraints.Size; | ||||
| import org.apache.commons.lang3.builder.ToStringBuilder; | ||||
| import org.apache.commons.lang3.builder.ToStringStyle; | ||||
| import com.stdiet.common.core.domain.BaseEntity; | ||||
|  | ||||
| /** | ||||
|  * 菜单权限表 sys_menu | ||||
|  *  | ||||
|  * @author stdiet | ||||
|  */ | ||||
| public class SysMenu extends BaseEntity | ||||
| { | ||||
|     private static final long serialVersionUID = 1L; | ||||
|  | ||||
|     /** 菜单ID */ | ||||
|     private Long menuId; | ||||
|  | ||||
|     /** 菜单名称 */ | ||||
|     private String menuName; | ||||
|  | ||||
|     /** 父菜单名称 */ | ||||
|     private String parentName; | ||||
|  | ||||
|     /** 父菜单ID */ | ||||
|     private Long parentId; | ||||
|  | ||||
|     /** 显示顺序 */ | ||||
|     private String orderNum; | ||||
|  | ||||
|     /** 路由地址 */ | ||||
|     private String path; | ||||
|  | ||||
|     /** 组件路径 */ | ||||
|     private String component; | ||||
|  | ||||
|     /** 是否为外链(0是 1否) */ | ||||
|     private String isFrame; | ||||
|  | ||||
|     /** 是否缓存(0缓存 1不缓存) */ | ||||
|     private String isCache; | ||||
|  | ||||
|     /** 类型(M目录 C菜单 F按钮) */ | ||||
|     private String menuType; | ||||
|  | ||||
|     /** 显示状态(0显示 1隐藏) */ | ||||
|     private String visible; | ||||
|      | ||||
|     /** 菜单状态(0显示 1隐藏) */ | ||||
|     private String status; | ||||
|  | ||||
|     /** 权限字符串 */ | ||||
|     private String perms; | ||||
|  | ||||
|     /** 菜单图标 */ | ||||
|     private String icon; | ||||
|  | ||||
|     /** 子菜单 */ | ||||
|     private List<SysMenu> children = new ArrayList<SysMenu>(); | ||||
|  | ||||
|     public Long getMenuId() | ||||
|     { | ||||
|         return menuId; | ||||
|     } | ||||
|  | ||||
|     public void setMenuId(Long menuId) | ||||
|     { | ||||
|         this.menuId = menuId; | ||||
|     } | ||||
|  | ||||
|     @NotBlank(message = "菜单名称不能为空") | ||||
|     @Size(min = 0, max = 50, message = "菜单名称长度不能超过50个字符") | ||||
|     public String getMenuName() | ||||
|     { | ||||
|         return menuName; | ||||
|     } | ||||
|  | ||||
|     public void setMenuName(String menuName) | ||||
|     { | ||||
|         this.menuName = menuName; | ||||
|     } | ||||
|  | ||||
|     public String getParentName() | ||||
|     { | ||||
|         return parentName; | ||||
|     } | ||||
|  | ||||
|     public void setParentName(String parentName) | ||||
|     { | ||||
|         this.parentName = parentName; | ||||
|     } | ||||
|  | ||||
|     public Long getParentId() | ||||
|     { | ||||
|         return parentId; | ||||
|     } | ||||
|  | ||||
|     public void setParentId(Long parentId) | ||||
|     { | ||||
|         this.parentId = parentId; | ||||
|     } | ||||
|  | ||||
|     @NotBlank(message = "显示顺序不能为空") | ||||
|     public String getOrderNum() | ||||
|     { | ||||
|         return orderNum; | ||||
|     } | ||||
|  | ||||
|     public void setOrderNum(String orderNum) | ||||
|     { | ||||
|         this.orderNum = orderNum; | ||||
|     } | ||||
|  | ||||
|     @Size(min = 0, max = 200, message = "路由地址不能超过200个字符") | ||||
|     public String getPath() | ||||
|     { | ||||
|         return path; | ||||
|     } | ||||
|  | ||||
|     public void setPath(String path) | ||||
|     { | ||||
|         this.path = path; | ||||
|     } | ||||
|  | ||||
|     @Size(min = 0, max = 200, message = "组件路径不能超过255个字符") | ||||
|     public String getComponent() | ||||
|     { | ||||
|         return component; | ||||
|     } | ||||
|  | ||||
|     public void setComponent(String component) | ||||
|     { | ||||
|         this.component = component; | ||||
|     } | ||||
|  | ||||
|     public String getIsFrame() | ||||
|     { | ||||
|         return isFrame; | ||||
|     } | ||||
|  | ||||
|     public void setIsFrame(String isFrame) | ||||
|     { | ||||
|         this.isFrame = isFrame; | ||||
|     } | ||||
|  | ||||
|     public String getIsCache() | ||||
|     { | ||||
|         return isCache; | ||||
|     } | ||||
|  | ||||
|     public void setIsCache(String isCache) | ||||
|     { | ||||
|         this.isCache = isCache; | ||||
|     } | ||||
|  | ||||
|     @NotBlank(message = "菜单类型不能为空") | ||||
|     public String getMenuType() | ||||
|     { | ||||
|         return menuType; | ||||
|     } | ||||
|  | ||||
|     public void setMenuType(String menuType) | ||||
|     { | ||||
|         this.menuType = menuType; | ||||
|     } | ||||
|  | ||||
|     public String getVisible() | ||||
|     { | ||||
|         return visible; | ||||
|     } | ||||
|  | ||||
|     public void setVisible(String visible) | ||||
|     { | ||||
|         this.visible = visible; | ||||
|     } | ||||
|  | ||||
|     public String getStatus() | ||||
|     { | ||||
|         return status; | ||||
|     } | ||||
|  | ||||
|     public void setStatus(String status) | ||||
|     { | ||||
|         this.status = status; | ||||
|     } | ||||
|  | ||||
|     @Size(min = 0, max = 100, message = "权限标识长度不能超过100个字符") | ||||
|     public String getPerms() | ||||
|     { | ||||
|         return perms; | ||||
|     } | ||||
|  | ||||
|     public void setPerms(String perms) | ||||
|     { | ||||
|         this.perms = perms; | ||||
|     } | ||||
|  | ||||
|     public String getIcon() | ||||
|     { | ||||
|         return icon; | ||||
|     } | ||||
|  | ||||
|     public void setIcon(String icon) | ||||
|     { | ||||
|         this.icon = icon; | ||||
|     } | ||||
|  | ||||
|     public List<SysMenu> getChildren() | ||||
|     { | ||||
|         return children; | ||||
|     } | ||||
|  | ||||
|     public void setChildren(List<SysMenu> children) | ||||
|     { | ||||
|         this.children = children; | ||||
|     } | ||||
|      | ||||
|     @Override | ||||
|     public String toString() { | ||||
|         return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) | ||||
|             .append("menuId", getMenuId()) | ||||
|             .append("menuName", getMenuName()) | ||||
|             .append("parentId", getParentId()) | ||||
|             .append("orderNum", getOrderNum()) | ||||
|             .append("path", getPath()) | ||||
|             .append("component", getComponent()) | ||||
|             .append("isFrame", getIsFrame()) | ||||
|             .append("IsCache", getIsCache()) | ||||
|             .append("menuType", getMenuType()) | ||||
|             .append("visible", getVisible()) | ||||
|             .append("status ", getStatus()) | ||||
|             .append("perms", getPerms()) | ||||
|             .append("icon", getIcon()) | ||||
|             .append("createBy", getCreateBy()) | ||||
|             .append("createTime", getCreateTime()) | ||||
|             .append("updateBy", getUpdateBy()) | ||||
|             .append("updateTime", getUpdateTime()) | ||||
|             .append("remark", getRemark()) | ||||
|             .toString(); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,226 @@ | ||||
| package com.stdiet.common.core.domain.entity; | ||||
|  | ||||
| import javax.validation.constraints.NotBlank; | ||||
| import javax.validation.constraints.Size; | ||||
| import org.apache.commons.lang3.builder.ToStringBuilder; | ||||
| import org.apache.commons.lang3.builder.ToStringStyle; | ||||
| import com.stdiet.common.annotation.Excel; | ||||
| import com.stdiet.common.annotation.Excel.ColumnType; | ||||
| import com.stdiet.common.core.domain.BaseEntity; | ||||
|  | ||||
| /** | ||||
|  * 角色表 sys_role | ||||
|  *  | ||||
|  * @author stdiet | ||||
|  */ | ||||
| public class SysRole extends BaseEntity | ||||
| { | ||||
|     private static final long serialVersionUID = 1L; | ||||
|  | ||||
|     /** 角色ID */ | ||||
|     @Excel(name = "角色序号", cellType = ColumnType.NUMERIC) | ||||
|     private Long roleId; | ||||
|  | ||||
|     /** 角色名称 */ | ||||
|     @Excel(name = "角色名称") | ||||
|     private String roleName; | ||||
|  | ||||
|     /** 角色权限 */ | ||||
|     @Excel(name = "角色权限") | ||||
|     private String roleKey; | ||||
|  | ||||
|     /** 角色排序 */ | ||||
|     @Excel(name = "角色排序") | ||||
|     private String roleSort; | ||||
|  | ||||
|     /** 数据范围(1:所有数据权限;2:自定义数据权限;3:本部门数据权限;4:本部门及以下数据权限) */ | ||||
|     @Excel(name = "数据范围", readConverterExp = "1=所有数据权限,2=自定义数据权限,3=本部门数据权限,4=本部门及以下数据权限") | ||||
|     private String dataScope; | ||||
|  | ||||
|     /** 菜单树选择项是否关联显示( 0:父子不互相关联显示 1:父子互相关联显示) */ | ||||
|     private boolean menuCheckStrictly; | ||||
|  | ||||
|     /** 部门树选择项是否关联显示(0:父子不互相关联显示 1:父子互相关联显示 ) */ | ||||
|     private boolean deptCheckStrictly; | ||||
|  | ||||
|     /** 角色状态(0正常 1停用) */ | ||||
|     @Excel(name = "角色状态", readConverterExp = "0=正常,1=停用") | ||||
|     private String status; | ||||
|  | ||||
|     /** 删除标志(0代表存在 2代表删除) */ | ||||
|     private String delFlag; | ||||
|  | ||||
|     /** 用户是否存在此角色标识 默认不存在 */ | ||||
|     private boolean flag = false; | ||||
|  | ||||
|     /** 菜单组 */ | ||||
|     private Long[] menuIds; | ||||
|  | ||||
|     /** 部门组(数据权限) */ | ||||
|     private Long[] deptIds; | ||||
|  | ||||
|     public SysRole() | ||||
|     { | ||||
|  | ||||
|     } | ||||
|  | ||||
|     public SysRole(Long roleId) | ||||
|     { | ||||
|         this.roleId = roleId; | ||||
|     } | ||||
|  | ||||
|     public Long getRoleId() | ||||
|     { | ||||
|         return roleId; | ||||
|     } | ||||
|  | ||||
|     public void setRoleId(Long roleId) | ||||
|     { | ||||
|         this.roleId = roleId; | ||||
|     } | ||||
|  | ||||
|     public boolean isAdmin() | ||||
|     { | ||||
|         return isAdmin(this.roleId); | ||||
|     } | ||||
|  | ||||
|     public static boolean isAdmin(Long roleId) | ||||
|     { | ||||
|         return roleId != null && 1L == roleId; | ||||
|     } | ||||
|  | ||||
|     @NotBlank(message = "角色名称不能为空") | ||||
|     @Size(min = 0, max = 30, message = "角色名称长度不能超过30个字符") | ||||
|     public String getRoleName() | ||||
|     { | ||||
|         return roleName; | ||||
|     } | ||||
|  | ||||
|     public void setRoleName(String roleName) | ||||
|     { | ||||
|         this.roleName = roleName; | ||||
|     } | ||||
|  | ||||
|     @NotBlank(message = "权限字符不能为空") | ||||
|     @Size(min = 0, max = 100, message = "权限字符长度不能超过100个字符") | ||||
|     public String getRoleKey() | ||||
|     { | ||||
|         return roleKey; | ||||
|     } | ||||
|  | ||||
|     public void setRoleKey(String roleKey) | ||||
|     { | ||||
|         this.roleKey = roleKey; | ||||
|     } | ||||
|  | ||||
|     @NotBlank(message = "显示顺序不能为空") | ||||
|     public String getRoleSort() | ||||
|     { | ||||
|         return roleSort; | ||||
|     } | ||||
|  | ||||
|     public void setRoleSort(String roleSort) | ||||
|     { | ||||
|         this.roleSort = roleSort; | ||||
|     } | ||||
|  | ||||
|     public String getDataScope() | ||||
|     { | ||||
|         return dataScope; | ||||
|     } | ||||
|  | ||||
|     public void setDataScope(String dataScope) | ||||
|     { | ||||
|         this.dataScope = dataScope; | ||||
|     } | ||||
|  | ||||
|     public boolean isMenuCheckStrictly() | ||||
|     { | ||||
|         return menuCheckStrictly; | ||||
|     } | ||||
|  | ||||
|     public void setMenuCheckStrictly(boolean menuCheckStrictly) | ||||
|     { | ||||
|         this.menuCheckStrictly = menuCheckStrictly; | ||||
|     } | ||||
|  | ||||
|     public boolean isDeptCheckStrictly() | ||||
|     { | ||||
|         return deptCheckStrictly; | ||||
|     } | ||||
|  | ||||
|     public void setDeptCheckStrictly(boolean deptCheckStrictly) | ||||
|     { | ||||
|         this.deptCheckStrictly = deptCheckStrictly; | ||||
|     } | ||||
|  | ||||
|     public String getStatus() | ||||
|     { | ||||
|         return status; | ||||
|     } | ||||
|  | ||||
|     public void setStatus(String status) | ||||
|     { | ||||
|         this.status = status; | ||||
|     } | ||||
|  | ||||
|     public String getDelFlag() | ||||
|     { | ||||
|         return delFlag; | ||||
|     } | ||||
|  | ||||
|     public void setDelFlag(String delFlag) | ||||
|     { | ||||
|         this.delFlag = delFlag; | ||||
|     } | ||||
|  | ||||
|     public boolean isFlag() | ||||
|     { | ||||
|         return flag; | ||||
|     } | ||||
|  | ||||
|     public void setFlag(boolean flag) | ||||
|     { | ||||
|         this.flag = flag; | ||||
|     } | ||||
|  | ||||
|     public Long[] getMenuIds() | ||||
|     { | ||||
|         return menuIds; | ||||
|     } | ||||
|  | ||||
|     public void setMenuIds(Long[] menuIds) | ||||
|     { | ||||
|         this.menuIds = menuIds; | ||||
|     } | ||||
|  | ||||
|     public Long[] getDeptIds() | ||||
|     { | ||||
|         return deptIds; | ||||
|     } | ||||
|  | ||||
|     public void setDeptIds(Long[] deptIds) | ||||
|     { | ||||
|         this.deptIds = deptIds; | ||||
|     } | ||||
|      | ||||
|     @Override | ||||
|     public String toString() { | ||||
|         return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) | ||||
|             .append("roleId", getRoleId()) | ||||
|             .append("roleName", getRoleName()) | ||||
|             .append("roleKey", getRoleKey()) | ||||
|             .append("roleSort", getRoleSort()) | ||||
|             .append("dataScope", getDataScope()) | ||||
|             .append("menuCheckStrictly", isMenuCheckStrictly()) | ||||
|             .append("deptCheckStrictly", isDeptCheckStrictly()) | ||||
|             .append("status", getStatus()) | ||||
|             .append("delFlag", getDelFlag()) | ||||
|             .append("createBy", getCreateBy()) | ||||
|             .append("createTime", getCreateTime()) | ||||
|             .append("updateBy", getUpdateBy()) | ||||
|             .append("updateTime", getUpdateTime()) | ||||
|             .append("remark", getRemark()) | ||||
|             .toString(); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,347 @@ | ||||
| package com.stdiet.common.core.domain.entity; | ||||
|  | ||||
| import java.util.Date; | ||||
| import java.util.List; | ||||
| import javax.validation.constraints.Email; | ||||
| import javax.validation.constraints.NotBlank; | ||||
| import javax.validation.constraints.Size; | ||||
|  | ||||
| import org.apache.commons.lang3.builder.ToStringBuilder; | ||||
| import org.apache.commons.lang3.builder.ToStringStyle; | ||||
| import com.fasterxml.jackson.annotation.JsonIgnore; | ||||
| import com.fasterxml.jackson.annotation.JsonProperty; | ||||
| import com.stdiet.common.annotation.Excel; | ||||
| import com.stdiet.common.annotation.Excel.ColumnType; | ||||
| import com.stdiet.common.annotation.Excel.Type; | ||||
| import com.stdiet.common.annotation.Excels; | ||||
| import com.stdiet.common.core.domain.BaseEntity; | ||||
|  | ||||
| /** | ||||
|  * 用户对象 sys_user | ||||
|  * | ||||
|  * @author stdiet | ||||
|  */ | ||||
| public class SysUser extends BaseEntity { | ||||
|     private static final long serialVersionUID = 1L; | ||||
|  | ||||
|     /** | ||||
|      * 用户ID | ||||
|      */ | ||||
|     @Excel(name = "用户序号", cellType = ColumnType.NUMERIC, prompt = "用户编号") | ||||
|     private Long userId; | ||||
|  | ||||
|     /** | ||||
|      * 部门ID | ||||
|      */ | ||||
|     @Excel(name = "部门编号", type = Type.IMPORT) | ||||
|     private Long deptId; | ||||
|  | ||||
|     /** | ||||
|      * 用户账号 | ||||
|      */ | ||||
|     @Excel(name = "登录名称") | ||||
|     private String userName; | ||||
|  | ||||
|     /** | ||||
|      * 用户昵称 | ||||
|      */ | ||||
|     @Excel(name = "用户名称") | ||||
|     private String nickName; | ||||
|  | ||||
|     /** | ||||
|      * 用户邮箱 | ||||
|      */ | ||||
|     @Excel(name = "用户邮箱") | ||||
|     private String email; | ||||
|  | ||||
|     /** | ||||
|      * 手机号码 | ||||
|      */ | ||||
|     @Excel(name = "手机号码") | ||||
|     private String phonenumber; | ||||
|  | ||||
|     /** | ||||
|      * 用户性别 | ||||
|      */ | ||||
|     @Excel(name = "用户性别", readConverterExp = "0=男,1=女,2=未知") | ||||
|     private String sex; | ||||
|  | ||||
|     /** | ||||
|      * 用户头像 | ||||
|      */ | ||||
|     private String avatar; | ||||
|  | ||||
|     /** | ||||
|      * 密码 | ||||
|      */ | ||||
|     private String password; | ||||
|  | ||||
|     /** | ||||
|      * 盐加密 | ||||
|      */ | ||||
|     private String salt; | ||||
|  | ||||
|     /** | ||||
|      * 帐号状态(0正常 1停用) | ||||
|      */ | ||||
|     @Excel(name = "帐号状态", readConverterExp = "0=正常,1=停用") | ||||
|     private String status; | ||||
|  | ||||
|     /** | ||||
|      * 删除标志(0代表存在 2代表删除) | ||||
|      */ | ||||
|     private String delFlag; | ||||
|  | ||||
|     /** | ||||
|      * 最后登录IP | ||||
|      */ | ||||
|     @Excel(name = "最后登录IP", type = Type.EXPORT) | ||||
|     private String loginIp; | ||||
|  | ||||
|     /** | ||||
|      * 最后登录时间 | ||||
|      */ | ||||
|     @Excel(name = "最后登录时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss", type = Type.EXPORT) | ||||
|     private Date loginDate; | ||||
|  | ||||
|     /** | ||||
|      * 部门对象 | ||||
|      */ | ||||
|     @Excels({ | ||||
|             @Excel(name = "部门名称", targetAttr = "deptName", type = Type.EXPORT), | ||||
|             @Excel(name = "部门负责人", targetAttr = "leader", type = Type.EXPORT) | ||||
|     }) | ||||
|     private SysDept dept; | ||||
|  | ||||
|     /** | ||||
|      * 角色对象 | ||||
|      */ | ||||
|     private List<SysRole> roles; | ||||
|  | ||||
|     /** | ||||
|      * 角色组 | ||||
|      */ | ||||
|     private Long[] roleIds; | ||||
|  | ||||
|     /** | ||||
|      * 岗位组 | ||||
|      */ | ||||
|     private Long[] postIds; | ||||
|  | ||||
|     private Long postId; | ||||
|  | ||||
|     @Excel(name = "岗位") | ||||
|     private String postName; | ||||
|  | ||||
|     public SysUser() { | ||||
|  | ||||
|     } | ||||
|  | ||||
|     public Long getPostId() { | ||||
|         return postId; | ||||
|     } | ||||
|  | ||||
|     public String getPostName() { | ||||
|         return postName; | ||||
|     } | ||||
|  | ||||
|     public void setPostId(Long postId) { | ||||
|         this.postId = postId; | ||||
|     } | ||||
|  | ||||
|     public void setPostName(String postName) { | ||||
|         this.postName = postName; | ||||
|     } | ||||
|  | ||||
|     public SysUser(Long userId) { | ||||
|         this.userId = userId; | ||||
|     } | ||||
|  | ||||
|     public Long getUserId() { | ||||
|         return userId; | ||||
|     } | ||||
|  | ||||
|     public void setUserId(Long userId) { | ||||
|         this.userId = userId; | ||||
|     } | ||||
|  | ||||
|     public boolean isAdmin() { | ||||
|         return isAdmin(this.userId); | ||||
|     } | ||||
|  | ||||
|     public static boolean isAdmin(Long userId) { | ||||
|         return userId != null && 1L == userId; | ||||
|     } | ||||
|  | ||||
|     public Long getDeptId() { | ||||
|         return deptId; | ||||
|     } | ||||
|  | ||||
|     public void setDeptId(Long deptId) { | ||||
|         this.deptId = deptId; | ||||
|     } | ||||
|  | ||||
|     @Size(min = 0, max = 30, message = "用户昵称长度不能超过30个字符") | ||||
|     public String getNickName() { | ||||
|         return nickName; | ||||
|     } | ||||
|  | ||||
|     public void setNickName(String nickName) { | ||||
|         this.nickName = nickName; | ||||
|     } | ||||
|  | ||||
|     @NotBlank(message = "用户账号不能为空") | ||||
|     @Size(min = 0, max = 30, message = "用户账号长度不能超过30个字符") | ||||
|     public String getUserName() { | ||||
|         return userName; | ||||
|     } | ||||
|  | ||||
|     public void setUserName(String userName) { | ||||
|         this.userName = userName; | ||||
|     } | ||||
|  | ||||
|     @Email(message = "邮箱格式不正确") | ||||
|     @Size(min = 0, max = 50, message = "邮箱长度不能超过50个字符") | ||||
|     public String getEmail() { | ||||
|         return email; | ||||
|     } | ||||
|  | ||||
|     public void setEmail(String email) { | ||||
|         this.email = email; | ||||
|     } | ||||
|  | ||||
|     @Size(min = 0, max = 11, message = "手机号码长度不能超过11个字符") | ||||
|     public String getPhonenumber() { | ||||
|         return phonenumber; | ||||
|     } | ||||
|  | ||||
|     public void setPhonenumber(String phonenumber) { | ||||
|         this.phonenumber = phonenumber; | ||||
|     } | ||||
|  | ||||
|     public String getSex() { | ||||
|         return sex; | ||||
|     } | ||||
|  | ||||
|     public void setSex(String sex) { | ||||
|         this.sex = sex; | ||||
|     } | ||||
|  | ||||
|     public String getAvatar() { | ||||
|         return avatar; | ||||
|     } | ||||
|  | ||||
|     public void setAvatar(String avatar) { | ||||
|         this.avatar = avatar; | ||||
|     } | ||||
|  | ||||
|     @JsonIgnore | ||||
|     @JsonProperty | ||||
|     public String getPassword() { | ||||
|         return password; | ||||
|     } | ||||
|  | ||||
|     public void setPassword(String password) { | ||||
|         this.password = password; | ||||
|     } | ||||
|  | ||||
|     public String getSalt() { | ||||
|         return salt; | ||||
|     } | ||||
|  | ||||
|     public void setSalt(String salt) { | ||||
|         this.salt = salt; | ||||
|     } | ||||
|  | ||||
|     public String getStatus() { | ||||
|         return status; | ||||
|     } | ||||
|  | ||||
|     public void setStatus(String status) { | ||||
|         this.status = status; | ||||
|     } | ||||
|  | ||||
|     public String getDelFlag() { | ||||
|         return delFlag; | ||||
|     } | ||||
|  | ||||
|     public void setDelFlag(String delFlag) { | ||||
|         this.delFlag = delFlag; | ||||
|     } | ||||
|  | ||||
|     public String getLoginIp() { | ||||
|         return loginIp; | ||||
|     } | ||||
|  | ||||
|     public void setLoginIp(String loginIp) { | ||||
|         this.loginIp = loginIp; | ||||
|     } | ||||
|  | ||||
|     public Date getLoginDate() { | ||||
|         return loginDate; | ||||
|     } | ||||
|  | ||||
|     public void setLoginDate(Date loginDate) { | ||||
|         this.loginDate = loginDate; | ||||
|     } | ||||
|  | ||||
|     public SysDept getDept() { | ||||
|         return dept; | ||||
|     } | ||||
|  | ||||
|     public void setDept(SysDept dept) { | ||||
|         this.dept = dept; | ||||
|     } | ||||
|  | ||||
|     public List<SysRole> getRoles() { | ||||
|         return roles; | ||||
|     } | ||||
|  | ||||
|     public void setRoles(List<SysRole> roles) { | ||||
|         this.roles = roles; | ||||
|     } | ||||
|  | ||||
|     public Long[] getRoleIds() { | ||||
|         return roleIds; | ||||
|     } | ||||
|  | ||||
|     public void setRoleIds(Long[] roleIds) { | ||||
|         this.roleIds = roleIds; | ||||
|     } | ||||
|  | ||||
|     public Long[] getPostIds() { | ||||
|         return postIds; | ||||
|     } | ||||
|  | ||||
|     public void setPostIds(Long[] postIds) { | ||||
|         this.postIds = postIds; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public String toString() { | ||||
|         return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE) | ||||
|                 .append("userId", getUserId()) | ||||
|                 .append("deptId", getDeptId()) | ||||
|                 .append("userName", getUserName()) | ||||
|                 .append("nickName", getNickName()) | ||||
|                 .append("email", getEmail()) | ||||
|                 .append("phonenumber", getPhonenumber()) | ||||
|                 .append("sex", getSex()) | ||||
|                 .append("avatar", getAvatar()) | ||||
|                 .append("password", getPassword()) | ||||
|                 .append("salt", getSalt()) | ||||
|                 .append("status", getStatus()) | ||||
|                 .append("delFlag", getDelFlag()) | ||||
|                 .append("loginIp", getLoginIp()) | ||||
|                 .append("loginDate", getLoginDate()) | ||||
|                 .append("createBy", getCreateBy()) | ||||
|                 .append("createTime", getCreateTime()) | ||||
|                 .append("updateBy", getUpdateBy()) | ||||
|                 .append("updateTime", getUpdateTime()) | ||||
|                 .append("remark", getRemark()) | ||||
|                 .append("dept", getDept()) | ||||
|                 .append("postId", getPostId()) | ||||
|                 .append("postName", getPostName()) | ||||
|                 .toString(); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,69 @@ | ||||
| package com.stdiet.common.core.domain.model; | ||||
|  | ||||
| /** | ||||
|  * 用户登录对象 | ||||
|  *  | ||||
|  * @author stdiet | ||||
|  */ | ||||
| public class LoginBody | ||||
| { | ||||
|     /** | ||||
|      * 用户名 | ||||
|      */ | ||||
|     private String username; | ||||
|  | ||||
|     /** | ||||
|      * 用户密码 | ||||
|      */ | ||||
|     private String password; | ||||
|  | ||||
|     /** | ||||
|      * 验证码 | ||||
|      */ | ||||
|     private String code; | ||||
|  | ||||
|     /** | ||||
|      * 唯一标识 | ||||
|      */ | ||||
|     private String uuid = ""; | ||||
|  | ||||
|     public String getUsername() | ||||
|     { | ||||
|         return username; | ||||
|     } | ||||
|  | ||||
|     public void setUsername(String username) | ||||
|     { | ||||
|         this.username = username; | ||||
|     } | ||||
|  | ||||
|     public String getPassword() | ||||
|     { | ||||
|         return password; | ||||
|     } | ||||
|  | ||||
|     public void setPassword(String password) | ||||
|     { | ||||
|         this.password = password; | ||||
|     } | ||||
|  | ||||
|     public String getCode() | ||||
|     { | ||||
|         return code; | ||||
|     } | ||||
|  | ||||
|     public void setCode(String code) | ||||
|     { | ||||
|         this.code = code; | ||||
|     } | ||||
|  | ||||
|     public String getUuid() | ||||
|     { | ||||
|         return uuid; | ||||
|     } | ||||
|  | ||||
|     public void setUuid(String uuid) | ||||
|     { | ||||
|         this.uuid = uuid; | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,228 @@ | ||||
| package com.stdiet.common.core.domain.model; | ||||
|  | ||||
| import java.util.Collection; | ||||
| import java.util.Set; | ||||
| import org.springframework.security.core.GrantedAuthority; | ||||
| import org.springframework.security.core.userdetails.UserDetails; | ||||
| import com.fasterxml.jackson.annotation.JsonIgnore; | ||||
| import com.stdiet.common.core.domain.entity.SysUser; | ||||
|  | ||||
| /** | ||||
|  * 登录用户身份权限 | ||||
|  *  | ||||
|  * @author stdiet | ||||
|  */ | ||||
| public class LoginUser implements UserDetails | ||||
| { | ||||
|     private static final long serialVersionUID = 1L; | ||||
|  | ||||
|     /** | ||||
|      * 用户唯一标识 | ||||
|      */ | ||||
|     private String token; | ||||
|  | ||||
|     /** | ||||
|      * 登录时间 | ||||
|      */ | ||||
|     private Long loginTime; | ||||
|  | ||||
|     /** | ||||
|      * 过期时间 | ||||
|      */ | ||||
|     private Long expireTime; | ||||
|  | ||||
|     /** | ||||
|      * 登录IP地址 | ||||
|      */ | ||||
|     private String ipaddr; | ||||
|  | ||||
|     /** | ||||
|      * 登录地点 | ||||
|      */ | ||||
|     private String loginLocation; | ||||
|  | ||||
|     /** | ||||
|      * 浏览器类型 | ||||
|      */ | ||||
|     private String browser; | ||||
|  | ||||
|     /** | ||||
|      * 操作系统 | ||||
|      */ | ||||
|     private String os; | ||||
|  | ||||
|     /** | ||||
|      * 权限列表 | ||||
|      */ | ||||
|     private Set<String> permissions; | ||||
|  | ||||
|     /** | ||||
|      * 用户信息 | ||||
|      */ | ||||
|     private SysUser user; | ||||
|  | ||||
|     public String getToken() | ||||
|     { | ||||
|         return token; | ||||
|     } | ||||
|  | ||||
|     public void setToken(String token) | ||||
|     { | ||||
|         this.token = token; | ||||
|     } | ||||
|  | ||||
|     public LoginUser() | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     public LoginUser(SysUser user, Set<String> permissions) | ||||
|     { | ||||
|         this.user = user; | ||||
|         this.permissions = permissions; | ||||
|     } | ||||
|  | ||||
|     @JsonIgnore | ||||
|     @Override | ||||
|     public String getPassword() | ||||
|     { | ||||
|         return user.getPassword(); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public String getUsername() | ||||
|     { | ||||
|         return user.getUserName(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 账户是否未过期,过期无法验证 | ||||
|      */ | ||||
|     @JsonIgnore | ||||
|     @Override | ||||
|     public boolean isAccountNonExpired() | ||||
|     { | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 指定用户是否解锁,锁定的用户无法进行身份验证 | ||||
|      *  | ||||
|      * @return | ||||
|      */ | ||||
|     @JsonIgnore | ||||
|     @Override | ||||
|     public boolean isAccountNonLocked() | ||||
|     { | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 指示是否已过期的用户的凭据(密码),过期的凭据防止认证 | ||||
|      *  | ||||
|      * @return | ||||
|      */ | ||||
|     @JsonIgnore | ||||
|     @Override | ||||
|     public boolean isCredentialsNonExpired() | ||||
|     { | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 是否可用 ,禁用的用户不能身份验证 | ||||
|      *  | ||||
|      * @return | ||||
|      */ | ||||
|     @JsonIgnore | ||||
|     @Override | ||||
|     public boolean isEnabled() | ||||
|     { | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     public Long getLoginTime() | ||||
|     { | ||||
|         return loginTime; | ||||
|     } | ||||
|  | ||||
|     public void setLoginTime(Long loginTime) | ||||
|     { | ||||
|         this.loginTime = loginTime; | ||||
|     } | ||||
|  | ||||
|     public String getIpaddr() | ||||
|     { | ||||
|         return ipaddr; | ||||
|     } | ||||
|  | ||||
|     public void setIpaddr(String ipaddr) | ||||
|     { | ||||
|         this.ipaddr = ipaddr; | ||||
|     } | ||||
|  | ||||
|     public String getLoginLocation() | ||||
|     { | ||||
|         return loginLocation; | ||||
|     } | ||||
|  | ||||
|     public void setLoginLocation(String loginLocation) | ||||
|     { | ||||
|         this.loginLocation = loginLocation; | ||||
|     } | ||||
|  | ||||
|     public String getBrowser() | ||||
|     { | ||||
|         return browser; | ||||
|     } | ||||
|  | ||||
|     public void setBrowser(String browser) | ||||
|     { | ||||
|         this.browser = browser; | ||||
|     } | ||||
|  | ||||
|     public String getOs() | ||||
|     { | ||||
|         return os; | ||||
|     } | ||||
|  | ||||
|     public void setOs(String os) | ||||
|     { | ||||
|         this.os = os; | ||||
|     } | ||||
|  | ||||
|     public Long getExpireTime() | ||||
|     { | ||||
|         return expireTime; | ||||
|     } | ||||
|  | ||||
|     public void setExpireTime(Long expireTime) | ||||
|     { | ||||
|         this.expireTime = expireTime; | ||||
|     } | ||||
|  | ||||
|     public Set<String> getPermissions() | ||||
|     { | ||||
|         return permissions; | ||||
|     } | ||||
|  | ||||
|     public void setPermissions(Set<String> permissions) | ||||
|     { | ||||
|         this.permissions = permissions; | ||||
|     } | ||||
|  | ||||
|     public SysUser getUser() | ||||
|     { | ||||
|         return user; | ||||
|     } | ||||
|  | ||||
|     public void setUser(SysUser user) | ||||
|     { | ||||
|         this.user = user; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public Collection<? extends GrantedAuthority> getAuthorities() | ||||
|     { | ||||
|         return null; | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,72 @@ | ||||
| package com.stdiet.common.core.page; | ||||
|  | ||||
| import com.stdiet.common.utils.StringUtils; | ||||
|  | ||||
| /** | ||||
|  * 分页数据 | ||||
|  *  | ||||
|  * @author stdiet | ||||
|  */ | ||||
| public class PageDomain | ||||
| { | ||||
|     /** 当前记录起始索引 */ | ||||
|     private Integer pageNum; | ||||
|  | ||||
|     /** 每页显示记录数 */ | ||||
|     private Integer pageSize; | ||||
|  | ||||
|     /** 排序列 */ | ||||
|     private String orderByColumn; | ||||
|  | ||||
|     /** 排序的方向desc或者asc */ | ||||
|     private String isAsc = "asc"; | ||||
|  | ||||
|     public String getOrderBy() | ||||
|     { | ||||
|         if (StringUtils.isEmpty(orderByColumn)) | ||||
|         { | ||||
|             return ""; | ||||
|         } | ||||
|         return StringUtils.toUnderScoreCase(orderByColumn) + " " + isAsc; | ||||
|     } | ||||
|  | ||||
|     public Integer getPageNum() | ||||
|     { | ||||
|         return pageNum; | ||||
|     } | ||||
|  | ||||
|     public void setPageNum(Integer pageNum) | ||||
|     { | ||||
|         this.pageNum = pageNum; | ||||
|     } | ||||
|  | ||||
|     public Integer getPageSize() | ||||
|     { | ||||
|         return pageSize; | ||||
|     } | ||||
|  | ||||
|     public void setPageSize(Integer pageSize) | ||||
|     { | ||||
|         this.pageSize = pageSize; | ||||
|     } | ||||
|  | ||||
|     public String getOrderByColumn() | ||||
|     { | ||||
|         return orderByColumn; | ||||
|     } | ||||
|  | ||||
|     public void setOrderByColumn(String orderByColumn) | ||||
|     { | ||||
|         this.orderByColumn = orderByColumn; | ||||
|     } | ||||
|  | ||||
|     public String getIsAsc() | ||||
|     { | ||||
|         return isAsc; | ||||
|     } | ||||
|  | ||||
|     public void setIsAsc(String isAsc) | ||||
|     { | ||||
|         this.isAsc = isAsc; | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,85 @@ | ||||
| package com.stdiet.common.core.page; | ||||
|  | ||||
| import java.io.Serializable; | ||||
| import java.util.List; | ||||
|  | ||||
| /** | ||||
|  * 表格分页数据对象 | ||||
|  *  | ||||
|  * @author stdiet | ||||
|  */ | ||||
| public class TableDataInfo implements Serializable | ||||
| { | ||||
|     private static final long serialVersionUID = 1L; | ||||
|  | ||||
|     /** 总记录数 */ | ||||
|     private long total; | ||||
|  | ||||
|     /** 列表数据 */ | ||||
|     private List<?> rows; | ||||
|  | ||||
|     /** 消息状态码 */ | ||||
|     private int code; | ||||
|  | ||||
|     /** 消息内容 */ | ||||
|     private String msg; | ||||
|  | ||||
|     /** | ||||
|      * 表格数据对象 | ||||
|      */ | ||||
|     public TableDataInfo() | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 分页 | ||||
|      *  | ||||
|      * @param list 列表数据 | ||||
|      * @param total 总记录数 | ||||
|      */ | ||||
|     public TableDataInfo(List<?> list, int total) | ||||
|     { | ||||
|         this.rows = list; | ||||
|         this.total = total; | ||||
|     } | ||||
|  | ||||
|     public long getTotal() | ||||
|     { | ||||
|         return total; | ||||
|     } | ||||
|  | ||||
|     public void setTotal(long total) | ||||
|     { | ||||
|         this.total = total; | ||||
|     } | ||||
|  | ||||
|     public List<?> getRows() | ||||
|     { | ||||
|         return rows; | ||||
|     } | ||||
|  | ||||
|     public void setRows(List<?> rows) | ||||
|     { | ||||
|         this.rows = rows; | ||||
|     } | ||||
|  | ||||
|     public int getCode() | ||||
|     { | ||||
|         return code; | ||||
|     } | ||||
|  | ||||
|     public void setCode(int code) | ||||
|     { | ||||
|         this.code = code; | ||||
|     } | ||||
|  | ||||
|     public String getMsg() | ||||
|     { | ||||
|         return msg; | ||||
|     } | ||||
|  | ||||
|     public void setMsg(String msg) | ||||
|     { | ||||
|         this.msg = msg; | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,49 @@ | ||||
| package com.stdiet.common.core.page; | ||||
|  | ||||
| import com.stdiet.common.utils.ServletUtils; | ||||
|  | ||||
| /** | ||||
|  * 表格数据处理 | ||||
|  *  | ||||
|  * @author stdiet | ||||
|  */ | ||||
| public class TableSupport | ||||
| { | ||||
|     /** | ||||
|      * 当前记录起始索引 | ||||
|      */ | ||||
|     public static final String PAGE_NUM = "pageNum"; | ||||
|  | ||||
|     /** | ||||
|      * 每页显示记录数 | ||||
|      */ | ||||
|     public static final String PAGE_SIZE = "pageSize"; | ||||
|  | ||||
|     /** | ||||
|      * 排序列 | ||||
|      */ | ||||
|     public static final String ORDER_BY_COLUMN = "orderByColumn"; | ||||
|  | ||||
|     /** | ||||
|      * 排序的方向 "desc" 或者 "asc". | ||||
|      */ | ||||
|     public static final String IS_ASC = "isAsc"; | ||||
|  | ||||
|     /** | ||||
|      * 封装分页对象 | ||||
|      */ | ||||
|     public static PageDomain getPageDomain() | ||||
|     { | ||||
|         PageDomain pageDomain = new PageDomain(); | ||||
|         pageDomain.setPageNum(ServletUtils.getParameterToInt(PAGE_NUM)); | ||||
|         pageDomain.setPageSize(ServletUtils.getParameterToInt(PAGE_SIZE)); | ||||
|         pageDomain.setOrderByColumn(ServletUtils.getParameter(ORDER_BY_COLUMN)); | ||||
|         pageDomain.setIsAsc(ServletUtils.getParameter(IS_ASC)); | ||||
|         return pageDomain; | ||||
|     } | ||||
|  | ||||
|     public static PageDomain buildPageRequest() | ||||
|     { | ||||
|         return getPageDomain(); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,227 @@ | ||||
| package com.stdiet.common.core.redis; | ||||
|  | ||||
| import java.util.Collection; | ||||
| import java.util.List; | ||||
| import java.util.Map; | ||||
| import java.util.Set; | ||||
| import java.util.concurrent.TimeUnit; | ||||
| import org.springframework.beans.factory.annotation.Autowired; | ||||
| import org.springframework.data.redis.core.HashOperations; | ||||
| import org.springframework.data.redis.core.RedisTemplate; | ||||
| import org.springframework.data.redis.core.ValueOperations; | ||||
| import org.springframework.stereotype.Component; | ||||
|  | ||||
| /** | ||||
|  * spring redis 工具类 | ||||
|  * | ||||
|  * @author stdiet | ||||
|  **/ | ||||
| @SuppressWarnings(value = { "unchecked", "rawtypes" }) | ||||
| @Component | ||||
| public class RedisCache | ||||
| { | ||||
|     @Autowired | ||||
|     public RedisTemplate redisTemplate; | ||||
|  | ||||
|     /** | ||||
|      * 缓存基本的对象,Integer、String、实体类等 | ||||
|      * | ||||
|      * @param key 缓存的键值 | ||||
|      * @param value 缓存的值 | ||||
|      */ | ||||
|     public <T> void setCacheObject(final String key, final T value) | ||||
|     { | ||||
|         redisTemplate.opsForValue().set(key, value); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 缓存基本的对象,Integer、String、实体类等 | ||||
|      * | ||||
|      * @param key 缓存的键值 | ||||
|      * @param value 缓存的值 | ||||
|      * @param timeout 时间 | ||||
|      * @param timeUnit 时间颗粒度 | ||||
|      */ | ||||
|     public <T> void setCacheObject(final String key, final T value, final Integer timeout, final TimeUnit timeUnit) | ||||
|     { | ||||
|         redisTemplate.opsForValue().set(key, value, timeout, timeUnit); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 设置有效时间 | ||||
|      * | ||||
|      * @param key Redis键 | ||||
|      * @param timeout 超时时间 | ||||
|      * @return true=设置成功;false=设置失败 | ||||
|      */ | ||||
|     public boolean expire(final String key, final long timeout) | ||||
|     { | ||||
|         return expire(key, timeout, TimeUnit.SECONDS); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 设置有效时间 | ||||
|      * | ||||
|      * @param key Redis键 | ||||
|      * @param timeout 超时时间 | ||||
|      * @param unit 时间单位 | ||||
|      * @return true=设置成功;false=设置失败 | ||||
|      */ | ||||
|     public boolean expire(final String key, final long timeout, final TimeUnit unit) | ||||
|     { | ||||
|         return redisTemplate.expire(key, timeout, unit); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 获得缓存的基本对象。 | ||||
|      * | ||||
|      * @param key 缓存键值 | ||||
|      * @return 缓存键值对应的数据 | ||||
|      */ | ||||
|     public <T> T getCacheObject(final String key) | ||||
|     { | ||||
|         ValueOperations<String, T> operation = redisTemplate.opsForValue(); | ||||
|         return operation.get(key); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 删除单个对象 | ||||
|      * | ||||
|      * @param key | ||||
|      */ | ||||
|     public boolean deleteObject(final String key) | ||||
|     { | ||||
|         return redisTemplate.delete(key); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 删除集合对象 | ||||
|      * | ||||
|      * @param collection 多个对象 | ||||
|      * @return | ||||
|      */ | ||||
|     public long deleteObject(final Collection collection) | ||||
|     { | ||||
|         return redisTemplate.delete(collection); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 缓存List数据 | ||||
|      * | ||||
|      * @param key 缓存的键值 | ||||
|      * @param dataList 待缓存的List数据 | ||||
|      * @return 缓存的对象 | ||||
|      */ | ||||
|     public <T> long setCacheList(final String key, final List<T> dataList) | ||||
|     { | ||||
|         Long count = redisTemplate.opsForList().rightPushAll(key, dataList); | ||||
|         return count == null ? 0 : count; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 获得缓存的list对象 | ||||
|      * | ||||
|      * @param key 缓存的键值 | ||||
|      * @return 缓存键值对应的数据 | ||||
|      */ | ||||
|     public <T> List<T> getCacheList(final String key) | ||||
|     { | ||||
|         return redisTemplate.opsForList().range(key, 0, -1); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 缓存Set | ||||
|      * | ||||
|      * @param key 缓存键值 | ||||
|      * @param dataSet 缓存的数据 | ||||
|      * @return 缓存数据的对象 | ||||
|      */ | ||||
|     public <T> long setCacheSet(final String key, final Set<T> dataSet) | ||||
|     { | ||||
|         Long count = redisTemplate.opsForSet().add(key, dataSet); | ||||
|         return count == null ? 0 : count; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 获得缓存的set | ||||
|      * | ||||
|      * @param key | ||||
|      * @return | ||||
|      */ | ||||
|     public <T> Set<T> getCacheSet(final String key) | ||||
|     { | ||||
|         return redisTemplate.opsForSet().members(key); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 缓存Map | ||||
|      * | ||||
|      * @param key | ||||
|      * @param dataMap | ||||
|      */ | ||||
|     public <T> void setCacheMap(final String key, final Map<String, T> dataMap) | ||||
|     { | ||||
|         if (dataMap != null) { | ||||
|             redisTemplate.opsForHash().putAll(key, dataMap); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 获得缓存的Map | ||||
|      * | ||||
|      * @param key | ||||
|      * @return | ||||
|      */ | ||||
|     public <T> Map<String, T> getCacheMap(final String key) | ||||
|     { | ||||
|         return redisTemplate.opsForHash().entries(key); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 往Hash中存入数据 | ||||
|      * | ||||
|      * @param key Redis键 | ||||
|      * @param hKey Hash键 | ||||
|      * @param value 值 | ||||
|      */ | ||||
|     public <T> void setCacheMapValue(final String key, final String hKey, final T value) | ||||
|     { | ||||
|         redisTemplate.opsForHash().put(key, hKey, value); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 获取Hash中的数据 | ||||
|      * | ||||
|      * @param key Redis键 | ||||
|      * @param hKey Hash键 | ||||
|      * @return Hash中的对象 | ||||
|      */ | ||||
|     public <T> T getCacheMapValue(final String key, final String hKey) | ||||
|     { | ||||
|         HashOperations<String, String, T> opsForHash = redisTemplate.opsForHash(); | ||||
|         return opsForHash.get(key, hKey); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 获取多个Hash中的数据 | ||||
|      * | ||||
|      * @param key Redis键 | ||||
|      * @param hKeys Hash键集合 | ||||
|      * @return Hash对象集合 | ||||
|      */ | ||||
|     public <T> List<T> getMultiCacheMapValue(final String key, final Collection<Object> hKeys) | ||||
|     { | ||||
|         return redisTemplate.opsForHash().multiGet(key, hKeys); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 获得缓存的基本对象列表 | ||||
|      * | ||||
|      * @param pattern 字符串前缀 | ||||
|      * @return 对象列表 | ||||
|      */ | ||||
|     public Collection<String> keys(final String pattern) | ||||
|     { | ||||
|         return redisTemplate.keys(pattern); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,86 @@ | ||||
| package com.stdiet.common.core.text; | ||||
|  | ||||
| import java.nio.charset.Charset; | ||||
| import java.nio.charset.StandardCharsets; | ||||
| import com.stdiet.common.utils.StringUtils; | ||||
|  | ||||
| /** | ||||
|  * 字符集工具类 | ||||
|  *  | ||||
|  * @author stdiet | ||||
|  */ | ||||
| public class CharsetKit | ||||
| { | ||||
|     /** ISO-8859-1 */ | ||||
|     public static final String ISO_8859_1 = "ISO-8859-1"; | ||||
|     /** UTF-8 */ | ||||
|     public static final String UTF_8 = "UTF-8"; | ||||
|     /** GBK */ | ||||
|     public static final String GBK = "GBK"; | ||||
|  | ||||
|     /** ISO-8859-1 */ | ||||
|     public static final Charset CHARSET_ISO_8859_1 = Charset.forName(ISO_8859_1); | ||||
|     /** UTF-8 */ | ||||
|     public static final Charset CHARSET_UTF_8 = Charset.forName(UTF_8); | ||||
|     /** GBK */ | ||||
|     public static final Charset CHARSET_GBK = Charset.forName(GBK); | ||||
|  | ||||
|     /** | ||||
|      * 转换为Charset对象 | ||||
|      *  | ||||
|      * @param charset 字符集,为空则返回默认字符集 | ||||
|      * @return Charset | ||||
|      */ | ||||
|     public static Charset charset(String charset) | ||||
|     { | ||||
|         return StringUtils.isEmpty(charset) ? Charset.defaultCharset() : Charset.forName(charset); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 转换字符串的字符集编码 | ||||
|      *  | ||||
|      * @param source 字符串 | ||||
|      * @param srcCharset 源字符集,默认ISO-8859-1 | ||||
|      * @param destCharset 目标字符集,默认UTF-8 | ||||
|      * @return 转换后的字符集 | ||||
|      */ | ||||
|     public static String convert(String source, String srcCharset, String destCharset) | ||||
|     { | ||||
|         return convert(source, Charset.forName(srcCharset), Charset.forName(destCharset)); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 转换字符串的字符集编码 | ||||
|      *  | ||||
|      * @param source 字符串 | ||||
|      * @param srcCharset 源字符集,默认ISO-8859-1 | ||||
|      * @param destCharset 目标字符集,默认UTF-8 | ||||
|      * @return 转换后的字符集 | ||||
|      */ | ||||
|     public static String convert(String source, Charset srcCharset, Charset destCharset) | ||||
|     { | ||||
|         if (null == srcCharset) | ||||
|         { | ||||
|             srcCharset = StandardCharsets.ISO_8859_1; | ||||
|         } | ||||
|  | ||||
|         if (null == destCharset) | ||||
|         { | ||||
|             srcCharset = StandardCharsets.UTF_8; | ||||
|         } | ||||
|  | ||||
|         if (StringUtils.isEmpty(source) || srcCharset.equals(destCharset)) | ||||
|         { | ||||
|             return source; | ||||
|         } | ||||
|         return new String(source.getBytes(srcCharset), destCharset); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return 系统字符集编码 | ||||
|      */ | ||||
|     public static String systemCharset() | ||||
|     { | ||||
|         return Charset.defaultCharset().name(); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,999 @@ | ||||
| package com.stdiet.common.core.text; | ||||
|  | ||||
| import java.math.BigDecimal; | ||||
| import java.math.BigInteger; | ||||
| import java.nio.ByteBuffer; | ||||
| import java.nio.charset.Charset; | ||||
| import java.text.NumberFormat; | ||||
| import java.util.Set; | ||||
| import com.stdiet.common.utils.StringUtils; | ||||
|  | ||||
| /** | ||||
|  * 类型转换器 | ||||
|  *  | ||||
|  * @author stdiet | ||||
|  */ | ||||
| public class Convert | ||||
| { | ||||
|     /** | ||||
|      * 转换为字符串<br> | ||||
|      * 如果给定的值为null,或者转换失败,返回默认值<br> | ||||
|      * 转换失败不会报错 | ||||
|      *  | ||||
|      * @param value 被转换的值 | ||||
|      * @param defaultValue 转换错误时的默认值 | ||||
|      * @return 结果 | ||||
|      */ | ||||
|     public static String toStr(Object value, String defaultValue) | ||||
|     { | ||||
|         if (null == value) | ||||
|         { | ||||
|             return defaultValue; | ||||
|         } | ||||
|         if (value instanceof String) | ||||
|         { | ||||
|             return (String) value; | ||||
|         } | ||||
|         return value.toString(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 转换为字符串<br> | ||||
|      * 如果给定的值为<code>null</code>,或者转换失败,返回默认值<code>null</code><br> | ||||
|      * 转换失败不会报错 | ||||
|      *  | ||||
|      * @param value 被转换的值 | ||||
|      * @return 结果 | ||||
|      */ | ||||
|     public static String toStr(Object value) | ||||
|     { | ||||
|         return toStr(value, null); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 转换为字符<br> | ||||
|      * 如果给定的值为null,或者转换失败,返回默认值<br> | ||||
|      * 转换失败不会报错 | ||||
|      *  | ||||
|      * @param value 被转换的值 | ||||
|      * @param defaultValue 转换错误时的默认值 | ||||
|      * @return 结果 | ||||
|      */ | ||||
|     public static Character toChar(Object value, Character defaultValue) | ||||
|     { | ||||
|         if (null == value) | ||||
|         { | ||||
|             return defaultValue; | ||||
|         } | ||||
|         if (value instanceof Character) | ||||
|         { | ||||
|             return (Character) value; | ||||
|         } | ||||
|  | ||||
|         final String valueStr = toStr(value, null); | ||||
|         return StringUtils.isEmpty(valueStr) ? defaultValue : valueStr.charAt(0); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 转换为字符<br> | ||||
|      * 如果给定的值为<code>null</code>,或者转换失败,返回默认值<code>null</code><br> | ||||
|      * 转换失败不会报错 | ||||
|      *  | ||||
|      * @param value 被转换的值 | ||||
|      * @return 结果 | ||||
|      */ | ||||
|     public static Character toChar(Object value) | ||||
|     { | ||||
|         return toChar(value, null); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 转换为byte<br> | ||||
|      * 如果给定的值为<code>null</code>,或者转换失败,返回默认值<br> | ||||
|      * 转换失败不会报错 | ||||
|      *  | ||||
|      * @param value 被转换的值 | ||||
|      * @param defaultValue 转换错误时的默认值 | ||||
|      * @return 结果 | ||||
|      */ | ||||
|     public static Byte toByte(Object value, Byte defaultValue) | ||||
|     { | ||||
|         if (value == null) | ||||
|         { | ||||
|             return defaultValue; | ||||
|         } | ||||
|         if (value instanceof Byte) | ||||
|         { | ||||
|             return (Byte) value; | ||||
|         } | ||||
|         if (value instanceof Number) | ||||
|         { | ||||
|             return ((Number) value).byteValue(); | ||||
|         } | ||||
|         final String valueStr = toStr(value, null); | ||||
|         if (StringUtils.isEmpty(valueStr)) | ||||
|         { | ||||
|             return defaultValue; | ||||
|         } | ||||
|         try | ||||
|         { | ||||
|             return Byte.parseByte(valueStr); | ||||
|         } | ||||
|         catch (Exception e) | ||||
|         { | ||||
|             return defaultValue; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 转换为byte<br> | ||||
|      * 如果给定的值为<code>null</code>,或者转换失败,返回默认值<code>null</code><br> | ||||
|      * 转换失败不会报错 | ||||
|      *  | ||||
|      * @param value 被转换的值 | ||||
|      * @return 结果 | ||||
|      */ | ||||
|     public static Byte toByte(Object value) | ||||
|     { | ||||
|         return toByte(value, null); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 转换为Short<br> | ||||
|      * 如果给定的值为<code>null</code>,或者转换失败,返回默认值<br> | ||||
|      * 转换失败不会报错 | ||||
|      *  | ||||
|      * @param value 被转换的值 | ||||
|      * @param defaultValue 转换错误时的默认值 | ||||
|      * @return 结果 | ||||
|      */ | ||||
|     public static Short toShort(Object value, Short defaultValue) | ||||
|     { | ||||
|         if (value == null) | ||||
|         { | ||||
|             return defaultValue; | ||||
|         } | ||||
|         if (value instanceof Short) | ||||
|         { | ||||
|             return (Short) value; | ||||
|         } | ||||
|         if (value instanceof Number) | ||||
|         { | ||||
|             return ((Number) value).shortValue(); | ||||
|         } | ||||
|         final String valueStr = toStr(value, null); | ||||
|         if (StringUtils.isEmpty(valueStr)) | ||||
|         { | ||||
|             return defaultValue; | ||||
|         } | ||||
|         try | ||||
|         { | ||||
|             return Short.parseShort(valueStr.trim()); | ||||
|         } | ||||
|         catch (Exception e) | ||||
|         { | ||||
|             return defaultValue; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 转换为Short<br> | ||||
|      * 如果给定的值为<code>null</code>,或者转换失败,返回默认值<code>null</code><br> | ||||
|      * 转换失败不会报错 | ||||
|      *  | ||||
|      * @param value 被转换的值 | ||||
|      * @return 结果 | ||||
|      */ | ||||
|     public static Short toShort(Object value) | ||||
|     { | ||||
|         return toShort(value, null); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 转换为Number<br> | ||||
|      * 如果给定的值为空,或者转换失败,返回默认值<br> | ||||
|      * 转换失败不会报错 | ||||
|      *  | ||||
|      * @param value 被转换的值 | ||||
|      * @param defaultValue 转换错误时的默认值 | ||||
|      * @return 结果 | ||||
|      */ | ||||
|     public static Number toNumber(Object value, Number defaultValue) | ||||
|     { | ||||
|         if (value == null) | ||||
|         { | ||||
|             return defaultValue; | ||||
|         } | ||||
|         if (value instanceof Number) | ||||
|         { | ||||
|             return (Number) value; | ||||
|         } | ||||
|         final String valueStr = toStr(value, null); | ||||
|         if (StringUtils.isEmpty(valueStr)) | ||||
|         { | ||||
|             return defaultValue; | ||||
|         } | ||||
|         try | ||||
|         { | ||||
|             return NumberFormat.getInstance().parse(valueStr); | ||||
|         } | ||||
|         catch (Exception e) | ||||
|         { | ||||
|             return defaultValue; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 转换为Number<br> | ||||
|      * 如果给定的值为空,或者转换失败,返回默认值<code>null</code><br> | ||||
|      * 转换失败不会报错 | ||||
|      *  | ||||
|      * @param value 被转换的值 | ||||
|      * @return 结果 | ||||
|      */ | ||||
|     public static Number toNumber(Object value) | ||||
|     { | ||||
|         return toNumber(value, null); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 转换为int<br> | ||||
|      * 如果给定的值为空,或者转换失败,返回默认值<br> | ||||
|      * 转换失败不会报错 | ||||
|      *  | ||||
|      * @param value 被转换的值 | ||||
|      * @param defaultValue 转换错误时的默认值 | ||||
|      * @return 结果 | ||||
|      */ | ||||
|     public static Integer toInt(Object value, Integer defaultValue) | ||||
|     { | ||||
|         if (value == null) | ||||
|         { | ||||
|             return defaultValue; | ||||
|         } | ||||
|         if (value instanceof Integer) | ||||
|         { | ||||
|             return (Integer) value; | ||||
|         } | ||||
|         if (value instanceof Number) | ||||
|         { | ||||
|             return ((Number) value).intValue(); | ||||
|         } | ||||
|         final String valueStr = toStr(value, null); | ||||
|         if (StringUtils.isEmpty(valueStr)) | ||||
|         { | ||||
|             return defaultValue; | ||||
|         } | ||||
|         try | ||||
|         { | ||||
|             return Integer.parseInt(valueStr.trim()); | ||||
|         } | ||||
|         catch (Exception e) | ||||
|         { | ||||
|             return defaultValue; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 转换为int<br> | ||||
|      * 如果给定的值为<code>null</code>,或者转换失败,返回默认值<code>null</code><br> | ||||
|      * 转换失败不会报错 | ||||
|      *  | ||||
|      * @param value 被转换的值 | ||||
|      * @return 结果 | ||||
|      */ | ||||
|     public static Integer toInt(Object value) | ||||
|     { | ||||
|         return toInt(value, null); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 转换为Integer数组<br> | ||||
|      *  | ||||
|      * @param str 被转换的值 | ||||
|      * @return 结果 | ||||
|      */ | ||||
|     public static Integer[] toIntArray(String str) | ||||
|     { | ||||
|         return toIntArray(",", str); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 转换为Long数组<br> | ||||
|      *  | ||||
|      * @param str 被转换的值 | ||||
|      * @return 结果 | ||||
|      */ | ||||
|     public static Long[] toLongArray(String str) | ||||
|     { | ||||
|         return toLongArray(",", str); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 转换为Integer数组<br> | ||||
|      *  | ||||
|      * @param split 分隔符 | ||||
|      * @param split 被转换的值 | ||||
|      * @return 结果 | ||||
|      */ | ||||
|     public static Integer[] toIntArray(String split, String str) | ||||
|     { | ||||
|         if (StringUtils.isEmpty(str)) | ||||
|         { | ||||
|             return new Integer[] {}; | ||||
|         } | ||||
|         String[] arr = str.split(split); | ||||
|         final Integer[] ints = new Integer[arr.length]; | ||||
|         for (int i = 0; i < arr.length; i++) | ||||
|         { | ||||
|             final Integer v = toInt(arr[i], 0); | ||||
|             ints[i] = v; | ||||
|         } | ||||
|         return ints; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 转换为Long数组<br> | ||||
|      *  | ||||
|      * @param split 分隔符 | ||||
|      * @param str 被转换的值 | ||||
|      * @return 结果 | ||||
|      */ | ||||
|     public static Long[] toLongArray(String split, String str) | ||||
|     { | ||||
|         if (StringUtils.isEmpty(str)) | ||||
|         { | ||||
|             return new Long[] {}; | ||||
|         } | ||||
|         String[] arr = str.split(split); | ||||
|         final Long[] longs = new Long[arr.length]; | ||||
|         for (int i = 0; i < arr.length; i++) | ||||
|         { | ||||
|             final Long v = toLong(arr[i], null); | ||||
|             longs[i] = v; | ||||
|         } | ||||
|         return longs; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 转换为String数组<br> | ||||
|      *  | ||||
|      * @param str 被转换的值 | ||||
|      * @return 结果 | ||||
|      */ | ||||
|     public static String[] toStrArray(String str) | ||||
|     { | ||||
|         return toStrArray(",", str); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 转换为String数组<br> | ||||
|      *  | ||||
|      * @param split 分隔符 | ||||
|      * @param split 被转换的值 | ||||
|      * @return 结果 | ||||
|      */ | ||||
|     public static String[] toStrArray(String split, String str) | ||||
|     { | ||||
|         return str.split(split); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 转换为long<br> | ||||
|      * 如果给定的值为空,或者转换失败,返回默认值<br> | ||||
|      * 转换失败不会报错 | ||||
|      *  | ||||
|      * @param value 被转换的值 | ||||
|      * @param defaultValue 转换错误时的默认值 | ||||
|      * @return 结果 | ||||
|      */ | ||||
|     public static Long toLong(Object value, Long defaultValue) | ||||
|     { | ||||
|         if (value == null) | ||||
|         { | ||||
|             return defaultValue; | ||||
|         } | ||||
|         if (value instanceof Long) | ||||
|         { | ||||
|             return (Long) value; | ||||
|         } | ||||
|         if (value instanceof Number) | ||||
|         { | ||||
|             return ((Number) value).longValue(); | ||||
|         } | ||||
|         final String valueStr = toStr(value, null); | ||||
|         if (StringUtils.isEmpty(valueStr)) | ||||
|         { | ||||
|             return defaultValue; | ||||
|         } | ||||
|         try | ||||
|         { | ||||
|             // 支持科学计数法 | ||||
|             return new BigDecimal(valueStr.trim()).longValue(); | ||||
|         } | ||||
|         catch (Exception e) | ||||
|         { | ||||
|             return defaultValue; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 转换为long<br> | ||||
|      * 如果给定的值为<code>null</code>,或者转换失败,返回默认值<code>null</code><br> | ||||
|      * 转换失败不会报错 | ||||
|      *  | ||||
|      * @param value 被转换的值 | ||||
|      * @return 结果 | ||||
|      */ | ||||
|     public static Long toLong(Object value) | ||||
|     { | ||||
|         return toLong(value, null); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 转换为double<br> | ||||
|      * 如果给定的值为空,或者转换失败,返回默认值<br> | ||||
|      * 转换失败不会报错 | ||||
|      *  | ||||
|      * @param value 被转换的值 | ||||
|      * @param defaultValue 转换错误时的默认值 | ||||
|      * @return 结果 | ||||
|      */ | ||||
|     public static Double toDouble(Object value, Double defaultValue) | ||||
|     { | ||||
|         if (value == null) | ||||
|         { | ||||
|             return defaultValue; | ||||
|         } | ||||
|         if (value instanceof Double) | ||||
|         { | ||||
|             return (Double) value; | ||||
|         } | ||||
|         if (value instanceof Number) | ||||
|         { | ||||
|             return ((Number) value).doubleValue(); | ||||
|         } | ||||
|         final String valueStr = toStr(value, null); | ||||
|         if (StringUtils.isEmpty(valueStr)) | ||||
|         { | ||||
|             return defaultValue; | ||||
|         } | ||||
|         try | ||||
|         { | ||||
|             // 支持科学计数法 | ||||
|             return new BigDecimal(valueStr.trim()).doubleValue(); | ||||
|         } | ||||
|         catch (Exception e) | ||||
|         { | ||||
|             return defaultValue; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 转换为double<br> | ||||
|      * 如果给定的值为空,或者转换失败,返回默认值<code>null</code><br> | ||||
|      * 转换失败不会报错 | ||||
|      *  | ||||
|      * @param value 被转换的值 | ||||
|      * @return 结果 | ||||
|      */ | ||||
|     public static Double toDouble(Object value) | ||||
|     { | ||||
|         return toDouble(value, null); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 转换为Float<br> | ||||
|      * 如果给定的值为空,或者转换失败,返回默认值<br> | ||||
|      * 转换失败不会报错 | ||||
|      *  | ||||
|      * @param value 被转换的值 | ||||
|      * @param defaultValue 转换错误时的默认值 | ||||
|      * @return 结果 | ||||
|      */ | ||||
|     public static Float toFloat(Object value, Float defaultValue) | ||||
|     { | ||||
|         if (value == null) | ||||
|         { | ||||
|             return defaultValue; | ||||
|         } | ||||
|         if (value instanceof Float) | ||||
|         { | ||||
|             return (Float) value; | ||||
|         } | ||||
|         if (value instanceof Number) | ||||
|         { | ||||
|             return ((Number) value).floatValue(); | ||||
|         } | ||||
|         final String valueStr = toStr(value, null); | ||||
|         if (StringUtils.isEmpty(valueStr)) | ||||
|         { | ||||
|             return defaultValue; | ||||
|         } | ||||
|         try | ||||
|         { | ||||
|             return Float.parseFloat(valueStr.trim()); | ||||
|         } | ||||
|         catch (Exception e) | ||||
|         { | ||||
|             return defaultValue; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 转换为Float<br> | ||||
|      * 如果给定的值为空,或者转换失败,返回默认值<code>null</code><br> | ||||
|      * 转换失败不会报错 | ||||
|      *  | ||||
|      * @param value 被转换的值 | ||||
|      * @return 结果 | ||||
|      */ | ||||
|     public static Float toFloat(Object value) | ||||
|     { | ||||
|         return toFloat(value, null); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 转换为boolean<br> | ||||
|      * String支持的值为:true、false、yes、ok、no,1,0 如果给定的值为空,或者转换失败,返回默认值<br> | ||||
|      * 转换失败不会报错 | ||||
|      *  | ||||
|      * @param value 被转换的值 | ||||
|      * @param defaultValue 转换错误时的默认值 | ||||
|      * @return 结果 | ||||
|      */ | ||||
|     public static Boolean toBool(Object value, Boolean defaultValue) | ||||
|     { | ||||
|         if (value == null) | ||||
|         { | ||||
|             return defaultValue; | ||||
|         } | ||||
|         if (value instanceof Boolean) | ||||
|         { | ||||
|             return (Boolean) value; | ||||
|         } | ||||
|         String valueStr = toStr(value, null); | ||||
|         if (StringUtils.isEmpty(valueStr)) | ||||
|         { | ||||
|             return defaultValue; | ||||
|         } | ||||
|         valueStr = valueStr.trim().toLowerCase(); | ||||
|         switch (valueStr) | ||||
|         { | ||||
|             case "true": | ||||
|                 return true; | ||||
|             case "false": | ||||
|                 return false; | ||||
|             case "yes": | ||||
|                 return true; | ||||
|             case "ok": | ||||
|                 return true; | ||||
|             case "no": | ||||
|                 return false; | ||||
|             case "1": | ||||
|                 return true; | ||||
|             case "0": | ||||
|                 return false; | ||||
|             default: | ||||
|                 return defaultValue; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 转换为boolean<br> | ||||
|      * 如果给定的值为空,或者转换失败,返回默认值<code>null</code><br> | ||||
|      * 转换失败不会报错 | ||||
|      *  | ||||
|      * @param value 被转换的值 | ||||
|      * @return 结果 | ||||
|      */ | ||||
|     public static Boolean toBool(Object value) | ||||
|     { | ||||
|         return toBool(value, null); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 转换为Enum对象<br> | ||||
|      * 如果给定的值为空,或者转换失败,返回默认值<br> | ||||
|      *  | ||||
|      * @param clazz Enum的Class | ||||
|      * @param value 值 | ||||
|      * @param defaultValue 默认值 | ||||
|      * @return Enum | ||||
|      */ | ||||
|     public static <E extends Enum<E>> E toEnum(Class<E> clazz, Object value, E defaultValue) | ||||
|     { | ||||
|         if (value == null) | ||||
|         { | ||||
|             return defaultValue; | ||||
|         } | ||||
|         if (clazz.isAssignableFrom(value.getClass())) | ||||
|         { | ||||
|             @SuppressWarnings("unchecked") | ||||
|             E myE = (E) value; | ||||
|             return myE; | ||||
|         } | ||||
|         final String valueStr = toStr(value, null); | ||||
|         if (StringUtils.isEmpty(valueStr)) | ||||
|         { | ||||
|             return defaultValue; | ||||
|         } | ||||
|         try | ||||
|         { | ||||
|             return Enum.valueOf(clazz, valueStr); | ||||
|         } | ||||
|         catch (Exception e) | ||||
|         { | ||||
|             return defaultValue; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 转换为Enum对象<br> | ||||
|      * 如果给定的值为空,或者转换失败,返回默认值<code>null</code><br> | ||||
|      *  | ||||
|      * @param clazz Enum的Class | ||||
|      * @param value 值 | ||||
|      * @return Enum | ||||
|      */ | ||||
|     public static <E extends Enum<E>> E toEnum(Class<E> clazz, Object value) | ||||
|     { | ||||
|         return toEnum(clazz, value, null); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 转换为BigInteger<br> | ||||
|      * 如果给定的值为空,或者转换失败,返回默认值<br> | ||||
|      * 转换失败不会报错 | ||||
|      *  | ||||
|      * @param value 被转换的值 | ||||
|      * @param defaultValue 转换错误时的默认值 | ||||
|      * @return 结果 | ||||
|      */ | ||||
|     public static BigInteger toBigInteger(Object value, BigInteger defaultValue) | ||||
|     { | ||||
|         if (value == null) | ||||
|         { | ||||
|             return defaultValue; | ||||
|         } | ||||
|         if (value instanceof BigInteger) | ||||
|         { | ||||
|             return (BigInteger) value; | ||||
|         } | ||||
|         if (value instanceof Long) | ||||
|         { | ||||
|             return BigInteger.valueOf((Long) value); | ||||
|         } | ||||
|         final String valueStr = toStr(value, null); | ||||
|         if (StringUtils.isEmpty(valueStr)) | ||||
|         { | ||||
|             return defaultValue; | ||||
|         } | ||||
|         try | ||||
|         { | ||||
|             return new BigInteger(valueStr); | ||||
|         } | ||||
|         catch (Exception e) | ||||
|         { | ||||
|             return defaultValue; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 转换为BigInteger<br> | ||||
|      * 如果给定的值为空,或者转换失败,返回默认值<code>null</code><br> | ||||
|      * 转换失败不会报错 | ||||
|      *  | ||||
|      * @param value 被转换的值 | ||||
|      * @return 结果 | ||||
|      */ | ||||
|     public static BigInteger toBigInteger(Object value) | ||||
|     { | ||||
|         return toBigInteger(value, null); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 转换为BigDecimal<br> | ||||
|      * 如果给定的值为空,或者转换失败,返回默认值<br> | ||||
|      * 转换失败不会报错 | ||||
|      *  | ||||
|      * @param value 被转换的值 | ||||
|      * @param defaultValue 转换错误时的默认值 | ||||
|      * @return 结果 | ||||
|      */ | ||||
|     public static BigDecimal toBigDecimal(Object value, BigDecimal defaultValue) | ||||
|     { | ||||
|         if (value == null) | ||||
|         { | ||||
|             return defaultValue; | ||||
|         } | ||||
|         if (value instanceof BigDecimal) | ||||
|         { | ||||
|             return (BigDecimal) value; | ||||
|         } | ||||
|         if (value instanceof Long) | ||||
|         { | ||||
|             return new BigDecimal((Long) value); | ||||
|         } | ||||
|         if (value instanceof Double) | ||||
|         { | ||||
|             return new BigDecimal((Double) value); | ||||
|         } | ||||
|         if (value instanceof Integer) | ||||
|         { | ||||
|             return new BigDecimal((Integer) value); | ||||
|         } | ||||
|         final String valueStr = toStr(value, null); | ||||
|         if (StringUtils.isEmpty(valueStr)) | ||||
|         { | ||||
|             return defaultValue; | ||||
|         } | ||||
|         try | ||||
|         { | ||||
|             return new BigDecimal(valueStr); | ||||
|         } | ||||
|         catch (Exception e) | ||||
|         { | ||||
|             return defaultValue; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 转换为BigDecimal<br> | ||||
|      * 如果给定的值为空,或者转换失败,返回默认值<br> | ||||
|      * 转换失败不会报错 | ||||
|      *  | ||||
|      * @param value 被转换的值 | ||||
|      * @return 结果 | ||||
|      */ | ||||
|     public static BigDecimal toBigDecimal(Object value) | ||||
|     { | ||||
|         return toBigDecimal(value, null); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 将对象转为字符串<br> | ||||
|      * 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法 | ||||
|      *  | ||||
|      * @param obj 对象 | ||||
|      * @return 字符串 | ||||
|      */ | ||||
|     public static String utf8Str(Object obj) | ||||
|     { | ||||
|         return str(obj, CharsetKit.CHARSET_UTF_8); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 将对象转为字符串<br> | ||||
|      * 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法 | ||||
|      *  | ||||
|      * @param obj 对象 | ||||
|      * @param charsetName 字符集 | ||||
|      * @return 字符串 | ||||
|      */ | ||||
|     public static String str(Object obj, String charsetName) | ||||
|     { | ||||
|         return str(obj, Charset.forName(charsetName)); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 将对象转为字符串<br> | ||||
|      * 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法 | ||||
|      *  | ||||
|      * @param obj 对象 | ||||
|      * @param charset 字符集 | ||||
|      * @return 字符串 | ||||
|      */ | ||||
|     public static String str(Object obj, Charset charset) | ||||
|     { | ||||
|         if (null == obj) | ||||
|         { | ||||
|             return null; | ||||
|         } | ||||
|  | ||||
|         if (obj instanceof String) | ||||
|         { | ||||
|             return (String) obj; | ||||
|         } | ||||
|         else if (obj instanceof byte[] || obj instanceof Byte[]) | ||||
|         { | ||||
|             return str((Byte[]) obj, charset); | ||||
|         } | ||||
|         else if (obj instanceof ByteBuffer) | ||||
|         { | ||||
|             return str((ByteBuffer) obj, charset); | ||||
|         } | ||||
|         return obj.toString(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 将byte数组转为字符串 | ||||
|      *  | ||||
|      * @param bytes byte数组 | ||||
|      * @param charset 字符集 | ||||
|      * @return 字符串 | ||||
|      */ | ||||
|     public static String str(byte[] bytes, String charset) | ||||
|     { | ||||
|         return str(bytes, StringUtils.isEmpty(charset) ? Charset.defaultCharset() : Charset.forName(charset)); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 解码字节码 | ||||
|      *  | ||||
|      * @param data 字符串 | ||||
|      * @param charset 字符集,如果此字段为空,则解码的结果取决于平台 | ||||
|      * @return 解码后的字符串 | ||||
|      */ | ||||
|     public static String str(byte[] data, Charset charset) | ||||
|     { | ||||
|         if (data == null) | ||||
|         { | ||||
|             return null; | ||||
|         } | ||||
|  | ||||
|         if (null == charset) | ||||
|         { | ||||
|             return new String(data); | ||||
|         } | ||||
|         return new String(data, charset); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 将编码的byteBuffer数据转换为字符串 | ||||
|      *  | ||||
|      * @param data 数据 | ||||
|      * @param charset 字符集,如果为空使用当前系统字符集 | ||||
|      * @return 字符串 | ||||
|      */ | ||||
|     public static String str(ByteBuffer data, String charset) | ||||
|     { | ||||
|         if (data == null) | ||||
|         { | ||||
|             return null; | ||||
|         } | ||||
|  | ||||
|         return str(data, Charset.forName(charset)); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 将编码的byteBuffer数据转换为字符串 | ||||
|      *  | ||||
|      * @param data 数据 | ||||
|      * @param charset 字符集,如果为空使用当前系统字符集 | ||||
|      * @return 字符串 | ||||
|      */ | ||||
|     public static String str(ByteBuffer data, Charset charset) | ||||
|     { | ||||
|         if (null == charset) | ||||
|         { | ||||
|             charset = Charset.defaultCharset(); | ||||
|         } | ||||
|         return charset.decode(data).toString(); | ||||
|     } | ||||
|  | ||||
|     // ----------------------------------------------------------------------- 全角半角转换 | ||||
|     /** | ||||
|      * 半角转全角 | ||||
|      *  | ||||
|      * @param input String. | ||||
|      * @return 全角字符串. | ||||
|      */ | ||||
|     public static String toSBC(String input) | ||||
|     { | ||||
|         return toSBC(input, null); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 半角转全角 | ||||
|      *  | ||||
|      * @param input String | ||||
|      * @param notConvertSet 不替换的字符集合 | ||||
|      * @return 全角字符串. | ||||
|      */ | ||||
|     public static String toSBC(String input, Set<Character> notConvertSet) | ||||
|     { | ||||
|         char c[] = input.toCharArray(); | ||||
|         for (int i = 0; i < c.length; i++) | ||||
|         { | ||||
|             if (null != notConvertSet && notConvertSet.contains(c[i])) | ||||
|             { | ||||
|                 // 跳过不替换的字符 | ||||
|                 continue; | ||||
|             } | ||||
|  | ||||
|             if (c[i] == ' ') | ||||
|             { | ||||
|                 c[i] = '\u3000'; | ||||
|             } | ||||
|             else if (c[i] < '\177') | ||||
|             { | ||||
|                 c[i] = (char) (c[i] + 65248); | ||||
|  | ||||
|             } | ||||
|         } | ||||
|         return new String(c); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 全角转半角 | ||||
|      *  | ||||
|      * @param input String. | ||||
|      * @return 半角字符串 | ||||
|      */ | ||||
|     public static String toDBC(String input) | ||||
|     { | ||||
|         return toDBC(input, null); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 替换全角为半角 | ||||
|      *  | ||||
|      * @param text 文本 | ||||
|      * @param notConvertSet 不替换的字符集合 | ||||
|      * @return 替换后的字符 | ||||
|      */ | ||||
|     public static String toDBC(String text, Set<Character> notConvertSet) | ||||
|     { | ||||
|         char c[] = text.toCharArray(); | ||||
|         for (int i = 0; i < c.length; i++) | ||||
|         { | ||||
|             if (null != notConvertSet && notConvertSet.contains(c[i])) | ||||
|             { | ||||
|                 // 跳过不替换的字符 | ||||
|                 continue; | ||||
|             } | ||||
|  | ||||
|             if (c[i] == '\u3000') | ||||
|             { | ||||
|                 c[i] = ' '; | ||||
|             } | ||||
|             else if (c[i] > '\uFF00' && c[i] < '\uFF5F') | ||||
|             { | ||||
|                 c[i] = (char) (c[i] - 65248); | ||||
|             } | ||||
|         } | ||||
|         String returnString = new String(c); | ||||
|  | ||||
|         return returnString; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 数字金额大写转换 先写个完整的然后将如零拾替换成零 | ||||
|      *  | ||||
|      * @param n 数字 | ||||
|      * @return 中文大写数字 | ||||
|      */ | ||||
|     public static String digitUppercase(double n) | ||||
|     { | ||||
|         String[] fraction = { "角", "分" }; | ||||
|         String[] digit = { "零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖" }; | ||||
|         String[][] unit = { { "元", "万", "亿" }, { "", "拾", "佰", "仟" } }; | ||||
|  | ||||
|         String head = n < 0 ? "负" : ""; | ||||
|         n = Math.abs(n); | ||||
|  | ||||
|         String s = ""; | ||||
|         for (int i = 0; i < fraction.length; i++) | ||||
|         { | ||||
|             s += (digit[(int) (Math.floor(n * 10 * Math.pow(10, i)) % 10)] + fraction[i]).replaceAll("(零.)+", ""); | ||||
|         } | ||||
|         if (s.length() < 1) | ||||
|         { | ||||
|             s = "整"; | ||||
|         } | ||||
|         int integerPart = (int) Math.floor(n); | ||||
|  | ||||
|         for (int i = 0; i < unit[0].length && integerPart > 0; i++) | ||||
|         { | ||||
|             String p = ""; | ||||
|             for (int j = 0; j < unit[1].length && n > 0; j++) | ||||
|             { | ||||
|                 p = digit[integerPart % 10] + unit[1][j] + p; | ||||
|                 integerPart = integerPart / 10; | ||||
|             } | ||||
|             s = p.replaceAll("(零.)*零$", "").replaceAll("^$", "零") + unit[0][i] + s; | ||||
|         } | ||||
|         return head + s.replaceAll("(零.)*零元", "元").replaceFirst("(零.)+", "").replaceAll("(零.)+", "零").replaceAll("^整$", "零元整"); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,92 @@ | ||||
| package com.stdiet.common.core.text; | ||||
|  | ||||
| import com.stdiet.common.utils.StringUtils; | ||||
|  | ||||
| /** | ||||
|  * 字符串格式化 | ||||
|  *  | ||||
|  * @author stdiet | ||||
|  */ | ||||
| public class StrFormatter | ||||
| { | ||||
|     public static final String EMPTY_JSON = "{}"; | ||||
|     public static final char C_BACKSLASH = '\\'; | ||||
|     public static final char C_DELIM_START = '{'; | ||||
|     public static final char C_DELIM_END = '}'; | ||||
|  | ||||
|     /** | ||||
|      * 格式化字符串<br> | ||||
|      * 此方法只是简单将占位符 {} 按照顺序替换为参数<br> | ||||
|      * 如果想输出 {} 使用 \\转义 { 即可,如果想输出 {} 之前的 \ 使用双转义符 \\\\ 即可<br> | ||||
|      * 例:<br> | ||||
|      * 通常使用:format("this is {} for {}", "a", "b") -> this is a for b<br> | ||||
|      * 转义{}: format("this is \\{} for {}", "a", "b") -> this is \{} for a<br> | ||||
|      * 转义\: format("this is \\\\{} for {}", "a", "b") -> this is \a for b<br> | ||||
|      *  | ||||
|      * @param strPattern 字符串模板 | ||||
|      * @param argArray 参数列表 | ||||
|      * @return 结果 | ||||
|      */ | ||||
|     public static String format(final String strPattern, final Object... argArray) | ||||
|     { | ||||
|         if (StringUtils.isEmpty(strPattern) || StringUtils.isEmpty(argArray)) | ||||
|         { | ||||
|             return strPattern; | ||||
|         } | ||||
|         final int strPatternLength = strPattern.length(); | ||||
|  | ||||
|         // 初始化定义好的长度以获得更好的性能 | ||||
|         StringBuilder sbuf = new StringBuilder(strPatternLength + 50); | ||||
|  | ||||
|         int handledPosition = 0; | ||||
|         int delimIndex;// 占位符所在位置 | ||||
|         for (int argIndex = 0; argIndex < argArray.length; argIndex++) | ||||
|         { | ||||
|             delimIndex = strPattern.indexOf(EMPTY_JSON, handledPosition); | ||||
|             if (delimIndex == -1) | ||||
|             { | ||||
|                 if (handledPosition == 0) | ||||
|                 { | ||||
|                     return strPattern; | ||||
|                 } | ||||
|                 else | ||||
|                 { // 字符串模板剩余部分不再包含占位符,加入剩余部分后返回结果 | ||||
|                     sbuf.append(strPattern, handledPosition, strPatternLength); | ||||
|                     return sbuf.toString(); | ||||
|                 } | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 if (delimIndex > 0 && strPattern.charAt(delimIndex - 1) == C_BACKSLASH) | ||||
|                 { | ||||
|                     if (delimIndex > 1 && strPattern.charAt(delimIndex - 2) == C_BACKSLASH) | ||||
|                     { | ||||
|                         // 转义符之前还有一个转义符,占位符依旧有效 | ||||
|                         sbuf.append(strPattern, handledPosition, delimIndex - 1); | ||||
|                         sbuf.append(Convert.utf8Str(argArray[argIndex])); | ||||
|                         handledPosition = delimIndex + 2; | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|                         // 占位符被转义 | ||||
|                         argIndex--; | ||||
|                         sbuf.append(strPattern, handledPosition, delimIndex - 1); | ||||
|                         sbuf.append(C_DELIM_START); | ||||
|                         handledPosition = delimIndex + 1; | ||||
|                     } | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     // 正常占位符 | ||||
|                     sbuf.append(strPattern, handledPosition, delimIndex); | ||||
|                     sbuf.append(Convert.utf8Str(argArray[argIndex])); | ||||
|                     handledPosition = delimIndex + 2; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         // 加入最后一个占位符后所有的字符 | ||||
|         sbuf.append(strPattern, handledPosition, strPattern.length()); | ||||
|  | ||||
|         return sbuf.toString(); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,20 @@ | ||||
| package com.stdiet.common.enums; | ||||
|  | ||||
| /** | ||||
|  * 操作状态 | ||||
|  *  | ||||
|  * @author ruoyi | ||||
|  * | ||||
|  */ | ||||
| public enum BusinessStatus | ||||
| { | ||||
|     /** | ||||
|      * 成功 | ||||
|      */ | ||||
|     SUCCESS, | ||||
|  | ||||
|     /** | ||||
|      * 失败 | ||||
|      */ | ||||
|     FAIL, | ||||
| } | ||||
| @@ -0,0 +1,59 @@ | ||||
| package com.stdiet.common.enums; | ||||
|  | ||||
| /** | ||||
|  * 业务操作类型 | ||||
|  *  | ||||
|  * @author ruoyi | ||||
|  */ | ||||
| public enum BusinessType | ||||
| { | ||||
|     /** | ||||
|      * 其它 | ||||
|      */ | ||||
|     OTHER, | ||||
|  | ||||
|     /** | ||||
|      * 新增 | ||||
|      */ | ||||
|     INSERT, | ||||
|  | ||||
|     /** | ||||
|      * 修改 | ||||
|      */ | ||||
|     UPDATE, | ||||
|  | ||||
|     /** | ||||
|      * 删除 | ||||
|      */ | ||||
|     DELETE, | ||||
|  | ||||
|     /** | ||||
|      * 授权 | ||||
|      */ | ||||
|     GRANT, | ||||
|  | ||||
|     /** | ||||
|      * 导出 | ||||
|      */ | ||||
|     EXPORT, | ||||
|  | ||||
|     /** | ||||
|      * 导入 | ||||
|      */ | ||||
|     IMPORT, | ||||
|  | ||||
|     /** | ||||
|      * 强退 | ||||
|      */ | ||||
|     FORCE, | ||||
|  | ||||
|     /** | ||||
|      * 生成代码 | ||||
|      */ | ||||
|     GENCODE, | ||||
|      | ||||
|     /** | ||||
|      * 清空数据 | ||||
|      */ | ||||
|     CLEAN, | ||||
| } | ||||
| @@ -0,0 +1,19 @@ | ||||
| package com.stdiet.common.enums; | ||||
|  | ||||
| /** | ||||
|  * 数据源 | ||||
|  *  | ||||
|  * @author ruoyi | ||||
|  */ | ||||
| public enum DataSourceType | ||||
| { | ||||
|     /** | ||||
|      * 主库 | ||||
|      */ | ||||
|     MASTER, | ||||
|  | ||||
|     /** | ||||
|      * 从库 | ||||
|      */ | ||||
|     SLAVE | ||||
| } | ||||
| @@ -0,0 +1,36 @@ | ||||
| package com.stdiet.common.enums; | ||||
|  | ||||
| import java.util.HashMap; | ||||
| import java.util.Map; | ||||
| import org.springframework.lang.Nullable; | ||||
|  | ||||
| /** | ||||
|  * 请求方式 | ||||
|  * | ||||
|  * @author ruoyi | ||||
|  */ | ||||
| public enum HttpMethod | ||||
| { | ||||
|     GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE; | ||||
|  | ||||
|     private static final Map<String, HttpMethod> mappings = new HashMap<>(16); | ||||
|  | ||||
|     static | ||||
|     { | ||||
|         for (HttpMethod httpMethod : values()) | ||||
|         { | ||||
|             mappings.put(httpMethod.name(), httpMethod); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     @Nullable | ||||
|     public static HttpMethod resolve(@Nullable String method) | ||||
|     { | ||||
|         return (method != null ? mappings.get(method) : null); | ||||
|     } | ||||
|  | ||||
|     public boolean matches(String method) | ||||
|     { | ||||
|         return (this == resolve(method)); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,24 @@ | ||||
| package com.stdiet.common.enums; | ||||
|  | ||||
| /** | ||||
|  * 操作人类别 | ||||
|  *  | ||||
|  * @author ruoyi | ||||
|  */ | ||||
| public enum OperatorType | ||||
| { | ||||
|     /** | ||||
|      * 其它 | ||||
|      */ | ||||
|     OTHER, | ||||
|  | ||||
|     /** | ||||
|      * 后台用户 | ||||
|      */ | ||||
|     MANAGE, | ||||
|  | ||||
|     /** | ||||
|      * 手机端用户 | ||||
|      */ | ||||
|     MOBILE | ||||
| } | ||||
| @@ -0,0 +1,30 @@ | ||||
| package com.stdiet.common.enums; | ||||
|  | ||||
| /** | ||||
|  * 用户状态 | ||||
|  *  | ||||
|  * @author ruoyi | ||||
|  */ | ||||
| public enum UserStatus | ||||
| { | ||||
|     OK("0", "正常"), DISABLE("1", "停用"), DELETED("2", "删除"); | ||||
|  | ||||
|     private final String code; | ||||
|     private final String info; | ||||
|  | ||||
|     UserStatus(String code, String info) | ||||
|     { | ||||
|         this.code = code; | ||||
|         this.info = info; | ||||
|     } | ||||
|  | ||||
|     public String getCode() | ||||
|     { | ||||
|         return code; | ||||
|     } | ||||
|  | ||||
|     public String getInfo() | ||||
|     { | ||||
|         return info; | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,97 @@ | ||||
| package com.stdiet.common.exception; | ||||
|  | ||||
| import com.stdiet.common.utils.MessageUtils; | ||||
| import com.stdiet.common.utils.StringUtils; | ||||
|  | ||||
| /** | ||||
|  * 基础异常 | ||||
|  *  | ||||
|  * @author stdiet | ||||
|  */ | ||||
| public class BaseException extends RuntimeException | ||||
| { | ||||
|     private static final long serialVersionUID = 1L; | ||||
|  | ||||
|     /** | ||||
|      * 所属模块 | ||||
|      */ | ||||
|     private String module; | ||||
|  | ||||
|     /** | ||||
|      * 错误码 | ||||
|      */ | ||||
|     private String code; | ||||
|  | ||||
|     /** | ||||
|      * 错误码对应的参数 | ||||
|      */ | ||||
|     private Object[] args; | ||||
|  | ||||
|     /** | ||||
|      * 错误消息 | ||||
|      */ | ||||
|     private String defaultMessage; | ||||
|  | ||||
|     public BaseException(String module, String code, Object[] args, String defaultMessage) | ||||
|     { | ||||
|         this.module = module; | ||||
|         this.code = code; | ||||
|         this.args = args; | ||||
|         this.defaultMessage = defaultMessage; | ||||
|     } | ||||
|  | ||||
|     public BaseException(String module, String code, Object[] args) | ||||
|     { | ||||
|         this(module, code, args, null); | ||||
|     } | ||||
|  | ||||
|     public BaseException(String module, String defaultMessage) | ||||
|     { | ||||
|         this(module, null, null, defaultMessage); | ||||
|     } | ||||
|  | ||||
|     public BaseException(String code, Object[] args) | ||||
|     { | ||||
|         this(null, code, args, null); | ||||
|     } | ||||
|  | ||||
|     public BaseException(String defaultMessage) | ||||
|     { | ||||
|         this(null, null, null, defaultMessage); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public String getMessage() | ||||
|     { | ||||
|         String message = null; | ||||
|         if (!StringUtils.isEmpty(code)) | ||||
|         { | ||||
|             message = MessageUtils.message(code, args); | ||||
|         } | ||||
|         if (message == null) | ||||
|         { | ||||
|             message = defaultMessage; | ||||
|         } | ||||
|         return message; | ||||
|     } | ||||
|  | ||||
|     public String getModule() | ||||
|     { | ||||
|         return module; | ||||
|     } | ||||
|  | ||||
|     public String getCode() | ||||
|     { | ||||
|         return code; | ||||
|     } | ||||
|  | ||||
|     public Object[] getArgs() | ||||
|     { | ||||
|         return args; | ||||
|     } | ||||
|  | ||||
|     public String getDefaultMessage() | ||||
|     { | ||||
|         return defaultMessage; | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,43 @@ | ||||
| package com.stdiet.common.exception; | ||||
|  | ||||
| /** | ||||
|  * 自定义异常 | ||||
|  *  | ||||
|  * @author stdiet | ||||
|  */ | ||||
| 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; | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,15 @@ | ||||
| package com.stdiet.common.exception; | ||||
|  | ||||
| /** | ||||
|  * 演示模式异常 | ||||
|  *  | ||||
|  * @author stdiet | ||||
|  */ | ||||
| public class DemoModeException extends RuntimeException | ||||
| { | ||||
|     private static final long serialVersionUID = 1L; | ||||
|  | ||||
|     public DemoModeException() | ||||
|     { | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,26 @@ | ||||
| package com.stdiet.common.exception; | ||||
|  | ||||
| /** | ||||
|  * 工具类异常 | ||||
|  *  | ||||
|  * @author stdiet | ||||
|  */ | ||||
| public class UtilException extends RuntimeException | ||||
| { | ||||
|     private static final long serialVersionUID = 8247610319171014183L; | ||||
|  | ||||
|     public UtilException(Throwable e) | ||||
|     { | ||||
|         super(e.getMessage(), e); | ||||
|     } | ||||
|  | ||||
|     public UtilException(String message) | ||||
|     { | ||||
|         super(message); | ||||
|     } | ||||
|  | ||||
|     public UtilException(String message, Throwable throwable) | ||||
|     { | ||||
|         super(message, throwable); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,19 @@ | ||||
| package com.stdiet.common.exception.file; | ||||
|  | ||||
| import com.stdiet.common.exception.BaseException; | ||||
|  | ||||
| /** | ||||
|  * 文件信息异常类 | ||||
|  *  | ||||
|  * @author stdiet | ||||
|  */ | ||||
| public class FileException extends BaseException | ||||
| { | ||||
|     private static final long serialVersionUID = 1L; | ||||
|  | ||||
|     public FileException(String code, Object[] args) | ||||
|     { | ||||
|         super("file", code, args, null); | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,16 @@ | ||||
| package com.stdiet.common.exception.file; | ||||
|  | ||||
| /** | ||||
|  * 文件名称超长限制异常类 | ||||
|  *  | ||||
|  * @author stdiet | ||||
|  */ | ||||
| public class FileNameLengthLimitExceededException extends FileException | ||||
| { | ||||
|     private static final long serialVersionUID = 1L; | ||||
|  | ||||
|     public FileNameLengthLimitExceededException(int defaultFileNameLength) | ||||
|     { | ||||
|         super("upload.filename.exceed.length", new Object[] { defaultFileNameLength }); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,16 @@ | ||||
| package com.stdiet.common.exception.file; | ||||
|  | ||||
| /** | ||||
|  * 文件名大小限制异常类 | ||||
|  *  | ||||
|  * @author stdiet | ||||
|  */ | ||||
| public class FileSizeLimitExceededException extends FileException | ||||
| { | ||||
|     private static final long serialVersionUID = 1L; | ||||
|  | ||||
|     public FileSizeLimitExceededException(long defaultMaxSize) | ||||
|     { | ||||
|         super("upload.exceed.maxSize", new Object[] { defaultMaxSize }); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,71 @@ | ||||
| package com.stdiet.common.exception.file; | ||||
|  | ||||
| import java.util.Arrays; | ||||
| import org.apache.commons.fileupload.FileUploadException; | ||||
|  | ||||
| /** | ||||
|  * 文件上传 误异常类 | ||||
|  *  | ||||
|  * @author stdiet | ||||
|  */ | ||||
| public class InvalidExtensionException extends FileUploadException | ||||
| { | ||||
|     private static final long serialVersionUID = 1L; | ||||
|  | ||||
|     private String[] allowedExtension; | ||||
|     private String extension; | ||||
|     private String filename; | ||||
|  | ||||
|     public InvalidExtensionException(String[] allowedExtension, String extension, String filename) | ||||
|     { | ||||
|         super("filename : [" + filename + "], extension : [" + extension + "], allowed extension : [" + Arrays.toString(allowedExtension) + "]"); | ||||
|         this.allowedExtension = allowedExtension; | ||||
|         this.extension = extension; | ||||
|         this.filename = filename; | ||||
|     } | ||||
|  | ||||
|     public String[] getAllowedExtension() | ||||
|     { | ||||
|         return allowedExtension; | ||||
|     } | ||||
|  | ||||
|     public String getExtension() | ||||
|     { | ||||
|         return extension; | ||||
|     } | ||||
|  | ||||
|     public String getFilename() | ||||
|     { | ||||
|         return filename; | ||||
|     } | ||||
|  | ||||
|     public static class InvalidImageExtensionException extends InvalidExtensionException | ||||
|     { | ||||
|         private static final long serialVersionUID = 1L; | ||||
|  | ||||
|         public InvalidImageExtensionException(String[] allowedExtension, String extension, String filename) | ||||
|         { | ||||
|             super(allowedExtension, extension, filename); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public static class InvalidFlashExtensionException extends InvalidExtensionException | ||||
|     { | ||||
|         private static final long serialVersionUID = 1L; | ||||
|  | ||||
|         public InvalidFlashExtensionException(String[] allowedExtension, String extension, String filename) | ||||
|         { | ||||
|             super(allowedExtension, extension, filename); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public static class InvalidMediaExtensionException extends InvalidExtensionException | ||||
|     { | ||||
|         private static final long serialVersionUID = 1L; | ||||
|  | ||||
|         public InvalidMediaExtensionException(String[] allowedExtension, String extension, String filename) | ||||
|         { | ||||
|             super(allowedExtension, extension, filename); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,34 @@ | ||||
| package com.stdiet.common.exception.job; | ||||
|  | ||||
| /** | ||||
|  * 计划策略异常 | ||||
|  *  | ||||
|  * @author stdiet | ||||
|  */ | ||||
| public class TaskException extends Exception | ||||
| { | ||||
|     private static final long serialVersionUID = 1L; | ||||
|  | ||||
|     private Code code; | ||||
|  | ||||
|     public TaskException(String msg, Code code) | ||||
|     { | ||||
|         this(msg, code, null); | ||||
|     } | ||||
|  | ||||
|     public TaskException(String msg, Code code, Exception nestedEx) | ||||
|     { | ||||
|         super(msg, nestedEx); | ||||
|         this.code = code; | ||||
|     } | ||||
|  | ||||
|     public Code getCode() | ||||
|     { | ||||
|         return code; | ||||
|     } | ||||
|  | ||||
|     public enum Code | ||||
|     { | ||||
|         TASK_EXISTS, NO_TASK_EXISTS, TASK_ALREADY_STARTED, UNKNOWN, CONFIG_ERROR, TASK_NODE_NOT_AVAILABLE | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,16 @@ | ||||
| package com.stdiet.common.exception.user; | ||||
|  | ||||
| /** | ||||
|  * 验证码错误异常类 | ||||
|  *  | ||||
|  * @author stdiet | ||||
|  */ | ||||
| public class CaptchaException extends UserException | ||||
| { | ||||
|     private static final long serialVersionUID = 1L; | ||||
|  | ||||
|     public CaptchaException() | ||||
|     { | ||||
|         super("user.jcaptcha.error", null); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,16 @@ | ||||
| package com.stdiet.common.exception.user; | ||||
|  | ||||
| /** | ||||
|  * 验证码失效异常类 | ||||
|  *  | ||||
|  * @author stdiet | ||||
|  */ | ||||
| public class CaptchaExpireException extends UserException | ||||
| { | ||||
|     private static final long serialVersionUID = 1L; | ||||
|  | ||||
|     public CaptchaExpireException() | ||||
|     { | ||||
|         super("user.jcaptcha.expire", null); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,18 @@ | ||||
| package com.stdiet.common.exception.user; | ||||
|  | ||||
| import com.stdiet.common.exception.BaseException; | ||||
|  | ||||
| /** | ||||
|  * 用户信息异常类 | ||||
|  *  | ||||
|  * @author stdiet | ||||
|  */ | ||||
| public class UserException extends BaseException | ||||
| { | ||||
|     private static final long serialVersionUID = 1L; | ||||
|  | ||||
|     public UserException(String code, Object[] args) | ||||
|     { | ||||
|         super("user", code, args, null); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,16 @@ | ||||
| package com.stdiet.common.exception.user; | ||||
|  | ||||
| /** | ||||
|  * 用户密码不正确或不符合规范异常类 | ||||
|  *  | ||||
|  * @author stdiet | ||||
|  */ | ||||
| public class UserPasswordNotMatchException extends UserException | ||||
| { | ||||
|     private static final long serialVersionUID = 1L; | ||||
|  | ||||
|     public UserPasswordNotMatchException() | ||||
|     { | ||||
|         super("user.password.not.match", null); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,52 @@ | ||||
| package com.stdiet.common.filter; | ||||
|  | ||||
| import java.io.IOException; | ||||
| import javax.servlet.Filter; | ||||
| import javax.servlet.FilterChain; | ||||
| import javax.servlet.FilterConfig; | ||||
| import javax.servlet.ServletException; | ||||
| import javax.servlet.ServletRequest; | ||||
| import javax.servlet.ServletResponse; | ||||
| import javax.servlet.http.HttpServletRequest; | ||||
| import org.springframework.http.MediaType; | ||||
| import com.stdiet.common.utils.StringUtils; | ||||
|  | ||||
| /** | ||||
|  * Repeatable 过滤器 | ||||
|  *  | ||||
|  * @author stdiet | ||||
|  */ | ||||
| public class RepeatableFilter implements Filter | ||||
| { | ||||
|     @Override | ||||
|     public void init(FilterConfig filterConfig) throws ServletException | ||||
|     { | ||||
|  | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) | ||||
|             throws IOException, ServletException | ||||
|     { | ||||
|         ServletRequest requestWrapper = null; | ||||
|         if (request instanceof HttpServletRequest && StringUtils.equalsAnyIgnoreCase(request.getContentType(), | ||||
|                 MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_JSON_UTF8_VALUE)) | ||||
|         { | ||||
|             requestWrapper = new RepeatedlyRequestWrapper((HttpServletRequest) request, response); | ||||
|         } | ||||
|         if (null == requestWrapper) | ||||
|         { | ||||
|             chain.doFilter(request, response); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             chain.doFilter(requestWrapper, response); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void destroy() | ||||
|     { | ||||
|  | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,72 @@ | ||||
| package com.stdiet.common.filter; | ||||
|  | ||||
| import java.io.BufferedReader; | ||||
| import java.io.ByteArrayInputStream; | ||||
| import java.io.IOException; | ||||
| import java.io.InputStreamReader; | ||||
| import javax.servlet.ReadListener; | ||||
| import javax.servlet.ServletInputStream; | ||||
| import javax.servlet.ServletResponse; | ||||
| import javax.servlet.http.HttpServletRequest; | ||||
| import javax.servlet.http.HttpServletRequestWrapper; | ||||
| import com.stdiet.common.utils.http.HttpHelper; | ||||
|  | ||||
| /** | ||||
|  * 构建可重复读取inputStream的request | ||||
|  *  | ||||
|  * @author stdiet | ||||
|  */ | ||||
| public class RepeatedlyRequestWrapper extends HttpServletRequestWrapper | ||||
| { | ||||
|     private final byte[] body; | ||||
|  | ||||
|     public RepeatedlyRequestWrapper(HttpServletRequest request, ServletResponse response) throws IOException | ||||
|     { | ||||
|         super(request); | ||||
|         request.setCharacterEncoding("UTF-8"); | ||||
|         response.setCharacterEncoding("UTF-8"); | ||||
|  | ||||
|         body = HttpHelper.getBodyString(request).getBytes("UTF-8"); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public BufferedReader getReader() throws IOException | ||||
|     { | ||||
|         return new BufferedReader(new InputStreamReader(getInputStream())); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public ServletInputStream getInputStream() throws IOException | ||||
|     { | ||||
|  | ||||
|         final ByteArrayInputStream bais = new ByteArrayInputStream(body); | ||||
|  | ||||
|         return new ServletInputStream() | ||||
|         { | ||||
|  | ||||
|             @Override | ||||
|             public int read() throws IOException | ||||
|             { | ||||
|                 return bais.read(); | ||||
|             } | ||||
|  | ||||
|             @Override | ||||
|             public boolean isFinished() | ||||
|             { | ||||
|                 return false; | ||||
|             } | ||||
|  | ||||
|             @Override | ||||
|             public boolean isReady() | ||||
|             { | ||||
|                 return false; | ||||
|             } | ||||
|  | ||||
|             @Override | ||||
|             public void setReadListener(ReadListener readListener) | ||||
|             { | ||||
|  | ||||
|             } | ||||
|         }; | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,97 @@ | ||||
| package com.stdiet.common.filter; | ||||
|  | ||||
| import java.io.IOException; | ||||
| import java.util.ArrayList; | ||||
| import java.util.List; | ||||
| import java.util.regex.Matcher; | ||||
| import java.util.regex.Pattern; | ||||
| import javax.servlet.Filter; | ||||
| import javax.servlet.FilterChain; | ||||
| import javax.servlet.FilterConfig; | ||||
| import javax.servlet.ServletException; | ||||
| import javax.servlet.ServletRequest; | ||||
| import javax.servlet.ServletResponse; | ||||
| import javax.servlet.http.HttpServletRequest; | ||||
| import javax.servlet.http.HttpServletResponse; | ||||
| import com.stdiet.common.utils.StringUtils; | ||||
|  | ||||
| /** | ||||
|  * 防止XSS攻击的过滤器 | ||||
|  *  | ||||
|  * @author stdiet | ||||
|  */ | ||||
| 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 (StringUtils.isNotEmpty(tempExcludes)) | ||||
|         { | ||||
|             String[] url = tempExcludes.split(","); | ||||
|             for (int i = 0; url != null && i < url.length; i++) | ||||
|             { | ||||
|                 excludes.add(url[i]); | ||||
|             } | ||||
|         } | ||||
|         if (StringUtils.isNotEmpty(tempEnabled)) | ||||
|         { | ||||
|             enabled = Boolean.valueOf(tempEnabled); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) | ||||
|             throws IOException, ServletException | ||||
|     { | ||||
|         HttpServletRequest req = (HttpServletRequest) request; | ||||
|         HttpServletResponse resp = (HttpServletResponse) response; | ||||
|         if (handleExcludeURL(req, resp)) | ||||
|         { | ||||
|             chain.doFilter(request, response); | ||||
|             return; | ||||
|         } | ||||
|         XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper((HttpServletRequest) request); | ||||
|         chain.doFilter(xssRequest, response); | ||||
|     } | ||||
|  | ||||
|     private boolean handleExcludeURL(HttpServletRequest request, HttpServletResponse response) | ||||
|     { | ||||
|         if (!enabled) | ||||
|         { | ||||
|             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; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void destroy() | ||||
|     { | ||||
|  | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,105 @@ | ||||
| package com.stdiet.common.filter; | ||||
|  | ||||
| import java.io.ByteArrayInputStream; | ||||
| import java.io.IOException; | ||||
| import javax.servlet.ReadListener; | ||||
| import javax.servlet.ServletInputStream; | ||||
| import javax.servlet.http.HttpServletRequest; | ||||
| import javax.servlet.http.HttpServletRequestWrapper; | ||||
| import org.apache.commons.io.IOUtils; | ||||
| import org.springframework.http.HttpHeaders; | ||||
| import org.springframework.http.MediaType; | ||||
| import com.stdiet.common.utils.StringUtils; | ||||
| import com.stdiet.common.utils.html.EscapeUtil; | ||||
|  | ||||
| /** | ||||
|  * XSS过滤处理 | ||||
|  *  | ||||
|  * @author stdiet | ||||
|  */ | ||||
| public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper | ||||
| { | ||||
|     /** | ||||
|      * @param request | ||||
|      */ | ||||
|     public XssHttpServletRequestWrapper(HttpServletRequest request) | ||||
|     { | ||||
|         super(request); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public String[] getParameterValues(String name) | ||||
|     { | ||||
|         String[] values = super.getParameterValues(name); | ||||
|         if (values != null) | ||||
|         { | ||||
|             int length = values.length; | ||||
|             String[] escapseValues = new String[length]; | ||||
|             for (int i = 0; i < length; i++) | ||||
|             { | ||||
|                 // 防xss攻击和过滤前后空格 | ||||
|                 escapseValues[i] = EscapeUtil.clean(values[i]).trim(); | ||||
|             } | ||||
|             return escapseValues; | ||||
|         } | ||||
|         return super.getParameterValues(name); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public ServletInputStream getInputStream() throws IOException | ||||
|     { | ||||
|         // 非json类型,直接返回 | ||||
|         if (!isJsonRequest()) | ||||
|         { | ||||
|             return super.getInputStream(); | ||||
|         } | ||||
|  | ||||
|         // 为空,直接返回 | ||||
|         String json = IOUtils.toString(super.getInputStream(), "utf-8"); | ||||
|         if (StringUtils.isEmpty(json)) | ||||
|         { | ||||
|             return super.getInputStream(); | ||||
|         } | ||||
|  | ||||
|         // xss过滤 | ||||
|         json = EscapeUtil.clean(json).trim(); | ||||
|         final ByteArrayInputStream bis = new ByteArrayInputStream(json.getBytes("utf-8")); | ||||
|         return new ServletInputStream() | ||||
|         { | ||||
|             @Override | ||||
|             public boolean isFinished() | ||||
|             { | ||||
|                 return true; | ||||
|             } | ||||
|  | ||||
|             @Override | ||||
|             public boolean isReady() | ||||
|             { | ||||
|                 return true; | ||||
|             } | ||||
|  | ||||
|             @Override | ||||
|             public void setReadListener(ReadListener readListener) | ||||
|             { | ||||
|             } | ||||
|  | ||||
|             @Override | ||||
|             public int read() throws IOException | ||||
|             { | ||||
|                 return bis.read(); | ||||
|             } | ||||
|         }; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 是否是Json请求 | ||||
|      *  | ||||
|      * @param request | ||||
|      */ | ||||
|     public boolean isJsonRequest() | ||||
|     { | ||||
|         String header = super.getHeader(HttpHeaders.CONTENT_TYPE); | ||||
|         return MediaType.APPLICATION_JSON_VALUE.equalsIgnoreCase(header) | ||||
|                 || MediaType.APPLICATION_JSON_UTF8_VALUE.equalsIgnoreCase(header); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										114
									
								
								stdiet-common/src/main/java/com/stdiet/common/utils/Arith.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										114
									
								
								stdiet-common/src/main/java/com/stdiet/common/utils/Arith.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,114 @@ | ||||
| package com.stdiet.common.utils; | ||||
|  | ||||
| import java.math.BigDecimal; | ||||
| import java.math.RoundingMode; | ||||
|  | ||||
| /** | ||||
|  * 精确的浮点数运算 | ||||
|  *  | ||||
|  * @author stdiet | ||||
|  */ | ||||
| public class Arith | ||||
| { | ||||
|  | ||||
|     /** 默认除法运算精度 */ | ||||
|     private static final int DEF_DIV_SCALE = 10; | ||||
|  | ||||
|     /** 这个类不能实例化 */ | ||||
|     private Arith() | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 提供精确的加法运算。 | ||||
|      * @param v1 被加数 | ||||
|      * @param v2 加数 | ||||
|      * @return 两个参数的和 | ||||
|      */ | ||||
|     public static double add(double v1, double v2) | ||||
|     { | ||||
|         BigDecimal b1 = new BigDecimal(Double.toString(v1)); | ||||
|         BigDecimal b2 = new BigDecimal(Double.toString(v2)); | ||||
|         return b1.add(b2).doubleValue(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 提供精确的减法运算。 | ||||
|      * @param v1 被减数 | ||||
|      * @param v2 减数 | ||||
|      * @return 两个参数的差 | ||||
|      */ | ||||
|     public static double sub(double v1, double v2) | ||||
|     { | ||||
|         BigDecimal b1 = new BigDecimal(Double.toString(v1)); | ||||
|         BigDecimal b2 = new BigDecimal(Double.toString(v2)); | ||||
|         return b1.subtract(b2).doubleValue(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 提供精确的乘法运算。 | ||||
|      * @param v1 被乘数 | ||||
|      * @param v2 乘数 | ||||
|      * @return 两个参数的积 | ||||
|      */ | ||||
|     public static double mul(double v1, double v2) | ||||
|     { | ||||
|         BigDecimal b1 = new BigDecimal(Double.toString(v1)); | ||||
|         BigDecimal b2 = new BigDecimal(Double.toString(v2)); | ||||
|         return b1.multiply(b2).doubleValue(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 提供(相对)精确的除法运算,当发生除不尽的情况时,精确到 | ||||
|      * 小数点以后10位,以后的数字四舍五入。 | ||||
|      * @param v1 被除数 | ||||
|      * @param v2 除数 | ||||
|      * @return 两个参数的商 | ||||
|      */ | ||||
|     public static double div(double v1, double v2) | ||||
|     { | ||||
|         return div(v1, v2, DEF_DIV_SCALE); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指 | ||||
|      * 定精度,以后的数字四舍五入。 | ||||
|      * @param v1 被除数 | ||||
|      * @param v2 除数 | ||||
|      * @param scale 表示表示需要精确到小数点以后几位。 | ||||
|      * @return 两个参数的商 | ||||
|      */ | ||||
|     public static double div(double v1, double v2, int scale) | ||||
|     { | ||||
|         if (scale < 0) | ||||
|         { | ||||
|             throw new IllegalArgumentException( | ||||
|                     "The scale must be a positive integer or zero"); | ||||
|         } | ||||
|         BigDecimal b1 = new BigDecimal(Double.toString(v1)); | ||||
|         BigDecimal b2 = new BigDecimal(Double.toString(v2)); | ||||
|         if (b1.compareTo(BigDecimal.ZERO) == 0) | ||||
|         { | ||||
|             return BigDecimal.ZERO.doubleValue(); | ||||
|         } | ||||
|         return b1.divide(b2, scale, RoundingMode.HALF_UP).doubleValue(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 提供精确的小数位四舍五入处理。 | ||||
|      * @param v 需要四舍五入的数字 | ||||
|      * @param scale 小数点后保留几位 | ||||
|      * @return 四舍五入后的结果 | ||||
|      */ | ||||
|     public static double round(double v, int scale) | ||||
|     { | ||||
|         if (scale < 0) | ||||
|         { | ||||
|             throw new IllegalArgumentException( | ||||
|                     "The scale must be a positive integer or zero"); | ||||
|         } | ||||
|         BigDecimal b = new BigDecimal(Double.toString(v)); | ||||
|         BigDecimal one = new BigDecimal("1"); | ||||
|         return b.divide(one, scale, RoundingMode.HALF_UP).doubleValue(); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,155 @@ | ||||
| package com.stdiet.common.utils; | ||||
|  | ||||
| import java.lang.management.ManagementFactory; | ||||
| import java.text.ParseException; | ||||
| import java.text.SimpleDateFormat; | ||||
| import java.util.Date; | ||||
| import org.apache.commons.lang3.time.DateFormatUtils; | ||||
|  | ||||
| /** | ||||
|  * 时间工具类 | ||||
|  *  | ||||
|  * @author stdiet | ||||
|  */ | ||||
| public class DateUtils extends org.apache.commons.lang3.time.DateUtils | ||||
| { | ||||
|     public static String YYYY = "yyyy"; | ||||
|  | ||||
|     public static String YYYY_MM = "yyyy-MM"; | ||||
|  | ||||
|     public static String YYYY_MM_DD = "yyyy-MM-dd"; | ||||
|  | ||||
|     public static String YYYYMMDDHHMMSS = "yyyyMMddHHmmss"; | ||||
|  | ||||
|     public static String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss"; | ||||
|      | ||||
|     private static String[] parsePatterns = { | ||||
|             "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM",  | ||||
|             "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM", | ||||
|             "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"}; | ||||
|  | ||||
|     /** | ||||
|      * 获取当前Date型日期 | ||||
|      *  | ||||
|      * @return Date() 当前日期 | ||||
|      */ | ||||
|     public static Date getNowDate() | ||||
|     { | ||||
|         return new Date(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 获取当前日期, 默认格式为yyyy-MM-dd | ||||
|      *  | ||||
|      * @return String | ||||
|      */ | ||||
|     public static String getDate() | ||||
|     { | ||||
|         return dateTimeNow(YYYY_MM_DD); | ||||
|     } | ||||
|  | ||||
|     public static final String getTime() | ||||
|     { | ||||
|         return dateTimeNow(YYYY_MM_DD_HH_MM_SS); | ||||
|     } | ||||
|  | ||||
|     public static final String dateTimeNow() | ||||
|     { | ||||
|         return dateTimeNow(YYYYMMDDHHMMSS); | ||||
|     } | ||||
|  | ||||
|     public static final String dateTimeNow(final String format) | ||||
|     { | ||||
|         return parseDateToStr(format, new Date()); | ||||
|     } | ||||
|  | ||||
|     public static final String dateTime(final Date date) | ||||
|     { | ||||
|         return parseDateToStr(YYYY_MM_DD, date); | ||||
|     } | ||||
|  | ||||
|     public static final String parseDateToStr(final String format, final Date date) | ||||
|     { | ||||
|         return new SimpleDateFormat(format).format(date); | ||||
|     } | ||||
|  | ||||
|     public static final Date dateTime(final String format, final String ts) | ||||
|     { | ||||
|         try | ||||
|         { | ||||
|             return new SimpleDateFormat(format).parse(ts); | ||||
|         } | ||||
|         catch (ParseException e) | ||||
|         { | ||||
|             throw new RuntimeException(e); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 日期路径 即年/月/日 如2018/08/08 | ||||
|      */ | ||||
|     public static final String datePath() | ||||
|     { | ||||
|         Date now = new Date(); | ||||
|         return DateFormatUtils.format(now, "yyyy/MM/dd"); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 日期路径 即年/月/日 如20180808 | ||||
|      */ | ||||
|     public static final String dateTime() | ||||
|     { | ||||
|         Date now = new Date(); | ||||
|         return DateFormatUtils.format(now, "yyyyMMdd"); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 日期型字符串转化为日期 格式 | ||||
|      */ | ||||
|     public static Date parseDate(Object str) | ||||
|     { | ||||
|         if (str == null) | ||||
|         { | ||||
|             return null; | ||||
|         } | ||||
|         try | ||||
|         { | ||||
|             return parseDate(str.toString(), parsePatterns); | ||||
|         } | ||||
|         catch (ParseException e) | ||||
|         { | ||||
|             return null; | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * 获取服务器启动时间 | ||||
|      */ | ||||
|     public static Date getServerStartDate() | ||||
|     { | ||||
|         long time = ManagementFactory.getRuntimeMXBean().getStartTime(); | ||||
|         return new Date(time); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 计算两个时间差 | ||||
|      */ | ||||
|     public static String getDatePoor(Date endDate, Date nowDate) | ||||
|     { | ||||
|         long nd = 1000 * 24 * 60 * 60; | ||||
|         long nh = 1000 * 60 * 60; | ||||
|         long nm = 1000 * 60; | ||||
|         // long ns = 1000; | ||||
|         // 获得两个时间的毫秒时间差异 | ||||
|         long diff = endDate.getTime() - nowDate.getTime(); | ||||
|         // 计算差多少天 | ||||
|         long day = diff / nd; | ||||
|         // 计算差多少小时 | ||||
|         long hour = diff % nd / nh; | ||||
|         // 计算差多少分钟 | ||||
|         long min = diff % nd % nh / nm; | ||||
|         // 计算差多少秒//输出结果 | ||||
|         // long sec = diff % nd % nh % nm / ns; | ||||
|         return day + "天" + hour + "小时" + min + "分钟"; | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,173 @@ | ||||
| package com.stdiet.common.utils; | ||||
|  | ||||
| import java.util.Collection; | ||||
| import java.util.List; | ||||
| import com.stdiet.common.constant.Constants; | ||||
| import com.stdiet.common.core.domain.entity.SysDictData; | ||||
| import com.stdiet.common.core.redis.RedisCache; | ||||
| import com.stdiet.common.utils.spring.SpringUtils; | ||||
|  | ||||
| /** | ||||
|  * 字典工具类 | ||||
|  *  | ||||
|  * @author ruoyi | ||||
|  */ | ||||
| public class DictUtils | ||||
| { | ||||
|     /** | ||||
|      * 分隔符 | ||||
|      */ | ||||
|     public static final String SEPARATOR = ","; | ||||
|  | ||||
|     /** | ||||
|      * 设置字典缓存 | ||||
|      *  | ||||
|      * @param key 参数键 | ||||
|      * @param dictDatas 字典数据列表 | ||||
|      */ | ||||
|     public static void setDictCache(String key, List<SysDictData> dictDatas) | ||||
|     { | ||||
|         SpringUtils.getBean(RedisCache.class).setCacheObject(getCacheKey(key), dictDatas); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 获取字典缓存 | ||||
|      *  | ||||
|      * @param key 参数键 | ||||
|      * @return dictDatas 字典数据列表 | ||||
|      */ | ||||
|     public static List<SysDictData> getDictCache(String key) | ||||
|     { | ||||
|         Object cacheObj = SpringUtils.getBean(RedisCache.class).getCacheObject(getCacheKey(key)); | ||||
|         if (StringUtils.isNotNull(cacheObj)) | ||||
|         { | ||||
|             List<SysDictData> dictDatas = StringUtils.cast(cacheObj); | ||||
|             return dictDatas; | ||||
|         } | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 根据字典类型和字典值获取字典标签 | ||||
|      *  | ||||
|      * @param dictType 字典类型 | ||||
|      * @param dictValue 字典值 | ||||
|      * @return 字典标签 | ||||
|      */ | ||||
|     public static String getDictLabel(String dictType, String dictValue) | ||||
|     { | ||||
|         return getDictLabel(dictType, dictValue, SEPARATOR); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 根据字典类型和字典标签获取字典值 | ||||
|      *  | ||||
|      * @param dictType 字典类型 | ||||
|      * @param dictLabel 字典标签 | ||||
|      * @return 字典值 | ||||
|      */ | ||||
|     public static String getDictValue(String dictType, String dictLabel) | ||||
|     { | ||||
|         return getDictValue(dictType, dictLabel, SEPARATOR); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 根据字典类型和字典值获取字典标签 | ||||
|      *  | ||||
|      * @param dictType 字典类型 | ||||
|      * @param dictValue 字典值 | ||||
|      * @param separator 分隔符 | ||||
|      * @return 字典标签 | ||||
|      */ | ||||
|     public static String getDictLabel(String dictType, String dictValue, String separator) | ||||
|     { | ||||
|         StringBuilder propertyString = new StringBuilder(); | ||||
|         List<SysDictData> datas = getDictCache(dictType); | ||||
|  | ||||
|         if (StringUtils.containsAny(separator, dictValue) && StringUtils.isNotEmpty(datas)) | ||||
|         { | ||||
|             for (SysDictData dict : datas) | ||||
|             { | ||||
|                 for (String value : dictValue.split(separator)) | ||||
|                 { | ||||
|                     if (value.equals(dict.getDictValue())) | ||||
|                     { | ||||
|                         propertyString.append(dict.getDictLabel() + separator); | ||||
|                         break; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             for (SysDictData dict : datas) | ||||
|             { | ||||
|                 if (dictValue.equals(dict.getDictValue())) | ||||
|                 { | ||||
|                     return dict.getDictLabel(); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         return StringUtils.stripEnd(propertyString.toString(), separator); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 根据字典类型和字典标签获取字典值 | ||||
|      *  | ||||
|      * @param dictType 字典类型 | ||||
|      * @param dictLabel 字典标签 | ||||
|      * @param separator 分隔符 | ||||
|      * @return 字典值 | ||||
|      */ | ||||
|     public static String getDictValue(String dictType, String dictLabel, String separator) | ||||
|     { | ||||
|         StringBuilder propertyString = new StringBuilder(); | ||||
|         List<SysDictData> datas = getDictCache(dictType); | ||||
|  | ||||
|         if (StringUtils.containsAny(separator, dictLabel) && StringUtils.isNotEmpty(datas)) | ||||
|         { | ||||
|             for (SysDictData dict : datas) | ||||
|             { | ||||
|                 for (String label : dictLabel.split(separator)) | ||||
|                 { | ||||
|                     if (label.equals(dict.getDictLabel())) | ||||
|                     { | ||||
|                         propertyString.append(dict.getDictValue() + separator); | ||||
|                         break; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             for (SysDictData dict : datas) | ||||
|             { | ||||
|                 if (dictLabel.equals(dict.getDictLabel())) | ||||
|                 { | ||||
|                     return dict.getDictValue(); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         return StringUtils.stripEnd(propertyString.toString(), separator); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 清空字典缓存 | ||||
|      */ | ||||
|     public static void clearDictCache() | ||||
|     { | ||||
|         Collection<String> keys = SpringUtils.getBean(RedisCache.class).keys(Constants.SYS_DICT_KEY + "*"); | ||||
|         SpringUtils.getBean(RedisCache.class).deleteObject(keys); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 设置cache key | ||||
|      *  | ||||
|      * @param configKey 参数键 | ||||
|      * @return 缓存键key | ||||
|      */ | ||||
|     public static String getCacheKey(String configKey) | ||||
|     { | ||||
|         return Constants.SYS_DICT_KEY + configKey; | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,40 @@ | ||||
| package com.stdiet.common.utils; | ||||
|  | ||||
| import java.io.PrintWriter; | ||||
| import java.io.StringWriter; | ||||
| import org.apache.commons.lang3.exception.ExceptionUtils; | ||||
|  | ||||
| /** | ||||
|  * 错误信息处理类。 | ||||
|  * | ||||
|  * @author ruoyi | ||||
|  */ | ||||
| public class ExceptionUtil | ||||
| { | ||||
|     /** | ||||
|      * 获取exception的详细错误信息。 | ||||
|      */ | ||||
|     public static String getExceptionMessage(Throwable e) | ||||
|     { | ||||
|         StringWriter sw = new StringWriter(); | ||||
|         e.printStackTrace(new PrintWriter(sw, true)); | ||||
|         String str = sw.toString(); | ||||
|         return str; | ||||
|     } | ||||
|  | ||||
|     public static String getRootErrorMseeage(Exception e) | ||||
|     { | ||||
|         Throwable root = ExceptionUtils.getRootCause(e); | ||||
|         root = (root == null ? e : root); | ||||
|         if (root == null) | ||||
|         { | ||||
|             return ""; | ||||
|         } | ||||
|         String msg = root.getMessage(); | ||||
|         if (msg == null) | ||||
|         { | ||||
|             return "null"; | ||||
|         } | ||||
|         return StringUtils.defaultString(msg); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,18 @@ | ||||
| package com.stdiet.common.utils; | ||||
|  | ||||
| /** | ||||
|  * 处理并记录日志文件 | ||||
|  *  | ||||
|  * @author stdiet | ||||
|  */ | ||||
| public class LogUtils | ||||
| { | ||||
|     public static String getBlock(Object msg) | ||||
|     { | ||||
|         if (msg == null) | ||||
|         { | ||||
|             msg = ""; | ||||
|         } | ||||
|         return "[" + msg.toString() + "]"; | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,26 @@ | ||||
| package com.stdiet.common.utils; | ||||
|  | ||||
| import org.springframework.context.MessageSource; | ||||
| import org.springframework.context.i18n.LocaleContextHolder; | ||||
| import com.stdiet.common.utils.spring.SpringUtils; | ||||
|  | ||||
| /** | ||||
|  * 获取i18n资源文件 | ||||
|  *  | ||||
|  * @author stdiet | ||||
|  */ | ||||
| public class MessageUtils | ||||
| { | ||||
|     /** | ||||
|      * 根据消息键和参数 获取消息 委托给spring messageSource | ||||
|      * | ||||
|      * @param code 消息键 | ||||
|      * @param args 参数 | ||||
|      * @return 获取国际化翻译值 | ||||
|      */ | ||||
|     public static String message(String code, Object... args) | ||||
|     { | ||||
|         MessageSource messageSource = SpringUtils.getBean(MessageSource.class); | ||||
|         return messageSource.getMessage(code, args, LocaleContextHolder.getLocale()); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,90 @@ | ||||
| package com.stdiet.common.utils; | ||||
|  | ||||
| import org.springframework.security.core.Authentication; | ||||
| import org.springframework.security.core.context.SecurityContextHolder; | ||||
| import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; | ||||
| import com.stdiet.common.constant.HttpStatus; | ||||
| import com.stdiet.common.core.domain.model.LoginUser; | ||||
| import com.stdiet.common.exception.CustomException; | ||||
|  | ||||
| /** | ||||
|  * 安全服务工具类 | ||||
|  *  | ||||
|  * @author stdiet | ||||
|  */ | ||||
| public class SecurityUtils | ||||
| { | ||||
|     /** | ||||
|      * 获取用户账户 | ||||
|      **/ | ||||
|     public static String getUsername() | ||||
|     { | ||||
|         try | ||||
|         { | ||||
|             return getLoginUser().getUsername(); | ||||
|         } | ||||
|         catch (Exception e) | ||||
|         { | ||||
|             throw new CustomException("获取用户账户异常", HttpStatus.UNAUTHORIZED); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 获取用户 | ||||
|      **/ | ||||
|     public static LoginUser getLoginUser() | ||||
|     { | ||||
|         try | ||||
|         { | ||||
|             return (LoginUser) getAuthentication().getPrincipal(); | ||||
|         } | ||||
|         catch (Exception e) | ||||
|         { | ||||
|             throw new CustomException("获取用户信息异常", HttpStatus.UNAUTHORIZED); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 获取Authentication | ||||
|      */ | ||||
|     public static Authentication getAuthentication() | ||||
|     { | ||||
|         return SecurityContextHolder.getContext().getAuthentication(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 生成BCryptPasswordEncoder密码 | ||||
|      * | ||||
|      * @param password 密码 | ||||
|      * @return 加密字符串 | ||||
|      */ | ||||
|     public static String encryptPassword(String password) | ||||
|     { | ||||
|         BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); | ||||
|         return passwordEncoder.encode(password); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 判断密码是否相同 | ||||
|      * | ||||
|      * @param rawPassword 真实密码 | ||||
|      * @param encodedPassword 加密后字符 | ||||
|      * @return 结果 | ||||
|      */ | ||||
|     public static boolean matchesPassword(String rawPassword, String encodedPassword) | ||||
|     { | ||||
|         BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); | ||||
|         return passwordEncoder.matches(rawPassword, encodedPassword); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 是否为管理员 | ||||
|      *  | ||||
|      * @param userId 用户ID | ||||
|      * @return 结果 | ||||
|      */ | ||||
|     public static boolean isAdmin(Long userId) | ||||
|     { | ||||
|         return userId != null && 1L == userId; | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,136 @@ | ||||
| package com.stdiet.common.utils; | ||||
|  | ||||
| import java.io.IOException; | ||||
| import javax.servlet.http.HttpServletRequest; | ||||
| import javax.servlet.http.HttpServletResponse; | ||||
| import javax.servlet.http.HttpSession; | ||||
| import org.springframework.web.context.request.RequestAttributes; | ||||
| import org.springframework.web.context.request.RequestContextHolder; | ||||
| import org.springframework.web.context.request.ServletRequestAttributes; | ||||
| import com.stdiet.common.core.text.Convert; | ||||
|  | ||||
| /** | ||||
|  * 客户端工具类 | ||||
|  *  | ||||
|  * @author ruoyi | ||||
|  */ | ||||
| public class ServletUtils | ||||
| { | ||||
|     /** | ||||
|      * 获取String参数 | ||||
|      */ | ||||
|     public static String getParameter(String name) | ||||
|     { | ||||
|         return getRequest().getParameter(name); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 获取String参数 | ||||
|      */ | ||||
|     public static String getParameter(String name, String defaultValue) | ||||
|     { | ||||
|         return Convert.toStr(getRequest().getParameter(name), defaultValue); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 获取Integer参数 | ||||
|      */ | ||||
|     public static Integer getParameterToInt(String name) | ||||
|     { | ||||
|         return Convert.toInt(getRequest().getParameter(name)); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 获取Integer参数 | ||||
|      */ | ||||
|     public static Integer getParameterToInt(String name, Integer defaultValue) | ||||
|     { | ||||
|         return Convert.toInt(getRequest().getParameter(name), defaultValue); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 获取request | ||||
|      */ | ||||
|     public static HttpServletRequest getRequest() | ||||
|     { | ||||
|         return getRequestAttributes().getRequest(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 获取response | ||||
|      */ | ||||
|     public static HttpServletResponse getResponse() | ||||
|     { | ||||
|         return getRequestAttributes().getResponse(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 获取session | ||||
|      */ | ||||
|     public static HttpSession getSession() | ||||
|     { | ||||
|         return getRequest().getSession(); | ||||
|     } | ||||
|  | ||||
|     public static ServletRequestAttributes getRequestAttributes() | ||||
|     { | ||||
|         RequestAttributes attributes = RequestContextHolder.getRequestAttributes(); | ||||
|         return (ServletRequestAttributes) attributes; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 将字符串渲染到客户端 | ||||
|      *  | ||||
|      * @param response 渲染对象 | ||||
|      * @param string 待渲染的字符串 | ||||
|      * @return null | ||||
|      */ | ||||
|     public static String renderString(HttpServletResponse response, String string) | ||||
|     { | ||||
|         try | ||||
|         { | ||||
|             response.setStatus(200); | ||||
|             response.setContentType("application/json"); | ||||
|             response.setCharacterEncoding("utf-8"); | ||||
|             response.getWriter().print(string); | ||||
|         } | ||||
|         catch (IOException e) | ||||
|         { | ||||
|             e.printStackTrace(); | ||||
|         } | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 是否是Ajax异步请求 | ||||
|      *  | ||||
|      * @param request | ||||
|      */ | ||||
|     public static boolean isAjaxRequest(HttpServletRequest request) | ||||
|     { | ||||
|         String accept = request.getHeader("accept"); | ||||
|         if (accept != null && accept.indexOf("application/json") != -1) | ||||
|         { | ||||
|             return true; | ||||
|         } | ||||
|  | ||||
|         String xRequestedWith = request.getHeader("X-Requested-With"); | ||||
|         if (xRequestedWith != null && xRequestedWith.indexOf("XMLHttpRequest") != -1) | ||||
|         { | ||||
|             return true; | ||||
|         } | ||||
|  | ||||
|         String uri = request.getRequestURI(); | ||||
|         if (StringUtils.inStringIgnoreCase(uri, ".json", ".xml")) | ||||
|         { | ||||
|             return true; | ||||
|         } | ||||
|  | ||||
|         String ajax = request.getParameter("__ajax"); | ||||
|         if (StringUtils.inStringIgnoreCase(ajax, "json", "xml")) | ||||
|         { | ||||
|             return true; | ||||
|         } | ||||
|         return false; | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,459 @@ | ||||
| package com.stdiet.common.utils; | ||||
|  | ||||
| import java.util.ArrayList; | ||||
| import java.util.Collection; | ||||
| import java.util.HashSet; | ||||
| import java.util.List; | ||||
| import java.util.Map; | ||||
| import java.util.Set; | ||||
| import com.stdiet.common.core.text.StrFormatter; | ||||
|  | ||||
| /** | ||||
|  * 字符串工具类 | ||||
|  *  | ||||
|  * @author ruoyi | ||||
|  */ | ||||
| public class StringUtils extends org.apache.commons.lang3.StringUtils | ||||
| { | ||||
|     /** 空字符串 */ | ||||
|     private static final String NULLSTR = ""; | ||||
|  | ||||
|     /** 下划线 */ | ||||
|     private static final char SEPARATOR = '_'; | ||||
|  | ||||
|     /** | ||||
|      * 获取参数不为空值 | ||||
|      *  | ||||
|      * @param value defaultValue 要判断的value | ||||
|      * @return value 返回值 | ||||
|      */ | ||||
|     public static <T> T nvl(T value, T defaultValue) | ||||
|     { | ||||
|         return value != null ? value : defaultValue; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * * 判断一个Collection是否为空, 包含List,Set,Queue | ||||
|      *  | ||||
|      * @param coll 要判断的Collection | ||||
|      * @return true:为空 false:非空 | ||||
|      */ | ||||
|     public static boolean isEmpty(Collection<?> coll) | ||||
|     { | ||||
|         return isNull(coll) || coll.isEmpty(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * * 判断一个Collection是否非空,包含List,Set,Queue | ||||
|      *  | ||||
|      * @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 isNull(objects) || (objects.length == 0); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * * 判断一个对象数组是否非空 | ||||
|      *  | ||||
|      * @param objects 要判断的对象数组 | ||||
|      * @return true:非空 false:空 | ||||
|      */ | ||||
|     public static boolean isNotEmpty(Object[] objects) | ||||
|     { | ||||
|         return !isEmpty(objects); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * * 判断一个Map是否为空 | ||||
|      *  | ||||
|      * @param map 要判断的Map | ||||
|      * @return true:为空 false:非空 | ||||
|      */ | ||||
|     public static boolean isEmpty(Map<?, ?> map) | ||||
|     { | ||||
|         return isNull(map) || map.isEmpty(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * * 判断一个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 isNull(str) || NULLSTR.equals(str.trim()); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * * 判断一个字符串是否为非空串 | ||||
|      *  | ||||
|      * @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 object == null; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * * 判断一个对象是否非空 | ||||
|      *  | ||||
|      * @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 isNotNull(object) && object.getClass().isArray(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 去空格 | ||||
|      */ | ||||
|     public static String trim(String str) | ||||
|     { | ||||
|         return (str == null ? "" : str.trim()); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 截取字符串 | ||||
|      *  | ||||
|      * @param str 字符串 | ||||
|      * @param start 开始 | ||||
|      * @return 结果 | ||||
|      */ | ||||
|     public static String substring(final String str, int start) | ||||
|     { | ||||
|         if (str == null) | ||||
|         { | ||||
|             return NULLSTR; | ||||
|         } | ||||
|  | ||||
|         if (start < 0) | ||||
|         { | ||||
|             start = str.length() + start; | ||||
|         } | ||||
|  | ||||
|         if (start < 0) | ||||
|         { | ||||
|             start = 0; | ||||
|         } | ||||
|         if (start > str.length()) | ||||
|         { | ||||
|             return NULLSTR; | ||||
|         } | ||||
|  | ||||
|         return str.substring(start); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 截取字符串 | ||||
|      *  | ||||
|      * @param str 字符串 | ||||
|      * @param start 开始 | ||||
|      * @param end 结束 | ||||
|      * @return 结果 | ||||
|      */ | ||||
|     public static String substring(final String str, int start, int end) | ||||
|     { | ||||
|         if (str == null) | ||||
|         { | ||||
|             return NULLSTR; | ||||
|         } | ||||
|  | ||||
|         if (end < 0) | ||||
|         { | ||||
|             end = str.length() + end; | ||||
|         } | ||||
|         if (start < 0) | ||||
|         { | ||||
|             start = str.length() + start; | ||||
|         } | ||||
|  | ||||
|         if (end > str.length()) | ||||
|         { | ||||
|             end = str.length(); | ||||
|         } | ||||
|  | ||||
|         if (start > end) | ||||
|         { | ||||
|             return NULLSTR; | ||||
|         } | ||||
|  | ||||
|         if (start < 0) | ||||
|         { | ||||
|             start = 0; | ||||
|         } | ||||
|         if (end < 0) | ||||
|         { | ||||
|             end = 0; | ||||
|         } | ||||
|  | ||||
|         return str.substring(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) | ||||
|     { | ||||
|         if (isEmpty(params) || isEmpty(template)) | ||||
|         { | ||||
|             return template; | ||||
|         } | ||||
|         return StrFormatter.format(template, params); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 字符串转set | ||||
|      *  | ||||
|      * @param str 字符串 | ||||
|      * @param sep 分隔符 | ||||
|      * @return set集合 | ||||
|      */ | ||||
|     public static final Set<String> str2Set(String str, String sep) | ||||
|     { | ||||
|         return new HashSet<String>(str2List(str, sep, true, false)); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 字符串转list | ||||
|      *  | ||||
|      * @param str 字符串 | ||||
|      * @param sep 分隔符 | ||||
|      * @param filterBlank 过滤纯空白 | ||||
|      * @param trim 去掉首尾空白 | ||||
|      * @return list集合 | ||||
|      */ | ||||
|     public static final List<String> str2List(String str, String sep, boolean filterBlank, boolean trim) | ||||
|     { | ||||
|         List<String> list = new ArrayList<String>(); | ||||
|         if (StringUtils.isEmpty(str)) | ||||
|         { | ||||
|             return list; | ||||
|         } | ||||
|  | ||||
|         // 过滤空白字符串 | ||||
|         if (filterBlank && StringUtils.isBlank(str)) | ||||
|         { | ||||
|             return list; | ||||
|         } | ||||
|         String[] split = str.split(sep); | ||||
|         for (String string : split) | ||||
|         { | ||||
|             if (filterBlank && StringUtils.isBlank(string)) | ||||
|             { | ||||
|                 continue; | ||||
|             } | ||||
|             if (trim) | ||||
|             { | ||||
|                 string = string.trim(); | ||||
|             } | ||||
|             list.add(string); | ||||
|         } | ||||
|  | ||||
|         return list; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 下划线转驼峰命名 | ||||
|      */ | ||||
|     public static String toUnderScoreCase(String str) | ||||
|     { | ||||
|         if (str == null) | ||||
|         { | ||||
|             return null; | ||||
|         } | ||||
|         StringBuilder sb = new StringBuilder(); | ||||
|         // 前置字符是否大写 | ||||
|         boolean preCharIsUpperCase = true; | ||||
|         // 当前字符是否大写 | ||||
|         boolean curreCharIsUpperCase = true; | ||||
|         // 下一字符是否大写 | ||||
|         boolean nexteCharIsUpperCase = true; | ||||
|         for (int i = 0; i < str.length(); i++) | ||||
|         { | ||||
|             char c = str.charAt(i); | ||||
|             if (i > 0) | ||||
|             { | ||||
|                 preCharIsUpperCase = Character.isUpperCase(str.charAt(i - 1)); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 preCharIsUpperCase = false; | ||||
|             } | ||||
|  | ||||
|             curreCharIsUpperCase = Character.isUpperCase(c); | ||||
|  | ||||
|             if (i < (str.length() - 1)) | ||||
|             { | ||||
|                 nexteCharIsUpperCase = Character.isUpperCase(str.charAt(i + 1)); | ||||
|             } | ||||
|  | ||||
|             if (preCharIsUpperCase && curreCharIsUpperCase && !nexteCharIsUpperCase) | ||||
|             { | ||||
|                 sb.append(SEPARATOR); | ||||
|             } | ||||
|             else if ((i != 0 && !preCharIsUpperCase) && curreCharIsUpperCase) | ||||
|             { | ||||
|                 sb.append(SEPARATOR); | ||||
|             } | ||||
|             sb.append(Character.toLowerCase(c)); | ||||
|         } | ||||
|  | ||||
|         return sb.toString(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 是否包含字符串 | ||||
|      *  | ||||
|      * @param str 验证字符串 | ||||
|      * @param strs 字符串组 | ||||
|      * @return 包含返回true | ||||
|      */ | ||||
|     public static boolean inStringIgnoreCase(String str, String... strs) | ||||
|     { | ||||
|         if (str != null && strs != null) | ||||
|         { | ||||
|             for (String s : strs) | ||||
|             { | ||||
|                 if (str.equalsIgnoreCase(trim(s))) | ||||
|                 { | ||||
|                     return true; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 将下划线大写方式命名的字符串转换为驼峰式。如果转换前的下划线大写方式命名的字符串为空,则返回空字符串。 例如:HELLO_WORLD->HelloWorld | ||||
|      *  | ||||
|      * @param name 转换前的下划线大写方式命名的字符串 | ||||
|      * @return 转换后的驼峰式命名的字符串 | ||||
|      */ | ||||
|     public static String convertToCamelCase(String name) | ||||
|     { | ||||
|         StringBuilder result = new StringBuilder(); | ||||
|         // 快速检查 | ||||
|         if (name == null || name.isEmpty()) | ||||
|         { | ||||
|             // 没必要转换 | ||||
|             return ""; | ||||
|         } | ||||
|         else if (!name.contains("_")) | ||||
|         { | ||||
|             // 不含下划线,仅将首字母大写 | ||||
|             return name.substring(0, 1).toUpperCase() + name.substring(1); | ||||
|         } | ||||
|         // 用下划线将原始字符串分割 | ||||
|         String[] camels = name.split("_"); | ||||
|         for (String camel : camels) | ||||
|         { | ||||
|             // 跳过原始字符串中开头、结尾的下换线或双重下划线 | ||||
|             if (camel.isEmpty()) | ||||
|             { | ||||
|                 continue; | ||||
|             } | ||||
|             // 首字母大写 | ||||
|             result.append(camel.substring(0, 1).toUpperCase()); | ||||
|             result.append(camel.substring(1).toLowerCase()); | ||||
|         } | ||||
|         return result.toString(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 驼峰式命名法 例如:user_name->userName | ||||
|      */ | ||||
|     public static String toCamelCase(String s) | ||||
|     { | ||||
|         if (s == null) | ||||
|         { | ||||
|             return null; | ||||
|         } | ||||
|         s = s.toLowerCase(); | ||||
|         StringBuilder sb = new StringBuilder(s.length()); | ||||
|         boolean upperCase = false; | ||||
|         for (int i = 0; i < s.length(); i++) | ||||
|         { | ||||
|             char c = s.charAt(i); | ||||
|  | ||||
|             if (c == SEPARATOR) | ||||
|             { | ||||
|                 upperCase = true; | ||||
|             } | ||||
|             else if (upperCase) | ||||
|             { | ||||
|                 sb.append(Character.toUpperCase(c)); | ||||
|                 upperCase = false; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 sb.append(c); | ||||
|             } | ||||
|         } | ||||
|         return sb.toString(); | ||||
|     } | ||||
|  | ||||
|     @SuppressWarnings("unchecked") | ||||
|     public static <T> T cast(Object obj) | ||||
|     { | ||||
|         return (T) obj; | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,99 @@ | ||||
| package com.stdiet.common.utils; | ||||
|  | ||||
| import java.util.concurrent.CancellationException; | ||||
| import java.util.concurrent.ExecutionException; | ||||
| import java.util.concurrent.ExecutorService; | ||||
| import java.util.concurrent.Future; | ||||
| import java.util.concurrent.TimeUnit; | ||||
| import org.slf4j.Logger; | ||||
| import org.slf4j.LoggerFactory; | ||||
|  | ||||
| /** | ||||
|  * 线程相关工具类. | ||||
|  *  | ||||
|  * @author stdiet | ||||
|  */ | ||||
| public class Threads | ||||
| { | ||||
|     private static final Logger logger = LoggerFactory.getLogger(Threads.class); | ||||
|  | ||||
|     /** | ||||
|      * sleep等待,单位为毫秒 | ||||
|      */ | ||||
|     public static void sleep(long milliseconds) | ||||
|     { | ||||
|         try | ||||
|         { | ||||
|             Thread.sleep(milliseconds); | ||||
|         } | ||||
|         catch (InterruptedException e) | ||||
|         { | ||||
|             return; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 停止线程池 | ||||
|      * 先使用shutdown, 停止接收新任务并尝试完成所有已存在任务. | ||||
|      * 如果超时, 则调用shutdownNow, 取消在workQueue中Pending的任务,并中断所有阻塞函数. | ||||
|      * 如果仍人超時,則強制退出. | ||||
|      * 另对在shutdown时线程本身被调用中断做了处理. | ||||
|      */ | ||||
|     public static void shutdownAndAwaitTermination(ExecutorService pool) | ||||
|     { | ||||
|         if (pool != null && !pool.isShutdown()) | ||||
|         { | ||||
|             pool.shutdown(); | ||||
|             try | ||||
|             { | ||||
|                 if (!pool.awaitTermination(120, TimeUnit.SECONDS)) | ||||
|                 { | ||||
|                     pool.shutdownNow(); | ||||
|                     if (!pool.awaitTermination(120, TimeUnit.SECONDS)) | ||||
|                     { | ||||
|                         logger.info("Pool did not terminate"); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|             catch (InterruptedException ie) | ||||
|             { | ||||
|                 pool.shutdownNow(); | ||||
|                 Thread.currentThread().interrupt(); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 打印线程异常信息 | ||||
|      */ | ||||
|     public static void printException(Runnable r, Throwable t) | ||||
|     { | ||||
|         if (t == null && r instanceof Future<?>) | ||||
|         { | ||||
|             try | ||||
|             { | ||||
|                 Future<?> future = (Future<?>) r; | ||||
|                 if (future.isDone()) | ||||
|                 { | ||||
|                     future.get(); | ||||
|                 } | ||||
|             } | ||||
|             catch (CancellationException ce) | ||||
|             { | ||||
|                 t = ce; | ||||
|             } | ||||
|             catch (ExecutionException ee) | ||||
|             { | ||||
|                 t = ee.getCause(); | ||||
|             } | ||||
|             catch (InterruptedException ie) | ||||
|             { | ||||
|                 Thread.currentThread().interrupt(); | ||||
|             } | ||||
|         } | ||||
|         if (t != null) | ||||
|         { | ||||
|             logger.error(t.getMessage(), t); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,228 @@ | ||||
| package com.stdiet.common.utils; | ||||
|  | ||||
| import java.awt.Color; | ||||
| import java.awt.Font; | ||||
| import java.awt.Graphics; | ||||
| import java.awt.Graphics2D; | ||||
| import java.awt.RenderingHints; | ||||
| import java.awt.geom.AffineTransform; | ||||
| import java.awt.image.BufferedImage; | ||||
| import java.io.IOException; | ||||
| import java.io.OutputStream; | ||||
| import java.security.SecureRandom; | ||||
| import java.util.Arrays; | ||||
| import java.util.Random; | ||||
| import javax.imageio.ImageIO; | ||||
|  | ||||
| /** | ||||
|  * 验证码工具类 | ||||
|  *  | ||||
|  * @author ruoyi | ||||
|  */ | ||||
| public class VerifyCodeUtils | ||||
| { | ||||
|     // 使用到Algerian字体,系统里没有的话需要安装字体,字体只显示大写,去掉了1,0,i,o几个容易混淆的字符 | ||||
|     public static final String VERIFY_CODES = "123456789ABCDEFGHJKLMNPQRSTUVWXYZ"; | ||||
|  | ||||
|     private static Random random = new SecureRandom(); | ||||
|  | ||||
|     /** | ||||
|      * 使用系统默认字符源生成验证码 | ||||
|      *  | ||||
|      * @param verifySize 验证码长度 | ||||
|      * @return | ||||
|      */ | ||||
|     public static String generateVerifyCode(int verifySize) | ||||
|     { | ||||
|         return generateVerifyCode(verifySize, VERIFY_CODES); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 使用指定源生成验证码 | ||||
|      *  | ||||
|      * @param verifySize 验证码长度 | ||||
|      * @param sources 验证码字符源 | ||||
|      * @return | ||||
|      */ | ||||
|     public static String generateVerifyCode(int verifySize, String sources) | ||||
|     { | ||||
|         if (sources == null || sources.length() == 0) | ||||
|         { | ||||
|             sources = VERIFY_CODES; | ||||
|         } | ||||
|         int codesLen = sources.length(); | ||||
|         Random rand = new Random(System.currentTimeMillis()); | ||||
|         StringBuilder verifyCode = new StringBuilder(verifySize); | ||||
|         for (int i = 0; i < verifySize; i++) | ||||
|         { | ||||
|             verifyCode.append(sources.charAt(rand.nextInt(codesLen - 1))); | ||||
|         } | ||||
|         return verifyCode.toString(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 输出指定验证码图片流 | ||||
|      *  | ||||
|      * @param w | ||||
|      * @param h | ||||
|      * @param os | ||||
|      * @param code | ||||
|      * @throws IOException | ||||
|      */ | ||||
|     public static void outputImage(int w, int h, OutputStream os, String code) throws IOException | ||||
|     { | ||||
|         int verifySize = code.length(); | ||||
|         BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); | ||||
|         Random rand = new Random(); | ||||
|         Graphics2D g2 = image.createGraphics(); | ||||
|         g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); | ||||
|         Color[] colors = new Color[5]; | ||||
|         Color[] colorSpaces = new Color[] { Color.WHITE, Color.CYAN, Color.GRAY, Color.LIGHT_GRAY, Color.MAGENTA, | ||||
|                 Color.ORANGE, Color.PINK, Color.YELLOW }; | ||||
|         float[] fractions = new float[colors.length]; | ||||
|         for (int i = 0; i < colors.length; i++) | ||||
|         { | ||||
|             colors[i] = colorSpaces[rand.nextInt(colorSpaces.length)]; | ||||
|             fractions[i] = rand.nextFloat(); | ||||
|         } | ||||
|         Arrays.sort(fractions); | ||||
|  | ||||
|         g2.setColor(Color.GRAY);// 设置边框色 | ||||
|         g2.fillRect(0, 0, w, h); | ||||
|  | ||||
|         Color c = getRandColor(200, 250); | ||||
|         g2.setColor(c);// 设置背景色 | ||||
|         g2.fillRect(0, 2, w, h - 4); | ||||
|  | ||||
|         // 绘制干扰线 | ||||
|         Random random = new Random(); | ||||
|         g2.setColor(getRandColor(160, 200));// 设置线条的颜色 | ||||
|         for (int i = 0; i < 20; i++) | ||||
|         { | ||||
|             int x = random.nextInt(w - 1); | ||||
|             int y = random.nextInt(h - 1); | ||||
|             int xl = random.nextInt(6) + 1; | ||||
|             int yl = random.nextInt(12) + 1; | ||||
|             g2.drawLine(x, y, x + xl + 40, y + yl + 20); | ||||
|         } | ||||
|  | ||||
|         // 添加噪点 | ||||
|         float yawpRate = 0.05f;// 噪声率 | ||||
|         int area = (int) (yawpRate * w * h); | ||||
|         for (int i = 0; i < area; i++) | ||||
|         { | ||||
|             int x = random.nextInt(w); | ||||
|             int y = random.nextInt(h); | ||||
|             int rgb = getRandomIntColor(); | ||||
|             image.setRGB(x, y, rgb); | ||||
|         } | ||||
|  | ||||
|         shear(g2, w, h, c);// 使图片扭曲 | ||||
|  | ||||
|         g2.setColor(getRandColor(100, 160)); | ||||
|         int fontSize = h - 4; | ||||
|         Font font = new Font("Algerian", Font.ITALIC, fontSize); | ||||
|         g2.setFont(font); | ||||
|         char[] chars = code.toCharArray(); | ||||
|         for (int i = 0; i < verifySize; i++) | ||||
|         { | ||||
|             AffineTransform affine = new AffineTransform(); | ||||
|             affine.setToRotation(Math.PI / 4 * rand.nextDouble() * (rand.nextBoolean() ? 1 : -1), | ||||
|                     (w / verifySize) * i + fontSize / 2, h / 2); | ||||
|             g2.setTransform(affine); | ||||
|             g2.drawChars(chars, i, 1, ((w - 10) / verifySize) * i + 5, h / 2 + fontSize / 2 - 10); | ||||
|         } | ||||
|  | ||||
|         g2.dispose(); | ||||
|         ImageIO.write(image, "jpg", os); | ||||
|     } | ||||
|  | ||||
|     private static Color getRandColor(int fc, int bc) | ||||
|     { | ||||
|         if (fc > 255) { | ||||
|             fc = 255; | ||||
|         } | ||||
|         if (bc > 255) { | ||||
|             bc = 255; | ||||
|         } | ||||
|         int r = fc + random.nextInt(bc - fc); | ||||
|         int g = fc + random.nextInt(bc - fc); | ||||
|         int b = fc + random.nextInt(bc - fc); | ||||
|         return new Color(r, g, b); | ||||
|     } | ||||
|  | ||||
|     private static int getRandomIntColor() | ||||
|     { | ||||
|         int[] rgb = getRandomRgb(); | ||||
|         int color = 0; | ||||
|         for (int c : rgb) | ||||
|         { | ||||
|             color = color << 8; | ||||
|             color = color | c; | ||||
|         } | ||||
|         return color; | ||||
|     } | ||||
|  | ||||
|     private static int[] getRandomRgb() | ||||
|     { | ||||
|         int[] rgb = new int[3]; | ||||
|         for (int i = 0; i < 3; i++) | ||||
|         { | ||||
|             rgb[i] = random.nextInt(255); | ||||
|         } | ||||
|         return rgb; | ||||
|     } | ||||
|  | ||||
|     private static void shear(Graphics g, int w1, int h1, Color color) | ||||
|     { | ||||
|         shearX(g, w1, h1, color); | ||||
|         shearY(g, w1, h1, color); | ||||
|     } | ||||
|  | ||||
|     private static void shearX(Graphics g, int w1, int h1, Color color) | ||||
|     { | ||||
|  | ||||
|         int period = random.nextInt(2); | ||||
|  | ||||
|         boolean borderGap = true; | ||||
|         int frames = 1; | ||||
|         int phase = random.nextInt(2); | ||||
|  | ||||
|         for (int i = 0; i < h1; i++) | ||||
|         { | ||||
|             double d = (double) (period >> 1) | ||||
|                     * Math.sin((double) i / (double) period + (6.2831853071795862D * (double) phase) / (double) frames); | ||||
|             g.copyArea(0, i, w1, 1, (int) d, 0); | ||||
|             if (borderGap) | ||||
|             { | ||||
|                 g.setColor(color); | ||||
|                 g.drawLine((int) d, i, 0, i); | ||||
|                 g.drawLine((int) d + w1, i, w1, i); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|     } | ||||
|  | ||||
|     private static void shearY(Graphics g, int w1, int h1, Color color) | ||||
|     { | ||||
|  | ||||
|         int period = random.nextInt(40) + 10; // 50; | ||||
|  | ||||
|         boolean borderGap = true; | ||||
|         int frames = 20; | ||||
|         int phase = 7; | ||||
|         for (int i = 0; i < w1; i++) | ||||
|         { | ||||
|             double d = (double) (period >> 1) | ||||
|                     * Math.sin((double) i / (double) period + (6.2831853071795862D * (double) phase) / (double) frames); | ||||
|             g.copyArea(i, 0, 1, h1, 0, (int) d); | ||||
|             if (borderGap) | ||||
|             { | ||||
|                 g.setColor(color); | ||||
|                 g.drawLine(i, (int) d, i, 0); | ||||
|                 g.drawLine(i, (int) d + h1, i, h1); | ||||
|             } | ||||
|  | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,110 @@ | ||||
| package com.stdiet.common.utils.bean; | ||||
|  | ||||
| import java.lang.reflect.Method; | ||||
| import java.util.ArrayList; | ||||
| import java.util.List; | ||||
| import java.util.regex.Matcher; | ||||
| import java.util.regex.Pattern; | ||||
|  | ||||
| /** | ||||
|  * Bean 工具类 | ||||
|  *  | ||||
|  * @author stdiet | ||||
|  */ | ||||
| public class BeanUtils extends org.springframework.beans.BeanUtils | ||||
| { | ||||
|     /** Bean方法名中属性名开始的下标 */ | ||||
|     private static final int BEAN_METHOD_PROP_INDEX = 3; | ||||
|  | ||||
|     /** * 匹配getter方法的正则表达式 */ | ||||
|     private static final Pattern GET_PATTERN = Pattern.compile("get(\\p{javaUpperCase}\\w*)"); | ||||
|  | ||||
|     /** * 匹配setter方法的正则表达式 */ | ||||
|     private static final Pattern SET_PATTERN = Pattern.compile("set(\\p{javaUpperCase}\\w*)"); | ||||
|  | ||||
|     /** | ||||
|      * Bean属性复制工具方法。 | ||||
|      *  | ||||
|      * @param dest 目标对象 | ||||
|      * @param src 源对象 | ||||
|      */ | ||||
|     public static void copyBeanProp(Object dest, Object src) | ||||
|     { | ||||
|         try | ||||
|         { | ||||
|             copyProperties(src, dest); | ||||
|         } | ||||
|         catch (Exception e) | ||||
|         { | ||||
|             e.printStackTrace(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 获取对象的setter方法。 | ||||
|      *  | ||||
|      * @param obj 对象 | ||||
|      * @return 对象的setter方法列表 | ||||
|      */ | ||||
|     public static List<Method> getSetterMethods(Object obj) | ||||
|     { | ||||
|         // setter方法列表 | ||||
|         List<Method> setterMethods = new ArrayList<Method>(); | ||||
|  | ||||
|         // 获取所有方法 | ||||
|         Method[] methods = obj.getClass().getMethods(); | ||||
|  | ||||
|         // 查找setter方法 | ||||
|  | ||||
|         for (Method method : methods) | ||||
|         { | ||||
|             Matcher m = SET_PATTERN.matcher(method.getName()); | ||||
|             if (m.matches() && (method.getParameterTypes().length == 1)) | ||||
|             { | ||||
|                 setterMethods.add(method); | ||||
|             } | ||||
|         } | ||||
|         // 返回setter方法列表 | ||||
|         return setterMethods; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 获取对象的getter方法。 | ||||
|      *  | ||||
|      * @param obj 对象 | ||||
|      * @return 对象的getter方法列表 | ||||
|      */ | ||||
|  | ||||
|     public static List<Method> getGetterMethods(Object obj) | ||||
|     { | ||||
|         // getter方法列表 | ||||
|         List<Method> getterMethods = new ArrayList<Method>(); | ||||
|         // 获取所有方法 | ||||
|         Method[] methods = obj.getClass().getMethods(); | ||||
|         // 查找getter方法 | ||||
|         for (Method method : methods) | ||||
|         { | ||||
|             Matcher m = GET_PATTERN.matcher(method.getName()); | ||||
|             if (m.matches() && (method.getParameterTypes().length == 0)) | ||||
|             { | ||||
|                 getterMethods.add(method); | ||||
|             } | ||||
|         } | ||||
|         // 返回getter方法列表 | ||||
|         return getterMethods; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 检查Bean方法名中的属性名是否相等。<br> | ||||
|      * 如getName()和setName()属性名一样,getName()和setAge()属性名不一样。 | ||||
|      *  | ||||
|      * @param m1 方法名1 | ||||
|      * @param m2 方法名2 | ||||
|      * @return 属性名一样返回true,否则返回false | ||||
|      */ | ||||
|  | ||||
|     public static boolean isMethodPropEquals(String m1, String m2) | ||||
|     { | ||||
|         return m1.substring(BEAN_METHOD_PROP_INDEX).equals(m2.substring(BEAN_METHOD_PROP_INDEX)); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,231 @@ | ||||
| package com.stdiet.common.utils.file; | ||||
|  | ||||
| import java.io.File; | ||||
| import java.io.IOException; | ||||
| import org.apache.commons.io.FilenameUtils; | ||||
| import org.springframework.web.multipart.MultipartFile; | ||||
| import com.stdiet.common.config.RuoYiConfig; | ||||
| import com.stdiet.common.constant.Constants; | ||||
| import com.stdiet.common.exception.file.FileNameLengthLimitExceededException; | ||||
| import com.stdiet.common.exception.file.FileSizeLimitExceededException; | ||||
| import com.stdiet.common.exception.file.InvalidExtensionException; | ||||
| import com.stdiet.common.utils.DateUtils; | ||||
| import com.stdiet.common.utils.StringUtils; | ||||
| import com.stdiet.common.utils.uuid.IdUtils; | ||||
|  | ||||
| /** | ||||
|  * 文件上传工具类 | ||||
|  * | ||||
|  * @author stdiet | ||||
|  */ | ||||
| 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); | ||||
|         file.transferTo(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() + "/" + IdUtils.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.getParentFile().exists()) | ||||
|         { | ||||
|             desc.getParentFile().mkdirs(); | ||||
|         } | ||||
|         if (!desc.exists()) | ||||
|         { | ||||
|             desc.createNewFile(); | ||||
|         } | ||||
|         return desc; | ||||
|     } | ||||
|  | ||||
|     private static final String getPathFileName(String uploadDir, String fileName) throws IOException | ||||
|     { | ||||
|         int dirLastIndex = RuoYiConfig.getProfile().length() + 1; | ||||
|         String currentDir = StringUtils.substring(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 | ||||
|             { | ||||
|                 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 (StringUtils.isEmpty(extension)) | ||||
|         { | ||||
|             extension = MimeTypeUtils.getExtension(file.getContentType()); | ||||
|         } | ||||
|         return extension; | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,142 @@ | ||||
| package com.stdiet.common.utils.file; | ||||
|  | ||||
| import java.io.File; | ||||
| import java.io.FileInputStream; | ||||
| import java.io.FileNotFoundException; | ||||
| import java.io.IOException; | ||||
| import java.io.OutputStream; | ||||
| import java.io.UnsupportedEncodingException; | ||||
| import java.net.URLEncoder; | ||||
| import javax.servlet.http.HttpServletRequest; | ||||
|  | ||||
| /** | ||||
|  * 文件处理工具类 | ||||
|  *  | ||||
|  * @author stdiet | ||||
|  */ | ||||
| public class FileUtils extends org.apache.commons.io.FileUtils | ||||
| { | ||||
|     public static String FILENAME_PATTERN = "[a-zA-Z0-9_\\-\\|\\.\\u4e00-\\u9fa5]+"; | ||||
|  | ||||
|     /** | ||||
|      * 输出指定文件的byte数组 | ||||
|      *  | ||||
|      * @param filePath 文件路径 | ||||
|      * @param os 输出流 | ||||
|      * @return | ||||
|      */ | ||||
|     public static void writeBytes(String filePath, OutputStream os) throws IOException | ||||
|     { | ||||
|         FileInputStream fis = null; | ||||
|         try | ||||
|         { | ||||
|             File file = new File(filePath); | ||||
|             if (!file.exists()) | ||||
|             { | ||||
|                 throw new FileNotFoundException(filePath); | ||||
|             } | ||||
|             fis = new FileInputStream(file); | ||||
|             byte[] b = new byte[1024]; | ||||
|             int length; | ||||
|             while ((length = fis.read(b)) > 0) | ||||
|             { | ||||
|                 os.write(b, 0, length); | ||||
|             } | ||||
|         } | ||||
|         catch (IOException e) | ||||
|         { | ||||
|             throw e; | ||||
|         } | ||||
|         finally | ||||
|         { | ||||
|             if (os != null) | ||||
|             { | ||||
|                 try | ||||
|                 { | ||||
|                     os.close(); | ||||
|                 } | ||||
|                 catch (IOException e1) | ||||
|                 { | ||||
|                     e1.printStackTrace(); | ||||
|                 } | ||||
|             } | ||||
|             if (fis != null) | ||||
|             { | ||||
|                 try | ||||
|                 { | ||||
|                     fis.close(); | ||||
|                 } | ||||
|                 catch (IOException e1) | ||||
|                 { | ||||
|                     e1.printStackTrace(); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 删除文件 | ||||
|      *  | ||||
|      * @param filePath 文件 | ||||
|      * @return | ||||
|      */ | ||||
|     public static boolean deleteFile(String filePath) | ||||
|     { | ||||
|         boolean flag = false; | ||||
|         File file = new File(filePath); | ||||
|         // 路径为文件且不为空则进行删除 | ||||
|         if (file.isFile() && file.exists()) | ||||
|         { | ||||
|             file.delete(); | ||||
|             flag = true; | ||||
|         } | ||||
|         return flag; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 文件名称验证 | ||||
|      *  | ||||
|      * @param filename 文件名称 | ||||
|      * @return true 正常 false 非法 | ||||
|      */ | ||||
|     public static boolean isValidFilename(String filename) | ||||
|     { | ||||
|         return filename.matches(FILENAME_PATTERN); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 下载文件名重新编码 | ||||
|      *  | ||||
|      * @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, "utf-8"); | ||||
|             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, "utf-8"); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             // 其它浏览器 | ||||
|             filename = URLEncoder.encode(filename, "utf-8"); | ||||
|         } | ||||
|         return filename; | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,55 @@ | ||||
| package com.stdiet.common.utils.file; | ||||
|  | ||||
| /** | ||||
|  * 媒体类型工具类 | ||||
|  *  | ||||
|  * @author stdiet | ||||
|  */ | ||||
| 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[] DEFAULT_ALLOWED_EXTENSION = { | ||||
|             // 图片 | ||||
|             "bmp", "gif", "jpg", "jpeg", "png", | ||||
|             // word excel powerpoint | ||||
|             "doc", "docx", "xls", "xlsx", "ppt", "pptx", "html", "htm", "txt", | ||||
|             // 压缩文件 | ||||
|             "rar", "zip", "gz", "bz2", | ||||
|             // 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 ""; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,155 @@ | ||||
| package com.stdiet.common.utils.html; | ||||
|  | ||||
| import com.stdiet.common.utils.StringUtils; | ||||
|  | ||||
| /** | ||||
|  * 转义和反转义工具类 | ||||
|  *  | ||||
|  * @author ruoyi | ||||
|  */ | ||||
| public class EscapeUtil | ||||
| { | ||||
|     public static final String RE_HTML_MARK = "(<[^<]*?>)|(<[\\s]*?/[^<]*?>)|(<[^<]*?/[\\s]*?>)"; | ||||
|  | ||||
|     private static final char[][] TEXT = new char[64][]; | ||||
|  | ||||
|     static | ||||
|     { | ||||
|         for (int i = 0; i < 64; i++) | ||||
|         { | ||||
|             TEXT[i] = new char[] { (char) i }; | ||||
|         } | ||||
|  | ||||
|         // special HTML characters | ||||
|         TEXT['\''] = "'".toCharArray(); // 单引号 | ||||
|         TEXT['"'] = """.toCharArray(); // 单引号 | ||||
|         TEXT['&'] = "&".toCharArray(); // &符 | ||||
|         TEXT['<'] = "<".toCharArray(); // 小于号 | ||||
|         TEXT['>'] = ">".toCharArray(); // 大于号 | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 转义文本中的HTML字符为安全的字符 | ||||
|      *  | ||||
|      * @param text 被转义的文本 | ||||
|      * @return 转义后的文本 | ||||
|      */ | ||||
|     public static String escape(String text) | ||||
|     { | ||||
|         return encode(text); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 还原被转义的HTML特殊字符 | ||||
|      *  | ||||
|      * @param content 包含转义符的HTML内容 | ||||
|      * @return 转换后的字符串 | ||||
|      */ | ||||
|     public static String unescape(String content) | ||||
|     { | ||||
|         return decode(content); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 清除所有HTML标签,但是不删除标签内的内容 | ||||
|      *  | ||||
|      * @param content 文本 | ||||
|      * @return 清除标签后的文本 | ||||
|      */ | ||||
|     public static String clean(String content) | ||||
|     { | ||||
|         return new HTMLFilter().filter(content); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Escape编码 | ||||
|      *  | ||||
|      * @param text 被编码的文本 | ||||
|      * @return 编码后的字符 | ||||
|      */ | ||||
|     private static String encode(String text) | ||||
|     { | ||||
|         int len; | ||||
|         if ((text == null) || ((len = text.length()) == 0)) | ||||
|         { | ||||
|             return StringUtils.EMPTY; | ||||
|         } | ||||
|         StringBuilder buffer = new StringBuilder(len + (len >> 2)); | ||||
|         char c; | ||||
|         for (int i = 0; i < len; i++) | ||||
|         { | ||||
|             c = text.charAt(i); | ||||
|             if (c < 64) | ||||
|             { | ||||
|                 buffer.append(TEXT[c]); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 buffer.append(c); | ||||
|             } | ||||
|         } | ||||
|         return buffer.toString(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Escape解码 | ||||
|      *  | ||||
|      * @param content 被转义的内容 | ||||
|      * @return 解码后的字符串 | ||||
|      */ | ||||
|     public static String decode(String content) | ||||
|     { | ||||
|         if (StringUtils.isEmpty(content)) | ||||
|         { | ||||
|             return content; | ||||
|         } | ||||
|  | ||||
|         StringBuilder tmp = new StringBuilder(content.length()); | ||||
|         int lastPos = 0, pos = 0; | ||||
|         char ch; | ||||
|         while (lastPos < content.length()) | ||||
|         { | ||||
|             pos = content.indexOf("%", lastPos); | ||||
|             if (pos == lastPos) | ||||
|             { | ||||
|                 if (content.charAt(pos + 1) == 'u') | ||||
|                 { | ||||
|                     ch = (char) Integer.parseInt(content.substring(pos + 2, pos + 6), 16); | ||||
|                     tmp.append(ch); | ||||
|                     lastPos = pos + 6; | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     ch = (char) Integer.parseInt(content.substring(pos + 1, pos + 3), 16); | ||||
|                     tmp.append(ch); | ||||
|                     lastPos = pos + 3; | ||||
|                 } | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 if (pos == -1) | ||||
|                 { | ||||
|                     tmp.append(content.substring(lastPos)); | ||||
|                     lastPos = content.length(); | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     tmp.append(content.substring(lastPos, pos)); | ||||
|                     lastPos = pos; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         return tmp.toString(); | ||||
|     } | ||||
|  | ||||
|     public static void main(String[] args) | ||||
|     { | ||||
|         String html = "<script>alert(1);</script>"; | ||||
|         // String html = "<scr<script>ipt>alert(\"XSS\")</scr<script>ipt>"; | ||||
|         // String html = "<123"; | ||||
|         // String html = "123>"; | ||||
|         System.out.println(EscapeUtil.clean(html)); | ||||
|         System.out.println(EscapeUtil.escape(html)); | ||||
|         System.out.println(EscapeUtil.unescape(html)); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,570 @@ | ||||
| package com.stdiet.common.utils.html; | ||||
|  | ||||
| import java.util.ArrayList; | ||||
| import java.util.Collections; | ||||
| import java.util.HashMap; | ||||
| import java.util.List; | ||||
| import java.util.Map; | ||||
| import java.util.concurrent.ConcurrentHashMap; | ||||
| import java.util.concurrent.ConcurrentMap; | ||||
| import java.util.regex.Matcher; | ||||
| import java.util.regex.Pattern; | ||||
|  | ||||
| /** | ||||
|  * HTML过滤器,用于去除XSS漏洞隐患。 | ||||
|  * | ||||
|  * @author ruoyi | ||||
|  */ | ||||
| public final class HTMLFilter | ||||
| { | ||||
|     /** | ||||
|      * regex flag union representing /si modifiers in php | ||||
|      **/ | ||||
|     private static final int REGEX_FLAGS_SI = Pattern.CASE_INSENSITIVE | Pattern.DOTALL; | ||||
|     private static final Pattern P_COMMENTS = Pattern.compile("<!--(.*?)-->", Pattern.DOTALL); | ||||
|     private static final Pattern P_COMMENT = Pattern.compile("^!--(.*)--$", REGEX_FLAGS_SI); | ||||
|     private static final Pattern P_TAGS = Pattern.compile("<(.*?)>", Pattern.DOTALL); | ||||
|     private static final Pattern P_END_TAG = Pattern.compile("^/([a-z0-9]+)", REGEX_FLAGS_SI); | ||||
|     private static final Pattern P_START_TAG = Pattern.compile("^([a-z0-9]+)(.*?)(/?)$", REGEX_FLAGS_SI); | ||||
|     private static final Pattern P_QUOTED_ATTRIBUTES = Pattern.compile("([a-z0-9]+)=([\"'])(.*?)\\2", REGEX_FLAGS_SI); | ||||
|     private static final Pattern P_UNQUOTED_ATTRIBUTES = Pattern.compile("([a-z0-9]+)(=)([^\"\\s']+)", REGEX_FLAGS_SI); | ||||
|     private static final Pattern P_PROTOCOL = Pattern.compile("^([^:]+):", REGEX_FLAGS_SI); | ||||
|     private static final Pattern P_ENTITY = Pattern.compile("&#(\\d+);?"); | ||||
|     private static final Pattern P_ENTITY_UNICODE = Pattern.compile("&#x([0-9a-f]+);?"); | ||||
|     private static final Pattern P_ENCODE = Pattern.compile("%([0-9a-f]{2});?"); | ||||
|     private static final Pattern P_VALID_ENTITIES = Pattern.compile("&([^&;]*)(?=(;|&|$))"); | ||||
|     private static final Pattern P_VALID_QUOTES = Pattern.compile("(>|^)([^<]+?)(<|$)", Pattern.DOTALL); | ||||
|     private static final Pattern P_END_ARROW = Pattern.compile("^>"); | ||||
|     private static final Pattern P_BODY_TO_END = Pattern.compile("<([^>]*?)(?=<|$)"); | ||||
|     private static final Pattern P_XML_CONTENT = Pattern.compile("(^|>)([^<]*?)(?=>)"); | ||||
|     private static final Pattern P_STRAY_LEFT_ARROW = Pattern.compile("<([^>]*?)(?=<|$)"); | ||||
|     private static final Pattern P_STRAY_RIGHT_ARROW = Pattern.compile("(^|>)([^<]*?)(?=>)"); | ||||
|     private static final Pattern P_AMP = Pattern.compile("&"); | ||||
|     private static final Pattern P_QUOTE = Pattern.compile("\""); | ||||
|     private static final Pattern P_LEFT_ARROW = Pattern.compile("<"); | ||||
|     private static final Pattern P_RIGHT_ARROW = Pattern.compile(">"); | ||||
|     private static final Pattern P_BOTH_ARROWS = Pattern.compile("<>"); | ||||
|  | ||||
|     // @xxx could grow large... maybe use sesat's ReferenceMap | ||||
|     private static final ConcurrentMap<String, Pattern> P_REMOVE_PAIR_BLANKS = new ConcurrentHashMap<>(); | ||||
|     private static final ConcurrentMap<String, Pattern> P_REMOVE_SELF_BLANKS = new ConcurrentHashMap<>(); | ||||
|  | ||||
|     /** | ||||
|      * set of allowed html elements, along with allowed attributes for each element | ||||
|      **/ | ||||
|     private final Map<String, List<String>> vAllowed; | ||||
|     /** | ||||
|      * counts of open tags for each (allowable) html element | ||||
|      **/ | ||||
|     private final Map<String, Integer> vTagCounts = new HashMap<>(); | ||||
|  | ||||
|     /** | ||||
|      * html elements which must always be self-closing (e.g. "<img />") | ||||
|      **/ | ||||
|     private final String[] vSelfClosingTags; | ||||
|     /** | ||||
|      * html elements which must always have separate opening and closing tags (e.g. "<b></b>") | ||||
|      **/ | ||||
|     private final String[] vNeedClosingTags; | ||||
|     /** | ||||
|      * set of disallowed html elements | ||||
|      **/ | ||||
|     private final String[] vDisallowed; | ||||
|     /** | ||||
|      * attributes which should be checked for valid protocols | ||||
|      **/ | ||||
|     private final String[] vProtocolAtts; | ||||
|     /** | ||||
|      * allowed protocols | ||||
|      **/ | ||||
|     private final String[] vAllowedProtocols; | ||||
|     /** | ||||
|      * tags which should be removed if they contain no content (e.g. "<b></b>" or "<b />") | ||||
|      **/ | ||||
|     private final String[] vRemoveBlanks; | ||||
|     /** | ||||
|      * entities allowed within html markup | ||||
|      **/ | ||||
|     private final String[] vAllowedEntities; | ||||
|     /** | ||||
|      * flag determining whether comments are allowed in input String. | ||||
|      */ | ||||
|     private final boolean stripComment; | ||||
|     private final boolean encodeQuotes; | ||||
|     /** | ||||
|      * flag determining whether to try to make tags when presented with "unbalanced" angle brackets (e.g. "<b text </b>" | ||||
|      * becomes "<b> text </b>"). If set to false, unbalanced angle brackets will be html escaped. | ||||
|      */ | ||||
|     private final boolean alwaysMakeTags; | ||||
|  | ||||
|     /** | ||||
|      * Default constructor. | ||||
|      */ | ||||
|     public HTMLFilter() | ||||
|     { | ||||
|         vAllowed = new HashMap<>(); | ||||
|  | ||||
|         final ArrayList<String> a_atts = new ArrayList<>(); | ||||
|         a_atts.add("href"); | ||||
|         a_atts.add("target"); | ||||
|         vAllowed.put("a", a_atts); | ||||
|  | ||||
|         final ArrayList<String> img_atts = new ArrayList<>(); | ||||
|         img_atts.add("src"); | ||||
|         img_atts.add("width"); | ||||
|         img_atts.add("height"); | ||||
|         img_atts.add("alt"); | ||||
|         vAllowed.put("img", img_atts); | ||||
|  | ||||
|         final ArrayList<String> no_atts = new ArrayList<>(); | ||||
|         vAllowed.put("b", no_atts); | ||||
|         vAllowed.put("strong", no_atts); | ||||
|         vAllowed.put("i", no_atts); | ||||
|         vAllowed.put("em", no_atts); | ||||
|  | ||||
|         vSelfClosingTags = new String[] { "img" }; | ||||
|         vNeedClosingTags = new String[] { "a", "b", "strong", "i", "em" }; | ||||
|         vDisallowed = new String[] {}; | ||||
|         vAllowedProtocols = new String[] { "http", "mailto", "https" }; // no ftp. | ||||
|         vProtocolAtts = new String[] { "src", "href" }; | ||||
|         vRemoveBlanks = new String[] { "a", "b", "strong", "i", "em" }; | ||||
|         vAllowedEntities = new String[] { "amp", "gt", "lt", "quot" }; | ||||
|         stripComment = true; | ||||
|         encodeQuotes = true; | ||||
|         alwaysMakeTags = false; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Map-parameter configurable constructor. | ||||
|      * | ||||
|      * @param conf map containing configuration. keys match field names. | ||||
|      */ | ||||
|     @SuppressWarnings("unchecked") | ||||
|     public HTMLFilter(final Map<String, Object> conf) | ||||
|     { | ||||
|  | ||||
|         assert conf.containsKey("vAllowed") : "configuration requires vAllowed"; | ||||
|         assert conf.containsKey("vSelfClosingTags") : "configuration requires vSelfClosingTags"; | ||||
|         assert conf.containsKey("vNeedClosingTags") : "configuration requires vNeedClosingTags"; | ||||
|         assert conf.containsKey("vDisallowed") : "configuration requires vDisallowed"; | ||||
|         assert conf.containsKey("vAllowedProtocols") : "configuration requires vAllowedProtocols"; | ||||
|         assert conf.containsKey("vProtocolAtts") : "configuration requires vProtocolAtts"; | ||||
|         assert conf.containsKey("vRemoveBlanks") : "configuration requires vRemoveBlanks"; | ||||
|         assert conf.containsKey("vAllowedEntities") : "configuration requires vAllowedEntities"; | ||||
|  | ||||
|         vAllowed = Collections.unmodifiableMap((HashMap<String, List<String>>) conf.get("vAllowed")); | ||||
|         vSelfClosingTags = (String[]) conf.get("vSelfClosingTags"); | ||||
|         vNeedClosingTags = (String[]) conf.get("vNeedClosingTags"); | ||||
|         vDisallowed = (String[]) conf.get("vDisallowed"); | ||||
|         vAllowedProtocols = (String[]) conf.get("vAllowedProtocols"); | ||||
|         vProtocolAtts = (String[]) conf.get("vProtocolAtts"); | ||||
|         vRemoveBlanks = (String[]) conf.get("vRemoveBlanks"); | ||||
|         vAllowedEntities = (String[]) conf.get("vAllowedEntities"); | ||||
|         stripComment = conf.containsKey("stripComment") ? (Boolean) conf.get("stripComment") : true; | ||||
|         encodeQuotes = conf.containsKey("encodeQuotes") ? (Boolean) conf.get("encodeQuotes") : true; | ||||
|         alwaysMakeTags = conf.containsKey("alwaysMakeTags") ? (Boolean) conf.get("alwaysMakeTags") : true; | ||||
|     } | ||||
|  | ||||
|     private void reset() | ||||
|     { | ||||
|         vTagCounts.clear(); | ||||
|     } | ||||
|  | ||||
|     // --------------------------------------------------------------- | ||||
|     // my versions of some PHP library functions | ||||
|     public static String chr(final int decimal) | ||||
|     { | ||||
|         return String.valueOf((char) decimal); | ||||
|     } | ||||
|  | ||||
|     public static String htmlSpecialChars(final String s) | ||||
|     { | ||||
|         String result = s; | ||||
|         result = regexReplace(P_AMP, "&", result); | ||||
|         result = regexReplace(P_QUOTE, """, result); | ||||
|         result = regexReplace(P_LEFT_ARROW, "<", result); | ||||
|         result = regexReplace(P_RIGHT_ARROW, ">", result); | ||||
|         return result; | ||||
|     } | ||||
|  | ||||
|     // --------------------------------------------------------------- | ||||
|  | ||||
|     /** | ||||
|      * given a user submitted input String, filter out any invalid or restricted html. | ||||
|      * | ||||
|      * @param input text (i.e. submitted by a user) than may contain html | ||||
|      * @return "clean" version of input, with only valid, whitelisted html elements allowed | ||||
|      */ | ||||
|     public String filter(final String input) | ||||
|     { | ||||
|         reset(); | ||||
|         String s = input; | ||||
|  | ||||
|         s = escapeComments(s); | ||||
|  | ||||
|         s = balanceHTML(s); | ||||
|  | ||||
|         s = checkTags(s); | ||||
|  | ||||
|         s = processRemoveBlanks(s); | ||||
|  | ||||
|         // s = validateEntities(s); | ||||
|  | ||||
|         return s; | ||||
|     } | ||||
|  | ||||
|     public boolean isAlwaysMakeTags() | ||||
|     { | ||||
|         return alwaysMakeTags; | ||||
|     } | ||||
|  | ||||
|     public boolean isStripComments() | ||||
|     { | ||||
|         return stripComment; | ||||
|     } | ||||
|  | ||||
|     private String escapeComments(final String s) | ||||
|     { | ||||
|         final Matcher m = P_COMMENTS.matcher(s); | ||||
|         final StringBuffer buf = new StringBuffer(); | ||||
|         if (m.find()) | ||||
|         { | ||||
|             final String match = m.group(1); // (.*?) | ||||
|             m.appendReplacement(buf, Matcher.quoteReplacement("<!--" + htmlSpecialChars(match) + "-->")); | ||||
|         } | ||||
|         m.appendTail(buf); | ||||
|  | ||||
|         return buf.toString(); | ||||
|     } | ||||
|  | ||||
|     private String balanceHTML(String s) | ||||
|     { | ||||
|         if (alwaysMakeTags) | ||||
|         { | ||||
|             // | ||||
|             // try and form html | ||||
|             // | ||||
|             s = regexReplace(P_END_ARROW, "", s); | ||||
|             // 不追加结束标签 | ||||
|             s = regexReplace(P_BODY_TO_END, "<$1>", s); | ||||
|             s = regexReplace(P_XML_CONTENT, "$1<$2", s); | ||||
|  | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             // | ||||
|             // escape stray brackets | ||||
|             // | ||||
|             s = regexReplace(P_STRAY_LEFT_ARROW, "<$1", s); | ||||
|             s = regexReplace(P_STRAY_RIGHT_ARROW, "$1$2><", s); | ||||
|  | ||||
|             // | ||||
|             // the last regexp causes '<>' entities to appear | ||||
|             // (we need to do a lookahead assertion so that the last bracket can | ||||
|             // be used in the next pass of the regexp) | ||||
|             // | ||||
|             s = regexReplace(P_BOTH_ARROWS, "", s); | ||||
|         } | ||||
|  | ||||
|         return s; | ||||
|     } | ||||
|  | ||||
|     private String checkTags(String s) | ||||
|     { | ||||
|         Matcher m = P_TAGS.matcher(s); | ||||
|  | ||||
|         final StringBuffer buf = new StringBuffer(); | ||||
|         while (m.find()) | ||||
|         { | ||||
|             String replaceStr = m.group(1); | ||||
|             replaceStr = processTag(replaceStr); | ||||
|             m.appendReplacement(buf, Matcher.quoteReplacement(replaceStr)); | ||||
|         } | ||||
|         m.appendTail(buf); | ||||
|  | ||||
|         // these get tallied in processTag | ||||
|         // (remember to reset before subsequent calls to filter method) | ||||
|         final StringBuilder sBuilder = new StringBuilder(buf.toString()); | ||||
|         for (String key : vTagCounts.keySet()) | ||||
|         { | ||||
|             for (int ii = 0; ii < vTagCounts.get(key); ii++) | ||||
|             { | ||||
|                 sBuilder.append("</").append(key).append(">"); | ||||
|             } | ||||
|         } | ||||
|         s = sBuilder.toString(); | ||||
|  | ||||
|         return s; | ||||
|     } | ||||
|  | ||||
|     private String processRemoveBlanks(final String s) | ||||
|     { | ||||
|         String result = s; | ||||
|         for (String tag : vRemoveBlanks) | ||||
|         { | ||||
|             if (!P_REMOVE_PAIR_BLANKS.containsKey(tag)) | ||||
|             { | ||||
|                 P_REMOVE_PAIR_BLANKS.putIfAbsent(tag, Pattern.compile("<" + tag + "(\\s[^>]*)?></" + tag + ">")); | ||||
|             } | ||||
|             result = regexReplace(P_REMOVE_PAIR_BLANKS.get(tag), "", result); | ||||
|             if (!P_REMOVE_SELF_BLANKS.containsKey(tag)) | ||||
|             { | ||||
|                 P_REMOVE_SELF_BLANKS.putIfAbsent(tag, Pattern.compile("<" + tag + "(\\s[^>]*)?/>")); | ||||
|             } | ||||
|             result = regexReplace(P_REMOVE_SELF_BLANKS.get(tag), "", result); | ||||
|         } | ||||
|  | ||||
|         return result; | ||||
|     } | ||||
|  | ||||
|     private static String regexReplace(final Pattern regex_pattern, final String replacement, final String s) | ||||
|     { | ||||
|         Matcher m = regex_pattern.matcher(s); | ||||
|         return m.replaceAll(replacement); | ||||
|     } | ||||
|  | ||||
|     private String processTag(final String s) | ||||
|     { | ||||
|         // ending tags | ||||
|         Matcher m = P_END_TAG.matcher(s); | ||||
|         if (m.find()) | ||||
|         { | ||||
|             final String name = m.group(1).toLowerCase(); | ||||
|             if (allowed(name)) | ||||
|             { | ||||
|                 if (false == inArray(name, vSelfClosingTags)) | ||||
|                 { | ||||
|                     if (vTagCounts.containsKey(name)) | ||||
|                     { | ||||
|                         vTagCounts.put(name, vTagCounts.get(name) - 1); | ||||
|                         return "</" + name + ">"; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         // starting tags | ||||
|         m = P_START_TAG.matcher(s); | ||||
|         if (m.find()) | ||||
|         { | ||||
|             final String name = m.group(1).toLowerCase(); | ||||
|             final String body = m.group(2); | ||||
|             String ending = m.group(3); | ||||
|  | ||||
|             // debug( "in a starting tag, name='" + name + "'; body='" + body + "'; ending='" + ending + "'" ); | ||||
|             if (allowed(name)) | ||||
|             { | ||||
|                 final StringBuilder params = new StringBuilder(); | ||||
|  | ||||
|                 final Matcher m2 = P_QUOTED_ATTRIBUTES.matcher(body); | ||||
|                 final Matcher m3 = P_UNQUOTED_ATTRIBUTES.matcher(body); | ||||
|                 final List<String> paramNames = new ArrayList<>(); | ||||
|                 final List<String> paramValues = new ArrayList<>(); | ||||
|                 while (m2.find()) | ||||
|                 { | ||||
|                     paramNames.add(m2.group(1)); // ([a-z0-9]+) | ||||
|                     paramValues.add(m2.group(3)); // (.*?) | ||||
|                 } | ||||
|                 while (m3.find()) | ||||
|                 { | ||||
|                     paramNames.add(m3.group(1)); // ([a-z0-9]+) | ||||
|                     paramValues.add(m3.group(3)); // ([^\"\\s']+) | ||||
|                 } | ||||
|  | ||||
|                 String paramName, paramValue; | ||||
|                 for (int ii = 0; ii < paramNames.size(); ii++) | ||||
|                 { | ||||
|                     paramName = paramNames.get(ii).toLowerCase(); | ||||
|                     paramValue = paramValues.get(ii); | ||||
|  | ||||
|                     // debug( "paramName='" + paramName + "'" ); | ||||
|                     // debug( "paramValue='" + paramValue + "'" ); | ||||
|                     // debug( "allowed? " + vAllowed.get( name ).contains( paramName ) ); | ||||
|  | ||||
|                     if (allowedAttribute(name, paramName)) | ||||
|                     { | ||||
|                         if (inArray(paramName, vProtocolAtts)) | ||||
|                         { | ||||
|                             paramValue = processParamProtocol(paramValue); | ||||
|                         } | ||||
|                         params.append(' ').append(paramName).append("=\"").append(paramValue).append("\""); | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 if (inArray(name, vSelfClosingTags)) | ||||
|                 { | ||||
|                     ending = " /"; | ||||
|                 } | ||||
|  | ||||
|                 if (inArray(name, vNeedClosingTags)) | ||||
|                 { | ||||
|                     ending = ""; | ||||
|                 } | ||||
|  | ||||
|                 if (ending == null || ending.length() < 1) | ||||
|                 { | ||||
|                     if (vTagCounts.containsKey(name)) | ||||
|                     { | ||||
|                         vTagCounts.put(name, vTagCounts.get(name) + 1); | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|                         vTagCounts.put(name, 1); | ||||
|                     } | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     ending = " /"; | ||||
|                 } | ||||
|                 return "<" + name + params + ending + ">"; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 return ""; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         // comments | ||||
|         m = P_COMMENT.matcher(s); | ||||
|         if (!stripComment && m.find()) | ||||
|         { | ||||
|             return "<" + m.group() + ">"; | ||||
|         } | ||||
|  | ||||
|         return ""; | ||||
|     } | ||||
|  | ||||
|     private String processParamProtocol(String s) | ||||
|     { | ||||
|         s = decodeEntities(s); | ||||
|         final Matcher m = P_PROTOCOL.matcher(s); | ||||
|         if (m.find()) | ||||
|         { | ||||
|             final String protocol = m.group(1); | ||||
|             if (!inArray(protocol, vAllowedProtocols)) | ||||
|             { | ||||
|                 // bad protocol, turn into local anchor link instead | ||||
|                 s = "#" + s.substring(protocol.length() + 1); | ||||
|                 if (s.startsWith("#//")) | ||||
|                 { | ||||
|                     s = "#" + s.substring(3); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return s; | ||||
|     } | ||||
|  | ||||
|     private String decodeEntities(String s) | ||||
|     { | ||||
|         StringBuffer buf = new StringBuffer(); | ||||
|  | ||||
|         Matcher m = P_ENTITY.matcher(s); | ||||
|         while (m.find()) | ||||
|         { | ||||
|             final String match = m.group(1); | ||||
|             final int decimal = Integer.decode(match).intValue(); | ||||
|             m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal))); | ||||
|         } | ||||
|         m.appendTail(buf); | ||||
|         s = buf.toString(); | ||||
|  | ||||
|         buf = new StringBuffer(); | ||||
|         m = P_ENTITY_UNICODE.matcher(s); | ||||
|         while (m.find()) | ||||
|         { | ||||
|             final String match = m.group(1); | ||||
|             final int decimal = Integer.valueOf(match, 16).intValue(); | ||||
|             m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal))); | ||||
|         } | ||||
|         m.appendTail(buf); | ||||
|         s = buf.toString(); | ||||
|  | ||||
|         buf = new StringBuffer(); | ||||
|         m = P_ENCODE.matcher(s); | ||||
|         while (m.find()) | ||||
|         { | ||||
|             final String match = m.group(1); | ||||
|             final int decimal = Integer.valueOf(match, 16).intValue(); | ||||
|             m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal))); | ||||
|         } | ||||
|         m.appendTail(buf); | ||||
|         s = buf.toString(); | ||||
|  | ||||
|         s = validateEntities(s); | ||||
|         return s; | ||||
|     } | ||||
|  | ||||
|     private String validateEntities(final String s) | ||||
|     { | ||||
|         StringBuffer buf = new StringBuffer(); | ||||
|  | ||||
|         // validate entities throughout the string | ||||
|         Matcher m = P_VALID_ENTITIES.matcher(s); | ||||
|         while (m.find()) | ||||
|         { | ||||
|             final String one = m.group(1); // ([^&;]*) | ||||
|             final String two = m.group(2); // (?=(;|&|$)) | ||||
|             m.appendReplacement(buf, Matcher.quoteReplacement(checkEntity(one, two))); | ||||
|         } | ||||
|         m.appendTail(buf); | ||||
|  | ||||
|         return encodeQuotes(buf.toString()); | ||||
|     } | ||||
|  | ||||
|     private String encodeQuotes(final String s) | ||||
|     { | ||||
|         if (encodeQuotes) | ||||
|         { | ||||
|             StringBuffer buf = new StringBuffer(); | ||||
|             Matcher m = P_VALID_QUOTES.matcher(s); | ||||
|             while (m.find()) | ||||
|             { | ||||
|                 final String one = m.group(1); // (>|^) | ||||
|                 final String two = m.group(2); // ([^<]+?) | ||||
|                 final String three = m.group(3); // (<|$) | ||||
|                 // 不替换双引号为",防止json格式无效 regexReplace(P_QUOTE, """, two) | ||||
|                 m.appendReplacement(buf, Matcher.quoteReplacement(one + two + three)); | ||||
|             } | ||||
|             m.appendTail(buf); | ||||
|             return buf.toString(); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             return s; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private String checkEntity(final String preamble, final String term) | ||||
|     { | ||||
|  | ||||
|         return ";".equals(term) && isValidEntity(preamble) ? '&' + preamble : "&" + preamble; | ||||
|     } | ||||
|  | ||||
|     private boolean isValidEntity(final String entity) | ||||
|     { | ||||
|         return inArray(entity, vAllowedEntities); | ||||
|     } | ||||
|  | ||||
|     private static boolean inArray(final String s, final String[] array) | ||||
|     { | ||||
|         for (String item : array) | ||||
|         { | ||||
|             if (item != null && item.equals(s)) | ||||
|             { | ||||
|                 return true; | ||||
|             } | ||||
|         } | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     private boolean allowed(final String name) | ||||
|     { | ||||
|         return (vAllowed.isEmpty() || vAllowed.containsKey(name)) && !inArray(name, vDisallowed); | ||||
|     } | ||||
|  | ||||
|     private boolean allowedAttribute(final String name, final String paramName) | ||||
|     { | ||||
|         return allowed(name) && (vAllowed.isEmpty() || vAllowed.get(name).contains(paramName)); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,55 @@ | ||||
| package com.stdiet.common.utils.http; | ||||
|  | ||||
| import java.io.BufferedReader; | ||||
| import java.io.IOException; | ||||
| import java.io.InputStream; | ||||
| import java.io.InputStreamReader; | ||||
| import java.nio.charset.Charset; | ||||
| import javax.servlet.ServletRequest; | ||||
| import org.apache.commons.lang3.exception.ExceptionUtils; | ||||
| import org.slf4j.Logger; | ||||
| import org.slf4j.LoggerFactory; | ||||
|  | ||||
| /** | ||||
|  * 通用http工具封装 | ||||
|  *  | ||||
|  * @author ruoyi | ||||
|  */ | ||||
| public class HttpHelper | ||||
| { | ||||
|     private static final Logger LOGGER = LoggerFactory.getLogger(HttpHelper.class); | ||||
|  | ||||
|     public static String getBodyString(ServletRequest request) | ||||
|     { | ||||
|         StringBuilder sb = new StringBuilder(); | ||||
|         BufferedReader reader = null; | ||||
|         try (InputStream inputStream = request.getInputStream()) | ||||
|         { | ||||
|             reader = new BufferedReader(new InputStreamReader(inputStream, Charset.forName("UTF-8"))); | ||||
|             String line = ""; | ||||
|             while ((line = reader.readLine()) != null) | ||||
|             { | ||||
|                 sb.append(line); | ||||
|             } | ||||
|         } | ||||
|         catch (IOException e) | ||||
|         { | ||||
|             LOGGER.warn("getBodyString出现问题!"); | ||||
|         } | ||||
|         finally | ||||
|         { | ||||
|             if (reader != null) | ||||
|             { | ||||
|                 try | ||||
|                 { | ||||
|                     reader.close(); | ||||
|                 } | ||||
|                 catch (IOException e) | ||||
|                 { | ||||
|                     LOGGER.error(ExceptionUtils.getMessage(e)); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         return sb.toString(); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,262 @@ | ||||
| package com.stdiet.common.utils.http; | ||||
|  | ||||
| import java.io.BufferedReader; | ||||
| import java.io.IOException; | ||||
| import java.io.InputStream; | ||||
| import java.io.InputStreamReader; | ||||
| import java.io.PrintWriter; | ||||
| import java.net.ConnectException; | ||||
| import java.net.SocketTimeoutException; | ||||
| import java.net.URL; | ||||
| import java.net.URLConnection; | ||||
| import java.security.cert.X509Certificate; | ||||
| import javax.net.ssl.HostnameVerifier; | ||||
| import javax.net.ssl.HttpsURLConnection; | ||||
| import javax.net.ssl.SSLContext; | ||||
| import javax.net.ssl.SSLSession; | ||||
| import javax.net.ssl.TrustManager; | ||||
| import javax.net.ssl.X509TrustManager; | ||||
| import org.slf4j.Logger; | ||||
| import org.slf4j.LoggerFactory; | ||||
| import com.stdiet.common.constant.Constants; | ||||
|  | ||||
| /** | ||||
|  * 通用http发送方法 | ||||
|  *  | ||||
|  * @author ruoyi | ||||
|  */ | ||||
| public class HttpUtils | ||||
| { | ||||
|     private static final Logger log = LoggerFactory.getLogger(HttpUtils.class); | ||||
|  | ||||
|     /** | ||||
|      * 向指定 URL 发送GET方法的请求 | ||||
|      * | ||||
|      * @param url 发送请求的 URL | ||||
|      * @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。 | ||||
|      * @return 所代表远程资源的响应结果 | ||||
|      */ | ||||
|     public static String sendGet(String url, String param) | ||||
|     { | ||||
|         return sendGet(url, param, Constants.UTF8); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 向指定 URL 发送GET方法的请求 | ||||
|      * | ||||
|      * @param url 发送请求的 URL | ||||
|      * @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。 | ||||
|      * @param contentType 编码类型 | ||||
|      * @return 所代表远程资源的响应结果 | ||||
|      */ | ||||
|     public static String sendGet(String url, String param, String contentType) | ||||
|     { | ||||
|         StringBuilder result = new StringBuilder(); | ||||
|         BufferedReader in = null; | ||||
|         try | ||||
|         { | ||||
|             String urlNameString = url + "?" + param; | ||||
|             log.info("sendGet - {}", urlNameString); | ||||
|             URL realUrl = new URL(urlNameString); | ||||
|             URLConnection connection = realUrl.openConnection(); | ||||
|             connection.setRequestProperty("accept", "*/*"); | ||||
|             connection.setRequestProperty("connection", "Keep-Alive"); | ||||
|             connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); | ||||
|             connection.connect(); | ||||
|             in = new BufferedReader(new InputStreamReader(connection.getInputStream(), contentType)); | ||||
|             String line; | ||||
|             while ((line = in.readLine()) != null) | ||||
|             { | ||||
|                 result.append(line); | ||||
|             } | ||||
|             log.info("recv - {}", result); | ||||
|         } | ||||
|         catch (ConnectException e) | ||||
|         { | ||||
|             log.error("调用HttpUtils.sendGet ConnectException, url=" + url + ",param=" + param, e); | ||||
|         } | ||||
|         catch (SocketTimeoutException e) | ||||
|         { | ||||
|             log.error("调用HttpUtils.sendGet SocketTimeoutException, url=" + url + ",param=" + param, e); | ||||
|         } | ||||
|         catch (IOException e) | ||||
|         { | ||||
|             log.error("调用HttpUtils.sendGet IOException, url=" + url + ",param=" + param, e); | ||||
|         } | ||||
|         catch (Exception e) | ||||
|         { | ||||
|             log.error("调用HttpsUtil.sendGet Exception, url=" + url + ",param=" + param, e); | ||||
|         } | ||||
|         finally | ||||
|         { | ||||
|             try | ||||
|             { | ||||
|                 if (in != null) | ||||
|                 { | ||||
|                     in.close(); | ||||
|                 } | ||||
|             } | ||||
|             catch (Exception ex) | ||||
|             { | ||||
|                 log.error("调用in.close Exception, url=" + url + ",param=" + param, ex); | ||||
|             } | ||||
|         } | ||||
|         return result.toString(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 向指定 URL 发送POST方法的请求 | ||||
|      * | ||||
|      * @param url 发送请求的 URL | ||||
|      * @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。 | ||||
|      * @return 所代表远程资源的响应结果 | ||||
|      */ | ||||
|     public static String sendPost(String url, String param) | ||||
|     { | ||||
|         PrintWriter out = null; | ||||
|         BufferedReader in = null; | ||||
|         StringBuilder result = new StringBuilder(); | ||||
|         try | ||||
|         { | ||||
|             String urlNameString = url; | ||||
|             log.info("sendPost - {}", urlNameString); | ||||
|             URL realUrl = new URL(urlNameString); | ||||
|             URLConnection conn = realUrl.openConnection(); | ||||
|             conn.setRequestProperty("accept", "*/*"); | ||||
|             conn.setRequestProperty("connection", "Keep-Alive"); | ||||
|             conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); | ||||
|             conn.setRequestProperty("Accept-Charset", "utf-8"); | ||||
|             conn.setRequestProperty("contentType", "utf-8"); | ||||
|             conn.setDoOutput(true); | ||||
|             conn.setDoInput(true); | ||||
|             out = new PrintWriter(conn.getOutputStream()); | ||||
|             out.print(param); | ||||
|             out.flush(); | ||||
|             in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "utf-8")); | ||||
|             String line; | ||||
|             while ((line = in.readLine()) != null) | ||||
|             { | ||||
|                 result.append(line); | ||||
|             } | ||||
|             log.info("recv - {}", result); | ||||
|         } | ||||
|         catch (ConnectException e) | ||||
|         { | ||||
|             log.error("调用HttpUtils.sendPost ConnectException, url=" + url + ",param=" + param, e); | ||||
|         } | ||||
|         catch (SocketTimeoutException e) | ||||
|         { | ||||
|             log.error("调用HttpUtils.sendPost SocketTimeoutException, url=" + url + ",param=" + param, e); | ||||
|         } | ||||
|         catch (IOException e) | ||||
|         { | ||||
|             log.error("调用HttpUtils.sendPost IOException, url=" + url + ",param=" + param, e); | ||||
|         } | ||||
|         catch (Exception e) | ||||
|         { | ||||
|             log.error("调用HttpsUtil.sendPost Exception, url=" + url + ",param=" + param, e); | ||||
|         } | ||||
|         finally | ||||
|         { | ||||
|             try | ||||
|             { | ||||
|                 if (out != null) | ||||
|                 { | ||||
|                     out.close(); | ||||
|                 } | ||||
|                 if (in != null) | ||||
|                 { | ||||
|                     in.close(); | ||||
|                 } | ||||
|             } | ||||
|             catch (IOException ex) | ||||
|             { | ||||
|                 log.error("调用in.close Exception, url=" + url + ",param=" + param, ex); | ||||
|             } | ||||
|         } | ||||
|         return result.toString(); | ||||
|     } | ||||
|  | ||||
|     public static String sendSSLPost(String url, String param) | ||||
|     { | ||||
|         StringBuilder result = new StringBuilder(); | ||||
|         String urlNameString = url + "?" + param; | ||||
|         try | ||||
|         { | ||||
|             log.info("sendSSLPost - {}", urlNameString); | ||||
|             SSLContext sc = SSLContext.getInstance("SSL"); | ||||
|             sc.init(null, new TrustManager[] { new TrustAnyTrustManager() }, new java.security.SecureRandom()); | ||||
|             URL console = new URL(urlNameString); | ||||
|             HttpsURLConnection conn = (HttpsURLConnection) console.openConnection(); | ||||
|             conn.setRequestProperty("accept", "*/*"); | ||||
|             conn.setRequestProperty("connection", "Keep-Alive"); | ||||
|             conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); | ||||
|             conn.setRequestProperty("Accept-Charset", "utf-8"); | ||||
|             conn.setRequestProperty("contentType", "utf-8"); | ||||
|             conn.setDoOutput(true); | ||||
|             conn.setDoInput(true); | ||||
|  | ||||
|             conn.setSSLSocketFactory(sc.getSocketFactory()); | ||||
|             conn.setHostnameVerifier(new TrustAnyHostnameVerifier()); | ||||
|             conn.connect(); | ||||
|             InputStream is = conn.getInputStream(); | ||||
|             BufferedReader br = new BufferedReader(new InputStreamReader(is)); | ||||
|             String ret = ""; | ||||
|             while ((ret = br.readLine()) != null) | ||||
|             { | ||||
|                 if (ret != null && !"".equals(ret.trim())) | ||||
|                 { | ||||
|                     result.append(new String(ret.getBytes("ISO-8859-1"), "utf-8")); | ||||
|                 } | ||||
|             } | ||||
|             log.info("recv - {}", result); | ||||
|             conn.disconnect(); | ||||
|             br.close(); | ||||
|         } | ||||
|         catch (ConnectException e) | ||||
|         { | ||||
|             log.error("调用HttpUtils.sendSSLPost ConnectException, url=" + url + ",param=" + param, e); | ||||
|         } | ||||
|         catch (SocketTimeoutException e) | ||||
|         { | ||||
|             log.error("调用HttpUtils.sendSSLPost SocketTimeoutException, url=" + url + ",param=" + param, e); | ||||
|         } | ||||
|         catch (IOException e) | ||||
|         { | ||||
|             log.error("调用HttpUtils.sendSSLPost IOException, url=" + url + ",param=" + param, e); | ||||
|         } | ||||
|         catch (Exception e) | ||||
|         { | ||||
|             log.error("调用HttpsUtil.sendSSLPost Exception, url=" + url + ",param=" + param, e); | ||||
|         } | ||||
|         return result.toString(); | ||||
|     } | ||||
|  | ||||
|     private static class TrustAnyTrustManager implements X509TrustManager | ||||
|     { | ||||
|         @Override | ||||
|         public void checkClientTrusted(X509Certificate[] chain, String authType) | ||||
|         { | ||||
|         } | ||||
|  | ||||
|         @Override | ||||
|         public void checkServerTrusted(X509Certificate[] chain, String authType) | ||||
|         { | ||||
|         } | ||||
|  | ||||
|         @Override | ||||
|         public X509Certificate[] getAcceptedIssuers() | ||||
|         { | ||||
|             return new X509Certificate[] {}; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private static class TrustAnyHostnameVerifier implements HostnameVerifier | ||||
|     { | ||||
|         @Override | ||||
|         public boolean verify(String hostname, SSLSession session) | ||||
|         { | ||||
|             return true; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,56 @@ | ||||
| package com.stdiet.common.utils.ip; | ||||
|  | ||||
| import org.slf4j.Logger; | ||||
| import org.slf4j.LoggerFactory; | ||||
| import com.alibaba.fastjson.JSONObject; | ||||
| import com.stdiet.common.config.RuoYiConfig; | ||||
| import com.stdiet.common.constant.Constants; | ||||
| import com.stdiet.common.utils.StringUtils; | ||||
| import com.stdiet.common.utils.http.HttpUtils; | ||||
|  | ||||
| /** | ||||
|  * 获取地址类 | ||||
|  *  | ||||
|  * @author stdiet | ||||
|  */ | ||||
| public class AddressUtils | ||||
| { | ||||
|     private static final Logger log = LoggerFactory.getLogger(AddressUtils.class); | ||||
|  | ||||
|     // IP地址查询 | ||||
|     public static final String IP_URL = "http://whois.pconline.com.cn/ipJson.jsp"; | ||||
|  | ||||
|     // 未知地址 | ||||
|     public static final String UNKNOWN = "XX XX"; | ||||
|  | ||||
|     public static String getRealAddressByIP(String ip) | ||||
|     { | ||||
|         String address = UNKNOWN; | ||||
|         // 内网不查询 | ||||
|         if (IpUtils.internalIp(ip)) | ||||
|         { | ||||
|             return "内网IP"; | ||||
|         } | ||||
|         if (RuoYiConfig.isAddressEnabled()) | ||||
|         { | ||||
|             try | ||||
|             { | ||||
|                 String rspStr = HttpUtils.sendGet(IP_URL, "ip=" + ip + "&json=true", Constants.GBK); | ||||
|                 if (StringUtils.isEmpty(rspStr)) | ||||
|                 { | ||||
|                     log.error("获取地理位置异常 {}", ip); | ||||
|                     return UNKNOWN; | ||||
|                 } | ||||
|                 JSONObject obj = JSONObject.parseObject(rspStr); | ||||
|                 String region = obj.getString("pro"); | ||||
|                 String city = obj.getString("city"); | ||||
|                 return String.format("%s %s", region, city); | ||||
|             } | ||||
|             catch (Exception e) | ||||
|             { | ||||
|                 log.error("获取地理位置异常 {}", ip); | ||||
|             } | ||||
|         } | ||||
|         return address; | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,195 @@ | ||||
| package com.stdiet.common.utils.ip; | ||||
|  | ||||
| import java.net.InetAddress; | ||||
| import java.net.UnknownHostException; | ||||
| import javax.servlet.http.HttpServletRequest; | ||||
| import com.stdiet.common.utils.StringUtils; | ||||
| import com.stdiet.common.utils.html.EscapeUtil; | ||||
|  | ||||
| /** | ||||
|  * 获取IP方法 | ||||
|  *  | ||||
|  * @author stdiet | ||||
|  */ | ||||
| public class IpUtils | ||||
| { | ||||
|     public static String getIpAddr(HttpServletRequest request) | ||||
|     { | ||||
|         if (request == null) | ||||
|         { | ||||
|             return "unknown"; | ||||
|         } | ||||
|         String ip = request.getHeader("x-forwarded-for"); | ||||
|         if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) | ||||
|         { | ||||
|             ip = request.getHeader("Proxy-Client-IP"); | ||||
|         } | ||||
|         if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) | ||||
|         { | ||||
|             ip = request.getHeader("X-Forwarded-For"); | ||||
|         } | ||||
|         if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) | ||||
|         { | ||||
|             ip = request.getHeader("WL-Proxy-Client-IP"); | ||||
|         } | ||||
|         if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) | ||||
|         { | ||||
|             ip = request.getHeader("X-Real-IP"); | ||||
|         } | ||||
|  | ||||
|         if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) | ||||
|         { | ||||
|             ip = request.getRemoteAddr(); | ||||
|         } | ||||
|         return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : EscapeUtil.clean(ip); | ||||
|     } | ||||
|  | ||||
|     public static boolean internalIp(String ip) | ||||
|     { | ||||
|         byte[] addr = textToNumericFormatV4(ip); | ||||
|         return internalIp(addr) || "127.0.0.1".equals(ip); | ||||
|     } | ||||
|  | ||||
|     private static boolean internalIp(byte[] addr) | ||||
|     { | ||||
|         if (StringUtils.isNull(addr) || addr.length < 2) | ||||
|         { | ||||
|             return true; | ||||
|         } | ||||
|         final byte b0 = addr[0]; | ||||
|         final byte b1 = addr[1]; | ||||
|         // 10.x.x.x/8 | ||||
|         final byte SECTION_1 = 0x0A; | ||||
|         // 172.16.x.x/12 | ||||
|         final byte SECTION_2 = (byte) 0xAC; | ||||
|         final byte SECTION_3 = (byte) 0x10; | ||||
|         final byte SECTION_4 = (byte) 0x1F; | ||||
|         // 192.168.x.x/16 | ||||
|         final byte SECTION_5 = (byte) 0xC0; | ||||
|         final byte SECTION_6 = (byte) 0xA8; | ||||
|         switch (b0) | ||||
|         { | ||||
|             case SECTION_1: | ||||
|                 return true; | ||||
|             case SECTION_2: | ||||
|                 if (b1 >= SECTION_3 && b1 <= SECTION_4) | ||||
|                 { | ||||
|                     return true; | ||||
|                 } | ||||
|             case SECTION_5: | ||||
|                 switch (b1) | ||||
|                 { | ||||
|                     case SECTION_6: | ||||
|                         return true; | ||||
|                 } | ||||
|             default: | ||||
|                 return false; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 将IPv4地址转换成字节 | ||||
|      *  | ||||
|      * @param text IPv4地址 | ||||
|      * @return byte 字节 | ||||
|      */ | ||||
|     public static byte[] textToNumericFormatV4(String text) | ||||
|     { | ||||
|         if (text.length() == 0) | ||||
|         { | ||||
|             return null; | ||||
|         } | ||||
|  | ||||
|         byte[] bytes = new byte[4]; | ||||
|         String[] elements = text.split("\\.", -1); | ||||
|         try | ||||
|         { | ||||
|             long l; | ||||
|             int i; | ||||
|             switch (elements.length) | ||||
|             { | ||||
|                 case 1: | ||||
|                     l = Long.parseLong(elements[0]); | ||||
|                     if ((l < 0L) || (l > 4294967295L)) { | ||||
|                         return null; | ||||
|                     } | ||||
|                     bytes[0] = (byte) (int) (l >> 24 & 0xFF); | ||||
|                     bytes[1] = (byte) (int) ((l & 0xFFFFFF) >> 16 & 0xFF); | ||||
|                     bytes[2] = (byte) (int) ((l & 0xFFFF) >> 8 & 0xFF); | ||||
|                     bytes[3] = (byte) (int) (l & 0xFF); | ||||
|                     break; | ||||
|                 case 2: | ||||
|                     l = Integer.parseInt(elements[0]); | ||||
|                     if ((l < 0L) || (l > 255L)) { | ||||
|                         return null; | ||||
|                     } | ||||
|                     bytes[0] = (byte) (int) (l & 0xFF); | ||||
|                     l = Integer.parseInt(elements[1]); | ||||
|                     if ((l < 0L) || (l > 16777215L)) { | ||||
|                         return null; | ||||
|                     } | ||||
|                     bytes[1] = (byte) (int) (l >> 16 & 0xFF); | ||||
|                     bytes[2] = (byte) (int) ((l & 0xFFFF) >> 8 & 0xFF); | ||||
|                     bytes[3] = (byte) (int) (l & 0xFF); | ||||
|                     break; | ||||
|                 case 3: | ||||
|                     for (i = 0; i < 2; ++i) | ||||
|                     { | ||||
|                         l = Integer.parseInt(elements[i]); | ||||
|                         if ((l < 0L) || (l > 255L)) { | ||||
|                             return null; | ||||
|                         } | ||||
|                         bytes[i] = (byte) (int) (l & 0xFF); | ||||
|                     } | ||||
|                     l = Integer.parseInt(elements[2]); | ||||
|                     if ((l < 0L) || (l > 65535L)) { | ||||
|                         return null; | ||||
|                     } | ||||
|                     bytes[2] = (byte) (int) (l >> 8 & 0xFF); | ||||
|                     bytes[3] = (byte) (int) (l & 0xFF); | ||||
|                     break; | ||||
|                 case 4: | ||||
|                     for (i = 0; i < 4; ++i) | ||||
|                     { | ||||
|                         l = Integer.parseInt(elements[i]); | ||||
|                         if ((l < 0L) || (l > 255L)) { | ||||
|                             return null; | ||||
|                         } | ||||
|                         bytes[i] = (byte) (int) (l & 0xFF); | ||||
|                     } | ||||
|                     break; | ||||
|                 default: | ||||
|                     return null; | ||||
|             } | ||||
|         } | ||||
|         catch (NumberFormatException e) | ||||
|         { | ||||
|             return null; | ||||
|         } | ||||
|         return bytes; | ||||
|     } | ||||
|  | ||||
|     public static String getHostIp() | ||||
|     { | ||||
|         try | ||||
|         { | ||||
|             return InetAddress.getLocalHost().getHostAddress(); | ||||
|         } | ||||
|         catch (UnknownHostException e) | ||||
|         { | ||||
|         } | ||||
|         return "127.0.0.1"; | ||||
|     } | ||||
|  | ||||
|     public static String getHostName() | ||||
|     { | ||||
|         try | ||||
|         { | ||||
|             return InetAddress.getLocalHost().getHostName(); | ||||
|         } | ||||
|         catch (UnknownHostException e) | ||||
|         { | ||||
|         } | ||||
|         return "未知"; | ||||
|     } | ||||
| } | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -0,0 +1,406 @@ | ||||
| package com.stdiet.common.utils.reflect; | ||||
|  | ||||
| import java.lang.reflect.Field; | ||||
| import java.lang.reflect.InvocationTargetException; | ||||
| import java.lang.reflect.Method; | ||||
| import java.lang.reflect.Modifier; | ||||
| import java.lang.reflect.ParameterizedType; | ||||
| import java.lang.reflect.Type; | ||||
| import java.util.Date; | ||||
| import org.apache.commons.lang3.StringUtils; | ||||
| import org.apache.commons.lang3.Validate; | ||||
| import org.apache.poi.ss.usermodel.DateUtil; | ||||
| import org.slf4j.Logger; | ||||
| import org.slf4j.LoggerFactory; | ||||
| import com.stdiet.common.core.text.Convert; | ||||
| import com.stdiet.common.utils.DateUtils; | ||||
|  | ||||
| /** | ||||
|  * 反射工具类. 提供调用getter/setter方法, 访问私有变量, 调用私有方法, 获取泛型类型Class, 被AOP过的真实类等工具函数. | ||||
|  *  | ||||
|  * @author stdiet | ||||
|  */ | ||||
| @SuppressWarnings("rawtypes") | ||||
| public class ReflectUtils | ||||
| { | ||||
|     private static final String SETTER_PREFIX = "set"; | ||||
|  | ||||
|     private static final String GETTER_PREFIX = "get"; | ||||
|  | ||||
|     private static final String CGLIB_CLASS_SEPARATOR = "$$"; | ||||
|  | ||||
|     private static Logger logger = LoggerFactory.getLogger(ReflectUtils.class); | ||||
|  | ||||
|     /** | ||||
|      * 调用Getter方法. | ||||
|      * 支持多级,如:对象名.对象名.方法 | ||||
|      */ | ||||
|     @SuppressWarnings("unchecked") | ||||
|     public static <E> E invokeGetter(Object obj, String propertyName) | ||||
|     { | ||||
|         Object object = obj; | ||||
|         for (String name : StringUtils.split(propertyName, ".")) | ||||
|         { | ||||
|             String getterMethodName = GETTER_PREFIX + StringUtils.capitalize(name); | ||||
|             object = invokeMethod(object, getterMethodName, new Class[] {}, new Object[] {}); | ||||
|         } | ||||
|         return (E) object; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 调用Setter方法, 仅匹配方法名。 | ||||
|      * 支持多级,如:对象名.对象名.方法 | ||||
|      */ | ||||
|     public static <E> void invokeSetter(Object obj, String propertyName, E value) | ||||
|     { | ||||
|         Object object = obj; | ||||
|         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 = invokeMethod(object, getterMethodName, new Class[] {}, new Object[] {}); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 String setterMethodName = SETTER_PREFIX + StringUtils.capitalize(names[i]); | ||||
|                 invokeMethodByName(object, setterMethodName, new Object[] { value }); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 直接读取对象属性值, 无视private/protected修饰符, 不经过getter函数. | ||||
|      */ | ||||
|     @SuppressWarnings("unchecked") | ||||
|     public static <E> E getFieldValue(final Object obj, final String fieldName) | ||||
|     { | ||||
|         Field field = getAccessibleField(obj, fieldName); | ||||
|         if (field == null) | ||||
|         { | ||||
|             logger.debug("在 [" + obj.getClass() + "] 中,没有找到 [" + fieldName + "] 字段 "); | ||||
|             return null; | ||||
|         } | ||||
|         E result = null; | ||||
|         try | ||||
|         { | ||||
|             result = (E) field.get(obj); | ||||
|         } | ||||
|         catch (IllegalAccessException e) | ||||
|         { | ||||
|             logger.error("不可能抛出的异常{}", e.getMessage()); | ||||
|         } | ||||
|         return result; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 直接设置对象属性值, 无视private/protected修饰符, 不经过setter函数. | ||||
|      */ | ||||
|     public static <E> void setFieldValue(final Object obj, final String fieldName, final E value) | ||||
|     { | ||||
|         Field field = getAccessibleField(obj, fieldName); | ||||
|         if (field == null) | ||||
|         { | ||||
|             // throw new IllegalArgumentException("在 [" + obj.getClass() + "] 中,没有找到 [" + fieldName + "] 字段 "); | ||||
|             logger.debug("在 [" + obj.getClass() + "] 中,没有找到 [" + fieldName + "] 字段 "); | ||||
|             return; | ||||
|         } | ||||
|         try | ||||
|         { | ||||
|             field.set(obj, value); | ||||
|         } | ||||
|         catch (IllegalAccessException e) | ||||
|         { | ||||
|             logger.error("不可能抛出的异常: {}", e.getMessage()); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 直接调用对象方法, 无视private/protected修饰符. | ||||
|      * 用于一次性调用的情况,否则应使用getAccessibleMethod()函数获得Method后反复调用. | ||||
|      * 同时匹配方法名+参数类型, | ||||
|      */ | ||||
|     @SuppressWarnings("unchecked") | ||||
|     public static <E> E invokeMethod(final Object obj, final String methodName, final Class<?>[] parameterTypes, | ||||
|             final Object[] args) | ||||
|     { | ||||
|         if (obj == null || methodName == null) | ||||
|         { | ||||
|             return null; | ||||
|         } | ||||
|         Method method = getAccessibleMethod(obj, methodName, parameterTypes); | ||||
|         if (method == null) | ||||
|         { | ||||
|             logger.debug("在 [" + obj.getClass() + "] 中,没有找到 [" + methodName + "] 方法 "); | ||||
|             return null; | ||||
|         } | ||||
|         try | ||||
|         { | ||||
|             return (E) method.invoke(obj, args); | ||||
|         } | ||||
|         catch (Exception e) | ||||
|         { | ||||
|             String msg = "method: " + method + ", obj: " + obj + ", args: " + args + ""; | ||||
|             throw convertReflectionExceptionToUnchecked(msg, e); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 直接调用对象方法, 无视private/protected修饰符, | ||||
|      * 用于一次性调用的情况,否则应使用getAccessibleMethodByName()函数获得Method后反复调用. | ||||
|      * 只匹配函数名,如果有多个同名函数调用第一个。 | ||||
|      */ | ||||
|     @SuppressWarnings("unchecked") | ||||
|     public static <E> E invokeMethodByName(final Object obj, final String methodName, final Object[] args) | ||||
|     { | ||||
|         Method method = getAccessibleMethodByName(obj, methodName, args.length); | ||||
|         if (method == null) | ||||
|         { | ||||
|             // 如果为空不报错,直接返回空。 | ||||
|             logger.debug("在 [" + obj.getClass() + "] 中,没有找到 [" + methodName + "] 方法 "); | ||||
|             return null; | ||||
|         } | ||||
|         try | ||||
|         { | ||||
|             // 类型转换(将参数数据类型转换为目标方法参数类型) | ||||
|             Class<?>[] cs = method.getParameterTypes(); | ||||
|             for (int i = 0; i < cs.length; i++) | ||||
|             { | ||||
|                 if (args[i] != null && !args[i].getClass().equals(cs[i])) | ||||
|                 { | ||||
|                     if (cs[i] == String.class) | ||||
|                     { | ||||
|                         args[i] = Convert.toStr(args[i]); | ||||
|                         if (StringUtils.endsWith((String) args[i], ".0")) | ||||
|                         { | ||||
|                             args[i] = StringUtils.substringBefore((String) args[i], ".0"); | ||||
|                         } | ||||
|                     } | ||||
|                     else if (cs[i] == Integer.class) | ||||
|                     { | ||||
|                         args[i] = Convert.toInt(args[i]); | ||||
|                     } | ||||
|                     else if (cs[i] == Long.class) | ||||
|                     { | ||||
|                         args[i] = Convert.toLong(args[i]); | ||||
|                     } | ||||
|                     else if (cs[i] == Double.class) | ||||
|                     { | ||||
|                         args[i] = Convert.toDouble(args[i]); | ||||
|                     } | ||||
|                     else if (cs[i] == Float.class) | ||||
|                     { | ||||
|                         args[i] = Convert.toFloat(args[i]); | ||||
|                     } | ||||
|                     else if (cs[i] == Date.class) | ||||
|                     { | ||||
|                         if (args[i] instanceof String) | ||||
|                         { | ||||
|                             args[i] = DateUtils.parseDate(args[i]); | ||||
|                         } | ||||
|                         else | ||||
|                         { | ||||
|                             args[i] = DateUtil.getJavaDate((Double) args[i]); | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|             return (E) method.invoke(obj, args); | ||||
|         } | ||||
|         catch (Exception e) | ||||
|         { | ||||
|             String msg = "method: " + method + ", obj: " + obj + ", args: " + args + ""; | ||||
|             throw convertReflectionExceptionToUnchecked(msg, e); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 循环向上转型, 获取对象的DeclaredField, 并强制设置为可访问. | ||||
|      * 如向上转型到Object仍无法找到, 返回null. | ||||
|      */ | ||||
|     public static Field getAccessibleField(final Object obj, final String fieldName) | ||||
|     { | ||||
|         // 为空不报错。直接返回 null | ||||
|         if (obj == null) | ||||
|         { | ||||
|             return null; | ||||
|         } | ||||
|         Validate.notBlank(fieldName, "fieldName can't be blank"); | ||||
|         for (Class<?> superClass = obj.getClass(); superClass != Object.class; superClass = superClass.getSuperclass()) | ||||
|         { | ||||
|             try | ||||
|             { | ||||
|                 Field field = superClass.getDeclaredField(fieldName); | ||||
|                 makeAccessible(field); | ||||
|                 return field; | ||||
|             } | ||||
|             catch (NoSuchFieldException e) | ||||
|             { | ||||
|                 continue; | ||||
|             } | ||||
|         } | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 循环向上转型, 获取对象的DeclaredMethod,并强制设置为可访问. | ||||
|      * 如向上转型到Object仍无法找到, 返回null. | ||||
|      * 匹配函数名+参数类型。 | ||||
|      * 用于方法需要被多次调用的情况. 先使用本函数先取得Method,然后调用Method.invoke(Object obj, Object... args) | ||||
|      */ | ||||
|     public static Method getAccessibleMethod(final Object obj, final String methodName, | ||||
|             final Class<?>... parameterTypes) | ||||
|     { | ||||
|         // 为空不报错。直接返回 null | ||||
|         if (obj == null) | ||||
|         { | ||||
|             return null; | ||||
|         } | ||||
|         Validate.notBlank(methodName, "methodName can't be blank"); | ||||
|         for (Class<?> searchType = obj.getClass(); searchType != Object.class; searchType = searchType.getSuperclass()) | ||||
|         { | ||||
|             try | ||||
|             { | ||||
|                 Method method = searchType.getDeclaredMethod(methodName, parameterTypes); | ||||
|                 makeAccessible(method); | ||||
|                 return method; | ||||
|             } | ||||
|             catch (NoSuchMethodException e) | ||||
|             { | ||||
|                 continue; | ||||
|             } | ||||
|         } | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 循环向上转型, 获取对象的DeclaredMethod,并强制设置为可访问. | ||||
|      * 如向上转型到Object仍无法找到, 返回null. | ||||
|      * 只匹配函数名。 | ||||
|      * 用于方法需要被多次调用的情况. 先使用本函数先取得Method,然后调用Method.invoke(Object obj, Object... args) | ||||
|      */ | ||||
|     public static Method getAccessibleMethodByName(final Object obj, final String methodName, int argsNum) | ||||
|     { | ||||
|         // 为空不报错。直接返回 null | ||||
|         if (obj == null) | ||||
|         { | ||||
|             return null; | ||||
|         } | ||||
|         Validate.notBlank(methodName, "methodName can't be blank"); | ||||
|         for (Class<?> searchType = obj.getClass(); searchType != Object.class; searchType = searchType.getSuperclass()) | ||||
|         { | ||||
|             Method[] methods = searchType.getDeclaredMethods(); | ||||
|             for (Method method : methods) | ||||
|             { | ||||
|                 if (method.getName().equals(methodName) && method.getParameterTypes().length == argsNum) | ||||
|                 { | ||||
|                     makeAccessible(method); | ||||
|                     return method; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 改变private/protected的方法为public,尽量不调用实际改动的语句,避免JDK的SecurityManager抱怨。 | ||||
|      */ | ||||
|     public static void makeAccessible(Method method) | ||||
|     { | ||||
|         if ((!Modifier.isPublic(method.getModifiers()) || !Modifier.isPublic(method.getDeclaringClass().getModifiers())) | ||||
|                 && !method.isAccessible()) | ||||
|         { | ||||
|             method.setAccessible(true); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 改变private/protected的成员变量为public,尽量不调用实际改动的语句,避免JDK的SecurityManager抱怨。 | ||||
|      */ | ||||
|     public static void makeAccessible(Field field) | ||||
|     { | ||||
|         if ((!Modifier.isPublic(field.getModifiers()) || !Modifier.isPublic(field.getDeclaringClass().getModifiers()) | ||||
|                 || Modifier.isFinal(field.getModifiers())) && !field.isAccessible()) | ||||
|         { | ||||
|             field.setAccessible(true); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 通过反射, 获得Class定义中声明的泛型参数的类型, 注意泛型必须定义在父类处 | ||||
|      * 如无法找到, 返回Object.class. | ||||
|      */ | ||||
|     @SuppressWarnings("unchecked") | ||||
|     public static <T> Class<T> getClassGenricType(final Class clazz) | ||||
|     { | ||||
|         return getClassGenricType(clazz, 0); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 通过反射, 获得Class定义中声明的父类的泛型参数的类型. | ||||
|      * 如无法找到, 返回Object.class. | ||||
|      */ | ||||
|     public static Class getClassGenricType(final Class clazz, final int index) | ||||
|     { | ||||
|         Type genType = clazz.getGenericSuperclass(); | ||||
|  | ||||
|         if (!(genType instanceof ParameterizedType)) | ||||
|         { | ||||
|             logger.debug(clazz.getSimpleName() + "'s superclass not ParameterizedType"); | ||||
|             return Object.class; | ||||
|         } | ||||
|  | ||||
|         Type[] params = ((ParameterizedType) genType).getActualTypeArguments(); | ||||
|  | ||||
|         if (index >= params.length || index < 0) | ||||
|         { | ||||
|             logger.debug("Index: " + index + ", Size of " + clazz.getSimpleName() + "'s Parameterized Type: " | ||||
|                     + params.length); | ||||
|             return Object.class; | ||||
|         } | ||||
|         if (!(params[index] instanceof Class)) | ||||
|         { | ||||
|             logger.debug(clazz.getSimpleName() + " not set the actual class on superclass generic parameter"); | ||||
|             return Object.class; | ||||
|         } | ||||
|  | ||||
|         return (Class) params[index]; | ||||
|     } | ||||
|  | ||||
|     public static Class<?> getUserClass(Object instance) | ||||
|     { | ||||
|         if (instance == null) | ||||
|         { | ||||
|             throw new RuntimeException("Instance must not be null"); | ||||
|         } | ||||
|         Class clazz = instance.getClass(); | ||||
|         if (clazz != null && clazz.getName().contains(CGLIB_CLASS_SEPARATOR)) | ||||
|         { | ||||
|             Class<?> superClass = clazz.getSuperclass(); | ||||
|             if (superClass != null && !Object.class.equals(superClass)) | ||||
|             { | ||||
|                 return superClass; | ||||
|             } | ||||
|         } | ||||
|         return clazz; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 将反射时的checked exception转换为unchecked exception. | ||||
|      */ | ||||
|     public static RuntimeException convertReflectionExceptionToUnchecked(String msg, Exception e) | ||||
|     { | ||||
|         if (e instanceof IllegalAccessException || e instanceof IllegalArgumentException | ||||
|                 || e instanceof NoSuchMethodException) | ||||
|         { | ||||
|             return new IllegalArgumentException(msg, e); | ||||
|         } | ||||
|         else if (e instanceof InvocationTargetException) | ||||
|         { | ||||
|             return new RuntimeException(msg, ((InvocationTargetException) e).getTargetException()); | ||||
|         } | ||||
|         return new RuntimeException(msg, e); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,291 @@ | ||||
| package com.stdiet.common.utils.sign; | ||||
|  | ||||
| /** | ||||
|  * Base64工具类 | ||||
|  *  | ||||
|  * @author ruoyi | ||||
|  */ | ||||
| public final class Base64 | ||||
| { | ||||
|     static private final int     BASELENGTH           = 128; | ||||
|     static private final int     LOOKUPLENGTH         = 64; | ||||
|     static private final int     TWENTYFOURBITGROUP   = 24; | ||||
|     static private final int     EIGHTBIT             = 8; | ||||
|     static private final int     SIXTEENBIT           = 16; | ||||
|     static private final int     FOURBYTE             = 4; | ||||
|     static private final int     SIGN                 = -128; | ||||
|     static private final char    PAD                  = '='; | ||||
|     static final private byte[]  base64Alphabet       = new byte[BASELENGTH]; | ||||
|     static final private char[]  lookUpBase64Alphabet = new char[LOOKUPLENGTH]; | ||||
|  | ||||
|     static | ||||
|     { | ||||
|         for (int i = 0; i < BASELENGTH; ++i) | ||||
|         { | ||||
|             base64Alphabet[i] = -1; | ||||
|         } | ||||
|         for (int i = 'Z'; i >= 'A'; i--) | ||||
|         { | ||||
|             base64Alphabet[i] = (byte) (i - 'A'); | ||||
|         } | ||||
|         for (int i = 'z'; i >= 'a'; i--) | ||||
|         { | ||||
|             base64Alphabet[i] = (byte) (i - 'a' + 26); | ||||
|         } | ||||
|  | ||||
|         for (int i = '9'; i >= '0'; i--) | ||||
|         { | ||||
|             base64Alphabet[i] = (byte) (i - '0' + 52); | ||||
|         } | ||||
|  | ||||
|         base64Alphabet['+'] = 62; | ||||
|         base64Alphabet['/'] = 63; | ||||
|  | ||||
|         for (int i = 0; i <= 25; i++) | ||||
|         { | ||||
|             lookUpBase64Alphabet[i] = (char) ('A' + i); | ||||
|         } | ||||
|  | ||||
|         for (int i = 26, j = 0; i <= 51; i++, j++) | ||||
|         { | ||||
|             lookUpBase64Alphabet[i] = (char) ('a' + j); | ||||
|         } | ||||
|  | ||||
|         for (int i = 52, j = 0; i <= 61; i++, j++) | ||||
|         { | ||||
|             lookUpBase64Alphabet[i] = (char) ('0' + j); | ||||
|         } | ||||
|         lookUpBase64Alphabet[62] = (char) '+'; | ||||
|         lookUpBase64Alphabet[63] = (char) '/'; | ||||
|     } | ||||
|  | ||||
|     private static boolean isWhiteSpace(char octect) | ||||
|     { | ||||
|         return (octect == 0x20 || octect == 0xd || octect == 0xa || octect == 0x9); | ||||
|     } | ||||
|  | ||||
|     private static boolean isPad(char octect) | ||||
|     { | ||||
|         return (octect == PAD); | ||||
|     } | ||||
|  | ||||
|     private static boolean isData(char octect) | ||||
|     { | ||||
|         return (octect < BASELENGTH && base64Alphabet[octect] != -1); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Encodes hex octects into Base64 | ||||
|      * | ||||
|      * @param binaryData Array containing binaryData | ||||
|      * @return Encoded Base64 array | ||||
|      */ | ||||
|     public static String encode(byte[] binaryData) | ||||
|     { | ||||
|         if (binaryData == null) | ||||
|         { | ||||
|             return null; | ||||
|         } | ||||
|  | ||||
|         int lengthDataBits = binaryData.length * EIGHTBIT; | ||||
|         if (lengthDataBits == 0) | ||||
|         { | ||||
|             return ""; | ||||
|         } | ||||
|  | ||||
|         int fewerThan24bits = lengthDataBits % TWENTYFOURBITGROUP; | ||||
|         int numberTriplets = lengthDataBits / TWENTYFOURBITGROUP; | ||||
|         int numberQuartet = fewerThan24bits != 0 ? numberTriplets + 1 : numberTriplets; | ||||
|         char encodedData[] = null; | ||||
|  | ||||
|         encodedData = new char[numberQuartet * 4]; | ||||
|  | ||||
|         byte k = 0, l = 0, b1 = 0, b2 = 0, b3 = 0; | ||||
|  | ||||
|         int encodedIndex = 0; | ||||
|         int dataIndex = 0; | ||||
|  | ||||
|         for (int i = 0; i < numberTriplets; i++) | ||||
|         { | ||||
|             b1 = binaryData[dataIndex++]; | ||||
|             b2 = binaryData[dataIndex++]; | ||||
|             b3 = binaryData[dataIndex++]; | ||||
|  | ||||
|             l = (byte) (b2 & 0x0f); | ||||
|             k = (byte) (b1 & 0x03); | ||||
|  | ||||
|             byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0); | ||||
|             byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4) : (byte) ((b2) >> 4 ^ 0xf0); | ||||
|             byte val3 = ((b3 & SIGN) == 0) ? (byte) (b3 >> 6) : (byte) ((b3) >> 6 ^ 0xfc); | ||||
|  | ||||
|             encodedData[encodedIndex++] = lookUpBase64Alphabet[val1]; | ||||
|             encodedData[encodedIndex++] = lookUpBase64Alphabet[val2 | (k << 4)]; | ||||
|             encodedData[encodedIndex++] = lookUpBase64Alphabet[(l << 2) | val3]; | ||||
|             encodedData[encodedIndex++] = lookUpBase64Alphabet[b3 & 0x3f]; | ||||
|         } | ||||
|  | ||||
|         // form integral number of 6-bit groups | ||||
|         if (fewerThan24bits == EIGHTBIT) | ||||
|         { | ||||
|             b1 = binaryData[dataIndex]; | ||||
|             k = (byte) (b1 & 0x03); | ||||
|             byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0); | ||||
|             encodedData[encodedIndex++] = lookUpBase64Alphabet[val1]; | ||||
|             encodedData[encodedIndex++] = lookUpBase64Alphabet[k << 4]; | ||||
|             encodedData[encodedIndex++] = PAD; | ||||
|             encodedData[encodedIndex++] = PAD; | ||||
|         } | ||||
|         else if (fewerThan24bits == SIXTEENBIT) | ||||
|         { | ||||
|             b1 = binaryData[dataIndex]; | ||||
|             b2 = binaryData[dataIndex + 1]; | ||||
|             l = (byte) (b2 & 0x0f); | ||||
|             k = (byte) (b1 & 0x03); | ||||
|  | ||||
|             byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0); | ||||
|             byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4) : (byte) ((b2) >> 4 ^ 0xf0); | ||||
|  | ||||
|             encodedData[encodedIndex++] = lookUpBase64Alphabet[val1]; | ||||
|             encodedData[encodedIndex++] = lookUpBase64Alphabet[val2 | (k << 4)]; | ||||
|             encodedData[encodedIndex++] = lookUpBase64Alphabet[l << 2]; | ||||
|             encodedData[encodedIndex++] = PAD; | ||||
|         } | ||||
|         return new String(encodedData); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Decodes Base64 data into octects | ||||
|      * | ||||
|      * @param encoded string containing Base64 data | ||||
|      * @return Array containind decoded data. | ||||
|      */ | ||||
|     public static byte[] decode(String encoded) | ||||
|     { | ||||
|         if (encoded == null) | ||||
|         { | ||||
|             return null; | ||||
|         } | ||||
|  | ||||
|         char[] base64Data = encoded.toCharArray(); | ||||
|         // remove white spaces | ||||
|         int len = removeWhiteSpace(base64Data); | ||||
|  | ||||
|         if (len % FOURBYTE != 0) | ||||
|         { | ||||
|             return null;// should be divisible by four | ||||
|         } | ||||
|  | ||||
|         int numberQuadruple = (len / FOURBYTE); | ||||
|  | ||||
|         if (numberQuadruple == 0) | ||||
|         { | ||||
|             return new byte[0]; | ||||
|         } | ||||
|  | ||||
|         byte decodedData[] = null; | ||||
|         byte b1 = 0, b2 = 0, b3 = 0, b4 = 0; | ||||
|         char d1 = 0, d2 = 0, d3 = 0, d4 = 0; | ||||
|  | ||||
|         int i = 0; | ||||
|         int encodedIndex = 0; | ||||
|         int dataIndex = 0; | ||||
|         decodedData = new byte[(numberQuadruple) * 3]; | ||||
|  | ||||
|         for (; i < numberQuadruple - 1; i++) | ||||
|         { | ||||
|  | ||||
|             if (!isData((d1 = base64Data[dataIndex++])) || !isData((d2 = base64Data[dataIndex++])) | ||||
|                     || !isData((d3 = base64Data[dataIndex++])) || !isData((d4 = base64Data[dataIndex++]))) | ||||
|             { | ||||
|                 return null; | ||||
|             } // if found "no data" just return null | ||||
|  | ||||
|             b1 = base64Alphabet[d1]; | ||||
|             b2 = base64Alphabet[d2]; | ||||
|             b3 = base64Alphabet[d3]; | ||||
|             b4 = base64Alphabet[d4]; | ||||
|  | ||||
|             decodedData[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4); | ||||
|             decodedData[encodedIndex++] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf)); | ||||
|             decodedData[encodedIndex++] = (byte) (b3 << 6 | b4); | ||||
|         } | ||||
|  | ||||
|         if (!isData((d1 = base64Data[dataIndex++])) || !isData((d2 = base64Data[dataIndex++]))) | ||||
|         { | ||||
|             return null;// if found "no data" just return null | ||||
|         } | ||||
|  | ||||
|         b1 = base64Alphabet[d1]; | ||||
|         b2 = base64Alphabet[d2]; | ||||
|  | ||||
|         d3 = base64Data[dataIndex++]; | ||||
|         d4 = base64Data[dataIndex++]; | ||||
|         if (!isData((d3)) || !isData((d4))) | ||||
|         {// Check if they are PAD characters | ||||
|             if (isPad(d3) && isPad(d4)) | ||||
|             { | ||||
|                 if ((b2 & 0xf) != 0)// last 4 bits should be zero | ||||
|                 { | ||||
|                     return null; | ||||
|                 } | ||||
|                 byte[] tmp = new byte[i * 3 + 1]; | ||||
|                 System.arraycopy(decodedData, 0, tmp, 0, i * 3); | ||||
|                 tmp[encodedIndex] = (byte) (b1 << 2 | b2 >> 4); | ||||
|                 return tmp; | ||||
|             } | ||||
|             else if (!isPad(d3) && isPad(d4)) | ||||
|             { | ||||
|                 b3 = base64Alphabet[d3]; | ||||
|                 if ((b3 & 0x3) != 0)// last 2 bits should be zero | ||||
|                 { | ||||
|                     return null; | ||||
|                 } | ||||
|                 byte[] tmp = new byte[i * 3 + 2]; | ||||
|                 System.arraycopy(decodedData, 0, tmp, 0, i * 3); | ||||
|                 tmp[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4); | ||||
|                 tmp[encodedIndex] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf)); | ||||
|                 return tmp; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 return null; | ||||
|             } | ||||
|         } | ||||
|         else | ||||
|         { // No PAD e.g 3cQl | ||||
|             b3 = base64Alphabet[d3]; | ||||
|             b4 = base64Alphabet[d4]; | ||||
|             decodedData[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4); | ||||
|             decodedData[encodedIndex++] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf)); | ||||
|             decodedData[encodedIndex++] = (byte) (b3 << 6 | b4); | ||||
|  | ||||
|         } | ||||
|         return decodedData; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * remove WhiteSpace from MIME containing encoded Base64 data. | ||||
|      * | ||||
|      * @param data the byte array of base64 data (with WS) | ||||
|      * @return the new length | ||||
|      */ | ||||
|     private static int removeWhiteSpace(char[] data) | ||||
|     { | ||||
|         if (data == null) | ||||
|         { | ||||
|             return 0; | ||||
|         } | ||||
|  | ||||
|         // count characters that's not whitespace | ||||
|         int newSize = 0; | ||||
|         int len = data.length; | ||||
|         for (int i = 0; i < len; i++) | ||||
|         { | ||||
|             if (!isWhiteSpace(data[i])) | ||||
|             { | ||||
|                 data[newSize++] = data[i]; | ||||
|             } | ||||
|         } | ||||
|         return newSize; | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,66 @@ | ||||
| package com.stdiet.common.utils.sign; | ||||
|  | ||||
| import java.security.MessageDigest; | ||||
| import org.slf4j.Logger; | ||||
| import org.slf4j.LoggerFactory; | ||||
|  | ||||
| /** | ||||
|  * Md5加密方法 | ||||
|  *  | ||||
|  * @author stdiet | ||||
|  */ | ||||
| public class Md5Utils | ||||
| { | ||||
|     private static final Logger log = LoggerFactory.getLogger(Md5Utils.class); | ||||
|  | ||||
|     private static byte[] md5(String s) | ||||
|     { | ||||
|         MessageDigest algorithm; | ||||
|         try | ||||
|         { | ||||
|             algorithm = MessageDigest.getInstance("MD5"); | ||||
|             algorithm.reset(); | ||||
|             algorithm.update(s.getBytes("UTF-8")); | ||||
|             byte[] messageDigest = algorithm.digest(); | ||||
|             return messageDigest; | ||||
|         } | ||||
|         catch (Exception e) | ||||
|         { | ||||
|             log.error("MD5 Error...", e); | ||||
|         } | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     private static final String toHex(byte hash[]) | ||||
|     { | ||||
|         if (hash == null) | ||||
|         { | ||||
|             return null; | ||||
|         } | ||||
|         StringBuffer buf = new StringBuffer(hash.length * 2); | ||||
|         int i; | ||||
|  | ||||
|         for (i = 0; i < hash.length; i++) | ||||
|         { | ||||
|             if ((hash[i] & 0xff) < 0x10) | ||||
|             { | ||||
|                 buf.append("0"); | ||||
|             } | ||||
|             buf.append(Long.toString(hash[i] & 0xff, 16)); | ||||
|         } | ||||
|         return buf.toString(); | ||||
|     } | ||||
|  | ||||
|     public static String hash(String s) | ||||
|     { | ||||
|         try | ||||
|         { | ||||
|             return new String(toHex(md5(s)).getBytes("UTF-8"), "UTF-8"); | ||||
|         } | ||||
|         catch (Exception e) | ||||
|         { | ||||
|             log.error("not supported charset...{}", e); | ||||
|             return s; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,146 @@ | ||||
| package com.stdiet.common.utils.spring; | ||||
|  | ||||
| import org.springframework.aop.framework.AopContext; | ||||
| import org.springframework.beans.BeansException; | ||||
| import org.springframework.beans.factory.NoSuchBeanDefinitionException; | ||||
| import org.springframework.beans.factory.config.BeanFactoryPostProcessor; | ||||
| import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; | ||||
| import org.springframework.context.ApplicationContext; | ||||
| import org.springframework.context.ApplicationContextAware; | ||||
| import org.springframework.stereotype.Component; | ||||
| import com.stdiet.common.utils.StringUtils; | ||||
|  | ||||
| /** | ||||
|  * spring工具类 方便在非spring管理环境中获取bean | ||||
|  *  | ||||
|  * @author stdiet | ||||
|  */ | ||||
| @Component | ||||
| public final class SpringUtils implements BeanFactoryPostProcessor, ApplicationContextAware  | ||||
| { | ||||
|     /** Spring应用上下文环境 */ | ||||
|     private static ConfigurableListableBeanFactory beanFactory; | ||||
|  | ||||
|     private static ApplicationContext applicationContext; | ||||
|  | ||||
|     @Override | ||||
|     public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException  | ||||
|     { | ||||
|         SpringUtils.beanFactory = beanFactory; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void setApplicationContext(ApplicationContext applicationContext) throws BeansException  | ||||
|     { | ||||
|         SpringUtils.applicationContext = applicationContext; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 获取对象 | ||||
|      * | ||||
|      * @param name | ||||
|      * @return Object 一个以所给名字注册的bean的实例 | ||||
|      * @throws org.springframework.beans.BeansException | ||||
|      * | ||||
|      */ | ||||
|     @SuppressWarnings("unchecked") | ||||
|     public static <T> T getBean(String name) throws BeansException | ||||
|     { | ||||
|         return (T) beanFactory.getBean(name); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 获取类型为requiredType的对象 | ||||
|      * | ||||
|      * @param clz | ||||
|      * @return | ||||
|      * @throws org.springframework.beans.BeansException | ||||
|      * | ||||
|      */ | ||||
|     public static <T> T getBean(Class<T> clz) throws BeansException | ||||
|     { | ||||
|         T result = (T) beanFactory.getBean(clz); | ||||
|         return result; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 如果BeanFactory包含一个与所给名称匹配的bean定义,则返回true | ||||
|      * | ||||
|      * @param name | ||||
|      * @return boolean | ||||
|      */ | ||||
|     public static boolean containsBean(String name) | ||||
|     { | ||||
|         return beanFactory.containsBean(name); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 判断以给定名字注册的bean定义是一个singleton还是一个prototype。 如果与给定名字相应的bean定义没有被找到,将会抛出一个异常(NoSuchBeanDefinitionException) | ||||
|      * | ||||
|      * @param name | ||||
|      * @return boolean | ||||
|      * @throws org.springframework.beans.factory.NoSuchBeanDefinitionException | ||||
|      * | ||||
|      */ | ||||
|     public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException | ||||
|     { | ||||
|         return beanFactory.isSingleton(name); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param name | ||||
|      * @return Class 注册对象的类型 | ||||
|      * @throws org.springframework.beans.factory.NoSuchBeanDefinitionException | ||||
|      * | ||||
|      */ | ||||
|     public static Class<?> getType(String name) throws NoSuchBeanDefinitionException | ||||
|     { | ||||
|         return beanFactory.getType(name); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 如果给定的bean名字在bean定义中有别名,则返回这些别名 | ||||
|      * | ||||
|      * @param name | ||||
|      * @return | ||||
|      * @throws org.springframework.beans.factory.NoSuchBeanDefinitionException | ||||
|      * | ||||
|      */ | ||||
|     public static String[] getAliases(String name) throws NoSuchBeanDefinitionException | ||||
|     { | ||||
|         return beanFactory.getAliases(name); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 获取aop代理对象 | ||||
|      *  | ||||
|      * @param invoker | ||||
|      * @return | ||||
|      */ | ||||
|     @SuppressWarnings("unchecked") | ||||
|     public static <T> T getAopProxy(T invoker) | ||||
|     { | ||||
|         return (T) AopContext.currentProxy(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 获取当前的环境配置,无配置返回null | ||||
|      * | ||||
|      * @return 当前的环境配置 | ||||
|      */ | ||||
|     public static String[] getActiveProfiles() | ||||
|     { | ||||
|         return applicationContext.getEnvironment().getActiveProfiles(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 获取当前的环境配置,当有多个环境配置时,只获取第一个 | ||||
|      * | ||||
|      * @return 当前的环境配置 | ||||
|      */ | ||||
|     public static String getActiveProfile() | ||||
|     { | ||||
|         final String[] activeProfiles = getActiveProfiles(); | ||||
|         return StringUtils.isNotEmpty(activeProfiles) ? activeProfiles[0] : null; | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,37 @@ | ||||
| package com.stdiet.common.utils.sql; | ||||
|  | ||||
| import com.stdiet.common.exception.BaseException; | ||||
| import com.stdiet.common.utils.StringUtils; | ||||
|  | ||||
| /** | ||||
|  * sql操作工具类 | ||||
|  *  | ||||
|  * @author stdiet | ||||
|  */ | ||||
| public class SqlUtil | ||||
| { | ||||
|     /** | ||||
|      * 仅支持字母、数字、下划线、空格、逗号、小数点(支持多个字段排序) | ||||
|      */ | ||||
|     public static String SQL_PATTERN = "[a-zA-Z0-9_\\ \\,\\.]+"; | ||||
|  | ||||
|     /** | ||||
|      * 检查字符,防止注入绕过 | ||||
|      */ | ||||
|     public static String escapeOrderBySql(String value) | ||||
|     { | ||||
|         if (StringUtils.isNotEmpty(value) && !isValidOrderBySql(value)) | ||||
|         { | ||||
|             throw new BaseException("参数不符合规范,不能进行查询"); | ||||
|         } | ||||
|         return value; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 验证 order by 语法是否符合规范 | ||||
|      */ | ||||
|     public static boolean isValidOrderBySql(String value) | ||||
|     { | ||||
|         return value.matches(SQL_PATTERN); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,51 @@ | ||||
| package com.stdiet.common.utils.uuid; | ||||
|  | ||||
| import com.stdiet.common.utils.uuid.UUID; | ||||
|  | ||||
| /** | ||||
|  * ID生成器工具类 | ||||
|  *  | ||||
|  * @author stdiet | ||||
|  */ | ||||
| public class IdUtils | ||||
| { | ||||
|     /** | ||||
|      * 获取随机UUID | ||||
|      *  | ||||
|      * @return 随机UUID | ||||
|      */ | ||||
|     public static String randomUUID() | ||||
|     { | ||||
|         return UUID.randomUUID().toString(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 简化的UUID,去掉了横线 | ||||
|      *  | ||||
|      * @return 简化的UUID,去掉了横线 | ||||
|      */ | ||||
|     public static String simpleUUID() | ||||
|     { | ||||
|         return UUID.randomUUID().toString(true); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 获取随机UUID,使用性能更好的ThreadLocalRandom生成UUID | ||||
|      *  | ||||
|      * @return 随机UUID | ||||
|      */ | ||||
|     public static String fastUUID() | ||||
|     { | ||||
|         return UUID.fastUUID().toString(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 简化的UUID,去掉了横线,使用性能更好的ThreadLocalRandom生成UUID | ||||
|      *  | ||||
|      * @return 简化的UUID,去掉了横线 | ||||
|      */ | ||||
|     public static String fastSimpleUUID() | ||||
|     { | ||||
|         return UUID.fastUUID().toString(true); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,484 @@ | ||||
| package com.stdiet.common.utils.uuid; | ||||
|  | ||||
| import java.security.MessageDigest; | ||||
| import java.security.NoSuchAlgorithmException; | ||||
| import java.security.SecureRandom; | ||||
| import java.util.Random; | ||||
| import java.util.concurrent.ThreadLocalRandom; | ||||
| import com.stdiet.common.exception.UtilException; | ||||
|  | ||||
| /** | ||||
|  * 提供通用唯一识别码(universally unique identifier)(UUID)实现 | ||||
|  * | ||||
|  * @author stdiet | ||||
|  */ | ||||
| public final class UUID implements java.io.Serializable, Comparable<UUID> | ||||
| { | ||||
|     private static final long serialVersionUID = -1185015143654744140L; | ||||
|  | ||||
|     /** | ||||
|      * SecureRandom 的单例 | ||||
|      * | ||||
|      */ | ||||
|     private static class Holder | ||||
|     { | ||||
|         static final SecureRandom numberGenerator = getSecureRandom(); | ||||
|     } | ||||
|  | ||||
|     /** 此UUID的最高64有效位 */ | ||||
|     private final long mostSigBits; | ||||
|  | ||||
|     /** 此UUID的最低64有效位 */ | ||||
|     private final long leastSigBits; | ||||
|  | ||||
|     /** | ||||
|      * 私有构造 | ||||
|      *  | ||||
|      * @param data 数据 | ||||
|      */ | ||||
|     private UUID(byte[] data) | ||||
|     { | ||||
|         long msb = 0; | ||||
|         long lsb = 0; | ||||
|         assert data.length == 16 : "data must be 16 bytes in length"; | ||||
|         for (int i = 0; i < 8; i++) | ||||
|         { | ||||
|             msb = (msb << 8) | (data[i] & 0xff); | ||||
|         } | ||||
|         for (int i = 8; i < 16; i++) | ||||
|         { | ||||
|             lsb = (lsb << 8) | (data[i] & 0xff); | ||||
|         } | ||||
|         this.mostSigBits = msb; | ||||
|         this.leastSigBits = lsb; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 使用指定的数据构造新的 UUID。 | ||||
|      * | ||||
|      * @param mostSigBits 用于 {@code UUID} 的最高有效 64 位 | ||||
|      * @param leastSigBits 用于 {@code UUID} 的最低有效 64 位 | ||||
|      */ | ||||
|     public UUID(long mostSigBits, long leastSigBits) | ||||
|     { | ||||
|         this.mostSigBits = mostSigBits; | ||||
|         this.leastSigBits = leastSigBits; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 获取类型 4(伪随机生成的)UUID 的静态工厂。 使用加密的本地线程伪随机数生成器生成该 UUID。 | ||||
|      *  | ||||
|      * @return 随机生成的 {@code UUID} | ||||
|      */ | ||||
|     public static UUID fastUUID() | ||||
|     { | ||||
|         return randomUUID(false); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 获取类型 4(伪随机生成的)UUID 的静态工厂。 使用加密的强伪随机数生成器生成该 UUID。 | ||||
|      *  | ||||
|      * @return 随机生成的 {@code UUID} | ||||
|      */ | ||||
|     public static UUID randomUUID() | ||||
|     { | ||||
|         return randomUUID(true); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 获取类型 4(伪随机生成的)UUID 的静态工厂。 使用加密的强伪随机数生成器生成该 UUID。 | ||||
|      *  | ||||
|      * @param isSecure 是否使用{@link SecureRandom}如果是可以获得更安全的随机码,否则可以得到更好的性能 | ||||
|      * @return 随机生成的 {@code UUID} | ||||
|      */ | ||||
|     public static UUID randomUUID(boolean isSecure) | ||||
|     { | ||||
|         final Random ng = isSecure ? Holder.numberGenerator : getRandom(); | ||||
|  | ||||
|         byte[] randomBytes = new byte[16]; | ||||
|         ng.nextBytes(randomBytes); | ||||
|         randomBytes[6] &= 0x0f; /* clear version */ | ||||
|         randomBytes[6] |= 0x40; /* set to version 4 */ | ||||
|         randomBytes[8] &= 0x3f; /* clear variant */ | ||||
|         randomBytes[8] |= 0x80; /* set to IETF variant */ | ||||
|         return new UUID(randomBytes); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 根据指定的字节数组获取类型 3(基于名称的)UUID 的静态工厂。 | ||||
|      * | ||||
|      * @param name 用于构造 UUID 的字节数组。 | ||||
|      * | ||||
|      * @return 根据指定数组生成的 {@code UUID} | ||||
|      */ | ||||
|     public static UUID nameUUIDFromBytes(byte[] name) | ||||
|     { | ||||
|         MessageDigest md; | ||||
|         try | ||||
|         { | ||||
|             md = MessageDigest.getInstance("MD5"); | ||||
|         } | ||||
|         catch (NoSuchAlgorithmException nsae) | ||||
|         { | ||||
|             throw new InternalError("MD5 not supported"); | ||||
|         } | ||||
|         byte[] md5Bytes = md.digest(name); | ||||
|         md5Bytes[6] &= 0x0f; /* clear version */ | ||||
|         md5Bytes[6] |= 0x30; /* set to version 3 */ | ||||
|         md5Bytes[8] &= 0x3f; /* clear variant */ | ||||
|         md5Bytes[8] |= 0x80; /* set to IETF variant */ | ||||
|         return new UUID(md5Bytes); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 根据 {@link #toString()} 方法中描述的字符串标准表示形式创建{@code UUID}。 | ||||
|      * | ||||
|      * @param name 指定 {@code UUID} 字符串 | ||||
|      * @return 具有指定值的 {@code UUID} | ||||
|      * @throws IllegalArgumentException 如果 name 与 {@link #toString} 中描述的字符串表示形式不符抛出此异常 | ||||
|      * | ||||
|      */ | ||||
|     public static UUID fromString(String name) | ||||
|     { | ||||
|         String[] components = name.split("-"); | ||||
|         if (components.length != 5) | ||||
|         { | ||||
|             throw new IllegalArgumentException("Invalid UUID string: " + name); | ||||
|         } | ||||
|         for (int i = 0; i < 5; i++) | ||||
|         { | ||||
|             components[i] = "0x" + components[i]; | ||||
|         } | ||||
|  | ||||
|         long mostSigBits = Long.decode(components[0]).longValue(); | ||||
|         mostSigBits <<= 16; | ||||
|         mostSigBits |= Long.decode(components[1]).longValue(); | ||||
|         mostSigBits <<= 16; | ||||
|         mostSigBits |= Long.decode(components[2]).longValue(); | ||||
|  | ||||
|         long leastSigBits = Long.decode(components[3]).longValue(); | ||||
|         leastSigBits <<= 48; | ||||
|         leastSigBits |= Long.decode(components[4]).longValue(); | ||||
|  | ||||
|         return new UUID(mostSigBits, leastSigBits); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 返回此 UUID 的 128 位值中的最低有效 64 位。 | ||||
|      * | ||||
|      * @return 此 UUID 的 128 位值中的最低有效 64 位。 | ||||
|      */ | ||||
|     public long getLeastSignificantBits() | ||||
|     { | ||||
|         return leastSigBits; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 返回此 UUID 的 128 位值中的最高有效 64 位。 | ||||
|      * | ||||
|      * @return 此 UUID 的 128 位值中最高有效 64 位。 | ||||
|      */ | ||||
|     public long getMostSignificantBits() | ||||
|     { | ||||
|         return mostSigBits; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 与此 {@code UUID} 相关联的版本号. 版本号描述此 {@code UUID} 是如何生成的。 | ||||
|      * <p> | ||||
|      * 版本号具有以下含意: | ||||
|      * <ul> | ||||
|      * <li>1 基于时间的 UUID | ||||
|      * <li>2 DCE 安全 UUID | ||||
|      * <li>3 基于名称的 UUID | ||||
|      * <li>4 随机生成的 UUID | ||||
|      * </ul> | ||||
|      * | ||||
|      * @return 此 {@code UUID} 的版本号 | ||||
|      */ | ||||
|     public int version() | ||||
|     { | ||||
|         // Version is bits masked by 0x000000000000F000 in MS long | ||||
|         return (int) ((mostSigBits >> 12) & 0x0f); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 与此 {@code UUID} 相关联的变体号。变体号描述 {@code UUID} 的布局。 | ||||
|      * <p> | ||||
|      * 变体号具有以下含意: | ||||
|      * <ul> | ||||
|      * <li>0 为 NCS 向后兼容保留 | ||||
|      * <li>2 <a href="http://www.ietf.org/rfc/rfc4122.txt">IETF RFC 4122</a>(Leach-Salz), 用于此类 | ||||
|      * <li>6 保留,微软向后兼容 | ||||
|      * <li>7 保留供以后定义使用 | ||||
|      * </ul> | ||||
|      * | ||||
|      * @return 此 {@code UUID} 相关联的变体号 | ||||
|      */ | ||||
|     public int variant() | ||||
|     { | ||||
|         // This field is composed of a varying number of bits. | ||||
|         // 0 - - Reserved for NCS backward compatibility | ||||
|         // 1 0 - The IETF aka Leach-Salz variant (used by this class) | ||||
|         // 1 1 0 Reserved, Microsoft backward compatibility | ||||
|         // 1 1 1 Reserved for future definition. | ||||
|         return (int) ((leastSigBits >>> (64 - (leastSigBits >>> 62))) & (leastSigBits >> 63)); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 与此 UUID 相关联的时间戳值。 | ||||
|      * | ||||
|      * <p> | ||||
|      * 60 位的时间戳值根据此 {@code UUID} 的 time_low、time_mid 和 time_hi 字段构造。<br> | ||||
|      * 所得到的时间戳以 100 毫微秒为单位,从 UTC(通用协调时间) 1582 年 10 月 15 日零时开始。 | ||||
|      * | ||||
|      * <p> | ||||
|      * 时间戳值仅在在基于时间的 UUID(其 version 类型为 1)中才有意义。<br> | ||||
|      * 如果此 {@code UUID} 不是基于时间的 UUID,则此方法抛出 UnsupportedOperationException。 | ||||
|      * | ||||
|      * @throws UnsupportedOperationException 如果此 {@code UUID} 不是 version 为 1 的 UUID。 | ||||
|      */ | ||||
|     public long timestamp() throws UnsupportedOperationException | ||||
|     { | ||||
|         checkTimeBase(); | ||||
|         return (mostSigBits & 0x0FFFL) << 48// | ||||
|                 | ((mostSigBits >> 16) & 0x0FFFFL) << 32// | ||||
|                 | mostSigBits >>> 32; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 与此 UUID 相关联的时钟序列值。 | ||||
|      * | ||||
|      * <p> | ||||
|      * 14 位的时钟序列值根据此 UUID 的 clock_seq 字段构造。clock_seq 字段用于保证在基于时间的 UUID 中的时间唯一性。 | ||||
|      * <p> | ||||
|      * {@code clockSequence} 值仅在基于时间的 UUID(其 version 类型为 1)中才有意义。 如果此 UUID 不是基于时间的 UUID,则此方法抛出 | ||||
|      * UnsupportedOperationException。 | ||||
|      * | ||||
|      * @return 此 {@code UUID} 的时钟序列 | ||||
|      * | ||||
|      * @throws UnsupportedOperationException 如果此 UUID 的 version 不为 1 | ||||
|      */ | ||||
|     public int clockSequence() throws UnsupportedOperationException | ||||
|     { | ||||
|         checkTimeBase(); | ||||
|         return (int) ((leastSigBits & 0x3FFF000000000000L) >>> 48); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 与此 UUID 相关的节点值。 | ||||
|      * | ||||
|      * <p> | ||||
|      * 48 位的节点值根据此 UUID 的 node 字段构造。此字段旨在用于保存机器的 IEEE 802 地址,该地址用于生成此 UUID 以保证空间唯一性。 | ||||
|      * <p> | ||||
|      * 节点值仅在基于时间的 UUID(其 version 类型为 1)中才有意义。<br> | ||||
|      * 如果此 UUID 不是基于时间的 UUID,则此方法抛出 UnsupportedOperationException。 | ||||
|      * | ||||
|      * @return 此 {@code UUID} 的节点值 | ||||
|      * | ||||
|      * @throws UnsupportedOperationException 如果此 UUID 的 version 不为 1 | ||||
|      */ | ||||
|     public long node() throws UnsupportedOperationException | ||||
|     { | ||||
|         checkTimeBase(); | ||||
|         return leastSigBits & 0x0000FFFFFFFFFFFFL; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 返回此{@code UUID} 的字符串表现形式。 | ||||
|      * | ||||
|      * <p> | ||||
|      * UUID 的字符串表示形式由此 BNF 描述: | ||||
|      *  | ||||
|      * <pre> | ||||
|      * {@code | ||||
|      * UUID                   = <time_low>-<time_mid>-<time_high_and_version>-<variant_and_sequence>-<node> | ||||
|      * time_low               = 4*<hexOctet> | ||||
|      * time_mid               = 2*<hexOctet> | ||||
|      * time_high_and_version  = 2*<hexOctet> | ||||
|      * variant_and_sequence   = 2*<hexOctet> | ||||
|      * node                   = 6*<hexOctet> | ||||
|      * hexOctet               = <hexDigit><hexDigit> | ||||
|      * hexDigit               = [0-9a-fA-F] | ||||
|      * } | ||||
|      * </pre> | ||||
|      *  | ||||
|      * </blockquote> | ||||
|      * | ||||
|      * @return 此{@code UUID} 的字符串表现形式 | ||||
|      * @see #toString(boolean) | ||||
|      */ | ||||
|     @Override | ||||
|     public String toString() | ||||
|     { | ||||
|         return toString(false); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 返回此{@code UUID} 的字符串表现形式。 | ||||
|      * | ||||
|      * <p> | ||||
|      * UUID 的字符串表示形式由此 BNF 描述: | ||||
|      *  | ||||
|      * <pre> | ||||
|      * {@code | ||||
|      * UUID                   = <time_low>-<time_mid>-<time_high_and_version>-<variant_and_sequence>-<node> | ||||
|      * time_low               = 4*<hexOctet> | ||||
|      * time_mid               = 2*<hexOctet> | ||||
|      * time_high_and_version  = 2*<hexOctet> | ||||
|      * variant_and_sequence   = 2*<hexOctet> | ||||
|      * node                   = 6*<hexOctet> | ||||
|      * hexOctet               = <hexDigit><hexDigit> | ||||
|      * hexDigit               = [0-9a-fA-F] | ||||
|      * } | ||||
|      * </pre> | ||||
|      *  | ||||
|      * </blockquote> | ||||
|      * | ||||
|      * @param isSimple 是否简单模式,简单模式为不带'-'的UUID字符串 | ||||
|      * @return 此{@code UUID} 的字符串表现形式 | ||||
|      */ | ||||
|     public String toString(boolean isSimple) | ||||
|     { | ||||
|         final StringBuilder builder = new StringBuilder(isSimple ? 32 : 36); | ||||
|         // time_low | ||||
|         builder.append(digits(mostSigBits >> 32, 8)); | ||||
|         if (false == isSimple) | ||||
|         { | ||||
|             builder.append('-'); | ||||
|         } | ||||
|         // time_mid | ||||
|         builder.append(digits(mostSigBits >> 16, 4)); | ||||
|         if (false == isSimple) | ||||
|         { | ||||
|             builder.append('-'); | ||||
|         } | ||||
|         // time_high_and_version | ||||
|         builder.append(digits(mostSigBits, 4)); | ||||
|         if (false == isSimple) | ||||
|         { | ||||
|             builder.append('-'); | ||||
|         } | ||||
|         // variant_and_sequence | ||||
|         builder.append(digits(leastSigBits >> 48, 4)); | ||||
|         if (false == isSimple) | ||||
|         { | ||||
|             builder.append('-'); | ||||
|         } | ||||
|         // node | ||||
|         builder.append(digits(leastSigBits, 12)); | ||||
|  | ||||
|         return builder.toString(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 返回此 UUID 的哈希码。 | ||||
|      * | ||||
|      * @return UUID 的哈希码值。 | ||||
|      */ | ||||
|     @Override | ||||
|     public int hashCode() | ||||
|     { | ||||
|         long hilo = mostSigBits ^ leastSigBits; | ||||
|         return ((int) (hilo >> 32)) ^ (int) hilo; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 将此对象与指定对象比较。 | ||||
|      * <p> | ||||
|      * 当且仅当参数不为 {@code null}、而是一个 UUID 对象、具有与此 UUID 相同的 varriant、包含相同的值(每一位均相同)时,结果才为 {@code true}。 | ||||
|      * | ||||
|      * @param obj 要与之比较的对象 | ||||
|      * | ||||
|      * @return 如果对象相同,则返回 {@code true};否则返回 {@code false} | ||||
|      */ | ||||
|     @Override | ||||
|     public boolean equals(Object obj) | ||||
|     { | ||||
|         if ((null == obj) || (obj.getClass() != UUID.class)) | ||||
|         { | ||||
|             return false; | ||||
|         } | ||||
|         UUID id = (UUID) obj; | ||||
|         return (mostSigBits == id.mostSigBits && leastSigBits == id.leastSigBits); | ||||
|     } | ||||
|  | ||||
|     // Comparison Operations | ||||
|  | ||||
|     /** | ||||
|      * 将此 UUID 与指定的 UUID 比较。 | ||||
|      * | ||||
|      * <p> | ||||
|      * 如果两个 UUID 不同,且第一个 UUID 的最高有效字段大于第二个 UUID 的对应字段,则第一个 UUID 大于第二个 UUID。 | ||||
|      * | ||||
|      * @param val 与此 UUID 比较的 UUID | ||||
|      * | ||||
|      * @return 在此 UUID 小于、等于或大于 val 时,分别返回 -1、0 或 1。 | ||||
|      * | ||||
|      */ | ||||
|     @Override | ||||
|     public int compareTo(UUID val) | ||||
|     { | ||||
|         // The ordering is intentionally set up so that the UUIDs | ||||
|         // can simply be numerically compared as two numbers | ||||
|         return (this.mostSigBits < val.mostSigBits ? -1 : // | ||||
|                 (this.mostSigBits > val.mostSigBits ? 1 : // | ||||
|                         (this.leastSigBits < val.leastSigBits ? -1 : // | ||||
|                                 (this.leastSigBits > val.leastSigBits ? 1 : // | ||||
|                                         0)))); | ||||
|     } | ||||
|  | ||||
|     // ------------------------------------------------------------------------------------------------------------------- | ||||
|     // Private method start | ||||
|     /** | ||||
|      * 返回指定数字对应的hex值 | ||||
|      *  | ||||
|      * @param val 值 | ||||
|      * @param digits 位 | ||||
|      * @return 值 | ||||
|      */ | ||||
|     private static String digits(long val, int digits) | ||||
|     { | ||||
|         long hi = 1L << (digits * 4); | ||||
|         return Long.toHexString(hi | (val & (hi - 1))).substring(1); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 检查是否为time-based版本UUID | ||||
|      */ | ||||
|     private void checkTimeBase() | ||||
|     { | ||||
|         if (version() != 1) | ||||
|         { | ||||
|             throw new UnsupportedOperationException("Not a time-based UUID"); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 获取{@link SecureRandom},类提供加密的强随机数生成器 (RNG) | ||||
|      *  | ||||
|      * @return {@link SecureRandom} | ||||
|      */ | ||||
|     public static SecureRandom getSecureRandom() | ||||
|     { | ||||
|         try | ||||
|         { | ||||
|             return SecureRandom.getInstance("SHA1PRNG"); | ||||
|         } | ||||
|         catch (NoSuchAlgorithmException e) | ||||
|         { | ||||
|             throw new UtilException(e); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 获取随机数生成器对象<br> | ||||
|      * ThreadLocalRandom是JDK 7之后提供并发产生随机数,能够解决多个线程发生的竞争争夺。 | ||||
|      *  | ||||
|      * @return {@link ThreadLocalRandom} | ||||
|      */ | ||||
|     public static ThreadLocalRandom getRandom() | ||||
|     { | ||||
|         return ThreadLocalRandom.current(); | ||||
|     } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user