迁移代码

This commit is contained in:
13768238378 2025-05-28 09:45:23 +08:00
parent 915997e9e3
commit 22e01dac3d
413 changed files with 29816 additions and 866 deletions

12
pom.xml
View File

@ -8,7 +8,7 @@
<artifactId>tcctyn-cloud</artifactId> <artifactId>tcctyn-cloud</artifactId>
<version>1.0.0</version> <version>1.0.0</version>
<name>forest-fire</name> <name>tcctyn-cloud</name>
<description>森林防火监测预警管理平台</description> <description>森林防火监测预警管理平台</description>
<properties> <properties>
@ -38,6 +38,16 @@
<tomcat.version>9.0.102</tomcat.version> <tomcat.version>9.0.102</tomcat.version>
<logback.version>1.2.13</logback.version> <logback.version>1.2.13</logback.version>
<spring-framework.version>5.3.39</spring-framework.version> <spring-framework.version>5.3.39</spring-framework.version>
<lombok.version>1.18.36</lombok.version>
<mybatis-plus-boot-starter.version>3.5.1</mybatis-plus-boot-starter.version>
<mybatis-plus-join-boot-starter.version>1.5.0</mybatis-plus-join-boot-starter.version>
<artemis-http-client.version>1.1.3</artemis-http-client.version>
<mybatis-plus-annotation.version>3.5.3.1</mybatis-plus-annotation.version>
<mybatis-plus-core.version>3.5.3.1</mybatis-plus-core.version>
<mybatis-plus-extension.version>3.5.3.1</mybatis-plus-extension.version>
<hutool-all.version>5.1.0</hutool-all.version>
<jna.version>5.15.0</jna.version>
<org.eclipse.paho.client.mqttv3.version>1.2.5</org.eclipse.paho.client.mqttv3.version>
</properties> </properties>
<!-- 依赖声明 --> <!-- 依赖声明 -->

21
sql/iot.sql Normal file
View File

@ -0,0 +1,21 @@
CREATE TABLE api_configs (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键ID',
name VARCHAR(64) NOT NULL COMMENT 'API名称',
url VARCHAR(255) NOT NULL COMMENT 'API URL地址',
api_key VARCHAR(255) DEFAULT NULL COMMENT 'API访问密钥',
api_secret VARCHAR(512) DEFAULT NULL COMMENT 'API安全密钥',
status TINYINT(1) UNSIGNED DEFAULT 0 COMMENT '状态(0-启用 1-停用)',
create_time datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
update_time datetime COMMENT '更新时间',
create_by VARCHAR(64) DEFAULT NULL COMMENT '创建人',
update_by VARCHAR(64) DEFAULT NULL COMMENT '更新人',
is_deleted TINYINT(1) UNSIGNED DEFAULT 0 COMMENT '是否删除(0-未删除 1-已删除)',
remark VARCHAR(255) DEFAULT NULL COMMENT '备注',
PRIMARY KEY (id),
UNIQUE KEY uk_name (name) COMMENT 'API名称唯一索引',
KEY idx_status (status) COMMENT '状态索引'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='API信息配置表';
INSERT INTO api_configs (name, url, api_key, api_secret, status,create_by)
VALUES("海康平台API","https://116.53.205.228:14443/artemis","21887937","hwOzOEqxuPDz5frAnEXb",0,"admin");

View File

@ -10,6 +10,7 @@
<modules> <modules>
<module>tcctyn-api-system</module> <module>tcctyn-api-system</module>
<module>tcctyn-api-iot</module>
</modules> </modules>
<artifactId>tcctyn-api</artifactId> <artifactId>tcctyn-api</artifactId>

View File

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.tcctyn</groupId>
<artifactId>tcctyn-api</artifactId>
<version>1.0.0</version>
</parent>
<artifactId>tcctyn-api-iot</artifactId>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-openfeign-core</artifactId>
</dependency>
<dependency>
<groupId>com.tcctyn</groupId>
<artifactId>tcctyn-common-core</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,29 @@
package com.tcctyn.iot.api;
import com.tcctyn.common.core.constant.ServiceNameConstants;
import com.tcctyn.common.core.web.domain.R;
import com.tcctyn.common.core.web.domain.model.LoginUser;
import com.tcctyn.iot.api.factory.RemoteDeviceFallbackFactory;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
/**
* 用户服务
*
* @author tcctyn
*/
@FeignClient(contextId = "remoteDeviceService", value = ServiceNameConstants.SYSTEM_SERVICE, fallbackFactory = RemoteDeviceFallbackFactory.class)
public interface RemoteDeviceService
{
/**
* 通过id获取设备信息
*
* @param username 用户名
* @return 结果
*/
@GetMapping("/device/info/{deviceNo}")
public R<LoginUser> getDeviceInfoByDeviceNo(@PathVariable("deviceNo") String deviceNo);
}

View File

@ -0,0 +1,58 @@
package com.tcctyn.iot.api.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
import javax.validation.constraints.NotBlank;
/**
* <p>
* 设备配置表
* </p>
*
* @author 宋国强
* @since 2025-04-14
*/
@Data
public class DeviceConfig {
/**
* 主键id
*/
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/**
* 设备编号
*/
@NotBlank(message = "设备编号不能为空")
private String deviceNo;
/**
* 用户账户
*/
private String username;
/**
* 密码
*/
private String password;
/**
* IP地址
*/
private String ip;
/**
* 端口号
*/
private String port;
/**
* 备注
*/
private String remark;
}

View File

@ -0,0 +1,161 @@
package com.tcctyn.iot.api.domain;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.validation.constraints.NotBlank;
import java.io.Serializable;
import java.util.Date;
/**
* <p>
* 设备信息表
* </p>
*
* @author 代超
* @since 2024-10-09
*/
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("device_info")
public class DeviceInfo implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 主键id
*/
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/**
* 设备编号
*/
@NotBlank(message = "设备编号不能为空")
private String deviceNo;
/**
* 设备名称
*/
private String deviceName;
/**
* 设备型号
*/
private String deviceModel;
/**
* 设备厂商
*/
private String deviceManufacturer;
/**
* 设备协议
*/
private String deviceProtocol;
/**
* 接入方式
*/
private String accessMethod;
/**
* 设备类型
*/
private String deviceType;
/**
* 设备状态在线/离线
*/
private String deviceStatus;
/**
* 归属区域id,机场需要挂在地区下面
*/
private Long regionId;
/**
* 归属云台/卡口id
*/
private Long pointId;
/**
* 林区id
*/
private Long forestId;
/**
* 林场id
*/
private Long farmId;
/**
* 电子围栏id
*/
private Long fenceId;
/**
* 机场id
*/
private Long airportId;
/**
* 地址
*/
private String address;
/**
* 经度
*/
private String longitude;
/**
* 纬度
*/
private String latitude;
/**
* 高度
*/
private String height;
/**
* 设备启用状态0-停用/1-启用
*/
private Integer enableFlag;
/**
* 备注信息
*/
private String remark;
/**
* 该条记录是否被删除1-已删除0-未删除
*/
@TableLogic
private Integer delFlag;
/**
* 创建人员姓名
*/
private String createdBy;
/**
* 记录创建时间默认用服务器时间
*/
@TableField(fill = FieldFill.INSERT)
private Date createdTime;
/**
* 修改人员姓名
*/
private String updatedBy;
/**
* 记录修改时间默认用服务器时间
*/
@TableField(fill = FieldFill.UPDATE)
private Date updatedTime;
}

View File

@ -0,0 +1,35 @@
package com.tcctyn.iot.api.factory;
import com.tcctyn.common.core.web.domain.R;
import com.tcctyn.common.core.web.domain.model.LoginUser;
import com.tcctyn.iot.api.RemoteDeviceService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.openfeign.FallbackFactory;
import org.springframework.stereotype.Component;
/**
* 用户服务降级处理
*
* @author tcctyn
*/
@Component
public class RemoteDeviceFallbackFactory implements FallbackFactory<RemoteDeviceService>
{
private static final Logger log = LoggerFactory.getLogger(RemoteDeviceFallbackFactory.class);
@Override
public RemoteDeviceService create(Throwable throwable)
{
log.error("物联网服务调用失败:{}", throwable.getMessage());
return new RemoteDeviceService()
{
@Override
public R<LoginUser> getDeviceInfoByDeviceNo(String deviceNo) {
return R.fail("获取设备信息失败:" + throwable.getMessage());
}
};
}
}

View File

@ -0,0 +1 @@
com.tcctyn.iot.api.factory.RemoteDeviceFallbackFactory

View File

@ -6,7 +6,7 @@ import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestPart; import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import com.tcctyn.common.core.constant.ServiceNameConstants; import com.tcctyn.common.core.constant.ServiceNameConstants;
import com.tcctyn.common.core.domain.R; import com.tcctyn.common.core.web.domain.R;
import com.tcctyn.system.api.domain.SysFile; import com.tcctyn.system.api.domain.SysFile;
import com.tcctyn.system.api.factory.RemoteFileFallbackFactory; import com.tcctyn.system.api.factory.RemoteFileFallbackFactory;

View File

@ -6,7 +6,7 @@ import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader; import org.springframework.web.bind.annotation.RequestHeader;
import com.tcctyn.common.core.constant.SecurityConstants; import com.tcctyn.common.core.constant.SecurityConstants;
import com.tcctyn.common.core.constant.ServiceNameConstants; import com.tcctyn.common.core.constant.ServiceNameConstants;
import com.tcctyn.common.core.domain.R; import com.tcctyn.common.core.web.domain.R;
import com.tcctyn.system.api.domain.SysLogininfor; import com.tcctyn.system.api.domain.SysLogininfor;
import com.tcctyn.system.api.domain.SysOperLog; import com.tcctyn.system.api.domain.SysOperLog;
import com.tcctyn.system.api.factory.RemoteLogFallbackFactory; import com.tcctyn.system.api.factory.RemoteLogFallbackFactory;

View File

@ -1,18 +1,16 @@
package com.tcctyn.system.api; package com.tcctyn.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.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import com.tcctyn.common.core.constant.SecurityConstants; import com.tcctyn.common.core.constant.SecurityConstants;
import com.tcctyn.common.core.constant.ServiceNameConstants; import com.tcctyn.common.core.constant.ServiceNameConstants;
import com.tcctyn.common.core.domain.R; import com.tcctyn.common.core.web.domain.R;
import com.tcctyn.system.api.domain.SysDept;
import com.tcctyn.system.api.domain.SysUser; import com.tcctyn.system.api.domain.SysUser;
import com.tcctyn.system.api.factory.RemoteUserFallbackFactory; import com.tcctyn.system.api.factory.RemoteUserFallbackFactory;
import com.tcctyn.system.api.model.LoginUser; import com.tcctyn.system.api.model.LoginUser;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/** /**
* 用户服务 * 用户服务
@ -29,7 +27,7 @@ public interface RemoteUserService
* @param source 请求来源 * @param source 请求来源
* @return 结果 * @return 结果
*/ */
@GetMapping("/user/info/{username}") @GetMapping("/system/user/info/{username}")
public R<LoginUser> getUserInfo(@PathVariable("username") String username, @RequestHeader(SecurityConstants.FROM_SOURCE) String source); public R<LoginUser> getUserInfo(@PathVariable("username") String username, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
/** /**
@ -39,7 +37,7 @@ public interface RemoteUserService
* @param source 请求来源 * @param source 请求来源
* @return 结果 * @return 结果
*/ */
@PostMapping("/user/register") @PostMapping("/system/user/register")
public R<Boolean> registerUserInfo(@RequestBody SysUser sysUser, @RequestHeader(SecurityConstants.FROM_SOURCE) String source); public R<Boolean> registerUserInfo(@RequestBody SysUser sysUser, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
/** /**
@ -49,6 +47,47 @@ public interface RemoteUserService
* @param source 请求来源 * @param source 请求来源
* @return 结果 * @return 结果
*/ */
@PutMapping("/user/recordlogin") @PutMapping("/system/user/recordlogin")
public R<Boolean> recordUserLogin(@RequestBody SysUser sysUser, @RequestHeader(SecurityConstants.FROM_SOURCE) String source); public R<Boolean> recordUserLogin(@RequestBody SysUser sysUser, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
/**
* 通过用户ID查询用户
*
* @return 结果
*/
@PostMapping("/system/user/selectUserById/{userId}")
public R<SysUser> selectUserById(@PathVariable("userId") Long userId);
/**
* 通过条件查询查询用户列表
*
* @param sysUser 用户信息
* @return 结果
*/
@PostMapping("/system/user/selectUserList")
public R<List<SysUser>> selectUserList(@RequestBody SysUser sysUser);
/**
* 获取用户列表用于前端选择器
* @param regionId 归属地区id
* @return
*/
@GetMapping("/system/user/userNames/{regionId}")
public R<List<SysUser>> selectUserByRegionIdList(@PathVariable("regionId") Long regionId) ;
/**
* 通过用户ID查询用户
*
* @return 结果
*/
@PostMapping("/system/dept/selectDeptById/{deptId}")
public R<SysDept> selectDeptById(@PathVariable("deptId") Long deptId);
/**
* 通过条件查询查询用户列表
*
* @return 结果
*/
@PostMapping("/system/dept/selectDeptList")
public R<List<SysDept>> selectDeptList(@RequestBody SysDept sysDept);
} }

View File

@ -5,7 +5,7 @@ import org.slf4j.LoggerFactory;
import org.springframework.cloud.openfeign.FallbackFactory; import org.springframework.cloud.openfeign.FallbackFactory;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import com.tcctyn.common.core.domain.R; import com.tcctyn.common.core.web.domain.R;
import com.tcctyn.system.api.RemoteFileService; import com.tcctyn.system.api.RemoteFileService;
import com.tcctyn.system.api.domain.SysFile; import com.tcctyn.system.api.domain.SysFile;

View File

@ -4,7 +4,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.cloud.openfeign.FallbackFactory; import org.springframework.cloud.openfeign.FallbackFactory;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import com.tcctyn.common.core.domain.R; import com.tcctyn.common.core.web.domain.R;
import com.tcctyn.system.api.RemoteLogService; import com.tcctyn.system.api.RemoteLogService;
import com.tcctyn.system.api.domain.SysLogininfor; import com.tcctyn.system.api.domain.SysLogininfor;
import com.tcctyn.system.api.domain.SysOperLog; import com.tcctyn.system.api.domain.SysOperLog;

View File

@ -1,14 +1,17 @@
package com.tcctyn.system.api.factory; package com.tcctyn.system.api.factory;
import com.tcctyn.system.api.domain.SysDept;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.cloud.openfeign.FallbackFactory; import org.springframework.cloud.openfeign.FallbackFactory;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import com.tcctyn.common.core.domain.R; import com.tcctyn.common.core.web.domain.R;
import com.tcctyn.system.api.RemoteUserService; import com.tcctyn.system.api.RemoteUserService;
import com.tcctyn.system.api.domain.SysUser; import com.tcctyn.system.api.domain.SysUser;
import com.tcctyn.system.api.model.LoginUser; import com.tcctyn.system.api.model.LoginUser;
import java.util.List;
/** /**
* 用户服务降级处理 * 用户服务降级处理
* *
@ -42,6 +45,31 @@ public class RemoteUserFallbackFactory implements FallbackFactory<RemoteUserServ
{ {
return R.fail("记录用户登录信息失败:" + throwable.getMessage()); return R.fail("记录用户登录信息失败:" + throwable.getMessage());
} }
@Override
public R<SysUser> selectUserById(Long userId) {
return R.fail("获取用户信息失败:" + throwable.getMessage());
}
@Override
public R<List<SysUser>> selectUserList(SysUser sysUser) {
return R.fail("获取用户信息列表失败:" + throwable.getMessage());
}
@Override
public R<List<SysUser>> selectUserByRegionIdList(Long regionId) {
return R.fail("获取用户区域id失败:" + throwable.getMessage());
}
@Override
public R<SysDept> selectDeptById(Long deptId) {
return R.fail("获取部门信息失败:" + throwable.getMessage());
}
@Override
public R<List<SysDept>> selectDeptList(SysDept sysDept) {
return R.fail("获取部门信息列表失败:" + throwable.getMessage());
}
}; };
} }
} }

View File

@ -9,7 +9,7 @@ import org.springframework.web.bind.annotation.RestController;
import com.tcctyn.auth.form.LoginBody; import com.tcctyn.auth.form.LoginBody;
import com.tcctyn.auth.form.RegisterBody; import com.tcctyn.auth.form.RegisterBody;
import com.tcctyn.auth.service.SysLoginService; import com.tcctyn.auth.service.SysLoginService;
import com.tcctyn.common.core.domain.R; import com.tcctyn.common.core.web.domain.R;
import com.tcctyn.common.core.utils.JwtUtils; import com.tcctyn.common.core.utils.JwtUtils;
import com.tcctyn.common.core.utils.StringUtils; import com.tcctyn.common.core.utils.StringUtils;
import com.tcctyn.common.security.auth.AuthUtil; import com.tcctyn.common.security.auth.AuthUtil;

View File

@ -6,7 +6,7 @@ import com.tcctyn.common.core.constant.CacheConstants;
import com.tcctyn.common.core.constant.Constants; import com.tcctyn.common.core.constant.Constants;
import com.tcctyn.common.core.constant.SecurityConstants; import com.tcctyn.common.core.constant.SecurityConstants;
import com.tcctyn.common.core.constant.UserConstants; import com.tcctyn.common.core.constant.UserConstants;
import com.tcctyn.common.core.domain.R; import com.tcctyn.common.core.web.domain.R;
import com.tcctyn.common.core.enums.UserStatus; import com.tcctyn.common.core.enums.UserStatus;
import com.tcctyn.common.core.exception.ServiceException; import com.tcctyn.common.core.exception.ServiceException;
import com.tcctyn.common.core.text.Convert; import com.tcctyn.common.core.text.Convert;

View File

@ -107,6 +107,38 @@
<artifactId>javax.servlet-api</artifactId> <artifactId>javax.servlet-api</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-annotation</artifactId>
<version>${mybatis-plus-annotation.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.eclipse.paho</groupId>
<artifactId>org.eclipse.paho.client.mqttv3</artifactId>
<version>${org.eclipse.paho.client.mqttv3.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>${hutool-all.version}</version>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@ -0,0 +1,15 @@
package com.tcctyn.common.core.annotation;
import java.lang.annotation.*;
/**
* 匿名访问不鉴权注解
*
* @author tcctyn
*/
@Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Anonymous
{
}

View File

@ -0,0 +1,29 @@
package com.tcctyn.common.core.annotation;
import java.lang.annotation.*;
/**
* 数据权限过滤注解
*
* @author tcctyn
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DataScope
{
/**
* 部门表的别名
*/
public String deptAlias() default "";
/**
* 用户表的别名
*/
public String userAlias() default "";
/**
* 权限字符用于多个角色匹配符合要求的权限默认根据权限注解@ss获取多个权限用逗号分隔开来
*/
public String permission() default "";
}

View File

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

View File

@ -1,13 +1,14 @@
package com.tcctyn.common.core.annotation; package com.tcctyn.common.core.annotation;
import com.tcctyn.common.core.utils.poi.ExcelHandlerAdapter;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.IndexedColors;
import java.lang.annotation.ElementType; import java.lang.annotation.ElementType;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
import java.math.BigDecimal; import java.math.BigDecimal;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.IndexedColors;
import com.tcctyn.common.core.utils.poi.ExcelHandlerAdapter;
/** /**
* 自定义导出Excel数据注解 * 自定义导出Excel数据注解
@ -33,6 +34,11 @@ public @interface Excel
*/ */
public String dateFormat() default ""; public String dateFormat() default "";
/**
* 如果是字典类型请设置字典的type值 (: sys_user_sex)
*/
public String dictType() default "";
/** /**
* 读取内容转表达式 (: 0=,1=,2=未知) * 读取内容转表达式 (: 0=,1=,2=未知)
*/ */
@ -78,16 +84,16 @@ public @interface Excel
*/ */
public String prompt() default ""; public String prompt() default "";
/**
* 是否允许内容换行
*/
public boolean wrapText() default false;
/** /**
* 设置只能选择不能输入的列内容. * 设置只能选择不能输入的列内容.
*/ */
public String[] combo() default {}; public String[] combo() default {};
/**
* 是否从字典读数据到combo,默认不读取,如读取需要设置dictType注解.
*/
public boolean comboReadDict() default false;
/** /**
* 是否需要纵向合并单元格,应对需求:含有list集合单元格) * 是否需要纵向合并单元格,应对需求:含有list集合单元格)
*/ */
@ -109,7 +115,7 @@ public @interface Excel
public boolean isStatistics() default false; public boolean isStatistics() default false;
/** /**
* 导出类型0数字 1字符串 * 导出类型0数字 1字符串 2图片
*/ */
public ColumnType cellType() default ColumnType.STRING; public ColumnType cellType() default ColumnType.STRING;

View File

@ -14,5 +14,5 @@ import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
public @interface Excels public @interface Excels
{ {
Excel[] value(); public Excel[] value();
} }

View File

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

View File

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

View File

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

View File

@ -0,0 +1,25 @@
package com.tcctyn.common.core.annotation;
import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.tcctyn.common.core.config.serializer.SensitiveJsonSerializer;
import com.tcctyn.common.core.enums.DesensitizedType;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 数据脱敏注解
*
* @author tcctyn
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@JacksonAnnotationsInside
@JsonSerialize(using = SensitiveJsonSerializer.class)
public @interface Sensitive
{
DesensitizedType desensitizedType();
}

View File

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

View File

@ -0,0 +1,68 @@
package com.tcctyn.common.core.config.serializer;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.ContextualSerializer;
import com.tcctyn.common.core.annotation.Sensitive;
import com.tcctyn.common.core.web.domain.model.LoginUser;
import com.tcctyn.common.core.enums.DesensitizedType;
import com.tcctyn.common.core.utils.SecurityUtils;
import java.io.IOException;
import java.util.Objects;
/**
* 数据脱敏序列化过滤
*
* @author tcctyn
*/
public class SensitiveJsonSerializer extends JsonSerializer<String> implements ContextualSerializer
{
private DesensitizedType desensitizedType;
@Override
public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException
{
if (desensitization())
{
gen.writeString(desensitizedType.desensitizer().apply(value));
}
else
{
gen.writeString(value);
}
}
@Override
public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property)
throws JsonMappingException
{
Sensitive annotation = property.getAnnotation(Sensitive.class);
if (Objects.nonNull(annotation) && Objects.equals(String.class, property.getType().getRawClass()))
{
this.desensitizedType = annotation.desensitizedType();
return this;
}
return prov.findValueSerializer(property.getType(), property);
}
/**
* 是否需要脱敏处理
*/
private boolean desensitization()
{
try
{
LoginUser securityUser = SecurityUtils.getLoginUser();
// 管理员不脱敏
return !securityUser.getUser().isAdmin();
}
catch (Exception e)
{
return true;
}
}
}

View File

@ -1,12 +1,47 @@
package com.tcctyn.common.core.constant; package com.tcctyn.common.core.constant;
/** /**
* 缓存常量信息 * 缓存的key 常量
* *
* @author tcctyn * @author tcctyn
*/ */
public class CacheConstants public class CacheConstants
{ {
/**
* 登录用户 redis key
*/
public static final String LOGIN_TOKEN_KEY = "login_tokens:";
/**
* 验证码 redis key
*/
public static final String CAPTCHA_CODE_KEY = "captcha_codes:";
/**
* 参数管理 cache key
*/
public static final String SYS_CONFIG_KEY = "sys_config:";
/**
* 字典管理 cache key
*/
public static final String SYS_DICT_KEY = "sys_dict:";
/**
* 防重提交 redis key
*/
public static final String REPEAT_SUBMIT_KEY = "repeat_submit:";
/**
* 限流 redis key
*/
public static final String RATE_LIMIT_KEY = "rate_limit:";
/**
* 登录账户密码错误次数 redis key
*/
public static final String PWD_ERR_CNT_KEY = "pwd_err_cnt:";
/** /**
* 缓存有效期默认720分钟 * 缓存有效期默认720分钟
*/ */
@ -27,30 +62,6 @@ public class CacheConstants
*/ */
public final static long PASSWORD_LOCK_TIME = 10; public final static long PASSWORD_LOCK_TIME = 10;
/**
* 权限缓存前缀
*/
public final static String LOGIN_TOKEN_KEY = "login_tokens:";
/**
* 验证码 redis key
*/
public static final String CAPTCHA_CODE_KEY = "captcha_codes:";
/**
* 参数管理 cache key
*/
public static final String SYS_CONFIG_KEY = "sys_config:";
/**
* 字典管理 cache key
*/
public static final String SYS_DICT_KEY = "sys_dict:";
/**
* 登录账户密码错误次数 redis key
*/
public static final String PWD_ERR_CNT_KEY = "pwd_err_cnt:";
/** /**
* 登录IP黑名单 cache key * 登录IP黑名单 cache key

View File

@ -1,8 +1,12 @@
package com.tcctyn.common.core.constant; package com.tcctyn.common.core.constant;
import io.jsonwebtoken.Claims;
import java.util.Locale;
/** /**
* 通用常量信息 * 通用常量信息
* *
* @author tcctyn * @author tcctyn
*/ */
public class Constants public class Constants
@ -17,26 +21,16 @@ public class Constants
*/ */
public static final String GBK = "GBK"; public static final String GBK = "GBK";
/**
* 系统语言
*/
public static final Locale DEFAULT_LOCALE = Locale.SIMPLIFIED_CHINESE;
/** /**
* www主域 * www主域
*/ */
public static final String WWW = "www."; public static final String WWW = "www.";
/**
* 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请求 * http请求
*/ */
@ -48,24 +42,14 @@ public class Constants
public static final String HTTPS = "https://"; public static final String HTTPS = "https://";
/** /**
* 成功标记 * 通用成功标识
*/ */
public static final Integer SUCCESS = 200; public static final String SUCCESS = "0";
/** /**
* 失败标记 * 通用失败标识
*/ */
public static final Integer FAIL = 500; public static final String FAIL = "1";
/**
* 登录成功状态
*/
public static final String LOGIN_SUCCESS_STATUS = "0";
/**
* 登录失败状态
*/
public static final String LOGIN_FAIL_STATUS = "1";
/** /**
* 登录成功 * 登录成功
@ -88,35 +72,91 @@ public class Constants
public static final String LOGIN_FAIL = "Error"; public static final String LOGIN_FAIL = "Error";
/** /**
* 当前记录起始索引 * 所有权限标识
*/ */
public static final String PAGE_NUM = "pageNum"; public static final String ALL_PERMISSION = "*:*:*";
/** /**
* 每页显示记录数 * 管理员角色权限标识
*/ */
public static final String PAGE_SIZE = "pageSize"; public static final String SUPER_ADMIN = "admin";
/** /**
* 排序列 * 角色权限分隔符
*/ */
public static final String ORDER_BY_COLUMN = "orderByColumn"; public static final String ROLE_DELIMETER = ",";
/** /**
* 排序的方向 "desc" 或者 "asc". * 权限标识分隔符
*/ */
public static final String IS_ASC = "isAsc"; public static final String PERMISSION_DELIMETER = ",";
/** /**
* 验证码有效期分钟 * 验证码有效期分钟
*/ */
public static final long CAPTCHA_EXPIRATION = 2; public static final long CAPTCHA_EXPIRATION = 2;
/**
* 令牌
*/
public static final String TOKEN = "token";
/**
* 令牌前缀
*/
public static final String TOKEN_PREFIX = "Bearer ";
/**
* 令牌前缀
*/
public static final String LOGIN_USER_KEY = "login_user_key";
/**
* 用户ID
*/
public static final String JWT_USERID = "userid";
/**
* 用户名称
*/
public static final String JWT_USERNAME = Claims.SUBJECT;
/**
* 用户头像
*/
public static final String JWT_AVATAR = "avatar";
/**
* 创建时间
*/
public static final String JWT_CREATED = "created";
/**
* 用户权限
*/
public static final String JWT_AUTHORITIES = "authorities";
/** /**
* 资源映射路径 前缀 * 资源映射路径 前缀
*/ */
public static final String RESOURCE_PREFIX = "/profile"; public static final String RESOURCE_PREFIX = "/profile";
/**
* RMI 远程方法调用
*/
public static final String LOOKUP_RMI = "rmi:";
/**
* LDAP 远程方法调用
*/
public static final String LOOKUP_LDAP = "ldap:";
/**
* LDAPS 远程方法调用
*/
public static final String LOOKUP_LDAPS = "ldaps:";
/** /**
* 自动识别json对象白名单配置仅允许解析的包名范围越小越安全 * 自动识别json对象白名单配置仅允许解析的包名范围越小越安全
*/ */
@ -125,11 +165,21 @@ public class Constants
/** /**
* 定时任务白名单配置仅允许访问的包名如其他需要可以自行添加 * 定时任务白名单配置仅允许访问的包名如其他需要可以自行添加
*/ */
public static final String[] JOB_WHITELIST_STR = { "com.tcctyn.job.task" }; public static final String[] JOB_WHITELIST_STR = { "com.tcctyn.quartz.task" };
/**
* 登录成功状态
*/
public static final String LOGIN_SUCCESS_STATUS = "0";
/**
* 登录失败状态
*/
public static final String LOGIN_FAIL_STATUS = "1";
/** /**
* 定时任务违规的字符 * 定时任务违规的字符
*/ */
public static final String[] JOB_ERROR_STR = { "java.net.URL", "javax.naming.InitialContext", "org.yaml.snakeyaml", public static final String[] JOB_ERROR_STR = { "java.net.URL", "javax.naming.InitialContext", "org.yaml.snakeyaml",
"org.springframework", "org.apache", "com.tcctyn.common.core.utils.file" }; "org.springframework", "org.apache", "com.tcctyn.common.utils.file", "com.tcctyn.common.config", "com.tcctyn.generator" };
} }

View File

@ -59,7 +59,7 @@ public class GenConstants
public static final String[] BASE_ENTITY = { "createBy", "createTime", "updateBy", "updateTime", "remark" }; public static final String[] BASE_ENTITY = { "createBy", "createTime", "updateBy", "updateTime", "remark" };
/** Tree基类字段 */ /** Tree基类字段 */
public static final String[] TREE_ENTITY = { "parentName", "parentId", "orderNum", "ancestors" }; public static final String[] TREE_ENTITY = { "parentName", "parentId", "orderNum", "ancestors", "children" };
/** 文本框 */ /** 文本框 */
public static final String HTML_INPUT = "input"; public static final String HTML_INPUT = "input";

View File

@ -0,0 +1,9 @@
package com.tcctyn.common.core.constant;
/**
* 地区常量
*/
public interface RegionConstants {
String DIVISION_COMMA = ",";
}

View File

@ -2,7 +2,7 @@ package com.tcctyn.common.core.constant;
/** /**
* 用户常量信息 * 用户常量信息
* *
* @author tcctyn * @author tcctyn
*/ */
public class UserConstants public class UserConstants

View File

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

View File

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

View File

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

View File

@ -0,0 +1,60 @@
package com.tcctyn.common.core.enums;
import com.tcctyn.common.core.utils.DesensitizedUtil;
import java.util.function.Function;
/**
* 脱敏类型
*
* @author tcctyn
*/
public enum DesensitizedType
{
/**
* 姓名第2位星号替换
*/
USERNAME(s -> s.replaceAll("(\\S)\\S(\\S*)", "$1*$2")),
/**
* 密码全部字符都用*代替
*/
PASSWORD(DesensitizedUtil::password),
/**
* 身份证中间10位星号替换
*/
ID_CARD(s -> s.replaceAll("(\\d{4})\\d{10}(\\d{4})", "$1** **** ****$2")),
/**
* 手机号中间4位星号替换
*/
PHONE(s -> s.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2")),
/**
* 电子邮箱仅显示第一个字母和@后面的地址显示其他星号替换
*/
EMAIL(s -> s.replaceAll("(^.)[^@]*(@.*$)", "$1****$2")),
/**
* 银行卡号保留最后4位其他星号替换
*/
BANK_CARD(s -> s.replaceAll("\\d{15}(\\d{3})", "**** **** **** **** $1")),
/**
* 车牌号码包含普通车辆新能源车辆
*/
CAR_LICENSE(DesensitizedUtil::carLicense);
private final Function<String, String> desensitizer;
DesensitizedType(Function<String, String> desensitizer)
{
this.desensitizer = desensitizer;
}
public Function<String, String> desensitizer()
{
return desensitizer;
}
}

View File

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

View File

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

View File

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

View File

@ -1,5 +1,8 @@
package com.tcctyn.common.core.exception.base; package com.tcctyn.common.core.exception.base;
import com.tcctyn.common.core.utils.MessageUtils;
import com.tcctyn.common.core.utils.StringUtils;
/** /**
* 基础异常 * 基础异常
* *
@ -57,6 +60,21 @@ public class BaseException extends RuntimeException
this(null, null, null, defaultMessage); this(null, null, null, defaultMessage);
} }
@Override
public String getMessage()
{
String message = null;
if (!StringUtils.isEmpty(code))
{
message = MessageUtils.message(code, args);
}
if (message == null)
{
message = defaultMessage;
}
return message;
}
public String getModule() public String getModule()
{ {
return module; return module;

View File

@ -11,9 +11,9 @@ public class FileException extends BaseException
{ {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
public FileException(String code, Object[] args, String msg) public FileException(String code, Object[] args)
{ {
super("file", code, args, msg); super("file", code, args, null);
} }
} }

View File

@ -11,6 +11,6 @@ public class FileNameLengthLimitExceededException extends FileException
public FileNameLengthLimitExceededException(int defaultFileNameLength) public FileNameLengthLimitExceededException(int defaultFileNameLength)
{ {
super("upload.filename.exceed.length", new Object[] { defaultFileNameLength }, "the filename is too long"); super("upload.filename.exceed.length", new Object[] { defaultFileNameLength });
} }
} }

View File

@ -11,6 +11,6 @@ public class FileSizeLimitExceededException extends FileException
public FileSizeLimitExceededException(long defaultMaxSize) public FileSizeLimitExceededException(long defaultMaxSize)
{ {
super("upload.exceed.maxSize", new Object[] { defaultMaxSize }, "the filesize is too large"); super("upload.exceed.maxSize", new Object[] { defaultMaxSize });
} }
} }

View File

@ -17,7 +17,7 @@ public class InvalidExtensionException extends FileUploadException
public InvalidExtensionException(String[] allowedExtension, String extension, String filename) public InvalidExtensionException(String[] allowedExtension, String extension, String filename)
{ {
super("filename : [" + filename + "], extension : [" + extension + "], allowed extension : [" + Arrays.toString(allowedExtension) + "]"); super("文件[" + filename + "]后缀[" + extension + "]不正确,请上传" + Arrays.toString(allowedExtension) + "格式");
this.allowedExtension = allowedExtension; this.allowedExtension = allowedExtension;
this.extension = extension; this.extension = extension;
this.filename = filename; this.filename = filename;
@ -67,7 +67,7 @@ public class InvalidExtensionException extends FileUploadException
super(allowedExtension, extension, filename); super(allowedExtension, extension, filename);
} }
} }
public static class InvalidVideoExtensionException extends InvalidExtensionException public static class InvalidVideoExtensionException extends InvalidExtensionException
{ {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;

View File

@ -0,0 +1,16 @@
package com.tcctyn.common.core.exception.user;
/**
* 黑名单IP异常类
*
* @author tcctyn
*/
public class BlackListException extends UserException
{
private static final long serialVersionUID = 1L;
public BlackListException()
{
super("login.blocked", null);
}
}

View File

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

View File

@ -0,0 +1,16 @@
package com.tcctyn.common.core.exception.user;
/**
* 用户不存在异常类
*
* @author tcctyn
*/
public class UserNotExistsException extends UserException
{
private static final long serialVersionUID = 1L;
public UserNotExistsException()
{
super("user.not.exists", null);
}
}

View File

@ -0,0 +1,16 @@
package com.tcctyn.common.core.exception.user;
/**
* 用户错误最大次数异常类
*
* @author tcctyn
*/
public class UserPasswordRetryLimitExceedException extends UserException
{
private static final long serialVersionUID = 1L;
public UserPasswordRetryLimitExceedException(int retryLimitCount, int lockTime)
{
super("user.password.retry.limit.exceed", new Object[] { retryLimitCount, lockTime });
}
}

View File

@ -0,0 +1,24 @@
package com.tcctyn.common.core.filter;
import com.alibaba.fastjson2.filter.SimplePropertyPreFilter;
/**
* 排除JSON敏感属性
*
* @author tcctyn
*/
public class PropertyPreExcludeFilter extends SimplePropertyPreFilter
{
public PropertyPreExcludeFilter()
{
}
public PropertyPreExcludeFilter addExcludes(String... filters)
{
for (int i = 0; i < filters.length; i++)
{
this.getExcludes().add(filters[i]);
}
return this;
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,8 +1,9 @@
package com.tcctyn.common.core.text; package com.tcctyn.common.core.text;
import com.tcctyn.common.core.utils.StringUtils;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import com.tcctyn.common.core.utils.StringUtils;
/** /**
* 字符集工具类 * 字符集工具类

View File

@ -1,5 +1,8 @@
package com.tcctyn.common.core.text; package com.tcctyn.common.core.text;
import com.tcctyn.common.core.utils.StringUtils;
import org.apache.commons.lang3.ArrayUtils;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.math.BigInteger; import java.math.BigInteger;
import java.math.RoundingMode; import java.math.RoundingMode;
@ -7,11 +10,10 @@ import java.nio.ByteBuffer;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.text.NumberFormat; import java.text.NumberFormat;
import java.util.Set; import java.util.Set;
import com.tcctyn.common.core.utils.StringUtils;
/** /**
* 类型转换器 * 类型转换器
* *
* @author tcctyn * @author tcctyn
*/ */
public class Convert public class Convert
@ -20,7 +22,7 @@ public class Convert
* 转换为字符串<br> * 转换为字符串<br>
* 如果给定的值为null或者转换失败返回默认值<br> * 如果给定的值为null或者转换失败返回默认值<br>
* 转换失败不会报错 * 转换失败不会报错
* *
* @param value 被转换的值 * @param value 被转换的值
* @param defaultValue 转换错误时的默认值 * @param defaultValue 转换错误时的默认值
* @return 结果 * @return 结果
@ -42,7 +44,7 @@ public class Convert
* 转换为字符串<br> * 转换为字符串<br>
* 如果给定的值为<code>null</code>或者转换失败返回默认值<code>null</code><br> * 如果给定的值为<code>null</code>或者转换失败返回默认值<code>null</code><br>
* 转换失败不会报错 * 转换失败不会报错
* *
* @param value 被转换的值 * @param value 被转换的值
* @return 结果 * @return 结果
*/ */
@ -55,7 +57,7 @@ public class Convert
* 转换为字符<br> * 转换为字符<br>
* 如果给定的值为null或者转换失败返回默认值<br> * 如果给定的值为null或者转换失败返回默认值<br>
* 转换失败不会报错 * 转换失败不会报错
* *
* @param value 被转换的值 * @param value 被转换的值
* @param defaultValue 转换错误时的默认值 * @param defaultValue 转换错误时的默认值
* @return 结果 * @return 结果
@ -79,7 +81,7 @@ public class Convert
* 转换为字符<br> * 转换为字符<br>
* 如果给定的值为<code>null</code>或者转换失败返回默认值<code>null</code><br> * 如果给定的值为<code>null</code>或者转换失败返回默认值<code>null</code><br>
* 转换失败不会报错 * 转换失败不会报错
* *
* @param value 被转换的值 * @param value 被转换的值
* @return 结果 * @return 结果
*/ */
@ -92,7 +94,7 @@ public class Convert
* 转换为byte<br> * 转换为byte<br>
* 如果给定的值为<code>null</code>或者转换失败返回默认值<br> * 如果给定的值为<code>null</code>或者转换失败返回默认值<br>
* 转换失败不会报错 * 转换失败不会报错
* *
* @param value 被转换的值 * @param value 被转换的值
* @param defaultValue 转换错误时的默认值 * @param defaultValue 转换错误时的默认值
* @return 结果 * @return 结果
@ -130,7 +132,7 @@ public class Convert
* 转换为byte<br> * 转换为byte<br>
* 如果给定的值为<code>null</code>或者转换失败返回默认值<code>null</code><br> * 如果给定的值为<code>null</code>或者转换失败返回默认值<code>null</code><br>
* 转换失败不会报错 * 转换失败不会报错
* *
* @param value 被转换的值 * @param value 被转换的值
* @return 结果 * @return 结果
*/ */
@ -143,7 +145,7 @@ public class Convert
* 转换为Short<br> * 转换为Short<br>
* 如果给定的值为<code>null</code>或者转换失败返回默认值<br> * 如果给定的值为<code>null</code>或者转换失败返回默认值<br>
* 转换失败不会报错 * 转换失败不会报错
* *
* @param value 被转换的值 * @param value 被转换的值
* @param defaultValue 转换错误时的默认值 * @param defaultValue 转换错误时的默认值
* @return 结果 * @return 结果
@ -181,7 +183,7 @@ public class Convert
* 转换为Short<br> * 转换为Short<br>
* 如果给定的值为<code>null</code>或者转换失败返回默认值<code>null</code><br> * 如果给定的值为<code>null</code>或者转换失败返回默认值<code>null</code><br>
* 转换失败不会报错 * 转换失败不会报错
* *
* @param value 被转换的值 * @param value 被转换的值
* @return 结果 * @return 结果
*/ */
@ -194,7 +196,7 @@ public class Convert
* 转换为Number<br> * 转换为Number<br>
* 如果给定的值为空或者转换失败返回默认值<br> * 如果给定的值为空或者转换失败返回默认值<br>
* 转换失败不会报错 * 转换失败不会报错
* *
* @param value 被转换的值 * @param value 被转换的值
* @param defaultValue 转换错误时的默认值 * @param defaultValue 转换错误时的默认值
* @return 结果 * @return 结果
@ -228,7 +230,7 @@ public class Convert
* 转换为Number<br> * 转换为Number<br>
* 如果给定的值为空或者转换失败返回默认值<code>null</code><br> * 如果给定的值为空或者转换失败返回默认值<code>null</code><br>
* 转换失败不会报错 * 转换失败不会报错
* *
* @param value 被转换的值 * @param value 被转换的值
* @return 结果 * @return 结果
*/ */
@ -241,7 +243,7 @@ public class Convert
* 转换为int<br> * 转换为int<br>
* 如果给定的值为空或者转换失败返回默认值<br> * 如果给定的值为空或者转换失败返回默认值<br>
* 转换失败不会报错 * 转换失败不会报错
* *
* @param value 被转换的值 * @param value 被转换的值
* @param defaultValue 转换错误时的默认值 * @param defaultValue 转换错误时的默认值
* @return 结果 * @return 结果
@ -279,7 +281,7 @@ public class Convert
* 转换为int<br> * 转换为int<br>
* 如果给定的值为<code>null</code>或者转换失败返回默认值<code>null</code><br> * 如果给定的值为<code>null</code>或者转换失败返回默认值<code>null</code><br>
* 转换失败不会报错 * 转换失败不会报错
* *
* @param value 被转换的值 * @param value 被转换的值
* @return 结果 * @return 结果
*/ */
@ -290,7 +292,7 @@ public class Convert
/** /**
* 转换为Integer数组<br> * 转换为Integer数组<br>
* *
* @param str 被转换的值 * @param str 被转换的值
* @return 结果 * @return 结果
*/ */
@ -301,7 +303,7 @@ public class Convert
/** /**
* 转换为Long数组<br> * 转换为Long数组<br>
* *
* @param str 被转换的值 * @param str 被转换的值
* @return 结果 * @return 结果
*/ */
@ -312,9 +314,9 @@ public class Convert
/** /**
* 转换为Integer数组<br> * 转换为Integer数组<br>
* *
* @param split 分隔符 * @param split 分隔符
* @param str 被转换的值 * @param split 被转换的值
* @return 结果 * @return 结果
*/ */
public static Integer[] toIntArray(String split, String str) public static Integer[] toIntArray(String split, String str)
@ -335,7 +337,7 @@ public class Convert
/** /**
* 转换为Long数组<br> * 转换为Long数组<br>
* *
* @param split 分隔符 * @param split 分隔符
* @param str 被转换的值 * @param str 被转换的值
* @return 结果 * @return 结果
@ -358,7 +360,7 @@ public class Convert
/** /**
* 转换为String数组<br> * 转换为String数组<br>
* *
* @param str 被转换的值 * @param str 被转换的值
* @return 结果 * @return 结果
*/ */
@ -373,9 +375,9 @@ public class Convert
/** /**
* 转换为String数组<br> * 转换为String数组<br>
* *
* @param split 分隔符 * @param split 分隔符
* @param str 被转换的值 * @param split 被转换的值
* @return 结果 * @return 结果
*/ */
public static String[] toStrArray(String split, String str) public static String[] toStrArray(String split, String str)
@ -387,7 +389,7 @@ public class Convert
* 转换为long<br> * 转换为long<br>
* 如果给定的值为空或者转换失败返回默认值<br> * 如果给定的值为空或者转换失败返回默认值<br>
* 转换失败不会报错 * 转换失败不会报错
* *
* @param value 被转换的值 * @param value 被转换的值
* @param defaultValue 转换错误时的默认值 * @param defaultValue 转换错误时的默认值
* @return 结果 * @return 结果
@ -426,7 +428,7 @@ public class Convert
* 转换为long<br> * 转换为long<br>
* 如果给定的值为<code>null</code>或者转换失败返回默认值<code>null</code><br> * 如果给定的值为<code>null</code>或者转换失败返回默认值<code>null</code><br>
* 转换失败不会报错 * 转换失败不会报错
* *
* @param value 被转换的值 * @param value 被转换的值
* @return 结果 * @return 结果
*/ */
@ -439,7 +441,7 @@ public class Convert
* 转换为double<br> * 转换为double<br>
* 如果给定的值为空或者转换失败返回默认值<br> * 如果给定的值为空或者转换失败返回默认值<br>
* 转换失败不会报错 * 转换失败不会报错
* *
* @param value 被转换的值 * @param value 被转换的值
* @param defaultValue 转换错误时的默认值 * @param defaultValue 转换错误时的默认值
* @return 结果 * @return 结果
@ -478,7 +480,7 @@ public class Convert
* 转换为double<br> * 转换为double<br>
* 如果给定的值为空或者转换失败返回默认值<code>null</code><br> * 如果给定的值为空或者转换失败返回默认值<code>null</code><br>
* 转换失败不会报错 * 转换失败不会报错
* *
* @param value 被转换的值 * @param value 被转换的值
* @return 结果 * @return 结果
*/ */
@ -491,7 +493,7 @@ public class Convert
* 转换为Float<br> * 转换为Float<br>
* 如果给定的值为空或者转换失败返回默认值<br> * 如果给定的值为空或者转换失败返回默认值<br>
* 转换失败不会报错 * 转换失败不会报错
* *
* @param value 被转换的值 * @param value 被转换的值
* @param defaultValue 转换错误时的默认值 * @param defaultValue 转换错误时的默认值
* @return 结果 * @return 结果
@ -529,7 +531,7 @@ public class Convert
* 转换为Float<br> * 转换为Float<br>
* 如果给定的值为空或者转换失败返回默认值<code>null</code><br> * 如果给定的值为空或者转换失败返回默认值<code>null</code><br>
* 转换失败不会报错 * 转换失败不会报错
* *
* @param value 被转换的值 * @param value 被转换的值
* @return 结果 * @return 结果
*/ */
@ -540,7 +542,7 @@ public class Convert
/** /**
* 转换为boolean<br> * 转换为boolean<br>
* String支持的值为truefalseyesokno10, 如果给定的值为空或者转换失败返回默认值<br> * String支持的值为truefalseyesokno1,0 如果给定的值为空或者转换失败返回默认值<br>
* 转换失败不会报错 * 转换失败不会报错
* *
* @param value 被转换的值 * @param value 被转换的值
@ -569,12 +571,10 @@ public class Convert
case "yes": case "yes":
case "ok": case "ok":
case "1": case "1":
case "":
return true; return true;
case "false": case "false":
case "no": case "no":
case "0": case "0":
case "":
return false; return false;
default: default:
return defaultValue; return defaultValue;
@ -585,7 +585,7 @@ public class Convert
* 转换为boolean<br> * 转换为boolean<br>
* 如果给定的值为空或者转换失败返回默认值<code>null</code><br> * 如果给定的值为空或者转换失败返回默认值<code>null</code><br>
* 转换失败不会报错 * 转换失败不会报错
* *
* @param value 被转换的值 * @param value 被转换的值
* @return 结果 * @return 结果
*/ */
@ -597,7 +597,7 @@ public class Convert
/** /**
* 转换为Enum对象<br> * 转换为Enum对象<br>
* 如果给定的值为空或者转换失败返回默认值<br> * 如果给定的值为空或者转换失败返回默认值<br>
* *
* @param clazz Enum的Class * @param clazz Enum的Class
* @param value * @param value
* @param defaultValue 默认值 * @param defaultValue 默认值
@ -633,7 +633,7 @@ public class Convert
/** /**
* 转换为Enum对象<br> * 转换为Enum对象<br>
* 如果给定的值为空或者转换失败返回默认值<code>null</code><br> * 如果给定的值为空或者转换失败返回默认值<code>null</code><br>
* *
* @param clazz Enum的Class * @param clazz Enum的Class
* @param value * @param value
* @return Enum * @return Enum
@ -647,7 +647,7 @@ public class Convert
* 转换为BigInteger<br> * 转换为BigInteger<br>
* 如果给定的值为空或者转换失败返回默认值<br> * 如果给定的值为空或者转换失败返回默认值<br>
* 转换失败不会报错 * 转换失败不会报错
* *
* @param value 被转换的值 * @param value 被转换的值
* @param defaultValue 转换错误时的默认值 * @param defaultValue 转换错误时的默认值
* @return 结果 * @return 结果
@ -685,7 +685,7 @@ public class Convert
* 转换为BigInteger<br> * 转换为BigInteger<br>
* 如果给定的值为空或者转换失败返回默认值<code>null</code><br> * 如果给定的值为空或者转换失败返回默认值<code>null</code><br>
* 转换失败不会报错 * 转换失败不会报错
* *
* @param value 被转换的值 * @param value 被转换的值
* @return 结果 * @return 结果
*/ */
@ -698,7 +698,7 @@ public class Convert
* 转换为BigDecimal<br> * 转换为BigDecimal<br>
* 如果给定的值为空或者转换失败返回默认值<br> * 如果给定的值为空或者转换失败返回默认值<br>
* 转换失败不会报错 * 转换失败不会报错
* *
* @param value 被转换的值 * @param value 被转换的值
* @param defaultValue 转换错误时的默认值 * @param defaultValue 转换错误时的默认值
* @return 结果 * @return 结果
@ -744,7 +744,7 @@ public class Convert
* 转换为BigDecimal<br> * 转换为BigDecimal<br>
* 如果给定的值为空或者转换失败返回默认值<br> * 如果给定的值为空或者转换失败返回默认值<br>
* 转换失败不会报错 * 转换失败不会报错
* *
* @param value 被转换的值 * @param value 被转换的值
* @return 结果 * @return 结果
*/ */
@ -756,7 +756,7 @@ public class Convert
/** /**
* 将对象转为字符串<br> * 将对象转为字符串<br>
* 1Byte数组和ByteBuffer会被转换为对应字符串的数组 2对象数组会调用Arrays.toString方法 * 1Byte数组和ByteBuffer会被转换为对应字符串的数组 2对象数组会调用Arrays.toString方法
* *
* @param obj 对象 * @param obj 对象
* @return 字符串 * @return 字符串
*/ */
@ -768,7 +768,7 @@ public class Convert
/** /**
* 将对象转为字符串<br> * 将对象转为字符串<br>
* 1Byte数组和ByteBuffer会被转换为对应字符串的数组 2对象数组会调用Arrays.toString方法 * 1Byte数组和ByteBuffer会被转换为对应字符串的数组 2对象数组会调用Arrays.toString方法
* *
* @param obj 对象 * @param obj 对象
* @param charsetName 字符集 * @param charsetName 字符集
* @return 字符串 * @return 字符串
@ -781,7 +781,7 @@ public class Convert
/** /**
* 将对象转为字符串<br> * 将对象转为字符串<br>
* 1Byte数组和ByteBuffer会被转换为对应字符串的数组 2对象数组会调用Arrays.toString方法 * 1Byte数组和ByteBuffer会被转换为对应字符串的数组 2对象数组会调用Arrays.toString方法
* *
* @param obj 对象 * @param obj 对象
* @param charset 字符集 * @param charset 字符集
* @return 字符串 * @return 字符串
@ -797,23 +797,14 @@ public class Convert
{ {
return (String) obj; return (String) obj;
} }
else if (obj instanceof byte[] || obj instanceof Byte[]) else if (obj instanceof byte[])
{ {
if (obj instanceof byte[]) return str((byte[]) obj, charset);
{ }
return str((byte[]) obj, charset); else if (obj instanceof Byte[])
} {
else byte[] bytes = ArrayUtils.toPrimitive((Byte[]) obj);
{ return str(bytes, charset);
Byte[] bytes = (Byte[]) obj;
int length = bytes.length;
byte[] dest = new byte[length];
for (int i = 0; i < length; i++)
{
dest[i] = bytes[i];
}
return str(dest, charset);
}
} }
else if (obj instanceof ByteBuffer) else if (obj instanceof ByteBuffer)
{ {
@ -824,7 +815,7 @@ public class Convert
/** /**
* 将byte数组转为字符串 * 将byte数组转为字符串
* *
* @param bytes byte数组 * @param bytes byte数组
* @param charset 字符集 * @param charset 字符集
* @return 字符串 * @return 字符串
@ -836,7 +827,7 @@ public class Convert
/** /**
* 解码字节码 * 解码字节码
* *
* @param data 字符串 * @param data 字符串
* @param charset 字符集如果此字段为空则解码的结果取决于平台 * @param charset 字符集如果此字段为空则解码的结果取决于平台
* @return 解码后的字符串 * @return 解码后的字符串
@ -857,7 +848,7 @@ public class Convert
/** /**
* 将编码的byteBuffer数据转换为字符串 * 将编码的byteBuffer数据转换为字符串
* *
* @param data 数据 * @param data 数据
* @param charset 字符集如果为空使用当前系统字符集 * @param charset 字符集如果为空使用当前系统字符集
* @return 字符串 * @return 字符串
@ -874,7 +865,7 @@ public class Convert
/** /**
* 将编码的byteBuffer数据转换为字符串 * 将编码的byteBuffer数据转换为字符串
* *
* @param data 数据 * @param data 数据
* @param charset 字符集如果为空使用当前系统字符集 * @param charset 字符集如果为空使用当前系统字符集
* @return 字符串 * @return 字符串
@ -891,7 +882,7 @@ public class Convert
// ----------------------------------------------------------------------- 全角半角转换 // ----------------------------------------------------------------------- 全角半角转换
/** /**
* 半角转全角 * 半角转全角
* *
* @param input String. * @param input String.
* @return 全角字符串. * @return 全角字符串.
*/ */
@ -902,7 +893,7 @@ public class Convert
/** /**
* 半角转全角 * 半角转全角
* *
* @param input String * @param input String
* @param notConvertSet 不替换的字符集合 * @param notConvertSet 不替换的字符集合
* @return 全角字符串. * @return 全角字符串.
@ -933,7 +924,7 @@ public class Convert
/** /**
* 全角转半角 * 全角转半角
* *
* @param input String. * @param input String.
* @return 半角字符串 * @return 半角字符串
*/ */
@ -944,7 +935,7 @@ public class Convert
/** /**
* 替换全角为半角 * 替换全角为半角
* *
* @param text 文本 * @param text 文本
* @param notConvertSet 不替换的字符集合 * @param notConvertSet 不替换的字符集合
* @return 替换后的字符 * @return 替换后的字符
@ -969,12 +960,14 @@ public class Convert
c[i] = (char) (c[i] - 65248); c[i] = (char) (c[i] - 65248);
} }
} }
return new String(c); String returnString = new String(c);
return returnString;
} }
/** /**
* 数字金额大写转换 先写个完整的然后将如零拾替换成零 * 数字金额大写转换 先写个完整的然后将如零拾替换成零
* *
* @param n 数字 * @param n 数字
* @return 中文大写数字 * @return 中文大写数字
*/ */

View File

@ -0,0 +1,100 @@
package com.tcctyn.common.core.utils;
import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
public class AESUtil {
// 加密密码可以为任意字符串
private static final String password_str = "中华名族的伟大复兴¥¥¥";
/**
* AES加密字符串
*
* @param content 需要被加密的字符串
* @return 密文
*/
public static String encrypt(String content) {
try {
KeyGenerator kgen = KeyGenerator.getInstance("AES");// 创建AES的Key生产者
kgen.init(128, new SecureRandom(password_str.getBytes()));// 利用用户密码作为随机数初始化出
//加密没关系SecureRandom是生成安全随机数序列password.getBytes()是种子只要种子相同序列就一样所以解密只要有password就行
SecretKey secretKey = kgen.generateKey();// 根据用户密码生成一个密钥
byte[] enCodeFormat = secretKey.getEncoded();// 返回基本编码格式的密钥如果此密钥不支持编码则返回
SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");// 转换为AES专用密钥
Cipher cipher = Cipher.getInstance("AES");// 创建密码器
byte[] byteContent = content.getBytes("utf-8");
cipher.init(Cipher.ENCRYPT_MODE, key);// 初始化为加密模式的密码器
byte[] result = cipher.doFinal(byteContent);// 加密
return ParseSystemUtil.parseByte2HexStr(result); //加密后的16进制
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
}
return null;
}
/**
* 解密AES加密过的字符串
*
* @param hexStr AES加密过过的内容
* @return 明文
*/
public static byte[] decrypt(String hexStr) {
try {
// 16进制转换为2进制
byte[] content = ParseSystemUtil.parseHexStr2Byte(hexStr);
KeyGenerator kgen = KeyGenerator.getInstance("AES");// 创建AES的Key生产者
kgen.init(128, new SecureRandom(password_str.getBytes()));
SecretKey secretKey = kgen.generateKey();// 根据用户密码生成一个密钥
byte[] enCodeFormat = secretKey.getEncoded();// 返回基本编码格式的密钥
SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");// 转换为AES专用密钥
Cipher cipher = Cipher.getInstance("AES");// 创建密码器
cipher.init(Cipher.DECRYPT_MODE, key);// 初始化为解密模式的密码器
byte[] result = cipher.doFinal(content); //解密后的二进制
return result; // 明文
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
}
return null;
}
public static void main(String[] args) throws Exception {
String content = "密码1993";
String password = "中华名族的伟大复兴";
System.out.println("需要加密的内容:" + content);
String encrypt = encrypt(content);
System.out.println(encrypt);
// System.out.println("加密后的2进制密文" + new String(encrypt));
// String hexStr = ParseSystemUtil.parseByte2HexStr(encrypt);
// System.out.println("加密后的16进制密文:" + hexStr);
// byte[] byte2 = ParseSystemUtil.parseHexStr2Byte(hexStr);
// System.out.println("加密后的2进制密文" + new String(byte2));
byte[] decrypt = decrypt(encrypt);
System.out.println("解密后的内容:" + new String(decrypt, "utf-8"));
}
}

View File

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

View File

@ -1,29 +1,28 @@
package com.tcctyn.common.core.utils; package com.tcctyn.common.core.utils;
import org.apache.commons.lang3.time.DateFormatUtils;
import java.lang.management.ManagementFactory; import java.lang.management.ManagementFactory;
import java.text.ParseException; import java.text.ParseException;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.time.LocalDate; import java.time.*;
import java.time.LocalDateTime; import java.util.Calendar;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Date; import java.util.Date;
import org.apache.commons.lang3.time.DateFormatUtils;
/** /**
* 时间工具类 * 时间工具类
* *
* @author tcctyn * @author tcctyn
*/ */
public class DateUtils extends org.apache.commons.lang3.time.DateUtils public class DateUtils extends org.apache.commons.lang3.time.DateUtils {
{
public static String YYYY = "yyyy"; public static String YYYY = "yyyy";
public static String YYYY_MM = "yyyy-MM"; public static String YYYY_MM = "yyyy-MM";
public static String YYYY_MM_DD = "yyyy-MM-dd"; public static String YYYY_MM_DD = "yyyy-MM-dd";
public static final String YYYYMMDD = "yyyyMMdd";
public static String YYYYMMDDHHMMSS = "yyyyMMddHHmmss"; public static String YYYYMMDDHHMMSS = "yyyyMMddHHmmss";
public static String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss"; public static String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
@ -38,8 +37,7 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils
* *
* @return Date() 当前日期 * @return Date() 当前日期
*/ */
public static Date getNowDate() public static Date getNowDate() {
{
return new Date(); return new Date();
} }
@ -48,44 +46,43 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils
* *
* @return String * @return String
*/ */
public static String getDate() public static String getDate() {
{
return dateTimeNow(YYYY_MM_DD); return dateTimeNow(YYYY_MM_DD);
} }
public static final String getTime() /**
{ * 获取当前日期
*
* @return String
*/
public static String getDate(String dateType) {
return dateTimeNow(dateType);
}
public static final String getTime() {
return dateTimeNow(YYYY_MM_DD_HH_MM_SS); return dateTimeNow(YYYY_MM_DD_HH_MM_SS);
} }
public static final String dateTimeNow() public static final String dateTimeNow() {
{
return dateTimeNow(YYYYMMDDHHMMSS); return dateTimeNow(YYYYMMDDHHMMSS);
} }
public static final String dateTimeNow(final String format) public static final String dateTimeNow(final String format) {
{
return parseDateToStr(format, new Date()); return parseDateToStr(format, new Date());
} }
public static final String dateTime(final Date date) public static final String dateTime(final Date date) {
{
return parseDateToStr(YYYY_MM_DD, date); return parseDateToStr(YYYY_MM_DD, date);
} }
public static final String parseDateToStr(final String format, final Date date) public static final String parseDateToStr(final String format, final Date date) {
{
return new SimpleDateFormat(format).format(date); return new SimpleDateFormat(format).format(date);
} }
public static final Date dateTime(final String format, final String ts) public static final Date dateTime(final String format, final String ts) {
{ try {
try
{
return new SimpleDateFormat(format).parse(ts); return new SimpleDateFormat(format).parse(ts);
} } catch (ParseException e) {
catch (ParseException e)
{
throw new RuntimeException(e); throw new RuntimeException(e);
} }
} }
@ -93,8 +90,7 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils
/** /**
* 日期路径 即年// 如2018/08/08 * 日期路径 即年// 如2018/08/08
*/ */
public static final String datePath() public static final String datePath() {
{
Date now = new Date(); Date now = new Date();
return DateFormatUtils.format(now, "yyyy/MM/dd"); return DateFormatUtils.format(now, "yyyy/MM/dd");
} }
@ -102,8 +98,7 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils
/** /**
* 日期路径 即年// 如20180808 * 日期路径 即年// 如20180808
*/ */
public static final String dateTime() public static final String dateTime() {
{
Date now = new Date(); Date now = new Date();
return DateFormatUtils.format(now, "yyyyMMdd"); return DateFormatUtils.format(now, "yyyyMMdd");
} }
@ -111,18 +106,13 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils
/** /**
* 日期型字符串转化为日期 格式 * 日期型字符串转化为日期 格式
*/ */
public static Date parseDate(Object str) public static Date parseDate(Object str) {
{ if (str == null) {
if (str == null)
{
return null; return null;
} }
try try {
{
return parseDate(str.toString(), parsePatterns); return parseDate(str.toString(), parsePatterns);
} } catch (ParseException e) {
catch (ParseException e)
{
return null; return null;
} }
} }
@ -130,21 +120,26 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils
/** /**
* 获取服务器启动时间 * 获取服务器启动时间
*/ */
public static Date getServerStartDate() public static Date getServerStartDate() {
{
long time = ManagementFactory.getRuntimeMXBean().getStartTime(); long time = ManagementFactory.getRuntimeMXBean().getStartTime();
return new Date(time); return new Date(time);
} }
/**
* 计算相差天数
*/
public static int differentDaysByMillisecond(Date date1, Date date2) {
return Math.abs((int) ((date2.getTime() - date1.getTime()) / (1000 * 3600 * 24)));
}
/** /**
* 计算时间差 * 计算时间差
* *
* @param endDate 最后时间 * @param endDate 最后时间
* @param startTime 开始时间 * @param startTime 开始时间
* @return 时间差/小时/分钟 * @return 时间差/小时/分钟
*/ */
public static String timeDistance(Date endDate, Date startTime) public static String timeDistance(Date endDate, Date startTime) {
{
long nd = 1000 * 24 * 60 * 60; long nd = 1000 * 24 * 60 * 60;
long nh = 1000 * 60 * 60; long nh = 1000 * 60 * 60;
long nm = 1000 * 60; long nm = 1000 * 60;
@ -165,8 +160,7 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils
/** /**
* 增加 LocalDateTime ==> Date * 增加 LocalDateTime ==> Date
*/ */
public static Date toDate(LocalDateTime temporalAccessor) public static Date toDate(LocalDateTime temporalAccessor) {
{
ZonedDateTime zdt = temporalAccessor.atZone(ZoneId.systemDefault()); ZonedDateTime zdt = temporalAccessor.atZone(ZoneId.systemDefault());
return Date.from(zdt.toInstant()); return Date.from(zdt.toInstant());
} }
@ -174,10 +168,59 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils
/** /**
* 增加 LocalDate ==> Date * 增加 LocalDate ==> Date
*/ */
public static Date toDate(LocalDate temporalAccessor) public static Date toDate(LocalDate temporalAccessor) {
{
LocalDateTime localDateTime = LocalDateTime.of(temporalAccessor, LocalTime.of(0, 0, 0)); LocalDateTime localDateTime = LocalDateTime.of(temporalAccessor, LocalTime.of(0, 0, 0));
ZonedDateTime zdt = localDateTime.atZone(ZoneId.systemDefault()); ZonedDateTime zdt = localDateTime.atZone(ZoneId.systemDefault());
return Date.from(zdt.toInstant()); return Date.from(zdt.toInstant());
} }
/**
* 获取当前周的周一日期
*
* @param date 当前日期
* @return 周一的日期
*/
public static Date getThisWeekMonday(Date date) {
Calendar cal = Calendar.getInstance();
cal.setTime(date);
cal.setFirstDayOfWeek(Calendar.MONDAY);
cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY); // 设置为周一
return cal.getTime();
}
/**
* 获取当前周的周日日期
*
* @param date 当前日期
* @return 周日的日期
*/
public static Date getThisWeekSunday(Date date) {
Calendar cal = Calendar.getInstance();
cal.setTime(date);
cal.setFirstDayOfWeek(Calendar.MONDAY);
cal.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY); // 设置为周日
return cal.getTime();
}
/**
* 获取星期
*
* @param date 日期
*/
public static int getWeek(Date date) {
Calendar cal = Calendar.getInstance();
cal.setTime(date);
int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK);
dayOfWeek -= 1;
if (dayOfWeek == 0) {
dayOfWeek = 7;
}
return dayOfWeek;
}
public static void main(String[] args) {
String date = DateUtils.getDate(DateUtils.YYYYMMDD);
System.out.println(date);
}
} }

View File

@ -0,0 +1,49 @@
package com.tcctyn.common.core.utils;
/**
* 脱敏工具类
*
* @author tcctyn
*/
public class DesensitizedUtil
{
/**
* 密码的全部字符都用*代替比如******
*
* @param password 密码
* @return 脱敏后的密码
*/
public static String password(String password)
{
if (StringUtils.isBlank(password))
{
return StringUtils.EMPTY;
}
return StringUtils.repeat('*', password.length());
}
/**
* 车牌中间用*代替如果是错误的车牌不处理
*
* @param carLicense 完整的车牌号
* @return 脱敏后的车牌
*/
public static String carLicense(String carLicense)
{
if (StringUtils.isBlank(carLicense))
{
return StringUtils.EMPTY;
}
// 普通车牌
if (carLicense.length() == 7)
{
carLicense = StringUtils.hide(carLicense, 3, 6);
}
else if (carLicense.length() == 8)
{
// 新能源车牌
carLicense = StringUtils.hide(carLicense, 3, 7);
}
return carLicense;
}
}

View File

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

View File

@ -0,0 +1,32 @@
package com.tcctyn.common.core.utils;
/**
* 距离计算工具类
*/
public class DistanceCalculationUtil {
// 地球半径单位千米
private static final double EARTH_RADIUS_KM = 6371.0;
public static double calculateDistance(String lon1, String lat1, String lon2, String lat2) {
// 将角度转换为弧度
double lat1Rad = Math.toRadians(Double.valueOf(lat1));
double lon1Rad = Math.toRadians(Double.valueOf(lon1));
double lat2Rad = Math.toRadians(Double.valueOf(lat2));
double lon2Rad = Math.toRadians(Double.valueOf(lon2));
// 计算纬度和经度的差值
double deltaLat = lat2Rad - lat1Rad;
double deltaLon = lon2Rad - lon1Rad;
// 应用Haversine公式
double a = Math.pow(Math.sin(deltaLat / 2), 2)
+ Math.cos(lat1Rad) * Math.cos(lat2Rad)
* Math.pow(Math.sin(deltaLon / 2), 2);
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
// 计算距离
return EARTH_RADIUS_KM * c;
}
}

View File

@ -1,8 +1,9 @@
package com.tcctyn.common.core.utils; package com.tcctyn.common.core.utils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.io.StringWriter; import java.io.StringWriter;
import org.apache.commons.lang3.exception.ExceptionUtils;
/** /**
* 错误信息处理类 * 错误信息处理类

View File

@ -0,0 +1,171 @@
package com.tcctyn.common.core.utils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import java.io.*;
import java.util.concurrent.TimeUnit;
/**
* @author songguoqiang
* @date 2025年04月17日 22:42:13
*/
@Component
public class FFmpegExecutor {
private Process ffmpegProcess;
private OutputStream ffmpegInput;
private static final Logger logger = LoggerFactory.getLogger(FFmpegExecutor.class);
public void start(String format, String outputUrl, String rtspUrl) throws IOException {
// 构建 FFmpeg 命令
ProcessBuilder pb = new ProcessBuilder(
"ffmpeg",
"-i", rtspUrl,
"-c:v", "copy",
"-c:a", "aac",
"-ar", "44100",
"-f", format,
outputUrl
);
// 启动进程
ffmpegProcess = pb.start();
ffmpegInput = ffmpegProcess.getOutputStream();
// 异步读取输出日志
new Thread(() -> {
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(ffmpegProcess.getInputStream()))) {
String line;
while ((line = reader.readLine()) != null) {
logger.info("[FFmpeg] {}", line);
}
} catch (IOException e) {
logger.error("Failed to read FFmpeg output: {}", e.getMessage());
}
}).start();
}
public void writeFrame(byte[] frameData) throws IOException {
ffmpegInput.write(frameData);
ffmpegInput.flush();
}
public void stop() {
if (ffmpegProcess != null) {
try {
// 1. 尝试优雅退出发送 'q' 命令
if (ffmpegInput != null) {
ffmpegInput.write("q\n".getBytes());
ffmpegInput.flush();
}
} catch (IOException e) {
logger.warn("Failed to send exit command: {}", e.getMessage());
}
// 2. 关闭输入流
try {
if (ffmpegInput != null) {
ffmpegInput.close();
}
} catch (IOException e) {
logger.error("Error closing input stream: {}", e.getMessage());
}
// 3. 销毁进程
if (ffmpegProcess.isAlive()) {
ffmpegProcess.destroy();
try {
if (!ffmpegProcess.waitFor(5, TimeUnit.SECONDS)) {
ffmpegProcess.destroyForcibly();
logger.warn("FFmpeg process was forcibly terminated");
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
logger.error("Interrupted while waiting for termination: {}", e.getMessage());
}
}
ffmpegProcess = null; // 清除引用
}
}
private void readProcessOutput(InputStream inputStream) {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
//package com.tcctyn.common.utils;
//
//import com.tcctyn.common.annotation.Anonymous;
//import org.springframework.stereotype.Component;
//
//import java.io.IOException;
//import java.io.OutputStream;
//import java.nio.ByteBuffer;
//import java.util.ArrayList;
//import java.util.List;
//
///**
// * @author Jason
// * @date 2025年03月26日 22:42:13
// */
//@Component
//
//public class FFmpegExecutor {
//
// private Process ffmpegProcess;
// private OutputStream ffmpegInput;
// public void start(String format, String outputUrl, byte[] sps, byte[] pps) throws IOException {
// List<String> command = new ArrayList<>();
// command.add("ffmpeg");
// command.add("-y");
// command.add("-f"); command.add("h264");
// command.add("-i"); command.add("pipe:0");
// command.add("-c:v"); command.add("copy"); // 直接拷贝视频流
// command.add("-f"); command.add(format);
// command.add("-flvflags"); command.add("no_duration_filesize");
// command.add("-movflags"); command.add("faststart");
// command.add("-preset"); command.add("ultrafast");
// command.add("-tune"); command.add("zerolatency");
// command.add("-g"); command.add("50"); // GOP长度
// command.add("-keyint_min"); command.add("25"); // 最小关键帧间隔
// command.add("-x264-params"); command.add("scenecut=0:open_gop=0:min-keyint=25:keyint=50");
// command.add(outputUrl);
//
// ProcessBuilder pb = new ProcessBuilder(command);
// pb.redirectErrorStream(true);
// ffmpegProcess = pb.start();
// ffmpegInput = ffmpegProcess.getOutputStream();
//
// // 写入extradata
// writeExtradata(sps, pps);
// }
//
// public void writeFrame(byte[] frameData) throws IOException {
// ffmpegInput.write(frameData);
// ffmpegInput.flush();
// }
//
// public void stop() {
// try {
// if (ffmpegInput != null) {
// ffmpegInput.close();
// }
// if (ffmpegProcess != null) {
// ffmpegProcess.destroyForcibly();
// }
// } catch (IOException e) {
// e.printStackTrace();
// }
// }
//}

View File

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

View File

@ -0,0 +1,25 @@
package com.tcctyn.common.core.utils;
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
/**
* 获取i18n资源文件
*
* @author tcctyn
*/
public class MessageUtils
{
/**
* 根据消息键和参数 获取消息 委托给spring messageSource
*
* @param code 消息键
* @param args 参数
* @return 获取国际化翻译值
*/
public static String message(String code, Object... args)
{
MessageSource messageSource = SpringUtils.getBean(MessageSource.class);
return messageSource.getMessage(code, args, LocaleContextHolder.getLocale());
}
}

View File

@ -1,9 +1,9 @@
package com.tcctyn.common.core.utils; package com.tcctyn.common.core.utils;
import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageHelper;
import com.tcctyn.common.core.utils.sql.SqlUtil;
import com.tcctyn.common.core.web.page.PageDomain; import com.tcctyn.common.core.web.page.PageDomain;
import com.tcctyn.common.core.web.page.TableSupport; import com.tcctyn.common.core.web.page.TableSupport;
import com.tcctyn.common.core.utils.sql.SqlUtil;
/** /**
* 分页工具类 * 分页工具类

View File

@ -0,0 +1,40 @@
package com.tcctyn.common.core.utils;
/**
* 进制转换工具类
*
*/
public class ParseSystemUtil {
/**将二进制转换成16进制
* @param buf
* @return
*/
public static String parseByte2HexStr(byte buf[]) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < buf.length; i++) {
String hex = Integer.toHexString(buf[i] & 0xFF);
if (hex.length() == 1) {
hex = '0' + hex;
}
sb.append(hex.toUpperCase());
}
return sb.toString();
}
/**将16进制转换为二进制
* @param hexStr
* @return
*/
public static byte[] parseHexStr2Byte(String hexStr) {
if (hexStr.length() < 1)
return null;
byte[] result = new byte[hexStr.length()/2];
for (int i = 0;i< hexStr.length()/2; i++) {
int high = Integer.parseInt(hexStr.substring(i*2, i*2+1), 16);
int low = Integer.parseInt(hexStr.substring(i*2+1, i*2+2), 16);
result[i] = (byte) (high * 16 + low);
}
return result;
}
}

View File

@ -0,0 +1,179 @@
package com.tcctyn.common.core.utils;
import com.tcctyn.common.core.constant.Constants;
import com.tcctyn.common.core.constant.HttpStatus;
import com.tcctyn.common.core.web.domain.entity.SysRole;
import com.tcctyn.common.core.web.domain.model.LoginUser;
import com.tcctyn.common.core.exception.ServiceException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.util.PatternMatchUtils;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
/**
* 安全服务工具类
*
* @author tcctyn
*/
public class SecurityUtils
{
/**
* 用户ID
**/
public static Long getUserId()
{
try
{
return getLoginUser().getUserId();
}
catch (Exception e)
{
throw new ServiceException("获取用户ID异常", HttpStatus.UNAUTHORIZED);
}
}
/**
* 获取部门ID
**/
public static Long getDeptId()
{
try
{
return getLoginUser().getDeptId();
}
catch (Exception e)
{
throw new ServiceException("获取部门ID异常", HttpStatus.UNAUTHORIZED);
}
}
/**
* 获取用户账户
**/
public static String getUsername()
{
try
{
return getLoginUser().getUsername();
}
catch (Exception e)
{
throw new ServiceException("获取用户账户异常", HttpStatus.UNAUTHORIZED);
}
}
/**
* 获取用户
**/
public static LoginUser getLoginUser()
{
try
{
return (LoginUser) getAuthentication().getPrincipal();
}
catch (Exception e)
{
throw new ServiceException("获取用户信息异常", HttpStatus.UNAUTHORIZED);
}
}
/**
* 获取Authentication
*/
public static Authentication getAuthentication()
{
return SecurityContextHolder.getContext().getAuthentication();
}
/**
* 生成BCryptPasswordEncoder密码
*
* @param password 密码
* @return 加密字符串
*/
public static String encryptPassword(String password)
{
BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
return passwordEncoder.encode(password);
}
/**
* 判断密码是否相同
*
* @param rawPassword 真实密码
* @param encodedPassword 加密后字符
* @return 结果
*/
public static boolean matchesPassword(String rawPassword, String encodedPassword)
{
BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
return passwordEncoder.matches(rawPassword, encodedPassword);
}
/**
* 是否为管理员
*
* @param userId 用户ID
* @return 结果
*/
public static boolean isAdmin(Long userId)
{
return userId != null && 1L == userId;
}
/**
* 验证用户是否具备某权限
*
* @param permission 权限字符串
* @return 用户是否具备某权限
*/
public static boolean hasPermi(String permission)
{
return hasPermi(getLoginUser().getPermissions(), permission);
}
/**
* 判断是否包含权限
*
* @param authorities 权限列表
* @param permission 权限字符串
* @return 用户是否具备某权限
*/
public static boolean hasPermi(Collection<String> authorities, String permission)
{
return authorities.stream().filter(StringUtils::hasText)
.anyMatch(x -> Constants.ALL_PERMISSION.equals(x) || PatternMatchUtils.simpleMatch(x, permission));
}
/**
* 验证用户是否拥有某个角色
*
* @param role 角色标识
* @return 用户是否具备某角色
*/
public static boolean hasRole(String role)
{
List<SysRole> roleList = getLoginUser().getUser().getRoles();
Collection<String> roles = roleList.stream().map(SysRole::getRoleKey).collect(Collectors.toSet());
return hasRole(roles, role);
}
/**
* 判断是否包含角色
*
* @param roles 角色列表
* @param role 角色
* @return 用户是否具备某角色权限
*/
public static boolean hasRole(Collection<String> roles, String role)
{
return roles.stream().filter(StringUtils::hasText)
.anyMatch(x -> Constants.SUPER_ADMIN.equals(x) || PatternMatchUtils.simpleMatch(x, role));
}
}

View File

@ -0,0 +1,59 @@
package com.tcctyn.common.core.utils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.concurrent.Semaphore;
/**
* 信号量相关处理
*
* @author ruoyi
*/
public class SemaphoreUtils
{
/**
* SemaphoreUtils 日志控制器
*/
private static final Logger LOGGER = LoggerFactory.getLogger(SemaphoreUtils.class);
/**
* 获取信号量
*
* @param semaphore
* @return
*/
public static boolean tryAcquire(Semaphore semaphore)
{
boolean flag = false;
try
{
flag = semaphore.tryAcquire();
}
catch (Exception e)
{
LOGGER.error("获取信号量异常", e);
}
return flag;
}
/**
* 释放信号量
*
* @param semaphore
*/
public static void release(Semaphore semaphore)
{
try
{
semaphore.release();
}
catch (Exception e)
{
LOGGER.error("释放信号量异常", e);
}
}
}

View File

@ -1,17 +1,9 @@
package com.tcctyn.common.core.utils; package com.tcctyn.common.core.utils;
import java.io.IOException; import com.alibaba.fastjson2.JSON;
import java.io.UnsupportedEncodingException; import com.tcctyn.common.core.constant.Constants;
import java.net.URLDecoder; import com.tcctyn.common.core.web.domain.R;
import java.net.URLEncoder; import com.tcctyn.common.core.text.Convert;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.core.io.buffer.DataBuffer; import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpHeaders; import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
@ -21,15 +13,24 @@ import org.springframework.util.LinkedCaseInsensitiveMap;
import org.springframework.web.context.request.RequestAttributes; import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes; import org.springframework.web.context.request.ServletRequestAttributes;
import com.alibaba.fastjson2.JSON;
import com.tcctyn.common.core.constant.Constants;
import com.tcctyn.common.core.domain.R;
import com.tcctyn.common.core.text.Convert;
import reactor.core.publisher.Mono; import reactor.core.publisher.Mono;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
/** /**
* 客户端工具类 * 客户端工具类
* *
* @author tcctyn * @author tcctyn
*/ */
public class ServletUtils public class ServletUtils
@ -189,7 +190,7 @@ public class ServletUtils
/** /**
* 将字符串渲染到客户端 * 将字符串渲染到客户端
* *
* @param response 渲染对象 * @param response 渲染对象
* @param string 待渲染的字符串 * @param string 待渲染的字符串
*/ */
@ -210,7 +211,7 @@ public class ServletUtils
/** /**
* 是否是Ajax异步请求 * 是否是Ajax异步请求
* *
* @param request * @param request
*/ */
public static boolean isAjaxRequest(HttpServletRequest request) public static boolean isAjaxRequest(HttpServletRequest request)
@ -239,7 +240,7 @@ public class ServletUtils
/** /**
* 内容编码 * 内容编码
* *
* @param str 内容 * @param str 内容
* @return 编码后的内容 * @return 编码后的内容
*/ */
@ -257,7 +258,7 @@ public class ServletUtils
/** /**
* 内容解码 * 内容解码
* *
* @param str 内容 * @param str 内容
* @return 解码后的内容 * @return 解码后的内容
*/ */

View File

@ -1,15 +1,16 @@
package com.tcctyn.common.core.utils; package com.tcctyn.common.core.utils;
import com.tcctyn.common.core.constant.Constants;
import com.tcctyn.common.core.text.StrFormatter;
import org.springframework.util.AntPathMatcher;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import org.springframework.util.AntPathMatcher;
import com.tcctyn.common.core.constant.Constants;
import com.tcctyn.common.core.text.StrFormatter;
/** /**
* 字符串工具类 * 字符串工具类
* *
* @author tcctyn * @author tcctyn
*/ */
public class StringUtils extends org.apache.commons.lang3.StringUtils public class StringUtils extends org.apache.commons.lang3.StringUtils
@ -25,7 +26,7 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
/** /**
* 获取参数不为空值 * 获取参数不为空值
* *
* @param value defaultValue 要判断的value * @param value defaultValue 要判断的value
* @return value 返回值 * @return value 返回值
*/ */
@ -36,7 +37,7 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
/** /**
* * 判断一个Collection是否为空 包含ListSetQueue * * 判断一个Collection是否为空 包含ListSetQueue
* *
* @param coll 要判断的Collection * @param coll 要判断的Collection
* @return true为空 false非空 * @return true为空 false非空
*/ */
@ -47,7 +48,7 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
/** /**
* * 判断一个Collection是否非空包含ListSetQueue * * 判断一个Collection是否非空包含ListSetQueue
* *
* @param coll 要判断的Collection * @param coll 要判断的Collection
* @return true非空 false * @return true非空 false
*/ */
@ -58,7 +59,7 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
/** /**
* * 判断一个对象数组是否为空 * * 判断一个对象数组是否为空
* *
* @param objects 要判断的对象数组 * @param objects 要判断的对象数组
** @return true为空 false非空 ** @return true为空 false非空
*/ */
@ -69,7 +70,7 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
/** /**
* * 判断一个对象数组是否非空 * * 判断一个对象数组是否非空
* *
* @param objects 要判断的对象数组 * @param objects 要判断的对象数组
* @return true非空 false * @return true非空 false
*/ */
@ -80,7 +81,7 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
/** /**
* * 判断一个Map是否为空 * * 判断一个Map是否为空
* *
* @param map 要判断的Map * @param map 要判断的Map
* @return true为空 false非空 * @return true为空 false非空
*/ */
@ -91,7 +92,7 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
/** /**
* * 判断一个Map是否为空 * * 判断一个Map是否为空
* *
* @param map 要判断的Map * @param map 要判断的Map
* @return true非空 false * @return true非空 false
*/ */
@ -102,7 +103,7 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
/** /**
* * 判断一个字符串是否为空串 * * 判断一个字符串是否为空串
* *
* @param str String * @param str String
* @return true为空 false非空 * @return true为空 false非空
*/ */
@ -113,7 +114,7 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
/** /**
* * 判断一个字符串是否为非空串 * * 判断一个字符串是否为非空串
* *
* @param str String * @param str String
* @return true非空串 false空串 * @return true非空串 false空串
*/ */
@ -124,7 +125,7 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
/** /**
* * 判断一个对象是否为空 * * 判断一个对象是否为空
* *
* @param object Object * @param object Object
* @return true为空 false非空 * @return true为空 false非空
*/ */
@ -135,7 +136,7 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
/** /**
* * 判断一个对象是否非空 * * 判断一个对象是否非空
* *
* @param object Object * @param object Object
* @return true非空 false * @return true非空 false
*/ */
@ -146,7 +147,7 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
/** /**
* * 判断一个对象是否是数组类型Java基本型别的数组 * * 判断一个对象是否是数组类型Java基本型别的数组
* *
* @param object 对象 * @param object 对象
* @return true是数组 false不是数组 * @return true是数组 false不是数组
*/ */
@ -208,7 +209,7 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
/** /**
* 截取字符串 * 截取字符串
* *
* @param str 字符串 * @param str 字符串
* @param start 开始 * @param start 开始
* @return 结果 * @return 结果
@ -239,7 +240,7 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
/** /**
* 截取字符串 * 截取字符串
* *
* @param str 字符串 * @param str 字符串
* @param start 开始 * @param start 开始
* @param end 结束 * @param end 结束
@ -285,7 +286,7 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
/** /**
* 在字符串中查找第一个出现的 `open` 和最后一个出现的 `close` 之间的子字符串 * 在字符串中查找第一个出现的 `open` 和最后一个出现的 `close` 之间的子字符串
* *
* @param str 要截取的字符串 * @param str 要截取的字符串
* @param open 起始字符串 * @param open 起始字符串
* @param close 结束字符串 * @param close 结束字符串
@ -311,7 +312,7 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
/** /**
* 判断是否为空并且不是空白字符 * 判断是否为空并且不是空白字符
* *
* @param str 要判断的value * @param str 要判断的value
* @return 结果 * @return 结果
*/ */
@ -341,7 +342,7 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
* 通常使用format("this is {} for {}", "a", "b") -> this is a for b<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 \{} for a<br>
* 转义\ format("this is \\\\{} for {}", "a", "b") -> this is \a for b<br> * 转义\ format("this is \\\\{} for {}", "a", "b") -> this is \a for b<br>
* *
* @param template 文本模板被替换的部分用 {} 表示 * @param template 文本模板被替换的部分用 {} 表示
* @param params 参数值 * @param params 参数值
* @return 格式化后的文本 * @return 格式化后的文本
@ -357,7 +358,7 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
/** /**
* 是否为http(s)://开头 * 是否为http(s)://开头
* *
* @param link 链接 * @param link 链接
* @return 结果 * @return 结果
*/ */
@ -443,7 +444,7 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
/** /**
* 是否包含字符串 * 是否包含字符串
* *
* @param str 验证字符串 * @param str 验证字符串
* @param strs 字符串组 * @param strs 字符串组
* @return 包含返回true * @return 包含返回true
@ -465,7 +466,7 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
/** /**
* 将下划线大写方式命名的字符串转换为驼峰式如果转换前的下划线大写方式命名的字符串为空则返回空字符串 例如HELLO_WORLD->HelloWorld * 将下划线大写方式命名的字符串转换为驼峰式如果转换前的下划线大写方式命名的字符串为空则返回空字符串 例如HELLO_WORLD->HelloWorld
* *
* @param name 转换前的下划线大写方式命名的字符串 * @param name 转换前的下划线大写方式命名的字符串
* @return 转换后的驼峰式命名的字符串 * @return 转换后的驼峰式命名的字符串
*/ */
@ -539,7 +540,7 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
/** /**
* 查找指定字符串是否匹配指定字符串列表中的任意一个字符串 * 查找指定字符串是否匹配指定字符串列表中的任意一个字符串
* *
* @param str 指定字符串 * @param str 指定字符串
* @param strs 需要检查的字符串数组 * @param strs 需要检查的字符串数组
* @return 是否匹配 * @return 是否匹配
@ -561,11 +562,11 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
} }
/** /**
* 判断url是否与规则配置: * 判断url是否与规则配置:
* ? 表示单个字符; * ? 表示单个字符;
* * 表示一层路径内的任意字符串不可跨层级; * * 表示一层路径内的任意字符串不可跨层级;
* ** 表示任意层路径; * ** 表示任意层路径;
* *
* @param pattern 匹配规则 * @param pattern 匹配规则
* @param url 需要匹配的url * @param url 需要匹配的url
* @return * @return
@ -584,7 +585,7 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
/** /**
* 数字左边补齐0使之达到指定长度注意如果数字转换为字符串后长度大于size则只保留 最后size个字符 * 数字左边补齐0使之达到指定长度注意如果数字转换为字符串后长度大于size则只保留 最后size个字符
* *
* @param num 数字对象 * @param num 数字对象
* @param size 字符串指定长度 * @param size 字符串指定长度
* @return 返回数字的字符串格式该字符串为指定长度 * @return 返回数字的字符串格式该字符串为指定长度
@ -596,7 +597,7 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
/** /**
* 字符串左补齐如果原始字符串s长度大于size则只保留最后size个字符 * 字符串左补齐如果原始字符串s长度大于size则只保留最后size个字符
* *
* @param s 原始字符串 * @param s 原始字符串
* @param size 字符串指定长度 * @param size 字符串指定长度
* @param c 用于补齐的字符 * @param c 用于补齐的字符

View File

@ -0,0 +1,96 @@
package com.tcctyn.common.core.utils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.concurrent.*;
/**
* 线程相关工具类.
*
* @author tcctyn
*/
public class Threads
{
private static final Logger logger = LoggerFactory.getLogger(Threads.class);
/**
* sleep等待,单位为毫秒
*/
public static void sleep(long milliseconds)
{
try
{
Thread.sleep(milliseconds);
}
catch (InterruptedException e)
{
return;
}
}
/**
* 停止线程池
* 先使用shutdown, 停止接收新任务并尝试完成所有已存在任务.
* 如果超时, 则调用shutdownNow, 取消在workQueue中Pending的任务,并中断所有阻塞函数.
* 如果仍然超時則強制退出.
* 另对在shutdown时线程本身被调用中断做了处理.
*/
public static void shutdownAndAwaitTermination(ExecutorService pool)
{
if (pool != null && !pool.isShutdown())
{
pool.shutdown();
try
{
if (!pool.awaitTermination(120, TimeUnit.SECONDS))
{
pool.shutdownNow();
if (!pool.awaitTermination(120, TimeUnit.SECONDS))
{
logger.info("Pool did not terminate");
}
}
}
catch (InterruptedException ie)
{
pool.shutdownNow();
Thread.currentThread().interrupt();
}
}
}
/**
* 打印线程异常信息
*/
public static void printException(Runnable r, Throwable t)
{
if (t == null && r instanceof Future<?>)
{
try
{
Future<?> future = (Future<?>) r;
if (future.isDone())
{
future.get();
}
}
catch (CancellationException ce)
{
t = ce;
}
catch (ExecutionException ee)
{
t = ee.getCause();
}
catch (InterruptedException ie)
{
Thread.currentThread().interrupt();
}
}
if (t != null)
{
logger.error(t.getMessage(), t);
}
}
}

View File

@ -1,53 +1,55 @@
package com.tcctyn.common.core.utils.bean; package com.tcctyn.common.core.utils.bean;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.ArrayList; import java.util.*;
import java.util.List;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import java.util.stream.Collectors;
import static cn.hutool.core.bean.BeanUtil.toBean;
/** /**
* Bean 工具类 * Bean 工具类
* *
* @author tcctyn * @author tcctyn
*/ */
public class BeanUtils extends org.springframework.beans.BeanUtils public class BeanUtils extends org.springframework.beans.BeanUtils {
{ /**
/** Bean方法名中属性名开始的下标 */ * Bean方法名中属性名开始的下标
*/
private static final int BEAN_METHOD_PROP_INDEX = 3; private static final int BEAN_METHOD_PROP_INDEX = 3;
/** * 匹配getter方法的正则表达式 */ /**
* 匹配getter方法的正则表达式
*/
private static final Pattern GET_PATTERN = Pattern.compile("get(\\p{javaUpperCase}\\w*)"); private static final Pattern GET_PATTERN = Pattern.compile("get(\\p{javaUpperCase}\\w*)");
/** * 匹配setter方法的正则表达式 */ /**
* 匹配setter方法的正则表达式
*/
private static final Pattern SET_PATTERN = Pattern.compile("set(\\p{javaUpperCase}\\w*)"); private static final Pattern SET_PATTERN = Pattern.compile("set(\\p{javaUpperCase}\\w*)");
/** /**
* Bean属性复制工具方法 * Bean属性复制工具方法
* *
* @param src 源对象
* @param dest 目标对象 * @param dest 目标对象
* @param src 源对象
*/ */
public static void copyBeanProp(Object dest, Object src) public static void copyBeanProp(Object src, Object dest) {
{ try {
try
{
copyProperties(src, dest); copyProperties(src, dest);
} } catch (Exception e) {
catch (Exception e)
{
e.printStackTrace(); e.printStackTrace();
} }
} }
/** /**
* 获取对象的setter方法 * 获取对象的setter方法
* *
* @param obj 对象 * @param obj 对象
* @return 对象的setter方法列表 * @return 对象的setter方法列表
*/ */
public static List<Method> getSetterMethods(Object obj) public static List<Method> getSetterMethods(Object obj) {
{
// setter方法列表 // setter方法列表
List<Method> setterMethods = new ArrayList<Method>(); List<Method> setterMethods = new ArrayList<Method>();
@ -56,11 +58,9 @@ public class BeanUtils extends org.springframework.beans.BeanUtils
// 查找setter方法 // 查找setter方法
for (Method method : methods) for (Method method : methods) {
{
Matcher m = SET_PATTERN.matcher(method.getName()); Matcher m = SET_PATTERN.matcher(method.getName());
if (m.matches() && (method.getParameterTypes().length == 1)) if (m.matches() && (method.getParameterTypes().length == 1)) {
{
setterMethods.add(method); setterMethods.add(method);
} }
} }
@ -70,23 +70,20 @@ public class BeanUtils extends org.springframework.beans.BeanUtils
/** /**
* 获取对象的getter方法 * 获取对象的getter方法
* *
* @param obj 对象 * @param obj 对象
* @return 对象的getter方法列表 * @return 对象的getter方法列表
*/ */
public static List<Method> getGetterMethods(Object obj) public static List<Method> getGetterMethods(Object obj) {
{
// getter方法列表 // getter方法列表
List<Method> getterMethods = new ArrayList<Method>(); List<Method> getterMethods = new ArrayList<Method>();
// 获取所有方法 // 获取所有方法
Method[] methods = obj.getClass().getMethods(); Method[] methods = obj.getClass().getMethods();
// 查找getter方法 // 查找getter方法
for (Method method : methods) for (Method method : methods) {
{
Matcher m = GET_PATTERN.matcher(method.getName()); Matcher m = GET_PATTERN.matcher(method.getName());
if (m.matches() && (method.getParameterTypes().length == 0)) if (m.matches() && (method.getParameterTypes().length == 0)) {
{
getterMethods.add(method); getterMethods.add(method);
} }
} }
@ -97,14 +94,29 @@ public class BeanUtils extends org.springframework.beans.BeanUtils
/** /**
* 检查Bean方法名中的属性名是否相等<br> * 检查Bean方法名中的属性名是否相等<br>
* 如getName()和setName()属性名一样getName()和setAge()属性名不一样 * 如getName()和setName()属性名一样getName()和setAge()属性名不一样
* *
* @param m1 方法名1 * @param m1 方法名1
* @param m2 方法名2 * @param m2 方法名2
* @return 属性名一样返回true否则返回false * @return 属性名一样返回true否则返回false
*/ */
public static boolean isMethodPropEquals(String m1, String m2) public static boolean isMethodPropEquals(String m1, String m2) {
{
return m1.substring(BEAN_METHOD_PROP_INDEX).equals(m2.substring(BEAN_METHOD_PROP_INDEX)); return m1.substring(BEAN_METHOD_PROP_INDEX).equals(m2.substring(BEAN_METHOD_PROP_INDEX));
} }
/**
* List 对象复制工具方法
*
* @param sourceList
* @param destinationClass
* @return
*/
public static <T, E> List<T> copyList(Collection<E> sourceList, Class<T> destinationClass) {
if (sourceList == null || sourceList.isEmpty() || destinationClass == null) {
return Collections.emptyList();
}
return sourceList.parallelStream()
.filter(Objects::nonNull)
.map(source -> toBean(source, destinationClass)).collect(Collectors.toList());
}
} }

View File

@ -1,9 +1,9 @@
package com.tcctyn.common.core.utils.bean; package com.tcctyn.common.core.utils.bean;
import java.util.Set;
import javax.validation.ConstraintViolation; import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException; import javax.validation.ConstraintViolationException;
import javax.validation.Validator; import javax.validation.Validator;
import java.util.Set;
/** /**
* bean对象属性验证 * bean对象属性验证

View File

@ -1,11 +1,12 @@
package com.tcctyn.common.core.utils.file; package com.tcctyn.common.core.utils.file;
import java.io.File;
import java.util.Objects;
import org.apache.commons.io.FilenameUtils; import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.util.Objects;
/** /**
* 文件类型工具类 * 文件类型工具类
* *
@ -17,7 +18,7 @@ public class FileTypeUtils
* 获取文件类型 * 获取文件类型
* <p> * <p>
* 例如: tcctyn.txt, 返回: txt * 例如: tcctyn.txt, 返回: txt
* *
* @param file 文件名 * @param file 文件名
* @return 后缀不含".") * @return 后缀不含".")
*/ */
@ -50,7 +51,7 @@ public class FileTypeUtils
/** /**
* 获取文件名的后缀 * 获取文件名的后缀
* *
* @param file 表单文件 * @param file 表单文件
* @return 后缀名 * @return 后缀名
*/ */
@ -66,7 +67,7 @@ public class FileTypeUtils
/** /**
* 获取文件类型 * 获取文件类型
* *
* @param photoByte 文件字节码 * @param photoByte 文件字节码
* @return 后缀不含".") * @return 后缀不含".")
*/ */

View File

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

View File

@ -1,17 +1,18 @@
package com.tcctyn.common.core.utils.file; package com.tcctyn.common.core.utils.file;
import java.io.File; import com.tcctyn.common.core.config.TcctynConfig;
import java.io.FileInputStream; import com.tcctyn.common.core.utils.DateUtils;
import java.io.FileNotFoundException; import com.tcctyn.common.core.utils.StringUtils;
import java.io.IOException; import com.tcctyn.common.core.utils.uuid.IdUtils;
import java.io.OutputStream; import org.apache.commons.io.FilenameUtils;
import java.io.UnsupportedEncodingException; import org.apache.commons.io.IOUtils;
import java.net.URLEncoder; import org.apache.commons.lang3.ArrayUtils;
import java.nio.charset.StandardCharsets;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.ArrayUtils; import java.io.*;
import com.tcctyn.common.core.utils.StringUtils; import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
/** /**
* 文件处理工具类 * 文件处理工具类
@ -20,12 +21,6 @@ import com.tcctyn.common.core.utils.StringUtils;
*/ */
public class FileUtils 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]+"; public static String FILENAME_PATTERN = "[a-zA-Z0-9_\\-\\|\\.\\u4e00-\\u9fa5]+";
/** /**
@ -59,31 +54,50 @@ public class FileUtils
} }
finally finally
{ {
if (os != null) IOUtils.close(os);
{ IOUtils.close(fis);
try
{
os.close();
}
catch (IOException e1)
{
e1.printStackTrace();
}
}
if (fis != null)
{
try
{
fis.close();
}
catch (IOException e1)
{
e1.printStackTrace();
}
}
} }
} }
/**
* 写数据到文件中
*
* @param data 数据
* @return 目标文件
* @throws IOException IO异常
*/
public static String writeImportBytes(byte[] data) throws IOException
{
return writeBytes(data, TcctynConfig.getImportPath());
}
/**
* 写数据到文件中
*
* @param data 数据
* @param uploadDir 目标文件
* @return 目标文件
* @throws IOException IO异常
*/
public static String writeBytes(byte[] data, String uploadDir) throws IOException
{
FileOutputStream fos = null;
String pathName = "";
try
{
String extension = getFileExtendName(data);
pathName = DateUtils.datePath() + "/" + IdUtils.fastUUID() + "." + extension;
File file = FileUploadUtils.getAbsoluteFile(uploadDir, pathName);
fos = new FileOutputStream(file);
fos.write(data);
}
finally
{
IOUtils.close(fos);
}
return FileUploadUtils.getPathFileName(uploadDir, pathName);
}
/** /**
* 删除文件 * 删除文件
* *
@ -126,8 +140,15 @@ public class FileUtils
{ {
return false; return false;
} }
// 判断是否在允许下载的文件规则内
return ArrayUtils.contains(MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION, FileTypeUtils.getFileType(resource)); // 检查允许下载的文件规则
if (ArrayUtils.contains(MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION, FileTypeUtils.getFileType(resource)))
{
return true;
}
// 不在允许下载的文件规则
return false;
} }
/** /**
@ -165,63 +186,11 @@ public class FileUtils
return filename; 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或者LinuxUnix文件分隔符<br>
* Windows平台下分隔符为\LinuxUnix/
*
* @param c 字符
* @return 是否为Windows或者LinuxUnix文件分隔符
*/
public static boolean isFileSeparator(char c)
{
return SLASH == c || BACKSLASH == c;
}
/** /**
* 下载文件名重新编码 * 下载文件名重新编码
* *
* @param response 响应对象 * @param response 响应对象
* @param realFileName 真实文件名 * @param realFileName 真实文件名
* @return
*/ */
public static void setAttachmentResponseHeader(HttpServletResponse response, String realFileName) throws UnsupportedEncodingException public static void setAttachmentResponseHeader(HttpServletResponse response, String realFileName) throws UnsupportedEncodingException
{ {
@ -235,6 +204,7 @@ public class FileUtils
.append("utf-8''") .append("utf-8''")
.append(percentEncodedFileName); .append(percentEncodedFileName);
response.addHeader("Access-Control-Expose-Headers", "Content-Disposition,download-filename");
response.setHeader("Content-disposition", contentDispositionValue.toString()); response.setHeader("Content-disposition", contentDispositionValue.toString());
response.setHeader("download-filename", percentEncodedFileName); response.setHeader("download-filename", percentEncodedFileName);
} }
@ -250,4 +220,67 @@ public class FileUtils
String encode = URLEncoder.encode(s, StandardCharsets.UTF_8.toString()); String encode = URLEncoder.encode(s, StandardCharsets.UTF_8.toString());
return encode.replaceAll("\\+", "%20"); return encode.replaceAll("\\+", "%20");
} }
/**
* 获取图像后缀
*
* @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;
}
/**
* 获取文件名称 /profile/upload/2022/04/16/tcctyn.png -- tcctyn.png
*
* @param fileName 路径名称
* @return 没有文件路径的名称
*/
public static String getName(String fileName)
{
if (fileName == null)
{
return null;
}
int lastUnixPos = fileName.lastIndexOf('/');
int lastWindowsPos = fileName.lastIndexOf('\\');
int index = Math.max(lastUnixPos, lastWindowsPos);
return fileName.substring(index + 1);
}
/**
* 获取不带后缀文件名称 /profile/upload/2022/04/16/tcctyn.png -- tcctyn
*
* @param fileName 路径名称
* @return 没有文件路径和后缀的名称
*/
public static String getNameNotSuffix(String fileName)
{
if (fileName == null)
{
return null;
}
String baseName = FilenameUtils.getBaseName(fileName);
return baseName;
}
} }

View File

@ -1,13 +1,18 @@
package com.tcctyn.common.core.utils.file; package com.tcctyn.common.core.utils.file;
import com.tcctyn.common.core.config.TcctynConfig;
import com.tcctyn.common.core.constant.Constants;
import com.tcctyn.common.core.utils.StringUtils;
import org.apache.poi.util.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.InputStream; import java.io.InputStream;
import java.net.URL; import java.net.URL;
import java.net.URLConnection; import java.net.URLConnection;
import java.util.Arrays; import java.util.Arrays;
import org.apache.poi.util.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/** /**
* 图片处理工具类 * 图片处理工具类
@ -62,18 +67,28 @@ public class ImageUtils
InputStream in = null; InputStream in = null;
try try
{ {
// 网络地址 if (url.startsWith("http"))
URL urlObj = new URL(url); {
URLConnection urlConnection = urlObj.openConnection(); // 网络地址
urlConnection.setConnectTimeout(30 * 1000); URL urlObj = new URL(url);
urlConnection.setReadTimeout(60 * 1000); URLConnection urlConnection = urlObj.openConnection();
urlConnection.setDoInput(true); urlConnection.setConnectTimeout(30 * 1000);
in = urlConnection.getInputStream(); urlConnection.setReadTimeout(60 * 1000);
urlConnection.setDoInput(true);
in = urlConnection.getInputStream();
}
else
{
// 本机地址
String localPath = TcctynConfig.getProfile();
String downloadPath = localPath + StringUtils.substringAfter(url, Constants.RESOURCE_PREFIX);
in = new FileInputStream(downloadPath);
}
return IOUtils.toByteArray(in); return IOUtils.toByteArray(in);
} }
catch (Exception e) catch (Exception e)
{ {
log.error("访问文件异常 {}", e); log.error("获取文件路径异常 {}", e);
return null; return null;
} }
finally finally

View File

@ -16,7 +16,7 @@ public class MimeTypeUtils
public static final String IMAGE_BMP = "image/bmp"; public static final String IMAGE_BMP = "image/bmp";
public static final String IMAGE_GIF = "image/gif"; public static final String IMAGE_GIF = "image/gif";
public static final String[] IMAGE_EXTENSION = { "bmp", "gif", "jpg", "jpeg", "png" }; public static final String[] IMAGE_EXTENSION = { "bmp", "gif", "jpg", "jpeg", "png" };
public static final String[] FLASH_EXTENSION = { "swf", "flv" }; public static final String[] FLASH_EXTENSION = { "swf", "flv" };

View File

@ -1,10 +1,6 @@
package com.tcctyn.common.core.utils.html; package com.tcctyn.common.core.utils.html;
import java.util.ArrayList; import java.util.*;
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.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ConcurrentMap;
import java.util.regex.Matcher; import java.util.regex.Matcher;

View File

@ -0,0 +1,56 @@
package com.tcctyn.common.core.utils.http;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.ServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
/**
* 通用http工具封装
*
* @author tcctyn
*/
public class HttpHelper
{
private static final Logger LOGGER = LoggerFactory.getLogger(HttpHelper.class);
public static String getBodyString(ServletRequest request)
{
StringBuilder sb = new StringBuilder();
BufferedReader reader = null;
try (InputStream inputStream = request.getInputStream())
{
reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
String line = "";
while ((line = reader.readLine()) != null)
{
sb.append(line);
}
}
catch (IOException e)
{
LOGGER.warn("getBodyString出现问题");
}
finally
{
if (reader != null)
{
try
{
reader.close();
}
catch (IOException e)
{
LOGGER.error(ExceptionUtils.getMessage(e));
}
}
}
return sb.toString();
}
}

View File

@ -0,0 +1,266 @@
package com.tcctyn.common.core.utils.http;
import com.tcctyn.common.core.constant.Constants;
import com.tcctyn.common.core.utils.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.net.ssl.*;
import java.io.*;
import java.net.ConnectException;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.StandardCharsets;
import java.security.cert.X509Certificate;
/**
* 通用http发送方法
*
* @author tcctyn
*/
public class HttpUtils
{
private static final Logger log = LoggerFactory.getLogger(HttpUtils.class);
/**
* 向指定 URL 发送GET方法的请求
*
* @param url 发送请求的 URL
* @return 所代表远程资源的响应结果
*/
public static String sendGet(String url)
{
return sendGet(url, StringUtils.EMPTY);
}
/**
* 向指定 URL 发送GET方法的请求
*
* @param url 发送请求的 URL
* @param param 请求参数请求参数应该是 name1=value1&name2=value2 的形式
* @return 所代表远程资源的响应结果
*/
public static String sendGet(String url, String param)
{
return sendGet(url, param, Constants.UTF8);
}
/**
* 向指定 URL 发送GET方法的请求
*
* @param url 发送请求的 URL
* @param param 请求参数请求参数应该是 name1=value1&name2=value2 的形式
* @param contentType 编码类型
* @return 所代表远程资源的响应结果
*/
public static String sendGet(String url, String param, String contentType)
{
StringBuilder result = new StringBuilder();
BufferedReader in = null;
try
{
String urlNameString = StringUtils.isNotBlank(param) ? url + "?" + param : url;
log.info("sendGet - {}", urlNameString);
URL realUrl = new URL(urlNameString);
URLConnection connection = realUrl.openConnection();
connection.setRequestProperty("accept", "*/*");
connection.setRequestProperty("connection", "Keep-Alive");
connection.setRequestProperty("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)");
connection.connect();
in = new BufferedReader(new InputStreamReader(connection.getInputStream(), contentType));
String line;
while ((line = in.readLine()) != null)
{
result.append(line);
}
log.info("recv - {}", result);
}
catch (ConnectException e)
{
log.error("调用HttpUtils.sendGet ConnectException, url=" + url + ",param=" + param, e);
}
catch (SocketTimeoutException e)
{
log.error("调用HttpUtils.sendGet SocketTimeoutException, url=" + url + ",param=" + param, e);
}
catch (IOException e)
{
log.error("调用HttpUtils.sendGet IOException, url=" + url + ",param=" + param, e);
}
catch (Exception e)
{
log.error("调用HttpsUtil.sendGet Exception, url=" + url + ",param=" + param, e);
}
finally
{
try
{
if (in != null)
{
in.close();
}
}
catch (Exception ex)
{
log.error("调用in.close Exception, url=" + url + ",param=" + param, ex);
}
}
return result.toString();
}
/**
* 向指定 URL 发送POST方法的请求
*
* @param url 发送请求的 URL
* @param param 请求参数请求参数应该是 name1=value1&name2=value2 的形式
* @return 所代表远程资源的响应结果
*/
public static String sendPost(String url, String param)
{
PrintWriter out = null;
BufferedReader in = null;
StringBuilder result = new StringBuilder();
try
{
log.info("sendPost - {}", url);
URL realUrl = new URL(url);
URLConnection conn = realUrl.openConnection();
conn.setRequestProperty("accept", "*/*");
conn.setRequestProperty("connection", "Keep-Alive");
conn.setRequestProperty("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)");
conn.setRequestProperty("Accept-Charset", "utf-8");
conn.setRequestProperty("contentType", "utf-8");
conn.setDoOutput(true);
conn.setDoInput(true);
out = new PrintWriter(conn.getOutputStream());
out.print(param);
out.flush();
in = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8));
String line;
while ((line = in.readLine()) != null)
{
result.append(line);
}
log.info("recv - {}", result);
}
catch (ConnectException e)
{
log.error("调用HttpUtils.sendPost ConnectException, url=" + url + ",param=" + param, e);
}
catch (SocketTimeoutException e)
{
log.error("调用HttpUtils.sendPost SocketTimeoutException, url=" + url + ",param=" + param, e);
}
catch (IOException e)
{
log.error("调用HttpUtils.sendPost IOException, url=" + url + ",param=" + param, e);
}
catch (Exception e)
{
log.error("调用HttpsUtil.sendPost Exception, url=" + url + ",param=" + param, e);
}
finally
{
try
{
if (out != null)
{
out.close();
}
if (in != null)
{
in.close();
}
}
catch (IOException ex)
{
log.error("调用in.close Exception, url=" + url + ",param=" + param, ex);
}
}
return result.toString();
}
public static String sendSSLPost(String url, String param)
{
StringBuilder result = new StringBuilder();
String urlNameString = url + "?" + param;
try
{
log.info("sendSSLPost - {}", urlNameString);
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, new TrustManager[] { new TrustAnyTrustManager() }, new java.security.SecureRandom());
URL console = new URL(urlNameString);
HttpsURLConnection conn = (HttpsURLConnection) console.openConnection();
conn.setRequestProperty("accept", "*/*");
conn.setRequestProperty("connection", "Keep-Alive");
conn.setRequestProperty("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)");
conn.setRequestProperty("Accept-Charset", "utf-8");
conn.setRequestProperty("contentType", "utf-8");
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setSSLSocketFactory(sc.getSocketFactory());
conn.setHostnameVerifier(new TrustAnyHostnameVerifier());
conn.connect();
InputStream is = conn.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String ret = "";
while ((ret = br.readLine()) != null)
{
if (ret != null && !"".equals(ret.trim()))
{
result.append(new String(ret.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8));
}
}
log.info("recv - {}", result);
conn.disconnect();
br.close();
}
catch (ConnectException e)
{
log.error("调用HttpUtils.sendSSLPost ConnectException, url=" + url + ",param=" + param, e);
}
catch (SocketTimeoutException e)
{
log.error("调用HttpUtils.sendSSLPost SocketTimeoutException, url=" + url + ",param=" + param, e);
}
catch (IOException e)
{
log.error("调用HttpUtils.sendSSLPost IOException, url=" + url + ",param=" + param, e);
}
catch (Exception e)
{
log.error("调用HttpsUtil.sendSSLPost Exception, url=" + url + ",param=" + param, e);
}
return result.toString();
}
private static class TrustAnyTrustManager implements X509TrustManager
{
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType)
{
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType)
{
}
@Override
public X509Certificate[] getAcceptedIssuers()
{
return new X509Certificate[] {};
}
}
private static class TrustAnyHostnameVerifier implements HostnameVerifier
{
@Override
public boolean verify(String hostname, SSLSession session)
{
return true;
}
}
}

View File

@ -0,0 +1,56 @@
package com.tcctyn.common.core.utils.ip;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.tcctyn.common.core.config.TcctynConfig;
import com.tcctyn.common.core.constant.Constants;
import com.tcctyn.common.core.utils.StringUtils;
import com.tcctyn.common.core.utils.http.HttpUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* 获取地址类
*
* @author tcctyn
*/
public class AddressUtils
{
private static final Logger log = LoggerFactory.getLogger(AddressUtils.class);
// IP地址查询
public static final String IP_URL = "http://whois.pconline.com.cn/ipJson.jsp";
// 未知地址
public static final String UNKNOWN = "XX XX";
public static String getRealAddressByIP(String ip)
{
// 内网不查询
if (IpUtils.internalIp(ip))
{
return "内网IP";
}
if (TcctynConfig.isAddressEnabled())
{
try
{
String rspStr = HttpUtils.sendGet(IP_URL, "ip=" + ip + "&json=true", Constants.GBK);
if (StringUtils.isEmpty(rspStr))
{
log.error("获取地理位置异常 {}", ip);
return UNKNOWN;
}
JSONObject obj = JSON.parseObject(rspStr);
String region = obj.getString("pro");
String city = obj.getString("city");
return String.format("%s %s", region, city);
}
catch (Exception e)
{
log.error("获取地理位置异常 {}", ip);
}
}
return UNKNOWN;
}
}

View File

@ -1,11 +1,12 @@
package com.tcctyn.common.core.utils.ip; package com.tcctyn.common.core.utils.ip;
import java.net.InetAddress;
import java.net.UnknownHostException;
import javax.servlet.http.HttpServletRequest;
import com.tcctyn.common.core.utils.ServletUtils; import com.tcctyn.common.core.utils.ServletUtils;
import com.tcctyn.common.core.utils.StringUtils; import com.tcctyn.common.core.utils.StringUtils;
import javax.servlet.http.HttpServletRequest;
import java.net.InetAddress;
import java.net.UnknownHostException;
/** /**
* 获取IP方法 * 获取IP方法
* *

View File

@ -0,0 +1,51 @@
package com.tcctyn.common.core.utils.mqtt;
public class JavaDemoMQTTV3 {
public static void main(String[] args) {
String broker = "tcp://47.109.202.121:1883";
String clientId = "hqyjDemo";
String topic = "topic/hqyj";
int subQos = 1;
int pubQos = 1;
String msg = "Hello MQTT";
// try {
// MqttClient client = new MqttClient(broker, clientId);
// MqttConnectOptions options = new MqttConnectOptions();
// client.connect(options);
//
// if (client.isConnected()) {
// client.setCallback(new MqttCallback() {
// public void messageArrived(String topic, MqttMessage message) throws Exception {
// System.out.println("topic: " + topic);
// System.out.println("qos: " + message.getQos());
// System.out.println("message content: " + new String(message.getPayload()));
// }
//
// public void connectionLost(Throwable cause) {
// System.out.println("connectionLost: " + cause.getMessage());
// }
//
// public void deliveryComplete(IMqttDeliveryToken token) {
// System.out.println("deliveryComplete: " + token.isComplete());
// }
// });
//
// client.subscribe(topic, subQos);
//
// MqttMessage message = new MqttMessage(msg.getBytes());
// message.setQos(pubQos);
// client.publish(topic, message);
// }
//
// client.disconnect();
// client.close();
//
// } catch (MqttException e) {
// e.printStackTrace();
// }
}
}

View File

@ -0,0 +1,63 @@
package com.tcctyn.common.core.utils.mqtt;
import com.tcctyn.common.core.utils.StringUtils;
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
@Component
@ConfigurationProperties("spring.mqtt")
@Data
public class MqttConfig {
@Autowired
private MqttPushClient mqttPushClient;
/**
* 用户名
*/
private String username;
/**
* 密码
*/
private String password;
/**
* 连接地址
*/
private String hostUrl;
/**
* 客户Id
*/
private String clientId;
/**
* 默认连接话题
*/
private String defaultTopic;
/**
* 超时时间
*/
private int timeout;
/**
* 保持连接数
*/
private int keepalive;
/**
* mqtt功能使能
*/
private boolean enabled;
@Bean
public MqttPushClient getMqttPushClient() {
if(enabled == true){
String mqtt_topic[] = StringUtils.split(defaultTopic, ",");
mqttPushClient.connect(hostUrl, clientId, username, password, timeout, keepalive);//连接
for(int i=0; i<mqtt_topic.length; i++){
mqttPushClient.subscribe(mqtt_topic[i], 0);//订阅主题
}
}
return mqttPushClient;
}
}

View File

@ -0,0 +1,108 @@
package com.tcctyn.common.core.utils.mqtt;
import com.tcctyn.common.core.web.domain.AjaxResult;
import org.eclipse.paho.client.mqttv3.*;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
@Component
public class MqttPushClient {
private static final Logger logger = LoggerFactory.getLogger(MqttPushClient.class);
@Autowired
@Lazy
private PushCallback pushCallback;
private static MqttClient client;
private static MqttClient getClient() {
return client;
}
private static void setClient(MqttClient client) {
MqttPushClient.client = client;
}
/**
* 客户端连接
*
* @param host ip+端口
* @param clientID 客户端Id
* @param username 用户名
* @param password 密码
* @param timeout 超时时间
* @param keepalive 保留数
*/
public void connect(String host, String clientID, String username, String password, int timeout, int keepalive) {
MqttClient client;
try {
client = new MqttClient(host, clientID, new MemoryPersistence());
MqttConnectOptions options = new MqttConnectOptions();
options.setCleanSession(true);
options.setUserName(username);
options.setPassword(password.toCharArray());
options.setConnectionTimeout(timeout);
options.setKeepAliveInterval(keepalive);
MqttPushClient.setClient(client);
try {
client.setCallback(pushCallback);
client.connect(options);
} catch (Exception e) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 发布
*
* @param qos 连接方式
* @param retained 是否保留
* @param topic 主题
* @param pushMessage 消息体
*/
public AjaxResult publish(int qos, boolean retained, String topic, String pushMessage) {
MqttMessage message = new MqttMessage();
message.setQos(qos);
message.setRetained(retained);
message.setPayload(pushMessage.getBytes());
MqttTopic mTopic = MqttPushClient.getClient().getTopic(topic);
if (null == mTopic) {
logger.error("topic not exist");
}
MqttDeliveryToken token;
try {
token = mTopic.publish(message);
token.waitForCompletion();
return AjaxResult.success();
} catch (MqttPersistenceException e) {
e.printStackTrace();
return AjaxResult.error();
} catch (MqttException e) {
e.printStackTrace();
return AjaxResult.error();
}
}
/**
* 订阅某个主题
*
* @param topic 主题
* @param qos 连接方式
*/
public void subscribe(String topic, int qos) {
logger.info("开始订阅主题" + topic);
try {
MqttPushClient.getClient().subscribe(topic, qos);
} catch (MqttException e) {
e.printStackTrace();
}
}
}

View File

@ -0,0 +1,70 @@
package com.tcctyn.common.core.utils.mqtt;
import com.alibaba.fastjson2.JSONObject;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
@Component
public class PushCallback implements MqttCallback {
private static final Logger logger = LoggerFactory.getLogger(MqttPushClient.class);
@Autowired
@Lazy
private MqttConfig mqttConfig;
private static MqttClient client;
private static String _topic;
private static String _qos;
private static String _msg;
@Override
public void connectionLost(Throwable throwable) {
// 连接丢失后一般在这里面进行重连
logger.info("连接断开,可以做重连");
if (client == null || !client.isConnected()) {
mqttConfig.getMqttPushClient();
}
}
@Override
public void messageArrived(String topic, MqttMessage mqttMessage) throws Exception {
// subscribe后得到的消息会执行到这里面
logger.info("接收消息主题 : " + topic);
logger.info("接收消息Qos : " + mqttMessage.getQos());
logger.info("接收消息内容 : " + new String(mqttMessage.getPayload()));
_topic = topic;
_qos = mqttMessage.getQos()+"";
_msg = new String(mqttMessage.getPayload());
/*
* 在这里添加处理接收到主题的代码
* 屎山开堆
*
*/
}
@Override
public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {
logger.info("deliveryComplete---------" + iMqttDeliveryToken.isComplete());
}
//别的Controller层会调用这个方法来 获取 接收到的硬件数据
public String receive() {
JSONObject jsonObject = new JSONObject();
jsonObject.put("topic", _topic);
jsonObject.put("qos", _qos);
jsonObject.put("msg", _msg);
return jsonObject.toString();
}
}

View File

@ -1,7 +1,37 @@
package com.tcctyn.common.core.utils.poi; package com.tcctyn.common.core.utils.poi;
import java.io.IOException; import com.tcctyn.common.core.annotation.Excel;
import java.io.InputStream; import com.tcctyn.common.core.annotation.Excel.ColumnType;
import com.tcctyn.common.core.annotation.Excel.Type;
import com.tcctyn.common.core.annotation.Excels;
import com.tcctyn.common.core.config.TcctynConfig;
import com.tcctyn.common.core.web.domain.AjaxResult;
import com.tcctyn.common.core.exception.UtilException;
import com.tcctyn.common.core.text.Convert;
import com.tcctyn.common.core.utils.DateUtils;
import com.tcctyn.common.core.utils.DictUtils;
import com.tcctyn.common.core.utils.StringUtils;
import com.tcctyn.common.core.utils.file.FileTypeUtils;
import com.tcctyn.common.core.utils.file.FileUtils;
import com.tcctyn.common.core.utils.file.ImageUtils;
import com.tcctyn.common.core.utils.reflect.ReflectUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.RegExUtils;
import org.apache.commons.lang3.reflect.FieldUtils;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ooxml.POIXMLDocumentPart;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellRangeAddressList;
import org.apache.poi.util.IOUtils;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.*;
import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTMarker;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType; import java.lang.reflect.ParameterizedType;
@ -9,64 +39,12 @@ import java.math.BigDecimal;
import java.text.DecimalFormat; import java.text.DecimalFormat;
import java.time.LocalDate; import java.time.LocalDate;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.ArrayList; import java.util.*;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.RegExUtils;
import org.apache.commons.lang3.reflect.FieldUtils;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.ClientAnchor;
import org.apache.poi.ss.usermodel.DataFormat;
import org.apache.poi.ss.usermodel.DataValidation;
import org.apache.poi.ss.usermodel.DataValidationConstraint;
import org.apache.poi.ss.usermodel.DataValidationHelper;
import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.ss.usermodel.Drawing;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.Name;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellRangeAddressList;
import org.apache.poi.util.IOUtils;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
import org.apache.poi.xssf.usermodel.XSSFDataValidation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.tcctyn.common.core.annotation.Excel;
import com.tcctyn.common.core.annotation.Excel.ColumnType;
import com.tcctyn.common.core.annotation.Excel.Type;
import com.tcctyn.common.core.annotation.Excels;
import com.tcctyn.common.core.exception.UtilException;
import com.tcctyn.common.core.text.Convert;
import com.tcctyn.common.core.utils.DateUtils;
import com.tcctyn.common.core.utils.StringUtils;
import com.tcctyn.common.core.utils.file.FileTypeUtils;
import com.tcctyn.common.core.utils.file.ImageUtils;
import com.tcctyn.common.core.utils.reflect.ReflectUtils;
/** /**
* Excel相关处理 * Excel相关处理
* *
* @author tcctyn * @author tcctyn
*/ */
public class ExcelUtil<T> public class ExcelUtil<T>
@ -77,6 +55,11 @@ public class ExcelUtil<T>
public static final String[] FORMULA_STR = { "=", "-", "+", "@" }; public static final String[] FORMULA_STR = { "=", "-", "+", "@" };
/**
* 用于dictType属性数据存储避免重复查缓存
*/
public Map<String, String> sysDictMap = new HashMap<String, String>();
/** /**
* Excel sheet最大行数默认65536 * Excel sheet最大行数默认65536
*/ */
@ -167,11 +150,6 @@ public class ExcelUtil<T>
*/ */
public Class<T> clazz; public Class<T> clazz;
/**
* 需要显示列属性
*/
public String[] includeFields;
/** /**
* 需要排除列属性 * 需要排除列属性
*/ */
@ -182,20 +160,11 @@ public class ExcelUtil<T>
this.clazz = clazz; this.clazz = clazz;
} }
/**
* 仅在Excel中显示列属性
*
* @param fields 列属性名 示例[单个"name"/多个"id","name"]
*/
public void showColumn(String... fields)
{
this.includeFields = fields;
}
/** /**
* 隐藏Excel中列属性 * 隐藏Excel中列属性
* *
* @param fields 列属性名 示例[单个"name"/多个"id","name"] * @param fields 列属性名 示例[单个"name"/多个"id","name"]
* @throws Exception
*/ */
public void hideColumn(String... fields) public void hideColumn(String... fields)
{ {
@ -225,6 +194,8 @@ public class ExcelUtil<T>
{ {
if (StringUtils.isNotEmpty(title)) if (StringUtils.isNotEmpty(title))
{ {
subMergedFirstRowNum++;
subMergedLastRowNum++;
int titleLastCol = this.fields.size() - 1; int titleLastCol = this.fields.size() - 1;
if (isSubList()) if (isSubList())
{ {
@ -235,7 +206,7 @@ public class ExcelUtil<T>
Cell titleCell = titleRow.createCell(0); Cell titleCell = titleRow.createCell(0);
titleCell.setCellStyle(styles.get("title")); titleCell.setCellStyle(styles.get("title"));
titleCell.setCellValue(title); titleCell.setCellValue(title);
sheet.addMergedRegion(new CellRangeAddress(titleRow.getRowNum(), titleRow.getRowNum(), 0, titleLastCol)); sheet.addMergedRegion(new CellRangeAddress(titleRow.getRowNum(), titleRow.getRowNum(), titleRow.getRowNum(), titleLastCol));
} }
} }
@ -246,31 +217,23 @@ public class ExcelUtil<T>
{ {
if (isSubList()) if (isSubList())
{ {
subMergedFirstRowNum++;
subMergedLastRowNum++;
Row subRow = sheet.createRow(rownum); Row subRow = sheet.createRow(rownum);
int column = 0; int excelNum = 0;
int subFieldSize = subFields != null ? subFields.size() : 0;
for (Object[] objects : fields) for (Object[] objects : fields)
{ {
Field field = (Field) objects[0];
Excel attr = (Excel) objects[1]; Excel attr = (Excel) objects[1];
if (Collection.class.isAssignableFrom(field.getType())) Cell headCell1 = subRow.createCell(excelNum);
{ headCell1.setCellValue(attr.name());
Cell cell = subRow.createCell(column); headCell1.setCellStyle(styles.get(StringUtils.format("header_{}_{}", attr.headerColor(), attr.headerBackgroundColor())));
cell.setCellValue(attr.name()); excelNum++;
cell.setCellStyle(styles.get(StringUtils.format("header_{}_{}", attr.headerColor(), attr.headerBackgroundColor()))); }
if (subFieldSize > 1) int headFirstRow = excelNum - 1;
{ int headLastRow = headFirstRow + subFields.size() - 1;
CellRangeAddress cellAddress = new CellRangeAddress(rownum, rownum, column, column + subFieldSize - 1); if (headLastRow > headFirstRow)
sheet.addMergedRegion(cellAddress); {
} sheet.addMergedRegion(new CellRangeAddress(rownum, rownum, headFirstRow, headLastRow));
column += subFieldSize;
}
else
{
Cell cell = subRow.createCell(column++);
cell.setCellValue(attr.name());
cell.setCellStyle(styles.get(StringUtils.format("header_{}_{}", attr.headerColor(), attr.headerBackgroundColor())));
}
} }
rownum++; rownum++;
} }
@ -283,23 +246,11 @@ public class ExcelUtil<T>
* @return 转换后集合 * @return 转换后集合
*/ */
public List<T> importExcel(InputStream is) public List<T> importExcel(InputStream is)
{
return importExcel(is, 0);
}
/**
* 对excel表单默认第一个索引名转换成list
*
* @param is 输入流
* @param titleNum 标题占用行数
* @return 转换后集合
*/
public List<T> importExcel(InputStream is, int titleNum)
{ {
List<T> list = null; List<T> list = null;
try try
{ {
list = importExcel(StringUtils.EMPTY, is, titleNum); list = importExcel(is, 0);
} }
catch (Exception e) catch (Exception e)
{ {
@ -313,6 +264,18 @@ public class ExcelUtil<T>
return list; return list;
} }
/**
* 对excel表单默认第一个索引名转换成list
*
* @param is 输入流
* @param titleNum 标题占用行数
* @return 转换后集合
*/
public List<T> importExcel(InputStream is, int titleNum) throws Exception
{
return importExcel(StringUtils.EMPTY, is, titleNum);
}
/** /**
* 对excel表单指定表格索引名转换成list * 对excel表单指定表格索引名转换成list
* *
@ -332,7 +295,16 @@ public class ExcelUtil<T>
{ {
throw new IOException("文件sheet不存在"); throw new IOException("文件sheet不存在");
} }
boolean isXSSFWorkbook = !(wb instanceof HSSFWorkbook);
Map<String, PictureData> pictures;
if (isXSSFWorkbook)
{
pictures = getSheetPictures07((XSSFSheet) sheet, (XSSFWorkbook) wb);
}
else
{
pictures = getSheetPictures03((HSSFSheet) sheet, (HSSFWorkbook) wb);
}
// 获取最后一个非空行的行下标比如总行数为n则返回的为n-1 // 获取最后一个非空行的行下标比如总行数为n则返回的为n-1
int rows = sheet.getLastRowNum(); int rows = sheet.getLastRowNum();
if (rows > 0) if (rows > 0)
@ -390,7 +362,7 @@ public class ExcelUtil<T>
if (String.class == fieldType) if (String.class == fieldType)
{ {
String s = Convert.toStr(val); String s = Convert.toStr(val);
if (s.matches("^\\d+\\.0$")) if (StringUtils.endsWith(s, ".0"))
{ {
val = StringUtils.substringBefore(s, ".0"); val = StringUtils.substringBefore(s, ".0");
} }
@ -453,10 +425,32 @@ public class ExcelUtil<T>
{ {
val = reverseByExp(Convert.toStr(val), attr.readConverterExp(), attr.separator()); val = reverseByExp(Convert.toStr(val), attr.readConverterExp(), attr.separator());
} }
else if (StringUtils.isNotEmpty(attr.dictType()))
{
if (!sysDictMap.containsKey(attr.dictType() + val))
{
String dictValue = reverseDictByExp(Convert.toStr(val), attr.dictType(), attr.separator());
sysDictMap.put(attr.dictType() + val, dictValue);
}
val = sysDictMap.get(attr.dictType() + val);
}
else if (!attr.handler().equals(ExcelHandlerAdapter.class)) else if (!attr.handler().equals(ExcelHandlerAdapter.class))
{ {
val = dataFormatHandlerAdapter(val, attr, null); val = dataFormatHandlerAdapter(val, attr, null);
} }
else if (ColumnType.IMAGE == attr.cellType() && StringUtils.isNotEmpty(pictures))
{
PictureData image = pictures.get(row.getRowNum() + "_" + entry.getKey());
if (image == null)
{
val = "";
}
else
{
byte[] data = image.getData();
val = FileUtils.writeImportBytes(data);
}
}
ReflectUtils.invokeSetter(entity, propertyName, val); ReflectUtils.invokeSetter(entity, propertyName, val);
} }
} }
@ -468,7 +462,33 @@ public class ExcelUtil<T>
/** /**
* 对list数据源将其里面的数据导入到excel表单 * 对list数据源将其里面的数据导入到excel表单
* *
* @param list 导出数据集合
* @param sheetName 工作表的名称
* @return 结果
*/
public AjaxResult exportExcel(List<T> list, String sheetName)
{
return exportExcel(list, sheetName, StringUtils.EMPTY);
}
/**
* 对list数据源将其里面的数据导入到excel表单
*
* @param list 导出数据集合
* @param sheetName 工作表的名称
* @param title 标题
* @return 结果
*/
public AjaxResult exportExcel(List<T> list, String sheetName, String title)
{
this.init(list, sheetName, title, Type.EXPORT);
return exportExcel();
}
/**
* 对list数据源将其里面的数据导入到excel表单
*
* @param response 返回数据 * @param response 返回数据
* @param list 导出数据集合 * @param list 导出数据集合
* @param sheetName 工作表的名称 * @param sheetName 工作表的名称
@ -481,7 +501,7 @@ public class ExcelUtil<T>
/** /**
* 对list数据源将其里面的数据导入到excel表单 * 对list数据源将其里面的数据导入到excel表单
* *
* @param response 返回数据 * @param response 返回数据
* @param list 导出数据集合 * @param list 导出数据集合
* @param sheetName 工作表的名称 * @param sheetName 工作表的名称
@ -498,7 +518,31 @@ public class ExcelUtil<T>
/** /**
* 对list数据源将其里面的数据导入到excel表单 * 对list数据源将其里面的数据导入到excel表单
* *
* @param sheetName 工作表的名称
* @return 结果
*/
public AjaxResult importTemplateExcel(String sheetName)
{
return importTemplateExcel(sheetName, StringUtils.EMPTY);
}
/**
* 对list数据源将其里面的数据导入到excel表单
*
* @param sheetName 工作表的名称
* @param title 标题
* @return 结果
*/
public AjaxResult importTemplateExcel(String sheetName, String title)
{
this.init(null, sheetName, title, Type.IMPORT);
return exportExcel();
}
/**
* 对list数据源将其里面的数据导入到excel表单
*
* @param sheetName 工作表的名称 * @param sheetName 工作表的名称
* @return 结果 * @return 结果
*/ */
@ -509,7 +553,7 @@ public class ExcelUtil<T>
/** /**
* 对list数据源将其里面的数据导入到excel表单 * 对list数据源将其里面的数据导入到excel表单
* *
* @param sheetName 工作表的名称 * @param sheetName 工作表的名称
* @param title 标题 * @param title 标题
* @return 结果 * @return 结果
@ -544,6 +588,34 @@ public class ExcelUtil<T>
} }
} }
/**
* 对list数据源将其里面的数据导入到excel表单
*
* @return 结果
*/
public AjaxResult exportExcel()
{
OutputStream out = null;
try
{
writeSheet();
String filename = encodingFilename(sheetName);
out = new FileOutputStream(getAbsoluteFile(filename));
wb.write(out);
return AjaxResult.success(filename);
}
catch (Exception e)
{
log.error("导出Excel异常{}", e.getMessage());
throw new UtilException("导出Excel失败请联系网站管理员");
}
finally
{
IOUtils.closeQuietly(wb);
IOUtils.closeQuietly(out);
}
}
/** /**
* 创建写入数据到Sheet * 创建写入数据到Sheet
*/ */
@ -595,91 +667,64 @@ public class ExcelUtil<T>
{ {
int startNo = index * sheetSize; int startNo = index * sheetSize;
int endNo = Math.min(startNo + sheetSize, list.size()); int endNo = Math.min(startNo + sheetSize, list.size());
int currentRowNum = rownum + 1; // 从标题行后开始 int rowNo = (1 + rownum) - startNo;
for (int i = startNo; i < endNo; i++) for (int i = startNo; i < endNo; i++)
{ {
row = sheet.createRow(currentRowNum); rowNo = isSubList() ? (i > 1 ? rowNo + 1 : rowNo + i) : i + 1 + rownum - startNo;
row = sheet.createRow(rowNo);
// 得到导出对象.
T vo = (T) list.get(i); T vo = (T) list.get(i);
Collection<?> subList = null;
if (isSubList())
{
if (isSubListValue(vo))
{
subList = getListCellValue(vo);
subMergedLastRowNum = subMergedLastRowNum + subList.size();
}
else
{
subMergedFirstRowNum++;
subMergedLastRowNum++;
}
}
int column = 0; int column = 0;
int maxSubListSize = getCurrentMaxSubListSize(vo);
for (Object[] os : fields) for (Object[] os : fields)
{ {
Field field = (Field) os[0]; Field field = (Field) os[0];
Excel excel = (Excel) os[1]; Excel excel = (Excel) os[1];
if (Collection.class.isAssignableFrom(field.getType())) if (Collection.class.isAssignableFrom(field.getType()) && StringUtils.isNotNull(subList))
{ {
try boolean subFirst = false;
for (Object obj : subList)
{ {
Collection<?> subList = (Collection<?>) getTargetValue(vo, field, excel); if (subFirst)
if (subList != null && !subList.isEmpty())
{ {
int subIndex = 0; rowNo++;
for (Object subVo : subList) row = sheet.createRow(rowNo);
{
Row subRow = sheet.getRow(currentRowNum + subIndex);
if (subRow == null)
{
subRow = sheet.createRow(currentRowNum + subIndex);
}
int subColumn = column;
for (Field subField : subFields)
{
Excel subExcel = subField.getAnnotation(Excel.class);
addCell(subExcel, subRow, (T) subVo, subField, subColumn++);
}
subIndex++;
}
column += subFields.size();
} }
List<Field> subFields = FieldUtils.getFieldsListWithAnnotation(obj.getClass(), Excel.class);
int subIndex = 0;
for (Field subField : subFields)
{
if (subField.isAnnotationPresent(Excel.class))
{
subField.setAccessible(true);
Excel attr = subField.getAnnotation(Excel.class);
this.addCell(attr, row, (T) obj, subField, column + subIndex);
}
subIndex++;
}
subFirst = true;
} }
catch (Exception e) this.subMergedFirstRowNum = this.subMergedFirstRowNum + subList.size();
{
log.error("填充集合数据失败", e);
}
} }
else else
{ {
// 创建单元格并设置值 this.addCell(excel, row, vo, field, column++);
addCell(excel, row, vo, field, column);
if (maxSubListSize > 1 && excel.needMerge())
{
sheet.addMergedRegion(new CellRangeAddress(currentRowNum, currentRowNum + maxSubListSize - 1, column, column));
}
column++;
}
}
currentRowNum += maxSubListSize;
}
}
/**
* 获取子列表最大数
*/
private int getCurrentMaxSubListSize(T vo)
{
int maxSubListSize = 1;
for (Object[] os : fields)
{
Field field = (Field) os[0];
if (Collection.class.isAssignableFrom(field.getType()))
{
try
{
Collection<?> subList = (Collection<?>) getTargetValue(vo, field, (Excel) os[1]);
if (subList != null && !subList.isEmpty())
{
maxSubListSize = Math.max(maxSubListSize, subList.size());
}
}
catch (Exception e)
{
log.error("获取集合大小失败", e);
} }
} }
} }
return maxSubListSize;
} }
/** /**
@ -814,7 +859,7 @@ public class ExcelUtil<T>
*/ */
public void annotationDataStyles(Map<String, CellStyle> styles, Field field, Excel excel) public void annotationDataStyles(Map<String, CellStyle> styles, Field field, Excel excel)
{ {
String key = StringUtils.format("data_{}_{}_{}_{}_{}", excel.align(), excel.color(), excel.backgroundColor(), excel.cellType(), excel.wrapText()); String key = StringUtils.format("data_{}_{}_{}_{}", excel.align(), excel.color(), excel.backgroundColor(), excel.cellType());
if (!styles.containsKey(key)) if (!styles.containsKey(key))
{ {
CellStyle style = wb.createCellStyle(); CellStyle style = wb.createCellStyle();
@ -830,7 +875,6 @@ public class ExcelUtil<T>
style.setBottomBorderColor(IndexedColors.GREY_50_PERCENT.getIndex()); style.setBottomBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
style.setFillPattern(FillPatternType.SOLID_FOREGROUND); style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
style.setFillForegroundColor(excel.backgroundColor().getIndex()); style.setFillForegroundColor(excel.backgroundColor().getIndex());
style.setWrapText(excel.wrapText());
Font dataFont = wb.createFont(); Font dataFont = wb.createFont();
dataFont.setFontName("Arial"); dataFont.setFontName("Arial");
dataFont.setFontHeightInPoints((short) 10); dataFont.setFontHeightInPoints((short) 10);
@ -859,7 +903,7 @@ public class ExcelUtil<T>
if (isSubList()) if (isSubList())
{ {
// 填充默认样式防止合并单元格样式失效 // 填充默认样式防止合并单元格样式失效
sheet.setDefaultColumnStyle(column, styles.get(StringUtils.format("data_{}_{}_{}_{}_{}", attr.align(), attr.color(), attr.backgroundColor(), attr.cellType(), attr.wrapText()))); sheet.setDefaultColumnStyle(column, styles.get(StringUtils.format("data_{}_{}_{}_{}", attr.align(), attr.color(), attr.backgroundColor(), attr.cellType())));
if (attr.needMerge()) if (attr.needMerge())
{ {
sheet.addMergedRegion(new CellRangeAddress(rownum - 1, rownum, column, column)); sheet.addMergedRegion(new CellRangeAddress(rownum - 1, rownum, column, column));
@ -954,17 +998,28 @@ public class ExcelUtil<T>
// 设置列宽 // 设置列宽
sheet.setColumnWidth(column, (int) ((attr.width() + 0.72) * 256)); sheet.setColumnWidth(column, (int) ((attr.width() + 0.72) * 256));
} }
if (StringUtils.isNotEmpty(attr.prompt()) || attr.combo().length > 0) if (StringUtils.isNotEmpty(attr.prompt()) || attr.combo().length > 0 || attr.comboReadDict())
{ {
if (attr.combo().length > 15 || StringUtils.join(attr.combo()).length() > 255) String[] comboArray = attr.combo();
if (attr.comboReadDict())
{
if (!sysDictMap.containsKey("combo_" + attr.dictType()))
{
String labels = DictUtils.getDictLabels(attr.dictType());
sysDictMap.put("combo_" + attr.dictType(), labels);
}
String val = sysDictMap.get("combo_" + attr.dictType());
comboArray = StringUtils.split(val, DictUtils.SEPARATOR);
}
if (comboArray.length > 15 || StringUtils.join(comboArray).length() > 255)
{ {
// 如果下拉数大于15或字符串长度大于255则使用一个新sheet存储避免生成的模板下拉值获取不到 // 如果下拉数大于15或字符串长度大于255则使用一个新sheet存储避免生成的模板下拉值获取不到
setXSSFValidationWithHidden(sheet, attr.combo(), attr.prompt(), 1, 100, column, column); setXSSFValidationWithHidden(sheet, comboArray, attr.prompt(), 1, 100, column, column);
} }
else else
{ {
// 提示信息或只能选择不能输入的列内容. // 提示信息或只能选择不能输入的列内容.
setPromptOrValidation(sheet, attr.combo(), attr.prompt(), 1, 100, column, column); setPromptOrValidation(sheet, comboArray, attr.prompt(), 1, 100, column, column);
} }
} }
} }
@ -986,27 +1041,34 @@ public class ExcelUtil<T>
cell = row.createCell(column); cell = row.createCell(column);
if (isSubListValue(vo) && getListCellValue(vo).size() > 1 && attr.needMerge()) if (isSubListValue(vo) && getListCellValue(vo).size() > 1 && attr.needMerge())
{ {
if (subMergedLastRowNum >= subMergedFirstRowNum) CellRangeAddress cellAddress = new CellRangeAddress(subMergedFirstRowNum, subMergedLastRowNum, column, column);
{ sheet.addMergedRegion(cellAddress);
sheet.addMergedRegion(new CellRangeAddress(subMergedFirstRowNum, subMergedLastRowNum, column, column));
}
} }
cell.setCellStyle(styles.get(StringUtils.format("data_{}_{}_{}_{}_{}", attr.align(), attr.color(), attr.backgroundColor(), attr.cellType(), attr.wrapText()))); cell.setCellStyle(styles.get(StringUtils.format("data_{}_{}_{}_{}", attr.align(), attr.color(), attr.backgroundColor(), attr.cellType())));
// 用于读取对象中的属性 // 用于读取对象中的属性
Object value = getTargetValue(vo, field, attr); Object value = getTargetValue(vo, field, attr);
String dateFormat = attr.dateFormat(); String dateFormat = attr.dateFormat();
String readConverterExp = attr.readConverterExp(); String readConverterExp = attr.readConverterExp();
String separator = attr.separator(); String separator = attr.separator();
String dictType = attr.dictType();
if (StringUtils.isNotEmpty(dateFormat) && StringUtils.isNotNull(value)) if (StringUtils.isNotEmpty(dateFormat) && StringUtils.isNotNull(value))
{ {
cell.getCellStyle().setDataFormat(this.wb.getCreationHelper().createDataFormat().getFormat(dateFormat));
cell.setCellValue(parseDateToStr(dateFormat, value)); cell.setCellValue(parseDateToStr(dateFormat, value));
} }
else if (StringUtils.isNotEmpty(readConverterExp) && StringUtils.isNotNull(value)) else if (StringUtils.isNotEmpty(readConverterExp) && StringUtils.isNotNull(value))
{ {
cell.setCellValue(convertByExp(Convert.toStr(value), readConverterExp, separator)); cell.setCellValue(convertByExp(Convert.toStr(value), readConverterExp, separator));
} }
else if (StringUtils.isNotEmpty(dictType) && StringUtils.isNotNull(value))
{
if (!sysDictMap.containsKey(dictType + value))
{
String lable = convertDictByExp(Convert.toStr(value), dictType, separator);
sysDictMap.put(dictType + value, lable);
}
cell.setCellValue(sysDictMap.get(dictType + value));
}
else if (value instanceof BigDecimal && -1 != attr.scale()) else if (value instanceof BigDecimal && -1 != attr.scale())
{ {
cell.setCellValue((((BigDecimal) value).setScale(attr.scale(), attr.roundingMode())).doubleValue()); cell.setCellValue((((BigDecimal) value).setScale(attr.scale(), attr.roundingMode())).doubleValue());
@ -1193,9 +1255,35 @@ public class ExcelUtil<T>
return StringUtils.stripEnd(propertyString.toString(), separator); return StringUtils.stripEnd(propertyString.toString(), separator);
} }
/**
* 解析字典值
*
* @param dictValue 字典值
* @param dictType 字典类型
* @param separator 分隔符
* @return 字典标签
*/
public static String convertDictByExp(String dictValue, String dictType, String separator)
{
return DictUtils.getDictLabel(dictType, dictValue, separator);
}
/**
* 反向解析值字典值
*
* @param dictLabel 字典标签
* @param dictType 字典类型
* @param separator 分隔符
* @return 字典值
*/
public static String reverseDictByExp(String dictLabel, String dictType, String separator)
{
return DictUtils.getDictValue(dictType, dictLabel, separator);
}
/** /**
* 数据处理器 * 数据处理器
* *
* @param value 数据值 * @param value 数据值
* @param excel 数据注解 * @param excel 数据注解
* @return * @return
@ -1261,9 +1349,34 @@ public class ExcelUtil<T>
} }
} }
/**
* 编码文件名
*/
public String encodingFilename(String filename)
{
filename = UUID.randomUUID() + "_" + filename + ".xlsx";
return filename;
}
/**
* 获取下载路径
*
* @param filename 文件名称
*/
public String getAbsoluteFile(String filename)
{
String downloadPath = TcctynConfig.getDownloadPath() + filename;
File desc = new File(downloadPath);
if (!desc.getParentFile().exists())
{
desc.getParentFile().mkdirs();
}
return downloadPath;
}
/** /**
* 获取bean中的属性值 * 获取bean中的属性值
* *
* @param vo 实体对象 * @param vo 实体对象
* @param field 字段 * @param field 字段
* @param excel 注解 * @param excel 注解
@ -1272,7 +1385,6 @@ public class ExcelUtil<T>
*/ */
private Object getTargetValue(T vo, Field field, Excel excel) throws Exception private Object getTargetValue(T vo, Field field, Excel excel) throws Exception
{ {
field.setAccessible(true);
Object o = field.get(vo); Object o = field.get(vo);
if (StringUtils.isNotEmpty(excel.targetAttr())) if (StringUtils.isNotEmpty(excel.targetAttr()))
{ {
@ -1295,7 +1407,7 @@ public class ExcelUtil<T>
/** /**
* 以类的属性的get方法方法形式获取值 * 以类的属性的get方法方法形式获取值
* *
* @param o * @param o
* @param name * @param name
* @return value * @return value
@ -1332,85 +1444,48 @@ public class ExcelUtil<T>
List<Field> tempFields = new ArrayList<>(); List<Field> tempFields = new ArrayList<>();
tempFields.addAll(Arrays.asList(clazz.getSuperclass().getDeclaredFields())); tempFields.addAll(Arrays.asList(clazz.getSuperclass().getDeclaredFields()));
tempFields.addAll(Arrays.asList(clazz.getDeclaredFields())); tempFields.addAll(Arrays.asList(clazz.getDeclaredFields()));
if (StringUtils.isNotEmpty(includeFields)) for (Field field : tempFields)
{ {
for (Field field : tempFields) if (!ArrayUtils.contains(this.excludeFields, field.getName()))
{ {
if (ArrayUtils.contains(this.includeFields, field.getName()) || field.isAnnotationPresent(Excels.class)) // 单注解
if (field.isAnnotationPresent(Excel.class))
{ {
addField(fields, field); Excel attr = field.getAnnotation(Excel.class);
if (attr != null && (attr.type() == Type.ALL || attr.type() == type))
{
field.setAccessible(true);
fields.add(new Object[] { field, attr });
}
if (Collection.class.isAssignableFrom(field.getType()))
{
subMethod = getSubMethod(field.getName(), clazz);
ParameterizedType pt = (ParameterizedType) field.getGenericType();
Class<?> subClass = (Class<?>) pt.getActualTypeArguments()[0];
this.subFields = FieldUtils.getFieldsListWithAnnotation(subClass, Excel.class);
}
} }
}
} // 多注解
else if (StringUtils.isNotEmpty(excludeFields)) if (field.isAnnotationPresent(Excels.class))
{
for (Field field : tempFields)
{
if (!ArrayUtils.contains(this.excludeFields, field.getName()))
{ {
addField(fields, field); Excels attrs = field.getAnnotation(Excels.class);
Excel[] excels = attrs.value();
for (Excel attr : excels)
{
if (!ArrayUtils.contains(this.excludeFields, field.getName() + "." + attr.targetAttr())
&& (attr != null && (attr.type() == Type.ALL || attr.type() == type)))
{
field.setAccessible(true);
fields.add(new Object[] { field, attr });
}
}
} }
} }
} }
else
{
for (Field field : tempFields)
{
addField(fields, field);
}
}
return fields; return fields;
} }
/**
* 添加字段信息
*/
public void addField(List<Object[]> fields, Field field)
{
// 单注解
if (field.isAnnotationPresent(Excel.class))
{
Excel attr = field.getAnnotation(Excel.class);
if (attr != null && (attr.type() == Type.ALL || attr.type() == type))
{
fields.add(new Object[] { field, attr });
}
if (Collection.class.isAssignableFrom(field.getType()))
{
subMethod = getSubMethod(field.getName(), clazz);
ParameterizedType pt = (ParameterizedType) field.getGenericType();
Class<?> subClass = (Class<?>) pt.getActualTypeArguments()[0];
this.subFields = FieldUtils.getFieldsListWithAnnotation(subClass, Excel.class);
}
}
// 多注解
if (field.isAnnotationPresent(Excels.class))
{
Excels attrs = field.getAnnotation(Excels.class);
Excel[] excels = attrs.value();
for (Excel attr : excels)
{
if (StringUtils.isNotEmpty(includeFields))
{
if (ArrayUtils.contains(this.includeFields, field.getName() + "." + attr.targetAttr())
&& (attr != null && (attr.type() == Type.ALL || attr.type() == type)))
{
fields.add(new Object[] { field, attr });
}
}
else
{
if (!ArrayUtils.contains(this.excludeFields, field.getName() + "." + attr.targetAttr())
&& (attr != null && (attr.type() == Type.ALL || attr.type() == type)))
{
fields.add(new Object[] { field, attr });
}
}
}
}
}
/** /**
* 根据注解获取最大行高 * 根据注解获取最大行高
*/ */
@ -1536,6 +1611,71 @@ public class ExcelUtil<T>
return true; return true;
} }
/**
* 获取Excel2003图片
*
* @param sheet 当前sheet对象
* @param workbook 工作簿对象
* @return Map key:图片单元格索引1_1Stringvalue:图片流PictureData
*/
public static Map<String, PictureData> getSheetPictures03(HSSFSheet sheet, HSSFWorkbook workbook)
{
Map<String, PictureData> sheetIndexPicMap = new HashMap<String, PictureData>();
List<HSSFPictureData> pictures = workbook.getAllPictures();
if (!pictures.isEmpty())
{
for (HSSFShape shape : sheet.getDrawingPatriarch().getChildren())
{
HSSFClientAnchor anchor = (HSSFClientAnchor) shape.getAnchor();
if (shape instanceof HSSFPicture)
{
HSSFPicture pic = (HSSFPicture) shape;
int pictureIndex = pic.getPictureIndex() - 1;
HSSFPictureData picData = pictures.get(pictureIndex);
String picIndex = anchor.getRow1() + "_" + anchor.getCol1();
sheetIndexPicMap.put(picIndex, picData);
}
}
return sheetIndexPicMap;
}
else
{
return sheetIndexPicMap;
}
}
/**
* 获取Excel2007图片
*
* @param sheet 当前sheet对象
* @param workbook 工作簿对象
* @return Map key:图片单元格索引1_1Stringvalue:图片流PictureData
*/
public static Map<String, PictureData> getSheetPictures07(XSSFSheet sheet, XSSFWorkbook workbook)
{
Map<String, PictureData> sheetIndexPicMap = new HashMap<String, PictureData>();
for (POIXMLDocumentPart dr : sheet.getRelations())
{
if (dr instanceof XSSFDrawing)
{
XSSFDrawing drawing = (XSSFDrawing) dr;
List<XSSFShape> shapes = drawing.getShapes();
for (XSSFShape shape : shapes)
{
if (shape instanceof XSSFPicture)
{
XSSFPicture pic = (XSSFPicture) shape;
XSSFClientAnchor anchor = pic.getPreferredSize();
CTMarker ctMarker = anchor.getFrom();
String picIndex = ctMarker.getRow() + "_" + ctMarker.getCol();
sheetIndexPicMap.put(picIndex, pic.getPictureData());
}
}
}
}
return sheetIndexPicMap;
}
/** /**
* 格式化不同类型的日期对象 * 格式化不同类型的日期对象
* *

View File

@ -1,19 +1,15 @@
package com.tcctyn.common.core.utils.reflect; package com.tcctyn.common.core.utils.reflect;
import java.lang.reflect.Field; import com.tcctyn.common.core.text.Convert;
import java.lang.reflect.InvocationTargetException; import com.tcctyn.common.core.utils.DateUtils;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Date;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate; import org.apache.commons.lang3.Validate;
import org.apache.poi.ss.usermodel.DateUtil; import org.apache.poi.ss.usermodel.DateUtil;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import com.tcctyn.common.core.text.Convert;
import com.tcctyn.common.core.utils.DateUtils; import java.lang.reflect.*;
import java.util.Date;
/** /**
* 反射工具类. 提供调用getter/setter方法, 访问私有变量, 调用私有方法, 获取泛型类型Class, 被AOP过的真实类等工具函数. * 反射工具类. 提供调用getter/setter方法, 访问私有变量, 调用私有方法, 获取泛型类型Class, 被AOP过的真实类等工具函数.

View File

@ -0,0 +1,68 @@
package com.tcctyn.common.core.utils.sign;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
/**
* Md5加密方法
*
* @author tcctyn
*/
public class Md5Utils
{
private static final Logger log = LoggerFactory.getLogger(Md5Utils.class);
private static byte[] md5(String s)
{
MessageDigest algorithm;
try
{
algorithm = MessageDigest.getInstance("MD5");
algorithm.reset();
algorithm.update(s.getBytes("UTF-8"));
byte[] messageDigest = algorithm.digest();
return messageDigest;
}
catch (Exception e)
{
log.error("MD5 Error...", e);
}
return null;
}
private static final String toHex(byte hash[])
{
if (hash == null)
{
return null;
}
StringBuffer buf = new StringBuffer(hash.length * 2);
int i;
for (i = 0; i < hash.length; i++)
{
if ((hash[i] & 0xff) < 0x10)
{
buf.append("0");
}
buf.append(Long.toString(hash[i] & 0xff, 16));
}
return buf.toString();
}
public static String hash(String s)
{
try
{
return new String(toHex(md5(s)).getBytes(StandardCharsets.UTF_8), StandardCharsets.UTF_8);
}
catch (Exception e)
{
log.error("not supported charset...{}", e);
return s;
}
}
}

View File

@ -13,7 +13,7 @@ public class SqlUtil
/** /**
* 定义常用的 sql关键字 * 定义常用的 sql关键字
*/ */
public static String SQL_REGEX = "\u000B|and |extractvalue|updatexml|sleep|exec |insert |select |delete |update |drop |count |chr |mid |master |truncate |char |declare |or |union |like |+|/*|user()"; public static String SQL_REGEX = "and |extractvalue|updatexml|exec |insert |select |delete |update |drop |count |chr |mid |master |truncate |char |declare |or |+|user()";
/** /**
* 仅支持字母数字下划线空格逗号小数点支持多个字段排序 * 仅支持字母数字下划线空格逗号小数点支持多个字段排序

View File

@ -1,9 +1,10 @@
package com.tcctyn.common.core.utils.uuid; package com.tcctyn.common.core.utils.uuid;
import java.util.concurrent.atomic.AtomicInteger;
import com.tcctyn.common.core.utils.DateUtils; import com.tcctyn.common.core.utils.DateUtils;
import com.tcctyn.common.core.utils.StringUtils; import com.tcctyn.common.core.utils.StringUtils;
import java.util.concurrent.atomic.AtomicInteger;
/** /**
* @author tcctyn 序列生成类 * @author tcctyn 序列生成类
*/ */

View File

@ -1,11 +1,12 @@
package com.tcctyn.common.core.utils.uuid; package com.tcctyn.common.core.utils.uuid;
import com.tcctyn.common.core.exception.UtilException;
import java.security.MessageDigest; import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom; import java.security.SecureRandom;
import java.util.Random; import java.util.Random;
import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.ThreadLocalRandom;
import com.tcctyn.common.core.exception.UtilException;
/** /**
* 提供通用唯一识别码universally unique identifierUUID实现 * 提供通用唯一识别码universally unique identifierUUID实现
@ -66,7 +67,7 @@ public final class UUID implements java.io.Serializable, Comparable<UUID>
} }
/** /**
* 获取类型 4伪随机生成的UUID 的静态工厂 * 获取类型 4伪随机生成的UUID 的静态工厂
* *
* @return 随机生成的 {@code UUID} * @return 随机生成的 {@code UUID}
*/ */

View File

@ -1,45 +1,44 @@
package com.tcctyn.common.core.web.controller; package com.tcctyn.common.core.web.controller;
import java.beans.PropertyEditorSupport; import com.github.pagehelper.PageHelper;
import java.util.Date; import com.github.pagehelper.PageInfo;
import java.util.List; import com.tcctyn.common.core.constant.HttpStatus;
import com.tcctyn.common.core.web.domain.AjaxResult;
import com.tcctyn.common.core.web.domain.model.LoginUser;
import com.tcctyn.common.core.web.page.PageDomain;
import com.tcctyn.common.core.web.page.TableDataInfo;
import com.tcctyn.common.core.web.page.TableSupport;
import com.tcctyn.common.core.utils.DateUtils;
import com.tcctyn.common.core.utils.PageUtils;
import com.tcctyn.common.core.utils.SecurityUtils;
import com.tcctyn.common.core.utils.StringUtils;
import com.tcctyn.common.core.utils.sql.SqlUtil;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.web.bind.WebDataBinder; import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder; import org.springframework.web.bind.annotation.InitBinder;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo; import java.beans.PropertyEditorSupport;
import com.tcctyn.common.core.constant.HttpStatus; import java.util.Date;
import com.tcctyn.common.core.utils.DateUtils; import java.util.List;
import com.tcctyn.common.core.utils.PageUtils;
import com.tcctyn.common.core.utils.StringUtils;
import com.tcctyn.common.core.utils.sql.SqlUtil;
import com.tcctyn.common.core.web.domain.AjaxResult;
import com.tcctyn.common.core.web.page.PageDomain;
import com.tcctyn.common.core.web.page.TableDataInfo;
import com.tcctyn.common.core.web.page.TableSupport;
/** /**
* web层通用数据处理 * web层通用数据处理
* *
* @author tcctyn * @author tcctyn
*/ */
public class BaseController public class BaseController {
{
protected final Logger logger = LoggerFactory.getLogger(this.getClass()); protected final Logger logger = LoggerFactory.getLogger(this.getClass());
/** /**
* 将前台传递过来的日期格式的字符串自动转化为Date类型 * 将前台传递过来的日期格式的字符串自动转化为Date类型
*/ */
@InitBinder @InitBinder
public void initBinder(WebDataBinder binder) public void initBinder(WebDataBinder binder) {
{
// Date 类型转换 // Date 类型转换
binder.registerCustomEditor(Date.class, new PropertyEditorSupport() binder.registerCustomEditor(Date.class, new PropertyEditorSupport() {
{
@Override @Override
public void setAsText(String text) public void setAsText(String text) {
{
setValue(DateUtils.parseDate(text)); setValue(DateUtils.parseDate(text));
} }
}); });
@ -48,19 +47,16 @@ public class BaseController
/** /**
* 设置请求分页数据 * 设置请求分页数据
*/ */
protected void startPage() protected void startPage() {
{
PageUtils.startPage(); PageUtils.startPage();
} }
/** /**
* 设置请求排序数据 * 设置请求排序数据
*/ */
protected void startOrderBy() protected void startOrderBy() {
{
PageDomain pageDomain = TableSupport.buildPageRequest(); PageDomain pageDomain = TableSupport.buildPageRequest();
if (StringUtils.isNotEmpty(pageDomain.getOrderBy())) if (StringUtils.isNotEmpty(pageDomain.getOrderBy())) {
{
String orderBy = SqlUtil.escapeOrderBySql(pageDomain.getOrderBy()); String orderBy = SqlUtil.escapeOrderBySql(pageDomain.getOrderBy());
PageHelper.orderBy(orderBy); PageHelper.orderBy(orderBy);
} }
@ -69,92 +65,132 @@ public class BaseController
/** /**
* 清理分页的线程变量 * 清理分页的线程变量
*/ */
protected void clearPage() protected void clearPage() {
{
PageUtils.clearPage(); PageUtils.clearPage();
} }
/** /**
* 响应请求分页数据 * 响应请求分页数据
*/ */
@SuppressWarnings({ "rawtypes", "unchecked" }) @SuppressWarnings({"rawtypes", "unchecked"})
protected TableDataInfo getDataTable(List<?> list) protected TableDataInfo getDataTable(List<?> list) {
{
TableDataInfo rspData = new TableDataInfo(); TableDataInfo rspData = new TableDataInfo();
rspData.setCode(HttpStatus.SUCCESS); rspData.setCode(HttpStatus.SUCCESS);
rspData.setRows(list);
rspData.setMsg("查询成功"); rspData.setMsg("查询成功");
rspData.setRows(list);
rspData.setTotal(new PageInfo(list).getTotal()); rspData.setTotal(new PageInfo(list).getTotal());
return rspData; return rspData;
} }
/**
* 涉及到DO转VO的使用下面这个方法
* @Param dolist 数据库查询出来的list
* @Param volist 前台展示的list
*/
protected TableDataInfo getDataTable(List<?> dolist, List<?> voList) {
TableDataInfo rspData = new TableDataInfo();
rspData.setCode(HttpStatus.SUCCESS);
rspData.setMsg("查询成功");
rspData.setRows(voList);
rspData.setTotal(new PageInfo(dolist).getTotal());
return rspData;
}
/** /**
* 返回成功 * 返回成功
*/ */
public AjaxResult success() public AjaxResult success() {
{
return AjaxResult.success(); return AjaxResult.success();
} }
/**
* 返回失败消息
*/
public AjaxResult error() {
return AjaxResult.error();
}
/** /**
* 返回成功消息 * 返回成功消息
*/ */
public AjaxResult success(String message) public AjaxResult success(String message) {
{
return AjaxResult.success(message); return AjaxResult.success(message);
} }
/** /**
* 返回成功消息 * 返回成功消息
*/ */
public AjaxResult success(Object data) public AjaxResult success(Object data) {
{
return AjaxResult.success(data); return AjaxResult.success(data);
} }
/** /**
* 返回失败消息 * 返回失败消息
*/ */
public AjaxResult error() public AjaxResult error(String message) {
{
return AjaxResult.error();
}
/**
* 返回失败消息
*/
public AjaxResult error(String message)
{
return AjaxResult.error(message); return AjaxResult.error(message);
} }
/** /**
* 返回警告消息 * 返回警告消息
*/ */
public AjaxResult warn(String message) public AjaxResult warn(String message) {
{
return AjaxResult.warn(message); return AjaxResult.warn(message);
} }
/** /**
* 响应返回结果 * 响应返回结果
* *
* @param rows 影响行数 * @param rows 影响行数
* @return 操作结果 * @return 操作结果
*/ */
protected AjaxResult toAjax(int rows) protected AjaxResult toAjax(int rows) {
{
return rows > 0 ? AjaxResult.success() : AjaxResult.error(); return rows > 0 ? AjaxResult.success() : AjaxResult.error();
} }
/** /**
* 响应返回结果 * 响应返回结果
* *
* @param result 结果 * @param result 结果
* @return 操作结果 * @return 操作结果
*/ */
protected AjaxResult toAjax(boolean result) protected AjaxResult toAjax(boolean result) {
{
return result ? success() : error(); return result ? success() : error();
} }
/**
* 页面跳转
*/
public String redirect(String url) {
return StringUtils.format("redirect:{}", url);
}
/**
* 获取用户缓存信息
*/
public LoginUser getLoginUser() {
return SecurityUtils.getLoginUser();
}
/**
* 获取登录用户id
*/
public Long getUserId() {
return getLoginUser().getUserId();
}
/**
* 获取登录部门id
*/
public Long getDeptId() {
return getLoginUser().getDeptId();
}
/**
* 获取登录用户名
*/
public String getUsername() {
return getLoginUser().getUsername();
}
} }

View File

@ -1,9 +1,10 @@
package com.tcctyn.common.core.web.domain; package com.tcctyn.common.core.web.domain;
import com.tcctyn.common.core.constant.HttpStatus;
import com.tcctyn.common.core.utils.StringUtils;
import java.util.HashMap; import java.util.HashMap;
import java.util.Objects; import java.util.Objects;
import com.tcctyn.common.core.constant.HttpStatus;
import com.tcctyn.common.core.utils.StringUtils;
/** /**
* 操作消息提醒 * 操作消息提醒
@ -203,9 +204,9 @@ public class AjaxResult extends HashMap<String, Object>
/** /**
* 方便链式调用 * 方便链式调用
* *
* @param key * @param key
* @param value * @param value
* @return * @return 数据对象
*/ */
@Override @Override
public AjaxResult put(String key, Object value) public AjaxResult put(String key, Object value)

View File

@ -1,12 +1,14 @@
package com.tcctyn.common.core.web.domain; package com.tcctyn.common.core.web.domain;
import com.baomidou.mybatisplus.annotation.TableField;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import java.io.Serializable; import java.io.Serializable;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
/** /**
* Entity基类 * Entity基类
@ -19,6 +21,7 @@ public class BaseEntity implements Serializable
/** 搜索值 */ /** 搜索值 */
@JsonIgnore @JsonIgnore
@TableField(exist = false)
private String searchValue; private String searchValue;
/** 创建者 */ /** 创建者 */
@ -36,10 +39,12 @@ public class BaseEntity implements Serializable
private Date updateTime; private Date updateTime;
/** 备注 */ /** 备注 */
@TableField(exist = false)
private String remark; private String remark;
/** 请求参数 */ /** 请求参数 */
@JsonInclude(JsonInclude.Include.NON_EMPTY) @JsonInclude(JsonInclude.Include.NON_EMPTY)
@TableField(exist = false)
private Map<String, Object> params; private Map<String, Object> params;
public String getSearchValue() public String getSearchValue()

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