Commit 66481b37 by wangdan

第一次提交项目

parents

Too many changes to show.

To preserve performance only 1000 of 1000+ files are displayed.

.idea
logs
target
*.iml
*.log
## minio存放路径
1. lccet/base/banner //轮播图
2. lccet/base/link //友情链接图
3. lccet/base/enterprise/info //企业logo,营业执照,承诺函……
4. lccet/base/enterprise/product //企业产品图片
5. lccet/base/enterprise/report //企业报告(碳足迹报告,epd报告)
6. lccet/base/enterprise/feedback //专家审核反馈意见的附件(lca和epd的审核)
7. lccet/cms/news/logo //新闻logo
8. lccet/cms/news/content //新闻内容图片
9. lccet/cms/down/ //上传文件,word,音视频,各种文档
10. lccet/cms/news/content //新闻内容图片
## 系统模块
~~~
com.vctgo
├── vctgo-ui // 前端框架 [80]
├── vctgo-gateway // 网关模块 [38080]
├── vctgo-auth // 认证中心 [39200]
├── vctgo-api // 接口模块
│ └── vctgo-api-system // 系统接口
├── vctgo-common // 通用模块
│ └── vctgo-common-core // 核心模块
│ └── vctgo-common-datascope // 权限范围
│ └── vctgo-common-datasource // 多数据源
│ └── vctgo-common-log // 日志记录
│ └── vctgo-common-redis // 缓存服务
│ └── vctgo-common-security // 安全模块
│ └── vctgo-common-swagger // 系统接口
│ └── vctgo-common-message // 消息通知
│ └── vctgo-common-mybatisplus // mybatis增强组件
├── vctgo-modules // 业务模块
│ └── vctgo-system // 系统模块 [39201]
│ └── vctgo-gen // 代码生成 [39202]
│ └── vctgo-file // 文件服务 [39300]
├── vctgo-visual // 图形化管理模块
│ └── vctgo-visual-monitor // 监控中心 [39100]
├──pom.xml // 公共依赖
~~~
## 内置功能
1. 租户管理:配置系统租户,支持 SaaS 场景下的多租户功能。
2. 配置租户套餐:自定每个租户的菜单、操作、按钮的权限。
3. 用户管理:用户是系统操作者,该功能主要完成系统用户配置。
4. 部门管理:配置系统组织机构(公司、部门、小组),树结构展现支持数据权限。
5. 岗位管理:配置系统用户所属担任职务。
6. 菜单管理:配置系统菜单,操作权限,按钮权限标识等。
7. 角色管理:角色菜单权限分配、设置角色按机构进行数据范围权限划分。
8. 字典管理:对系统中经常使用的一些较为固定的数据进行维护。
9. 参数管理:对系统动态配置常用参数。
10. 通知公告:系统通知公告信息发布维护。
11. 操作日志:系统正常操作日志记录和查询;系统异常信息日志记录和查询。
12. 登录日志:系统登录日志记录查询包含登录异常。
13. 在线用户:当前系统中活跃用户状态监控。
14. 代码生成:前后端代码的生成(java、html、xml、sql)支持CRUD下载 。
15. 系统接口:根据业务代码自动生成相关的api接口文档。
16. 服务监控:监视当前系统CPU、内存、磁盘、堆栈等相关信息。
17. 在线构建器:拖动表单元素生成相应的HTML代码。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>com.lccet</groupId>
<artifactId>lccet-api</artifactId>
<version>1.2.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>lccet-api-system</artifactId>
<description>
lccet-api-system系统接口模块
</description>
<dependencies>
<!-- lccet Common Core-->
<dependency>
<groupId>com.lccet</groupId>
<artifactId>lccet-common-core</artifactId>
</dependency>
</dependencies>
</project>
package com.lccet.system.api;
import com.lccet.common.core.constant.SecurityConstants;
import com.lccet.common.core.constant.ServiceNameConstants;
import com.lccet.common.core.domain.R;
import com.lccet.common.core.web.domain.AjaxResult;
import com.lccet.system.api.domain.SysDictData;
import com.lccet.system.api.factory.RemoteUserFallbackFactory;
import com.lccet.system.api.model.LoginUser;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestHeader;
import java.util.List;
/**
* 字典服务
*
*
*/
@FeignClient(contextId = "remoteDictDataService", value = ServiceNameConstants.SYSTEM_SERVICE, fallbackFactory = RemoteUserFallbackFactory.class)
public interface RemoteDictDataService {
/**
* 根据字典类型查询字典值集合
* @param dictType
* @return
*/
@GetMapping("/dict/data/type/{dictType}")
AjaxResult getDictDatasByType(@PathVariable("dictType") String dictType, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
}
package com.lccet.system.api;
import com.lccet.system.api.domain.SysFile;
import com.lccet.system.api.factory.RemoteFileFallbackFactory;
import org.apache.ibatis.annotations.Param;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.multipart.MultipartFile;
import com.lccet.common.core.constant.ServiceNameConstants;
import com.lccet.common.core.domain.R;
/**
* 文件服务
*
* @author vctgo
*/
@FeignClient(contextId = "remoteFileService", value = ServiceNameConstants.FILE_SERVICE, fallbackFactory = RemoteFileFallbackFactory.class)
public interface RemoteFileService {
/**
* 上传文件
*
* @param file 文件信息
* @return 结果
*/
@PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public R<SysFile> upload(@RequestPart(value = "file") MultipartFile file);
/**
* 上传文件
*
* @param file 文件信息
* @param target 文件路径(如:base/enterprise/product)
* @return 结果
*/
@PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public R<SysFile> upload(@RequestPart(value = "file") MultipartFile file, @RequestParam("target") String target);
}
package com.lccet.system.api;
import com.lccet.system.api.domain.SysLogininfor;
import com.lccet.system.api.domain.SysOperLog;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import com.lccet.common.core.constant.SecurityConstants;
import com.lccet.common.core.constant.ServiceNameConstants;
import com.lccet.common.core.domain.R;
import com.lccet.system.api.factory.RemoteLogFallbackFactory;
/**
* 日志服务
*
* @author vctgo
*/
@FeignClient(contextId = "remoteLogService", value = ServiceNameConstants.SYSTEM_SERVICE, fallbackFactory = RemoteLogFallbackFactory.class)
public interface RemoteLogService
{
/**
* 保存系统日志
*
* @param sysOperLog 日志实体
* @param source 请求来源
* @return 结果
*/
@PostMapping("/operlog")
public R<Boolean> saveLog(@RequestBody SysOperLog sysOperLog, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
/**
* 保存访问记录
*
* @param sysLogininfor 访问实体
* @param source 请求来源
* @return 结果
*/
@PostMapping("/logininfor")
public R<Boolean> saveLogininfor(@RequestBody SysLogininfor sysLogininfor, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
}
package com.lccet.system.api;
import com.lccet.system.api.model.LoginUser;
import com.lccet.system.api.domain.SysUser;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import com.lccet.common.core.constant.SecurityConstants;
import com.lccet.common.core.constant.ServiceNameConstants;
import com.lccet.common.core.domain.R;
import com.lccet.system.api.factory.RemoteUserFallbackFactory;
/**
* 用户服务
*
* @author vctgo
*/
@FeignClient(contextId = "remoteUserService", value = ServiceNameConstants.SYSTEM_SERVICE, fallbackFactory = RemoteUserFallbackFactory.class)
public interface RemoteUserService
{
/**
* 通过用户名查询用户信息
*
* @param username 用户名
* @param source 请求来源
* @return 结果
*/
@GetMapping("/user/info/{username}")
R<LoginUser> getUserInfo(@PathVariable("username") String username, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
/**
* 注册用户信息
*
* @param sysUser 用户信息
* @param source 请求来源
* @return 结果
*/
@PostMapping("/user/register")
R<Boolean> registerUserInfo(@RequestBody SysUser sysUser, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
/**
* 根据用户名更新最后登录时间
* @param username
* @return
*/
@GetMapping("/user/updateLoginDate/{username}")
R<Boolean> updateLoginDate(@PathVariable("username") String username, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
/**
* 更新登录失败次数
* @param username
* @return
*/
@GetMapping("/user/updateLoginErrorCount/{username}")
R<Boolean> updateLoginErrorCount(@PathVariable("username") String username, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
}
package com.lccet.system.api.domain;
import lombok.Data;
/**
* @description:
* @author: xuchao
* @time: 2022/4/18 13:18
*/
@Data
public class SmsResult {
private String success;
private String code;
private String message;
private String data;
private String extras;
private String timestamp;
}
package com.lccet.system.api.domain;
import java.util.ArrayList;
import java.util.List;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.lccet.common.core.web.domain.TenantEntity;
import lombok.Data;
/**
* 部门表 sys_dept
*
* @author vctgo
*/
@Data
@TableName("sys_dept")
public class SysDept extends TenantEntity
{
private static final long serialVersionUID = 1L;
/** 部门ID */
@TableId
private Long deptId;
/** 父部门ID */
private Long parentId;
/** 祖级列表 */
private String ancestors;
/** 部门名称 */
@NotBlank(message = "部门名称不能为空")
@Size(min = 0, max = 30, message = "部门名称长度不能超过30个字符")
private String deptName;
/** 显示顺序 */
@NotNull(message = "显示顺序不能为空")
private Integer orderNum;
/** 负责人 */
private String leader;
/** 联系电话 */
@Size(min = 0, max = 11, message = "联系电话长度不能超过11个字符")
private String phone;
/** 邮箱 */
@Email(message = "邮箱格式不正确")
@Size(min = 0, max = 50, message = "邮箱长度不能超过50个字符")
private String email;
/** 部门状态:0正常,1停用 */
private String status;
/** 删除标志(0代表存在 1代表删除) */
private String delFlag;
@TableField(exist = false)
/** 父部门名称 */
private String parentName;
@TableField(exist = false)
/** 子部门 */
private List<SysDept> children = new ArrayList<SysDept>();
}
package com.lccet.system.api.domain;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import com.lccet.common.core.annotation.Excel;
import com.lccet.common.core.annotation.Excel.ColumnType;
import com.lccet.common.core.constant.UserConstants;
import com.lccet.common.core.web.domain.BaseEntity;
/**
* 字典数据表 sys_dict_data
*
* @author vctgo
*/
@Data
@TableName("sys_dict_data")
public class SysDictData extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 字典编码 */
@Excel(name = "字典编码", cellType = ColumnType.NUMERIC)
@TableId
private Long dictCode;
/** 字典排序 */
@Excel(name = "字典排序", cellType = ColumnType.NUMERIC)
private Long dictSort;
/** 字典标签 */
@Excel(name = "字典标签")
@NotBlank(message = "字典标签不能为空")
@Size(min = 0, max = 100, message = "字典标签长度不能超过100个字符")
private String dictLabel;
/** 字典标签 */
@Excel(name = "字典标签")
@NotBlank(message = "字典标签不能为空")
@Size(min = 0, max = 100, message = "字典标签长度不能超过100个字符")
private String dictLabelEn;
/** 字典键值 */
@Excel(name = "字典键值")
@NotBlank(message = "字典键值不能为空")
@Size(min = 0, max = 100, message = "字典键值长度不能超过100个字符")
private String dictValue;
/** 字典类型 */
@Excel(name = "字典类型")
@NotBlank(message = "字典类型不能为空")
@Size(min = 0, max = 100, message = "字典类型长度不能超过100个字符")
private String dictType;
/** 样式属性(其他样式扩展) */
@Size(min = 0, max = 100, message = "样式属性长度不能超过100个字符")
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 boolean getDefault()
{
return UserConstants.YES.equals(this.isDefault) ? true : false;
}
}
package com.lccet.system.api.domain;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import com.lccet.common.core.annotation.Excel;
import com.lccet.common.core.annotation.Excel.ColumnType;
import com.lccet.common.core.web.domain.BaseEntity;
/**
* 字典类型表 sys_dict_type
*
* @author vctgo
*/
@Data
@TableName("sys_dict_type")
public class SysDictType extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 字典主键 */
@Excel(name = "字典主键", cellType = ColumnType.NUMERIC)
@TableId
private Long dictId;
/** 字典名称 */
@Excel(name = "字典名称")
@NotBlank(message = "字典名称不能为空")
@Size(min = 0, max = 100, message = "字典类型名称长度不能超过100个字符")
private String dictName;
/** 字典类型 */
@Excel(name = "字典类型")
@NotBlank(message = "字典类型不能为空")
@Size(min = 0, max = 100, message = "字典类型类型长度不能超过100个字符")
@Pattern(regexp = "^[a-z][a-z0-9_]*$", message = "字典类型必须以字母开头,且只能为(小写字母,数字,下滑线)")
private String dictType;
/** 状态(0正常 1停用) */
@Excel(name = "状态", readConverterExp = "0=正常,1=停用")
private String status;
}
package com.lccet.system.api.domain;
import lombok.Data;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
/**
* 文件信息
*
* @author vctgo
*/
@Data
public class SysFile
{
/**
* 文件名称
*/
private String name;
/**
* 文件地址
*/
private String url;
}
package com.lccet.system.api.domain;
import java.util.Date;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.lccet.common.core.annotation.Excel;
import com.lccet.common.core.annotation.Excel.ColumnType;
import com.lccet.common.core.web.domain.TenantEntity;
import lombok.Data;
/**
* 系统访问记录表 sys_logininfor
*
* @author vctgo
*/
@Data
@TableName("sys_logininfor")
public class SysLogininfor extends TenantEntity
{
private static final long serialVersionUID = 1L;
/** ID */
@Excel(name = "序号", cellType = ColumnType.NUMERIC)
@TableId
private Long infoId;
/** 用户账号 */
@Excel(name = "用户账号")
private String userName;
/** 状态 0成功 1失败 */
@Excel(name = "状态", readConverterExp = "0=成功,1=失败")
private String status;
/** 地址 */
@Excel(name = "地址")
private String ipaddr;
/** 描述 */
@Excel(name = "描述")
private String msg;
/** 访问时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Excel(name = "访问时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
private Date accessTime;
}
package com.lccet.system.api.domain;
import java.util.Date;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.lccet.common.core.annotation.Excel;
import com.lccet.common.core.annotation.Excel.ColumnType;
import com.lccet.common.core.web.domain.TenantEntity;
import lombok.Data;
/**
* 操作日志记录表 sys_oper_log
*
* @author vctgo
*/
@Data
@TableName("sys_oper_log")
public class SysOperLog extends TenantEntity
{
private static final long serialVersionUID = 1L;
/** 日志主键 */
@Excel(name = "操作序号", cellType = ColumnType.NUMERIC)
@TableId
private Long operId;
/** 操作模块 */
@Excel(name = "操作模块")
private String title;
/** 业务类型(0其它 1新增 2修改 3删除) */
@Excel(name = "业务类型", readConverterExp = "0=其它,1=新增,2=修改,3=删除,4=授权,5=导出,6=导入,7=强退,8=生成代码,9=清空数据")
private Integer businessType;
/** 业务类型数组 */
private Integer[] businessTypes;
/** 请求方法 */
@Excel(name = "请求方法")
private String method;
/** 请求方式 */
@Excel(name = "请求方式")
private String requestMethod;
/** 操作类别(0其它 1后台用户 2手机端用户) */
@Excel(name = "操作类别", readConverterExp = "0=其它,1=后台用户,2=手机端用户")
private Integer operatorType;
/** 操作人员 */
@Excel(name = "操作人员")
private String operName;
/** 部门名称 */
@Excel(name = "部门名称")
private String deptName;
/** 请求url */
@Excel(name = "请求地址")
private String operUrl;
/** 操作地址 */
@Excel(name = "操作地址")
private String operIp;
/** 请求参数 */
@Excel(name = "请求参数")
private String operParam;
/** 返回参数 */
@Excel(name = "返回参数")
private String jsonResult;
/** 操作状态(0正常 1异常) */
@Excel(name = "状态", readConverterExp = "0=正常,1=异常")
private Integer status;
/** 错误消息 */
@Excel(name = "错误消息")
private String errorMsg;
/** 操作时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Excel(name = "操作时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
private Date operTime;
}
package com.lccet.system.api.domain;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.lccet.common.core.web.domain.TenantEntity;
import lombok.Data;
import lombok.NoArgsConstructor;
import com.lccet.common.core.annotation.Excel;
import com.lccet.common.core.annotation.Excel.ColumnType;
/**
* 角色表 sys_role
*
* @author vctgo
*/
@Data
@NoArgsConstructor
@TableName("sys_role")
public class SysRole extends TenantEntity
{
private static final long serialVersionUID = 1L;
/** 角色ID */
@Excel(name = "角色序号", cellType = ColumnType.NUMERIC)
@TableId
private Long roleId;
/** 角色名称 */
@Excel(name = "角色名称")
@NotBlank(message = "角色名称不能为空")
@Size(min = 0, max = 30, message = "角色名称长度不能超过30个字符")
private String roleName;
/** 角色权限 */
@Excel(name = "角色权限")
@NotBlank(message = "权限字符不能为空")
@Size(min = 0, max = 100, message = "权限字符长度不能超过100个字符")
private String roleKey;
/** 角色排序 */
@Excel(name = "角色排序")
@NotBlank(message = "显示顺序不能为空")
private String roleSort;
/** 数据范围(1:所有数据权限;2:自定义数据权限;3:本部门数据权限;4:本部门及以下数据权限;5:仅本人数据权限) */
@Excel(name = "数据范围", readConverterExp = "1=所有数据权限,2=自定义数据权限,3=本部门数据权限,4=本部门及以下数据权限,5=仅本人数据权限")
private String dataScope;
/** 菜单树选择项是否关联显示( 0:父子不互相关联显示 1:父子互相关联显示) */
private boolean menuCheckStrictly;
/** 部门树选择项是否关联显示(0:父子不互相关联显示 1:父子互相关联显示 ) */
private boolean deptCheckStrictly;
/** 是否管理员角色(0 不是 1是) */
private boolean adminRole;
/** 角色状态(0正常 1停用) */
@Excel(name = "角色状态", readConverterExp = "0=正常,1=停用")
private String status;
/** 删除标志(0代表存在 1代表删除) */
private String delFlag;
/** 备注 */
private String remark;
@TableField(exist = false)
/** 用户是否存在此角色标识 默认不存在 */
private boolean flag = false;
@TableField(exist = false)
/** 菜单组 */
private Long[] menuIds;
@TableField(exist = false)
/** 部门组(数据权限) */
private Long[] deptIds;
public SysRole(Long roleId)
{
this.roleId = roleId;
}
public boolean isAdmin()
{
return isAdmin(this.roleId);
}
public static boolean isAdmin(Long roleId)
{
return roleId != null && 1L == roleId;
}
}
package com.lccet.system.api.domain;
import java.util.Date;
import java.util.List;
import javax.validation.constraints.*;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.lccet.common.core.web.domain.TenantEntity;
import lombok.Data;
import com.lccet.common.core.annotation.Excel;
import com.lccet.common.core.annotation.Excel.ColumnType;
import com.lccet.common.core.annotation.Excel.Type;
import com.lccet.common.core.annotation.Excels;
import com.lccet.common.core.xss.Xss;
import lombok.NoArgsConstructor;
/**
* 用户对象 sys_user
*
* @author vctgo
*/
@Data
@NoArgsConstructor
@TableName("sys_user")
public class SysUser extends TenantEntity
{
private static final long serialVersionUID = 1L;
/** 用户ID */
@Excel(name = "用户序号", cellType = ColumnType.NUMERIC, prompt = "用户编号")
@TableId
private Long userId;
/** 部门ID */
@Excel(name = "部门编号", type = Type.IMPORT)
private Long deptId;
/** 用户账号 */
@Excel(name = "登录名称")
@Xss(message = "用户账号不能包含脚本字符")
@NotBlank(message = "用户账号不能为空")
@Size(min = 0, max = 30, message = "用户账号长度不能超过30个字符")
private String userName;
/** 用户昵称 */
@Excel(name = "用户名称")
@Xss(message = "用户昵称不能包含脚本字符")
@Size(min = 0, max = 30, message = "用户昵称长度不能超过30个字符")
private String nickName;
/** 用户类型 */
@Excel(name = "用户类型")
@Xss(message = "用户类型不能包含脚本字符")
@Size(min = 0, max = 2, message = "用户类型长度不能超过2个字符")
private String userType;
/** 工作单位 */
@Excel(name = "")
@Xss(message = "工作单位不能包含脚本字符")
@Size(min = 0, max = 2, message = "工作单位长度不能超过50个字符")
private String company;
/** 用户邮箱 */
@Excel(name = "用户邮箱")
@Email(message = "邮箱格式不正确")
@Size(min = 0, max = 50, message = "邮箱长度不能超过50个字符")
private String email;
/** 用户邮箱 */
@Email(message = "邮箱格式不正确")
@Size(min = 0, max = 50, message = "邮箱长度不能超过50个字符")
@TableField(exist = false)
private String newEmail;
/** 手机号码 */
@Excel(name = "手机号码")
@Size(min = 0, max = 11, message = "手机号码长度不能超过11个字符")
private String phonenumber;
/** 用户性别 */
@Excel(name = "用户性别", readConverterExp = "0=男,1=女,2=未知")
private String sex;
/** 用户头像 */
private String avatar;
/** 密码 */
private String password;
/** 帐号状态(0正常 1停用) */
@Excel(name = "帐号状态", readConverterExp = "0=正常,1=停用")
private String status;
/** 删除标志(0代表存在 1代表删除) */
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;
@TableField(exist = false)
/** 部门对象 */
@Excels({
@Excel(name = "部门名称", targetAttr = "deptName", type = Type.EXPORT),
@Excel(name = "部门负责人", targetAttr = "leader", type = Type.EXPORT)
})
private SysDept dept;
@TableField(exist = false)
/** 角色对象 */
private List<SysRole> roles;
@TableField(exist = false)
/** 角色组 */
private Long[] roleIds;
@TableField(exist = false)
/** 岗位组 */
private Long[] postIds;
@TableField(exist = false)
/** 角色ID */
private Long roleId;
/** 注册验证码缓存key */
@TableField(exist = false)
private String verifyKey;
/** 用户输入的验证码 */
@TableField(exist = false)
private String verifyCode;
/** 用户输入的新密码 */
@TableField(exist = false)
private String newPassword;
public SysUser(Long userId)
{
this.userId = userId;
}
public boolean isAdmin()
{
return isAdmin(this.userId);
}
public static boolean isAdmin(Long userId)
{
return userId != null && 1L == userId;
}
private int loginErrorCount;
private Date lockTime;
}
package com.lccet.system.api.factory;
import com.lccet.system.api.RemoteFileService;
import com.lccet.system.api.domain.SysFile;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.openfeign.FallbackFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import com.lccet.common.core.domain.R;
/**
* 文件服务降级处理
*
* @author vctgo
*/
@Component
public class RemoteFileFallbackFactory implements FallbackFactory<RemoteFileService>
{
private static final Logger log = LoggerFactory.getLogger(RemoteFileFallbackFactory.class);
@Override
public RemoteFileService create(Throwable throwable)
{
log.error("文件服务调用失败:{}", throwable.getMessage());
return new RemoteFileService()
{
@Override
public R<SysFile> upload(MultipartFile file) {
return R.fail("上传文件失败:" + throwable.getMessage());
}
@Override
public R<SysFile> upload(MultipartFile file, String target) {
return R.fail("上传文件失败:" + throwable.getMessage());
}
};
}
}
package com.lccet.system.api.factory;
import com.lccet.system.api.RemoteLogService;
import com.lccet.system.api.domain.SysLogininfor;
import com.lccet.system.api.domain.SysOperLog;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.openfeign.FallbackFactory;
import org.springframework.stereotype.Component;
import com.lccet.common.core.domain.R;
/**
* 日志服务降级处理
*
* @author vctgo
*/
@Component
public class RemoteLogFallbackFactory implements FallbackFactory<RemoteLogService>
{
private static final Logger log = LoggerFactory.getLogger(RemoteLogFallbackFactory.class);
@Override
public RemoteLogService create(Throwable throwable)
{
log.error("日志服务调用失败:{}", throwable.getMessage());
return new RemoteLogService()
{
@Override
public R<Boolean> saveLog(SysOperLog sysOperLog, String source)
{
return null;
}
@Override
public R<Boolean> saveLogininfor(SysLogininfor sysLogininfor, String source)
{
return null;
}
};
}
}
package com.lccet.system.api.factory;
import com.lccet.system.api.RemoteUserService;
import com.lccet.system.api.domain.SysUser;
import com.lccet.system.api.model.LoginUser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.openfeign.FallbackFactory;
import org.springframework.stereotype.Component;
import com.lccet.common.core.domain.R;
/**
* 用户服务降级处理
*
* @author vctgo
*/
@Component
public class RemoteUserFallbackFactory implements FallbackFactory<RemoteUserService>
{
private static final Logger log = LoggerFactory.getLogger(RemoteUserFallbackFactory.class);
@Override
public RemoteUserService create(Throwable throwable)
{
log.error("用户服务调用失败:{}", throwable.getMessage());
return new RemoteUserService()
{
@Override
public R<LoginUser> getUserInfo(String username, String source)
{
return R.fail("获取用户失败:" + throwable.getMessage());
}
@Override
public R<Boolean> registerUserInfo(SysUser sysUser, String source)
{
return R.fail("注册用户失败:" + throwable.getMessage());
}
@Override
public R<Boolean> updateLoginDate(String username, String source) {
return R.fail("更新最后登录时间失败:" + throwable.getMessage());
}
@Override
public R<Boolean> updateLoginErrorCount(String username, String source) {
return R.fail("更新登录失败次数:" + throwable.getMessage());
}
};
}
}
package com.lccet.system.api.model;
import java.io.Serializable;
import java.util.Date;
import java.util.Set;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.lccet.system.api.domain.SysUser;
import lombok.Data;
/**
* 用户信息
*
* @author vctgo
*/
@Data
public class LoginUser implements Serializable
{
private static final long serialVersionUID = 1L;
/**
* 用户唯一标识
*/
private String token;
/**
* 用户名id
*/
private Long userid;
/**
* 用户名
*/
private String username;
/**
* 登录时间
*/
private Long loginTime;
/**
* 过期时间
*/
private Long expireTime;
/**
* 登录IP地址
*/
private String ipaddr;
/**
* 登录地点
*/
private String loginLocation;
/**
* 浏览器类型
*/
private String browser;
/**
* 操作系统
*/
private String os;
/**
* 权限列表
*/
private Set<String> permissions;
/**
* 角色列表
*/
private Set<String> roles;
/**
* 用户信息
*/
private SysUser sysUser;
/**
* 租户租赁截止日期--dhr
*/
private Date tenantEndDate;
/**
* 租户状态
*/
private Integer tenantStatus;
/**
* 登录错误次数
*/
private int loginErrorCount;
/**
* 开始锁定时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date lockTime;
}
com.lccet.system.api.factory.RemoteUserFallbackFactory
com.lccet.system.api.factory.RemoteLogFallbackFactory
com.lccet.system.api.factory.RemoteFileFallbackFactory
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>com.lccet</groupId>
<artifactId>lccet</artifactId>
<version>1.2.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<modules>
<module>lccet-api-system</module>
</modules>
<artifactId>lccet-api</artifactId>
<packaging>pom</packaging>
<description>
lccet-api系统接口
</description>
</project>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>com.lccet</groupId>
<artifactId>lccet</artifactId>
<version>1.2.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>lccet-auth</artifactId>
<description>
lccet-auth认证授权中心
</description>
<dependencies>
<!-- SpringCloud Alibaba Nacos -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- SpringCloud Alibaba Nacos Config -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!-- SpringCloud Alibaba Sentinel -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<!-- SpringBoot Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- SpringBoot Actuator -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- lccet Common Security-->
<dependency>
<groupId>com.lccet</groupId>
<artifactId>lccet-common-security</artifactId>
</dependency>
</dependencies>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
package com.lccet.auth;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import com.lccet.common.security.annotation.EnableVctgoFeignClients;
/**
* 认证授权中心
*
* @author vctgo
*/
@Slf4j
@EnableVctgoFeignClients
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class })
public class LccetAuthApplication
{
public static void main(String[] args)
{
SpringApplication.run(LccetAuthApplication.class, args);
log.info(" (^^)/▽ ▽\(^^)------vctgo权限启动成功---(^_^)/★\(^_^) \n");
}
}
package com.lccet.auth.controller;
import javax.servlet.http.HttpServletRequest;
import com.lccet.auth.form.LoginBody;
import com.lccet.auth.form.RegisterBody;
import com.lccet.auth.service.SysLoginService;
import com.lccet.common.core.constant.CacheConstants;
import com.lccet.common.core.context.SecurityContextHolder;
import com.lccet.common.core.utils.ServletUtils;
import com.lccet.common.redis.service.RedisService;
import jdk.nashorn.internal.ir.RuntimeNode;
import jdk.nashorn.internal.runtime.logging.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.lccet.common.core.domain.R;
import com.lccet.common.core.utils.JwtUtils;
import com.lccet.common.core.utils.StringUtils;
import com.lccet.common.security.auth.AuthUtil;
import com.lccet.common.security.service.TokenService;
import com.lccet.common.security.utils.SecurityUtils;
import com.lccet.system.api.model.LoginUser;
import java.util.Collection;
import java.util.Map;
/**
* token 控制
*
* @author vctgo
*/
@RestController
public class TokenController
{
@Autowired
private TokenService tokenService;
@Autowired
private SysLoginService sysLoginService;
@Autowired
private RedisService redisService;
@PostMapping("login")
public R<?> login(@RequestBody LoginBody form,HttpServletRequest request) {
// 用户登录
LoginUser userInfo = sysLoginService.login(form.getUsername(), form.getPassword());
//限制同一个账号只能在一点登录
// Collection<String> keys = redisService.keys(CacheConstants.LOGIN_TOKEN_KEY + "*");
// for (String key : keys)
// {
// LoginUser onlineUser = redisService.getCacheObject(key);
// if(onlineUser.getSysUser().getUserName().equals(form.getUsername()) )
// {
// redisService.deleteObject(key);
// }
// }
// 获取登录token
return R.ok(tokenService.createToken(userInfo));
}
@DeleteMapping("logout")
public R<?> logout(HttpServletRequest request)
{
String token = SecurityUtils.getToken(request);
if (StringUtils.isNotEmpty(token))
{
String username = JwtUtils.getUserName(token);
// 删除用户缓存记录
AuthUtil.logoutByToken(token);
// 记录用户退出日志
sysLoginService.logout(username);
}
return R.ok();
}
@PostMapping("refresh")
public R<?> refresh(HttpServletRequest request)
{
LoginUser loginUser = tokenService.getLoginUser(request);
if (StringUtils.isNotNull(loginUser))
{
// 刷新令牌有效期
tokenService.refreshToken(loginUser);
return R.ok();
}
return R.ok();
}
@PostMapping("register")
public R<?> register(@RequestBody RegisterBody registerBody)
{
// 用户注册
sysLoginService.register(registerBody.getUsername(), registerBody.getPassword());
return R.ok();
}
}
package com.lccet.auth.form;
import lombok.Data;
/**
* 用户登录对象
*
* @author vctgo
*/
@Data
public class LoginBody
{
/**
* 用户名
*/
private String username;
/**
* 用户密码
*/
private String password;
}
package com.lccet.auth.form;
import lombok.Data;
/**
* 用户注册对象
*
* @author vctgo
*/
@Data
public class RegisterBody extends LoginBody
{
}
package com.lccet.auth.service;
import com.lccet.common.core.enums.CompareUnitEnum;
import com.lccet.common.core.text.Convert;
import com.lccet.common.core.utils.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import com.lccet.common.core.constant.Constants;
import com.lccet.common.core.constant.SecurityConstants;
import com.lccet.common.core.constant.UserConstants;
import com.lccet.common.core.domain.R;
import com.lccet.common.core.enums.UserStatus;
import com.lccet.common.core.exception.ServiceException;
import com.lccet.common.core.utils.ServletUtils;
import com.lccet.common.core.utils.StringUtils;
import com.lccet.common.core.utils.ip.IpUtils;
import com.lccet.common.security.utils.SecurityUtils;
import com.lccet.system.api.RemoteLogService;
import com.lccet.system.api.RemoteUserService;
import com.lccet.system.api.domain.SysLogininfor;
import com.lccet.system.api.domain.SysUser;
import com.lccet.system.api.model.LoginUser;
import java.util.Date;
/**
* 登录校验方法
*
* @author vctgo
*/
@Component
public class SysLoginService
{
@Autowired
private RemoteLogService remoteLogService;
@Autowired
private RemoteUserService remoteUserService;
@Value("${loginLock.loginErrorCount}")
private String loginErrorCount;
@Value("${loginLock.lockTime}")
private String lockTime;
/**
* 登录
*/
public LoginUser login(String username, String password)
{
// 用户名或密码为空 错误
if (StringUtils.isAnyBlank(username, password))
{
recordLogininfor(username, Constants.LOGIN_FAIL, "用户/密码必须填写");
throw new ServiceException("用户/密码必须填写");
}
// 密码如果不在指定范围内 错误
if (password.length() < UserConstants.PASSWORD_MIN_LENGTH
|| password.length() > UserConstants.PASSWORD_MAX_LENGTH)
{
recordLogininfor(username, Constants.LOGIN_FAIL, "用户密码不在指定范围");
throw new ServiceException("用户密码不在指定范围");
}
// 用户名不在指定范围内 错误
if (username.length() < UserConstants.USERNAME_MIN_LENGTH
|| username.length() > UserConstants.USERNAME_MAX_LENGTH)
{
recordLogininfor(username, Constants.LOGIN_FAIL, "用户名不在指定范围");
throw new ServiceException("用户名不在指定范围");
}
// 查询用户信息
R<LoginUser> userResult = remoteUserService.getUserInfo(username, SecurityConstants.INNER);
if (R.FAIL == userResult.getCode())
{
throw new ServiceException(userResult.getMsg());
}
if (StringUtils.isNull(userResult) || StringUtils.isNull(userResult.getData()))
{
recordLogininfor(username, Constants.LOGIN_FAIL, "登录用户不存在");
throw new ServiceException("登录用户:" + username + " 不存在");
}
LoginUser userInfo = userResult.getData();
SysUser user = userResult.getData().getSysUser();
//判断登录次数是否大于等于3
Long diffMinutes=DateUtils.compareTo(new Date(),user.getLockTime(), CompareUnitEnum.MINUTE);
// Boolean b=user.getLoginErrorCount()>=3;
// Boolean bb=user.getLoginErrorCount()>=3&& diffMinutes<=10;
if(user.getLoginErrorCount()>=Integer.parseInt(loginErrorCount)&& diffMinutes<=Integer.parseInt(lockTime)){
throw new ServiceException("您的账号:" + username + " 处于锁定状态中");
}
//线程塞入租户ID
SecurityUtils.setTenantId(Convert.toStr(user.getTenantId()));
if (UserStatus.DELETED.getCode().equals(user.getDelFlag()))
{
recordLogininfor(username, Constants.LOGIN_FAIL, "对不起,您的账号已被删除");
throw new ServiceException("对不起,您的账号:" + username + " 已被删除");
}
if (UserStatus.DISABLE.getCode().equals(user.getStatus()))
{
recordLogininfor(username, Constants.LOGIN_FAIL, "用户已停用,请联系管理员");
throw new ServiceException("对不起,您的账号:" + username + " 已停用");
}
if (!SecurityUtils.matchesPassword(password, user.getPassword()))
{
recordLogininfor(username, Constants.LOGIN_FAIL, "用户密码错误");
//更新密码输入错误次数
remoteUserService.updateLoginErrorCount(username,SecurityConstants.INNER);
if(user.getLoginErrorCount()>=Integer.parseInt(loginErrorCount)-1){
throw new ServiceException("密码错误次数太多,请3分钟后重试");
}
throw new ServiceException("用户不存在/密码错误");
}
//先查询是否被停用了租户
if (userInfo.getTenantStatus() != null && UserStatus.DISABLE.getCode().equals(userInfo.getTenantStatus().toString()))
{
recordLogininfor(username, Constants.LOGIN_FAIL, "当前租户已经被停用,请联系管理员");
throw new ServiceException("当前租户已经被停用");
}
if (userInfo.getTenantEndDate() != null && userInfo.getTenantEndDate().compareTo(new Date()) < 0)
{
recordLogininfor(username, Constants.LOGIN_FAIL, "当前租户已超过租赁日期,请联系管理员");
throw new ServiceException("当前租户已超过租赁日期");
}
recordLogininfor(username, Constants.LOGIN_SUCCESS, "登录成功");
//更新最后登录时间
remoteUserService.updateLoginDate(username,SecurityConstants.INNER);
return userInfo;
}
public void logout(String loginName)
{
recordLogininfor(loginName, Constants.LOGOUT, "退出成功");
}
/**
* 注册
*/
public void register(String username, String password)
{
// 用户名或密码为空 错误
if (StringUtils.isAnyBlank(username, password))
{
throw new ServiceException("用户/密码必须填写");
}
if (username.length() < UserConstants.USERNAME_MIN_LENGTH
|| username.length() > UserConstants.USERNAME_MAX_LENGTH)
{
throw new ServiceException("账户长度必须在2到20个字符之间");
}
if (password.length() < UserConstants.PASSWORD_MIN_LENGTH
|| password.length() > UserConstants.PASSWORD_MAX_LENGTH)
{
throw new ServiceException("密码长度必须在5到20个字符之间");
}
// 注册用户信息
SysUser sysUser = new SysUser();
sysUser.setUserName(username);
sysUser.setNickName(username);
sysUser.setPassword(SecurityUtils.encryptPassword(password));
R<?> registerResult = remoteUserService.registerUserInfo(sysUser, SecurityConstants.INNER);
if (R.FAIL == registerResult.getCode())
{
throw new ServiceException(registerResult.getMsg());
}
recordLogininfor(username, Constants.REGISTER, "注册成功");
}
/**
* 记录登录信息
*
* @param username 用户名
* @param status 状态
* @param message 消息内容
* @return
*/
public void recordLogininfor(String username, String status, String message)
{
SysLogininfor logininfor = new SysLogininfor();
logininfor.setUserName(username);
logininfor.setIpaddr(IpUtils.getIpAddr(ServletUtils.getRequest()));
logininfor.setMsg(message);
logininfor.setTenantId(SecurityUtils.getTenantId());
// 日志状态
if (StringUtils.equalsAny(status, Constants.LOGIN_SUCCESS, Constants.LOGOUT, Constants.REGISTER))
{
logininfor.setStatus(Constants.LOGIN_SUCCESS_STATUS);
}
else if (Constants.LOGIN_FAIL.equals(status))
{
logininfor.setStatus(Constants.LOGIN_FAIL_STATUS);
}
remoteLogService.saveLogininfor(logininfor, SecurityConstants.INNER);
}
}
# Tomcat
server:
port: 39200
# Spring
spring:
application:
# 应用名称
name: lccet-auth
profiles:
# 环境配置
active: dev
cloud:
nacos:
discovery:
# 服务注册地址
server-addr: ${NACOS_HOST:114.116.233.96}:${NACOS_PORT:12845}
#服务注册ip和端口
ip: ${NETWORK_IP:127.0.0.1}
port: ${server.port}
config:
# 配置中心地址
server-addr: ${spring.cloud.nacos.discovery.server-addr}
# 配置文件格式
file-extension: yml
# 共享配置
shared-configs:
- application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>com.lccet</groupId>
<artifactId>lccet-common</artifactId>
<version>1.2.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>lccet-common-core</artifactId>
<description>
lccet-common-core核心模块
</description>
<dependencies>
<!-- SpringCloud Openfeign -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!-- SpringCloud Loadbalancer -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
<!-- Spring Context Support -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
</dependency>
<!-- Spring Web -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</dependency>
<!-- Transmittable ThreadLocal -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>transmittable-thread-local</artifactId>
</dependency>
<!-- Hibernate Validator -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<!-- Jackson -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<!-- Alibaba Fastjson -->
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2</artifactId>
</dependency>
<!-- Jwt -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
</dependency>
<!-- Jaxb -->
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
</dependency>
<!-- Apache Lang3 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<!-- Commons Io -->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
</dependency>
<!-- Commons Fileupload -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
</dependency>
<!-- excel工具 -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
</dependency>
<!-- Java Servlet -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
</dependency>
<!-- Swagger -->
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId>
</dependency>
<dependency>
<groupId>com.github.junrar</groupId>
<artifactId>junrar</artifactId>
<version>4.0.0</version>
</dependency>
<dependency>
<groupId>net.lingala</groupId>
<artifactId>zip4j</artifactId>
<version>1.3.3</version>
</dependency>
</dependencies>
</project>
package com.lccet.common.core.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;
import com.lccet.common.core.utils.poi.ExcelHandlerAdapter;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.IndexedColors;
/**
* 自定义导出Excel数据注解
*
* @author vctgo
*/
@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 "";
/**
* 读取内容转表达式 (如: 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;
/**
* 导出时在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字符串)
*/
public ColumnType cellType() default ColumnType.STRING;
/**
* 导出列头背景色
*/
public IndexedColors headerBackgroundColor() default IndexedColors.GREY_50_PERCENT;
/**
* 导出列头字体颜色
*/
public IndexedColors headerColor() default IndexedColors.WHITE;
/**
* 导出单元格背景色
*/
public IndexedColors backgroundColor() default IndexedColors.WHITE;
/**
* 导出单元格字体颜色
*/
public IndexedColors color() default IndexedColors.BLACK;
/**
* 导出字段对齐方式
*/
public HorizontalAlignment align() default HorizontalAlignment.CENTER;
/**
* 自定义数据处理器
*/
public Class<?> handler() default ExcelHandlerAdapter.class;
/**
* 自定义数据处理器参数
*/
public String[] args() default {};
/**
* 字段类型(0:导出导入;1:仅导出;2:仅导入)
*/
Type type() default Type.ALL;
public enum Type
{
ALL(0), EXPORT(1), IMPORT(2);
private final int value;
Type(int value)
{
this.value = value;
}
public int value()
{
return this.value;
}
}
public enum ColumnType
{
NUMERIC(0), STRING(1), IMAGE(2);
private final int value;
ColumnType(int value)
{
this.value = value;
}
public int value()
{
return this.value;
}
}
}
package com.lccet.common.core.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Excel注解集
*
* @author vctgo
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Excels
{
Excel[] value();
}
package com.lccet.common.core.constant;
/**
* 缓存的key 常量
*
* @author vctgo
*/
public class CacheConstants
{
/**
* 缓存有效期,默认720(分钟)
*/
public final static long EXPIRATION = 720;
/**
* 页面一段时间无任何操作自动退出,默认10(分钟)
*/
public final static long NHANDLEEXPIRATION = 30;
/**
* 缓存刷新时间,默认120(分钟)
*/
public final static long REFRESH_TIME = 120;
/**
* 权限缓存前缀
*/
public final static String LOGIN_TOKEN_KEY = "login_tokens:";
/**
* 权限缓存前缀
*/
public final static String NOHANDLE_EXPRIE_KEY = "nohandle_expire:";
}
package com.lccet.common.core.constant;
/**
* 通用常量信息
*
* @author vctgo
*/
public class Constants
{
/**
* UTF-8 字符集
*/
public static final String UTF8 = "UTF-8";
/**
* GBK 字符集
*/
public static final String GBK = "GBK";
/**
* RMI 远程方法调用
*/
public static final String LOOKUP_RMI = "rmi:";
/**
* LDAP 远程方法调用
*/
public static final String LOOKUP_LDAP = "ldap:";
/**
* LDAPS 远程方法调用
*/
public static final String LOOKUP_LDAPS = "ldaps:";
/**
* http请求
*/
public static final String HTTP = "http://";
/**
* https请求
*/
public static final String HTTPS = "https://";
/**
* 成功标记
*/
public static final Integer SUCCESS = 200;
/**
* 失败标记
*/
public static final Integer FAIL = 500;
/**
* 登录成功状态
*/
public static final String LOGIN_SUCCESS_STATUS = "0";
/**
* 登录失败状态
*/
public static final String LOGIN_FAIL_STATUS = "1";
/**
* 登录成功
*/
public static final String LOGIN_SUCCESS = "Success";
/**
* 注销
*/
public static final String LOGOUT = "Logout";
/**
* 注册
*/
public static final String REGISTER = "Register";
/**
* 登录失败
*/
public static final String LOGIN_FAIL = "Error";
/**
* 当前记录起始索引
*/
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";
/**
* 验证码 redis key
*/
public static final String CAPTCHA_CODE_KEY = "captcha_codes:";
/**
* 注册验证码 redis key
*/
public static final String REGISTE_CODE_KEY = "register_code:";
/**
* 验证码有效期(分钟)
*/
public static final long CAPTCHA_EXPIRATION = 2;
/**
* 参数管理 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";
}
package com.lccet.common.core.constant;
/**
* 代码生成通用常量
*
* @author vctgo
*/
public class GenConstants
{
/** 单表(增删改查) */
public static final String TPL_CRUD = "crud";
/** 树表(增删改查) */
public static final String TPL_TREE = "tree";
/** 主子表(增删改查) */
public static final String TPL_SUB = "sub";
/** 树编码字段 */
public static final String TREE_CODE = "treeCode";
/** 树父编码字段 */
public static final String TREE_PARENT_CODE = "treeParentCode";
/** 树名称字段 */
public static final String TREE_NAME = "treeName";
/** 上级菜单ID字段 */
public static final String PARENT_MENU_ID = "parentMenuId";
/** 上级菜单名称字段 */
public static final String PARENT_MENU_NAME = "parentMenuName";
/** 数据库字符串类型 */
public static final String[] COLUMNTYPE_STR = { "char", "varchar", "nvarchar", "varchar2" };
/** 数据库文本类型 */
public static final String[] COLUMNTYPE_TEXT = { "tinytext", "text", "mediumtext", "longtext" };
/** 数据库时间类型 */
public static final String[] COLUMNTYPE_TIME = { "datetime", "time", "date", "timestamp" };
/** 数据库数字类型 */
public static final String[] COLUMNTYPE_NUMBER = { "tinyint", "smallint", "mediumint", "int", "number", "integer",
"bigint", "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" };
/** 文本框 */
public static final String HTML_INPUT = "input";
/** 文本域 */
public static final String HTML_TEXTAREA = "textarea";
/** 下拉框 */
public static final String HTML_SELECT = "select";
/** 单选框 */
public static final String HTML_RADIO = "radio";
/** 复选框 */
public static final String HTML_CHECKBOX = "checkbox";
/** 日期控件 */
public static final String HTML_DATETIME = "datetime";
/** 图片上传控件 */
public static final String HTML_IMAGE_UPLOAD = "imageUpload";
/** 文件上传控件 */
public static final String HTML_FILE_UPLOAD = "fileUpload";
/** 富文本控件 */
public static final String HTML_EDITOR = "editor";
/** 字符串类型 */
public static final String TYPE_STRING = "String";
/** 整型 */
public static final String TYPE_INTEGER = "Integer";
/** 长整型 */
public static final String TYPE_LONG = "Long";
/** 浮点型 */
public static final String TYPE_DOUBLE = "Double";
/** 高精度计算类型 */
public static final String TYPE_BIGDECIMAL = "BigDecimal";
/** 时间类型 */
public static final String TYPE_DATE = "Date";
/** 模糊查询 */
public static final String QUERY_LIKE = "LIKE";
/** 相等查询 */
public static final String QUERY_EQ = "EQ";
/** 需要 */
public static final String REQUIRE = "1";
}
package com.lccet.common.core.constant;
/**
* 返回状态码
*
* @author vctgo
*/
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;
}
package com.lccet.common.core.constant;
/**
* 任务调度通用常量
*
* @author vctgo
*/
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;
}
}
}
package com.lccet.common.core.constant;
/**
* 权限相关通用常量
*
* @author vctgo
*/
public class SecurityConstants
{
/**
* 用户ID字段
*/
public static final String DETAILS_TENANT_ID = "tenant-id";
/**
* 用户ID字段
*/
public static final String DETAILS_USER_ID = "user_id";
/**
* 用户名字段
*/
public static final String DETAILS_USERNAME = "username";
/**
* 授权信息字段
*/
public static final String AUTHORIZATION_HEADER = "authorization";
/**
* 请求来源
*/
public static final String FROM_SOURCE = "from-source";
/**
* 内部请求
*/
public static final String INNER = "inner";
/**
* 用户标识
*/
public static final String USER_KEY = "user_key";
/**
* 登录用户
*/
public static final String LOGIN_USER = "login_user";
/**
* 授权信息字段
*/
public static final String REMOTE_HEADER = "remoteheader";
}
package com.lccet.common.core.constant;
/**
* 服务名称
*
* @author vctgo
*/
public class ServiceNameConstants
{
/**
* 认证服务的serviceid
*/
public static final String AUTH_SERVICE = "lccet-auth";
/**
* 系统模块的serviceid
*/
public static final String SYSTEM_SERVICE = "lccet-system";
/**
* 文件服务的serviceid
*/
public static final String FILE_SERVICE = "lccet-file";
}
package com.lccet.common.core.constant;
/**
* Token的Key常量
*
* @author vctgo
*/
public class TokenConstants
{
/**
* 令牌自定义标识
*/
public static final String AUTHENTICATION = "Authorization";
/**
* 令牌前缀
*/
public static final String PREFIX = "Bearer ";
/**
* 令牌秘钥
*/
public final static String SECRET = "abcdefghijklmnopqrstuvwxyz";
}
package com.lccet.common.core.constant;
/**
* 用户常量信息
*
* @author vctgo
*/
public class UserConstants
{
/**
* 平台内系统用户的唯一标志
*/
public static final String SYS_USER = "SYS_USER";
/** 正常状态 */
public static final String NORMAL = "0";
/** 异常状态 */
public static final String EXCEPTION = "1";
/** 用户封禁状态 */
public static final String USER_DISABLE = "1";
/** 角色封禁状态 */
public static final String ROLE_DISABLE = "1";
/** 部门正常状态 */
public static final String DEPT_NORMAL = "0";
/** 部门停用状态 */
public static final String DEPT_DISABLE = "1";
/** 字典正常状态 */
public static final String DICT_NORMAL = "0";
/** 是否为系统默认(是) */
public static final String YES = "Y";
/** 是否菜单外链(是) */
public static final String YES_FRAME = "0";
/** 是否菜单外链(否) */
public static final String NO_FRAME = "1";
/** 菜单类型(目录) */
public static final String TYPE_DIR = "M";
/** 菜单类型(菜单) */
public static final String TYPE_MENU = "C";
/** 菜单类型(按钮) */
public static final String TYPE_BUTTON = "F";
/** Layout组件标识 */
public final static String LAYOUT = "Layout";
/** ParentView组件标识 */
public final static String PARENT_VIEW = "ParentView";
/** InnerLink组件标识 */
public final static String INNER_LINK = "InnerLink";
/** 校验返回结果码 */
public final static String UNIQUE = "0";
public final static String NOT_UNIQUE = "1";
/**
* 用户名长度限制
*/
public static final int USERNAME_MIN_LENGTH = 2;
public static final int USERNAME_MAX_LENGTH = 20;
/**
* 密码长度限制
*/
public static final int PASSWORD_MIN_LENGTH = 5;
public static final int PASSWORD_MAX_LENGTH = 20;
}
package com.lccet.common.core.context;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import com.alibaba.ttl.TransmittableThreadLocal;
import com.lccet.common.core.constant.SecurityConstants;
import com.lccet.common.core.text.Convert;
import com.lccet.common.core.utils.StringUtils;
/**
* 获取当前线程变量中的 用户id、用户名称、Token等信息
* 注意: 必须在网关通过请求头的方法传入,同时在HeaderInterceptor拦截器设置值。 否则这里无法获取
*
* @author vctgo
*/
public class SecurityContextHolder
{
private static final TransmittableThreadLocal<Map<String, Object>> THREAD_LOCAL = new TransmittableThreadLocal<>();
public static void set(String key, Object value)
{
Map<String, Object> map = getLocalMap();
map.put(key, value == null ? StringUtils.EMPTY : value);
}
public static String get(String key)
{
Map<String, Object> map = getLocalMap();
return Convert.toStr(map.getOrDefault(key, StringUtils.EMPTY));
}
public static <T> T get(String key, Class<T> clazz)
{
Map<String, Object> map = getLocalMap();
return StringUtils.cast(map.getOrDefault(key, null));
}
public static Map<String, Object> getLocalMap()
{
Map<String, Object> map = THREAD_LOCAL.get();
if (map == null)
{
map = new ConcurrentHashMap<String, Object>();
THREAD_LOCAL.set(map);
}
return map;
}
public static void setLocalMap(Map<String, Object> threadLocalMap)
{
THREAD_LOCAL.set(threadLocalMap);
}
public static Long getTenantId()
{
return Convert.toLong(get(SecurityConstants.DETAILS_TENANT_ID), 9999L);
}
public static void setTenantId(String account)
{
set(SecurityConstants.DETAILS_TENANT_ID, account);
}
public static void setRemoteHeader(Object account)
{
set(SecurityConstants.REMOTE_HEADER, account);
}
public static Long getUserId()
{
return Convert.toLong(get(SecurityConstants.DETAILS_USER_ID), 0L);
}
public static void setUserId(String account)
{
set(SecurityConstants.DETAILS_USER_ID, account);
}
public static String getUserName()
{
return get(SecurityConstants.DETAILS_USERNAME);
}
public static void setUserName(String username)
{
set(SecurityConstants.DETAILS_USERNAME, username);
}
public static String getUserKey()
{
return get(SecurityConstants.USER_KEY);
}
public static void setUserKey(String userKey)
{
set(SecurityConstants.USER_KEY, userKey);
}
public static void remove()
{
THREAD_LOCAL.remove();
}
}
package com.lccet.common.core.domain;
import java.io.Serializable;
import com.lccet.common.core.constant.Constants;
/**
* 响应信息主体
*
* @author vctgo
*/
public class R<T> implements Serializable
{
private static final long serialVersionUID = 1L;
/** 成功 */
public static final int SUCCESS = Constants.SUCCESS;
/** 失败 */
public static final int FAIL = Constants.FAIL;
private int code;
private String msg;
private T data;
public static <T> R<T> ok()
{
return restResult(null, SUCCESS, null);
}
public static <T> R<T> ok(T data)
{
return restResult(data, SUCCESS, null);
}
public static <T> R<T> ok(T data, String msg)
{
return restResult(data, SUCCESS, msg);
}
public static <T> R<T> fail()
{
return restResult(null, FAIL, null);
}
public static <T> R<T> fail(String msg)
{
return restResult(null, FAIL, msg);
}
public static <T> R<T> fail(T data)
{
return restResult(data, FAIL, null);
}
public static <T> R<T> fail(T data, String msg)
{
return restResult(data, FAIL, msg);
}
public static <T> R<T> fail(int code, String msg)
{
return restResult(null, code, msg);
}
private static <T> R<T> restResult(T data, int code, String msg)
{
R<T> apiResult = new R<>();
apiResult.setCode(code);
apiResult.setData(data);
apiResult.setMsg(msg);
return apiResult;
}
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;
}
public T getData()
{
return data;
}
public void setData(T data)
{
this.data = data;
}
}
package com.lccet.common.core.enums;
public enum CompareUnitEnum {
HOUR, //时
MINUTE, //分
SECOND //秒
}
package com.lccet.common.core.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 语言枚举
*
* @author
*/
@Getter
@AllArgsConstructor
public enum LanguageEnum {
CN(1), // 中文
EN(2), // 英文
;
/**
* 类型
*/
private final Integer languageType;
}
package com.lccet.common.core.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 菜单类型枚举类
*
* @author 芋道源码
*/
@Getter
@AllArgsConstructor
public enum MenuTypeEnum {
DIR(1), // 目录
MENU(2), // 菜单
BUTTON(3) // 按钮
;
/**
* 类型
*/
private final Integer type;
}
package com.lccet.common.core.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* @author zzqtdos
* 描述:
* 创建时间:2023/2/3 16:17
* 修改时间:2023/2/3 16:17
*/
@Getter
@AllArgsConstructor
public enum ProcessEnum {
原材料供应(6),
运输(7),
制造(8),
;
/**
* 类型
*/
private final Integer processId;
}
package com.lccet.common.core.enums;
/**
* 用户状态
*
* @author vctgo
*/
public enum UserStatus
{
OK("0", "正常"), DISABLE("1", "停用"), DELETED("1", "删除");
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;
}
}
package com.lccet.common.core.exception;
/**
* 验证码错误异常类
*
* @author vctgo
*/
public class CaptchaException extends RuntimeException
{
private static final long serialVersionUID = 1L;
public CaptchaException(String msg)
{
super(msg);
}
}
package com.lccet.common.core.exception;
/**
* 检查异常
*
* @author vctgo
*/
public class CheckedException extends RuntimeException
{
private static final long serialVersionUID = 1L;
public CheckedException(String message)
{
super(message);
}
public CheckedException(Throwable cause)
{
super(cause);
}
public CheckedException(String message, Throwable cause)
{
super(message, cause);
}
public CheckedException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace)
{
super(message, cause, enableSuppression, writableStackTrace);
}
}
package com.lccet.common.core.exception;
/**
* 演示模式异常
*
* @author vctgo
*/
public class DemoModeException extends RuntimeException
{
private static final long serialVersionUID = 1L;
public DemoModeException()
{
}
}
package com.lccet.common.core.exception;
/**
* 全局异常
*
* @author vctgo
*/
public class GlobalException extends RuntimeException
{
private static final long serialVersionUID = 1L;
/**
* 错误提示
*/
private String message;
/**
* 错误明细,内部调试错误
*
* 和 {@link CommonResult#getDetailMessage()} 一致的设计
*/
private String detailMessage;
/**
* 空构造方法,避免反序列化问题
*/
public GlobalException()
{
}
public GlobalException(String message)
{
this.message = message;
}
public String getDetailMessage()
{
return detailMessage;
}
public GlobalException setDetailMessage(String detailMessage)
{
this.detailMessage = detailMessage;
return this;
}
@Override
public String getMessage()
{
return message;
}
public GlobalException setMessage(String message)
{
this.message = message;
return this;
}
}
package com.lccet.common.core.exception;
/**
* 内部认证异常
*
* @author vctgo
*/
public class InnerAuthException extends RuntimeException
{
private static final long serialVersionUID = 1L;
public InnerAuthException(String message)
{
super(message);
}
}
package com.lccet.common.core.exception;
/**
* 权限异常
*
* @author vctgo
*/
public class PreAuthorizeException extends RuntimeException
{
private static final long serialVersionUID = 1L;
public PreAuthorizeException()
{
}
}
package com.lccet.common.core.exception;
/**
* 业务异常
*
* @author vctgo
*/
public final class ServiceException extends RuntimeException
{
private static final long serialVersionUID = 1L;
/**
* 错误码
*/
private Integer code;
/**
* 错误提示
*/
private String message;
/**
* 错误明细,内部调试错误
*
* 和 {@link CommonResult#getDetailMessage()} 一致的设计
*/
private String detailMessage;
/**
* 空构造方法,避免反序列化问题
*/
public ServiceException()
{
}
public ServiceException(String message)
{
this.message = message;
}
public ServiceException(String message, Integer code)
{
this.message = message;
this.code = code;
}
public String getDetailMessage()
{
return detailMessage;
}
@Override
public String getMessage()
{
return message;
}
public Integer getCode()
{
return code;
}
public ServiceException setMessage(String message)
{
this.message = message;
return this;
}
public ServiceException setDetailMessage(String detailMessage)
{
this.detailMessage = detailMessage;
return this;
}
}
package com.lccet.common.core.exception;
/**
* 工具类异常
*
* @author vctgo
*/
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);
}
}
package com.lccet.common.core.exception.auth;
/**
* 未能通过的登录认证异常
*
* @author vctgo
*/
public class NotLoginException extends RuntimeException
{
private static final long serialVersionUID = 1L;
public NotLoginException(String message)
{
super(message);
}
}
package com.lccet.common.core.exception.auth;
import org.apache.commons.lang3.StringUtils;
/**
* 未能通过的权限认证异常
*
* @author vctgo
*/
public class NotPermissionException extends RuntimeException
{
private static final long serialVersionUID = 1L;
public NotPermissionException(String permission)
{
super(permission);
}
public NotPermissionException(String[] permissions)
{
super(StringUtils.join(permissions, ","));
}
}
package com.lccet.common.core.exception.auth;
import org.apache.commons.lang3.StringUtils;
/**
* 未能通过的角色认证异常
*
* @author vctgo
*/
public class NotRoleException extends RuntimeException
{
private static final long serialVersionUID = 1L;
public NotRoleException(String role)
{
super(role);
}
public NotRoleException(String[] roles)
{
super(StringUtils.join(roles, ","));
}
}
package com.lccet.common.core.exception.base;
/**
* 基础异常
*
* @author vctgo
*/
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);
}
public String getModule()
{
return module;
}
public String getCode()
{
return code;
}
public Object[] getArgs()
{
return args;
}
public String getDefaultMessage()
{
return defaultMessage;
}
}
package com.lccet.common.core.exception.file;
import com.lccet.common.core.exception.base.BaseException;
/**
* 文件信息异常类
*
* @author vctgo
*/
public class FileException extends BaseException
{
private static final long serialVersionUID = 1L;
public FileException(String code, Object[] args)
{
super("file", code, args, null);
}
}
package com.lccet.common.core.exception.file;
/**
* 文件名称超长限制异常类
*
* @author vctgo
*/
public class FileNameLengthLimitExceededException extends FileException
{
private static final long serialVersionUID = 1L;
public FileNameLengthLimitExceededException(int defaultFileNameLength)
{
super("upload.filename.exceed.length", new Object[] { defaultFileNameLength });
}
}
package com.lccet.common.core.exception.file;
/**
* 文件名大小限制异常类
*
* @author vctgo
*/
public class FileSizeLimitExceededException extends FileException
{
private static final long serialVersionUID = 1L;
public FileSizeLimitExceededException(long defaultMaxSize)
{
super("upload.exceed.maxSize", new Object[] { defaultMaxSize });
}
}
package com.lccet.common.core.exception.file;
import java.util.Arrays;
import org.apache.commons.fileupload.FileUploadException;
/**
* 文件上传 误异常类
*
* @author vctgo
*/
public class InvalidExtensionException extends FileUploadException
{
private static final long serialVersionUID = 1L;
private String[] allowedExtension;
private String extension;
private String filename;
public InvalidExtensionException(String[] allowedExtension, String extension, String filename)
{
super("filename : [" + filename + "], extension : [" + extension + "], allowed extension : [" + Arrays.toString(allowedExtension) + "]");
this.allowedExtension = allowedExtension;
this.extension = extension;
this.filename = filename;
}
public String[] getAllowedExtension()
{
return allowedExtension;
}
public String getExtension()
{
return extension;
}
public String getFilename()
{
return filename;
}
public static class InvalidImageExtensionException extends InvalidExtensionException
{
private static final long serialVersionUID = 1L;
public InvalidImageExtensionException(String[] allowedExtension, String extension, String filename)
{
super(allowedExtension, extension, filename);
}
}
public static class InvalidFlashExtensionException extends InvalidExtensionException
{
private static final long serialVersionUID = 1L;
public InvalidFlashExtensionException(String[] allowedExtension, String extension, String filename)
{
super(allowedExtension, extension, filename);
}
}
public static class InvalidMediaExtensionException extends InvalidExtensionException
{
private static final long serialVersionUID = 1L;
public InvalidMediaExtensionException(String[] allowedExtension, String extension, String filename)
{
super(allowedExtension, extension, filename);
}
}
public static class InvalidVideoExtensionException extends InvalidExtensionException
{
private static final long serialVersionUID = 1L;
public InvalidVideoExtensionException(String[] allowedExtension, String extension, String filename)
{
super(allowedExtension, extension, filename);
}
}
}
package com.lccet.common.core.exception.job;
/**
* 计划策略异常
*
* @author vctgo
*/
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
}
}
package com.lccet.common.core.exception.user;
/**
* 验证码失效异常类
*
* @author vctgo
*/
public class CaptchaExpireException extends UserException
{
private static final long serialVersionUID = 1L;
public CaptchaExpireException()
{
super("user.jcaptcha.expire", null);
}
}
package com.lccet.common.core.exception.user;
import com.lccet.common.core.exception.base.BaseException;
/**
* 用户信息异常类
*
* @author vctgo
*/
public class UserException extends BaseException
{
private static final long serialVersionUID = 1L;
public UserException(String code, Object[] args)
{
super("user", code, args, null);
}
}
package com.lccet.common.core.exception.user;
/**
* 用户密码不正确或不符合规范异常类
*
* @author vctgo
*/
public class UserPasswordNotMatchException extends UserException
{
private static final long serialVersionUID = 1L;
public UserPasswordNotMatchException()
{
super("user.password.not.match", null);
}
}
package com.lccet.common.core.text;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import com.lccet.common.core.utils.StringUtils;
/**
* 字符集工具类
*
* @author vctgo
*/
public class CharsetKit
{
/** ISO-8859-1 */
public static final String ISO_8859_1 = "ISO-8859-1";
/** UTF-8 */
public static final String UTF_8 = "UTF-8";
/** GBK */
public static final String GBK = "GBK";
/** ISO-8859-1 */
public static final Charset CHARSET_ISO_8859_1 = Charset.forName(ISO_8859_1);
/** UTF-8 */
public static final Charset CHARSET_UTF_8 = Charset.forName(UTF_8);
/** GBK */
public static final Charset CHARSET_GBK = Charset.forName(GBK);
/**
* 转换为Charset对象
*
* @param charset 字符集,为空则返回默认字符集
* @return Charset
*/
public static Charset charset(String charset)
{
return StringUtils.isEmpty(charset) ? Charset.defaultCharset() : Charset.forName(charset);
}
/**
* 转换字符串的字符集编码
*
* @param source 字符串
* @param srcCharset 源字符集,默认ISO-8859-1
* @param destCharset 目标字符集,默认UTF-8
* @return 转换后的字符集
*/
public static String convert(String source, String srcCharset, String destCharset)
{
return convert(source, Charset.forName(srcCharset), Charset.forName(destCharset));
}
/**
* 转换字符串的字符集编码
*
* @param source 字符串
* @param srcCharset 源字符集,默认ISO-8859-1
* @param destCharset 目标字符集,默认UTF-8
* @return 转换后的字符集
*/
public static String convert(String source, Charset srcCharset, Charset destCharset)
{
if (null == srcCharset)
{
srcCharset = StandardCharsets.ISO_8859_1;
}
if (null == destCharset)
{
destCharset = StandardCharsets.UTF_8;
}
if (StringUtils.isEmpty(source) || srcCharset.equals(destCharset))
{
return source;
}
return new String(source.getBytes(srcCharset), destCharset);
}
/**
* @return 系统字符集编码
*/
public static String systemCharset()
{
return Charset.defaultCharset().name();
}
}
package com.lccet.common.core.text;
import com.lccet.common.core.utils.StringUtils;
/**
* 字符串格式化
*
* @author vctgo
*/
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();
}
}
package com.lccet.common.core.utils;
import java.math.BigDecimal;
import java.math.RoundingMode;
/**
* 精确的浮点数运算
*
* @author vctgo
*/
public class Arith {
/**
* 默认除法运算精度
*/
private static final int DEF_DIV_SCALE = 10;
/**
* 这个类不能实例化
*/
private Arith() {
}
/**
* 提供精确的加法运算。
*
* @param v1 被加数
* @param v2 加数
* @return 两个参数的和
*/
public static double add(double v1, double v2) {
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.add(b2).doubleValue();
}
/**
* 提供精确的减法运算。
*
* @param v1 被减数
* @param v2 减数
* @return 两个参数的差
*/
public static double sub(double v1, double v2) {
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.subtract(b2).doubleValue();
}
/**
* 提供精确的乘法运算。
*
* @param v1 被乘数
* @param v2 乘数
* @return 两个参数的积
*/
public static double mul(double v1, double v2) {
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.multiply(b2).doubleValue();
}
/**
* 提供(相对)精确的除法运算,当发生除不尽的情况时,精确到
* 小数点以后10位,以后的数字四舍五入。
*
* @param v1 被除数
* @param v2 除数
* @return 两个参数的商
*/
public static double div(double v1, double v2) {
return div(v1, v2, DEF_DIV_SCALE);
}
/**
* 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指
* 定精度,以后的数字四舍五入。
*
* @param v1 被除数
* @param v2 除数
* @param scale 表示表示需要精确到小数点以后几位。
* @return 两个参数的商
*/
public static double div(double v1, double v2, int scale) {
if (scale < 0) {
throw new IllegalArgumentException(
"The scale must be a positive integer or zero");
}
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
if (b1.compareTo(BigDecimal.ZERO) == 0) {
return BigDecimal.ZERO.doubleValue();
}
return b1.divide(b2, scale, RoundingMode.HALF_UP).doubleValue();
}
/**
* 提供精确的小数位四舍五入处理。
*
* @param v 需要四舍五入的数字
* @param scale 小数点后保留几位
* @return 四舍五入后的结果
*/
public static double round(double v, int scale) {
if (scale < 0) {
throw new IllegalArgumentException(
"The scale must be a positive integer or zero");
}
BigDecimal b = new BigDecimal(Double.toString(v));
BigDecimal one = BigDecimal.ONE;
return b.divide(one, scale, RoundingMode.HALF_UP).doubleValue();
}
/**
* 提供精确的小数位四舍五入处理。
*
* @param v 需要四舍五入的数字
* @param scale 小数点后保留几位
* @return 四舍五入后的结果
*/
public static String round(String v, int scale) {
if (scale < 0) {
throw new IllegalArgumentException(
"The scale must be a positive integer or zero");
}
BigDecimal b = new BigDecimal(v);
BigDecimal one = BigDecimal.ONE;
return b.divide(one, scale, RoundingMode.HALF_UP).toPlainString();
}
/**
* 加法运算
*
* @param v1
* @param v2
* @return
*/
public static String add(String v1, String v2) {
BigDecimal b1 = new BigDecimal(v1);
BigDecimal b2 = new BigDecimal(v2);
return b1.add(b2).toPlainString();
}
public static BigDecimal add(BigDecimal v1, BigDecimal v2) {
return v1.add(v2);
}
/**
* 减法运算
*
* @param v1
* @param v2
* @return
*/
public static String sub(String v1, String v2) {
BigDecimal b1 = new BigDecimal(v1);
BigDecimal b2 = new BigDecimal(v2);
return b1.subtract(b2).toPlainString();
}
/**
* 乘法运算
*
* @param v1
* @param v2
* @return
*/
public static String multiply(String v1, String v2) {
BigDecimal b1 = new BigDecimal(v1);
BigDecimal b2 = new BigDecimal(v2);
return b1.multiply(b2).toPlainString();
}
/**
* 乘法运算
*
* @param v1
* @param v2
* @return
*/
public static BigDecimal multiplyToBD(String v1, String v2) {
BigDecimal b1 = new BigDecimal(v1);
BigDecimal b2 = new BigDecimal(v2);
return b1.multiply(b2);
}
/**
* 除法运算
*
* @param v1 被除数
* @param v2 除数
* @return
*/
public static String divide(String v1, String v2) {
BigDecimal b1 = new BigDecimal(v1);
BigDecimal b2 = new BigDecimal(v2);
return b1.divide(b2).toPlainString();
}
}
package com.lccet.common.core.utils;
import org.apache.ibatis.executor.result.ResultMapException;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.MappedTypes;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* @Name: CustomStringTypeHandler
* @Desc: 自定义mybatis处理类,将null返回为空串(‘’)
* @Author: Administrator
* @author dhr
* @desc CustomStringTypeHandler
* @date 2020/11/05
*/
@MappedTypes({String.class})
@MappedJdbcTypes(JdbcType.VARCHAR)
public class CustomStringTypeHandler extends BaseTypeHandler<String> {
@Override
public String getResult(ResultSet rs, String columnName) {
String result;
try {
result = getNullableResult(rs, columnName);
} catch (Exception e) {
throw new ResultMapException("Error attempting to get column '" + columnName + "' from result set. Cause: " + e, e);
}
return result;
}
@Override
public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType)
throws SQLException {
ps.setString(i, parameter);
}
@Override
public String getNullableResult(ResultSet rs, String columnName)
throws SQLException {
return rs.getString(columnName) == null? "" : rs.getString(columnName);
}
@Override
public String getNullableResult(ResultSet rs, int columnIndex)
throws SQLException {
return rs.getString(columnIndex) == null? "" : rs.getString(columnIndex);
}
@Override
public String getNullableResult(CallableStatement cs, int columnIndex)
throws SQLException {
return cs.getString(columnIndex) == null? "" : cs.getString(columnIndex);
}
}
package com.lccet.common.core.utils;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.lang.management.ManagementFactory;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Calendar;
import java.util.Date;
import com.lccet.common.core.enums.CompareUnitEnum;
import org.apache.commons.lang3.time.DateFormatUtils;
/**
* 时间工具类
*
* @author vctgo
*/
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 + "分钟";
}
/**
* 时间比较
*
* @param t1 时间1
* @param t2 时间2
* @param unit 单位
* @return
*/
public static long compareTo(Date t1, Date t2, CompareUnitEnum unit) {
long res;
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
Calendar c1 = Calendar.getInstance();
Calendar c2 = Calendar.getInstance();
try {
c1.setTime(t1);
c2.setTime(t2);
long m1 = c1.getTime().getTime();
long m2 = c2.getTime().getTime();
switch (unit) {
case SECOND:
res = (m1 - m2) / 1000;
break;
case MINUTE:
res = (m1 - m2) / 1000 / 60;
break;
case HOUR:
res = (m1 - m2) / 1000 / 60 / 24;
break;
default:
res = -1L;
break;
}
} catch (Exception e) {
ByteArrayOutputStream bs = new ByteArrayOutputStream();
e.printStackTrace(new PrintStream(bs));
res = -1L;
}
return res;
}
/**
* 增加 LocalDateTime ==> Date
*/
public static Date toDate(LocalDateTime temporalAccessor)
{
ZonedDateTime zdt = temporalAccessor.atZone(ZoneId.systemDefault());
return Date.from(zdt.toInstant());
}
/**
* 增加 LocalDate ==> Date
*/
public static Date toDate(LocalDate temporalAccessor)
{
LocalDateTime localDateTime = LocalDateTime.of(temporalAccessor, LocalTime.of(0, 0, 0));
ZonedDateTime zdt = localDateTime.atZone(ZoneId.systemDefault());
return Date.from(zdt.toInstant());
}
}
package com.lccet.common.core.utils;
import java.io.PrintWriter;
import java.io.StringWriter;
import org.apache.commons.lang3.exception.ExceptionUtils;
/**
* 错误信息处理类。
*
* @author vctgo
*/
public class ExceptionUtil
{
/**
* 获取exception的详细错误信息。
*/
public static String getExceptionMessage(Throwable e)
{
StringWriter sw = new StringWriter();
e.printStackTrace(new PrintWriter(sw, true));
return sw.toString();
}
public static String getRootErrorMessage(Exception e)
{
Throwable root = ExceptionUtils.getRootCause(e);
root = (root == null ? e : root);
if (root == null)
{
return "";
}
String msg = root.getMessage();
if (msg == null)
{
return "null";
}
return StringUtils.defaultString(msg);
}
}
package com.lccet.common.core.utils;
import java.util.Map;
import com.lccet.common.core.constant.SecurityConstants;
import com.lccet.common.core.constant.TokenConstants;
import com.lccet.common.core.text.Convert;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
/**
* Jwt工具类
*
* @author vctgo
*/
public class JwtUtils
{
public static String secret = TokenConstants.SECRET;
/**
* 从数据声明生成令牌
*
* @param claims 数据声明
* @return 令牌
*/
public static String createToken(Map<String, Object> claims)
{
String token = Jwts.builder().setClaims(claims).signWith(SignatureAlgorithm.HS512, secret).compact();
return token;
}
/**
* 从令牌中获取数据声明
*
* @param token 令牌
* @return 数据声明
*/
public static Claims parseToken(String token)
{
return Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody();
}
/**
* 根据令牌获取用户标识
*
* @param token 令牌
* @return 用户ID
*/
public static String getUserKey(String token)
{
Claims claims = parseToken(token);
return getValue(claims, SecurityConstants.USER_KEY);
}
/**
* 根据令牌获取用户标识
*
* @param claims 身份信息
* @return 用户ID
*/
public static String getUserKey(Claims claims)
{
return getValue(claims, SecurityConstants.USER_KEY);
}
/**
* 根据令牌获取用户ID
*
* @param token 令牌
* @return 用户ID
*/
public static String getUserId(String token)
{
Claims claims = parseToken(token);
return getValue(claims, SecurityConstants.DETAILS_USER_ID);
}
/**
* 根据身份信息获取用户ID
*
* @param claims 身份信息
* @return 用户ID
*/
public static String getUserId(Claims claims)
{
return getValue(claims, SecurityConstants.DETAILS_USER_ID);
}
/**
* 根据令牌获取用户名
*
* @param token 令牌
* @return 用户名
*/
public static String getUserName(String token)
{
Claims claims = parseToken(token);
return getValue(claims, SecurityConstants.DETAILS_USERNAME);
}
/**
* 根据身份信息获取用户名
*
* @param claims 身份信息
* @return 用户名
*/
public static String getUserName(Claims claims)
{
return getValue(claims, SecurityConstants.DETAILS_USERNAME);
}
/**
* 根据身份信息获取键值
*
* @param claims 身份信息
* @param key 键
* @return 值
*/
public static String getValue(Claims claims, String key)
{
return Convert.toStr(claims.get(key), "");
}
}
package com.lccet.common.core.utils;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.Enumeration;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import com.lccet.common.core.constant.Constants;
import com.lccet.common.core.domain.R;
import com.lccet.common.core.text.Convert;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.util.LinkedCaseInsensitiveMap;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import com.alibaba.fastjson2.JSON;
import reactor.core.publisher.Mono;
/**
* 客户端工具类
*
* @author vctgo
*/
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);
}
/**
* 获取Boolean参数
*/
public static Boolean getParameterToBool(String name)
{
return Convert.toBool(getRequest().getParameter(name));
}
/**
* 获取Boolean参数
*/
public static Boolean getParameterToBool(String name, Boolean defaultValue)
{
return Convert.toBool(getRequest().getParameter(name), defaultValue);
}
/**
* 获取request
*/
public static HttpServletRequest getRequest()
{
try
{
return getRequestAttributes().getRequest();
}
catch (Exception e)
{
return null;
}
}
/**
* 获取response
*/
public static HttpServletResponse getResponse()
{
try
{
return getRequestAttributes().getResponse();
}
catch (Exception e)
{
return null;
}
}
/**
* 获取session
*/
public static HttpSession getSession()
{
return getRequest().getSession();
}
public static ServletRequestAttributes getRequestAttributes()
{
try
{
RequestAttributes attributes = RequestContextHolder.getRequestAttributes();
return (ServletRequestAttributes) attributes;
}
catch (Exception e)
{
return null;
}
}
public static String getHeader(HttpServletRequest request, String name)
{
String value = request.getHeader(name);
if (StringUtils.isEmpty(value))
{
return StringUtils.EMPTY;
}
return urlDecode(value);
}
public static Map<String, String> getHeaders(HttpServletRequest request)
{
Map<String, String> map = new LinkedCaseInsensitiveMap<>();
Enumeration<String> enumeration = request.getHeaderNames();
if (enumeration != null)
{
while (enumeration.hasMoreElements())
{
String key = enumeration.nextElement();
String value = request.getHeader(key);
map.put(key, value);
}
}
return map;
}
/**
* 将字符串渲染到客户端
*
* @param response 渲染对象
* @param string 待渲染的字符串
*/
public static void 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();
}
}
/**
* 是否是Ajax异步请求
*
* @param request
*/
public static boolean isAjaxRequest(HttpServletRequest request)
{
String accept = request.getHeader("accept");
if (accept != null && accept.contains("application/json"))
{
return true;
}
String xRequestedWith = request.getHeader("X-Requested-With");
if (xRequestedWith != null && xRequestedWith.contains("XMLHttpRequest"))
{
return true;
}
String uri = request.getRequestURI();
if (StringUtils.inStringIgnoreCase(uri, ".json", ".xml"))
{
return true;
}
String ajax = request.getParameter("__ajax");
return StringUtils.inStringIgnoreCase(ajax, "json", "xml");
}
/**
* 内容编码
*
* @param str 内容
* @return 编码后的内容
*/
public static String urlEncode(String str)
{
try
{
return URLEncoder.encode(str, Constants.UTF8);
}
catch (UnsupportedEncodingException e)
{
return StringUtils.EMPTY;
}
}
/**
* 内容解码
*
* @param str 内容
* @return 解码后的内容
*/
public static String urlDecode(String str)
{
try
{
return URLDecoder.decode(str, Constants.UTF8);
}
catch (UnsupportedEncodingException e)
{
return StringUtils.EMPTY;
}
}
/**
* 设置webflux模型响应
*
* @param response ServerHttpResponse
* @param value 响应内容
* @return Mono<Void>
*/
public static Mono<Void> webFluxResponseWriter(ServerHttpResponse response, Object value)
{
return webFluxResponseWriter(response, HttpStatus.OK, value, R.FAIL);
}
/**
* 设置webflux模型响应
*
* @param response ServerHttpResponse
* @param code 响应状态码
* @param value 响应内容
* @return Mono<Void>
*/
public static Mono<Void> webFluxResponseWriter(ServerHttpResponse response, Object value, int code)
{
return webFluxResponseWriter(response, HttpStatus.OK, value, code);
}
/**
* 设置webflux模型响应
*
* @param response ServerHttpResponse
* @param status http状态码
* @param code 响应状态码
* @param value 响应内容
* @return Mono<Void>
*/
public static Mono<Void> webFluxResponseWriter(ServerHttpResponse response, HttpStatus status, Object value, int code)
{
return webFluxResponseWriter(response, MediaType.APPLICATION_JSON_VALUE, status, value, code);
}
/**
* 设置webflux模型响应
*
* @param response ServerHttpResponse
* @param contentType content-type
* @param status http状态码
* @param code 响应状态码
* @param value 响应内容
* @return Mono<Void>
*/
public static Mono<Void> webFluxResponseWriter(ServerHttpResponse response, String contentType, HttpStatus status, Object value, int code)
{
response.setStatusCode(status);
response.getHeaders().add(HttpHeaders.CONTENT_TYPE, contentType);
R<?> result = R.fail(code, value.toString());
DataBuffer dataBuffer = response.bufferFactory().wrap(JSON.toJSONString(result).getBytes());
return response.writeWith(Mono.just(dataBuffer));
}
}
package com.lccet.common.core.utils;
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.stereotype.Component;
/**
* spring工具类 方便在非spring管理环境中获取bean
*
* @author vctgo
*/
@Component
public final class SpringUtils implements BeanFactoryPostProcessor
{
/** Spring应用上下文环境 */
private static ConfigurableListableBeanFactory beanFactory;
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException
{
SpringUtils.beanFactory = beanFactory;
}
/**
* 获取对象
*
* @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();
}
}
package com.lccet.common.core.utils;
import com.github.junrar.Archive;
import com.github.junrar.VolumeManager;
import com.github.junrar.rarfile.FileHeader;
import lombok.extern.slf4j.Slf4j;
import net.lingala.zip4j.core.ZipFile;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* @author zzqtdos
* 描述:
* 创建时间:2023/2/2 16:12
* 修改时间:2023/2/2 16:12
*/
@Slf4j
public class UnPackeUtil {
/**
* zip文件解压
*
* @param destPath 解压文件路径
* @param zipFile 压缩文件
* @param password 解压密码(如果有)
*/
public static void unPackZip(File zipFile, String password, String destPath) {
ZipFile zip = null;
try {
zip = new ZipFile(zipFile);
/*zip4j默认用GBK编码去解压,这里设置编码为GBK的*/
zip.setFileNameCharset("GBK");
log.info("begin unpack zip file....");
zip.extractAll(destPath);
// 如果解压需要密码
if (password != null) {
if (zip.isEncrypted()) {
zip.setPassword(password);
}
}
} catch (Exception e) {
log.error("解压失败:", e.getMessage(), e);
}
}
/**
* rar文件解压(不支持有密码的压缩包)
*
* @param rarFile rar压缩包
* @param destPath 解压保存路径
*/
public static void unPackRar(File rarFile, String destPath) {
try (Archive archive = new Archive((VolumeManager) rarFile)) {
if (null != archive) {
FileHeader fileHeader = archive.nextFileHeader();
File file = null;
while (null != fileHeader) {
// 防止文件名中文乱码问题的处理
String fileName = fileHeader.getFileNameW().isEmpty() ? fileHeader.getFileNameString() : fileHeader.getFileNameW();
if (fileHeader.isDirectory()) {
//是文件夹
file = new File(destPath + File.separator + fileName);
file.mkdirs();
} else {
//不是文件夹
file = new File(destPath + File.separator + fileName.trim());
if (!file.exists()) {
if (!file.getParentFile().exists()) {
// 相对路径可能多级,可能需要创建父目录.
file.getParentFile().mkdirs();
}
file.createNewFile();
}
FileOutputStream os = new FileOutputStream(file);
archive.extractFile(fileHeader, os);
os.close();
}
fileHeader = archive.nextFileHeader();
}
}
} catch (Exception e) {
log.error("解压失败:", e.getMessage(), e);
}
}
}
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment