9月4
错误信息:
Could not read JSON: Cannot construct instance of java.util.ArrayList$SubList(no Creators, like default construct, exist): no default no-arguments constructor found

原因是读取Redis缓存时,报错异常导致!

原因是缓存中是集合ArrayList中含有SubList,因为SubList不能序列化和反序列化,导致解析失败。

解决办法:

1、若存在使用SubList方法,只需要 重新new 下:

原代码:       resultList = regionDistributionVOList.subList(ZERO, FOUR);

改正后:       resultList = new ArrayList<>(regionDistributionVOList.subList(ZERO, FOUR));
或者:            resultList.addAll(regionDistributionVOList.subList(ZERO, FOUR));

2、若通过 Lists.partition(ZERO, TEN)获取的,则需要将subList转为ArrayList

用: Lists.newArrayList(subList)
8月24
首先经过了解查看源码,@Scheduled是单线程的,如果有多个定时任务,势必需要前一个任务执行完才会执行后面的任务
点击在新窗口中浏览此图片

所以我们有三种方法解决定时任务线程池配置解决多个定时任务阻塞问题
1、重写SchedulingConfigurer#configureTasks(),直接实现SchedulingConfigurer这个接口,设置taskScheduler
2、也可以配置文件配置,Spring Boot quartz 已经提供了一个配置用来配置线程池的大小 spring.task.scheduling.pool.size=10
3、配置线程池,再使用@Async开启异步任务

package com.nine.rivers.apps.core.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;

import java.util.concurrent.ThreadPoolExecutor;

import static com.nine.rivers.apps.core.constants.NumberConstant.*;

/**
* 定时任务线程池配置解决多个定时任务阻塞问题
* 三种方法,任选期一:
* <p>1、重写SchedulingConfigurer#configureTasks(),直接实现SchedulingConfigurer这个接口,设置taskScheduler
* <p>2、也可以配置文件配置,Spring Boot quartz 已经提供了一个配置用来配置线程池的大小 spring.task.scheduling.pool.size=10
* <p>3、配置线程池,再使用@Async开启异步任务
*
* @author heck
* @date 2023/08/24
*/
@Configuration
public class ScheduleConfig implements SchedulingConfigurer {
    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        taskRegistrar.setScheduler(taskScheduler());
    }

    /**
     * 覆盖taskScheduler
     */
    @Bean
    public TaskScheduler taskScheduler() {
        ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
        taskScheduler.setPoolSize(SIX);
        taskScheduler.setThreadNamePrefix("ndp-apps-scheduler-pool-");
        return taskScheduler;
    }

}

方法三

    /**
     * 配置线程池,再使用@Async开启异步任务
     */
    @Bean
    public ThreadPoolTaskExecutor taskExecutor() {
        ThreadPoolTaskExecutor poolTaskExecutor = new ThreadPoolTaskExecutor();

        poolTaskExecutor.setCorePoolSize(FOUR);
        poolTaskExecutor.setMaxPoolSize(SIX);
        // 设置线程活跃时间(秒)
        poolTaskExecutor.setKeepAliveSeconds(TWO * SIX * TEN);
        // 设置队列容量
        poolTaskExecutor.setQueueCapacity(FOUR * TEN);

        poolTaskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        // 等待所有任务结束后再关闭线程池
        poolTaskExecutor.setWaitForTasksToCompleteOnShutdown(true);

        return poolTaskExecutor;
    }
4月18
今天遇到的问题是jdk1.8_291The server selected protocol version TLS10 is not accepted by client preferences [TLS12]
配置的是jdk1.8_291
之前一直用的jdk1.8_191没有遇到连接sqlserver数据库错误的问题,今天遇到了就各种百度查原因,大概都是说新版本不支持TLS10
解决方案:
根据环境变量配置中 jre 的地址,在 jre\lib\security 文件夹下,编辑 java.security 文件
在文件中找到 jdk.tls.disabledAlgorithms 配置项,将 TLSv1, TLSv1.1, 3DES_EDE_CBC 删除即可。
修改后:
jdk.tls.disabledAlgorithms=SSLv3,RC4, DES, MD5withRSA,
DH keySize < 1024, EC keySize < 224, anon, NULL,
include jdk.disabled.namedCurves

我试着修改了,但是不起作用,以为要重启,连电脑我都重启了,还是不起作用,最后!!!
重点来了!!修改的是jdk下的jre里面的lib\security 文件夹下的 java.security 文件!!!我的目录是:D:\Java\jdk1.8.0_291\jre\lib\security(改这个文件下面的才有效!!!)

之前没生效是因为我改的是直接jre下的lib\security 文件夹下的 java.security文件
jre目录是:D:\Java\jre1.8.0_291\lib\security(这个没用,改了完全不起作用)
花了好几个小时终于不再报错,留个记录,警醒自己,当然如果能帮到你们就更好啦~
3月20
redis读取数据失败,打印异常信息如下:
Could not read JSON: Invalid UTF-32 character 0x22636364 (above 0x0010ffff) at char #15, byte #63); nested exception is java.io.CharConversionException: Invalid UTF-32 character 0x22636364 (above 0x0010ffff) at char #15, byte #63)

问题的原因是我在添加数据时设置了存活时间但是忘记指定单位了;
正确的应该是再指定TimeUnit.SECONDS参数。
时间单位:
天:TimeUnit.DAYS
小时:TimeUnit.HOURS
分钟:TimeUnit.MINUTES
秒:TimeUnit.SECONDS
毫秒:TimeUnit.MILLISECONDS
3月17
下面列举下EasyPoi支持的指令以及作用,最主要的就是各种fe的用法文字
三元运算 {{test ? obj:obj2}}
n: 表示 这个cell是数值类型 {{n:}}
le: 代表长度{{le:()}} 在if/else 运用{{le:() > 8 ? obj1 : obj2}}
fd: 格式化时间 {{fd:(obj;yyyy-MM-dd)}}
fn: 格式化数字 {{fn:(obj;###.00)}}
fe: 遍历数据,创建row
!fe: 遍历数据不创建row
$fe: 下移插入,把当前行,下面的行全部下移.size()行,然后插入
#fe: 横向遍历
v_fe: 横向遍历值
!if: 删除当前列 {{!if:(test)}}
单引号表示常量值 ‘’ 比如’1’ 那么输出的就是 1
&NULL& 空格
&INDEX& 表示循环中的序号,自动添加,看到这里应该就明白怎么在表格中增加一列序号了。
]] 换行符 多行遍历导出
sum: 统计数据
3月8
1、前端封装JSON值,后台需要List<实体类>接收

Map map = jsonObject.getInnerMap();
List<RecommendDTO> recommendDTOlist = (List<RecommendDTO>) map.get("xxx");

2、进行forearch循环的时候报错

recommendDTOlist .forEach((item)->{})

3、从redis中获取数据后进行遍历
List<RecommendDTO> recommendDTOlist = redisUtil.get(defaultCacheKey);
for (RecommendDTO recommendDTO : defaultRecommendList) {

}

报错信息:

java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to com.heckjj.apps.modules.smartpush.dto.RecommendDTO

4、打断点调试查看发现里面封装的是两个Map 而不是实体类而是个LinkedHashMap

5、解决方法

ObjectMapper mapper = new ObjectMapper();
List<RecommendDTO> recommendDTOlist = (List<RecommendDTO>) map.get("xxx");
List<RecommendDTO> recommendDTOlist = mapper.convertValue(list1, new TypeReference<List<RecommendDTO>>() { });

记住引入包路径是下面这两个

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
1月10
系统中对密码复杂度的校验是比较常见的工作,往往我们可以通过正则来实现,或者基于规则而实现特定的算法来满足需求。

下面我来介绍两个开源的解决方案。

1.使用vt-password来实现密码复杂度的检查
VT 密码是一个 Java 库,用于验证密码是否符合定义的规则集。
该库包括以下规则实现:

AllowedCharacterRule - 密码是否只包含特定的字符列表
AlphabeticalSequenceRule - 密码是否包含字母顺序
CharacterCharacteristicRule - 密码是否包含所需的字符类型组合
DictionaryRule - 密码是否与字典中的单词匹配
DictionarySubstringRule - 密码是否包含字典中的单词
DigitCharacterRule - 密码是否包含数字
HistoryRule - 密码是否与以前的密码匹配,支持散列
IllegalCharacterRule - 密码是否包含非法字符
LengthRule - 是一定长度的密码
LowercaseCharacterRule - 密码是否包含小写字符
NonAlphanumericCharacterRule - 密码是否包含非字母数字字符
NumericalSequenceRule - 密码是否包含数字序列
RegexRule - 密码是否与正则表达式匹配
RepeatCharacterRegexRule - 密码是否包含重复字符
SequenceRule - 密码是否包含键盘序列
SourceRule - 密码是否与来自另一个系统或来源的密码匹配
QwertySequenceRule - 密码是否包含 QWERTY 键盘序列
UppercaseCharacterRule - 密码是否包含大写字符
UsernameRule - 密码是否包含用户名
WhitespaceRule - 密码是否包含空格
如果你想在你的Maven构建中使用这个项目,请在你的pom.xml 中包含以下内容:

<dependency>
  <groupId>edu.vt.middleware</groupId>
  <artifactId>vt-password</artifactId>
  <version>3.1.2</version>
</dependency>
12月9
公司有个项目不能解析内网所以需要对本地hosts文件进行修改,添加一条本地域名解析记录,如果让客户去操作,很容易破坏掉原先的hosts文件,用户只需要以管理员权限运行即可,如果记录存在则替换掉。
由于办公电脑都使用信创麒麟的系统,所以最好做一个deb的安装包,通过程序写修改的,在信创麒麟的系统电脑下载安装即可执行。
下面是实现逻辑,要将java打包成deb安装包就需要使用jdeb的maven插件来打包。
我使用的是1.8的版本,具体配置就不贴上来了,需要的联系我。
               <artifactId>jdeb</artifactId>
                <groupId>org.vafer</groupId>
                <version>1.8</version>


package com.nine.rivers.jdeb;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IORuntimeException;
import cn.hutool.core.util.StrUtil;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

/**
* @Description 不破坏原有hosts文件,支持新host绑定或修改支持host解绑
* @Date 2022/12/9 16:42
* @Author heck
**/
public class HostUtil {

    public static final String LINUX = "linux";
    public static final String LINUX_HOSTS_PATH = "/etc/hosts";
    public static final String WINDIR = "windir";
    public static final String WIN_HOSTS_PATH = "\\system32\\drivers\\etc\\hosts";
    public static final String OS_NAME = "os.name";

    /**
     * 获取host文件路径
     *
     * @return
     */
    public static String getHostFile() {
        String fileName = null;
        // 判断系统
        if (LINUX.equalsIgnoreCase(System.getProperty(OS_NAME))) {
            fileName = LINUX_HOSTS_PATH;
        } else {
            fileName = System.getenv(WINDIR) + WIN_HOSTS_PATH;
        }
        return fileName;
    }
11月30
原因:SpringBoot内嵌web容器,其特点是只有一个jar文件,在容器启动后不会解压缩。

解决方式:

1. 必须使用相对路径读取文件;

假设你的模板文件放在了 resources —> templates —> test.xlsx

2. 只能使用流去读取,不能用file;

  // jar里面文件读取方式:
  ClassPathResource classPathResource = new ClassPathResource("templates/test.xlsx");
  // 获取文件流
  classPathResource .getInputStream();

如果要将流存储到数组中如下:

  /**
     * 输出流转字节数组
     * @param input 输出流
     * @return 字节数组
     */
    public static byte[] toByteArray(InputStream input) throws IOException {
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024 * 4];
        int size = 0;
        while (-1 != (size = input.read(buffer))) {
            output.write(buffer, 0, size);
        }
        return output.toByteArray();
    }
11月27
Archetype是用于创建项目的骨架(或者模板),通过Archetype我们可以创建类似的Maven工程,同时Archetype能够极大的简化我们创建一个工程的步骤和流程。这里我将介绍自定义Maven的工程模板Archetype的方法和流程,这里采用的方法是从现有工程创建工程模板。

关于Archetype介绍参考:Introduction to Archetypes

一、Archetype自定义流程:
1、创建模板工程:找到一个现有的项目,进行编辑,将项目中的包结构、各类文件放置到合适的位置;



2、从模板工程创建Archetype:打开cmd窗口,切换当前目录到上面的工程目录下,执行maven命令:

mvn archetype:create-from-project
执行完成后,target/generated-sourced/archetype目录下就是我们需要的项目模板。

3、安装Archetype到本地仓库:cd进入target/generated-sourced/archetype中,执行命令:

mvn -Dmaven.test.skip=true clean install
将自定义Archetype安装到本地仓库即可:此时,自定义archetype就被安装到settings.xml中<localRepository>指定的本地仓库中,我的机器本地目录是D:/q/repos-maven;另外,archetype安装到本地仓库后,会在.m2/archetype-catalog.xml中加入对应的archetype节点,结构如下:

<archetype>

      <groupId>com.heckjj.blog</groupId>

      <artifactId>crm-archetype-archetype</artifactId>

      <version>1.0.0</version>

      <description>The parent pom of crm</description>

    </archetype>



4、使用自定义Archetype创建工程:

这样我们就创建成功了自定义的Archetype,可以通过命令从本地模板创建工程:

mvn archetype:generate -DarchetypeCatalog=local
以上就是创建自定义Archetype的简单流程。
分页: 2/20 第一页 上页 1 2 3 4 5 6 7 8 9 10 下页 最后页 [ 显示模式: 摘要 | 列表 ]