10月11
${ew.customSqlSegment} 会直接在前面添加 where

@Select(select * from a ${ew.customSqlSegment})
List<a> getHeck(@Param(Constants.WRAPPER)QueryWrapper queryWrapper)

${ew.sqlSegment} 就只有条件语句

@Select(select * from a where ${ew.sqlSegment})
List<a> getHeck(@Param(Constants.WRAPPER)QueryWrapper queryWrapper)

${ew.sqlSelect} 就是 queryWrapper.select(****) 你所定义需要查询的字段

@Select(select ${ew.sqlSelect} from a )
List<a> getHeck(@Param(Constants.WRAPPER)QueryWrapper queryWrapper)
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;
    }
8月21
错误原因和现象
在执行shell脚本的时候,报错:/bin/bash^M: bad interpreter: No such file or directory。
是由于该脚本文件是在Windows平台编写,然后在MacOS或者Kylin-Server平台中执行。
在Windows平台上文件是dos格式,换行符尾\r\n,而MacOS或者Kylin-Server平台文件是unix格式,换行符尾\n。因此在运行脚本文件时,不能正确解析\r,导致编译错误、运行失败。

解决方案

在MacOS或者Kylin-Server平台上,打开命令行工具执行命令vim *.sh(编辑你的脚本文件),然后执行命令:set ff=unix,最后执行:wq( 保存退出)即可。
7月24
方式一:SM2密钥在线生成
SM2密钥在线生成工具

如果你没线下生成工具,可用下面2种线上生成方式之一:

1. sm2密钥在线生成(const.net.cn

2. web encrypt(webencrypt.org

方式一:生成SM2公私钥(.pem格式)
一.系统环境
系统环境:windows系统。
二.工具软件
工具软件:Win64OpenSSL。
三.生成SM2公私钥
步骤一:在windows操作系统上安装Win64OpenSSL软件;
步骤二:打开Win64OpenSSL软件,首先生成私钥,命令为:ecparam -genkey -name SM2 -out priv.key;
7月17
Linux 系统中,Spring Boot 应用以 java -jar 命令启动时,会在操作系统的 /tmp 目录下生成一个 tomcat(或 undertow )临时目录,上传的文件先要转换成临时文件保存在这个文件夹下面。由于临时 /tmp 目录下的文件,在长时间(10天)没有使用的情况下,系统执行了 tmp 目录清理服务(systemd-tmpfiles-clean.service),导致 /tmp/undertow...8090 文件被清理,然而在上传的时候,undertow 服务器需要创建/tmp/undertow...8090/undertow...upload 临时文件,但是调用 Files.createFile(...) 的时候就会发现找不到父目录,才导致了以上的错误。

具体错误日志(参考)
undertow

java.nio.file.NoSuchFileException: /tmp/undertow.17753558642503713859.8085/undertow7370242804103803588upload

Tomcat

The temporary upload location [/tmp/tomcat.7957874575370093230.8088/work/Tomcat/localhost/ROOT] is not valid

重现方法
找到类 io.undertow.server.handlers.form.MultiPartParserDefinition
定位到如下代码

@Override
public void beginPart(final HeaderMap headers) {
    this.currentFileSize = 0;
    this.headers = headers;
    final String disposition = headers.getFirst(Headers.CONTENT_DISPOSITION);
    if (disposition != null) {
        if (disposition.startsWith("form-data")) {
            currentName = Headers.extractQuotedValueFromHeader(disposition, "name");
            fileName = Headers.extractQuotedValueFromHeaderWithEncoding(disposition, "filename");
            if (fileName != null && fileSizeThreshold == 0) {
                try {
                    if (tempFileLocation != null) {
                        file = Files.createTempFile(tempFileLocation, "undertow", "upload");
                    } else {
                        file = Files.createTempFile("undertow", "upload");
                    }
                    createdFiles.add(file);
                    fileChannel = FileChannel.open(file, StandardOpenOption.READ, StandardOpenOption.WRITE);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }
}

在 createdFiles.add(file); 处打断点,复制file的 path 的值找到该文件并将其删除;放开断点,错误重现;
6月30
在做javaweb项目时,关于统一错误页面在开发的过程中就做过编码,并且一直都很有效,像500,404,403等常规错误码都能得到有效处理,但是400却不行,而且还暴露tomcat的版本信息,这是很严重的安全漏洞
解决方法百度和测试很多,总结如下:

问题产生:
根据rfc规范,url中不允许有 |,{,}等特殊字符,但在实际生产中还是有些url有可能携带有这些字符,特别是|还是较为常见的。在tomcat升级到7以后,对url字符的检查都变严格了,如果出现这类字符,服务器tomcat将直接返回400状态码。

方法一:降低tomcat的版本
开发人员增加一项设置,允许配置在url可以出现的特殊字符,但也仅限于|,{,}三种,见:http://tomcat.apache.org/tomcat-8.0-doc/config/systemprops.html#Other
该项设置在以下版本的tomcat中有效:

- 8.5.x for 8.5.12 onwards

- 8.0.x for 8.0.42 onwards

- 7.0.x for 7.0.76 onwards
- 这个只是允许出现一些特殊字符,并没有说是全部特殊字符。
好像是tomcat7.9以上的版本,都不支持请求链接上带有特殊字符.否则会报400错误,
tomcat请求中包含特殊字符 [] | {} 发送get请求失败:
原因:
这是因为Tomcat严格按照 RFC 3986规范进行访问解析,而 RFC 3986规范定义了Url中只允许包含英文字母(a-zA-Z)、数字(0-9)、-_.~4个特殊字符以及所有保留字符(RFC3986中指定了以下字符为保留字符:! * ’ ( ) ; : @ & = + $ , / ? # [ ])。传入的参数中有"[]"、""不在RFC3986中的保留字段中,所以会报这个错。

方法二:修改server.xml
<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" relaxedQueryChars="[]|{}^&#x5c;&#x60;&quot;&lt;&gt;" redirectPort="8443" />
方法三:修改server.xml(推荐方法)
在Host里加入:
<Valve className="org.apache.catalina.valves.ErrorReportValve"  showReport="false" showServerInfo="false" />
方法三 修改后只会显示出HTTP 400 错误,不会打印堆栈和tomcat版本号信息
6月29
linux同步时间命令:

1、hwclock命令,可以让系统时间和硬件时间的同步,例“hwclock -w”或“hwclock -s”;
2、ntpdate命令,可以让不同机器间同步时间。


在Windwos中,系统时间的设置很简单,界面操作,通俗易懂,而且设置后,重启,关机都没关系。系统时间会自动保存在BIOS时钟里面,启动计算机的时候,系统会自动在BIOS里面取硬件时间,以保证时间的不间断。

但在Linux下,默认情况下,系统时间和硬件时间并不会自动同步。在Linux运行过程中,系统时间和硬件时间以异步的方式运行,互不干扰。硬件时间的运行,是靠BIOS电池来维持,而系统时间,是用CPU Tick来维持的。在系统开机的时候,会自动从BIOS中取得硬件时间,设置为系统时间。

1. Linux系统时间的设置
在Linux中设置系统时间,可以用date命令:

//查看时间

[root@node1 ~]# date

Tue Feb 25 20:15:18 CST 2014

//修改时间

[root@node1 ~]# date -s "20140225 20:16:00"  #yyyymmdd hh:mm:ss

Tue Feb 25 20:16:00 CST 2014

//date 有多种时间格式可接受,查看date --help

2. Linux硬件时间的设置
硬件时间的设置,可以用hwclock或者clock命令。两者基本相同,只用一个就行,只不过clock命令除了支持x86硬件体系外,还支持Alpha硬件体系。

//查看硬件时间可以是用hwclock ,hwclock --show 或者 hwclock -r

[root@node1 ~]# hwclock --show

Tue 25 Feb 2014 08:21:14 PM CST -0.327068 seconds

//设置硬件时间

[root@node1 ~]# hwclock --set --date "20140225 20:23:00"

[root@node1 ~]# hwclock

Tue 25 Feb 2014 08:23:04 PM CST -0.750440 seconds

3. 系统时间和硬件时间的同步
同步系统时间和硬件时间,可以使用hwclock命令。

//以系统时间为基准,修改硬件时间

[root@node1 ~]# hwclock --systohc <== sys(系统时间)to(写到)hc(Hard Clock)

//或者

[root@node1 ~]# hwclock -w

//以硬件时间为基准,修改系统时间

[root@node1 ~]# hwclock --hctosys

//或者

[root@node1 ~]# hwclock -s
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
分页: 2/66 第一页 上页 1 2 3 4 5 6 7 8 9 10 下页 最后页 [ 显示模式: 摘要 | 列表 ]