MessageFormat.format
public String getKey(){
return MessageFormat.format("{0}:{1}:{2}:{3}:{4}:{5}:{6}",
systemType.getCode(),
applySystemType.getCode(),
budgetSystemType.getCode(),
protocolSystemType.getCode(),
goodsSystemType.getCode(),
startParty.getCode(),
countType.getCode());
}
list转Map
Map<Long, OrderItemModel> orderItemModelMap = orderItemModelList.stream().collect(Collectors.toMap(OrderItemModel::getId, Function.identity(), (k1, k2) -> (k1)));
Map<String,Integer> fieldMap = entExtendFieldConfigVOList.stream().collect(Collectors.toMap(EntExtendFieldConfigVO::getFieldName,EntExtendFieldConfigVO::getFieldType,(k1,k2)->k1));
根据list对象中某一个字段去重
List<OuterProjectQryModel.EsbDate.MasterDate.DataInfos.DataInfo> dataInfoList = orgDataInfoList.stream().sorted(Comparator.comparing(OuterProjectQryModel.EsbDate.MasterDate.DataInfos.DataInfo::getLASTMODIFYRECORDTIME).reversed())
.distinct().collect(Collectors.toList())
.stream()
.filter(distinctByKey( t -> t.getPRJ_CODE()))
.collect(Collectors.toList());
private static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
ConcurrentHashMap<Object, Boolean> map = new ConcurrentHashMap<>();
return t -> map.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
}
list根据时间降序排列
List<AuditLog> auditLogs = auditLogList.stream().sorted(Comparator.comparing(AuditLog::getCreateTime,Comparator.nullsFirst(Comparator.naturalOrder())).reversed()).collect(Collectors.toList());
函数编程IF ELSE转化
@FunctionalInterface
public interface Branch {
void trueOrFalseHandle(Runnable trueHandle, Runnable falseHandle);
}
package net.zywx.oa.project.func;
public class BranchUtil {
public static Branch isTureOrFalse(boolean b){
return (trueHandle, falseHandle) -> {
if (b){
trueHandle.run();
} else {
falseHandle.run();
}
};
}
}
public Branch isTureOrFalse(boolean b){
return (trueHandle, falseHandle) -> {
if (b){
trueHandle.run();
} else {
falseHandle.run();
}
};
}
BranchUtil.isTureOrFalse(deptUserIsNotNull).trueOrFalseHandle(() -> {
List<ProjectDeptTaskUser> taskUserList = projectDeptTaskDTO.getProjectDeptTaskUsers().stream().map(item -> {
item.setProjectTaskId(zyoaProjectDeptTask.getId());
item.setDelFlag("0");
return item;
}).collect(Collectors.toList());
int countBatchTaskUser = SpringUtil.getBean(ProjectDeptTaskUserMapper.class).batchInsert(taskUserList);
},() -> {
//无操作
});
代码生成器
package com.sunyur.tailor.channel.start;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class CodeGenerator {
/**
* <p>
* 读取控制台内容
* </p>
*/
public static String scanner(String tip) {
Scanner scanner = new Scanner(System.in);
StringBuilder help = new StringBuilder();
help.append("请输入" + tip + ":");
if (scanner.hasNext()) {
String ipt = scanner.next();
if (StringUtils.isNotBlank(ipt)) {
return ipt;
}
}
throw new MybatisPlusException("请输入正确的" + tip + "!");
}
public static void main(String[] args) {
// 代码生成器
AutoGenerator mpg = new AutoGenerator();
// 全局配置
GlobalConfig gc = new GlobalConfig();
String projectPath = System.getProperty("user.dir");
gc.setOutputDir(projectPath + "/src/main/java");
gc.setAuthor("jobob");
gc.setOpen(false);
// 代码生成器就不会生成LocalDateTime类型,而是Date类型
gc.setDateType(DateType.ONLY_DATE);
gc.setIdType(IdType.AUTO);
gc.setBaseColumnList(true);
gc.setBaseResultMap(true);
// gc.setSwagger2(true); 实体属性 Swagger2 注解
mpg.setGlobalConfig(gc);
// 数据源配置
DataSourceConfig dsc = new DataSourceConfig();
dsc.setUrl("jdbc:mysql://10.0.29.240:3306/api_channel?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT");
// dsc.setSchemaName("public");
dsc.setDriverName("com.mysql.jdbc.Driver");
dsc.setUsername("root");
dsc.setPassword("tK48Bwg12T");
mpg.setDataSource(dsc);
// 包配置
PackageConfig pc = new PackageConfig();
pc.setModuleName(scanner("模块名"));
pc.setParent("com.baomidou.ant");
mpg.setPackageInfo(pc);
// 自定义配置
InjectionConfig cfg = new InjectionConfig() {
@Override
public void initMap() {
// to do nothing
}
};
// 如果模板引擎是 freemarker
String templatePath = "/templates/mapper.xml.ftl";
// 如果模板引擎是 velocity
// String templatePath = "/templates/mapper.xml.vm";
// 自定义输出配置
List<FileOutConfig> focList = new ArrayList<>();
// 自定义配置会被优先输出
focList.add(new FileOutConfig(templatePath) {
@Override
public String outputFile(TableInfo tableInfo) {
// 自定义输出文件名 , 如果你 Entity 设置了前后缀、此处注意 xml 的名称会跟着发生变化!!
return projectPath + "/src/main/resources/mapper/" + pc.getModuleName()
+ "/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;
}
});
/*
cfg.setFileCreate(new IFileCreate() {
@Override
public boolean isCreate(ConfigBuilder configBuilder, FileType fileType, String filePath) {
// 判断自定义文件夹是否需要创建
checkDir("调用默认方法创建的目录,自定义目录用");
if (fileType == FileType.MAPPER) {
// 已经生成 mapper 文件判断存在,不想重新生成返回 false
return !new File(filePath).exists();
}
// 允许生成模板文件
return true;
}
});
*/
cfg.setFileOutConfigList(focList);
mpg.setCfg(cfg);
// 配置模板
TemplateConfig templateConfig = new TemplateConfig();
// 配置自定义输出模板
//指定自定义模板路径,注意不要带上.ftl/.vm, 会根据使用的模板引擎自动识别
// templateConfig.setEntity("templates/entity2.java");
// templateConfig.setService();
// templateConfig.setController();
templateConfig.setXml(null);
mpg.setTemplate(templateConfig);
// 策略配置
StrategyConfig strategy = new StrategyConfig();
strategy.setNaming(NamingStrategy.underline_to_camel);
strategy.setColumnNaming(NamingStrategy.underline_to_camel);
strategy.setEntityLombokModel(true);
strategy.setRestControllerStyle(true);
// 公共父类
// 写于父类中的公共字段
strategy.setSuperEntityColumns("id");
strategy.setInclude(scanner("表名,多个英文逗号分割").split(","));
strategy.setControllerMappingHyphenStyle(true);
strategy.setTablePrefix(pc.getModuleName() + "_");
mpg.setStrategy(strategy);
mpg.setTemplateEngine(new FreemarkerTemplateEngine());
mpg.execute();
}
}
if else优化技巧
Stream优化
Jdk1.8新特性Stream流有三个这样API,anyMatch,allMatch,noneMatch,各自的作用如下:
- anyMatch:判断条件里任意一个满足条件,则返回true;
- allMatch:判断条件里所有都满足条件,则返回true;
- noneMatch:判断条件里所有都不满足条件,则返回true;
List<String> list = Arrays.asList("a", "b", "c","d", "");
//任意一个字符串判断不为空则为true
boolean anyMatch = list.stream().anyMatch( s->StringUtils.isEmpty(s));
//所有字符串判断都不为空则为true
boolean allMatch = list.stream().allMatch( s->StringUtils.isEmpty(s));
//没有一个字符判断为空则为true
boolean noneMatch = list.stream().noneMatch( s->StringUtils.isEmpty(s));
Map优化
在定义map的时候,**使用到了一个ImmutableMap的东西,这是Google Guava里的一个类,可生成一个不可变的Map对象,这就意味着,初始化定义后,后续就无法再put修改了,它的这个特性可以保证线程的安全。**一般用来替换if-else的map,我们就是要求在初始化定义后,就不会再允许修改了,因此,这个ImmutableMap生成的map,可以很好地帮我们实现这一点。另外,最重要一点是,使用这个ImmutableMap,可以实现链式编程,就像上面定义的链式写法,若是用传统的map定义,就每次都要map.put()、map.put()地赋值。
public static final Map<String,String> dayMap= ImmutableMap.<String, String>builder()
.put("Monday","今天上英语课")
.put("Tuesday","今天上语文课")
.put("Wednesday","今天上数学课")
.put("Thursday","今天上音乐课")
.put("Sunday","今天上编程课")
.build();
public String getDay(String day){
return dayMap.get(day);
}
Optional类优化
String name=null;
if(school!=null){
Grades grade=school.getGrades();
if(grade!=null){
Student student=grade.getStuendt();
if(student!=null){
name = student.getName();
}
}
}
String name = Optional.ofNullable(school)
.flatMap(School::getGrades)
.flatMap(Grades::getStuendt)
.map(Student::getName)
.orElse(null);
从数据库查3小时以内的数据
lambdaQueryWrapper.apply("create_time >= DATE_SUB(NOW(),INTERVAL 3 HOUR)");
.apply("DATE_FORMAT(create_time,'%Y-%m') = DATE_FORMAT(NOW() - INTERVAL 1 MONTH,'%Y-%m')")));
反射给对象赋值
for (Field field : ProjectInfoQuery.getClass().getDeclaredFields()) {
field.setAccessible(true);
try {
String fieldName = field.getName();
String fieldValue = field.get(zyoaProjectInfoQuery).toString();
Integer fieldType = fieldMap.get(fieldName);
String value = "";
switch (fieldType) {
case 1:
value = "AND pe." + fieldPattern(fieldName) + " LIKE CONCAT('%', '" + fieldValue + "', '%')";
break;
field.setAccessible(true);
field.set(zyoaProjectInfoQuery, value);
}catch (Exception e){
e.printStackTrace();
}
}
date比较日期大小
SimpleDateFormat myFormatter = new SimpleDateFormat("yyyy-MM-dd");
myFormatter.setLenient(false);
timesAfter = myFormatter.parse(DateUtil.timestamp2Date(orderHeadModel.getCreateTime())).compareTo(myFormatter.parse("2023-12-01")) < 0;
GET请求URL特殊字符转义
@SneakyThrows
public <T> Result execGet(String path, String requestBody, TypeReference<SunyurResult<T>> typeReference){
LOGGER_INFO.info("SunyurClient execGet path:{}, requestBody:{}", path, requestBody);
String url = URLEncoder.encode(sunyurDomain + path, "UTF-8")
.replaceAll("%3A", ":")
.replaceAll("%2F", "/")
.replaceAll("%3F", "?")
.replaceAll("%3D", "=")
.replaceAll("%26", "&")
.replaceAll("\\+", "%20");
HttpGet http = new HttpGet(url);
SunyurResult result = new SunyurResult();
this.addHeader(path, requestBody, http);
HttpResponse httpResponse;
String responseBody;
try {
httpResponse = httpClient.execute(http);
responseBody = EntityUtils.toString(httpResponse.getEntity(), StandardCharsets.UTF_8);
} catch (IOException e) {
LOGGER_ERROR.error("SunyurClient execGet exception:{}", e);
result.setErrorMessage(MiddleResultEnum.EXCEPTION.getCode(), e.getMessage());
return result;
}
LOGGER_INFO.info("SunyurClient execGet path:{}, responseBody:{}", path, responseBody);
if (httpResponse.getStatusLine().getStatusCode() == 200) {
if (Objects.isNull(typeReference)) {
result = JSON.parseObject(responseBody, SunyurResult.class);
}else {
result = JSON.parseObject(responseBody, typeReference);
}
result.setContent(result.getContent());
return result;
} else {
result.setErrorMessage(MiddleResultEnum.FAILED.getCode(), MiddleResultEnum.FAILED.getValue());
}
return result;
}
UUID生成器
package net.zywx.oa.common.core.utils.uuid;
import net.zywx.oa.common.core.exception.UtilException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;
/**
* 提供通用唯一识别码(universally unique identifier)(UUID)实现
*
* @author ruoyi
*/
public final class UUID implements java.io.Serializable, Comparable<UUID>
{
private static final long serialVersionUID = -1185015143654744140L;
/**
* SecureRandom 的单例
*
*/
private static class Holder
{
static final SecureRandom numberGenerator = getSecureRandom();
}
/** 此UUID的最高64有效位 */
private final long mostSigBits;
/** 此UUID的最低64有效位 */
private final long leastSigBits;
/**
* 私有构造
*
* @param data 数据
*/
private UUID(byte[] data)
{
long msb = 0;
long lsb = 0;
assert data.length == 16 : "data must be 16 bytes in length";
for (int i = 0; i < 8; i++)
{
msb = (msb << 8) | (data[i] & 0xff);
}
for (int i = 8; i < 16; i++)
{
lsb = (lsb << 8) | (data[i] & 0xff);
}
this.mostSigBits = msb;
this.leastSigBits = lsb;
}
/**
* 使用指定的数据构造新的 UUID。
*
* @param mostSigBits 用于 {@code UUID} 的最高有效 64 位
* @param leastSigBits 用于 {@code UUID} 的最低有效 64 位
*/
public UUID(long mostSigBits, long leastSigBits)
{
this.mostSigBits = mostSigBits;
this.leastSigBits = leastSigBits;
}
/**
* 获取类型 4(伪随机生成的)UUID 的静态工厂。 使用加密的本地线程伪随机数生成器生成该 UUID。
*
* @return 随机生成的 {@code UUID}
*/
public static UUID fastUUID()
{
return randomUUID(false);
}
/**
* 获取类型 4(伪随机生成的)UUID 的静态工厂。 使用加密的强伪随机数生成器生成该 UUID。
*
* @return 随机生成的 {@code UUID}
*/
public static UUID randomUUID()
{
return randomUUID(true);
}
/**
* 获取类型 4(伪随机生成的)UUID 的静态工厂。 使用加密的强伪随机数生成器生成该 UUID。
*
* @param isSecure 是否使用{@link SecureRandom}如果是可以获得更安全的随机码,否则可以得到更好的性能
* @return 随机生成的 {@code UUID}
*/
public static UUID randomUUID(boolean isSecure)
{
final Random ng = isSecure ? Holder.numberGenerator : getRandom();
byte[] randomBytes = new byte[16];
ng.nextBytes(randomBytes);
randomBytes[6] &= 0x0f; /* clear version */
randomBytes[6] |= 0x40; /* set to version 4 */
randomBytes[8] &= 0x3f; /* clear variant */
randomBytes[8] |= 0x80; /* set to IETF variant */
return new UUID(randomBytes);
}
/**
* 根据指定的字节数组获取类型 3(基于名称的)UUID 的静态工厂。
*
* @param name 用于构造 UUID 的字节数组。
*
* @return 根据指定数组生成的 {@code UUID}
*/
public static UUID nameUUIDFromBytes(byte[] name)
{
MessageDigest md;
try
{
md = MessageDigest.getInstance("MD5");
}
catch (NoSuchAlgorithmException nsae)
{
throw new InternalError("MD5 not supported");
}
byte[] md5Bytes = md.digest(name);
md5Bytes[6] &= 0x0f; /* clear version */
md5Bytes[6] |= 0x30; /* set to version 3 */
md5Bytes[8] &= 0x3f; /* clear variant */
md5Bytes[8] |= 0x80; /* set to IETF variant */
return new UUID(md5Bytes);
}
/**
* 根据 {@link #toString()} 方法中描述的字符串标准表示形式创建{@code UUID}。
*
* @param name 指定 {@code UUID} 字符串
* @return 具有指定值的 {@code UUID}
* @throws IllegalArgumentException 如果 name 与 {@link #toString} 中描述的字符串表示形式不符抛出此异常
*
*/
public static UUID fromString(String name)
{
String[] components = name.split("-");
if (components.length != 5)
{
throw new IllegalArgumentException("Invalid UUID string: " + name);
}
for (int i = 0; i < 5; i++)
{
components[i] = "0x" + components[i];
}
long mostSigBits = Long.decode(components[0]).longValue();
mostSigBits <<= 16;
mostSigBits |= Long.decode(components[1]).longValue();
mostSigBits <<= 16;
mostSigBits |= Long.decode(components[2]).longValue();
long leastSigBits = Long.decode(components[3]).longValue();
leastSigBits <<= 48;
leastSigBits |= Long.decode(components[4]).longValue();
return new UUID(mostSigBits, leastSigBits);
}
/**
* 返回此 UUID 的 128 位值中的最低有效 64 位。
*
* @return 此 UUID 的 128 位值中的最低有效 64 位。
*/
public long getLeastSignificantBits()
{
return leastSigBits;
}
/**
* 返回此 UUID 的 128 位值中的最高有效 64 位。
*
* @return 此 UUID 的 128 位值中最高有效 64 位。
*/
public long getMostSignificantBits()
{
return mostSigBits;
}
/**
* 与此 {@code UUID} 相关联的版本号. 版本号描述此 {@code UUID} 是如何生成的。
* <p>
* 版本号具有以下含意:
* <ul>
* <li>1 基于时间的 UUID
* <li>2 DCE 安全 UUID
* <li>3 基于名称的 UUID
* <li>4 随机生成的 UUID
* </ul>
*
* @return 此 {@code UUID} 的版本号
*/
public int version()
{
// Version is bits masked by 0x000000000000F000 in MS long
return (int) ((mostSigBits >> 12) & 0x0f);
}
/**
* 与此 {@code UUID} 相关联的变体号。变体号描述 {@code UUID} 的布局。
* <p>
* 变体号具有以下含意:
* <ul>
* <li>0 为 NCS 向后兼容保留
* <li>2 <a href="http://www.ietf.org/rfc/rfc4122.txt">IETF RFC 4122</a>(Leach-Salz), 用于此类
* <li>6 保留,微软向后兼容
* <li>7 保留供以后定义使用
* </ul>
*
* @return 此 {@code UUID} 相关联的变体号
*/
public int variant()
{
// This field is composed of a varying number of bits.
// 0 - - Reserved for NCS backward compatibility
// 1 0 - The IETF aka Leach-Salz variant (used by this class)
// 1 1 0 Reserved, Microsoft backward compatibility
// 1 1 1 Reserved for future definition.
return (int) ((leastSigBits >>> (64 - (leastSigBits >>> 62))) & (leastSigBits >> 63));
}
/**
* 与此 UUID 相关联的时间戳值。
*
* <p>
* 60 位的时间戳值根据此 {@code UUID} 的 time_low、time_mid 和 time_hi 字段构造。<br>
* 所得到的时间戳以 100 毫微秒为单位,从 UTC(通用协调时间) 1582 年 10 月 15 日零时开始。
*
* <p>
* 时间戳值仅在在基于时间的 UUID(其 version 类型为 1)中才有意义。<br>
* 如果此 {@code UUID} 不是基于时间的 UUID,则此方法抛出 UnsupportedOperationException。
*
* @throws UnsupportedOperationException 如果此 {@code UUID} 不是 version 为 1 的 UUID。
*/
public long timestamp() throws UnsupportedOperationException
{
checkTimeBase();
return (mostSigBits & 0x0FFFL) << 48//
| ((mostSigBits >> 16) & 0x0FFFFL) << 32//
| mostSigBits >>> 32;
}
/**
* 与此 UUID 相关联的时钟序列值。
*
* <p>
* 14 位的时钟序列值根据此 UUID 的 clock_seq 字段构造。clock_seq 字段用于保证在基于时间的 UUID 中的时间唯一性。
* <p>
* {@code clockSequence} 值仅在基于时间的 UUID(其 version 类型为 1)中才有意义。 如果此 UUID 不是基于时间的 UUID,则此方法抛出
* UnsupportedOperationException。
*
* @return 此 {@code UUID} 的时钟序列
*
* @throws UnsupportedOperationException 如果此 UUID 的 version 不为 1
*/
public int clockSequence() throws UnsupportedOperationException
{
checkTimeBase();
return (int) ((leastSigBits & 0x3FFF000000000000L) >>> 48);
}
/**
* 与此 UUID 相关的节点值。
*
* <p>
* 48 位的节点值根据此 UUID 的 node 字段构造。此字段旨在用于保存机器的 IEEE 802 地址,该地址用于生成此 UUID 以保证空间唯一性。
* <p>
* 节点值仅在基于时间的 UUID(其 version 类型为 1)中才有意义。<br>
* 如果此 UUID 不是基于时间的 UUID,则此方法抛出 UnsupportedOperationException。
*
* @return 此 {@code UUID} 的节点值
*
* @throws UnsupportedOperationException 如果此 UUID 的 version 不为 1
*/
public long node() throws UnsupportedOperationException
{
checkTimeBase();
return leastSigBits & 0x0000FFFFFFFFFFFFL;
}
/**
* 返回此{@code UUID} 的字符串表现形式。
*
* <p>
* UUID 的字符串表示形式由此 BNF 描述:
*
* <pre>
* {@code
* UUID = <time_low>-<time_mid>-<time_high_and_version>-<variant_and_sequence>-<node>
* time_low = 4*<hexOctet>
* time_mid = 2*<hexOctet>
* time_high_and_version = 2*<hexOctet>
* variant_and_sequence = 2*<hexOctet>
* node = 6*<hexOctet>
* hexOctet = <hexDigit><hexDigit>
* hexDigit = [0-9a-fA-F]
* }
* </pre>
*
* </blockquote>
*
* @return 此{@code UUID} 的字符串表现形式
* @see #toString(boolean)
*/
@Override
public String toString()
{
return toString(false);
}
/**
* 返回此{@code UUID} 的字符串表现形式。
*
* <p>
* UUID 的字符串表示形式由此 BNF 描述:
*
* <pre>
* {@code
* UUID = <time_low>-<time_mid>-<time_high_and_version>-<variant_and_sequence>-<node>
* time_low = 4*<hexOctet>
* time_mid = 2*<hexOctet>
* time_high_and_version = 2*<hexOctet>
* variant_and_sequence = 2*<hexOctet>
* node = 6*<hexOctet>
* hexOctet = <hexDigit><hexDigit>
* hexDigit = [0-9a-fA-F]
* }
* </pre>
*
* </blockquote>
*
* @param isSimple 是否简单模式,简单模式为不带'-'的UUID字符串
* @return 此{@code UUID} 的字符串表现形式
*/
public String toString(boolean isSimple)
{
final StringBuilder builder = new StringBuilder(isSimple ? 32 : 36);
// time_low
builder.append(digits(mostSigBits >> 32, 8));
if (false == isSimple)
{
builder.append('-');
}
// time_mid
builder.append(digits(mostSigBits >> 16, 4));
if (false == isSimple)
{
builder.append('-');
}
// time_high_and_version
builder.append(digits(mostSigBits, 4));
if (false == isSimple)
{
builder.append('-');
}
// variant_and_sequence
builder.append(digits(leastSigBits >> 48, 4));
if (false == isSimple)
{
builder.append('-');
}
// node
builder.append(digits(leastSigBits, 12));
return builder.toString();
}
/**
* 返回此 UUID 的哈希码。
*
* @return UUID 的哈希码值。
*/
@Override
public int hashCode()
{
long hilo = mostSigBits ^ leastSigBits;
return ((int) (hilo >> 32)) ^ (int) hilo;
}
/**
* 将此对象与指定对象比较。
* <p>
* 当且仅当参数不为 {@code null}、而是一个 UUID 对象、具有与此 UUID 相同的 varriant、包含相同的值(每一位均相同)时,结果才为 {@code true}。
*
* @param obj 要与之比较的对象
*
* @return 如果对象相同,则返回 {@code true};否则返回 {@code false}
*/
@Override
public boolean equals(Object obj)
{
if ((null == obj) || (obj.getClass() != UUID.class))
{
return false;
}
UUID id = (UUID) obj;
return (mostSigBits == id.mostSigBits && leastSigBits == id.leastSigBits);
}
// Comparison Operations
/**
* 将此 UUID 与指定的 UUID 比较。
*
* <p>
* 如果两个 UUID 不同,且第一个 UUID 的最高有效字段大于第二个 UUID 的对应字段,则第一个 UUID 大于第二个 UUID。
*
* @param val 与此 UUID 比较的 UUID
*
* @return 在此 UUID 小于、等于或大于 val 时,分别返回 -1、0 或 1。
*
*/
@Override
public int compareTo(UUID val)
{
// The ordering is intentionally set up so that the UUIDs
// can simply be numerically compared as two numbers
return (this.mostSigBits < val.mostSigBits ? -1 : //
(this.mostSigBits > val.mostSigBits ? 1 : //
(this.leastSigBits < val.leastSigBits ? -1 : //
(this.leastSigBits > val.leastSigBits ? 1 : //
0))));
}
// -------------------------------------------------------------------------------------------------------------------
// Private method start
/**
* 返回指定数字对应的hex值
*
* @param val 值
* @param digits 位
* @return 值
*/
private static String digits(long val, int digits)
{
long hi = 1L << (digits * 4);
return Long.toHexString(hi | (val & (hi - 1))).substring(1);
}
/**
* 检查是否为time-based版本UUID
*/
private void checkTimeBase()
{
if (version() != 1)
{
throw new UnsupportedOperationException("Not a time-based UUID");
}
}
/**
* 获取{@link SecureRandom},类提供加密的强随机数生成器 (RNG)
*
* @return {@link SecureRandom}
*/
public static SecureRandom getSecureRandom()
{
try
{
return SecureRandom.getInstance("SHA1PRNG");
}
catch (NoSuchAlgorithmException e)
{
throw new UtilException(e);
}
}
/**
* 获取随机数生成器对象<br>
* ThreadLocalRandom是JDK 7之后提供并发产生随机数,能够解决多个线程发生的竞争争夺。
*
* @return {@link ThreadLocalRandom}
*/
public static ThreadLocalRandom getRandom()
{
return ThreadLocalRandom.current();
}
}
SQL防注入工具
package net.zywx.oa.common.utils.sql;
import net.zywx.oa.common.exception.BaseException;
import net.zywx.oa.common.core.utils.StringUtils;
/**
* sql操作工具类
*
* @author ruoyi
*/
public class SqlUtil
{
/**
* 仅支持字母、数字、下划线、减号、空格、逗号、小数点(支持多个字段排序)
*/
public static String SQL_PATTERN = "[a-zA-Z0-9_\\-\\ \\,\\.\\/]+";
/**
* 检查字符,防止注入绕过
*/
public static String escapeOrderBySql(String value)
{
if (StringUtils.isNotEmpty(value) && !isValidOrderBySql(value))
{
throw new BaseException("参数不符合规范,不能进行查询");
}
return value;
}
/**
* 验证 order by 语法是否符合规范
*/
public static boolean isValidOrderBySql(String value)
{
return value.matches(SQL_PATTERN);
}
}
文件压缩工具类
package net.zywx.oa.core.utils;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import org.apache.commons.io.IOUtils;
import java.io.*;
import java.util.Objects;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
/**
* 文件压缩工具类
* @author LiuShun
* @date 2023-02-07
*/
public class FileCompressionUtil {
private static volatile FileCompressionUtil fileCompressionUtil;
/**
* 压缩一个文件或目录
* @param inFile 输入,可以是普通文件或目录
* @param zipFile 输出
* @throws IOException
*/
public static void zip(File inFile, File zipFile) throws IOException {
ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(zipFile)));
zipFile = zipFile.getCanonicalFile();
String rootPath = zipFile.getParent();
if (!rootPath.endsWith(File.separator)) {
rootPath += File.separator;
}
try {
if (!inFile.exists()) {
throw new FileNotFoundException(inFile.getAbsolutePath());
}
addFileToZipOut(inFile, out, rootPath);
// 线上拉倒本地文件需要删除
deleteRecursively(inFile);
} finally {
out.close();
}
}
/**
* 将腾讯云文件保存到本地
**/
public static void downloadFile(String fileUrl, String localDow, String originalFileName) {
if (fileUrl != null) {
// 获取文件后缀名
String fileExtName = fileUrl.substring(fileUrl.lastIndexOf("."));
try {
HttpUtil.downloadFile(fileUrl, localDow + File.separator + originalFileName + fileExtName);
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 将腾讯云文件保存到本地,并返回本地文件路径
**/
public static String downloadFile(String fileUrl, String localDow) {
if (fileUrl != null) {
// 获取文件名
String fileName = StrUtil.subAfter(fileUrl, "/", true);
try {
String filePath = localDow + File.separator + fileName;
HttpUtil.downloadFile(fileUrl, filePath);
return filePath;
} catch (Exception e) {
e.printStackTrace();
}
}
return StrUtil.EMPTY;
}
/**
* 删除非空目录(需要先清空目录)
* @param file 目录
* @throws IOException
*/
private static void deleteRecursively(File file) throws IOException{
if (file.isFile()){
boolean delete = file.delete();
if (!delete){
throw new IOException("Failed to delete " + file.getCanonicalPath());
}
}
if (file.isDirectory()){
for (File listFile : Objects.requireNonNull(file.listFiles())) {
deleteRecursively(listFile);
}
if (!file.delete()){
throw new IOException("Failed to delete " + file.getCanonicalPath());
}
}
}
/**
* 压缩一个文件或目录
* @param file 输入,可以是普通文件或目录
* @param out 输出
* @param rootPath 父目录
* @throws IOException
*/
private static void addFileToZipOut(File file, ZipOutputStream out, String rootPath) throws IOException {
String relativePath = file.getCanonicalPath().substring(rootPath.length());
if(file.isFile()) {
out.putNextEntry(new ZipEntry(relativePath));
InputStream in = new BufferedInputStream(new FileInputStream(file));
try {
IOUtils.copy(in, out);
} finally {
in.close();
}
} else {
out.putNextEntry(new ZipEntry(relativePath + File.separator));
for(File f : Objects.requireNonNull(file.listFiles())) {
addFileToZipOut(f, out, rootPath);
}
}
}
private FileCompressionUtil(){}
public static FileCompressionUtil getInstance(){
if (null == fileCompressionUtil){
synchronized (FileCompressionUtil.class){
if (null == fileCompressionUtil){
fileCompressionUtil = new FileCompressionUtil();
}
return fileCompressionUtil;
}
}
return fileCompressionUtil;
}
}
异步线程池配置
package com.ms.recruit.web.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;
/**
* *<pre>
* * desc : 线程池管理
* 使用线程池的时候需要考虑线程池的大小,当前配置的是核心线程数10个
* 仅仅用作发送短信的
* *</pre>
*/
@Configuration
public class TaskConfiguration {
@Bean("taskExecutor")
public Executor taskExecutor(){
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(10);
executor.setMaxPoolSize(30);
executor.setQueueCapacity(200);
executor.setKeepAliveSeconds(60);
executor.setThreadNamePrefix("taskExecutor-");
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.setWaitForTasksToCompleteOnShutdown(true);
executor.setAwaitTerminationSeconds(60);
return executor;
}
@Bean("taskExecutorWorkToolRobot")
public Executor taskExecutorWorkToolRobot(){
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(10);
executor.setMaxPoolSize(30);
executor.setQueueCapacity(200);
executor.setKeepAliveSeconds(60);
executor.setThreadNamePrefix("taskExecutorWorkToolRobot-");
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.setWaitForTasksToCompleteOnShutdown(true);
executor.setAwaitTerminationSeconds(60);
return executor;
}
@Bean("mqExecutor")
public Executor mqExecutor(){
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(10);
executor.setMaxPoolSize(20);
executor.setQueueCapacity(200);
executor.setKeepAliveSeconds(60);
executor.setThreadNamePrefix("mqTaskExecutor-");
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.setWaitForTasksToCompleteOnShutdown(true);
executor.setAwaitTerminationSeconds(60);
return executor;
}
@Bean("taskReleaseExecutor")
public Executor taskReleaseExecutor(){
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(10);
executor.setMaxPoolSize(30);
executor.setQueueCapacity(200);
executor.setKeepAliveSeconds(60);
executor.setThreadNamePrefix("taskReleaseExecutor-");
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.setWaitForTasksToCompleteOnShutdown(true);
executor.setAwaitTerminationSeconds(60);
return executor;
}
@Bean(name = "uploadExecutor")
public Executor uploadExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(20);
executor.setMaxPoolSize(50);
executor.setQueueCapacity(200);
executor.setKeepAliveSeconds(60);
executor.setThreadNamePrefix("uploadTaskExecutor-");
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.setWaitForTasksToCompleteOnShutdown(true);
executor.setAwaitTerminationSeconds(60);
return executor;
}
public static void main(String[] args) {
String test = "";
System.out.println(test == "" ? "a":"b");
}
}
@Component
public class AsyncService {
@Async("taskExecutor")
public void writeCandidateLog(List<CandidateOperationLogInfo> candidateLogs, String operName){
}
}