344 changed files with 36721 additions and 18 deletions
@ -1,23 +1,46 @@ |
|||
# Compiled class file |
|||
*.class |
|||
###################################################################### |
|||
# Build Tools |
|||
|
|||
# Log file |
|||
*.log |
|||
.gradle |
|||
/build/ |
|||
!gradle/wrapper/gradle-wrapper.jar |
|||
|
|||
target/ |
|||
!.mvn/wrapper/maven-wrapper.jar |
|||
|
|||
###################################################################### |
|||
# IDE |
|||
|
|||
# BlueJ files |
|||
*.ctxt |
|||
### STS ### |
|||
.apt_generated |
|||
.classpath |
|||
.factorypath |
|||
.project |
|||
.settings |
|||
.springBeans |
|||
|
|||
# Mobile Tools for Java (J2ME) |
|||
.mtj.tmp/ |
|||
### IntelliJ IDEA ### |
|||
.idea |
|||
*.iws |
|||
*.iml |
|||
*.ipr |
|||
|
|||
# Package Files # |
|||
*.jar |
|||
*.war |
|||
*.nar |
|||
*.ear |
|||
*.zip |
|||
*.tar.gz |
|||
*.rar |
|||
### JRebel ### |
|||
rebel.xml |
|||
### NetBeans ### |
|||
nbproject/private/ |
|||
build/* |
|||
nbbuild/ |
|||
dist/ |
|||
nbdist/ |
|||
.nb-gradle/ |
|||
|
|||
###################################################################### |
|||
# Others |
|||
*.log |
|||
*.xml.versionsBackup |
|||
*.swp |
|||
|
|||
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml |
|||
hs_err_pid* |
|||
!*/build/*.java |
|||
!*/build/*.html |
|||
!*/build/*.xml |
|||
@ -0,0 +1,28 @@ |
|||
<?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.dimensionalnode</groupId> |
|||
<artifactId>bnyer-api</artifactId> |
|||
<version>1.0.0</version> |
|||
</parent> |
|||
<modelVersion>4.0.0</modelVersion> |
|||
|
|||
<artifactId>bnyer-api-system</artifactId> |
|||
|
|||
<description> |
|||
bnyer-api-system系统接口模块 |
|||
</description> |
|||
|
|||
<dependencies> |
|||
|
|||
<!-- bnyer Common Core--> |
|||
<dependency> |
|||
<groupId>com.dimensionalnode</groupId> |
|||
<artifactId>bnyer-common-core</artifactId> |
|||
</dependency> |
|||
|
|||
</dependencies> |
|||
|
|||
</project> |
|||
@ -0,0 +1,29 @@ |
|||
package com.bnyer.system.api; |
|||
|
|||
import com.bnyer.system.api.factory.RemoteFileFallbackFactory; |
|||
import org.springframework.cloud.openfeign.FeignClient; |
|||
import org.springframework.http.MediaType; |
|||
import org.springframework.web.bind.annotation.PostMapping; |
|||
import org.springframework.web.bind.annotation.RequestPart; |
|||
import org.springframework.web.multipart.MultipartFile; |
|||
import com.bnyer.common.core.constant.ServiceNameConstants; |
|||
import com.bnyer.common.core.domain.R; |
|||
import com.bnyer.system.api.domain.SysFile; |
|||
|
|||
/** |
|||
* 文件服务 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
@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); |
|||
} |
|||
@ -0,0 +1,41 @@ |
|||
package com.bnyer.system.api; |
|||
|
|||
import com.bnyer.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.bnyer.common.core.constant.SecurityConstants; |
|||
import com.bnyer.common.core.constant.ServiceNameConstants; |
|||
import com.bnyer.common.core.domain.R; |
|||
import com.bnyer.system.api.domain.SysLogininfor; |
|||
import com.bnyer.system.api.factory.RemoteLogFallbackFactory; |
|||
|
|||
/** |
|||
* 日志服务 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
@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); |
|||
} |
|||
@ -0,0 +1,43 @@ |
|||
package com.bnyer.system.api; |
|||
|
|||
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.bnyer.common.core.constant.SecurityConstants; |
|||
import com.bnyer.common.core.constant.ServiceNameConstants; |
|||
import com.bnyer.common.core.domain.R; |
|||
import com.bnyer.system.api.domain.SysUser; |
|||
import com.bnyer.system.api.factory.RemoteUserFallbackFactory; |
|||
import com.bnyer.system.api.model.LoginUser; |
|||
|
|||
/** |
|||
* 用户服务 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
@FeignClient(contextId = "remoteUserService", value = ServiceNameConstants.SYSTEM_SERVICE, fallbackFactory = RemoteUserFallbackFactory.class) |
|||
public interface RemoteUserService |
|||
{ |
|||
/** |
|||
* 通过用户名查询用户信息 |
|||
* |
|||
* @param username 用户名 |
|||
* @param source 请求来源 |
|||
* @return 结果 |
|||
*/ |
|||
@GetMapping("/user/info/{username}") |
|||
public R<LoginUser> getUserInfo(@PathVariable("username") String username, @RequestHeader(SecurityConstants.FROM_SOURCE) String source); |
|||
|
|||
/** |
|||
* 注册用户信息 |
|||
* |
|||
* @param sysUser 用户信息 |
|||
* @param source 请求来源 |
|||
* @return 结果 |
|||
*/ |
|||
@PostMapping("/user/register") |
|||
public R<Boolean> registerUserInfo(@RequestBody SysUser sysUser, @RequestHeader(SecurityConstants.FROM_SOURCE) String source); |
|||
} |
|||
@ -0,0 +1,202 @@ |
|||
package com.bnyer.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.Size; |
|||
import org.apache.commons.lang3.builder.ToStringBuilder; |
|||
import org.apache.commons.lang3.builder.ToStringStyle; |
|||
import com.bnyer.common.core.web.domain.BaseEntity; |
|||
|
|||
/** |
|||
* 部门表 sys_dept |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
public class SysDept extends BaseEntity |
|||
{ |
|||
private static final long serialVersionUID = 1L; |
|||
|
|||
/** 部门ID */ |
|||
private Long deptId; |
|||
|
|||
/** 父部门ID */ |
|||
private Long parentId; |
|||
|
|||
/** 祖级列表 */ |
|||
private String ancestors; |
|||
|
|||
/** 部门名称 */ |
|||
private String deptName; |
|||
|
|||
/** 显示顺序 */ |
|||
private String orderNum; |
|||
|
|||
/** 负责人 */ |
|||
private String leader; |
|||
|
|||
/** 联系电话 */ |
|||
private String phone; |
|||
|
|||
/** 邮箱 */ |
|||
private String email; |
|||
|
|||
/** 部门状态:0正常,1停用 */ |
|||
private String status; |
|||
|
|||
/** 删除标志(0代表存在 2代表删除) */ |
|||
private String delFlag; |
|||
|
|||
/** 父部门名称 */ |
|||
private String parentName; |
|||
|
|||
/** 子部门 */ |
|||
private List<SysDept> children = new ArrayList<SysDept>(); |
|||
|
|||
public Long getDeptId() |
|||
{ |
|||
return deptId; |
|||
} |
|||
|
|||
public void setDeptId(Long deptId) |
|||
{ |
|||
this.deptId = deptId; |
|||
} |
|||
|
|||
public Long getParentId() |
|||
{ |
|||
return parentId; |
|||
} |
|||
|
|||
public void setParentId(Long parentId) |
|||
{ |
|||
this.parentId = parentId; |
|||
} |
|||
|
|||
public String getAncestors() |
|||
{ |
|||
return ancestors; |
|||
} |
|||
|
|||
public void setAncestors(String ancestors) |
|||
{ |
|||
this.ancestors = ancestors; |
|||
} |
|||
|
|||
@NotBlank(message = "部门名称不能为空") |
|||
@Size(min = 0, max = 30, message = "部门名称长度不能超过30个字符") |
|||
public String getDeptName() |
|||
{ |
|||
return deptName; |
|||
} |
|||
|
|||
public void setDeptName(String deptName) |
|||
{ |
|||
this.deptName = deptName; |
|||
} |
|||
|
|||
@NotBlank(message = "显示顺序不能为空") |
|||
public String getOrderNum() |
|||
{ |
|||
return orderNum; |
|||
} |
|||
|
|||
public void setOrderNum(String orderNum) |
|||
{ |
|||
this.orderNum = orderNum; |
|||
} |
|||
|
|||
public String getLeader() |
|||
{ |
|||
return leader; |
|||
} |
|||
|
|||
public void setLeader(String leader) |
|||
{ |
|||
this.leader = leader; |
|||
} |
|||
|
|||
@Size(min = 0, max = 11, message = "联系电话长度不能超过11个字符") |
|||
public String getPhone() |
|||
{ |
|||
return phone; |
|||
} |
|||
|
|||
public void setPhone(String phone) |
|||
{ |
|||
this.phone = phone; |
|||
} |
|||
|
|||
@Email(message = "邮箱格式不正确") |
|||
@Size(min = 0, max = 50, message = "邮箱长度不能超过50个字符") |
|||
public String getEmail() |
|||
{ |
|||
return email; |
|||
} |
|||
|
|||
public void setEmail(String email) |
|||
{ |
|||
this.email = email; |
|||
} |
|||
|
|||
public String getStatus() |
|||
{ |
|||
return status; |
|||
} |
|||
|
|||
public void setStatus(String status) |
|||
{ |
|||
this.status = status; |
|||
} |
|||
|
|||
public String getDelFlag() |
|||
{ |
|||
return delFlag; |
|||
} |
|||
|
|||
public void setDelFlag(String delFlag) |
|||
{ |
|||
this.delFlag = delFlag; |
|||
} |
|||
|
|||
public String getParentName() |
|||
{ |
|||
return parentName; |
|||
} |
|||
|
|||
public void setParentName(String parentName) |
|||
{ |
|||
this.parentName = parentName; |
|||
} |
|||
|
|||
public List<SysDept> getChildren() |
|||
{ |
|||
return children; |
|||
} |
|||
|
|||
public void setChildren(List<SysDept> children) |
|||
{ |
|||
this.children = children; |
|||
} |
|||
|
|||
@Override |
|||
public String toString() { |
|||
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) |
|||
.append("deptId", getDeptId()) |
|||
.append("parentId", getParentId()) |
|||
.append("ancestors", getAncestors()) |
|||
.append("deptName", getDeptName()) |
|||
.append("orderNum", getOrderNum()) |
|||
.append("leader", getLeader()) |
|||
.append("phone", getPhone()) |
|||
.append("email", getEmail()) |
|||
.append("status", getStatus()) |
|||
.append("delFlag", getDelFlag()) |
|||
.append("createBy", getCreateBy()) |
|||
.append("createTime", getCreateTime()) |
|||
.append("updateBy", getUpdateBy()) |
|||
.append("updateTime", getUpdateTime()) |
|||
.toString(); |
|||
} |
|||
} |
|||
@ -0,0 +1,176 @@ |
|||
package com.bnyer.system.api.domain; |
|||
|
|||
import javax.validation.constraints.NotBlank; |
|||
import javax.validation.constraints.Size; |
|||
import org.apache.commons.lang3.builder.ToStringBuilder; |
|||
import org.apache.commons.lang3.builder.ToStringStyle; |
|||
import com.bnyer.common.core.annotation.Excel; |
|||
import com.bnyer.common.core.annotation.Excel.ColumnType; |
|||
import com.bnyer.common.core.constant.UserConstants; |
|||
import com.bnyer.common.core.web.domain.BaseEntity; |
|||
|
|||
/** |
|||
* 字典数据表 sys_dict_data |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
public class SysDictData extends BaseEntity |
|||
{ |
|||
private static final long serialVersionUID = 1L; |
|||
|
|||
/** 字典编码 */ |
|||
@Excel(name = "字典编码", cellType = ColumnType.NUMERIC) |
|||
private Long dictCode; |
|||
|
|||
/** 字典排序 */ |
|||
@Excel(name = "字典排序", cellType = ColumnType.NUMERIC) |
|||
private Long dictSort; |
|||
|
|||
/** 字典标签 */ |
|||
@Excel(name = "字典标签") |
|||
private String dictLabel; |
|||
|
|||
/** 字典键值 */ |
|||
@Excel(name = "字典键值") |
|||
private String dictValue; |
|||
|
|||
/** 字典类型 */ |
|||
@Excel(name = "字典类型") |
|||
private String dictType; |
|||
|
|||
/** 样式属性(其他样式扩展) */ |
|||
private String cssClass; |
|||
|
|||
/** 表格字典样式 */ |
|||
private String listClass; |
|||
|
|||
/** 是否默认(Y是 N否) */ |
|||
@Excel(name = "是否默认", readConverterExp = "Y=是,N=否") |
|||
private String isDefault; |
|||
|
|||
/** 状态(0正常 1停用) */ |
|||
@Excel(name = "状态", readConverterExp = "0=正常,1=停用") |
|||
private String status; |
|||
|
|||
public Long getDictCode() |
|||
{ |
|||
return dictCode; |
|||
} |
|||
|
|||
public void setDictCode(Long dictCode) |
|||
{ |
|||
this.dictCode = dictCode; |
|||
} |
|||
|
|||
public Long getDictSort() |
|||
{ |
|||
return dictSort; |
|||
} |
|||
|
|||
public void setDictSort(Long dictSort) |
|||
{ |
|||
this.dictSort = dictSort; |
|||
} |
|||
|
|||
@NotBlank(message = "字典标签不能为空") |
|||
@Size(min = 0, max = 100, message = "字典标签长度不能超过100个字符") |
|||
public String getDictLabel() |
|||
{ |
|||
return dictLabel; |
|||
} |
|||
|
|||
public void setDictLabel(String dictLabel) |
|||
{ |
|||
this.dictLabel = dictLabel; |
|||
} |
|||
|
|||
@NotBlank(message = "字典键值不能为空") |
|||
@Size(min = 0, max = 100, message = "字典键值长度不能超过100个字符") |
|||
public String getDictValue() |
|||
{ |
|||
return dictValue; |
|||
} |
|||
|
|||
public void setDictValue(String dictValue) |
|||
{ |
|||
this.dictValue = dictValue; |
|||
} |
|||
|
|||
@NotBlank(message = "字典类型不能为空") |
|||
@Size(min = 0, max = 100, message = "字典类型长度不能超过100个字符") |
|||
public String getDictType() |
|||
{ |
|||
return dictType; |
|||
} |
|||
|
|||
public void setDictType(String dictType) |
|||
{ |
|||
this.dictType = dictType; |
|||
} |
|||
|
|||
@Size(min = 0, max = 100, message = "样式属性长度不能超过100个字符") |
|||
public String getCssClass() |
|||
{ |
|||
return cssClass; |
|||
} |
|||
|
|||
public void setCssClass(String cssClass) |
|||
{ |
|||
this.cssClass = cssClass; |
|||
} |
|||
|
|||
public String getListClass() |
|||
{ |
|||
return listClass; |
|||
} |
|||
|
|||
public void setListClass(String listClass) |
|||
{ |
|||
this.listClass = listClass; |
|||
} |
|||
|
|||
public boolean getDefault() |
|||
{ |
|||
return UserConstants.YES.equals(this.isDefault) ? true : false; |
|||
} |
|||
|
|||
public String getIsDefault() |
|||
{ |
|||
return isDefault; |
|||
} |
|||
|
|||
public void setIsDefault(String isDefault) |
|||
{ |
|||
this.isDefault = isDefault; |
|||
} |
|||
|
|||
public String getStatus() |
|||
{ |
|||
return status; |
|||
} |
|||
|
|||
public void setStatus(String status) |
|||
{ |
|||
this.status = status; |
|||
} |
|||
|
|||
@Override |
|||
public String toString() { |
|||
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) |
|||
.append("dictCode", getDictCode()) |
|||
.append("dictSort", getDictSort()) |
|||
.append("dictLabel", getDictLabel()) |
|||
.append("dictValue", getDictValue()) |
|||
.append("dictType", getDictType()) |
|||
.append("cssClass", getCssClass()) |
|||
.append("listClass", getListClass()) |
|||
.append("isDefault", getIsDefault()) |
|||
.append("status", getStatus()) |
|||
.append("createBy", getCreateBy()) |
|||
.append("createTime", getCreateTime()) |
|||
.append("updateBy", getUpdateBy()) |
|||
.append("updateTime", getUpdateTime()) |
|||
.append("remark", getRemark()) |
|||
.toString(); |
|||
} |
|||
} |
|||
@ -0,0 +1,94 @@ |
|||
package com.bnyer.system.api.domain; |
|||
|
|||
import javax.validation.constraints.NotBlank; |
|||
import javax.validation.constraints.Size; |
|||
import org.apache.commons.lang3.builder.ToStringBuilder; |
|||
import org.apache.commons.lang3.builder.ToStringStyle; |
|||
import com.bnyer.common.core.annotation.Excel; |
|||
import com.bnyer.common.core.annotation.Excel.ColumnType; |
|||
import com.bnyer.common.core.web.domain.BaseEntity; |
|||
|
|||
/** |
|||
* 字典类型表 sys_dict_type |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
public class SysDictType extends BaseEntity |
|||
{ |
|||
private static final long serialVersionUID = 1L; |
|||
|
|||
/** 字典主键 */ |
|||
@Excel(name = "字典主键", cellType = ColumnType.NUMERIC) |
|||
private Long dictId; |
|||
|
|||
/** 字典名称 */ |
|||
@Excel(name = "字典名称") |
|||
private String dictName; |
|||
|
|||
/** 字典类型 */ |
|||
@Excel(name = "字典类型") |
|||
private String dictType; |
|||
|
|||
/** 状态(0正常 1停用) */ |
|||
@Excel(name = "状态", readConverterExp = "0=正常,1=停用") |
|||
private String status; |
|||
|
|||
public Long getDictId() |
|||
{ |
|||
return dictId; |
|||
} |
|||
|
|||
public void setDictId(Long dictId) |
|||
{ |
|||
this.dictId = dictId; |
|||
} |
|||
|
|||
@NotBlank(message = "字典名称不能为空") |
|||
@Size(min = 0, max = 100, message = "字典类型名称长度不能超过100个字符") |
|||
public String getDictName() |
|||
{ |
|||
return dictName; |
|||
} |
|||
|
|||
public void setDictName(String dictName) |
|||
{ |
|||
this.dictName = dictName; |
|||
} |
|||
|
|||
@NotBlank(message = "字典类型不能为空") |
|||
@Size(min = 0, max = 100, message = "字典类型类型长度不能超过100个字符") |
|||
public String getDictType() |
|||
{ |
|||
return dictType; |
|||
} |
|||
|
|||
public void setDictType(String dictType) |
|||
{ |
|||
this.dictType = dictType; |
|||
} |
|||
|
|||
public String getStatus() |
|||
{ |
|||
return status; |
|||
} |
|||
|
|||
public void setStatus(String status) |
|||
{ |
|||
this.status = status; |
|||
} |
|||
|
|||
@Override |
|||
public String toString() { |
|||
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) |
|||
.append("dictId", getDictId()) |
|||
.append("dictName", getDictName()) |
|||
.append("dictType", getDictType()) |
|||
.append("status", getStatus()) |
|||
.append("createBy", getCreateBy()) |
|||
.append("createTime", getCreateTime()) |
|||
.append("updateBy", getUpdateBy()) |
|||
.append("updateTime", getUpdateTime()) |
|||
.append("remark", getRemark()) |
|||
.toString(); |
|||
} |
|||
} |
|||
@ -0,0 +1,50 @@ |
|||
package com.bnyer.system.api.domain; |
|||
|
|||
import org.apache.commons.lang3.builder.ToStringBuilder; |
|||
import org.apache.commons.lang3.builder.ToStringStyle; |
|||
|
|||
/** |
|||
* 文件信息 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
public class SysFile |
|||
{ |
|||
/** |
|||
* 文件名称 |
|||
*/ |
|||
private String name; |
|||
|
|||
/** |
|||
* 文件地址 |
|||
*/ |
|||
private String url; |
|||
|
|||
public String getName() |
|||
{ |
|||
return name; |
|||
} |
|||
|
|||
public void setName(String name) |
|||
{ |
|||
this.name = name; |
|||
} |
|||
|
|||
public String getUrl() |
|||
{ |
|||
return url; |
|||
} |
|||
|
|||
public void setUrl(String url) |
|||
{ |
|||
this.url = url; |
|||
} |
|||
|
|||
@Override |
|||
public String toString() { |
|||
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) |
|||
.append("name", getName()) |
|||
.append("url", getUrl()) |
|||
.toString(); |
|||
} |
|||
} |
|||
@ -0,0 +1,102 @@ |
|||
package com.bnyer.system.api.domain; |
|||
|
|||
import java.util.Date; |
|||
import com.fasterxml.jackson.annotation.JsonFormat; |
|||
import com.bnyer.common.core.annotation.Excel; |
|||
import com.bnyer.common.core.annotation.Excel.ColumnType; |
|||
import com.bnyer.common.core.web.domain.BaseEntity; |
|||
|
|||
/** |
|||
* 系统访问记录表 sys_logininfor |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
public class SysLogininfor extends BaseEntity |
|||
{ |
|||
private static final long serialVersionUID = 1L; |
|||
|
|||
/** ID */ |
|||
@Excel(name = "序号", cellType = ColumnType.NUMERIC) |
|||
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; |
|||
|
|||
public Long getInfoId() |
|||
{ |
|||
return infoId; |
|||
} |
|||
|
|||
public void setInfoId(Long infoId) |
|||
{ |
|||
this.infoId = infoId; |
|||
} |
|||
|
|||
public String getUserName() |
|||
{ |
|||
return userName; |
|||
} |
|||
|
|||
public void setUserName(String userName) |
|||
{ |
|||
this.userName = userName; |
|||
} |
|||
|
|||
public String getStatus() |
|||
{ |
|||
return status; |
|||
} |
|||
|
|||
public void setStatus(String status) |
|||
{ |
|||
this.status = status; |
|||
} |
|||
|
|||
public String getIpaddr() |
|||
{ |
|||
return ipaddr; |
|||
} |
|||
|
|||
public void setIpaddr(String ipaddr) |
|||
{ |
|||
this.ipaddr = ipaddr; |
|||
} |
|||
|
|||
public String getMsg() |
|||
{ |
|||
return msg; |
|||
} |
|||
|
|||
public void setMsg(String msg) |
|||
{ |
|||
this.msg = msg; |
|||
} |
|||
|
|||
public Date getAccessTime() |
|||
{ |
|||
return accessTime; |
|||
} |
|||
|
|||
public void setAccessTime(Date accessTime) |
|||
{ |
|||
this.accessTime = accessTime; |
|||
} |
|||
} |
|||
@ -0,0 +1,241 @@ |
|||
package com.bnyer.system.api.domain; |
|||
|
|||
import java.util.Date; |
|||
import com.fasterxml.jackson.annotation.JsonFormat; |
|||
import com.bnyer.common.core.annotation.Excel; |
|||
import com.bnyer.common.core.annotation.Excel.ColumnType; |
|||
import com.bnyer.common.core.web.domain.BaseEntity; |
|||
|
|||
/** |
|||
* 操作日志记录表 oper_log |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
public class SysOperLog extends BaseEntity |
|||
{ |
|||
private static final long serialVersionUID = 1L; |
|||
|
|||
/** 日志主键 */ |
|||
@Excel(name = "操作序号", cellType = ColumnType.NUMERIC) |
|||
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; |
|||
|
|||
public Long getOperId() |
|||
{ |
|||
return operId; |
|||
} |
|||
|
|||
public void setOperId(Long operId) |
|||
{ |
|||
this.operId = operId; |
|||
} |
|||
|
|||
public String getTitle() |
|||
{ |
|||
return title; |
|||
} |
|||
|
|||
public void setTitle(String title) |
|||
{ |
|||
this.title = title; |
|||
} |
|||
|
|||
public Integer getBusinessType() |
|||
{ |
|||
return businessType; |
|||
} |
|||
|
|||
public void setBusinessType(Integer businessType) |
|||
{ |
|||
this.businessType = businessType; |
|||
} |
|||
|
|||
public Integer[] getBusinessTypes() |
|||
{ |
|||
return businessTypes; |
|||
} |
|||
|
|||
public void setBusinessTypes(Integer[] businessTypes) |
|||
{ |
|||
this.businessTypes = businessTypes; |
|||
} |
|||
|
|||
public String getMethod() |
|||
{ |
|||
return method; |
|||
} |
|||
|
|||
public void setMethod(String method) |
|||
{ |
|||
this.method = method; |
|||
} |
|||
|
|||
public String getRequestMethod() |
|||
{ |
|||
return requestMethod; |
|||
} |
|||
|
|||
public void setRequestMethod(String requestMethod) |
|||
{ |
|||
this.requestMethod = requestMethod; |
|||
} |
|||
|
|||
public Integer getOperatorType() |
|||
{ |
|||
return operatorType; |
|||
} |
|||
|
|||
public void setOperatorType(Integer operatorType) |
|||
{ |
|||
this.operatorType = operatorType; |
|||
} |
|||
|
|||
public String getOperName() |
|||
{ |
|||
return operName; |
|||
} |
|||
|
|||
public void setOperName(String operName) |
|||
{ |
|||
this.operName = operName; |
|||
} |
|||
|
|||
public String getDeptName() |
|||
{ |
|||
return deptName; |
|||
} |
|||
|
|||
public void setDeptName(String deptName) |
|||
{ |
|||
this.deptName = deptName; |
|||
} |
|||
|
|||
public String getOperUrl() |
|||
{ |
|||
return operUrl; |
|||
} |
|||
|
|||
public void setOperUrl(String operUrl) |
|||
{ |
|||
this.operUrl = operUrl; |
|||
} |
|||
|
|||
public String getOperIp() |
|||
{ |
|||
return operIp; |
|||
} |
|||
|
|||
public void setOperIp(String operIp) |
|||
{ |
|||
this.operIp = operIp; |
|||
} |
|||
|
|||
public String getOperParam() |
|||
{ |
|||
return operParam; |
|||
} |
|||
|
|||
public void setOperParam(String operParam) |
|||
{ |
|||
this.operParam = operParam; |
|||
} |
|||
|
|||
public String getJsonResult() |
|||
{ |
|||
return jsonResult; |
|||
} |
|||
|
|||
public void setJsonResult(String jsonResult) |
|||
{ |
|||
this.jsonResult = jsonResult; |
|||
} |
|||
|
|||
public Integer getStatus() |
|||
{ |
|||
return status; |
|||
} |
|||
|
|||
public void setStatus(Integer status) |
|||
{ |
|||
this.status = status; |
|||
} |
|||
|
|||
public String getErrorMsg() |
|||
{ |
|||
return errorMsg; |
|||
} |
|||
|
|||
public void setErrorMsg(String errorMsg) |
|||
{ |
|||
this.errorMsg = errorMsg; |
|||
} |
|||
|
|||
public Date getOperTime() |
|||
{ |
|||
return operTime; |
|||
} |
|||
|
|||
public void setOperTime(Date operTime) |
|||
{ |
|||
this.operTime = operTime; |
|||
} |
|||
} |
|||
@ -0,0 +1,226 @@ |
|||
package com.bnyer.system.api.domain; |
|||
|
|||
import javax.validation.constraints.NotBlank; |
|||
import javax.validation.constraints.Size; |
|||
import org.apache.commons.lang3.builder.ToStringBuilder; |
|||
import org.apache.commons.lang3.builder.ToStringStyle; |
|||
import com.bnyer.common.core.annotation.Excel; |
|||
import com.bnyer.common.core.annotation.Excel.ColumnType; |
|||
import com.bnyer.common.core.web.domain.BaseEntity; |
|||
|
|||
/** |
|||
* 角色表 sys_role |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
public class SysRole extends BaseEntity |
|||
{ |
|||
private static final long serialVersionUID = 1L; |
|||
|
|||
/** 角色ID */ |
|||
@Excel(name = "角色序号", cellType = ColumnType.NUMERIC) |
|||
private Long roleId; |
|||
|
|||
/** 角色名称 */ |
|||
@Excel(name = "角色名称") |
|||
private String roleName; |
|||
|
|||
/** 角色权限 */ |
|||
@Excel(name = "角色权限") |
|||
private String roleKey; |
|||
|
|||
/** 角色排序 */ |
|||
@Excel(name = "角色排序") |
|||
private String roleSort; |
|||
|
|||
/** 数据范围(1:所有数据权限;2:自定义数据权限;3:本部门数据权限;4:本部门及以下数据权限;5:仅本人数据权限) */ |
|||
@Excel(name = "数据范围", readConverterExp = "1=所有数据权限,2=自定义数据权限,3=本部门数据权限,4=本部门及以下数据权限,5=仅本人数据权限") |
|||
private String dataScope; |
|||
|
|||
/** 菜单树选择项是否关联显示( 0:父子不互相关联显示 1:父子互相关联显示) */ |
|||
private boolean menuCheckStrictly; |
|||
|
|||
/** 部门树选择项是否关联显示(0:父子不互相关联显示 1:父子互相关联显示 ) */ |
|||
private boolean deptCheckStrictly; |
|||
|
|||
/** 角色状态(0正常 1停用) */ |
|||
@Excel(name = "角色状态", readConverterExp = "0=正常,1=停用") |
|||
private String status; |
|||
|
|||
/** 删除标志(0代表存在 2代表删除) */ |
|||
private String delFlag; |
|||
|
|||
/** 用户是否存在此角色标识 默认不存在 */ |
|||
private boolean flag = false; |
|||
|
|||
/** 菜单组 */ |
|||
private Long[] menuIds; |
|||
|
|||
/** 部门组(数据权限) */ |
|||
private Long[] deptIds; |
|||
|
|||
public SysRole() |
|||
{ |
|||
|
|||
} |
|||
|
|||
public SysRole(Long roleId) |
|||
{ |
|||
this.roleId = roleId; |
|||
} |
|||
|
|||
public Long getRoleId() |
|||
{ |
|||
return roleId; |
|||
} |
|||
|
|||
public void setRoleId(Long roleId) |
|||
{ |
|||
this.roleId = roleId; |
|||
} |
|||
|
|||
public boolean isAdmin() |
|||
{ |
|||
return isAdmin(this.roleId); |
|||
} |
|||
|
|||
public static boolean isAdmin(Long roleId) |
|||
{ |
|||
return roleId != null && 1L == roleId; |
|||
} |
|||
|
|||
@NotBlank(message = "角色名称不能为空") |
|||
@Size(min = 0, max = 30, message = "角色名称长度不能超过30个字符") |
|||
public String getRoleName() |
|||
{ |
|||
return roleName; |
|||
} |
|||
|
|||
public void setRoleName(String roleName) |
|||
{ |
|||
this.roleName = roleName; |
|||
} |
|||
|
|||
@NotBlank(message = "权限字符不能为空") |
|||
@Size(min = 0, max = 100, message = "权限字符长度不能超过100个字符") |
|||
public String getRoleKey() |
|||
{ |
|||
return roleKey; |
|||
} |
|||
|
|||
public void setRoleKey(String roleKey) |
|||
{ |
|||
this.roleKey = roleKey; |
|||
} |
|||
|
|||
@NotBlank(message = "显示顺序不能为空") |
|||
public String getRoleSort() |
|||
{ |
|||
return roleSort; |
|||
} |
|||
|
|||
public void setRoleSort(String roleSort) |
|||
{ |
|||
this.roleSort = roleSort; |
|||
} |
|||
|
|||
public String getDataScope() |
|||
{ |
|||
return dataScope; |
|||
} |
|||
|
|||
public void setDataScope(String dataScope) |
|||
{ |
|||
this.dataScope = dataScope; |
|||
} |
|||
|
|||
public boolean isMenuCheckStrictly() |
|||
{ |
|||
return menuCheckStrictly; |
|||
} |
|||
|
|||
public void setMenuCheckStrictly(boolean menuCheckStrictly) |
|||
{ |
|||
this.menuCheckStrictly = menuCheckStrictly; |
|||
} |
|||
|
|||
public boolean isDeptCheckStrictly() |
|||
{ |
|||
return deptCheckStrictly; |
|||
} |
|||
|
|||
public void setDeptCheckStrictly(boolean deptCheckStrictly) |
|||
{ |
|||
this.deptCheckStrictly = deptCheckStrictly; |
|||
} |
|||
|
|||
public String getStatus() |
|||
{ |
|||
return status; |
|||
} |
|||
|
|||
public void setStatus(String status) |
|||
{ |
|||
this.status = status; |
|||
} |
|||
|
|||
public String getDelFlag() |
|||
{ |
|||
return delFlag; |
|||
} |
|||
|
|||
public void setDelFlag(String delFlag) |
|||
{ |
|||
this.delFlag = delFlag; |
|||
} |
|||
|
|||
public boolean isFlag() |
|||
{ |
|||
return flag; |
|||
} |
|||
|
|||
public void setFlag(boolean flag) |
|||
{ |
|||
this.flag = flag; |
|||
} |
|||
|
|||
public Long[] getMenuIds() |
|||
{ |
|||
return menuIds; |
|||
} |
|||
|
|||
public void setMenuIds(Long[] menuIds) |
|||
{ |
|||
this.menuIds = menuIds; |
|||
} |
|||
|
|||
public Long[] getDeptIds() |
|||
{ |
|||
return deptIds; |
|||
} |
|||
|
|||
public void setDeptIds(Long[] deptIds) |
|||
{ |
|||
this.deptIds = deptIds; |
|||
} |
|||
|
|||
@Override |
|||
public String toString() { |
|||
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) |
|||
.append("roleId", getRoleId()) |
|||
.append("roleName", getRoleName()) |
|||
.append("roleKey", getRoleKey()) |
|||
.append("roleSort", getRoleSort()) |
|||
.append("dataScope", getDataScope()) |
|||
.append("menuCheckStrictly", isMenuCheckStrictly()) |
|||
.append("deptCheckStrictly", isDeptCheckStrictly()) |
|||
.append("status", getStatus()) |
|||
.append("delFlag", getDelFlag()) |
|||
.append("createBy", getCreateBy()) |
|||
.append("createTime", getCreateTime()) |
|||
.append("updateBy", getUpdateBy()) |
|||
.append("updateTime", getUpdateTime()) |
|||
.append("remark", getRemark()) |
|||
.toString(); |
|||
} |
|||
} |
|||
@ -0,0 +1,325 @@ |
|||
package com.bnyer.system.api.domain; |
|||
|
|||
import java.util.Date; |
|||
import java.util.List; |
|||
import javax.validation.constraints.*; |
|||
import org.apache.commons.lang3.builder.ToStringBuilder; |
|||
import org.apache.commons.lang3.builder.ToStringStyle; |
|||
import com.fasterxml.jackson.annotation.JsonProperty; |
|||
import com.bnyer.common.core.annotation.Excel; |
|||
import com.bnyer.common.core.annotation.Excel.ColumnType; |
|||
import com.bnyer.common.core.annotation.Excel.Type; |
|||
import com.bnyer.common.core.annotation.Excels; |
|||
import com.bnyer.common.core.web.domain.BaseEntity; |
|||
import com.bnyer.common.core.xss.Xss; |
|||
|
|||
/** |
|||
* 用户对象 sys_user |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
public class SysUser extends BaseEntity |
|||
{ |
|||
private static final long serialVersionUID = 1L; |
|||
|
|||
/** 用户ID */ |
|||
@Excel(name = "用户序号", cellType = ColumnType.NUMERIC, prompt = "用户编号") |
|||
private Long userId; |
|||
|
|||
/** 部门ID */ |
|||
@Excel(name = "部门编号", type = Type.IMPORT) |
|||
private Long deptId; |
|||
|
|||
/** 用户账号 */ |
|||
@Excel(name = "登录名称") |
|||
private String userName; |
|||
|
|||
/** 用户昵称 */ |
|||
@Excel(name = "用户名称") |
|||
private String nickName; |
|||
|
|||
/** 用户邮箱 */ |
|||
@Excel(name = "用户邮箱") |
|||
private String email; |
|||
|
|||
/** 手机号码 */ |
|||
@Excel(name = "手机号码") |
|||
private String phonenumber; |
|||
|
|||
/** 用户性别 */ |
|||
@Excel(name = "用户性别", readConverterExp = "0=男,1=女,2=未知") |
|||
private String sex; |
|||
|
|||
/** 用户头像 */ |
|||
private String avatar; |
|||
|
|||
/** 密码 */ |
|||
private String password; |
|||
|
|||
/** 帐号状态(0正常 1停用) */ |
|||
@Excel(name = "帐号状态", readConverterExp = "0=正常,1=停用") |
|||
private String status; |
|||
|
|||
/** 删除标志(0代表存在 2代表删除) */ |
|||
private String delFlag; |
|||
|
|||
/** 最后登录IP */ |
|||
@Excel(name = "最后登录IP", type = Type.EXPORT) |
|||
private String loginIp; |
|||
|
|||
/** 最后登录时间 */ |
|||
@Excel(name = "最后登录时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss", type = Type.EXPORT) |
|||
private Date loginDate; |
|||
|
|||
/** 部门对象 */ |
|||
@Excels({ |
|||
@Excel(name = "部门名称", targetAttr = "deptName", type = Type.EXPORT), |
|||
@Excel(name = "部门负责人", targetAttr = "leader", type = Type.EXPORT) |
|||
}) |
|||
private SysDept dept; |
|||
|
|||
/** 角色对象 */ |
|||
private List<SysRole> roles; |
|||
|
|||
/** 角色组 */ |
|||
private Long[] roleIds; |
|||
|
|||
/** 岗位组 */ |
|||
private Long[] postIds; |
|||
|
|||
/** 角色ID */ |
|||
private Long roleId; |
|||
|
|||
public SysUser() |
|||
{ |
|||
|
|||
} |
|||
|
|||
public SysUser(Long userId) |
|||
{ |
|||
this.userId = userId; |
|||
} |
|||
|
|||
public Long getUserId() |
|||
{ |
|||
return userId; |
|||
} |
|||
|
|||
public void setUserId(Long userId) |
|||
{ |
|||
this.userId = userId; |
|||
} |
|||
|
|||
public boolean isAdmin() |
|||
{ |
|||
return isAdmin(this.userId); |
|||
} |
|||
|
|||
public static boolean isAdmin(Long userId) |
|||
{ |
|||
return userId != null && 1L == userId; |
|||
} |
|||
|
|||
public Long getDeptId() |
|||
{ |
|||
return deptId; |
|||
} |
|||
|
|||
public void setDeptId(Long deptId) |
|||
{ |
|||
this.deptId = deptId; |
|||
} |
|||
|
|||
@Xss(message = "用户昵称不能包含脚本字符") |
|||
@Size(min = 0, max = 30, message = "用户昵称长度不能超过30个字符") |
|||
public String getNickName() |
|||
{ |
|||
return nickName; |
|||
} |
|||
|
|||
public void setNickName(String nickName) |
|||
{ |
|||
this.nickName = nickName; |
|||
} |
|||
|
|||
@Xss(message = "用户账号不能包含脚本字符") |
|||
@NotBlank(message = "用户账号不能为空") |
|||
@Size(min = 0, max = 30, message = "用户账号长度不能超过30个字符") |
|||
public String getUserName() |
|||
{ |
|||
return userName; |
|||
} |
|||
|
|||
public void setUserName(String userName) |
|||
{ |
|||
this.userName = userName; |
|||
} |
|||
|
|||
@Email(message = "邮箱格式不正确") |
|||
@Size(min = 0, max = 50, message = "邮箱长度不能超过50个字符") |
|||
public String getEmail() |
|||
{ |
|||
return email; |
|||
} |
|||
|
|||
public void setEmail(String email) |
|||
{ |
|||
this.email = email; |
|||
} |
|||
|
|||
@Size(min = 0, max = 11, message = "手机号码长度不能超过11个字符") |
|||
public String getPhonenumber() |
|||
{ |
|||
return phonenumber; |
|||
} |
|||
|
|||
public void setPhonenumber(String phonenumber) |
|||
{ |
|||
this.phonenumber = phonenumber; |
|||
} |
|||
|
|||
public String getSex() |
|||
{ |
|||
return sex; |
|||
} |
|||
|
|||
public void setSex(String sex) |
|||
{ |
|||
this.sex = sex; |
|||
} |
|||
|
|||
public String getAvatar() |
|||
{ |
|||
return avatar; |
|||
} |
|||
|
|||
public void setAvatar(String avatar) |
|||
{ |
|||
this.avatar = avatar; |
|||
} |
|||
|
|||
@JsonProperty |
|||
public String getPassword() |
|||
{ |
|||
return password; |
|||
} |
|||
|
|||
public void setPassword(String password) |
|||
{ |
|||
this.password = password; |
|||
} |
|||
|
|||
public String getStatus() |
|||
{ |
|||
return status; |
|||
} |
|||
|
|||
public void setStatus(String status) |
|||
{ |
|||
this.status = status; |
|||
} |
|||
|
|||
public String getDelFlag() |
|||
{ |
|||
return delFlag; |
|||
} |
|||
|
|||
public void setDelFlag(String delFlag) |
|||
{ |
|||
this.delFlag = delFlag; |
|||
} |
|||
|
|||
public String getLoginIp() |
|||
{ |
|||
return loginIp; |
|||
} |
|||
|
|||
public void setLoginIp(String loginIp) |
|||
{ |
|||
this.loginIp = loginIp; |
|||
} |
|||
|
|||
public Date getLoginDate() |
|||
{ |
|||
return loginDate; |
|||
} |
|||
|
|||
public void setLoginDate(Date loginDate) |
|||
{ |
|||
this.loginDate = loginDate; |
|||
} |
|||
|
|||
public SysDept getDept() |
|||
{ |
|||
return dept; |
|||
} |
|||
|
|||
public void setDept(SysDept dept) |
|||
{ |
|||
this.dept = dept; |
|||
} |
|||
|
|||
public List<SysRole> getRoles() |
|||
{ |
|||
return roles; |
|||
} |
|||
|
|||
public void setRoles(List<SysRole> roles) |
|||
{ |
|||
this.roles = roles; |
|||
} |
|||
|
|||
public Long[] getRoleIds() |
|||
{ |
|||
return roleIds; |
|||
} |
|||
|
|||
public void setRoleIds(Long[] roleIds) |
|||
{ |
|||
this.roleIds = roleIds; |
|||
} |
|||
|
|||
public Long[] getPostIds() |
|||
{ |
|||
return postIds; |
|||
} |
|||
|
|||
public void setPostIds(Long[] postIds) |
|||
{ |
|||
this.postIds = postIds; |
|||
} |
|||
|
|||
public Long getRoleId() |
|||
{ |
|||
return roleId; |
|||
} |
|||
|
|||
public void setRoleId(Long roleId) |
|||
{ |
|||
this.roleId = roleId; |
|||
} |
|||
@Override |
|||
public String toString() { |
|||
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) |
|||
.append("userId", getUserId()) |
|||
.append("deptId", getDeptId()) |
|||
.append("userName", getUserName()) |
|||
.append("nickName", getNickName()) |
|||
.append("email", getEmail()) |
|||
.append("phonenumber", getPhonenumber()) |
|||
.append("sex", getSex()) |
|||
.append("avatar", getAvatar()) |
|||
.append("password", getPassword()) |
|||
.append("status", getStatus()) |
|||
.append("delFlag", getDelFlag()) |
|||
.append("loginIp", getLoginIp()) |
|||
.append("loginDate", getLoginDate()) |
|||
.append("createBy", getCreateBy()) |
|||
.append("createTime", getCreateTime()) |
|||
.append("updateBy", getUpdateBy()) |
|||
.append("updateTime", getUpdateTime()) |
|||
.append("remark", getRemark()) |
|||
.append("dept", getDept()) |
|||
.toString(); |
|||
} |
|||
} |
|||
@ -0,0 +1,35 @@ |
|||
package com.bnyer.system.api.factory; |
|||
|
|||
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.bnyer.common.core.domain.R; |
|||
import com.bnyer.system.api.RemoteFileService; |
|||
import com.bnyer.system.api.domain.SysFile; |
|||
|
|||
/** |
|||
* 文件服务降级处理 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
@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()); |
|||
} |
|||
}; |
|||
} |
|||
} |
|||
@ -0,0 +1,42 @@ |
|||
package com.bnyer.system.api.factory; |
|||
|
|||
import com.bnyer.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.bnyer.common.core.domain.R; |
|||
import com.bnyer.system.api.RemoteLogService; |
|||
import com.bnyer.system.api.domain.SysLogininfor; |
|||
|
|||
/** |
|||
* 日志服务降级处理 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
@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; |
|||
} |
|||
}; |
|||
|
|||
} |
|||
} |
|||
@ -0,0 +1,41 @@ |
|||
package com.bnyer.system.api.factory; |
|||
|
|||
import org.slf4j.Logger; |
|||
import org.slf4j.LoggerFactory; |
|||
import org.springframework.cloud.openfeign.FallbackFactory; |
|||
import org.springframework.stereotype.Component; |
|||
import com.bnyer.common.core.domain.R; |
|||
import com.bnyer.system.api.RemoteUserService; |
|||
import com.bnyer.system.api.domain.SysUser; |
|||
import com.bnyer.system.api.model.LoginUser; |
|||
|
|||
/** |
|||
* 用户服务降级处理 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
@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()); |
|||
} |
|||
}; |
|||
} |
|||
} |
|||
@ -0,0 +1,150 @@ |
|||
package com.bnyer.system.api.model; |
|||
|
|||
import java.io.Serializable; |
|||
import java.util.Set; |
|||
import com.bnyer.system.api.domain.SysUser; |
|||
|
|||
/** |
|||
* 用户信息 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
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 Set<String> permissions; |
|||
|
|||
/** |
|||
* 角色列表 |
|||
*/ |
|||
private Set<String> roles; |
|||
|
|||
/** |
|||
* 用户信息 |
|||
*/ |
|||
private SysUser sysUser; |
|||
|
|||
public String getToken() |
|||
{ |
|||
return token; |
|||
} |
|||
|
|||
public void setToken(String token) |
|||
{ |
|||
this.token = token; |
|||
} |
|||
|
|||
public Long getUserid() |
|||
{ |
|||
return userid; |
|||
} |
|||
|
|||
public void setUserid(Long userid) |
|||
{ |
|||
this.userid = userid; |
|||
} |
|||
|
|||
public String getUsername() |
|||
{ |
|||
return username; |
|||
} |
|||
|
|||
public void setUsername(String username) |
|||
{ |
|||
this.username = username; |
|||
} |
|||
|
|||
public Long getLoginTime() |
|||
{ |
|||
return loginTime; |
|||
} |
|||
|
|||
public void setLoginTime(Long loginTime) |
|||
{ |
|||
this.loginTime = loginTime; |
|||
} |
|||
|
|||
public Long getExpireTime() |
|||
{ |
|||
return expireTime; |
|||
} |
|||
|
|||
public void setExpireTime(Long expireTime) |
|||
{ |
|||
this.expireTime = expireTime; |
|||
} |
|||
|
|||
public String getIpaddr() |
|||
{ |
|||
return ipaddr; |
|||
} |
|||
|
|||
public void setIpaddr(String ipaddr) |
|||
{ |
|||
this.ipaddr = ipaddr; |
|||
} |
|||
|
|||
public Set<String> getPermissions() |
|||
{ |
|||
return permissions; |
|||
} |
|||
|
|||
public void setPermissions(Set<String> permissions) |
|||
{ |
|||
this.permissions = permissions; |
|||
} |
|||
|
|||
public Set<String> getRoles() |
|||
{ |
|||
return roles; |
|||
} |
|||
|
|||
public void setRoles(Set<String> roles) |
|||
{ |
|||
this.roles = roles; |
|||
} |
|||
|
|||
public SysUser getSysUser() |
|||
{ |
|||
return sysUser; |
|||
} |
|||
|
|||
public void setSysUser(SysUser sysUser) |
|||
{ |
|||
this.sysUser = sysUser; |
|||
} |
|||
} |
|||
@ -0,0 +1,4 @@ |
|||
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ |
|||
com.bnyer.system.api.factory.RemoteUserFallbackFactory,\ |
|||
com.bnyer.system.api.factory.RemoteLogFallbackFactory, \ |
|||
com.bnyer.system.api.factory.RemoteFileFallbackFactory |
|||
@ -0,0 +1,22 @@ |
|||
<?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.dimensionalnode</groupId> |
|||
<artifactId>bnyer</artifactId> |
|||
<version>1.0.0</version> |
|||
</parent> |
|||
<modelVersion>4.0.0</modelVersion> |
|||
|
|||
<modules> |
|||
<module>bnyer-api-system</module> |
|||
</modules> |
|||
|
|||
<artifactId>bnyer-api</artifactId> |
|||
<packaging>pom</packaging> |
|||
|
|||
<description> |
|||
bnyer-api系统接口 |
|||
</description> |
|||
|
|||
</project> |
|||
@ -0,0 +1,74 @@ |
|||
<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.dimensionalnode</groupId> |
|||
<artifactId>bnyer</artifactId> |
|||
<version>1.0.0</version> |
|||
</parent> |
|||
<modelVersion>4.0.0</modelVersion> |
|||
|
|||
<artifactId>bnyer-auth</artifactId> |
|||
|
|||
<description> |
|||
bnyer-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> |
|||
|
|||
<!-- bnyer Common Security--> |
|||
<dependency> |
|||
<groupId>com.dimensionalnode</groupId> |
|||
<artifactId>bnyer-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> |
|||
@ -0,0 +1,31 @@ |
|||
package com.bnyer.auth; |
|||
|
|||
import com.bnyer.common.security.annotation.EnableRyFeignClients; |
|||
import org.springframework.boot.SpringApplication; |
|||
import org.springframework.boot.autoconfigure.SpringBootApplication; |
|||
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; |
|||
|
|||
/** |
|||
* 认证授权中心 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
@EnableRyFeignClients |
|||
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class }) |
|||
public class BnyerAuthApplication |
|||
{ |
|||
public static void main(String[] args) |
|||
{ |
|||
SpringApplication.run(BnyerAuthApplication.class, args); |
|||
System.out.println("(♥◠‿◠)ノ゙ 认证授权中心启动成功 ლ(´ڡ`ლ)゙ \n" + |
|||
" .-------. ____ __ \n" + |
|||
" | _ _ \\ \\ \\ / / \n" + |
|||
" | ( ' ) | \\ _. / ' \n" + |
|||
" |(_ o _) / _( )_ .' \n" + |
|||
" | (_,_).' __ ___(_ o _)' \n" + |
|||
" | |\\ \\ | || |(_,_)' \n" + |
|||
" | | \\ `' /| `-' / \n" + |
|||
" | | \\ / \\ / \n" + |
|||
" ''-' `'-' `-..-' "); |
|||
} |
|||
} |
|||
@ -0,0 +1,79 @@ |
|||
package com.bnyer.auth.controller; |
|||
|
|||
import javax.servlet.http.HttpServletRequest; |
|||
|
|||
import com.bnyer.auth.form.LoginBody; |
|||
import com.bnyer.auth.form.RegisterBody; |
|||
import com.bnyer.auth.service.SysLoginService; |
|||
import com.bnyer.common.core.domain.R; |
|||
import com.bnyer.common.core.utils.JwtUtils; |
|||
import com.bnyer.common.core.utils.StringUtils; |
|||
import com.bnyer.common.security.auth.AuthUtil; |
|||
import com.bnyer.common.security.service.TokenService; |
|||
import com.bnyer.common.security.utils.SecurityUtils; |
|||
import com.bnyer.system.api.model.LoginUser; |
|||
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; |
|||
|
|||
/** |
|||
* token 控制 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
@RestController |
|||
public class TokenController |
|||
{ |
|||
@Autowired |
|||
private TokenService tokenService; |
|||
|
|||
@Autowired |
|||
private SysLoginService sysLoginService; |
|||
|
|||
@PostMapping("login") |
|||
public R<?> login(@RequestBody LoginBody form) |
|||
{ |
|||
// 用户登录
|
|||
LoginUser userInfo = sysLoginService.login(form.getUsername(), form.getPassword()); |
|||
// 获取登录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(); |
|||
} |
|||
} |
|||
@ -0,0 +1,39 @@ |
|||
package com.bnyer.auth.form; |
|||
|
|||
/** |
|||
* 用户登录对象 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
public class LoginBody |
|||
{ |
|||
/** |
|||
* 用户名 |
|||
*/ |
|||
private String username; |
|||
|
|||
/** |
|||
* 用户密码 |
|||
*/ |
|||
private String password; |
|||
|
|||
public String getUsername() |
|||
{ |
|||
return username; |
|||
} |
|||
|
|||
public void setUsername(String username) |
|||
{ |
|||
this.username = username; |
|||
} |
|||
|
|||
public String getPassword() |
|||
{ |
|||
return password; |
|||
} |
|||
|
|||
public void setPassword(String password) |
|||
{ |
|||
this.password = password; |
|||
} |
|||
} |
|||
@ -0,0 +1,11 @@ |
|||
package com.bnyer.auth.form; |
|||
|
|||
/** |
|||
* 用户注册对象 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
public class RegisterBody extends LoginBody |
|||
{ |
|||
|
|||
} |
|||
@ -0,0 +1,159 @@ |
|||
package com.bnyer.auth.service; |
|||
|
|||
import com.bnyer.common.core.constant.Constants; |
|||
import com.bnyer.common.core.constant.SecurityConstants; |
|||
import com.bnyer.common.core.constant.UserConstants; |
|||
import com.bnyer.common.core.domain.R; |
|||
import com.bnyer.common.core.enums.UserStatus; |
|||
import com.bnyer.common.core.exception.ServiceException; |
|||
import com.bnyer.common.core.utils.ServletUtils; |
|||
import com.bnyer.common.core.utils.StringUtils; |
|||
import com.bnyer.common.core.utils.ip.IpUtils; |
|||
import com.bnyer.common.security.utils.SecurityUtils; |
|||
import com.bnyer.system.api.RemoteLogService; |
|||
import com.bnyer.system.api.RemoteUserService; |
|||
import com.bnyer.system.api.domain.SysLogininfor; |
|||
import com.bnyer.system.api.domain.SysUser; |
|||
import com.bnyer.system.api.model.LoginUser; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.stereotype.Component; |
|||
|
|||
/** |
|||
* 登录校验方法 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
@Component |
|||
public class SysLoginService |
|||
{ |
|||
@Autowired |
|||
private RemoteLogService remoteLogService; |
|||
|
|||
@Autowired |
|||
private RemoteUserService remoteUserService; |
|||
|
|||
/** |
|||
* 登录 |
|||
*/ |
|||
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(); |
|||
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, "用户密码错误"); |
|||
throw new ServiceException("用户不存在/密码错误"); |
|||
} |
|||
recordLogininfor(username, Constants.LOGIN_SUCCESS, "登录成功"); |
|||
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); |
|||
// 日志状态
|
|||
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); |
|||
} |
|||
} |
|||
@ -0,0 +1,13 @@ |
|||
Spring Boot Version: ${spring-boot.version} |
|||
Spring Application Name: ${spring.application.name} |
|||
.----------------. .-----------------. .----------------. .----------------. .----------------. .----------------. .----------------. .----------------. .----------------. .----------------. |
|||
| .--------------. || .--------------. || .--------------. || .--------------. || .--------------. || .--------------. || .--------------. || .--------------. || .--------------. || .--------------. | |
|||
| | ______ | || | ____ _____ | || | ____ ____ | || | _________ | || | _______ | || | | || | __ | || | _____ _____ | || | _________ | || | ____ ____ | | |
|||
| | |_ _ \ | || ||_ \|_ _| | || | |_ _||_ _| | || | |_ ___ | | || | |_ __ \ | || | | || | / \ | || ||_ _||_ _|| || | | _ _ | | || | |_ || _| | | |
|||
| | | |_) | | || | | \ | | | || | \ \ / / | || | | |_ \_| | || | | |__) | | || | ______ | || | / /\ \ | || | | | | | | || | |_/ | | \_| | || | | |__| | | | |
|||
| | | __'. | || | | |\ \| | | || | \ \/ / | || | | _| _ | || | | __ / | || | |______| | || | / ____ \ | || | | ' ' | | || | | | | || | | __ | | | |
|||
| | _| |__) | | || | _| |_\ |_ | || | _| |_ | || | _| |___/ | | || | _| | \ \_ | || | | || | _/ / \ \_ | || | \ `--' / | || | _| |_ | || | _| | | |_ | | |
|||
| | |_______/ | || ||_____|\____| | || | |______| | || | |_________| | || | |____| |___| | || | | || ||____| |____|| || | `.__.' | || | |_____| | || | |____||____| | | |
|||
| | | || | | || | | || | | || | | || | | || | | || | | || | | || | | | |
|||
| '--------------' || '--------------' || '--------------' || '--------------' || '--------------' || '--------------' || '--------------' || '--------------' || '--------------' || '--------------' | |
|||
'----------------' '----------------' '----------------' '----------------' '----------------' '----------------' '----------------' '----------------' '----------------' '----------------' |
|||
@ -0,0 +1,25 @@ |
|||
# Tomcat |
|||
server: |
|||
port: 9200 |
|||
|
|||
# Spring |
|||
spring: |
|||
application: |
|||
# 应用名称 |
|||
name: bnyer-auth |
|||
profiles: |
|||
# 环境配置 |
|||
active: dev |
|||
cloud: |
|||
nacos: |
|||
discovery: |
|||
# 服务注册地址 |
|||
server-addr: 127.0.0.1:8848 |
|||
config: |
|||
# 配置中心地址 |
|||
server-addr: 127.0.0.1:8848 |
|||
# 配置文件格式 |
|||
file-extension: yml |
|||
# 共享配置 |
|||
shared-configs: |
|||
- application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} |
|||
@ -0,0 +1,74 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<configuration scan="true" scanPeriod="60 seconds" debug="false"> |
|||
<!-- 日志存放路径 --> |
|||
<property name="log.path" value="logs/bnyer-auth" /> |
|||
<!-- 日志输出格式 --> |
|||
<property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" /> |
|||
|
|||
<!-- 控制台输出 --> |
|||
<appender name="console" class="ch.qos.logback.core.ConsoleAppender"> |
|||
<encoder> |
|||
<pattern>${log.pattern}</pattern> |
|||
</encoder> |
|||
</appender> |
|||
|
|||
<!-- 系统日志输出 --> |
|||
<appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender"> |
|||
<file>${log.path}/info.log</file> |
|||
<!-- 循环政策:基于时间创建日志文件 --> |
|||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> |
|||
<!-- 日志文件名格式 --> |
|||
<fileNamePattern>${log.path}/info.%d{yyyy-MM-dd}.log</fileNamePattern> |
|||
<!-- 日志最大的历史 60天 --> |
|||
<maxHistory>60</maxHistory> |
|||
</rollingPolicy> |
|||
<encoder> |
|||
<pattern>${log.pattern}</pattern> |
|||
</encoder> |
|||
<filter class="ch.qos.logback.classic.filter.LevelFilter"> |
|||
<!-- 过滤的级别 --> |
|||
<level>INFO</level> |
|||
<!-- 匹配时的操作:接收(记录) --> |
|||
<onMatch>ACCEPT</onMatch> |
|||
<!-- 不匹配时的操作:拒绝(不记录) --> |
|||
<onMismatch>DENY</onMismatch> |
|||
</filter> |
|||
</appender> |
|||
|
|||
<appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender"> |
|||
<file>${log.path}/error.log</file> |
|||
<!-- 循环政策:基于时间创建日志文件 --> |
|||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> |
|||
<!-- 日志文件名格式 --> |
|||
<fileNamePattern>${log.path}/error.%d{yyyy-MM-dd}.log</fileNamePattern> |
|||
<!-- 日志最大的历史 60天 --> |
|||
<maxHistory>60</maxHistory> |
|||
</rollingPolicy> |
|||
<encoder> |
|||
<pattern>${log.pattern}</pattern> |
|||
</encoder> |
|||
<filter class="ch.qos.logback.classic.filter.LevelFilter"> |
|||
<!-- 过滤的级别 --> |
|||
<level>ERROR</level> |
|||
<!-- 匹配时的操作:接收(记录) --> |
|||
<onMatch>ACCEPT</onMatch> |
|||
<!-- 不匹配时的操作:拒绝(不记录) --> |
|||
<onMismatch>DENY</onMismatch> |
|||
</filter> |
|||
</appender> |
|||
|
|||
<!-- 系统模块日志级别控制 --> |
|||
<logger name="com.bnyer" level="info" /> |
|||
<!-- Spring日志级别控制 --> |
|||
<logger name="org.springframework" level="warn" /> |
|||
|
|||
<root level="info"> |
|||
<appender-ref ref="console" /> |
|||
</root> |
|||
|
|||
<!--系统操作日志--> |
|||
<root level="info"> |
|||
<appender-ref ref="file_info" /> |
|||
<appender-ref ref="file_error" /> |
|||
</root> |
|||
</configuration> |
|||
@ -0,0 +1,124 @@ |
|||
<?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.dimensionalnode</groupId> |
|||
<artifactId>bnyer-common</artifactId> |
|||
<version>1.0.0</version> |
|||
</parent> |
|||
<modelVersion>4.0.0</modelVersion> |
|||
|
|||
<artifactId>bnyer-common-core</artifactId> |
|||
|
|||
<description> |
|||
bnyer-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> |
|||
|
|||
<!-- Pagehelper --> |
|||
<dependency> |
|||
<groupId>com.github.pagehelper</groupId> |
|||
<artifactId>pagehelper-spring-boot-starter</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</groupId> |
|||
<artifactId>fastjson</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> |
|||
|
|||
</dependencies> |
|||
|
|||
</project> |
|||
@ -0,0 +1,171 @@ |
|||
package com.bnyer.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.bnyer.common.core.utils.poi.ExcelHandlerAdapter; |
|||
|
|||
/** |
|||
* 自定义导出Excel数据注解 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
@Retention(RetentionPolicy.RUNTIME) |
|||
@Target(ElementType.FIELD) |
|||
public @interface Excel |
|||
{ |
|||
/** |
|||
* 导出时在excel中排序 |
|||
*/ |
|||
public int sort() default Integer.MAX_VALUE; |
|||
|
|||
/** |
|||
* 导出到Excel中的名字. |
|||
*/ |
|||
public String name() default ""; |
|||
|
|||
/** |
|||
* 日期格式, 如: yyyy-MM-dd |
|||
*/ |
|||
public String dateFormat() default ""; |
|||
|
|||
/** |
|||
* 读取内容转表达式 (如: 0=男,1=女,2=未知) |
|||
*/ |
|||
public String readConverterExp() default ""; |
|||
|
|||
/** |
|||
* 分隔符,读取字符串组内容 |
|||
*/ |
|||
public String separator() default ","; |
|||
|
|||
/** |
|||
* BigDecimal 精度 默认:-1(默认不开启BigDecimal格式化) |
|||
*/ |
|||
public int scale() default -1; |
|||
|
|||
/** |
|||
* BigDecimal 舍入规则 默认:BigDecimal.ROUND_HALF_EVEN |
|||
*/ |
|||
public int roundingMode() default BigDecimal.ROUND_HALF_EVEN; |
|||
|
|||
/** |
|||
* 导出类型(0数字 1字符串) |
|||
*/ |
|||
public ColumnType cellType() default ColumnType.STRING; |
|||
|
|||
/** |
|||
* 导出时在excel中每个列的高度 单位为字符 |
|||
*/ |
|||
public double height() default 14; |
|||
|
|||
/** |
|||
* 导出时在excel中每个列的宽 单位为字符 |
|||
*/ |
|||
public double width() default 16; |
|||
|
|||
/** |
|||
* 文字后缀,如% 90 变成90% |
|||
*/ |
|||
public String suffix() default ""; |
|||
|
|||
/** |
|||
* 当值为空时,字段的默认值 |
|||
*/ |
|||
public String defaultValue() default ""; |
|||
|
|||
/** |
|||
* 提示信息 |
|||
*/ |
|||
public String prompt() default ""; |
|||
|
|||
/** |
|||
* 设置只能选择不能输入的列内容. |
|||
*/ |
|||
public String[] combo() default {}; |
|||
|
|||
/** |
|||
* 是否导出数据,应对需求:有时我们需要导出一份模板,这是标题需要但内容需要用户手工填写. |
|||
*/ |
|||
public boolean isExport() default true; |
|||
|
|||
/** |
|||
* 另一个类中的属性名称,支持多级获取,以小数点隔开 |
|||
*/ |
|||
public String targetAttr() default ""; |
|||
|
|||
/** |
|||
* 是否自动统计数据,在最后追加一行统计数据总和 |
|||
*/ |
|||
public boolean isStatistics() default false; |
|||
|
|||
/** |
|||
* 导出字段对齐方式(0:默认;1:靠左;2:居中;3:靠右) |
|||
*/ |
|||
public Align align() default Align.AUTO; |
|||
|
|||
/** |
|||
* 自定义数据处理器 |
|||
*/ |
|||
public Class<?> handler() default ExcelHandlerAdapter.class; |
|||
|
|||
/** |
|||
* 自定义数据处理器参数 |
|||
*/ |
|||
public String[] args() default {}; |
|||
|
|||
public enum Align |
|||
{ |
|||
AUTO(0), LEFT(1), CENTER(2), RIGHT(3); |
|||
private final int value; |
|||
|
|||
Align(int value) |
|||
{ |
|||
this.value = value; |
|||
} |
|||
|
|||
public int value() |
|||
{ |
|||
return this.value; |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 字段类型(0:导出导入;1:仅导出;2:仅导入) |
|||
*/ |
|||
Type type() default Type.ALL; |
|||
|
|||
public enum Type |
|||
{ |
|||
ALL(0), EXPORT(1), IMPORT(2); |
|||
private final int value; |
|||
|
|||
Type(int value) |
|||
{ |
|||
this.value = value; |
|||
} |
|||
|
|||
public int value() |
|||
{ |
|||
return this.value; |
|||
} |
|||
} |
|||
|
|||
public enum ColumnType |
|||
{ |
|||
NUMERIC(0), STRING(1), IMAGE(2); |
|||
private final int value; |
|||
|
|||
ColumnType(int value) |
|||
{ |
|||
this.value = value; |
|||
} |
|||
|
|||
public int value() |
|||
{ |
|||
return this.value; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,18 @@ |
|||
package com.bnyer.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 ruoyi |
|||
*/ |
|||
@Target(ElementType.FIELD) |
|||
@Retention(RetentionPolicy.RUNTIME) |
|||
public @interface Excels |
|||
{ |
|||
Excel[] value(); |
|||
} |
|||
@ -0,0 +1,24 @@ |
|||
package com.bnyer.common.core.constant; |
|||
|
|||
/** |
|||
* 缓存的key 常量 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
public class CacheConstants |
|||
{ |
|||
/** |
|||
* 缓存有效期,默认720(分钟) |
|||
*/ |
|||
public final static long EXPIRATION = 720; |
|||
|
|||
/** |
|||
* 缓存刷新时间,默认120(分钟) |
|||
*/ |
|||
public final static long REFRESH_TIME = 120; |
|||
|
|||
/** |
|||
* 权限缓存前缀 |
|||
*/ |
|||
public final static String LOGIN_TOKEN_KEY = "login_tokens:"; |
|||
} |
|||
@ -0,0 +1,141 @@ |
|||
package com.bnyer.common.core.constant; |
|||
|
|||
/** |
|||
* 通用常量信息 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
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:"; |
|||
|
|||
/** |
|||
* 验证码有效期(分钟) |
|||
*/ |
|||
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"; |
|||
|
|||
/** |
|||
* 定时任务白名单配置(仅允许访问的包名,如其他需要可以自行添加) |
|||
*/ |
|||
public static final String[] JOB_WHITELIST_STR = { "com.bnyer" }; |
|||
|
|||
/** |
|||
* 定时任务违规的字符 |
|||
*/ |
|||
public static final String[] JOB_ERROR_STR = { "java.net.URL", "javax.naming.InitialContext", "org.yaml.snakeyaml", |
|||
"org.springframework", "org.apache", "com.bnyer.common.core.utils.file" }; |
|||
} |
|||
@ -0,0 +1,117 @@ |
|||
package com.bnyer.common.core.constant; |
|||
|
|||
/** |
|||
* 代码生成通用常量 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
public class GenConstants |
|||
{ |
|||
/** 单表(增删改查) */ |
|||
public static final String TPL_CRUD = "crud"; |
|||
|
|||
/** 树表(增删改查) */ |
|||
public static final String TPL_TREE = "tree"; |
|||
|
|||
/** 主子表(增删改查) */ |
|||
public static final String TPL_SUB = "sub"; |
|||
|
|||
/** 树编码字段 */ |
|||
public static final String TREE_CODE = "treeCode"; |
|||
|
|||
/** 树父编码字段 */ |
|||
public static final String TREE_PARENT_CODE = "treeParentCode"; |
|||
|
|||
/** 树名称字段 */ |
|||
public static final String TREE_NAME = "treeName"; |
|||
|
|||
/** 上级菜单ID字段 */ |
|||
public static final String PARENT_MENU_ID = "parentMenuId"; |
|||
|
|||
/** 上级菜单名称字段 */ |
|||
public static final String PARENT_MENU_NAME = "parentMenuName"; |
|||
|
|||
/** 数据库字符串类型 */ |
|||
public static final String[] COLUMNTYPE_STR = { "char", "varchar", "nvarchar", "varchar2" }; |
|||
|
|||
/** 数据库文本类型 */ |
|||
public static final String[] COLUMNTYPE_TEXT = { "tinytext", "text", "mediumtext", "longtext" }; |
|||
|
|||
/** 数据库时间类型 */ |
|||
public static final String[] COLUMNTYPE_TIME = { "datetime", "time", "date", "timestamp" }; |
|||
|
|||
/** 数据库数字类型 */ |
|||
public static final String[] COLUMNTYPE_NUMBER = { "tinyint", "smallint", "mediumint", "int", "number", "integer", |
|||
"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"; |
|||
} |
|||
@ -0,0 +1,89 @@ |
|||
package com.bnyer.common.core.constant; |
|||
|
|||
/** |
|||
* 返回状态码 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
public class HttpStatus |
|||
{ |
|||
/** |
|||
* 操作成功 |
|||
*/ |
|||
public static final int SUCCESS = 200; |
|||
|
|||
/** |
|||
* 对象创建成功 |
|||
*/ |
|||
public static final int CREATED = 201; |
|||
|
|||
/** |
|||
* 请求已经被接受 |
|||
*/ |
|||
public static final int ACCEPTED = 202; |
|||
|
|||
/** |
|||
* 操作已经执行成功,但是没有返回数据 |
|||
*/ |
|||
public static final int NO_CONTENT = 204; |
|||
|
|||
/** |
|||
* 资源已被移除 |
|||
*/ |
|||
public static final int MOVED_PERM = 301; |
|||
|
|||
/** |
|||
* 重定向 |
|||
*/ |
|||
public static final int SEE_OTHER = 303; |
|||
|
|||
/** |
|||
* 资源没有被修改 |
|||
*/ |
|||
public static final int NOT_MODIFIED = 304; |
|||
|
|||
/** |
|||
* 参数列表错误(缺少,格式不匹配) |
|||
*/ |
|||
public static final int BAD_REQUEST = 400; |
|||
|
|||
/** |
|||
* 未授权 |
|||
*/ |
|||
public static final int UNAUTHORIZED = 401; |
|||
|
|||
/** |
|||
* 访问受限,授权过期 |
|||
*/ |
|||
public static final int FORBIDDEN = 403; |
|||
|
|||
/** |
|||
* 资源,服务未找到 |
|||
*/ |
|||
public static final int NOT_FOUND = 404; |
|||
|
|||
/** |
|||
* 不允许的http方法 |
|||
*/ |
|||
public static final int BAD_METHOD = 405; |
|||
|
|||
/** |
|||
* 资源冲突,或者资源被锁 |
|||
*/ |
|||
public static final int CONFLICT = 409; |
|||
|
|||
/** |
|||
* 不支持的数据,媒体类型 |
|||
*/ |
|||
public static final int UNSUPPORTED_TYPE = 415; |
|||
|
|||
/** |
|||
* 系统内部错误 |
|||
*/ |
|||
public static final int ERROR = 500; |
|||
|
|||
/** |
|||
* 接口未实现 |
|||
*/ |
|||
public static final int NOT_IMPLEMENTED = 501; |
|||
} |
|||
@ -0,0 +1,50 @@ |
|||
package com.bnyer.common.core.constant; |
|||
|
|||
/** |
|||
* 任务调度通用常量 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
public class ScheduleConstants |
|||
{ |
|||
public static final String TASK_CLASS_NAME = "TASK_CLASS_NAME"; |
|||
|
|||
/** 执行目标key */ |
|||
public static final String TASK_PROPERTIES = "TASK_PROPERTIES"; |
|||
|
|||
/** 默认 */ |
|||
public static final String MISFIRE_DEFAULT = "0"; |
|||
|
|||
/** 立即触发执行 */ |
|||
public static final String MISFIRE_IGNORE_MISFIRES = "1"; |
|||
|
|||
/** 触发一次执行 */ |
|||
public static final String MISFIRE_FIRE_AND_PROCEED = "2"; |
|||
|
|||
/** 不触发立即执行 */ |
|||
public static final String MISFIRE_DO_NOTHING = "3"; |
|||
|
|||
public enum Status |
|||
{ |
|||
/** |
|||
* 正常 |
|||
*/ |
|||
NORMAL("0"), |
|||
/** |
|||
* 暂停 |
|||
*/ |
|||
PAUSE("1"); |
|||
|
|||
private String value; |
|||
|
|||
private Status(String value) |
|||
{ |
|||
this.value = value; |
|||
} |
|||
|
|||
public String getValue() |
|||
{ |
|||
return value; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,44 @@ |
|||
package com.bnyer.common.core.constant; |
|||
|
|||
/** |
|||
* 权限相关通用常量 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
public class SecurityConstants |
|||
{ |
|||
/** |
|||
* 用户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"; |
|||
} |
|||
@ -0,0 +1,24 @@ |
|||
package com.bnyer.common.core.constant; |
|||
|
|||
/** |
|||
* 服务名称 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
public class ServiceNameConstants |
|||
{ |
|||
/** |
|||
* 认证服务的serviceid |
|||
*/ |
|||
public static final String AUTH_SERVICE = "bnyer-auth"; |
|||
|
|||
/** |
|||
* 系统模块的serviceid |
|||
*/ |
|||
public static final String SYSTEM_SERVICE = "bnyer-system"; |
|||
|
|||
/** |
|||
* 文件服务的serviceid |
|||
*/ |
|||
public static final String FILE_SERVICE = "bnyer-file"; |
|||
} |
|||
@ -0,0 +1,25 @@ |
|||
package com.bnyer.common.core.constant; |
|||
|
|||
/** |
|||
* Token的Key常量 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
public class TokenConstants |
|||
{ |
|||
/** |
|||
* 令牌自定义标识 |
|||
*/ |
|||
public static final String AUTHENTICATION = "Authorization"; |
|||
|
|||
/** |
|||
* 令牌前缀 |
|||
*/ |
|||
public static final String PREFIX = "Bearer "; |
|||
|
|||
/** |
|||
* 令牌秘钥 |
|||
*/ |
|||
public final static String SECRET = "abcdefghijklmnopqrstuvwxyz"; |
|||
|
|||
} |
|||
@ -0,0 +1,81 @@ |
|||
package com.bnyer.common.core.constant; |
|||
|
|||
/** |
|||
* 用户常量信息 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
public class UserConstants |
|||
{ |
|||
/** |
|||
* 平台内系统用户的唯一标志 |
|||
*/ |
|||
public static final String SYS_USER = "SYS_USER"; |
|||
|
|||
/** 正常状态 */ |
|||
public static final String NORMAL = "0"; |
|||
|
|||
/** 异常状态 */ |
|||
public static final String EXCEPTION = "1"; |
|||
|
|||
/** 用户封禁状态 */ |
|||
public static final String USER_DISABLE = "1"; |
|||
|
|||
/** 角色封禁状态 */ |
|||
public static final String ROLE_DISABLE = "1"; |
|||
|
|||
/** 部门正常状态 */ |
|||
public static final String DEPT_NORMAL = "0"; |
|||
|
|||
/** 部门停用状态 */ |
|||
public static final String DEPT_DISABLE = "1"; |
|||
|
|||
/** 字典正常状态 */ |
|||
public static final String DICT_NORMAL = "0"; |
|||
|
|||
/** 是否为系统默认(是) */ |
|||
public static final String YES = "Y"; |
|||
|
|||
/** 是否菜单外链(是) */ |
|||
public static final String YES_FRAME = "0"; |
|||
|
|||
/** 是否菜单外链(否) */ |
|||
public static final String NO_FRAME = "1"; |
|||
|
|||
/** 菜单类型(目录) */ |
|||
public static final String TYPE_DIR = "M"; |
|||
|
|||
/** 菜单类型(菜单) */ |
|||
public static final String TYPE_MENU = "C"; |
|||
|
|||
/** 菜单类型(按钮) */ |
|||
public static final String TYPE_BUTTON = "F"; |
|||
|
|||
/** Layout组件标识 */ |
|||
public final static String LAYOUT = "Layout"; |
|||
|
|||
/** ParentView组件标识 */ |
|||
public final static String PARENT_VIEW = "ParentView"; |
|||
|
|||
/** InnerLink组件标识 */ |
|||
public final static String INNER_LINK = "InnerLink"; |
|||
|
|||
/** 校验返回结果码 */ |
|||
public final static String UNIQUE = "0"; |
|||
|
|||
public final static String NOT_UNIQUE = "1"; |
|||
|
|||
/** |
|||
* 用户名长度限制 |
|||
*/ |
|||
public static final int USERNAME_MIN_LENGTH = 2; |
|||
|
|||
public static final int USERNAME_MAX_LENGTH = 20; |
|||
|
|||
/** |
|||
* 密码长度限制 |
|||
*/ |
|||
public static final int PASSWORD_MIN_LENGTH = 5; |
|||
|
|||
public static final int PASSWORD_MAX_LENGTH = 20; |
|||
} |
|||
@ -0,0 +1,88 @@ |
|||
package com.bnyer.common.core.context; |
|||
|
|||
import java.util.Map; |
|||
import java.util.concurrent.ConcurrentHashMap; |
|||
import com.alibaba.ttl.TransmittableThreadLocal; |
|||
import com.bnyer.common.core.constant.SecurityConstants; |
|||
import com.bnyer.common.core.text.Convert; |
|||
import com.bnyer.common.core.utils.StringUtils; |
|||
|
|||
/** |
|||
* 获取当前线程变量中的 用户id、用户名称、Token等信息 |
|||
* 注意: 必须在网关通过请求头的方法传入,同时在HeaderInterceptor拦截器设置值。 否则这里无法获取 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
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 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(); |
|||
} |
|||
} |
|||
@ -0,0 +1,106 @@ |
|||
package com.bnyer.common.core.domain; |
|||
|
|||
import java.io.Serializable; |
|||
|
|||
import com.bnyer.common.core.constant.Constants; |
|||
|
|||
/** |
|||
* 响应信息主体 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
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; |
|||
} |
|||
} |
|||
@ -0,0 +1,30 @@ |
|||
package com.bnyer.common.core.enums; |
|||
|
|||
/** |
|||
* 用户状态 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
public enum UserStatus |
|||
{ |
|||
OK("0", "正常"), DISABLE("1", "停用"), DELETED("2", "删除"); |
|||
|
|||
private final String code; |
|||
private final String info; |
|||
|
|||
UserStatus(String code, String info) |
|||
{ |
|||
this.code = code; |
|||
this.info = info; |
|||
} |
|||
|
|||
public String getCode() |
|||
{ |
|||
return code; |
|||
} |
|||
|
|||
public String getInfo() |
|||
{ |
|||
return info; |
|||
} |
|||
} |
|||
@ -0,0 +1,16 @@ |
|||
package com.bnyer.common.core.exception; |
|||
|
|||
/** |
|||
* 验证码错误异常类 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
public class CaptchaException extends RuntimeException |
|||
{ |
|||
private static final long serialVersionUID = 1L; |
|||
|
|||
public CaptchaException(String msg) |
|||
{ |
|||
super(msg); |
|||
} |
|||
} |
|||
@ -0,0 +1,31 @@ |
|||
package com.bnyer.common.core.exception; |
|||
|
|||
/** |
|||
* 检查异常 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
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); |
|||
} |
|||
} |
|||
@ -0,0 +1,15 @@ |
|||
package com.bnyer.common.core.exception; |
|||
|
|||
/** |
|||
* 演示模式异常 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
public class DemoModeException extends RuntimeException |
|||
{ |
|||
private static final long serialVersionUID = 1L; |
|||
|
|||
public DemoModeException() |
|||
{ |
|||
} |
|||
} |
|||
@ -0,0 +1,58 @@ |
|||
package com.bnyer.common.core.exception; |
|||
|
|||
/** |
|||
* 全局异常 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
public class GlobalException extends RuntimeException |
|||
{ |
|||
|
|||
private static final long serialVersionUID = 1L; |
|||
|
|||
/** |
|||
* 错误提示 |
|||
*/ |
|||
private String message; |
|||
|
|||
/** |
|||
* 错误明细,内部调试错误 |
|||
* |
|||
* 和 {@link CommonResult#getDetailMessage()} 一致的设计 |
|||
*/ |
|||
private String detailMessage; |
|||
|
|||
/** |
|||
* 空构造方法,避免反序列化问题 |
|||
*/ |
|||
public GlobalException() |
|||
{ |
|||
} |
|||
|
|||
public GlobalException(String message) |
|||
{ |
|||
this.message = message; |
|||
} |
|||
|
|||
public String getDetailMessage() |
|||
{ |
|||
return detailMessage; |
|||
} |
|||
|
|||
public GlobalException setDetailMessage(String detailMessage) |
|||
{ |
|||
this.detailMessage = detailMessage; |
|||
return this; |
|||
} |
|||
|
|||
public String getMessage() |
|||
{ |
|||
return message; |
|||
} |
|||
|
|||
public GlobalException setMessage(String message) |
|||
{ |
|||
this.message = message; |
|||
return this; |
|||
} |
|||
} |
|||
@ -0,0 +1,16 @@ |
|||
package com.bnyer.common.core.exception; |
|||
|
|||
/** |
|||
* 内部认证异常 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
public class InnerAuthException extends RuntimeException |
|||
{ |
|||
private static final long serialVersionUID = 1L; |
|||
|
|||
public InnerAuthException(String message) |
|||
{ |
|||
super(message); |
|||
} |
|||
} |
|||
@ -0,0 +1,15 @@ |
|||
package com.bnyer.common.core.exception; |
|||
|
|||
/** |
|||
* 权限异常 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
public class PreAuthorizeException extends RuntimeException |
|||
{ |
|||
private static final long serialVersionUID = 1L; |
|||
|
|||
public PreAuthorizeException() |
|||
{ |
|||
} |
|||
} |
|||
@ -0,0 +1,73 @@ |
|||
package com.bnyer.common.core.exception; |
|||
|
|||
/** |
|||
* 业务异常 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
public final class ServiceException extends RuntimeException |
|||
{ |
|||
private static final long serialVersionUID = 1L; |
|||
|
|||
/** |
|||
* 错误码 |
|||
*/ |
|||
private Integer code; |
|||
|
|||
/** |
|||
* 错误提示 |
|||
*/ |
|||
private String message; |
|||
|
|||
/** |
|||
* 错误明细,内部调试错误 |
|||
* |
|||
* 和 {@link CommonResult#getDetailMessage()} 一致的设计 |
|||
*/ |
|||
private String detailMessage; |
|||
|
|||
/** |
|||
* 空构造方法,避免反序列化问题 |
|||
*/ |
|||
public ServiceException() |
|||
{ |
|||
} |
|||
|
|||
public ServiceException(String message) |
|||
{ |
|||
this.message = message; |
|||
} |
|||
|
|||
public ServiceException(String message, Integer code) |
|||
{ |
|||
this.message = message; |
|||
this.code = code; |
|||
} |
|||
|
|||
public String getDetailMessage() |
|||
{ |
|||
return detailMessage; |
|||
} |
|||
|
|||
public String getMessage() |
|||
{ |
|||
return message; |
|||
} |
|||
|
|||
public Integer getCode() |
|||
{ |
|||
return code; |
|||
} |
|||
|
|||
public ServiceException setMessage(String message) |
|||
{ |
|||
this.message = message; |
|||
return this; |
|||
} |
|||
|
|||
public ServiceException setDetailMessage(String detailMessage) |
|||
{ |
|||
this.detailMessage = detailMessage; |
|||
return this; |
|||
} |
|||
} |
|||
@ -0,0 +1,26 @@ |
|||
package com.bnyer.common.core.exception; |
|||
|
|||
/** |
|||
* 工具类异常 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
public class UtilException extends RuntimeException |
|||
{ |
|||
private static final long serialVersionUID = 8247610319171014183L; |
|||
|
|||
public UtilException(Throwable e) |
|||
{ |
|||
super(e.getMessage(), e); |
|||
} |
|||
|
|||
public UtilException(String message) |
|||
{ |
|||
super(message); |
|||
} |
|||
|
|||
public UtilException(String message, Throwable throwable) |
|||
{ |
|||
super(message, throwable); |
|||
} |
|||
} |
|||
@ -0,0 +1,16 @@ |
|||
package com.bnyer.common.core.exception.auth; |
|||
|
|||
/** |
|||
* 未能通过的登录认证异常 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
public class NotLoginException extends RuntimeException |
|||
{ |
|||
private static final long serialVersionUID = 1L; |
|||
|
|||
public NotLoginException(String message) |
|||
{ |
|||
super(message); |
|||
} |
|||
} |
|||
@ -0,0 +1,23 @@ |
|||
package com.bnyer.common.core.exception.auth; |
|||
|
|||
import org.apache.commons.lang3.StringUtils; |
|||
|
|||
/** |
|||
* 未能通过的权限认证异常 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
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, ",")); |
|||
} |
|||
} |
|||
@ -0,0 +1,23 @@ |
|||
package com.bnyer.common.core.exception.auth; |
|||
|
|||
import org.apache.commons.lang3.StringUtils; |
|||
|
|||
/** |
|||
* 未能通过的角色认证异常 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
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, ",")); |
|||
} |
|||
} |
|||
@ -0,0 +1,79 @@ |
|||
package com.bnyer.common.core.exception.base; |
|||
|
|||
/** |
|||
* 基础异常 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
public class BaseException extends RuntimeException |
|||
{ |
|||
private static final long serialVersionUID = 1L; |
|||
|
|||
/** |
|||
* 所属模块 |
|||
*/ |
|||
private String module; |
|||
|
|||
/** |
|||
* 错误码 |
|||
*/ |
|||
private String code; |
|||
|
|||
/** |
|||
* 错误码对应的参数 |
|||
*/ |
|||
private Object[] args; |
|||
|
|||
/** |
|||
* 错误消息 |
|||
*/ |
|||
private String defaultMessage; |
|||
|
|||
public BaseException(String module, String code, Object[] args, String defaultMessage) |
|||
{ |
|||
this.module = module; |
|||
this.code = code; |
|||
this.args = args; |
|||
this.defaultMessage = defaultMessage; |
|||
} |
|||
|
|||
public BaseException(String module, String code, Object[] args) |
|||
{ |
|||
this(module, code, args, null); |
|||
} |
|||
|
|||
public BaseException(String module, String defaultMessage) |
|||
{ |
|||
this(module, null, null, defaultMessage); |
|||
} |
|||
|
|||
public BaseException(String code, Object[] args) |
|||
{ |
|||
this(null, code, args, null); |
|||
} |
|||
|
|||
public BaseException(String defaultMessage) |
|||
{ |
|||
this(null, null, null, defaultMessage); |
|||
} |
|||
|
|||
public String getModule() |
|||
{ |
|||
return module; |
|||
} |
|||
|
|||
public String getCode() |
|||
{ |
|||
return code; |
|||
} |
|||
|
|||
public Object[] getArgs() |
|||
{ |
|||
return args; |
|||
} |
|||
|
|||
public String getDefaultMessage() |
|||
{ |
|||
return defaultMessage; |
|||
} |
|||
} |
|||
@ -0,0 +1,19 @@ |
|||
package com.bnyer.common.core.exception.file; |
|||
|
|||
import com.bnyer.common.core.exception.base.BaseException; |
|||
|
|||
/** |
|||
* 文件信息异常类 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
public class FileException extends BaseException |
|||
{ |
|||
private static final long serialVersionUID = 1L; |
|||
|
|||
public FileException(String code, Object[] args) |
|||
{ |
|||
super("file", code, args, null); |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,16 @@ |
|||
package com.bnyer.common.core.exception.file; |
|||
|
|||
/** |
|||
* 文件名称超长限制异常类 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
public class FileNameLengthLimitExceededException extends FileException |
|||
{ |
|||
private static final long serialVersionUID = 1L; |
|||
|
|||
public FileNameLengthLimitExceededException(int defaultFileNameLength) |
|||
{ |
|||
super("upload.filename.exceed.length", new Object[] { defaultFileNameLength }); |
|||
} |
|||
} |
|||
@ -0,0 +1,16 @@ |
|||
package com.bnyer.common.core.exception.file; |
|||
|
|||
/** |
|||
* 文件名大小限制异常类 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
public class FileSizeLimitExceededException extends FileException |
|||
{ |
|||
private static final long serialVersionUID = 1L; |
|||
|
|||
public FileSizeLimitExceededException(long defaultMaxSize) |
|||
{ |
|||
super("upload.exceed.maxSize", new Object[] { defaultMaxSize }); |
|||
} |
|||
} |
|||
@ -0,0 +1,81 @@ |
|||
package com.bnyer.common.core.exception.file; |
|||
|
|||
import java.util.Arrays; |
|||
import org.apache.commons.fileupload.FileUploadException; |
|||
|
|||
/** |
|||
* 文件上传 误异常类 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
public class InvalidExtensionException extends FileUploadException |
|||
{ |
|||
private static final long serialVersionUID = 1L; |
|||
|
|||
private String[] allowedExtension; |
|||
private String extension; |
|||
private String filename; |
|||
|
|||
public InvalidExtensionException(String[] allowedExtension, String extension, String filename) |
|||
{ |
|||
super("filename : [" + filename + "], extension : [" + extension + "], allowed extension : [" + Arrays.toString(allowedExtension) + "]"); |
|||
this.allowedExtension = allowedExtension; |
|||
this.extension = extension; |
|||
this.filename = filename; |
|||
} |
|||
|
|||
public String[] getAllowedExtension() |
|||
{ |
|||
return allowedExtension; |
|||
} |
|||
|
|||
public String getExtension() |
|||
{ |
|||
return extension; |
|||
} |
|||
|
|||
public String getFilename() |
|||
{ |
|||
return filename; |
|||
} |
|||
|
|||
public static class InvalidImageExtensionException extends InvalidExtensionException |
|||
{ |
|||
private static final long serialVersionUID = 1L; |
|||
|
|||
public InvalidImageExtensionException(String[] allowedExtension, String extension, String filename) |
|||
{ |
|||
super(allowedExtension, extension, filename); |
|||
} |
|||
} |
|||
|
|||
public static class InvalidFlashExtensionException extends InvalidExtensionException |
|||
{ |
|||
private static final long serialVersionUID = 1L; |
|||
|
|||
public InvalidFlashExtensionException(String[] allowedExtension, String extension, String filename) |
|||
{ |
|||
super(allowedExtension, extension, filename); |
|||
} |
|||
} |
|||
|
|||
public static class InvalidMediaExtensionException extends InvalidExtensionException |
|||
{ |
|||
private static final long serialVersionUID = 1L; |
|||
|
|||
public InvalidMediaExtensionException(String[] allowedExtension, String extension, String filename) |
|||
{ |
|||
super(allowedExtension, extension, filename); |
|||
} |
|||
} |
|||
|
|||
public static class InvalidVideoExtensionException extends InvalidExtensionException |
|||
{ |
|||
private static final long serialVersionUID = 1L; |
|||
|
|||
public InvalidVideoExtensionException(String[] allowedExtension, String extension, String filename) |
|||
{ |
|||
super(allowedExtension, extension, filename); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,34 @@ |
|||
package com.bnyer.common.core.exception.job; |
|||
|
|||
/** |
|||
* 计划策略异常 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
public class TaskException extends Exception |
|||
{ |
|||
private static final long serialVersionUID = 1L; |
|||
|
|||
private Code code; |
|||
|
|||
public TaskException(String msg, Code code) |
|||
{ |
|||
this(msg, code, null); |
|||
} |
|||
|
|||
public TaskException(String msg, Code code, Exception nestedEx) |
|||
{ |
|||
super(msg, nestedEx); |
|||
this.code = code; |
|||
} |
|||
|
|||
public Code getCode() |
|||
{ |
|||
return code; |
|||
} |
|||
|
|||
public enum Code |
|||
{ |
|||
TASK_EXISTS, NO_TASK_EXISTS, TASK_ALREADY_STARTED, UNKNOWN, CONFIG_ERROR, TASK_NODE_NOT_AVAILABLE |
|||
} |
|||
} |
|||
@ -0,0 +1,16 @@ |
|||
package com.bnyer.common.core.exception.user; |
|||
|
|||
/** |
|||
* 验证码失效异常类 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
public class CaptchaExpireException extends UserException |
|||
{ |
|||
private static final long serialVersionUID = 1L; |
|||
|
|||
public CaptchaExpireException() |
|||
{ |
|||
super("user.jcaptcha.expire", null); |
|||
} |
|||
} |
|||
@ -0,0 +1,18 @@ |
|||
package com.bnyer.common.core.exception.user; |
|||
|
|||
import com.bnyer.common.core.exception.base.BaseException; |
|||
|
|||
/** |
|||
* 用户信息异常类 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
public class UserException extends BaseException |
|||
{ |
|||
private static final long serialVersionUID = 1L; |
|||
|
|||
public UserException(String code, Object[] args) |
|||
{ |
|||
super("user", code, args, null); |
|||
} |
|||
} |
|||
@ -0,0 +1,16 @@ |
|||
package com.bnyer.common.core.exception.user; |
|||
|
|||
/** |
|||
* 用户密码不正确或不符合规范异常类 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
public class UserPasswordNotMatchException extends UserException |
|||
{ |
|||
private static final long serialVersionUID = 1L; |
|||
|
|||
public UserPasswordNotMatchException() |
|||
{ |
|||
super("user.password.not.match", null); |
|||
} |
|||
} |
|||
@ -0,0 +1,87 @@ |
|||
package com.bnyer.common.core.text; |
|||
|
|||
import java.nio.charset.Charset; |
|||
import java.nio.charset.StandardCharsets; |
|||
|
|||
import com.bnyer.common.core.utils.StringUtils; |
|||
|
|||
/** |
|||
* 字符集工具类 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
public class CharsetKit |
|||
{ |
|||
/** ISO-8859-1 */ |
|||
public static final String ISO_8859_1 = "ISO-8859-1"; |
|||
/** UTF-8 */ |
|||
public static final String UTF_8 = "UTF-8"; |
|||
/** GBK */ |
|||
public static final String GBK = "GBK"; |
|||
|
|||
/** ISO-8859-1 */ |
|||
public static final Charset CHARSET_ISO_8859_1 = Charset.forName(ISO_8859_1); |
|||
/** UTF-8 */ |
|||
public static final Charset CHARSET_UTF_8 = Charset.forName(UTF_8); |
|||
/** GBK */ |
|||
public static final Charset CHARSET_GBK = Charset.forName(GBK); |
|||
|
|||
/** |
|||
* 转换为Charset对象 |
|||
* |
|||
* @param charset 字符集,为空则返回默认字符集 |
|||
* @return Charset |
|||
*/ |
|||
public static Charset charset(String charset) |
|||
{ |
|||
return StringUtils.isEmpty(charset) ? Charset.defaultCharset() : Charset.forName(charset); |
|||
} |
|||
|
|||
/** |
|||
* 转换字符串的字符集编码 |
|||
* |
|||
* @param source 字符串 |
|||
* @param srcCharset 源字符集,默认ISO-8859-1 |
|||
* @param destCharset 目标字符集,默认UTF-8 |
|||
* @return 转换后的字符集 |
|||
*/ |
|||
public static String convert(String source, String srcCharset, String destCharset) |
|||
{ |
|||
return convert(source, Charset.forName(srcCharset), Charset.forName(destCharset)); |
|||
} |
|||
|
|||
/** |
|||
* 转换字符串的字符集编码 |
|||
* |
|||
* @param source 字符串 |
|||
* @param srcCharset 源字符集,默认ISO-8859-1 |
|||
* @param destCharset 目标字符集,默认UTF-8 |
|||
* @return 转换后的字符集 |
|||
*/ |
|||
public static String convert(String source, Charset srcCharset, Charset destCharset) |
|||
{ |
|||
if (null == srcCharset) |
|||
{ |
|||
srcCharset = StandardCharsets.ISO_8859_1; |
|||
} |
|||
|
|||
if (null == destCharset) |
|||
{ |
|||
destCharset = StandardCharsets.UTF_8; |
|||
} |
|||
|
|||
if (StringUtils.isEmpty(source) || srcCharset.equals(destCharset)) |
|||
{ |
|||
return source; |
|||
} |
|||
return new String(source.getBytes(srcCharset), destCharset); |
|||
} |
|||
|
|||
/** |
|||
* @return 系统字符集编码 |
|||
*/ |
|||
public static String systemCharset() |
|||
{ |
|||
return Charset.defaultCharset().name(); |
|||
} |
|||
} |
|||
File diff suppressed because it is too large
@ -0,0 +1,92 @@ |
|||
package com.bnyer.common.core.text; |
|||
|
|||
import com.bnyer.common.core.utils.StringUtils; |
|||
|
|||
/** |
|||
* 字符串格式化 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
public class StrFormatter |
|||
{ |
|||
public static final String EMPTY_JSON = "{}"; |
|||
public static final char C_BACKSLASH = '\\'; |
|||
public static final char C_DELIM_START = '{'; |
|||
public static final char C_DELIM_END = '}'; |
|||
|
|||
/** |
|||
* 格式化字符串<br> |
|||
* 此方法只是简单将占位符 {} 按照顺序替换为参数<br> |
|||
* 如果想输出 {} 使用 \\转义 { 即可,如果想输出 {} 之前的 \ 使用双转义符 \\\\ 即可<br> |
|||
* 例:<br> |
|||
* 通常使用:format("this is {} for {}", "a", "b") -> this is a for b<br> |
|||
* 转义{}: format("this is \\{} for {}", "a", "b") -> this is \{} for a<br> |
|||
* 转义\: format("this is \\\\{} for {}", "a", "b") -> this is \a for b<br> |
|||
* |
|||
* @param strPattern 字符串模板 |
|||
* @param argArray 参数列表 |
|||
* @return 结果 |
|||
*/ |
|||
public static String format(final String strPattern, final Object... argArray) |
|||
{ |
|||
if (StringUtils.isEmpty(strPattern) || StringUtils.isEmpty(argArray)) |
|||
{ |
|||
return strPattern; |
|||
} |
|||
final int strPatternLength = strPattern.length(); |
|||
|
|||
// 初始化定义好的长度以获得更好的性能
|
|||
StringBuilder sbuf = new StringBuilder(strPatternLength + 50); |
|||
|
|||
int handledPosition = 0; |
|||
int delimIndex;// 占位符所在位置
|
|||
for (int argIndex = 0; argIndex < argArray.length; argIndex++) |
|||
{ |
|||
delimIndex = strPattern.indexOf(EMPTY_JSON, handledPosition); |
|||
if (delimIndex == -1) |
|||
{ |
|||
if (handledPosition == 0) |
|||
{ |
|||
return strPattern; |
|||
} |
|||
else |
|||
{ // 字符串模板剩余部分不再包含占位符,加入剩余部分后返回结果
|
|||
sbuf.append(strPattern, handledPosition, strPatternLength); |
|||
return sbuf.toString(); |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
if (delimIndex > 0 && strPattern.charAt(delimIndex - 1) == C_BACKSLASH) |
|||
{ |
|||
if (delimIndex > 1 && strPattern.charAt(delimIndex - 2) == C_BACKSLASH) |
|||
{ |
|||
// 转义符之前还有一个转义符,占位符依旧有效
|
|||
sbuf.append(strPattern, handledPosition, delimIndex - 1); |
|||
sbuf.append(Convert.utf8Str(argArray[argIndex])); |
|||
handledPosition = delimIndex + 2; |
|||
} |
|||
else |
|||
{ |
|||
// 占位符被转义
|
|||
argIndex--; |
|||
sbuf.append(strPattern, handledPosition, delimIndex - 1); |
|||
sbuf.append(C_DELIM_START); |
|||
handledPosition = delimIndex + 1; |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
// 正常占位符
|
|||
sbuf.append(strPattern, handledPosition, delimIndex); |
|||
sbuf.append(Convert.utf8Str(argArray[argIndex])); |
|||
handledPosition = delimIndex + 2; |
|||
} |
|||
} |
|||
} |
|||
// 加入最后一个占位符后所有的字符
|
|||
sbuf.append(strPattern, handledPosition, strPattern.length()); |
|||
|
|||
return sbuf.toString(); |
|||
} |
|||
} |
|||
@ -0,0 +1,179 @@ |
|||
package com.bnyer.common.core.utils; |
|||
|
|||
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.Date; |
|||
import org.apache.commons.lang3.time.DateFormatUtils; |
|||
|
|||
/** |
|||
* 时间工具类 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
public class DateUtils extends org.apache.commons.lang3.time.DateUtils |
|||
{ |
|||
public static String YYYY = "yyyy"; |
|||
|
|||
public static String YYYY_MM = "yyyy-MM"; |
|||
|
|||
public static String YYYY_MM_DD = "yyyy-MM-dd"; |
|||
|
|||
public static String YYYYMMDDHHMMSS = "yyyyMMddHHmmss"; |
|||
|
|||
public static String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss"; |
|||
|
|||
private static String[] parsePatterns = { |
|||
"yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM", |
|||
"yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM", |
|||
"yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"}; |
|||
|
|||
/** |
|||
* 获取当前Date型日期 |
|||
* |
|||
* @return Date() 当前日期 |
|||
*/ |
|||
public static Date getNowDate() |
|||
{ |
|||
return new Date(); |
|||
} |
|||
|
|||
/** |
|||
* 获取当前日期, 默认格式为yyyy-MM-dd |
|||
* |
|||
* @return String |
|||
*/ |
|||
public static String getDate() |
|||
{ |
|||
return dateTimeNow(YYYY_MM_DD); |
|||
} |
|||
|
|||
public static final String getTime() |
|||
{ |
|||
return dateTimeNow(YYYY_MM_DD_HH_MM_SS); |
|||
} |
|||
|
|||
public static final String dateTimeNow() |
|||
{ |
|||
return dateTimeNow(YYYYMMDDHHMMSS); |
|||
} |
|||
|
|||
public static final String dateTimeNow(final String format) |
|||
{ |
|||
return parseDateToStr(format, new Date()); |
|||
} |
|||
|
|||
public static final String dateTime(final Date date) |
|||
{ |
|||
return parseDateToStr(YYYY_MM_DD, date); |
|||
} |
|||
|
|||
public static final String parseDateToStr(final String format, final Date date) |
|||
{ |
|||
return new SimpleDateFormat(format).format(date); |
|||
} |
|||
|
|||
public static final Date dateTime(final String format, final String ts) |
|||
{ |
|||
try |
|||
{ |
|||
return new SimpleDateFormat(format).parse(ts); |
|||
} |
|||
catch (ParseException e) |
|||
{ |
|||
throw new RuntimeException(e); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 日期路径 即年/月/日 如2018/08/08 |
|||
*/ |
|||
public static final String datePath() |
|||
{ |
|||
Date now = new Date(); |
|||
return DateFormatUtils.format(now, "yyyy/MM/dd"); |
|||
} |
|||
|
|||
/** |
|||
* 日期路径 即年/月/日 如20180808 |
|||
*/ |
|||
public static final String dateTime() |
|||
{ |
|||
Date now = new Date(); |
|||
return DateFormatUtils.format(now, "yyyyMMdd"); |
|||
} |
|||
|
|||
/** |
|||
* 日期型字符串转化为日期 格式 |
|||
*/ |
|||
public static Date parseDate(Object str) |
|||
{ |
|||
if (str == null) |
|||
{ |
|||
return null; |
|||
} |
|||
try |
|||
{ |
|||
return parseDate(str.toString(), parsePatterns); |
|||
} |
|||
catch (ParseException e) |
|||
{ |
|||
return null; |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 获取服务器启动时间 |
|||
*/ |
|||
public static Date getServerStartDate() |
|||
{ |
|||
long time = ManagementFactory.getRuntimeMXBean().getStartTime(); |
|||
return new Date(time); |
|||
} |
|||
|
|||
/** |
|||
* 计算两个时间差 |
|||
*/ |
|||
public static String getDatePoor(Date endDate, Date nowDate) |
|||
{ |
|||
long nd = 1000 * 24 * 60 * 60; |
|||
long nh = 1000 * 60 * 60; |
|||
long nm = 1000 * 60; |
|||
// long ns = 1000;
|
|||
// 获得两个时间的毫秒时间差异
|
|||
long diff = endDate.getTime() - nowDate.getTime(); |
|||
// 计算差多少天
|
|||
long day = diff / nd; |
|||
// 计算差多少小时
|
|||
long hour = diff % nd / nh; |
|||
// 计算差多少分钟
|
|||
long min = diff % nd % nh / nm; |
|||
// 计算差多少秒//输出结果
|
|||
// long sec = diff % nd % nh % nm / ns;
|
|||
return day + "天" + hour + "小时" + min + "分钟"; |
|||
} |
|||
|
|||
/** |
|||
* 增加 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()); |
|||
} |
|||
} |
|||
@ -0,0 +1,39 @@ |
|||
package com.bnyer.common.core.utils; |
|||
|
|||
import java.io.PrintWriter; |
|||
import java.io.StringWriter; |
|||
import org.apache.commons.lang3.exception.ExceptionUtils; |
|||
|
|||
/** |
|||
* 错误信息处理类。 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
public class ExceptionUtil |
|||
{ |
|||
/** |
|||
* 获取exception的详细错误信息。 |
|||
*/ |
|||
public static String getExceptionMessage(Throwable e) |
|||
{ |
|||
StringWriter sw = new StringWriter(); |
|||
e.printStackTrace(new PrintWriter(sw, true)); |
|||
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); |
|||
} |
|||
} |
|||
@ -0,0 +1,123 @@ |
|||
package com.bnyer.common.core.utils; |
|||
|
|||
import java.util.Map; |
|||
import com.bnyer.common.core.constant.SecurityConstants; |
|||
import com.bnyer.common.core.constant.TokenConstants; |
|||
import com.bnyer.common.core.text.Convert; |
|||
import io.jsonwebtoken.Claims; |
|||
import io.jsonwebtoken.Jwts; |
|||
import io.jsonwebtoken.SignatureAlgorithm; |
|||
|
|||
/** |
|||
* Jwt工具类 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
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), ""); |
|||
} |
|||
} |
|||
@ -0,0 +1,38 @@ |
|||
package com.bnyer.common.core.utils; |
|||
|
|||
import com.github.pagehelper.PageHelper; |
|||
import com.bnyer.common.core.utils.sql.SqlUtil; |
|||
import com.bnyer.common.core.web.page.PageDomain; |
|||
import com.bnyer.common.core.web.page.TableSupport; |
|||
|
|||
/** |
|||
* 分页工具类 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
public class PageUtils extends PageHelper |
|||
{ |
|||
/** |
|||
* 设置请求分页数据 |
|||
*/ |
|||
public static void startPage() |
|||
{ |
|||
PageDomain pageDomain = TableSupport.buildPageRequest(); |
|||
Integer pageNum = pageDomain.getPageNum(); |
|||
Integer pageSize = pageDomain.getPageSize(); |
|||
if (StringUtils.isNotNull(pageNum) && StringUtils.isNotNull(pageSize)) |
|||
{ |
|||
String orderBy = SqlUtil.escapeOrderBySql(pageDomain.getOrderBy()); |
|||
Boolean reasonable = pageDomain.getReasonable(); |
|||
PageHelper.startPage(pageNum, pageSize, orderBy).setReasonable(reasonable); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 清理分页的线程变量 |
|||
*/ |
|||
public static void clearPage() |
|||
{ |
|||
PageHelper.clearPage(); |
|||
} |
|||
} |
|||
@ -0,0 +1,163 @@ |
|||
package com.bnyer.common.core.utils; |
|||
|
|||
import java.util.Arrays; |
|||
import java.util.Collection; |
|||
import java.util.HashSet; |
|||
import java.util.Set; |
|||
import java.util.regex.Matcher; |
|||
import java.util.regex.Pattern; |
|||
|
|||
import com.bnyer.common.core.text.Convert; |
|||
|
|||
public class ReUtil |
|||
{ |
|||
public final static Pattern GROUP_VAR = Pattern.compile("\\$(\\d+)"); |
|||
|
|||
/** |
|||
* 正则中需要被转义的关键字 |
|||
*/ |
|||
public final static Set<Character> RE_KEYS = new HashSet<>( |
|||
Arrays.asList('$', '(', ')', '*', '+', '.', '[', ']', '?', '\\', '^', '{', '}', '|'));; |
|||
|
|||
/** |
|||
* 正则替换指定值<br> |
|||
* 通过正则查找到字符串,然后把匹配到的字符串加入到replacementTemplate中,$1表示分组1的字符串 |
|||
* |
|||
* <p> |
|||
* 例如:原字符串是:中文1234,我想把1234换成(1234),则可以: |
|||
* |
|||
* <pre> |
|||
* ReUtil.replaceAll("中文1234", "(\\d+)", "($1)")) |
|||
* |
|||
* 结果:中文(1234) |
|||
* </pre> |
|||
* |
|||
* @param content 文本 |
|||
* @param regex 正则 |
|||
* @param replacementTemplate 替换的文本模板,可以使用$1类似的变量提取正则匹配出的内容 |
|||
* @return 处理后的文本 |
|||
*/ |
|||
public static String replaceAll(CharSequence content, String regex, String replacementTemplate) |
|||
{ |
|||
final Pattern pattern = Pattern.compile(regex, Pattern.DOTALL); |
|||
return replaceAll(content, pattern, replacementTemplate); |
|||
} |
|||
|
|||
/** |
|||
* 正则替换指定值<br> |
|||
* 通过正则查找到字符串,然后把匹配到的字符串加入到replacementTemplate中,$1表示分组1的字符串 |
|||
* |
|||
* @param content 文本 |
|||
* @param pattern {@link Pattern} |
|||
* @param replacementTemplate 替换的文本模板,可以使用$1类似的变量提取正则匹配出的内容 |
|||
* @return 处理后的文本 |
|||
* @since 3.0.4 |
|||
*/ |
|||
public static String replaceAll(CharSequence content, Pattern pattern, String replacementTemplate) |
|||
{ |
|||
if (StringUtils.isEmpty(content)) |
|||
{ |
|||
return StringUtils.EMPTY; |
|||
} |
|||
|
|||
final Matcher matcher = pattern.matcher(content); |
|||
boolean result = matcher.find(); |
|||
if (result) |
|||
{ |
|||
final Set<String> varNums = findAll(GROUP_VAR, replacementTemplate, 1, new HashSet<>()); |
|||
final StringBuffer sb = new StringBuffer(); |
|||
do |
|||
{ |
|||
String replacement = replacementTemplate; |
|||
for (String var : varNums) |
|||
{ |
|||
int group = Integer.parseInt(var); |
|||
replacement = replacement.replace("$" + var, matcher.group(group)); |
|||
} |
|||
matcher.appendReplacement(sb, escape(replacement)); |
|||
result = matcher.find(); |
|||
} |
|||
while (result); |
|||
matcher.appendTail(sb); |
|||
return sb.toString(); |
|||
} |
|||
return Convert.toStr(content); |
|||
} |
|||
|
|||
/** |
|||
* 取得内容中匹配的所有结果 |
|||
* |
|||
* @param <T> 集合类型 |
|||
* @param pattern 编译后的正则模式 |
|||
* @param content 被查找的内容 |
|||
* @param group 正则的分组 |
|||
* @param collection 返回的集合类型 |
|||
* @return 结果集 |
|||
*/ |
|||
public static <T extends Collection<String>> T findAll(Pattern pattern, CharSequence content, int group, |
|||
T collection) |
|||
{ |
|||
if (null == pattern || null == content) |
|||
{ |
|||
return null; |
|||
} |
|||
|
|||
if (null == collection) |
|||
{ |
|||
throw new NullPointerException("Null collection param provided!"); |
|||
} |
|||
|
|||
final Matcher matcher = pattern.matcher(content); |
|||
while (matcher.find()) |
|||
{ |
|||
collection.add(matcher.group(group)); |
|||
} |
|||
return collection; |
|||
} |
|||
|
|||
/** |
|||
* 转义字符,将正则的关键字转义 |
|||
* |
|||
* @param c 字符 |
|||
* @return 转义后的文本 |
|||
*/ |
|||
public static String escape(char c) |
|||
{ |
|||
final StringBuilder builder = new StringBuilder(); |
|||
if (RE_KEYS.contains(c)) |
|||
{ |
|||
builder.append('\\'); |
|||
} |
|||
builder.append(c); |
|||
return builder.toString(); |
|||
} |
|||
|
|||
/** |
|||
* 转义字符串,将正则的关键字转义 |
|||
* |
|||
* @param content 文本 |
|||
* @return 转义后的文本 |
|||
*/ |
|||
public static String escape(CharSequence content) |
|||
{ |
|||
if (StringUtils.isBlank(content)) |
|||
{ |
|||
return StringUtils.EMPTY; |
|||
} |
|||
|
|||
final StringBuilder builder = new StringBuilder(); |
|||
int len = content.length(); |
|||
char current; |
|||
for (int i = 0; i < len; i++) |
|||
{ |
|||
current = content.charAt(i); |
|||
if (RE_KEYS.contains(current)) |
|||
{ |
|||
builder.append('\\'); |
|||
} |
|||
builder.append(current); |
|||
} |
|||
return builder.toString(); |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,303 @@ |
|||
package com.bnyer.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.LinkedHashMap; |
|||
import java.util.Map; |
|||
import javax.servlet.http.HttpServletRequest; |
|||
import javax.servlet.http.HttpServletResponse; |
|||
import javax.servlet.http.HttpSession; |
|||
|
|||
import com.bnyer.common.core.constant.Constants; |
|||
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.web.context.request.RequestAttributes; |
|||
import org.springframework.web.context.request.RequestContextHolder; |
|||
import org.springframework.web.context.request.ServletRequestAttributes; |
|||
import com.alibaba.fastjson.JSONObject; |
|||
import com.bnyer.common.core.domain.R; |
|||
import com.bnyer.common.core.text.Convert; |
|||
import reactor.core.publisher.Mono; |
|||
|
|||
/** |
|||
* 客户端工具类 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
public class ServletUtils |
|||
{ |
|||
/** |
|||
* 获取String参数 |
|||
*/ |
|||
public static String getParameter(String name) |
|||
{ |
|||
return getRequest().getParameter(name); |
|||
} |
|||
|
|||
/** |
|||
* 获取String参数 |
|||
*/ |
|||
public static String getParameter(String name, String defaultValue) |
|||
{ |
|||
return Convert.toStr(getRequest().getParameter(name), defaultValue); |
|||
} |
|||
|
|||
/** |
|||
* 获取Integer参数 |
|||
*/ |
|||
public static Integer getParameterToInt(String name) |
|||
{ |
|||
return Convert.toInt(getRequest().getParameter(name)); |
|||
} |
|||
|
|||
/** |
|||
* 获取Integer参数 |
|||
*/ |
|||
public static Integer getParameterToInt(String name, Integer defaultValue) |
|||
{ |
|||
return Convert.toInt(getRequest().getParameter(name), defaultValue); |
|||
} |
|||
|
|||
/** |
|||
* 获取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 LinkedHashMap<>(); |
|||
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(JSONObject.toJSONString(result).getBytes()); |
|||
return response.writeWith(Mono.just(dataBuffer)); |
|||
} |
|||
} |
|||
@ -0,0 +1,114 @@ |
|||
package com.bnyer.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 ruoyi |
|||
*/ |
|||
@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(); |
|||
} |
|||
} |
|||
@ -0,0 +1,531 @@ |
|||
package com.bnyer.common.core.utils; |
|||
|
|||
import java.util.Collection; |
|||
import java.util.List; |
|||
import java.util.Map; |
|||
|
|||
import com.bnyer.common.core.constant.Constants; |
|||
import com.bnyer.common.core.text.StrFormatter; |
|||
import org.springframework.util.AntPathMatcher; |
|||
|
|||
/** |
|||
* 字符串工具类 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
public class StringUtils extends org.apache.commons.lang3.StringUtils |
|||
{ |
|||
/** 空字符串 */ |
|||
private static final String NULLSTR = ""; |
|||
|
|||
/** 下划线 */ |
|||
private static final char SEPARATOR = '_'; |
|||
|
|||
/** |
|||
* 获取参数不为空值 |
|||
* |
|||
* @param value defaultValue 要判断的value |
|||
* @return value 返回值 |
|||
*/ |
|||
public static <T> T nvl(T value, T defaultValue) |
|||
{ |
|||
return value != null ? value : defaultValue; |
|||
} |
|||
|
|||
/** |
|||
* * 判断一个Collection是否为空, 包含List,Set,Queue |
|||
* |
|||
* @param coll 要判断的Collection |
|||
* @return true:为空 false:非空 |
|||
*/ |
|||
public static boolean isEmpty(Collection<?> coll) |
|||
{ |
|||
return isNull(coll) || coll.isEmpty(); |
|||
} |
|||
|
|||
/** |
|||
* * 判断一个Collection是否非空,包含List,Set,Queue |
|||
* |
|||
* @param coll 要判断的Collection |
|||
* @return true:非空 false:空 |
|||
*/ |
|||
public static boolean isNotEmpty(Collection<?> coll) |
|||
{ |
|||
return !isEmpty(coll); |
|||
} |
|||
|
|||
/** |
|||
* * 判断一个对象数组是否为空 |
|||
* |
|||
* @param objects 要判断的对象数组 |
|||
** @return true:为空 false:非空 |
|||
*/ |
|||
public static boolean isEmpty(Object[] objects) |
|||
{ |
|||
return isNull(objects) || (objects.length == 0); |
|||
} |
|||
|
|||
/** |
|||
* * 判断一个对象数组是否非空 |
|||
* |
|||
* @param objects 要判断的对象数组 |
|||
* @return true:非空 false:空 |
|||
*/ |
|||
public static boolean isNotEmpty(Object[] objects) |
|||
{ |
|||
return !isEmpty(objects); |
|||
} |
|||
|
|||
/** |
|||
* * 判断一个Map是否为空 |
|||
* |
|||
* @param map 要判断的Map |
|||
* @return true:为空 false:非空 |
|||
*/ |
|||
public static boolean isEmpty(Map<?, ?> map) |
|||
{ |
|||
return isNull(map) || map.isEmpty(); |
|||
} |
|||
|
|||
/** |
|||
* * 判断一个Map是否为空 |
|||
* |
|||
* @param map 要判断的Map |
|||
* @return true:非空 false:空 |
|||
*/ |
|||
public static boolean isNotEmpty(Map<?, ?> map) |
|||
{ |
|||
return !isEmpty(map); |
|||
} |
|||
|
|||
/** |
|||
* * 判断一个字符串是否为空串 |
|||
* |
|||
* @param str String |
|||
* @return true:为空 false:非空 |
|||
*/ |
|||
public static boolean isEmpty(String str) |
|||
{ |
|||
return isNull(str) || NULLSTR.equals(str.trim()); |
|||
} |
|||
|
|||
/** |
|||
* * 判断一个字符串是否为非空串 |
|||
* |
|||
* @param str String |
|||
* @return true:非空串 false:空串 |
|||
*/ |
|||
public static boolean isNotEmpty(String str) |
|||
{ |
|||
return !isEmpty(str); |
|||
} |
|||
|
|||
/** |
|||
* * 判断一个对象是否为空 |
|||
* |
|||
* @param object Object |
|||
* @return true:为空 false:非空 |
|||
*/ |
|||
public static boolean isNull(Object object) |
|||
{ |
|||
return object == null; |
|||
} |
|||
|
|||
/** |
|||
* * 判断一个对象是否非空 |
|||
* |
|||
* @param object Object |
|||
* @return true:非空 false:空 |
|||
*/ |
|||
public static boolean isNotNull(Object object) |
|||
{ |
|||
return !isNull(object); |
|||
} |
|||
|
|||
/** |
|||
* * 判断一个对象是否是数组类型(Java基本型别的数组) |
|||
* |
|||
* @param object 对象 |
|||
* @return true:是数组 false:不是数组 |
|||
*/ |
|||
public static boolean isArray(Object object) |
|||
{ |
|||
return isNotNull(object) && object.getClass().isArray(); |
|||
} |
|||
|
|||
/** |
|||
* 去空格 |
|||
*/ |
|||
public static String trim(String str) |
|||
{ |
|||
return (str == null ? "" : str.trim()); |
|||
} |
|||
|
|||
/** |
|||
* 截取字符串 |
|||
* |
|||
* @param str 字符串 |
|||
* @param start 开始 |
|||
* @return 结果 |
|||
*/ |
|||
public static String substring(final String str, int start) |
|||
{ |
|||
if (str == null) |
|||
{ |
|||
return NULLSTR; |
|||
} |
|||
|
|||
if (start < 0) |
|||
{ |
|||
start = str.length() + start; |
|||
} |
|||
|
|||
if (start < 0) |
|||
{ |
|||
start = 0; |
|||
} |
|||
if (start > str.length()) |
|||
{ |
|||
return NULLSTR; |
|||
} |
|||
|
|||
return str.substring(start); |
|||
} |
|||
|
|||
/** |
|||
* 截取字符串 |
|||
* |
|||
* @param str 字符串 |
|||
* @param start 开始 |
|||
* @param end 结束 |
|||
* @return 结果 |
|||
*/ |
|||
public static String substring(final String str, int start, int end) |
|||
{ |
|||
if (str == null) |
|||
{ |
|||
return NULLSTR; |
|||
} |
|||
|
|||
if (end < 0) |
|||
{ |
|||
end = str.length() + end; |
|||
} |
|||
if (start < 0) |
|||
{ |
|||
start = str.length() + start; |
|||
} |
|||
|
|||
if (end > str.length()) |
|||
{ |
|||
end = str.length(); |
|||
} |
|||
|
|||
if (start > end) |
|||
{ |
|||
return NULLSTR; |
|||
} |
|||
|
|||
if (start < 0) |
|||
{ |
|||
start = 0; |
|||
} |
|||
if (end < 0) |
|||
{ |
|||
end = 0; |
|||
} |
|||
|
|||
return str.substring(start, end); |
|||
} |
|||
|
|||
/** |
|||
* 判断是否为空,并且不是空白字符 |
|||
* |
|||
* @param str 要判断的value |
|||
* @return 结果 |
|||
*/ |
|||
public static boolean hasText(String str) |
|||
{ |
|||
return (str != null && !str.isEmpty() && containsText(str)); |
|||
} |
|||
|
|||
private static boolean containsText(CharSequence str) |
|||
{ |
|||
int strLen = str.length(); |
|||
for (int i = 0; i < strLen; i++) |
|||
{ |
|||
if (!Character.isWhitespace(str.charAt(i))) |
|||
{ |
|||
return true; |
|||
} |
|||
} |
|||
return false; |
|||
} |
|||
|
|||
/** |
|||
* 格式化文本, {} 表示占位符<br> |
|||
* 此方法只是简单将占位符 {} 按照顺序替换为参数<br> |
|||
* 如果想输出 {} 使用 \\转义 { 即可,如果想输出 {} 之前的 \ 使用双转义符 \\\\ 即可<br> |
|||
* 例:<br> |
|||
* 通常使用:format("this is {} for {}", "a", "b") -> this is a for b<br> |
|||
* 转义{}: format("this is \\{} for {}", "a", "b") -> this is \{} for a<br> |
|||
* 转义\: format("this is \\\\{} for {}", "a", "b") -> this is \a for b<br> |
|||
* |
|||
* @param template 文本模板,被替换的部分用 {} 表示 |
|||
* @param params 参数值 |
|||
* @return 格式化后的文本 |
|||
*/ |
|||
public static String format(String template, Object... params) |
|||
{ |
|||
if (isEmpty(params) || isEmpty(template)) |
|||
{ |
|||
return template; |
|||
} |
|||
return StrFormatter.format(template, params); |
|||
} |
|||
|
|||
/** |
|||
* 是否为http(s)://开头
|
|||
* |
|||
* @param link 链接 |
|||
* @return 结果 |
|||
*/ |
|||
public static boolean ishttp(String link) |
|||
{ |
|||
return StringUtils.startsWithAny(link, Constants.HTTP, Constants.HTTPS); |
|||
} |
|||
|
|||
/** |
|||
* 驼峰转下划线命名 |
|||
*/ |
|||
public static String toUnderScoreCase(String str) |
|||
{ |
|||
if (str == null) |
|||
{ |
|||
return null; |
|||
} |
|||
StringBuilder sb = new StringBuilder(); |
|||
// 前置字符是否大写
|
|||
boolean preCharIsUpperCase = true; |
|||
// 当前字符是否大写
|
|||
boolean curreCharIsUpperCase = true; |
|||
// 下一字符是否大写
|
|||
boolean nexteCharIsUpperCase = true; |
|||
for (int i = 0; i < str.length(); i++) |
|||
{ |
|||
char c = str.charAt(i); |
|||
if (i > 0) |
|||
{ |
|||
preCharIsUpperCase = Character.isUpperCase(str.charAt(i - 1)); |
|||
} |
|||
else |
|||
{ |
|||
preCharIsUpperCase = false; |
|||
} |
|||
|
|||
curreCharIsUpperCase = Character.isUpperCase(c); |
|||
|
|||
if (i < (str.length() - 1)) |
|||
{ |
|||
nexteCharIsUpperCase = Character.isUpperCase(str.charAt(i + 1)); |
|||
} |
|||
|
|||
if (preCharIsUpperCase && curreCharIsUpperCase && !nexteCharIsUpperCase) |
|||
{ |
|||
sb.append(SEPARATOR); |
|||
} |
|||
else if ((i != 0 && !preCharIsUpperCase) && curreCharIsUpperCase) |
|||
{ |
|||
sb.append(SEPARATOR); |
|||
} |
|||
sb.append(Character.toLowerCase(c)); |
|||
} |
|||
|
|||
return sb.toString(); |
|||
} |
|||
|
|||
/** |
|||
* 是否包含字符串 |
|||
* |
|||
* @param str 验证字符串 |
|||
* @param strs 字符串组 |
|||
* @return 包含返回true |
|||
*/ |
|||
public static boolean inStringIgnoreCase(String str, String... strs) |
|||
{ |
|||
if (str != null && strs != null) |
|||
{ |
|||
for (String s : strs) |
|||
{ |
|||
if (str.equalsIgnoreCase(trim(s))) |
|||
{ |
|||
return true; |
|||
} |
|||
} |
|||
} |
|||
return false; |
|||
} |
|||
|
|||
/** |
|||
* 将下划线大写方式命名的字符串转换为驼峰式。如果转换前的下划线大写方式命名的字符串为空,则返回空字符串。 例如:HELLO_WORLD->HelloWorld |
|||
* |
|||
* @param name 转换前的下划线大写方式命名的字符串 |
|||
* @return 转换后的驼峰式命名的字符串 |
|||
*/ |
|||
public static String convertToCamelCase(String name) |
|||
{ |
|||
StringBuilder result = new StringBuilder(); |
|||
// 快速检查
|
|||
if (name == null || name.isEmpty()) |
|||
{ |
|||
// 没必要转换
|
|||
return ""; |
|||
} |
|||
else if (!name.contains("_")) |
|||
{ |
|||
// 不含下划线,仅将首字母大写
|
|||
return name.substring(0, 1).toUpperCase() + name.substring(1); |
|||
} |
|||
// 用下划线将原始字符串分割
|
|||
String[] camels = name.split("_"); |
|||
for (String camel : camels) |
|||
{ |
|||
// 跳过原始字符串中开头、结尾的下换线或双重下划线
|
|||
if (camel.isEmpty()) |
|||
{ |
|||
continue; |
|||
} |
|||
// 首字母大写
|
|||
result.append(camel.substring(0, 1).toUpperCase()); |
|||
result.append(camel.substring(1).toLowerCase()); |
|||
} |
|||
return result.toString(); |
|||
} |
|||
|
|||
/** |
|||
* 驼峰式命名法 例如:user_name->userName |
|||
*/ |
|||
public static String toCamelCase(String s) |
|||
{ |
|||
if (s == null) |
|||
{ |
|||
return null; |
|||
} |
|||
s = s.toLowerCase(); |
|||
StringBuilder sb = new StringBuilder(s.length()); |
|||
boolean upperCase = false; |
|||
for (int i = 0; i < s.length(); i++) |
|||
{ |
|||
char c = s.charAt(i); |
|||
|
|||
if (c == SEPARATOR) |
|||
{ |
|||
upperCase = true; |
|||
} |
|||
else if (upperCase) |
|||
{ |
|||
sb.append(Character.toUpperCase(c)); |
|||
upperCase = false; |
|||
} |
|||
else |
|||
{ |
|||
sb.append(c); |
|||
} |
|||
} |
|||
return sb.toString(); |
|||
} |
|||
|
|||
/** |
|||
* 查找指定字符串是否匹配指定字符串列表中的任意一个字符串 |
|||
* |
|||
* @param str 指定字符串 |
|||
* @param strs 需要检查的字符串数组 |
|||
* @return 是否匹配 |
|||
*/ |
|||
public static boolean matches(String str, List<String> strs) |
|||
{ |
|||
if (isEmpty(str) || isEmpty(strs)) |
|||
{ |
|||
return false; |
|||
} |
|||
for (String pattern : strs) |
|||
{ |
|||
if (isMatch(pattern, str)) |
|||
{ |
|||
return true; |
|||
} |
|||
} |
|||
return false; |
|||
} |
|||
|
|||
/** |
|||
* 判断url是否与规则配置: |
|||
* ? 表示单个字符; |
|||
* * 表示一层路径内的任意字符串,不可跨层级; |
|||
* ** 表示任意层路径; |
|||
* |
|||
* @param pattern 匹配规则 |
|||
* @param url 需要匹配的url |
|||
* @return |
|||
*/ |
|||
public static boolean isMatch(String pattern, String url) |
|||
{ |
|||
AntPathMatcher matcher = new AntPathMatcher(); |
|||
return matcher.match(pattern, url); |
|||
} |
|||
|
|||
@SuppressWarnings("unchecked") |
|||
public static <T> T cast(Object obj) |
|||
{ |
|||
return (T) obj; |
|||
} |
|||
|
|||
/** |
|||
* 数字左边补齐0,使之达到指定长度。注意,如果数字转换为字符串后,长度大于size,则只保留 最后size个字符。 |
|||
* |
|||
* @param num 数字对象 |
|||
* @param size 字符串指定长度 |
|||
* @return 返回数字的字符串格式,该字符串为指定长度。 |
|||
*/ |
|||
public static final String padl(final Number num, final int size) |
|||
{ |
|||
return padl(num.toString(), size, '0'); |
|||
} |
|||
|
|||
/** |
|||
* 字符串左补齐。如果原始字符串s长度大于size,则只保留最后size个字符。 |
|||
* |
|||
* @param s 原始字符串 |
|||
* @param size 字符串指定长度 |
|||
* @param c 用于补齐的字符 |
|||
* @return 返回指定长度的字符串,由原字符串左补齐或截取得到。 |
|||
*/ |
|||
public static final String padl(final String s, final int size, final char c) |
|||
{ |
|||
final StringBuilder sb = new StringBuilder(size); |
|||
if (s != null) |
|||
{ |
|||
final int len = s.length(); |
|||
if (s.length() <= size) |
|||
{ |
|||
for (int i = size - len; i > 0; i--) |
|||
{ |
|||
sb.append(c); |
|||
} |
|||
sb.append(s); |
|||
} |
|||
else |
|||
{ |
|||
return s.substring(len - size, len); |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
for (int i = size; i > 0; i--) |
|||
{ |
|||
sb.append(c); |
|||
} |
|||
} |
|||
return sb.toString(); |
|||
} |
|||
} |
|||
@ -0,0 +1,110 @@ |
|||
package com.bnyer.common.core.utils.bean; |
|||
|
|||
import java.lang.reflect.Method; |
|||
import java.util.ArrayList; |
|||
import java.util.List; |
|||
import java.util.regex.Matcher; |
|||
import java.util.regex.Pattern; |
|||
|
|||
/** |
|||
* Bean 工具类 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
public class BeanUtils extends org.springframework.beans.BeanUtils |
|||
{ |
|||
/** Bean方法名中属性名开始的下标 */ |
|||
private static final int BEAN_METHOD_PROP_INDEX = 3; |
|||
|
|||
/** * 匹配getter方法的正则表达式 */ |
|||
private static final Pattern GET_PATTERN = Pattern.compile("get(\\p{javaUpperCase}\\w*)"); |
|||
|
|||
/** * 匹配setter方法的正则表达式 */ |
|||
private static final Pattern SET_PATTERN = Pattern.compile("set(\\p{javaUpperCase}\\w*)"); |
|||
|
|||
/** |
|||
* Bean属性复制工具方法。 |
|||
* |
|||
* @param dest 目标对象 |
|||
* @param src 源对象 |
|||
*/ |
|||
public static void copyBeanProp(Object dest, Object src) |
|||
{ |
|||
try |
|||
{ |
|||
copyProperties(src, dest); |
|||
} |
|||
catch (Exception e) |
|||
{ |
|||
e.printStackTrace(); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 获取对象的setter方法。 |
|||
* |
|||
* @param obj 对象 |
|||
* @return 对象的setter方法列表 |
|||
*/ |
|||
public static List<Method> getSetterMethods(Object obj) |
|||
{ |
|||
// setter方法列表
|
|||
List<Method> setterMethods = new ArrayList<Method>(); |
|||
|
|||
// 获取所有方法
|
|||
Method[] methods = obj.getClass().getMethods(); |
|||
|
|||
// 查找setter方法
|
|||
|
|||
for (Method method : methods) |
|||
{ |
|||
Matcher m = SET_PATTERN.matcher(method.getName()); |
|||
if (m.matches() && (method.getParameterTypes().length == 1)) |
|||
{ |
|||
setterMethods.add(method); |
|||
} |
|||
} |
|||
// 返回setter方法列表
|
|||
return setterMethods; |
|||
} |
|||
|
|||
/** |
|||
* 获取对象的getter方法。 |
|||
* |
|||
* @param obj 对象 |
|||
* @return 对象的getter方法列表 |
|||
*/ |
|||
|
|||
public static List<Method> getGetterMethods(Object obj) |
|||
{ |
|||
// getter方法列表
|
|||
List<Method> getterMethods = new ArrayList<Method>(); |
|||
// 获取所有方法
|
|||
Method[] methods = obj.getClass().getMethods(); |
|||
// 查找getter方法
|
|||
for (Method method : methods) |
|||
{ |
|||
Matcher m = GET_PATTERN.matcher(method.getName()); |
|||
if (m.matches() && (method.getParameterTypes().length == 0)) |
|||
{ |
|||
getterMethods.add(method); |
|||
} |
|||
} |
|||
// 返回getter方法列表
|
|||
return getterMethods; |
|||
} |
|||
|
|||
/** |
|||
* 检查Bean方法名中的属性名是否相等。<br> |
|||
* 如getName()和setName()属性名一样,getName()和setAge()属性名不一样。 |
|||
* |
|||
* @param m1 方法名1 |
|||
* @param m2 方法名2 |
|||
* @return 属性名一样返回true,否则返回false |
|||
*/ |
|||
|
|||
public static boolean isMethodPropEquals(String m1, String m2) |
|||
{ |
|||
return m1.substring(BEAN_METHOD_PROP_INDEX).equals(m2.substring(BEAN_METHOD_PROP_INDEX)); |
|||
} |
|||
} |
|||
@ -0,0 +1,24 @@ |
|||
package com.bnyer.common.core.utils.bean; |
|||
|
|||
import java.util.Set; |
|||
import javax.validation.ConstraintViolation; |
|||
import javax.validation.ConstraintViolationException; |
|||
import javax.validation.Validator; |
|||
|
|||
/** |
|||
* bean对象属性验证 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
public class BeanValidators |
|||
{ |
|||
public static void validateWithException(Validator validator, Object object, Class<?>... groups) |
|||
throws ConstraintViolationException |
|||
{ |
|||
Set<ConstraintViolation<Object>> constraintViolations = validator.validate(object, groups); |
|||
if (!constraintViolations.isEmpty()) |
|||
{ |
|||
throw new ConstraintViolationException(constraintViolations); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,76 @@ |
|||
package com.bnyer.common.core.utils.file; |
|||
|
|||
import java.io.File; |
|||
import org.apache.commons.lang3.StringUtils; |
|||
|
|||
/** |
|||
* 文件类型工具类 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
public class FileTypeUtils |
|||
{ |
|||
/** |
|||
* 获取文件类型 |
|||
* <p> |
|||
* 例如: bnyer.txt, 返回: txt |
|||
* |
|||
* @param file 文件名 |
|||
* @return 后缀(不含".") |
|||
*/ |
|||
public static String getFileType(File file) |
|||
{ |
|||
if (null == file) |
|||
{ |
|||
return StringUtils.EMPTY; |
|||
} |
|||
return getFileType(file.getName()); |
|||
} |
|||
|
|||
/** |
|||
* 获取文件类型 |
|||
* <p> |
|||
* 例如: bnyer.txt, 返回: txt |
|||
* |
|||
* @param fileName 文件名 |
|||
* @return 后缀(不含".") |
|||
*/ |
|||
public static String getFileType(String fileName) |
|||
{ |
|||
int separatorIndex = fileName.lastIndexOf("."); |
|||
if (separatorIndex < 0) |
|||
{ |
|||
return ""; |
|||
} |
|||
return fileName.substring(separatorIndex + 1).toLowerCase(); |
|||
} |
|||
|
|||
/** |
|||
* 获取文件类型 |
|||
* |
|||
* @param photoByte 文件字节码 |
|||
* @return 后缀(不含".") |
|||
*/ |
|||
public static String getFileExtendName(byte[] photoByte) |
|||
{ |
|||
String strFileExtendName = "JPG"; |
|||
if ((photoByte[0] == 71) && (photoByte[1] == 73) && (photoByte[2] == 70) && (photoByte[3] == 56) |
|||
&& ((photoByte[4] == 55) || (photoByte[4] == 57)) && (photoByte[5] == 97)) |
|||
{ |
|||
strFileExtendName = "GIF"; |
|||
} |
|||
else if ((photoByte[6] == 74) && (photoByte[7] == 70) && (photoByte[8] == 73) && (photoByte[9] == 70)) |
|||
{ |
|||
strFileExtendName = "JPG"; |
|||
} |
|||
else if ((photoByte[0] == 66) && (photoByte[1] == 77)) |
|||
{ |
|||
strFileExtendName = "BMP"; |
|||
} |
|||
else if ((photoByte[1] == 80) && (photoByte[2] == 78) && (photoByte[3] == 71)) |
|||
{ |
|||
strFileExtendName = "PNG"; |
|||
} |
|||
return strFileExtendName; |
|||
} |
|||
} |
|||
@ -0,0 +1,261 @@ |
|||
package com.bnyer.common.core.utils.file; |
|||
|
|||
import java.io.File; |
|||
import java.io.FileInputStream; |
|||
import java.io.FileNotFoundException; |
|||
import java.io.IOException; |
|||
import java.io.OutputStream; |
|||
import java.io.UnsupportedEncodingException; |
|||
import java.net.URLEncoder; |
|||
import java.nio.charset.StandardCharsets; |
|||
import javax.servlet.http.HttpServletRequest; |
|||
import javax.servlet.http.HttpServletResponse; |
|||
import org.apache.commons.lang3.ArrayUtils; |
|||
import com.bnyer.common.core.utils.StringUtils; |
|||
|
|||
/** |
|||
* 文件处理工具类 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
public class FileUtils |
|||
{ |
|||
/** 字符常量:斜杠 {@code '/'} */ |
|||
public static final char SLASH = '/'; |
|||
|
|||
/** 字符常量:反斜杠 {@code '\\'} */ |
|||
public static final char BACKSLASH = '\\'; |
|||
|
|||
public static String FILENAME_PATTERN = "[a-zA-Z0-9_\\-\\|\\.\\u4e00-\\u9fa5]+"; |
|||
|
|||
/** |
|||
* 输出指定文件的byte数组 |
|||
* |
|||
* @param filePath 文件路径 |
|||
* @param os 输出流 |
|||
* @return |
|||
*/ |
|||
public static void writeBytes(String filePath, OutputStream os) throws IOException |
|||
{ |
|||
FileInputStream fis = null; |
|||
try |
|||
{ |
|||
File file = new File(filePath); |
|||
if (!file.exists()) |
|||
{ |
|||
throw new FileNotFoundException(filePath); |
|||
} |
|||
fis = new FileInputStream(file); |
|||
byte[] b = new byte[1024]; |
|||
int length; |
|||
while ((length = fis.read(b)) > 0) |
|||
{ |
|||
os.write(b, 0, length); |
|||
} |
|||
} |
|||
catch (IOException e) |
|||
{ |
|||
throw e; |
|||
} |
|||
finally |
|||
{ |
|||
if (os != null) |
|||
{ |
|||
try |
|||
{ |
|||
os.close(); |
|||
} |
|||
catch (IOException e1) |
|||
{ |
|||
e1.printStackTrace(); |
|||
} |
|||
} |
|||
if (fis != null) |
|||
{ |
|||
try |
|||
{ |
|||
fis.close(); |
|||
} |
|||
catch (IOException e1) |
|||
{ |
|||
e1.printStackTrace(); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 删除文件 |
|||
* |
|||
* @param filePath 文件 |
|||
* @return |
|||
*/ |
|||
public static boolean deleteFile(String filePath) |
|||
{ |
|||
boolean flag = false; |
|||
File file = new File(filePath); |
|||
// 路径为文件且不为空则进行删除
|
|||
if (file.isFile() && file.exists()) |
|||
{ |
|||
file.delete(); |
|||
flag = true; |
|||
} |
|||
return flag; |
|||
} |
|||
|
|||
/** |
|||
* 文件名称验证 |
|||
* |
|||
* @param filename 文件名称 |
|||
* @return true 正常 false 非法 |
|||
*/ |
|||
public static boolean isValidFilename(String filename) |
|||
{ |
|||
return filename.matches(FILENAME_PATTERN); |
|||
} |
|||
|
|||
/** |
|||
* 检查文件是否可下载 |
|||
* |
|||
* @param resource 需要下载的文件 |
|||
* @return true 正常 false 非法 |
|||
*/ |
|||
public static boolean checkAllowDownload(String resource) |
|||
{ |
|||
// 禁止目录上跳级别
|
|||
if (StringUtils.contains(resource, "..")) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
// 检查允许下载的文件规则
|
|||
if (ArrayUtils.contains(MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION, FileTypeUtils.getFileType(resource))) |
|||
{ |
|||
return true; |
|||
} |
|||
|
|||
// 不在允许下载的文件规则
|
|||
return false; |
|||
} |
|||
|
|||
/** |
|||
* 下载文件名重新编码 |
|||
* |
|||
* @param request 请求对象 |
|||
* @param fileName 文件名 |
|||
* @return 编码后的文件名 |
|||
*/ |
|||
public static String setFileDownloadHeader(HttpServletRequest request, String fileName) throws UnsupportedEncodingException |
|||
{ |
|||
final String agent = request.getHeader("USER-AGENT"); |
|||
String filename = fileName; |
|||
if (agent.contains("MSIE")) |
|||
{ |
|||
// IE浏览器
|
|||
filename = URLEncoder.encode(filename, "utf-8"); |
|||
filename = filename.replace("+", " "); |
|||
} |
|||
else if (agent.contains("Firefox")) |
|||
{ |
|||
// 火狐浏览器
|
|||
filename = new String(fileName.getBytes(), "ISO8859-1"); |
|||
} |
|||
else if (agent.contains("Chrome")) |
|||
{ |
|||
// google浏览器
|
|||
filename = URLEncoder.encode(filename, "utf-8"); |
|||
} |
|||
else |
|||
{ |
|||
// 其它浏览器
|
|||
filename = URLEncoder.encode(filename, "utf-8"); |
|||
} |
|||
return filename; |
|||
} |
|||
|
|||
/** |
|||
* 返回文件名 |
|||
* |
|||
* @param filePath 文件 |
|||
* @return 文件名 |
|||
*/ |
|||
public static String getName(String filePath) |
|||
{ |
|||
if (null == filePath) |
|||
{ |
|||
return null; |
|||
} |
|||
int len = filePath.length(); |
|||
if (0 == len) |
|||
{ |
|||
return filePath; |
|||
} |
|||
if (isFileSeparator(filePath.charAt(len - 1))) |
|||
{ |
|||
// 以分隔符结尾的去掉结尾分隔符
|
|||
len--; |
|||
} |
|||
|
|||
int begin = 0; |
|||
char c; |
|||
for (int i = len - 1; i > -1; i--) |
|||
{ |
|||
c = filePath.charAt(i); |
|||
if (isFileSeparator(c)) |
|||
{ |
|||
// 查找最后一个路径分隔符(/或者\)
|
|||
begin = i + 1; |
|||
break; |
|||
} |
|||
} |
|||
|
|||
return filePath.substring(begin, len); |
|||
} |
|||
|
|||
/** |
|||
* 是否为Windows或者Linux(Unix)文件分隔符<br> |
|||
* Windows平台下分隔符为\,Linux(Unix)为/ |
|||
* |
|||
* @param c 字符 |
|||
* @return 是否为Windows或者Linux(Unix)文件分隔符 |
|||
*/ |
|||
public static boolean isFileSeparator(char c) |
|||
{ |
|||
return SLASH == c || BACKSLASH == c; |
|||
} |
|||
|
|||
/** |
|||
* 下载文件名重新编码 |
|||
* |
|||
* @param response 响应对象 |
|||
* @param realFileName 真实文件名 |
|||
* @return |
|||
*/ |
|||
public static void setAttachmentResponseHeader(HttpServletResponse response, String realFileName) throws UnsupportedEncodingException |
|||
{ |
|||
String percentEncodedFileName = percentEncode(realFileName); |
|||
|
|||
StringBuilder contentDispositionValue = new StringBuilder(); |
|||
contentDispositionValue.append("attachment; filename=") |
|||
.append(percentEncodedFileName) |
|||
.append(";") |
|||
.append("filename*=") |
|||
.append("utf-8''") |
|||
.append(percentEncodedFileName); |
|||
|
|||
response.setHeader("Content-disposition", contentDispositionValue.toString()); |
|||
response.setHeader("download-filename", percentEncodedFileName); |
|||
} |
|||
|
|||
/** |
|||
* 百分号编码工具方法 |
|||
* |
|||
* @param s 需要百分号编码的字符串 |
|||
* @return 百分号编码后的字符串 |
|||
*/ |
|||
public static String percentEncode(String s) throws UnsupportedEncodingException |
|||
{ |
|||
String encode = URLEncoder.encode(s, StandardCharsets.UTF_8.toString()); |
|||
return encode.replaceAll("\\+", "%20"); |
|||
} |
|||
} |
|||
@ -0,0 +1,84 @@ |
|||
package com.bnyer.common.core.utils.file; |
|||
|
|||
import java.io.ByteArrayInputStream; |
|||
import java.io.InputStream; |
|||
import java.net.URL; |
|||
import java.net.URLConnection; |
|||
import java.util.Arrays; |
|||
import org.apache.poi.util.IOUtils; |
|||
import org.slf4j.Logger; |
|||
import org.slf4j.LoggerFactory; |
|||
|
|||
/** |
|||
* 图片处理工具类 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
public class ImageUtils |
|||
{ |
|||
private static final Logger log = LoggerFactory.getLogger(ImageUtils.class); |
|||
|
|||
public static byte[] getImage(String imagePath) |
|||
{ |
|||
InputStream is = getFile(imagePath); |
|||
try |
|||
{ |
|||
return IOUtils.toByteArray(is); |
|||
} |
|||
catch (Exception e) |
|||
{ |
|||
log.error("图片加载异常 {}", e); |
|||
return null; |
|||
} |
|||
finally |
|||
{ |
|||
IOUtils.closeQuietly(is); |
|||
} |
|||
} |
|||
|
|||
public static InputStream getFile(String imagePath) |
|||
{ |
|||
try |
|||
{ |
|||
byte[] result = readFile(imagePath); |
|||
result = Arrays.copyOf(result, result.length); |
|||
return new ByteArrayInputStream(result); |
|||
} |
|||
catch (Exception e) |
|||
{ |
|||
log.error("获取图片异常 {}", e); |
|||
} |
|||
return null; |
|||
} |
|||
|
|||
/** |
|||
* 读取文件为字节数据 |
|||
* |
|||
* @param url 地址 |
|||
* @return 字节数据 |
|||
*/ |
|||
public static byte[] readFile(String url) |
|||
{ |
|||
InputStream in = null; |
|||
try |
|||
{ |
|||
// 网络地址
|
|||
URL urlObj = new URL(url); |
|||
URLConnection urlConnection = urlObj.openConnection(); |
|||
urlConnection.setConnectTimeout(30 * 1000); |
|||
urlConnection.setReadTimeout(60 * 1000); |
|||
urlConnection.setDoInput(true); |
|||
in = urlConnection.getInputStream(); |
|||
return IOUtils.toByteArray(in); |
|||
} |
|||
catch (Exception e) |
|||
{ |
|||
log.error("访问文件异常 {}", e); |
|||
return null; |
|||
} |
|||
finally |
|||
{ |
|||
IOUtils.closeQuietly(in); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,59 @@ |
|||
package com.bnyer.common.core.utils.file; |
|||
|
|||
/** |
|||
* 媒体类型工具类 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
public class MimeTypeUtils |
|||
{ |
|||
public static final String IMAGE_PNG = "image/png"; |
|||
|
|||
public static final String IMAGE_JPG = "image/jpg"; |
|||
|
|||
public static final String IMAGE_JPEG = "image/jpeg"; |
|||
|
|||
public static final String IMAGE_BMP = "image/bmp"; |
|||
|
|||
public static final String IMAGE_GIF = "image/gif"; |
|||
|
|||
public static final String[] IMAGE_EXTENSION = { "bmp", "gif", "jpg", "jpeg", "png" }; |
|||
|
|||
public static final String[] FLASH_EXTENSION = { "swf", "flv" }; |
|||
|
|||
public static final String[] MEDIA_EXTENSION = { "swf", "flv", "mp3", "wav", "wma", "wmv", "mid", "avi", "mpg", |
|||
"asf", "rm", "rmvb" }; |
|||
|
|||
public static final String[] VIDEO_EXTENSION = { "mp4", "avi", "rmvb" }; |
|||
|
|||
public static final String[] DEFAULT_ALLOWED_EXTENSION = { |
|||
// 图片
|
|||
"bmp", "gif", "jpg", "jpeg", "png", |
|||
// word excel powerpoint
|
|||
"doc", "docx", "xls", "xlsx", "ppt", "pptx", "html", "htm", "txt", |
|||
// 压缩文件
|
|||
"rar", "zip", "gz", "bz2", |
|||
// 视频格式
|
|||
"mp4", "avi", "rmvb", |
|||
// pdf
|
|||
"pdf" }; |
|||
|
|||
public static String getExtension(String prefix) |
|||
{ |
|||
switch (prefix) |
|||
{ |
|||
case IMAGE_PNG: |
|||
return "png"; |
|||
case IMAGE_JPG: |
|||
return "jpg"; |
|||
case IMAGE_JPEG: |
|||
return "jpeg"; |
|||
case IMAGE_BMP: |
|||
return "bmp"; |
|||
case IMAGE_GIF: |
|||
return "gif"; |
|||
default: |
|||
return ""; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,167 @@ |
|||
package com.bnyer.common.core.utils.html; |
|||
|
|||
import com.bnyer.common.core.utils.StringUtils; |
|||
|
|||
/** |
|||
* 转义和反转义工具类 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
public class EscapeUtil |
|||
{ |
|||
public static final String RE_HTML_MARK = "(<[^<]*?>)|(<[\\s]*?/[^<]*?>)|(<[^<]*?/[\\s]*?>)"; |
|||
|
|||
private static final char[][] TEXT = new char[64][]; |
|||
|
|||
static |
|||
{ |
|||
for (int i = 0; i < 64; i++) |
|||
{ |
|||
TEXT[i] = new char[] { (char) i }; |
|||
} |
|||
|
|||
// special HTML characters
|
|||
TEXT['\''] = "'".toCharArray(); // 单引号
|
|||
TEXT['"'] = """.toCharArray(); // 双引号
|
|||
TEXT['&'] = "&".toCharArray(); // &符
|
|||
TEXT['<'] = "<".toCharArray(); // 小于号
|
|||
TEXT['>'] = ">".toCharArray(); // 大于号
|
|||
} |
|||
|
|||
/** |
|||
* 转义文本中的HTML字符为安全的字符 |
|||
* |
|||
* @param text 被转义的文本 |
|||
* @return 转义后的文本 |
|||
*/ |
|||
public static String escape(String text) |
|||
{ |
|||
return encode(text); |
|||
} |
|||
|
|||
/** |
|||
* 还原被转义的HTML特殊字符 |
|||
* |
|||
* @param content 包含转义符的HTML内容 |
|||
* @return 转换后的字符串 |
|||
*/ |
|||
public static String unescape(String content) |
|||
{ |
|||
return decode(content); |
|||
} |
|||
|
|||
/** |
|||
* 清除所有HTML标签,但是不删除标签内的内容 |
|||
* |
|||
* @param content 文本 |
|||
* @return 清除标签后的文本 |
|||
*/ |
|||
public static String clean(String content) |
|||
{ |
|||
return new HTMLFilter().filter(content); |
|||
} |
|||
|
|||
/** |
|||
* Escape编码 |
|||
* |
|||
* @param text 被编码的文本 |
|||
* @return 编码后的字符 |
|||
*/ |
|||
private static String encode(String text) |
|||
{ |
|||
if (StringUtils.isEmpty(text)) |
|||
{ |
|||
return StringUtils.EMPTY; |
|||
} |
|||
|
|||
final StringBuilder tmp = new StringBuilder(text.length() * 6); |
|||
char c; |
|||
for (int i = 0; i < text.length(); i++) |
|||
{ |
|||
c = text.charAt(i); |
|||
if (c < 256) |
|||
{ |
|||
tmp.append("%"); |
|||
if (c < 16) |
|||
{ |
|||
tmp.append("0"); |
|||
} |
|||
tmp.append(Integer.toString(c, 16)); |
|||
} |
|||
else |
|||
{ |
|||
tmp.append("%u"); |
|||
if (c <= 0xfff) |
|||
{ |
|||
// issue#I49JU8@Gitee
|
|||
tmp.append("0"); |
|||
} |
|||
tmp.append(Integer.toString(c, 16)); |
|||
} |
|||
} |
|||
return tmp.toString(); |
|||
} |
|||
|
|||
/** |
|||
* Escape解码 |
|||
* |
|||
* @param content 被转义的内容 |
|||
* @return 解码后的字符串 |
|||
*/ |
|||
public static String decode(String content) |
|||
{ |
|||
if (StringUtils.isEmpty(content)) |
|||
{ |
|||
return content; |
|||
} |
|||
|
|||
StringBuilder tmp = new StringBuilder(content.length()); |
|||
int lastPos = 0, pos = 0; |
|||
char ch; |
|||
while (lastPos < content.length()) |
|||
{ |
|||
pos = content.indexOf("%", lastPos); |
|||
if (pos == lastPos) |
|||
{ |
|||
if (content.charAt(pos + 1) == 'u') |
|||
{ |
|||
ch = (char) Integer.parseInt(content.substring(pos + 2, pos + 6), 16); |
|||
tmp.append(ch); |
|||
lastPos = pos + 6; |
|||
} |
|||
else |
|||
{ |
|||
ch = (char) Integer.parseInt(content.substring(pos + 1, pos + 3), 16); |
|||
tmp.append(ch); |
|||
lastPos = pos + 3; |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
if (pos == -1) |
|||
{ |
|||
tmp.append(content.substring(lastPos)); |
|||
lastPos = content.length(); |
|||
} |
|||
else |
|||
{ |
|||
tmp.append(content.substring(lastPos, pos)); |
|||
lastPos = pos; |
|||
} |
|||
} |
|||
} |
|||
return tmp.toString(); |
|||
} |
|||
|
|||
public static void main(String[] args) |
|||
{ |
|||
String html = "<script>alert(1);</script>"; |
|||
String escape = EscapeUtil.escape(html); |
|||
// String html = "<scr<script>ipt>alert(\"XSS\")</scr<script>ipt>";
|
|||
// String html = "<123";
|
|||
// String html = "123>";
|
|||
System.out.println("clean: " + EscapeUtil.clean(html)); |
|||
System.out.println("escape: " + escape); |
|||
System.out.println("unescape: " + EscapeUtil.unescape(escape)); |
|||
} |
|||
} |
|||
@ -0,0 +1,570 @@ |
|||
package com.bnyer.common.core.utils.html; |
|||
|
|||
import java.util.ArrayList; |
|||
import java.util.Collections; |
|||
import java.util.HashMap; |
|||
import java.util.List; |
|||
import java.util.Map; |
|||
import java.util.concurrent.ConcurrentHashMap; |
|||
import java.util.concurrent.ConcurrentMap; |
|||
import java.util.regex.Matcher; |
|||
import java.util.regex.Pattern; |
|||
|
|||
/** |
|||
* HTML过滤器,用于去除XSS漏洞隐患。 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
public final class HTMLFilter |
|||
{ |
|||
/** |
|||
* regex flag union representing /si modifiers in php |
|||
**/ |
|||
private static final int REGEX_FLAGS_SI = Pattern.CASE_INSENSITIVE | Pattern.DOTALL; |
|||
private static final Pattern P_COMMENTS = Pattern.compile("<!--(.*?)-->", Pattern.DOTALL); |
|||
private static final Pattern P_COMMENT = Pattern.compile("^!--(.*)--$", REGEX_FLAGS_SI); |
|||
private static final Pattern P_TAGS = Pattern.compile("<(.*?)>", Pattern.DOTALL); |
|||
private static final Pattern P_END_TAG = Pattern.compile("^/([a-z0-9]+)", REGEX_FLAGS_SI); |
|||
private static final Pattern P_START_TAG = Pattern.compile("^([a-z0-9]+)(.*?)(/?)$", REGEX_FLAGS_SI); |
|||
private static final Pattern P_QUOTED_ATTRIBUTES = Pattern.compile("([a-z0-9]+)=([\"'])(.*?)\\2", REGEX_FLAGS_SI); |
|||
private static final Pattern P_UNQUOTED_ATTRIBUTES = Pattern.compile("([a-z0-9]+)(=)([^\"\\s']+)", REGEX_FLAGS_SI); |
|||
private static final Pattern P_PROTOCOL = Pattern.compile("^([^:]+):", REGEX_FLAGS_SI); |
|||
private static final Pattern P_ENTITY = Pattern.compile("&#(\\d+);?"); |
|||
private static final Pattern P_ENTITY_UNICODE = Pattern.compile("&#x([0-9a-f]+);?"); |
|||
private static final Pattern P_ENCODE = Pattern.compile("%([0-9a-f]{2});?"); |
|||
private static final Pattern P_VALID_ENTITIES = Pattern.compile("&([^&;]*)(?=(;|&|$))"); |
|||
private static final Pattern P_VALID_QUOTES = Pattern.compile("(>|^)([^<]+?)(<|$)", Pattern.DOTALL); |
|||
private static final Pattern P_END_ARROW = Pattern.compile("^>"); |
|||
private static final Pattern P_BODY_TO_END = Pattern.compile("<([^>]*?)(?=<|$)"); |
|||
private static final Pattern P_XML_CONTENT = Pattern.compile("(^|>)([^<]*?)(?=>)"); |
|||
private static final Pattern P_STRAY_LEFT_ARROW = Pattern.compile("<([^>]*?)(?=<|$)"); |
|||
private static final Pattern P_STRAY_RIGHT_ARROW = Pattern.compile("(^|>)([^<]*?)(?=>)"); |
|||
private static final Pattern P_AMP = Pattern.compile("&"); |
|||
private static final Pattern P_QUOTE = Pattern.compile("\""); |
|||
private static final Pattern P_LEFT_ARROW = Pattern.compile("<"); |
|||
private static final Pattern P_RIGHT_ARROW = Pattern.compile(">"); |
|||
private static final Pattern P_BOTH_ARROWS = Pattern.compile("<>"); |
|||
|
|||
// @xxx could grow large... maybe use sesat's ReferenceMap
|
|||
private static final ConcurrentMap<String, Pattern> P_REMOVE_PAIR_BLANKS = new ConcurrentHashMap<>(); |
|||
private static final ConcurrentMap<String, Pattern> P_REMOVE_SELF_BLANKS = new ConcurrentHashMap<>(); |
|||
|
|||
/** |
|||
* set of allowed html elements, along with allowed attributes for each element |
|||
**/ |
|||
private final Map<String, List<String>> vAllowed; |
|||
/** |
|||
* counts of open tags for each (allowable) html element |
|||
**/ |
|||
private final Map<String, Integer> vTagCounts = new HashMap<>(); |
|||
|
|||
/** |
|||
* html elements which must always be self-closing (e.g. "<img />") |
|||
**/ |
|||
private final String[] vSelfClosingTags; |
|||
/** |
|||
* html elements which must always have separate opening and closing tags (e.g. "<b></b>") |
|||
**/ |
|||
private final String[] vNeedClosingTags; |
|||
/** |
|||
* set of disallowed html elements |
|||
**/ |
|||
private final String[] vDisallowed; |
|||
/** |
|||
* attributes which should be checked for valid protocols |
|||
**/ |
|||
private final String[] vProtocolAtts; |
|||
/** |
|||
* allowed protocols |
|||
**/ |
|||
private final String[] vAllowedProtocols; |
|||
/** |
|||
* tags which should be removed if they contain no content (e.g. "<b></b>" or "<b />") |
|||
**/ |
|||
private final String[] vRemoveBlanks; |
|||
/** |
|||
* entities allowed within html markup |
|||
**/ |
|||
private final String[] vAllowedEntities; |
|||
/** |
|||
* flag determining whether comments are allowed in input String. |
|||
*/ |
|||
private final boolean stripComment; |
|||
private final boolean encodeQuotes; |
|||
/** |
|||
* flag determining whether to try to make tags when presented with "unbalanced" angle brackets (e.g. "<b text </b>" |
|||
* becomes "<b> text </b>"). If set to false, unbalanced angle brackets will be html escaped. |
|||
*/ |
|||
private final boolean alwaysMakeTags; |
|||
|
|||
/** |
|||
* Default constructor. |
|||
*/ |
|||
public HTMLFilter() |
|||
{ |
|||
vAllowed = new HashMap<>(); |
|||
|
|||
final ArrayList<String> a_atts = new ArrayList<>(); |
|||
a_atts.add("href"); |
|||
a_atts.add("target"); |
|||
vAllowed.put("a", a_atts); |
|||
|
|||
final ArrayList<String> img_atts = new ArrayList<>(); |
|||
img_atts.add("src"); |
|||
img_atts.add("width"); |
|||
img_atts.add("height"); |
|||
img_atts.add("alt"); |
|||
vAllowed.put("img", img_atts); |
|||
|
|||
final ArrayList<String> no_atts = new ArrayList<>(); |
|||
vAllowed.put("b", no_atts); |
|||
vAllowed.put("strong", no_atts); |
|||
vAllowed.put("i", no_atts); |
|||
vAllowed.put("em", no_atts); |
|||
|
|||
vSelfClosingTags = new String[] { "img" }; |
|||
vNeedClosingTags = new String[] { "a", "b", "strong", "i", "em" }; |
|||
vDisallowed = new String[] {}; |
|||
vAllowedProtocols = new String[] { "http", "mailto", "https" }; // no ftp.
|
|||
vProtocolAtts = new String[] { "src", "href" }; |
|||
vRemoveBlanks = new String[] { "a", "b", "strong", "i", "em" }; |
|||
vAllowedEntities = new String[] { "amp", "gt", "lt", "quot" }; |
|||
stripComment = true; |
|||
encodeQuotes = true; |
|||
alwaysMakeTags = false; |
|||
} |
|||
|
|||
/** |
|||
* Map-parameter configurable constructor. |
|||
* |
|||
* @param conf map containing configuration. keys match field names. |
|||
*/ |
|||
@SuppressWarnings("unchecked") |
|||
public HTMLFilter(final Map<String, Object> conf) |
|||
{ |
|||
|
|||
assert conf.containsKey("vAllowed") : "configuration requires vAllowed"; |
|||
assert conf.containsKey("vSelfClosingTags") : "configuration requires vSelfClosingTags"; |
|||
assert conf.containsKey("vNeedClosingTags") : "configuration requires vNeedClosingTags"; |
|||
assert conf.containsKey("vDisallowed") : "configuration requires vDisallowed"; |
|||
assert conf.containsKey("vAllowedProtocols") : "configuration requires vAllowedProtocols"; |
|||
assert conf.containsKey("vProtocolAtts") : "configuration requires vProtocolAtts"; |
|||
assert conf.containsKey("vRemoveBlanks") : "configuration requires vRemoveBlanks"; |
|||
assert conf.containsKey("vAllowedEntities") : "configuration requires vAllowedEntities"; |
|||
|
|||
vAllowed = Collections.unmodifiableMap((HashMap<String, List<String>>) conf.get("vAllowed")); |
|||
vSelfClosingTags = (String[]) conf.get("vSelfClosingTags"); |
|||
vNeedClosingTags = (String[]) conf.get("vNeedClosingTags"); |
|||
vDisallowed = (String[]) conf.get("vDisallowed"); |
|||
vAllowedProtocols = (String[]) conf.get("vAllowedProtocols"); |
|||
vProtocolAtts = (String[]) conf.get("vProtocolAtts"); |
|||
vRemoveBlanks = (String[]) conf.get("vRemoveBlanks"); |
|||
vAllowedEntities = (String[]) conf.get("vAllowedEntities"); |
|||
stripComment = conf.containsKey("stripComment") ? (Boolean) conf.get("stripComment") : true; |
|||
encodeQuotes = conf.containsKey("encodeQuotes") ? (Boolean) conf.get("encodeQuotes") : true; |
|||
alwaysMakeTags = conf.containsKey("alwaysMakeTags") ? (Boolean) conf.get("alwaysMakeTags") : true; |
|||
} |
|||
|
|||
private void reset() |
|||
{ |
|||
vTagCounts.clear(); |
|||
} |
|||
|
|||
// ---------------------------------------------------------------
|
|||
// my versions of some PHP library functions
|
|||
public static String chr(final int decimal) |
|||
{ |
|||
return String.valueOf((char) decimal); |
|||
} |
|||
|
|||
public static String htmlSpecialChars(final String s) |
|||
{ |
|||
String result = s; |
|||
result = regexReplace(P_AMP, "&", result); |
|||
result = regexReplace(P_QUOTE, """, result); |
|||
result = regexReplace(P_LEFT_ARROW, "<", result); |
|||
result = regexReplace(P_RIGHT_ARROW, ">", result); |
|||
return result; |
|||
} |
|||
|
|||
// ---------------------------------------------------------------
|
|||
|
|||
/** |
|||
* given a user submitted input String, filter out any invalid or restricted html. |
|||
* |
|||
* @param input text (i.e. submitted by a user) than may contain html |
|||
* @return "clean" version of input, with only valid, whitelisted html elements allowed |
|||
*/ |
|||
public String filter(final String input) |
|||
{ |
|||
reset(); |
|||
String s = input; |
|||
|
|||
s = escapeComments(s); |
|||
|
|||
s = balanceHTML(s); |
|||
|
|||
s = checkTags(s); |
|||
|
|||
s = processRemoveBlanks(s); |
|||
|
|||
// s = validateEntities(s);
|
|||
|
|||
return s; |
|||
} |
|||
|
|||
public boolean isAlwaysMakeTags() |
|||
{ |
|||
return alwaysMakeTags; |
|||
} |
|||
|
|||
public boolean isStripComments() |
|||
{ |
|||
return stripComment; |
|||
} |
|||
|
|||
private String escapeComments(final String s) |
|||
{ |
|||
final Matcher m = P_COMMENTS.matcher(s); |
|||
final StringBuffer buf = new StringBuffer(); |
|||
if (m.find()) |
|||
{ |
|||
final String match = m.group(1); // (.*?)
|
|||
m.appendReplacement(buf, Matcher.quoteReplacement("<!--" + htmlSpecialChars(match) + "-->")); |
|||
} |
|||
m.appendTail(buf); |
|||
|
|||
return buf.toString(); |
|||
} |
|||
|
|||
private String balanceHTML(String s) |
|||
{ |
|||
if (alwaysMakeTags) |
|||
{ |
|||
//
|
|||
// try and form html
|
|||
//
|
|||
s = regexReplace(P_END_ARROW, "", s); |
|||
// 不追加结束标签
|
|||
s = regexReplace(P_BODY_TO_END, "<$1>", s); |
|||
s = regexReplace(P_XML_CONTENT, "$1<$2", s); |
|||
|
|||
} |
|||
else |
|||
{ |
|||
//
|
|||
// escape stray brackets
|
|||
//
|
|||
s = regexReplace(P_STRAY_LEFT_ARROW, "<$1", s); |
|||
s = regexReplace(P_STRAY_RIGHT_ARROW, "$1$2><", s); |
|||
|
|||
//
|
|||
// the last regexp causes '<>' entities to appear
|
|||
// (we need to do a lookahead assertion so that the last bracket can
|
|||
// be used in the next pass of the regexp)
|
|||
//
|
|||
s = regexReplace(P_BOTH_ARROWS, "", s); |
|||
} |
|||
|
|||
return s; |
|||
} |
|||
|
|||
private String checkTags(String s) |
|||
{ |
|||
Matcher m = P_TAGS.matcher(s); |
|||
|
|||
final StringBuffer buf = new StringBuffer(); |
|||
while (m.find()) |
|||
{ |
|||
String replaceStr = m.group(1); |
|||
replaceStr = processTag(replaceStr); |
|||
m.appendReplacement(buf, Matcher.quoteReplacement(replaceStr)); |
|||
} |
|||
m.appendTail(buf); |
|||
|
|||
// these get tallied in processTag
|
|||
// (remember to reset before subsequent calls to filter method)
|
|||
final StringBuilder sBuilder = new StringBuilder(buf.toString()); |
|||
for (String key : vTagCounts.keySet()) |
|||
{ |
|||
for (int ii = 0; ii < vTagCounts.get(key); ii++) |
|||
{ |
|||
sBuilder.append("</").append(key).append(">"); |
|||
} |
|||
} |
|||
s = sBuilder.toString(); |
|||
|
|||
return s; |
|||
} |
|||
|
|||
private String processRemoveBlanks(final String s) |
|||
{ |
|||
String result = s; |
|||
for (String tag : vRemoveBlanks) |
|||
{ |
|||
if (!P_REMOVE_PAIR_BLANKS.containsKey(tag)) |
|||
{ |
|||
P_REMOVE_PAIR_BLANKS.putIfAbsent(tag, Pattern.compile("<" + tag + "(\\s[^>]*)?></" + tag + ">")); |
|||
} |
|||
result = regexReplace(P_REMOVE_PAIR_BLANKS.get(tag), "", result); |
|||
if (!P_REMOVE_SELF_BLANKS.containsKey(tag)) |
|||
{ |
|||
P_REMOVE_SELF_BLANKS.putIfAbsent(tag, Pattern.compile("<" + tag + "(\\s[^>]*)?/>")); |
|||
} |
|||
result = regexReplace(P_REMOVE_SELF_BLANKS.get(tag), "", result); |
|||
} |
|||
|
|||
return result; |
|||
} |
|||
|
|||
private static String regexReplace(final Pattern regex_pattern, final String replacement, final String s) |
|||
{ |
|||
Matcher m = regex_pattern.matcher(s); |
|||
return m.replaceAll(replacement); |
|||
} |
|||
|
|||
private String processTag(final String s) |
|||
{ |
|||
// ending tags
|
|||
Matcher m = P_END_TAG.matcher(s); |
|||
if (m.find()) |
|||
{ |
|||
final String name = m.group(1).toLowerCase(); |
|||
if (allowed(name)) |
|||
{ |
|||
if (false == inArray(name, vSelfClosingTags)) |
|||
{ |
|||
if (vTagCounts.containsKey(name)) |
|||
{ |
|||
vTagCounts.put(name, vTagCounts.get(name) - 1); |
|||
return "</" + name + ">"; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
// starting tags
|
|||
m = P_START_TAG.matcher(s); |
|||
if (m.find()) |
|||
{ |
|||
final String name = m.group(1).toLowerCase(); |
|||
final String body = m.group(2); |
|||
String ending = m.group(3); |
|||
|
|||
// debug( "in a starting tag, name='" + name + "'; body='" + body + "'; ending='" + ending + "'" );
|
|||
if (allowed(name)) |
|||
{ |
|||
final StringBuilder params = new StringBuilder(); |
|||
|
|||
final Matcher m2 = P_QUOTED_ATTRIBUTES.matcher(body); |
|||
final Matcher m3 = P_UNQUOTED_ATTRIBUTES.matcher(body); |
|||
final List<String> paramNames = new ArrayList<>(); |
|||
final List<String> paramValues = new ArrayList<>(); |
|||
while (m2.find()) |
|||
{ |
|||
paramNames.add(m2.group(1)); // ([a-z0-9]+)
|
|||
paramValues.add(m2.group(3)); // (.*?)
|
|||
} |
|||
while (m3.find()) |
|||
{ |
|||
paramNames.add(m3.group(1)); // ([a-z0-9]+)
|
|||
paramValues.add(m3.group(3)); // ([^\"\\s']+)
|
|||
} |
|||
|
|||
String paramName, paramValue; |
|||
for (int ii = 0; ii < paramNames.size(); ii++) |
|||
{ |
|||
paramName = paramNames.get(ii).toLowerCase(); |
|||
paramValue = paramValues.get(ii); |
|||
|
|||
// debug( "paramName='" + paramName + "'" );
|
|||
// debug( "paramValue='" + paramValue + "'" );
|
|||
// debug( "allowed? " + vAllowed.get( name ).contains( paramName ) );
|
|||
|
|||
if (allowedAttribute(name, paramName)) |
|||
{ |
|||
if (inArray(paramName, vProtocolAtts)) |
|||
{ |
|||
paramValue = processParamProtocol(paramValue); |
|||
} |
|||
params.append(' ').append(paramName).append("=\\\"").append(paramValue).append("\""); |
|||
} |
|||
} |
|||
|
|||
if (inArray(name, vSelfClosingTags)) |
|||
{ |
|||
ending = " /"; |
|||
} |
|||
|
|||
if (inArray(name, vNeedClosingTags)) |
|||
{ |
|||
ending = ""; |
|||
} |
|||
|
|||
if (ending == null || ending.length() < 1) |
|||
{ |
|||
if (vTagCounts.containsKey(name)) |
|||
{ |
|||
vTagCounts.put(name, vTagCounts.get(name) + 1); |
|||
} |
|||
else |
|||
{ |
|||
vTagCounts.put(name, 1); |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
ending = " /"; |
|||
} |
|||
return "<" + name + params + ending + ">"; |
|||
} |
|||
else |
|||
{ |
|||
return ""; |
|||
} |
|||
} |
|||
|
|||
// comments
|
|||
m = P_COMMENT.matcher(s); |
|||
if (!stripComment && m.find()) |
|||
{ |
|||
return "<" + m.group() + ">"; |
|||
} |
|||
|
|||
return ""; |
|||
} |
|||
|
|||
private String processParamProtocol(String s) |
|||
{ |
|||
s = decodeEntities(s); |
|||
final Matcher m = P_PROTOCOL.matcher(s); |
|||
if (m.find()) |
|||
{ |
|||
final String protocol = m.group(1); |
|||
if (!inArray(protocol, vAllowedProtocols)) |
|||
{ |
|||
// bad protocol, turn into local anchor link instead
|
|||
s = "#" + s.substring(protocol.length() + 1); |
|||
if (s.startsWith("#//")) |
|||
{ |
|||
s = "#" + s.substring(3); |
|||
} |
|||
} |
|||
} |
|||
|
|||
return s; |
|||
} |
|||
|
|||
private String decodeEntities(String s) |
|||
{ |
|||
StringBuffer buf = new StringBuffer(); |
|||
|
|||
Matcher m = P_ENTITY.matcher(s); |
|||
while (m.find()) |
|||
{ |
|||
final String match = m.group(1); |
|||
final int decimal = Integer.decode(match).intValue(); |
|||
m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal))); |
|||
} |
|||
m.appendTail(buf); |
|||
s = buf.toString(); |
|||
|
|||
buf = new StringBuffer(); |
|||
m = P_ENTITY_UNICODE.matcher(s); |
|||
while (m.find()) |
|||
{ |
|||
final String match = m.group(1); |
|||
final int decimal = Integer.valueOf(match, 16).intValue(); |
|||
m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal))); |
|||
} |
|||
m.appendTail(buf); |
|||
s = buf.toString(); |
|||
|
|||
buf = new StringBuffer(); |
|||
m = P_ENCODE.matcher(s); |
|||
while (m.find()) |
|||
{ |
|||
final String match = m.group(1); |
|||
final int decimal = Integer.valueOf(match, 16).intValue(); |
|||
m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal))); |
|||
} |
|||
m.appendTail(buf); |
|||
s = buf.toString(); |
|||
|
|||
s = validateEntities(s); |
|||
return s; |
|||
} |
|||
|
|||
private String validateEntities(final String s) |
|||
{ |
|||
StringBuffer buf = new StringBuffer(); |
|||
|
|||
// validate entities throughout the string
|
|||
Matcher m = P_VALID_ENTITIES.matcher(s); |
|||
while (m.find()) |
|||
{ |
|||
final String one = m.group(1); // ([^&;]*)
|
|||
final String two = m.group(2); // (?=(;|&|$))
|
|||
m.appendReplacement(buf, Matcher.quoteReplacement(checkEntity(one, two))); |
|||
} |
|||
m.appendTail(buf); |
|||
|
|||
return encodeQuotes(buf.toString()); |
|||
} |
|||
|
|||
private String encodeQuotes(final String s) |
|||
{ |
|||
if (encodeQuotes) |
|||
{ |
|||
StringBuffer buf = new StringBuffer(); |
|||
Matcher m = P_VALID_QUOTES.matcher(s); |
|||
while (m.find()) |
|||
{ |
|||
final String one = m.group(1); // (>|^)
|
|||
final String two = m.group(2); // ([^<]+?)
|
|||
final String three = m.group(3); // (<|$)
|
|||
// 不替换双引号为",防止json格式无效 regexReplace(P_QUOTE, """, two)
|
|||
m.appendReplacement(buf, Matcher.quoteReplacement(one + two + three)); |
|||
} |
|||
m.appendTail(buf); |
|||
return buf.toString(); |
|||
} |
|||
else |
|||
{ |
|||
return s; |
|||
} |
|||
} |
|||
|
|||
private String checkEntity(final String preamble, final String term) |
|||
{ |
|||
|
|||
return ";".equals(term) && isValidEntity(preamble) ? '&' + preamble : "&" + preamble; |
|||
} |
|||
|
|||
private boolean isValidEntity(final String entity) |
|||
{ |
|||
return inArray(entity, vAllowedEntities); |
|||
} |
|||
|
|||
private static boolean inArray(final String s, final String[] array) |
|||
{ |
|||
for (String item : array) |
|||
{ |
|||
if (item != null && item.equals(s)) |
|||
{ |
|||
return true; |
|||
} |
|||
} |
|||
return false; |
|||
} |
|||
|
|||
private boolean allowed(final String name) |
|||
{ |
|||
return (vAllowed.isEmpty() || vAllowed.containsKey(name)) && !inArray(name, vDisallowed); |
|||
} |
|||
|
|||
private boolean allowedAttribute(final String name, final String paramName) |
|||
{ |
|||
return allowed(name) && (vAllowed.isEmpty() || vAllowed.get(name).contains(paramName)); |
|||
} |
|||
} |
|||
@ -0,0 +1,265 @@ |
|||
package com.bnyer.common.core.utils.ip; |
|||
|
|||
import java.net.InetAddress; |
|||
import java.net.UnknownHostException; |
|||
import javax.servlet.http.HttpServletRequest; |
|||
|
|||
import com.bnyer.common.core.utils.StringUtils; |
|||
|
|||
/** |
|||
* 获取IP方法 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
public class IpUtils |
|||
{ |
|||
/** |
|||
* 获取客户端IP |
|||
* |
|||
* @param request 请求对象 |
|||
* @return IP地址 |
|||
*/ |
|||
public static String getIpAddr(HttpServletRequest request) |
|||
{ |
|||
if (request == null) |
|||
{ |
|||
return "unknown"; |
|||
} |
|||
String ip = request.getHeader("x-forwarded-for"); |
|||
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) |
|||
{ |
|||
ip = request.getHeader("Proxy-Client-IP"); |
|||
} |
|||
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) |
|||
{ |
|||
ip = request.getHeader("X-Forwarded-For"); |
|||
} |
|||
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) |
|||
{ |
|||
ip = request.getHeader("WL-Proxy-Client-IP"); |
|||
} |
|||
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) |
|||
{ |
|||
ip = request.getHeader("X-Real-IP"); |
|||
} |
|||
|
|||
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) |
|||
{ |
|||
ip = request.getRemoteAddr(); |
|||
} |
|||
|
|||
return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : getMultistageReverseProxyIp(ip); |
|||
} |
|||
|
|||
/** |
|||
* 检查是否为内部IP地址 |
|||
* |
|||
* @param ip IP地址 |
|||
* @return 结果 |
|||
*/ |
|||
public static boolean internalIp(String ip) |
|||
{ |
|||
byte[] addr = textToNumericFormatV4(ip); |
|||
return internalIp(addr) || "127.0.0.1".equals(ip); |
|||
} |
|||
|
|||
/** |
|||
* 检查是否为内部IP地址 |
|||
* |
|||
* @param addr byte地址 |
|||
* @return 结果 |
|||
*/ |
|||
private static boolean internalIp(byte[] addr) |
|||
{ |
|||
if (StringUtils.isNull(addr) || addr.length < 2) |
|||
{ |
|||
return true; |
|||
} |
|||
final byte b0 = addr[0]; |
|||
final byte b1 = addr[1]; |
|||
// 10.x.x.x/8
|
|||
final byte SECTION_1 = 0x0A; |
|||
// 172.16.x.x/12
|
|||
final byte SECTION_2 = (byte) 0xAC; |
|||
final byte SECTION_3 = (byte) 0x10; |
|||
final byte SECTION_4 = (byte) 0x1F; |
|||
// 192.168.x.x/16
|
|||
final byte SECTION_5 = (byte) 0xC0; |
|||
final byte SECTION_6 = (byte) 0xA8; |
|||
switch (b0) |
|||
{ |
|||
case SECTION_1: |
|||
return true; |
|||
case SECTION_2: |
|||
if (b1 >= SECTION_3 && b1 <= SECTION_4) |
|||
{ |
|||
return true; |
|||
} |
|||
case SECTION_5: |
|||
switch (b1) |
|||
{ |
|||
case SECTION_6: |
|||
return true; |
|||
} |
|||
default: |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 将IPv4地址转换成字节 |
|||
* |
|||
* @param text IPv4地址 |
|||
* @return byte 字节 |
|||
*/ |
|||
public static byte[] textToNumericFormatV4(String text) |
|||
{ |
|||
if (text.length() == 0) |
|||
{ |
|||
return null; |
|||
} |
|||
|
|||
byte[] bytes = new byte[4]; |
|||
String[] elements = text.split("\\.", -1); |
|||
try |
|||
{ |
|||
long l; |
|||
int i; |
|||
switch (elements.length) |
|||
{ |
|||
case 1: |
|||
l = Long.parseLong(elements[0]); |
|||
if ((l < 0L) || (l > 4294967295L)) |
|||
{ |
|||
return null; |
|||
} |
|||
bytes[0] = (byte) (int) (l >> 24 & 0xFF); |
|||
bytes[1] = (byte) (int) ((l & 0xFFFFFF) >> 16 & 0xFF); |
|||
bytes[2] = (byte) (int) ((l & 0xFFFF) >> 8 & 0xFF); |
|||
bytes[3] = (byte) (int) (l & 0xFF); |
|||
break; |
|||
case 2: |
|||
l = Integer.parseInt(elements[0]); |
|||
if ((l < 0L) || (l > 255L)) |
|||
{ |
|||
return null; |
|||
} |
|||
bytes[0] = (byte) (int) (l & 0xFF); |
|||
l = Integer.parseInt(elements[1]); |
|||
if ((l < 0L) || (l > 16777215L)) |
|||
{ |
|||
return null; |
|||
} |
|||
bytes[1] = (byte) (int) (l >> 16 & 0xFF); |
|||
bytes[2] = (byte) (int) ((l & 0xFFFF) >> 8 & 0xFF); |
|||
bytes[3] = (byte) (int) (l & 0xFF); |
|||
break; |
|||
case 3: |
|||
for (i = 0; i < 2; ++i) |
|||
{ |
|||
l = Integer.parseInt(elements[i]); |
|||
if ((l < 0L) || (l > 255L)) |
|||
{ |
|||
return null; |
|||
} |
|||
bytes[i] = (byte) (int) (l & 0xFF); |
|||
} |
|||
l = Integer.parseInt(elements[2]); |
|||
if ((l < 0L) || (l > 65535L)) |
|||
{ |
|||
return null; |
|||
} |
|||
bytes[2] = (byte) (int) (l >> 8 & 0xFF); |
|||
bytes[3] = (byte) (int) (l & 0xFF); |
|||
break; |
|||
case 4: |
|||
for (i = 0; i < 4; ++i) |
|||
{ |
|||
l = Integer.parseInt(elements[i]); |
|||
if ((l < 0L) || (l > 255L)) |
|||
{ |
|||
return null; |
|||
} |
|||
bytes[i] = (byte) (int) (l & 0xFF); |
|||
} |
|||
break; |
|||
default: |
|||
return null; |
|||
} |
|||
} |
|||
catch (NumberFormatException e) |
|||
{ |
|||
return null; |
|||
} |
|||
return bytes; |
|||
} |
|||
|
|||
/** |
|||
* 获取IP地址 |
|||
* |
|||
* @return 本地IP地址 |
|||
*/ |
|||
public static String getHostIp() |
|||
{ |
|||
try |
|||
{ |
|||
return InetAddress.getLocalHost().getHostAddress(); |
|||
} |
|||
catch (UnknownHostException e) |
|||
{ |
|||
} |
|||
return "127.0.0.1"; |
|||
} |
|||
|
|||
/** |
|||
* 获取主机名 |
|||
* |
|||
* @return 本地主机名 |
|||
*/ |
|||
public static String getHostName() |
|||
{ |
|||
try |
|||
{ |
|||
return InetAddress.getLocalHost().getHostName(); |
|||
} |
|||
catch (UnknownHostException e) |
|||
{ |
|||
} |
|||
return "未知"; |
|||
} |
|||
|
|||
/** |
|||
* 从多级反向代理中获得第一个非unknown IP地址 |
|||
* |
|||
* @param ip 获得的IP地址 |
|||
* @return 第一个非unknown IP地址 |
|||
*/ |
|||
public static String getMultistageReverseProxyIp(String ip) |
|||
{ |
|||
// 多级反向代理检测
|
|||
if (ip != null && ip.indexOf(",") > 0) |
|||
{ |
|||
final String[] ips = ip.trim().split(","); |
|||
for (String subIp : ips) |
|||
{ |
|||
if (false == isUnknown(subIp)) |
|||
{ |
|||
ip = subIp; |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
return ip; |
|||
} |
|||
|
|||
/** |
|||
* 检测给定字符串是否为未知,多用于检测HTTP请求相关 |
|||
* |
|||
* @param checkString 被检测的字符串 |
|||
* @return 是否未知 |
|||
*/ |
|||
public static boolean isUnknown(String checkString) |
|||
{ |
|||
return StringUtils.isBlank(checkString) || "unknown".equalsIgnoreCase(checkString); |
|||
} |
|||
} |
|||
@ -0,0 +1,19 @@ |
|||
package com.bnyer.common.core.utils.poi; |
|||
|
|||
/** |
|||
* Excel数据格式处理适配器 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
public interface ExcelHandlerAdapter |
|||
{ |
|||
/** |
|||
* 格式化 |
|||
* |
|||
* @param value 单元格数据值 |
|||
* @param args excel注解args参数组 |
|||
* |
|||
* @return 处理后的值 |
|||
*/ |
|||
Object format(Object value, String[] args); |
|||
} |
|||
File diff suppressed because it is too large
@ -0,0 +1,411 @@ |
|||
package com.bnyer.common.core.utils.reflect; |
|||
|
|||
import java.lang.reflect.Field; |
|||
import java.lang.reflect.InvocationTargetException; |
|||
import java.lang.reflect.Method; |
|||
import java.lang.reflect.Modifier; |
|||
import java.lang.reflect.ParameterizedType; |
|||
import java.lang.reflect.Type; |
|||
import java.util.Date; |
|||
|
|||
import com.bnyer.common.core.utils.DateUtils; |
|||
import org.apache.commons.lang3.StringUtils; |
|||
import org.apache.commons.lang3.Validate; |
|||
import org.apache.poi.ss.usermodel.DateUtil; |
|||
import org.slf4j.Logger; |
|||
import org.slf4j.LoggerFactory; |
|||
import com.bnyer.common.core.text.Convert; |
|||
|
|||
/** |
|||
* 反射工具类. 提供调用getter/setter方法, 访问私有变量, 调用私有方法, 获取泛型类型Class, 被AOP过的真实类等工具函数. |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
@SuppressWarnings("rawtypes") |
|||
public class ReflectUtils |
|||
{ |
|||
private static final String SETTER_PREFIX = "set"; |
|||
|
|||
private static final String GETTER_PREFIX = "get"; |
|||
|
|||
private static final String CGLIB_CLASS_SEPARATOR = "$$"; |
|||
|
|||
private static Logger logger = LoggerFactory.getLogger(ReflectUtils.class); |
|||
|
|||
/** |
|||
* 调用Getter方法. |
|||
* 支持多级,如:对象名.对象名.方法 |
|||
*/ |
|||
@SuppressWarnings("unchecked") |
|||
public static <E> E invokeGetter(Object obj, String propertyName) |
|||
{ |
|||
Object object = obj; |
|||
for (String name : StringUtils.split(propertyName, ".")) |
|||
{ |
|||
String getterMethodName = GETTER_PREFIX + StringUtils.capitalize(name); |
|||
object = invokeMethod(object, getterMethodName, new Class[] {}, new Object[] {}); |
|||
} |
|||
return (E) object; |
|||
} |
|||
|
|||
/** |
|||
* 调用Setter方法, 仅匹配方法名。 |
|||
* 支持多级,如:对象名.对象名.方法 |
|||
*/ |
|||
public static <E> void invokeSetter(Object obj, String propertyName, E value) |
|||
{ |
|||
Object object = obj; |
|||
String[] names = StringUtils.split(propertyName, "."); |
|||
for (int i = 0; i < names.length; i++) |
|||
{ |
|||
if (i < names.length - 1) |
|||
{ |
|||
String getterMethodName = GETTER_PREFIX + StringUtils.capitalize(names[i]); |
|||
object = invokeMethod(object, getterMethodName, new Class[] {}, new Object[] {}); |
|||
} |
|||
else |
|||
{ |
|||
String setterMethodName = SETTER_PREFIX + StringUtils.capitalize(names[i]); |
|||
invokeMethodByName(object, setterMethodName, new Object[] { value }); |
|||
} |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 直接读取对象属性值, 无视private/protected修饰符, 不经过getter函数. |
|||
*/ |
|||
@SuppressWarnings("unchecked") |
|||
public static <E> E getFieldValue(final Object obj, final String fieldName) |
|||
{ |
|||
Field field = getAccessibleField(obj, fieldName); |
|||
if (field == null) |
|||
{ |
|||
logger.debug("在 [" + obj.getClass() + "] 中,没有找到 [" + fieldName + "] 字段 "); |
|||
return null; |
|||
} |
|||
E result = null; |
|||
try |
|||
{ |
|||
result = (E) field.get(obj); |
|||
} |
|||
catch (IllegalAccessException e) |
|||
{ |
|||
logger.error("不可能抛出的异常{}", e.getMessage()); |
|||
} |
|||
return result; |
|||
} |
|||
|
|||
/** |
|||
* 直接设置对象属性值, 无视private/protected修饰符, 不经过setter函数. |
|||
*/ |
|||
public static <E> void setFieldValue(final Object obj, final String fieldName, final E value) |
|||
{ |
|||
Field field = getAccessibleField(obj, fieldName); |
|||
if (field == null) |
|||
{ |
|||
// throw new IllegalArgumentException("在 [" + obj.getClass() + "] 中,没有找到 [" + fieldName + "] 字段 ");
|
|||
logger.debug("在 [" + obj.getClass() + "] 中,没有找到 [" + fieldName + "] 字段 "); |
|||
return; |
|||
} |
|||
try |
|||
{ |
|||
field.set(obj, value); |
|||
} |
|||
catch (IllegalAccessException e) |
|||
{ |
|||
logger.error("不可能抛出的异常: {}", e.getMessage()); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 直接调用对象方法, 无视private/protected修饰符. |
|||
* 用于一次性调用的情况,否则应使用getAccessibleMethod()函数获得Method后反复调用. |
|||
* 同时匹配方法名+参数类型, |
|||
*/ |
|||
@SuppressWarnings("unchecked") |
|||
public static <E> E invokeMethod(final Object obj, final String methodName, final Class<?>[] parameterTypes, |
|||
final Object[] args) |
|||
{ |
|||
if (obj == null || methodName == null) |
|||
{ |
|||
return null; |
|||
} |
|||
Method method = getAccessibleMethod(obj, methodName, parameterTypes); |
|||
if (method == null) |
|||
{ |
|||
logger.debug("在 [" + obj.getClass() + "] 中,没有找到 [" + methodName + "] 方法 "); |
|||
return null; |
|||
} |
|||
try |
|||
{ |
|||
return (E) method.invoke(obj, args); |
|||
} |
|||
catch (Exception e) |
|||
{ |
|||
String msg = "method: " + method + ", obj: " + obj + ", args: " + args + ""; |
|||
throw convertReflectionExceptionToUnchecked(msg, e); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 直接调用对象方法, 无视private/protected修饰符, |
|||
* 用于一次性调用的情况,否则应使用getAccessibleMethodByName()函数获得Method后反复调用. |
|||
* 只匹配函数名,如果有多个同名函数调用第一个。 |
|||
*/ |
|||
@SuppressWarnings("unchecked") |
|||
public static <E> E invokeMethodByName(final Object obj, final String methodName, final Object[] args) |
|||
{ |
|||
Method method = getAccessibleMethodByName(obj, methodName, args.length); |
|||
if (method == null) |
|||
{ |
|||
// 如果为空不报错,直接返回空。
|
|||
logger.debug("在 [" + obj.getClass() + "] 中,没有找到 [" + methodName + "] 方法 "); |
|||
return null; |
|||
} |
|||
try |
|||
{ |
|||
// 类型转换(将参数数据类型转换为目标方法参数类型)
|
|||
Class<?>[] cs = method.getParameterTypes(); |
|||
for (int i = 0; i < cs.length; i++) |
|||
{ |
|||
if (args[i] != null && !args[i].getClass().equals(cs[i])) |
|||
{ |
|||
if (cs[i] == String.class) |
|||
{ |
|||
args[i] = Convert.toStr(args[i]); |
|||
if (StringUtils.endsWith((String) args[i], ".0")) |
|||
{ |
|||
args[i] = StringUtils.substringBefore((String) args[i], ".0"); |
|||
} |
|||
} |
|||
else if (cs[i] == Integer.class) |
|||
{ |
|||
args[i] = Convert.toInt(args[i]); |
|||
} |
|||
else if (cs[i] == Long.class) |
|||
{ |
|||
args[i] = Convert.toLong(args[i]); |
|||
} |
|||
else if (cs[i] == Double.class) |
|||
{ |
|||
args[i] = Convert.toDouble(args[i]); |
|||
} |
|||
else if (cs[i] == Float.class) |
|||
{ |
|||
args[i] = Convert.toFloat(args[i]); |
|||
} |
|||
else if (cs[i] == Date.class) |
|||
{ |
|||
if (args[i] instanceof String) |
|||
{ |
|||
args[i] = DateUtils.parseDate(args[i]); |
|||
} |
|||
else |
|||
{ |
|||
args[i] = DateUtil.getJavaDate((Double) args[i]); |
|||
} |
|||
} |
|||
else if (cs[i] == boolean.class || cs[i] == Boolean.class) |
|||
{ |
|||
args[i] = Convert.toBool(args[i]); |
|||
} |
|||
} |
|||
} |
|||
return (E) method.invoke(obj, args); |
|||
} |
|||
catch (Exception e) |
|||
{ |
|||
String msg = "method: " + method + ", obj: " + obj + ", args: " + args + ""; |
|||
throw convertReflectionExceptionToUnchecked(msg, e); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 循环向上转型, 获取对象的DeclaredField, 并强制设置为可访问. |
|||
* 如向上转型到Object仍无法找到, 返回null. |
|||
*/ |
|||
public static Field getAccessibleField(final Object obj, final String fieldName) |
|||
{ |
|||
// 为空不报错。直接返回 null
|
|||
if (obj == null) |
|||
{ |
|||
return null; |
|||
} |
|||
Validate.notBlank(fieldName, "fieldName can't be blank"); |
|||
for (Class<?> superClass = obj.getClass(); superClass != Object.class; superClass = superClass.getSuperclass()) |
|||
{ |
|||
try |
|||
{ |
|||
Field field = superClass.getDeclaredField(fieldName); |
|||
makeAccessible(field); |
|||
return field; |
|||
} |
|||
catch (NoSuchFieldException e) |
|||
{ |
|||
continue; |
|||
} |
|||
} |
|||
return null; |
|||
} |
|||
|
|||
/** |
|||
* 循环向上转型, 获取对象的DeclaredMethod,并强制设置为可访问. |
|||
* 如向上转型到Object仍无法找到, 返回null. |
|||
* 匹配函数名+参数类型。 |
|||
* 用于方法需要被多次调用的情况. 先使用本函数先取得Method,然后调用Method.invoke(Object obj, Object... args) |
|||
*/ |
|||
public static Method getAccessibleMethod(final Object obj, final String methodName, |
|||
final Class<?>... parameterTypes) |
|||
{ |
|||
// 为空不报错。直接返回 null
|
|||
if (obj == null) |
|||
{ |
|||
return null; |
|||
} |
|||
Validate.notBlank(methodName, "methodName can't be blank"); |
|||
for (Class<?> searchType = obj.getClass(); searchType != Object.class; searchType = searchType.getSuperclass()) |
|||
{ |
|||
try |
|||
{ |
|||
Method method = searchType.getDeclaredMethod(methodName, parameterTypes); |
|||
makeAccessible(method); |
|||
return method; |
|||
} |
|||
catch (NoSuchMethodException e) |
|||
{ |
|||
continue; |
|||
} |
|||
} |
|||
return null; |
|||
} |
|||
|
|||
/** |
|||
* 循环向上转型, 获取对象的DeclaredMethod,并强制设置为可访问. |
|||
* 如向上转型到Object仍无法找到, 返回null. |
|||
* 只匹配函数名。 |
|||
* 用于方法需要被多次调用的情况. 先使用本函数先取得Method,然后调用Method.invoke(Object obj, Object... args) |
|||
*/ |
|||
public static Method getAccessibleMethodByName(final Object obj, final String methodName, int argsNum) |
|||
{ |
|||
// 为空不报错。直接返回 null
|
|||
if (obj == null) |
|||
{ |
|||
return null; |
|||
} |
|||
Validate.notBlank(methodName, "methodName can't be blank"); |
|||
for (Class<?> searchType = obj.getClass(); searchType != Object.class; searchType = searchType.getSuperclass()) |
|||
{ |
|||
Method[] methods = searchType.getDeclaredMethods(); |
|||
for (Method method : methods) |
|||
{ |
|||
if (method.getName().equals(methodName) && method.getParameterTypes().length == argsNum) |
|||
{ |
|||
makeAccessible(method); |
|||
return method; |
|||
} |
|||
} |
|||
} |
|||
return null; |
|||
} |
|||
|
|||
/** |
|||
* 改变private/protected的方法为public,尽量不调用实际改动的语句,避免JDK的SecurityManager抱怨。 |
|||
*/ |
|||
public static void makeAccessible(Method method) |
|||
{ |
|||
if ((!Modifier.isPublic(method.getModifiers()) || !Modifier.isPublic(method.getDeclaringClass().getModifiers())) |
|||
&& !method.isAccessible()) |
|||
{ |
|||
method.setAccessible(true); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 改变private/protected的成员变量为public,尽量不调用实际改动的语句,避免JDK的SecurityManager抱怨。 |
|||
*/ |
|||
public static void makeAccessible(Field field) |
|||
{ |
|||
if ((!Modifier.isPublic(field.getModifiers()) || !Modifier.isPublic(field.getDeclaringClass().getModifiers()) |
|||
|| Modifier.isFinal(field.getModifiers())) && !field.isAccessible()) |
|||
{ |
|||
field.setAccessible(true); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 通过反射, 获得Class定义中声明的泛型参数的类型, 注意泛型必须定义在父类处 |
|||
* 如无法找到, 返回Object.class. |
|||
*/ |
|||
@SuppressWarnings("unchecked") |
|||
public static <T> Class<T> getClassGenricType(final Class clazz) |
|||
{ |
|||
return getClassGenricType(clazz, 0); |
|||
} |
|||
|
|||
/** |
|||
* 通过反射, 获得Class定义中声明的父类的泛型参数的类型. |
|||
* 如无法找到, 返回Object.class. |
|||
*/ |
|||
public static Class getClassGenricType(final Class clazz, final int index) |
|||
{ |
|||
Type genType = clazz.getGenericSuperclass(); |
|||
|
|||
if (!(genType instanceof ParameterizedType)) |
|||
{ |
|||
logger.debug(clazz.getSimpleName() + "'s superclass not ParameterizedType"); |
|||
return Object.class; |
|||
} |
|||
|
|||
Type[] params = ((ParameterizedType) genType).getActualTypeArguments(); |
|||
|
|||
if (index >= params.length || index < 0) |
|||
{ |
|||
logger.debug("Index: " + index + ", Size of " + clazz.getSimpleName() + "'s Parameterized Type: " |
|||
+ params.length); |
|||
return Object.class; |
|||
} |
|||
if (!(params[index] instanceof Class)) |
|||
{ |
|||
logger.debug(clazz.getSimpleName() + " not set the actual class on superclass generic parameter"); |
|||
return Object.class; |
|||
} |
|||
|
|||
return (Class) params[index]; |
|||
} |
|||
|
|||
public static Class<?> getUserClass(Object instance) |
|||
{ |
|||
if (instance == null) |
|||
{ |
|||
throw new RuntimeException("Instance must not be null"); |
|||
} |
|||
Class clazz = instance.getClass(); |
|||
if (clazz != null && clazz.getName().contains(CGLIB_CLASS_SEPARATOR)) |
|||
{ |
|||
Class<?> superClass = clazz.getSuperclass(); |
|||
if (superClass != null && !Object.class.equals(superClass)) |
|||
{ |
|||
return superClass; |
|||
} |
|||
} |
|||
return clazz; |
|||
|
|||
} |
|||
|
|||
/** |
|||
* 将反射时的checked exception转换为unchecked exception. |
|||
*/ |
|||
public static RuntimeException convertReflectionExceptionToUnchecked(String msg, Exception e) |
|||
{ |
|||
if (e instanceof IllegalAccessException || e instanceof IllegalArgumentException |
|||
|| e instanceof NoSuchMethodException) |
|||
{ |
|||
return new IllegalArgumentException(msg, e); |
|||
} |
|||
else if (e instanceof InvocationTargetException) |
|||
{ |
|||
return new RuntimeException(msg, ((InvocationTargetException) e).getTargetException()); |
|||
} |
|||
return new RuntimeException(msg, e); |
|||
} |
|||
} |
|||
@ -0,0 +1,291 @@ |
|||
package com.bnyer.common.core.utils.sign; |
|||
|
|||
/** |
|||
* Base64工具类 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
public final class Base64 |
|||
{ |
|||
static private final int BASELENGTH = 128; |
|||
static private final int LOOKUPLENGTH = 64; |
|||
static private final int TWENTYFOURBITGROUP = 24; |
|||
static private final int EIGHTBIT = 8; |
|||
static private final int SIXTEENBIT = 16; |
|||
static private final int FOURBYTE = 4; |
|||
static private final int SIGN = -128; |
|||
static private final char PAD = '='; |
|||
static final private byte[] base64Alphabet = new byte[BASELENGTH]; |
|||
static final private char[] lookUpBase64Alphabet = new char[LOOKUPLENGTH]; |
|||
|
|||
static |
|||
{ |
|||
for (int i = 0; i < BASELENGTH; ++i) |
|||
{ |
|||
base64Alphabet[i] = -1; |
|||
} |
|||
for (int i = 'Z'; i >= 'A'; i--) |
|||
{ |
|||
base64Alphabet[i] = (byte) (i - 'A'); |
|||
} |
|||
for (int i = 'z'; i >= 'a'; i--) |
|||
{ |
|||
base64Alphabet[i] = (byte) (i - 'a' + 26); |
|||
} |
|||
|
|||
for (int i = '9'; i >= '0'; i--) |
|||
{ |
|||
base64Alphabet[i] = (byte) (i - '0' + 52); |
|||
} |
|||
|
|||
base64Alphabet['+'] = 62; |
|||
base64Alphabet['/'] = 63; |
|||
|
|||
for (int i = 0; i <= 25; i++) |
|||
{ |
|||
lookUpBase64Alphabet[i] = (char) ('A' + i); |
|||
} |
|||
|
|||
for (int i = 26, j = 0; i <= 51; i++, j++) |
|||
{ |
|||
lookUpBase64Alphabet[i] = (char) ('a' + j); |
|||
} |
|||
|
|||
for (int i = 52, j = 0; i <= 61; i++, j++) |
|||
{ |
|||
lookUpBase64Alphabet[i] = (char) ('0' + j); |
|||
} |
|||
lookUpBase64Alphabet[62] = (char) '+'; |
|||
lookUpBase64Alphabet[63] = (char) '/'; |
|||
} |
|||
|
|||
private static boolean isWhiteSpace(char octect) |
|||
{ |
|||
return (octect == 0x20 || octect == 0xd || octect == 0xa || octect == 0x9); |
|||
} |
|||
|
|||
private static boolean isPad(char octect) |
|||
{ |
|||
return (octect == PAD); |
|||
} |
|||
|
|||
private static boolean isData(char octect) |
|||
{ |
|||
return (octect < BASELENGTH && base64Alphabet[octect] != -1); |
|||
} |
|||
|
|||
/** |
|||
* Encodes hex octects into Base64 |
|||
* |
|||
* @param binaryData Array containing binaryData |
|||
* @return Encoded Base64 array |
|||
*/ |
|||
public static String encode(byte[] binaryData) |
|||
{ |
|||
if (binaryData == null) |
|||
{ |
|||
return null; |
|||
} |
|||
|
|||
int lengthDataBits = binaryData.length * EIGHTBIT; |
|||
if (lengthDataBits == 0) |
|||
{ |
|||
return ""; |
|||
} |
|||
|
|||
int fewerThan24bits = lengthDataBits % TWENTYFOURBITGROUP; |
|||
int numberTriplets = lengthDataBits / TWENTYFOURBITGROUP; |
|||
int numberQuartet = fewerThan24bits != 0 ? numberTriplets + 1 : numberTriplets; |
|||
char encodedData[] = null; |
|||
|
|||
encodedData = new char[numberQuartet * 4]; |
|||
|
|||
byte k = 0, l = 0, b1 = 0, b2 = 0, b3 = 0; |
|||
|
|||
int encodedIndex = 0; |
|||
int dataIndex = 0; |
|||
|
|||
for (int i = 0; i < numberTriplets; i++) |
|||
{ |
|||
b1 = binaryData[dataIndex++]; |
|||
b2 = binaryData[dataIndex++]; |
|||
b3 = binaryData[dataIndex++]; |
|||
|
|||
l = (byte) (b2 & 0x0f); |
|||
k = (byte) (b1 & 0x03); |
|||
|
|||
byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0); |
|||
byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4) : (byte) ((b2) >> 4 ^ 0xf0); |
|||
byte val3 = ((b3 & SIGN) == 0) ? (byte) (b3 >> 6) : (byte) ((b3) >> 6 ^ 0xfc); |
|||
|
|||
encodedData[encodedIndex++] = lookUpBase64Alphabet[val1]; |
|||
encodedData[encodedIndex++] = lookUpBase64Alphabet[val2 | (k << 4)]; |
|||
encodedData[encodedIndex++] = lookUpBase64Alphabet[(l << 2) | val3]; |
|||
encodedData[encodedIndex++] = lookUpBase64Alphabet[b3 & 0x3f]; |
|||
} |
|||
|
|||
// form integral number of 6-bit groups
|
|||
if (fewerThan24bits == EIGHTBIT) |
|||
{ |
|||
b1 = binaryData[dataIndex]; |
|||
k = (byte) (b1 & 0x03); |
|||
byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0); |
|||
encodedData[encodedIndex++] = lookUpBase64Alphabet[val1]; |
|||
encodedData[encodedIndex++] = lookUpBase64Alphabet[k << 4]; |
|||
encodedData[encodedIndex++] = PAD; |
|||
encodedData[encodedIndex++] = PAD; |
|||
} |
|||
else if (fewerThan24bits == SIXTEENBIT) |
|||
{ |
|||
b1 = binaryData[dataIndex]; |
|||
b2 = binaryData[dataIndex + 1]; |
|||
l = (byte) (b2 & 0x0f); |
|||
k = (byte) (b1 & 0x03); |
|||
|
|||
byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0); |
|||
byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4) : (byte) ((b2) >> 4 ^ 0xf0); |
|||
|
|||
encodedData[encodedIndex++] = lookUpBase64Alphabet[val1]; |
|||
encodedData[encodedIndex++] = lookUpBase64Alphabet[val2 | (k << 4)]; |
|||
encodedData[encodedIndex++] = lookUpBase64Alphabet[l << 2]; |
|||
encodedData[encodedIndex++] = PAD; |
|||
} |
|||
return new String(encodedData); |
|||
} |
|||
|
|||
/** |
|||
* Decodes Base64 data into octects |
|||
* |
|||
* @param encoded string containing Base64 data |
|||
* @return Array containind decoded data. |
|||
*/ |
|||
public static byte[] decode(String encoded) |
|||
{ |
|||
if (encoded == null) |
|||
{ |
|||
return null; |
|||
} |
|||
|
|||
char[] base64Data = encoded.toCharArray(); |
|||
// remove white spaces
|
|||
int len = removeWhiteSpace(base64Data); |
|||
|
|||
if (len % FOURBYTE != 0) |
|||
{ |
|||
return null;// should be divisible by four
|
|||
} |
|||
|
|||
int numberQuadruple = (len / FOURBYTE); |
|||
|
|||
if (numberQuadruple == 0) |
|||
{ |
|||
return new byte[0]; |
|||
} |
|||
|
|||
byte decodedData[] = null; |
|||
byte b1 = 0, b2 = 0, b3 = 0, b4 = 0; |
|||
char d1 = 0, d2 = 0, d3 = 0, d4 = 0; |
|||
|
|||
int i = 0; |
|||
int encodedIndex = 0; |
|||
int dataIndex = 0; |
|||
decodedData = new byte[(numberQuadruple) * 3]; |
|||
|
|||
for (; i < numberQuadruple - 1; i++) |
|||
{ |
|||
|
|||
if (!isData((d1 = base64Data[dataIndex++])) || !isData((d2 = base64Data[dataIndex++])) |
|||
|| !isData((d3 = base64Data[dataIndex++])) || !isData((d4 = base64Data[dataIndex++]))) |
|||
{ |
|||
return null; |
|||
} // if found "no data" just return null
|
|||
|
|||
b1 = base64Alphabet[d1]; |
|||
b2 = base64Alphabet[d2]; |
|||
b3 = base64Alphabet[d3]; |
|||
b4 = base64Alphabet[d4]; |
|||
|
|||
decodedData[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4); |
|||
decodedData[encodedIndex++] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf)); |
|||
decodedData[encodedIndex++] = (byte) (b3 << 6 | b4); |
|||
} |
|||
|
|||
if (!isData((d1 = base64Data[dataIndex++])) || !isData((d2 = base64Data[dataIndex++]))) |
|||
{ |
|||
return null;// if found "no data" just return null
|
|||
} |
|||
|
|||
b1 = base64Alphabet[d1]; |
|||
b2 = base64Alphabet[d2]; |
|||
|
|||
d3 = base64Data[dataIndex++]; |
|||
d4 = base64Data[dataIndex++]; |
|||
if (!isData((d3)) || !isData((d4))) |
|||
{// Check if they are PAD characters
|
|||
if (isPad(d3) && isPad(d4)) |
|||
{ |
|||
if ((b2 & 0xf) != 0)// last 4 bits should be zero
|
|||
{ |
|||
return null; |
|||
} |
|||
byte[] tmp = new byte[i * 3 + 1]; |
|||
System.arraycopy(decodedData, 0, tmp, 0, i * 3); |
|||
tmp[encodedIndex] = (byte) (b1 << 2 | b2 >> 4); |
|||
return tmp; |
|||
} |
|||
else if (!isPad(d3) && isPad(d4)) |
|||
{ |
|||
b3 = base64Alphabet[d3]; |
|||
if ((b3 & 0x3) != 0)// last 2 bits should be zero
|
|||
{ |
|||
return null; |
|||
} |
|||
byte[] tmp = new byte[i * 3 + 2]; |
|||
System.arraycopy(decodedData, 0, tmp, 0, i * 3); |
|||
tmp[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4); |
|||
tmp[encodedIndex] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf)); |
|||
return tmp; |
|||
} |
|||
else |
|||
{ |
|||
return null; |
|||
} |
|||
} |
|||
else |
|||
{ // No PAD e.g 3cQl
|
|||
b3 = base64Alphabet[d3]; |
|||
b4 = base64Alphabet[d4]; |
|||
decodedData[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4); |
|||
decodedData[encodedIndex++] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf)); |
|||
decodedData[encodedIndex++] = (byte) (b3 << 6 | b4); |
|||
|
|||
} |
|||
return decodedData; |
|||
} |
|||
|
|||
/** |
|||
* remove WhiteSpace from MIME containing encoded Base64 data. |
|||
* |
|||
* @param data the byte array of base64 data (with WS) |
|||
* @return the new length |
|||
*/ |
|||
private static int removeWhiteSpace(char[] data) |
|||
{ |
|||
if (data == null) |
|||
{ |
|||
return 0; |
|||
} |
|||
|
|||
// count characters that's not whitespace
|
|||
int newSize = 0; |
|||
int len = data.length; |
|||
for (int i = 0; i < len; i++) |
|||
{ |
|||
if (!isWhiteSpace(data[i])) |
|||
{ |
|||
data[newSize++] = data[i]; |
|||
} |
|||
} |
|||
return newSize; |
|||
} |
|||
} |
|||
@ -0,0 +1,61 @@ |
|||
package com.bnyer.common.core.utils.sql; |
|||
|
|||
import com.bnyer.common.core.exception.UtilException; |
|||
import com.bnyer.common.core.utils.StringUtils; |
|||
|
|||
/** |
|||
* sql操作工具类 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
public class SqlUtil |
|||
{ |
|||
/** |
|||
* 定义常用的 sql关键字 |
|||
*/ |
|||
public static String SQL_REGEX = "select |insert |delete |update |drop |count |exec |chr |mid |master |truncate |char |and |declare "; |
|||
|
|||
/** |
|||
* 仅支持字母、数字、下划线、空格、逗号、小数点(支持多个字段排序) |
|||
*/ |
|||
public static String SQL_PATTERN = "[a-zA-Z0-9_\\ \\,\\.]+"; |
|||
|
|||
/** |
|||
* 检查字符,防止注入绕过 |
|||
*/ |
|||
public static String escapeOrderBySql(String value) |
|||
{ |
|||
if (StringUtils.isNotEmpty(value) && !isValidOrderBySql(value)) |
|||
{ |
|||
throw new UtilException("参数不符合规范,不能进行查询"); |
|||
} |
|||
return value; |
|||
} |
|||
|
|||
/** |
|||
* 验证 order by 语法是否符合规范 |
|||
*/ |
|||
public static boolean isValidOrderBySql(String value) |
|||
{ |
|||
return value.matches(SQL_PATTERN); |
|||
} |
|||
|
|||
/** |
|||
* SQL关键字检查 |
|||
*/ |
|||
public static void filterKeyword(String value) |
|||
{ |
|||
if (StringUtils.isEmpty(value)) |
|||
{ |
|||
return; |
|||
} |
|||
String[] sqlKeywords = StringUtils.split(SQL_REGEX, "\\|"); |
|||
for (String sqlKeyword : sqlKeywords) |
|||
{ |
|||
if (StringUtils.indexOfIgnoreCase(value, sqlKeyword) > -1) |
|||
{ |
|||
throw new UtilException("参数存在SQL注入风险"); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,49 @@ |
|||
package com.bnyer.common.core.utils.uuid; |
|||
|
|||
/** |
|||
* ID生成器工具类 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
public class IdUtils |
|||
{ |
|||
/** |
|||
* 获取随机UUID |
|||
* |
|||
* @return 随机UUID |
|||
*/ |
|||
public static String randomUUID() |
|||
{ |
|||
return UUID.randomUUID().toString(); |
|||
} |
|||
|
|||
/** |
|||
* 简化的UUID,去掉了横线 |
|||
* |
|||
* @return 简化的UUID,去掉了横线 |
|||
*/ |
|||
public static String simpleUUID() |
|||
{ |
|||
return UUID.randomUUID().toString(true); |
|||
} |
|||
|
|||
/** |
|||
* 获取随机UUID,使用性能更好的ThreadLocalRandom生成UUID |
|||
* |
|||
* @return 随机UUID |
|||
*/ |
|||
public static String fastUUID() |
|||
{ |
|||
return UUID.fastUUID().toString(); |
|||
} |
|||
|
|||
/** |
|||
* 简化的UUID,去掉了横线,使用性能更好的ThreadLocalRandom生成UUID |
|||
* |
|||
* @return 简化的UUID,去掉了横线 |
|||
*/ |
|||
public static String fastSimpleUUID() |
|||
{ |
|||
return UUID.fastUUID().toString(true); |
|||
} |
|||
} |
|||
@ -0,0 +1,86 @@ |
|||
package com.bnyer.common.core.utils.uuid; |
|||
|
|||
import java.util.concurrent.atomic.AtomicInteger; |
|||
import com.bnyer.common.core.utils.DateUtils; |
|||
import com.bnyer.common.core.utils.StringUtils; |
|||
|
|||
/** |
|||
* @author ruoyi 序列生成类 |
|||
*/ |
|||
public class Seq |
|||
{ |
|||
// 通用序列类型
|
|||
public static final String commSeqType = "COMMON"; |
|||
|
|||
// 上传序列类型
|
|||
public static final String uploadSeqType = "UPLOAD"; |
|||
|
|||
// 通用接口序列数
|
|||
private static AtomicInteger commSeq = new AtomicInteger(1); |
|||
|
|||
// 上传接口序列数
|
|||
private static AtomicInteger uploadSeq = new AtomicInteger(1); |
|||
|
|||
// 机器标识
|
|||
private static String machineCode = "A"; |
|||
|
|||
/** |
|||
* 获取通用序列号 |
|||
* |
|||
* @return 序列值 |
|||
*/ |
|||
public static String getId() |
|||
{ |
|||
return getId(commSeqType); |
|||
} |
|||
|
|||
/** |
|||
* 默认16位序列号 yyMMddHHmmss + 一位机器标识 + 3长度循环递增字符串 |
|||
* |
|||
* @return 序列值 |
|||
*/ |
|||
public static String getId(String type) |
|||
{ |
|||
AtomicInteger atomicInt = commSeq; |
|||
if (uploadSeqType.equals(type)) |
|||
{ |
|||
atomicInt = uploadSeq; |
|||
} |
|||
return getId(atomicInt, 3); |
|||
} |
|||
|
|||
/** |
|||
* 通用接口序列号 yyMMddHHmmss + 一位机器标识 + length长度循环递增字符串 |
|||
* |
|||
* @param atomicInt 序列数 |
|||
* @param length 数值长度 |
|||
* @return 序列值 |
|||
*/ |
|||
public static String getId(AtomicInteger atomicInt, int length) |
|||
{ |
|||
String result = DateUtils.dateTimeNow(); |
|||
result += machineCode; |
|||
result += getSeq(atomicInt, length); |
|||
return result; |
|||
} |
|||
|
|||
/** |
|||
* 序列循环递增字符串[1, 10 的 (length)幂次方), 用0左补齐length位数 |
|||
* |
|||
* @return 序列值 |
|||
*/ |
|||
private synchronized static String getSeq(AtomicInteger atomicInt, int length) |
|||
{ |
|||
// 先取值再+1
|
|||
int value = atomicInt.getAndIncrement(); |
|||
|
|||
// 如果更新后值>=10 的 (length)幂次方则重置为1
|
|||
int maxSeq = (int) Math.pow(10, length); |
|||
if (atomicInt.get() >= maxSeq) |
|||
{ |
|||
atomicInt.set(1); |
|||
} |
|||
// 转字符串,用0左补齐
|
|||
return StringUtils.padl(value, length); |
|||
} |
|||
} |
|||
@ -0,0 +1,484 @@ |
|||
package com.bnyer.common.core.utils.uuid; |
|||
|
|||
import java.security.MessageDigest; |
|||
import java.security.NoSuchAlgorithmException; |
|||
import java.security.SecureRandom; |
|||
import java.util.Random; |
|||
import java.util.concurrent.ThreadLocalRandom; |
|||
import com.bnyer.common.core.exception.UtilException; |
|||
|
|||
/** |
|||
* 提供通用唯一识别码(universally unique identifier)(UUID)实现 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
public final class UUID implements java.io.Serializable, Comparable<UUID> |
|||
{ |
|||
private static final long serialVersionUID = -1185015143654744140L; |
|||
|
|||
/** |
|||
* SecureRandom 的单例 |
|||
* |
|||
*/ |
|||
private static class Holder |
|||
{ |
|||
static final SecureRandom numberGenerator = getSecureRandom(); |
|||
} |
|||
|
|||
/** 此UUID的最高64有效位 */ |
|||
private final long mostSigBits; |
|||
|
|||
/** 此UUID的最低64有效位 */ |
|||
private final long leastSigBits; |
|||
|
|||
/** |
|||
* 私有构造 |
|||
* |
|||
* @param data 数据 |
|||
*/ |
|||
private UUID(byte[] data) |
|||
{ |
|||
long msb = 0; |
|||
long lsb = 0; |
|||
assert data.length == 16 : "data must be 16 bytes in length"; |
|||
for (int i = 0; i < 8; i++) |
|||
{ |
|||
msb = (msb << 8) | (data[i] & 0xff); |
|||
} |
|||
for (int i = 8; i < 16; i++) |
|||
{ |
|||
lsb = (lsb << 8) | (data[i] & 0xff); |
|||
} |
|||
this.mostSigBits = msb; |
|||
this.leastSigBits = lsb; |
|||
} |
|||
|
|||
/** |
|||
* 使用指定的数据构造新的 UUID。 |
|||
* |
|||
* @param mostSigBits 用于 {@code UUID} 的最高有效 64 位 |
|||
* @param leastSigBits 用于 {@code UUID} 的最低有效 64 位 |
|||
*/ |
|||
public UUID(long mostSigBits, long leastSigBits) |
|||
{ |
|||
this.mostSigBits = mostSigBits; |
|||
this.leastSigBits = leastSigBits; |
|||
} |
|||
|
|||
/** |
|||
* 获取类型 4(伪随机生成的)UUID 的静态工厂。 使用加密的本地线程伪随机数生成器生成该 UUID。 |
|||
* |
|||
* @return 随机生成的 {@code UUID} |
|||
*/ |
|||
public static UUID fastUUID() |
|||
{ |
|||
return randomUUID(false); |
|||
} |
|||
|
|||
/** |
|||
* 获取类型 4(伪随机生成的)UUID 的静态工厂。 使用加密的强伪随机数生成器生成该 UUID。 |
|||
* |
|||
* @return 随机生成的 {@code UUID} |
|||
*/ |
|||
public static UUID randomUUID() |
|||
{ |
|||
return randomUUID(true); |
|||
} |
|||
|
|||
/** |
|||
* 获取类型 4(伪随机生成的)UUID 的静态工厂。 使用加密的强伪随机数生成器生成该 UUID。 |
|||
* |
|||
* @param isSecure 是否使用{@link SecureRandom}如果是可以获得更安全的随机码,否则可以得到更好的性能 |
|||
* @return 随机生成的 {@code UUID} |
|||
*/ |
|||
public static UUID randomUUID(boolean isSecure) |
|||
{ |
|||
final Random ng = isSecure ? Holder.numberGenerator : getRandom(); |
|||
|
|||
byte[] randomBytes = new byte[16]; |
|||
ng.nextBytes(randomBytes); |
|||
randomBytes[6] &= 0x0f; /* clear version */ |
|||
randomBytes[6] |= 0x40; /* set to version 4 */ |
|||
randomBytes[8] &= 0x3f; /* clear variant */ |
|||
randomBytes[8] |= 0x80; /* set to IETF variant */ |
|||
return new UUID(randomBytes); |
|||
} |
|||
|
|||
/** |
|||
* 根据指定的字节数组获取类型 3(基于名称的)UUID 的静态工厂。 |
|||
* |
|||
* @param name 用于构造 UUID 的字节数组。 |
|||
* |
|||
* @return 根据指定数组生成的 {@code UUID} |
|||
*/ |
|||
public static UUID nameUUIDFromBytes(byte[] name) |
|||
{ |
|||
MessageDigest md; |
|||
try |
|||
{ |
|||
md = MessageDigest.getInstance("MD5"); |
|||
} |
|||
catch (NoSuchAlgorithmException nsae) |
|||
{ |
|||
throw new InternalError("MD5 not supported"); |
|||
} |
|||
byte[] md5Bytes = md.digest(name); |
|||
md5Bytes[6] &= 0x0f; /* clear version */ |
|||
md5Bytes[6] |= 0x30; /* set to version 3 */ |
|||
md5Bytes[8] &= 0x3f; /* clear variant */ |
|||
md5Bytes[8] |= 0x80; /* set to IETF variant */ |
|||
return new UUID(md5Bytes); |
|||
} |
|||
|
|||
/** |
|||
* 根据 {@link #toString()} 方法中描述的字符串标准表示形式创建{@code UUID}。 |
|||
* |
|||
* @param name 指定 {@code UUID} 字符串 |
|||
* @return 具有指定值的 {@code UUID} |
|||
* @throws IllegalArgumentException 如果 name 与 {@link #toString} 中描述的字符串表示形式不符抛出此异常 |
|||
* |
|||
*/ |
|||
public static UUID fromString(String name) |
|||
{ |
|||
String[] components = name.split("-"); |
|||
if (components.length != 5) |
|||
{ |
|||
throw new IllegalArgumentException("Invalid UUID string: " + name); |
|||
} |
|||
for (int i = 0; i < 5; i++) |
|||
{ |
|||
components[i] = "0x" + components[i]; |
|||
} |
|||
|
|||
long mostSigBits = Long.decode(components[0]).longValue(); |
|||
mostSigBits <<= 16; |
|||
mostSigBits |= Long.decode(components[1]).longValue(); |
|||
mostSigBits <<= 16; |
|||
mostSigBits |= Long.decode(components[2]).longValue(); |
|||
|
|||
long leastSigBits = Long.decode(components[3]).longValue(); |
|||
leastSigBits <<= 48; |
|||
leastSigBits |= Long.decode(components[4]).longValue(); |
|||
|
|||
return new UUID(mostSigBits, leastSigBits); |
|||
} |
|||
|
|||
/** |
|||
* 返回此 UUID 的 128 位值中的最低有效 64 位。 |
|||
* |
|||
* @return 此 UUID 的 128 位值中的最低有效 64 位。 |
|||
*/ |
|||
public long getLeastSignificantBits() |
|||
{ |
|||
return leastSigBits; |
|||
} |
|||
|
|||
/** |
|||
* 返回此 UUID 的 128 位值中的最高有效 64 位。 |
|||
* |
|||
* @return 此 UUID 的 128 位值中最高有效 64 位。 |
|||
*/ |
|||
public long getMostSignificantBits() |
|||
{ |
|||
return mostSigBits; |
|||
} |
|||
|
|||
/** |
|||
* 与此 {@code UUID} 相关联的版本号. 版本号描述此 {@code UUID} 是如何生成的。 |
|||
* <p> |
|||
* 版本号具有以下含意: |
|||
* <ul> |
|||
* <li>1 基于时间的 UUID |
|||
* <li>2 DCE 安全 UUID |
|||
* <li>3 基于名称的 UUID |
|||
* <li>4 随机生成的 UUID |
|||
* </ul> |
|||
* |
|||
* @return 此 {@code UUID} 的版本号 |
|||
*/ |
|||
public int version() |
|||
{ |
|||
// Version is bits masked by 0x000000000000F000 in MS long
|
|||
return (int) ((mostSigBits >> 12) & 0x0f); |
|||
} |
|||
|
|||
/** |
|||
* 与此 {@code UUID} 相关联的变体号。变体号描述 {@code UUID} 的布局。 |
|||
* <p> |
|||
* 变体号具有以下含意: |
|||
* <ul> |
|||
* <li>0 为 NCS 向后兼容保留 |
|||
* <li>2 <a href="http://www.ietf.org/rfc/rfc4122.txt">IETF RFC 4122</a>(Leach-Salz), 用于此类 |
|||
* <li>6 保留,微软向后兼容 |
|||
* <li>7 保留供以后定义使用 |
|||
* </ul> |
|||
* |
|||
* @return 此 {@code UUID} 相关联的变体号 |
|||
*/ |
|||
public int variant() |
|||
{ |
|||
// This field is composed of a varying number of bits.
|
|||
// 0 - - Reserved for NCS backward compatibility
|
|||
// 1 0 - The IETF aka Leach-Salz variant (used by this class)
|
|||
// 1 1 0 Reserved, Microsoft backward compatibility
|
|||
// 1 1 1 Reserved for future definition.
|
|||
return (int) ((leastSigBits >>> (64 - (leastSigBits >>> 62))) & (leastSigBits >> 63)); |
|||
} |
|||
|
|||
/** |
|||
* 与此 UUID 相关联的时间戳值。 |
|||
* |
|||
* <p> |
|||
* 60 位的时间戳值根据此 {@code UUID} 的 time_low、time_mid 和 time_hi 字段构造。<br> |
|||
* 所得到的时间戳以 100 毫微秒为单位,从 UTC(通用协调时间) 1582 年 10 月 15 日零时开始。 |
|||
* |
|||
* <p> |
|||
* 时间戳值仅在在基于时间的 UUID(其 version 类型为 1)中才有意义。<br> |
|||
* 如果此 {@code UUID} 不是基于时间的 UUID,则此方法抛出 UnsupportedOperationException。 |
|||
* |
|||
* @throws UnsupportedOperationException 如果此 {@code UUID} 不是 version 为 1 的 UUID。 |
|||
*/ |
|||
public long timestamp() throws UnsupportedOperationException |
|||
{ |
|||
checkTimeBase(); |
|||
return (mostSigBits & 0x0FFFL) << 48//
|
|||
| ((mostSigBits >> 16) & 0x0FFFFL) << 32//
|
|||
| mostSigBits >>> 32; |
|||
} |
|||
|
|||
/** |
|||
* 与此 UUID 相关联的时钟序列值。 |
|||
* |
|||
* <p> |
|||
* 14 位的时钟序列值根据此 UUID 的 clock_seq 字段构造。clock_seq 字段用于保证在基于时间的 UUID 中的时间唯一性。 |
|||
* <p> |
|||
* {@code clockSequence} 值仅在基于时间的 UUID(其 version 类型为 1)中才有意义。 如果此 UUID 不是基于时间的 UUID,则此方法抛出 |
|||
* UnsupportedOperationException。 |
|||
* |
|||
* @return 此 {@code UUID} 的时钟序列 |
|||
* |
|||
* @throws UnsupportedOperationException 如果此 UUID 的 version 不为 1 |
|||
*/ |
|||
public int clockSequence() throws UnsupportedOperationException |
|||
{ |
|||
checkTimeBase(); |
|||
return (int) ((leastSigBits & 0x3FFF000000000000L) >>> 48); |
|||
} |
|||
|
|||
/** |
|||
* 与此 UUID 相关的节点值。 |
|||
* |
|||
* <p> |
|||
* 48 位的节点值根据此 UUID 的 node 字段构造。此字段旨在用于保存机器的 IEEE 802 地址,该地址用于生成此 UUID 以保证空间唯一性。 |
|||
* <p> |
|||
* 节点值仅在基于时间的 UUID(其 version 类型为 1)中才有意义。<br> |
|||
* 如果此 UUID 不是基于时间的 UUID,则此方法抛出 UnsupportedOperationException。 |
|||
* |
|||
* @return 此 {@code UUID} 的节点值 |
|||
* |
|||
* @throws UnsupportedOperationException 如果此 UUID 的 version 不为 1 |
|||
*/ |
|||
public long node() throws UnsupportedOperationException |
|||
{ |
|||
checkTimeBase(); |
|||
return leastSigBits & 0x0000FFFFFFFFFFFFL; |
|||
} |
|||
|
|||
/** |
|||
* 返回此{@code UUID} 的字符串表现形式。 |
|||
* |
|||
* <p> |
|||
* UUID 的字符串表示形式由此 BNF 描述: |
|||
* |
|||
* <pre> |
|||
* {@code |
|||
* UUID = <time_low>-<time_mid>-<time_high_and_version>-<variant_and_sequence>-<node> |
|||
* time_low = 4*<hexOctet> |
|||
* time_mid = 2*<hexOctet> |
|||
* time_high_and_version = 2*<hexOctet> |
|||
* variant_and_sequence = 2*<hexOctet> |
|||
* node = 6*<hexOctet> |
|||
* hexOctet = <hexDigit><hexDigit> |
|||
* hexDigit = [0-9a-fA-F] |
|||
* } |
|||
* </pre> |
|||
* |
|||
* </blockquote> |
|||
* |
|||
* @return 此{@code UUID} 的字符串表现形式 |
|||
* @see #toString(boolean) |
|||
*/ |
|||
@Override |
|||
public String toString() |
|||
{ |
|||
return toString(false); |
|||
} |
|||
|
|||
/** |
|||
* 返回此{@code UUID} 的字符串表现形式。 |
|||
* |
|||
* <p> |
|||
* UUID 的字符串表示形式由此 BNF 描述: |
|||
* |
|||
* <pre> |
|||
* {@code |
|||
* UUID = <time_low>-<time_mid>-<time_high_and_version>-<variant_and_sequence>-<node> |
|||
* time_low = 4*<hexOctet> |
|||
* time_mid = 2*<hexOctet> |
|||
* time_high_and_version = 2*<hexOctet> |
|||
* variant_and_sequence = 2*<hexOctet> |
|||
* node = 6*<hexOctet> |
|||
* hexOctet = <hexDigit><hexDigit> |
|||
* hexDigit = [0-9a-fA-F] |
|||
* } |
|||
* </pre> |
|||
* |
|||
* </blockquote> |
|||
* |
|||
* @param isSimple 是否简单模式,简单模式为不带'-'的UUID字符串 |
|||
* @return 此{@code UUID} 的字符串表现形式 |
|||
*/ |
|||
public String toString(boolean isSimple) |
|||
{ |
|||
final StringBuilder builder = new StringBuilder(isSimple ? 32 : 36); |
|||
// time_low
|
|||
builder.append(digits(mostSigBits >> 32, 8)); |
|||
if (false == isSimple) |
|||
{ |
|||
builder.append('-'); |
|||
} |
|||
// time_mid
|
|||
builder.append(digits(mostSigBits >> 16, 4)); |
|||
if (false == isSimple) |
|||
{ |
|||
builder.append('-'); |
|||
} |
|||
// time_high_and_version
|
|||
builder.append(digits(mostSigBits, 4)); |
|||
if (false == isSimple) |
|||
{ |
|||
builder.append('-'); |
|||
} |
|||
// variant_and_sequence
|
|||
builder.append(digits(leastSigBits >> 48, 4)); |
|||
if (false == isSimple) |
|||
{ |
|||
builder.append('-'); |
|||
} |
|||
// node
|
|||
builder.append(digits(leastSigBits, 12)); |
|||
|
|||
return builder.toString(); |
|||
} |
|||
|
|||
/** |
|||
* 返回此 UUID 的哈希码。 |
|||
* |
|||
* @return UUID 的哈希码值。 |
|||
*/ |
|||
@Override |
|||
public int hashCode() |
|||
{ |
|||
long hilo = mostSigBits ^ leastSigBits; |
|||
return ((int) (hilo >> 32)) ^ (int) hilo; |
|||
} |
|||
|
|||
/** |
|||
* 将此对象与指定对象比较。 |
|||
* <p> |
|||
* 当且仅当参数不为 {@code null}、而是一个 UUID 对象、具有与此 UUID 相同的 varriant、包含相同的值(每一位均相同)时,结果才为 {@code true}。 |
|||
* |
|||
* @param obj 要与之比较的对象 |
|||
* |
|||
* @return 如果对象相同,则返回 {@code true};否则返回 {@code false} |
|||
*/ |
|||
@Override |
|||
public boolean equals(Object obj) |
|||
{ |
|||
if ((null == obj) || (obj.getClass() != UUID.class)) |
|||
{ |
|||
return false; |
|||
} |
|||
UUID id = (UUID) obj; |
|||
return (mostSigBits == id.mostSigBits && leastSigBits == id.leastSigBits); |
|||
} |
|||
|
|||
// Comparison Operations
|
|||
|
|||
/** |
|||
* 将此 UUID 与指定的 UUID 比较。 |
|||
* |
|||
* <p> |
|||
* 如果两个 UUID 不同,且第一个 UUID 的最高有效字段大于第二个 UUID 的对应字段,则第一个 UUID 大于第二个 UUID。 |
|||
* |
|||
* @param val 与此 UUID 比较的 UUID |
|||
* |
|||
* @return 在此 UUID 小于、等于或大于 val 时,分别返回 -1、0 或 1。 |
|||
* |
|||
*/ |
|||
@Override |
|||
public int compareTo(UUID val) |
|||
{ |
|||
// The ordering is intentionally set up so that the UUIDs
|
|||
// can simply be numerically compared as two numbers
|
|||
return (this.mostSigBits < val.mostSigBits ? -1 : //
|
|||
(this.mostSigBits > val.mostSigBits ? 1 : //
|
|||
(this.leastSigBits < val.leastSigBits ? -1 : //
|
|||
(this.leastSigBits > val.leastSigBits ? 1 : //
|
|||
0)))); |
|||
} |
|||
|
|||
// -------------------------------------------------------------------------------------------------------------------
|
|||
// Private method start
|
|||
/** |
|||
* 返回指定数字对应的hex值 |
|||
* |
|||
* @param val 值 |
|||
* @param digits 位 |
|||
* @return 值 |
|||
*/ |
|||
private static String digits(long val, int digits) |
|||
{ |
|||
long hi = 1L << (digits * 4); |
|||
return Long.toHexString(hi | (val & (hi - 1))).substring(1); |
|||
} |
|||
|
|||
/** |
|||
* 检查是否为time-based版本UUID |
|||
*/ |
|||
private void checkTimeBase() |
|||
{ |
|||
if (version() != 1) |
|||
{ |
|||
throw new UnsupportedOperationException("Not a time-based UUID"); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 获取{@link SecureRandom},类提供加密的强随机数生成器 (RNG) |
|||
* |
|||
* @return {@link SecureRandom} |
|||
*/ |
|||
public static SecureRandom getSecureRandom() |
|||
{ |
|||
try |
|||
{ |
|||
return SecureRandom.getInstance("SHA1PRNG"); |
|||
} |
|||
catch (NoSuchAlgorithmException e) |
|||
{ |
|||
throw new UtilException(e); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 获取随机数生成器对象<br> |
|||
* ThreadLocalRandom是JDK 7之后提供并发产生随机数,能够解决多个线程发生的竞争争夺。 |
|||
* |
|||
* @return {@link ThreadLocalRandom} |
|||
*/ |
|||
public static ThreadLocalRandom getRandom() |
|||
{ |
|||
return ThreadLocalRandom.current(); |
|||
} |
|||
} |
|||
@ -0,0 +1,127 @@ |
|||
package com.bnyer.common.core.web.controller; |
|||
|
|||
import java.beans.PropertyEditorSupport; |
|||
import java.util.Date; |
|||
import java.util.List; |
|||
|
|||
import com.bnyer.common.core.utils.PageUtils; |
|||
import com.bnyer.common.core.web.page.TableDataInfo; |
|||
import org.slf4j.Logger; |
|||
import org.slf4j.LoggerFactory; |
|||
import org.springframework.web.bind.WebDataBinder; |
|||
import org.springframework.web.bind.annotation.InitBinder; |
|||
import com.github.pagehelper.PageInfo; |
|||
import com.bnyer.common.core.constant.HttpStatus; |
|||
import com.bnyer.common.core.utils.DateUtils; |
|||
import com.bnyer.common.core.web.domain.AjaxResult; |
|||
|
|||
/** |
|||
* web层通用数据处理 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
public class BaseController |
|||
{ |
|||
protected final Logger logger = LoggerFactory.getLogger(this.getClass()); |
|||
|
|||
/** |
|||
* 将前台传递过来的日期格式的字符串,自动转化为Date类型 |
|||
*/ |
|||
@InitBinder |
|||
public void initBinder(WebDataBinder binder) |
|||
{ |
|||
// Date 类型转换
|
|||
binder.registerCustomEditor(Date.class, new PropertyEditorSupport() |
|||
{ |
|||
@Override |
|||
public void setAsText(String text) |
|||
{ |
|||
setValue(DateUtils.parseDate(text)); |
|||
} |
|||
}); |
|||
} |
|||
|
|||
/** |
|||
* 设置请求分页数据 |
|||
*/ |
|||
protected void startPage() |
|||
{ |
|||
PageUtils.startPage(); |
|||
} |
|||
|
|||
/** |
|||
* 清理分页的线程变量 |
|||
*/ |
|||
protected void clearPage() |
|||
{ |
|||
PageUtils.clearPage(); |
|||
} |
|||
|
|||
/** |
|||
* 响应请求分页数据 |
|||
*/ |
|||
@SuppressWarnings({ "rawtypes", "unchecked" }) |
|||
protected TableDataInfo getDataTable(List<?> list) |
|||
{ |
|||
TableDataInfo rspData = new TableDataInfo(); |
|||
rspData.setCode(HttpStatus.SUCCESS); |
|||
rspData.setRows(list); |
|||
rspData.setMsg("查询成功"); |
|||
rspData.setTotal(new PageInfo(list).getTotal()); |
|||
return rspData; |
|||
} |
|||
|
|||
/** |
|||
* 响应返回结果 |
|||
* |
|||
* @param rows 影响行数 |
|||
* @return 操作结果 |
|||
*/ |
|||
protected AjaxResult toAjax(int rows) |
|||
{ |
|||
return rows > 0 ? AjaxResult.success() : AjaxResult.error(); |
|||
} |
|||
|
|||
/** |
|||
* 响应返回结果 |
|||
* |
|||
* @param result 结果 |
|||
* @return 操作结果 |
|||
*/ |
|||
protected AjaxResult toAjax(boolean result) |
|||
{ |
|||
return result ? success() : error(); |
|||
} |
|||
|
|||
/** |
|||
* 返回成功 |
|||
*/ |
|||
public AjaxResult success() |
|||
{ |
|||
return AjaxResult.success(); |
|||
} |
|||
|
|||
/** |
|||
* 返回失败消息 |
|||
*/ |
|||
public AjaxResult error() |
|||
{ |
|||
return AjaxResult.error(); |
|||
} |
|||
|
|||
/** |
|||
* 返回成功消息 |
|||
*/ |
|||
public AjaxResult success(String message) |
|||
{ |
|||
return AjaxResult.success(message); |
|||
} |
|||
|
|||
/** |
|||
* 返回失败消息 |
|||
*/ |
|||
public AjaxResult error(String message) |
|||
{ |
|||
return AjaxResult.error(message); |
|||
} |
|||
} |
|||
@ -0,0 +1,162 @@ |
|||
package com.bnyer.common.core.web.domain; |
|||
|
|||
import java.util.HashMap; |
|||
import com.bnyer.common.core.constant.HttpStatus; |
|||
import com.bnyer.common.core.utils.StringUtils; |
|||
|
|||
/** |
|||
* 操作消息提醒 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
public class AjaxResult extends HashMap<String, Object> |
|||
{ |
|||
private static final long serialVersionUID = 1L; |
|||
|
|||
/** 状态码 */ |
|||
public static final String CODE_TAG = "code"; |
|||
|
|||
/** 返回内容 */ |
|||
public static final String MSG_TAG = "msg"; |
|||
|
|||
/** 数据对象 */ |
|||
public static final String DATA_TAG = "data"; |
|||
|
|||
/** |
|||
* 初始化一个新创建的 AjaxResult 对象,使其表示一个空消息。 |
|||
*/ |
|||
public AjaxResult() |
|||
{ |
|||
} |
|||
|
|||
/** |
|||
* 初始化一个新创建的 AjaxResult 对象 |
|||
* |
|||
* @param code 状态码 |
|||
* @param msg 返回内容 |
|||
*/ |
|||
public AjaxResult(int code, String msg) |
|||
{ |
|||
super.put(CODE_TAG, code); |
|||
super.put(MSG_TAG, msg); |
|||
} |
|||
|
|||
/** |
|||
* 初始化一个新创建的 AjaxResult 对象 |
|||
* |
|||
* @param code 状态码 |
|||
* @param msg 返回内容 |
|||
* @param data 数据对象 |
|||
*/ |
|||
public AjaxResult(int code, String msg, Object data) |
|||
{ |
|||
super.put(CODE_TAG, code); |
|||
super.put(MSG_TAG, msg); |
|||
if (StringUtils.isNotNull(data)) |
|||
{ |
|||
super.put(DATA_TAG, data); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 方便链式调用 |
|||
* |
|||
* @param key |
|||
* @param value |
|||
* @return |
|||
*/ |
|||
@Override |
|||
public AjaxResult put(String key, Object value) |
|||
{ |
|||
super.put(key, value); |
|||
return this; |
|||
} |
|||
|
|||
/** |
|||
* 返回成功消息 |
|||
* |
|||
* @return 成功消息 |
|||
*/ |
|||
public static AjaxResult success() |
|||
{ |
|||
return AjaxResult.success("操作成功"); |
|||
} |
|||
|
|||
/** |
|||
* 返回成功数据 |
|||
* |
|||
* @return 成功消息 |
|||
*/ |
|||
public static AjaxResult success(Object data) |
|||
{ |
|||
return AjaxResult.success("操作成功", data); |
|||
} |
|||
|
|||
/** |
|||
* 返回成功消息 |
|||
* |
|||
* @param msg 返回内容 |
|||
* @return 成功消息 |
|||
*/ |
|||
public static AjaxResult success(String msg) |
|||
{ |
|||
return AjaxResult.success(msg, null); |
|||
} |
|||
|
|||
/** |
|||
* 返回成功消息 |
|||
* |
|||
* @param msg 返回内容 |
|||
* @param data 数据对象 |
|||
* @return 成功消息 |
|||
*/ |
|||
public static AjaxResult success(String msg, Object data) |
|||
{ |
|||
return new AjaxResult(HttpStatus.SUCCESS, msg, data); |
|||
} |
|||
|
|||
/** |
|||
* 返回错误消息 |
|||
* |
|||
* @return |
|||
*/ |
|||
public static AjaxResult error() |
|||
{ |
|||
return AjaxResult.error("操作失败"); |
|||
} |
|||
|
|||
/** |
|||
* 返回错误消息 |
|||
* |
|||
* @param msg 返回内容 |
|||
* @return 警告消息 |
|||
*/ |
|||
public static AjaxResult error(String msg) |
|||
{ |
|||
return AjaxResult.error(msg, null); |
|||
} |
|||
|
|||
/** |
|||
* 返回错误消息 |
|||
* |
|||
* @param msg 返回内容 |
|||
* @param data 数据对象 |
|||
* @return 警告消息 |
|||
*/ |
|||
public static AjaxResult error(String msg, Object data) |
|||
{ |
|||
return new AjaxResult(HttpStatus.ERROR, msg, data); |
|||
} |
|||
|
|||
/** |
|||
* 返回错误消息 |
|||
* |
|||
* @param code 状态码 |
|||
* @param msg 返回内容 |
|||
* @return 警告消息 |
|||
*/ |
|||
public static AjaxResult error(int code, String msg) |
|||
{ |
|||
return new AjaxResult(code, msg, null); |
|||
} |
|||
} |
|||
@ -0,0 +1,114 @@ |
|||
package com.bnyer.common.core.web.domain; |
|||
|
|||
import java.io.Serializable; |
|||
import java.util.Date; |
|||
import java.util.HashMap; |
|||
import java.util.Map; |
|||
import com.fasterxml.jackson.annotation.JsonFormat; |
|||
|
|||
/** |
|||
* Entity基类 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
public class BaseEntity implements Serializable |
|||
{ |
|||
private static final long serialVersionUID = 1L; |
|||
|
|||
/** 搜索值 */ |
|||
private String searchValue; |
|||
|
|||
/** 创建者 */ |
|||
private String createBy; |
|||
|
|||
/** 创建时间 */ |
|||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") |
|||
private Date createTime; |
|||
|
|||
/** 更新者 */ |
|||
private String updateBy; |
|||
|
|||
/** 更新时间 */ |
|||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") |
|||
private Date updateTime; |
|||
|
|||
/** 备注 */ |
|||
private String remark; |
|||
|
|||
/** 请求参数 */ |
|||
private Map<String, Object> params; |
|||
|
|||
public String getSearchValue() |
|||
{ |
|||
return searchValue; |
|||
} |
|||
|
|||
public void setSearchValue(String searchValue) |
|||
{ |
|||
this.searchValue = searchValue; |
|||
} |
|||
|
|||
public String getCreateBy() |
|||
{ |
|||
return createBy; |
|||
} |
|||
|
|||
public void setCreateBy(String createBy) |
|||
{ |
|||
this.createBy = createBy; |
|||
} |
|||
|
|||
public Date getCreateTime() |
|||
{ |
|||
return createTime; |
|||
} |
|||
|
|||
public void setCreateTime(Date createTime) |
|||
{ |
|||
this.createTime = createTime; |
|||
} |
|||
|
|||
public String getUpdateBy() |
|||
{ |
|||
return updateBy; |
|||
} |
|||
|
|||
public void setUpdateBy(String updateBy) |
|||
{ |
|||
this.updateBy = updateBy; |
|||
} |
|||
|
|||
public Date getUpdateTime() |
|||
{ |
|||
return updateTime; |
|||
} |
|||
|
|||
public void setUpdateTime(Date updateTime) |
|||
{ |
|||
this.updateTime = updateTime; |
|||
} |
|||
|
|||
public String getRemark() |
|||
{ |
|||
return remark; |
|||
} |
|||
|
|||
public void setRemark(String remark) |
|||
{ |
|||
this.remark = remark; |
|||
} |
|||
|
|||
public Map<String, Object> getParams() |
|||
{ |
|||
if (params == null) |
|||
{ |
|||
params = new HashMap<>(); |
|||
} |
|||
return params; |
|||
} |
|||
|
|||
public void setParams(Map<String, Object> params) |
|||
{ |
|||
this.params = params; |
|||
} |
|||
} |
|||
@ -0,0 +1,79 @@ |
|||
package com.bnyer.common.core.web.domain; |
|||
|
|||
import java.util.ArrayList; |
|||
import java.util.List; |
|||
|
|||
/** |
|||
* Tree基类 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
public class TreeEntity extends BaseEntity |
|||
{ |
|||
private static final long serialVersionUID = 1L; |
|||
|
|||
/** 父菜单名称 */ |
|||
private String parentName; |
|||
|
|||
/** 父菜单ID */ |
|||
private Long parentId; |
|||
|
|||
/** 显示顺序 */ |
|||
private Integer orderNum; |
|||
|
|||
/** 祖级列表 */ |
|||
private String ancestors; |
|||
|
|||
/** 子部门 */ |
|||
private List<?> children = new ArrayList<>(); |
|||
|
|||
public String getParentName() |
|||
{ |
|||
return parentName; |
|||
} |
|||
|
|||
public void setParentName(String parentName) |
|||
{ |
|||
this.parentName = parentName; |
|||
} |
|||
|
|||
public Long getParentId() |
|||
{ |
|||
return parentId; |
|||
} |
|||
|
|||
public void setParentId(Long parentId) |
|||
{ |
|||
this.parentId = parentId; |
|||
} |
|||
|
|||
public Integer getOrderNum() |
|||
{ |
|||
return orderNum; |
|||
} |
|||
|
|||
public void setOrderNum(Integer orderNum) |
|||
{ |
|||
this.orderNum = orderNum; |
|||
} |
|||
|
|||
public String getAncestors() |
|||
{ |
|||
return ancestors; |
|||
} |
|||
|
|||
public void setAncestors(String ancestors) |
|||
{ |
|||
this.ancestors = ancestors; |
|||
} |
|||
|
|||
public List<?> getChildren() |
|||
{ |
|||
return children; |
|||
} |
|||
|
|||
public void setChildren(List<?> children) |
|||
{ |
|||
this.children = children; |
|||
} |
|||
} |
|||
@ -0,0 +1,101 @@ |
|||
package com.bnyer.common.core.web.page; |
|||
|
|||
import com.bnyer.common.core.utils.StringUtils; |
|||
|
|||
/** |
|||
* 分页数据 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
public class PageDomain |
|||
{ |
|||
/** 当前记录起始索引 */ |
|||
private Integer pageNum; |
|||
|
|||
/** 每页显示记录数 */ |
|||
private Integer pageSize; |
|||
|
|||
/** 排序列 */ |
|||
private String orderByColumn; |
|||
|
|||
/** 排序的方向desc或者asc */ |
|||
private String isAsc = "asc"; |
|||
|
|||
/** 分页参数合理化 */ |
|||
private Boolean reasonable = true; |
|||
|
|||
public String getOrderBy() |
|||
{ |
|||
if (StringUtils.isEmpty(orderByColumn)) |
|||
{ |
|||
return ""; |
|||
} |
|||
return StringUtils.toUnderScoreCase(orderByColumn) + " " + isAsc; |
|||
} |
|||
|
|||
public Integer getPageNum() |
|||
{ |
|||
return pageNum; |
|||
} |
|||
|
|||
public void setPageNum(Integer pageNum) |
|||
{ |
|||
this.pageNum = pageNum; |
|||
} |
|||
|
|||
public Integer getPageSize() |
|||
{ |
|||
return pageSize; |
|||
} |
|||
|
|||
public void setPageSize(Integer pageSize) |
|||
{ |
|||
this.pageSize = pageSize; |
|||
} |
|||
|
|||
public String getOrderByColumn() |
|||
{ |
|||
return orderByColumn; |
|||
} |
|||
|
|||
public void setOrderByColumn(String orderByColumn) |
|||
{ |
|||
this.orderByColumn = orderByColumn; |
|||
} |
|||
|
|||
public String getIsAsc() |
|||
{ |
|||
return isAsc; |
|||
} |
|||
|
|||
public void setIsAsc(String isAsc) |
|||
{ |
|||
if (StringUtils.isNotEmpty(isAsc)) |
|||
{ |
|||
// 兼容前端排序类型
|
|||
if ("ascending".equals(isAsc)) |
|||
{ |
|||
isAsc = "asc"; |
|||
} |
|||
else if ("descending".equals(isAsc)) |
|||
{ |
|||
isAsc = "desc"; |
|||
} |
|||
this.isAsc = isAsc; |
|||
} |
|||
} |
|||
|
|||
public Boolean getReasonable() |
|||
{ |
|||
if (StringUtils.isNull(reasonable)) |
|||
{ |
|||
return Boolean.TRUE; |
|||
} |
|||
return reasonable; |
|||
} |
|||
|
|||
public void setReasonable(Boolean reasonable) |
|||
{ |
|||
this.reasonable = reasonable; |
|||
} |
|||
} |
|||
@ -0,0 +1,85 @@ |
|||
package com.bnyer.common.core.web.page; |
|||
|
|||
import java.io.Serializable; |
|||
import java.util.List; |
|||
|
|||
/** |
|||
* 表格分页数据对象 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
public class TableDataInfo implements Serializable |
|||
{ |
|||
private static final long serialVersionUID = 1L; |
|||
|
|||
/** 总记录数 */ |
|||
private long total; |
|||
|
|||
/** 列表数据 */ |
|||
private List<?> rows; |
|||
|
|||
/** 消息状态码 */ |
|||
private int code; |
|||
|
|||
/** 消息内容 */ |
|||
private String msg; |
|||
|
|||
/** |
|||
* 表格数据对象 |
|||
*/ |
|||
public TableDataInfo() |
|||
{ |
|||
} |
|||
|
|||
/** |
|||
* 分页 |
|||
* |
|||
* @param list 列表数据 |
|||
* @param total 总记录数 |
|||
*/ |
|||
public TableDataInfo(List<?> list, int total) |
|||
{ |
|||
this.rows = list; |
|||
this.total = total; |
|||
} |
|||
|
|||
public long getTotal() |
|||
{ |
|||
return total; |
|||
} |
|||
|
|||
public void setTotal(long total) |
|||
{ |
|||
this.total = total; |
|||
} |
|||
|
|||
public List<?> getRows() |
|||
{ |
|||
return rows; |
|||
} |
|||
|
|||
public void setRows(List<?> rows) |
|||
{ |
|||
this.rows = rows; |
|||
} |
|||
|
|||
public int getCode() |
|||
{ |
|||
return code; |
|||
} |
|||
|
|||
public void setCode(int code) |
|||
{ |
|||
this.code = code; |
|||
} |
|||
|
|||
public String getMsg() |
|||
{ |
|||
return msg; |
|||
} |
|||
|
|||
public void setMsg(String msg) |
|||
{ |
|||
this.msg = msg; |
|||
} |
|||
} |
|||
@ -0,0 +1,55 @@ |
|||
package com.bnyer.common.core.web.page; |
|||
|
|||
import com.bnyer.common.core.utils.ServletUtils; |
|||
|
|||
/** |
|||
* 表格数据处理 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
public class TableSupport |
|||
{ |
|||
/** |
|||
* 当前记录起始索引 |
|||
*/ |
|||
public static final String PAGE_NUM = "pageNum"; |
|||
|
|||
/** |
|||
* 每页显示记录数 |
|||
*/ |
|||
public static final String PAGE_SIZE = "pageSize"; |
|||
|
|||
/** |
|||
* 排序列 |
|||
*/ |
|||
public static final String ORDER_BY_COLUMN = "orderByColumn"; |
|||
|
|||
/** |
|||
* 排序的方向 "desc" 或者 "asc". |
|||
*/ |
|||
public static final String IS_ASC = "isAsc"; |
|||
|
|||
/** |
|||
* 分页参数合理化 |
|||
*/ |
|||
public static final String REASONABLE = "reasonable"; |
|||
|
|||
/** |
|||
* 封装分页对象 |
|||
*/ |
|||
public static PageDomain getPageDomain() |
|||
{ |
|||
PageDomain pageDomain = new PageDomain(); |
|||
pageDomain.setPageNum(ServletUtils.getParameterToInt(PAGE_NUM)); |
|||
pageDomain.setPageSize(ServletUtils.getParameterToInt(PAGE_SIZE)); |
|||
pageDomain.setOrderByColumn(ServletUtils.getParameter(ORDER_BY_COLUMN)); |
|||
pageDomain.setIsAsc(ServletUtils.getParameter(IS_ASC)); |
|||
pageDomain.setReasonable(ServletUtils.getParameterToBool(REASONABLE)); |
|||
return pageDomain; |
|||
} |
|||
|
|||
public static PageDomain buildPageRequest() |
|||
{ |
|||
return getPageDomain(); |
|||
} |
|||
} |
|||
@ -0,0 +1,27 @@ |
|||
package com.bnyer.common.core.xss; |
|||
|
|||
import javax.validation.Constraint; |
|||
import javax.validation.Payload; |
|||
import java.lang.annotation.ElementType; |
|||
import java.lang.annotation.Retention; |
|||
import java.lang.annotation.RetentionPolicy; |
|||
import java.lang.annotation.Target; |
|||
|
|||
/** |
|||
* 自定义xss校验注解 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
@Retention(RetentionPolicy.RUNTIME) |
|||
@Target(value = { ElementType.METHOD, ElementType.FIELD, ElementType.CONSTRUCTOR, ElementType.PARAMETER }) |
|||
@Constraint(validatedBy = { XssValidator.class }) |
|||
public @interface Xss |
|||
{ |
|||
String message() |
|||
|
|||
default "不允许任何脚本运行"; |
|||
|
|||
Class<?>[] groups() default {}; |
|||
|
|||
Class<? extends Payload>[] payload() default {}; |
|||
} |
|||
@ -0,0 +1,34 @@ |
|||
package com.bnyer.common.core.xss; |
|||
|
|||
import java.util.regex.Matcher; |
|||
import java.util.regex.Pattern; |
|||
import javax.validation.ConstraintValidator; |
|||
import javax.validation.ConstraintValidatorContext; |
|||
import com.bnyer.common.core.utils.StringUtils; |
|||
|
|||
/** |
|||
* 自定义xss校验注解实现 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
public class XssValidator implements ConstraintValidator<Xss, String> |
|||
{ |
|||
private static final String HTML_PATTERN = "<(\\S*?)[^>]*>.*?|<.*? />"; |
|||
|
|||
@Override |
|||
public boolean isValid(String value, ConstraintValidatorContext constraintValidatorContext) |
|||
{ |
|||
if (StringUtils.isBlank(value)) |
|||
{ |
|||
return true; |
|||
} |
|||
return !containsHtml(value); |
|||
} |
|||
|
|||
public static boolean containsHtml(String value) |
|||
{ |
|||
Pattern pattern = Pattern.compile(HTML_PATTERN); |
|||
Matcher matcher = pattern.matcher(value); |
|||
return matcher.matches(); |
|||
} |
|||
} |
|||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue