0%

前言

最近项目里需要查看下第三方类的源码,发现怎么都无法下载,下载报错如下

1
Cannot download sources Sources not found for: xxx
解决办法
1
2
# 在对应项目pom.xml所在目录下执行以下命令:
mvn dependency:resolve -Dclassifier=sources

前言

今天遇到一个问题,将前端压缩部署到nginx下,总是有几个静态资源文件找不到,要说是所有静态文件都找不到,那就说是我路径配置错了,但是只是个别几个找不到,很是奇怪,经过查看日志分析,是路径匹配的问题,下面具体记录下!

问题

下面是我的nginx配置文件的部分内容(未修改前)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#默认请求
location / {
index index.html;
root /download/code/html;
}

location ~ /(code|app) {
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://127.0.0.1:9999;
}

一开始的问题,http://127.0.0.1/code?random=1,这个路径是获取验证码的,但是发现匹配到第一个里去了,去找html/code文件,所以找不到,直接404,还有个问题是有个js文件名是`app.01ab.js`,但是确匹配到了第二个里去了,猛然一看,好像确实是,因为我这个只是字符串匹配,只要路径里有app,就会匹配到,所以需要加个开头匹配,修改配置如下后恢复正常

1
2
3
4
5
6
7
8
location ~ ^/(code|app) {
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://127.0.0.1:9999;
}

结语

所以用正则匹配的时候一定要配置正确,如果需要开头匹配就一定要加开始符号,否则就是全路径字符串匹配

前言

前端同事让帮忙看一个问题,Android系统的微信小程序new Date("2021-02-12")打印出来没问题,但是同样的这行代码在IOS系统的微信小程序行打印为null,这是一个很奇怪的问题,一个一个排查,确定代码没有写错,最终发现是IOS系统不兼容短横线-的问题

解决

需要把 ‘-’改为 ‘/’,用正则替换一下:

1
'2021-01-22'.replace(/-/g, '/')

然后再new Date('2021-01-22')发现和Android一样正常了

前言

只要是从事java开发的同学,Hutool这个工具类应该不需要我过多介绍,非常有名,工具类非常齐全,可以满足日常开发的各种用途,这边文章长期更新,将常用的工具类我会一一列出来,做个笔记,方便后面使用参考

安装

这里是官方文档,介绍了安装方法和常用的一些工具类

Maven项目使用

1
2
3
4
5
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.4</version>
</dependency>

Gradle项目使用

1
implementation 'cn.hutool:hutool-all:5.8.4'

也可以自行下载jar包,下载方式参考官方文档,这里不展开

图片压缩
1
2
3
Img.from(FileUtil.file("e:/pic/1111.png"))
.setQuality(0.8)//压缩比率
.write(FileUtil.file("e:/pic/1111_target.jpg"));

获取base64图片大小

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int size = base64Str.length() - encode.length() / 8 * 2;//计算出来是字节


/**
* byte(字节)根据长度转成kb(千字节)
* @param bytes 字节长度
* @return kb(千字节)
*/
public static Integer bytesToKB(long bytes) {
BigDecimal filesize = new BigDecimal(bytes);
BigDecimal kilobyte = new BigDecimal(1024);
float returnValue = filesize.divide(kilobyte, 1, RoundingMode.DOWN).floatValue();
return Convert.toInt(returnValue);
}

//以上方法转为KB,其实就是除以1024,只不过是四舍五入

压缩base64图片

1
2
3
BufferedImage bufferedImage = ImgUtil.toImage(base64Str);
Image scaleImage = ImgUtil.scale(bufferedImage, 0.2f);
return ImgUtil.toBase64(scaleImage, ImgUtil.IMAGE_TYPE_JPG);
StrUtil

这是一个string处理相关的工具类,方法特别的丰富,基本上涵盖了我们日常开发中所能想到的所有方法,下面介绍几个

字符串是否为空白isBlank,空白的定义如下:

  1. null
  2. 空字符串:""
  3. 空格、全角空格、制表符、换行符,等不可见字符
1
public static boolean isBlank(CharSequence str)

相反的方法就是isNotBlank

1
public static boolean isNotBlank(CharSequence str)

这是我们常用的判空的方法,其实还有isEmpty可以判空,但是这个不处理空白符,所以一般我们只用isBlank就行

其他的比如我们常见的字符串方法

split 分割

``sub` 截取

indexOf 索引

startWith 前缀是否匹配

endWith 后缀是否匹配

equals 两个字符串是否相等

都有很多类似的相关方法,具体的方法和API文档参考这里

IdUtil

在分布式环境中,唯一ID生成应用十分广泛,生成方法也多种多样,Hutool针对一些常用生成策略做了简单封装

uuid生成

1
2
3
4
5
//生成的UUID是带-的字符串,类似于:a5c8a5e8-df2b-4706-bea4-08d0939410e3
String uuid = IdUtil.randomUUID();

//生成的是不带-的字符串,类似于:b17f24ff026d40949c85a24f4f375d42
String simpleUUID = IdUtil.simpleUUID();

ObjectId生成

1
2
3
4
5
//生成类似:5b9e306a4df4f8c54a39fb0c
String id = ObjectId.next();

//方法2:从Hutool-4.1.14开始提供
String id2 = IdUtil.objectId();

Snowflake(雪花算法)

1
2
3
4
5
6
7
8
//参数1为终端ID
//参数2为数据中心ID
Snowflake snowflake = IdUtil.getSnowflake(1, 1);
long id = snowflake.nextId();

//简单使用
long id = IdUtil.getSnowflakeNextId();
String id = snowflake.getSnowflakeNextIdStr();

注意 IdUtil.createSnowflake每次调用会创建一个新的Snowflake对象,不同的Snowflake对象创建的ID可能会有重复,因此请自行维护此对象为单例,或者使用IdUtil.getSnowflake使用全局单例对象。

SecureUtil

SecureUtil主要针对常用加密算法构建快捷方式,还有提供一些密钥生成的快捷工具方法。

对称加密

  • SecureUtil.aes
  • SecureUtil.des

摘要算法

  • SecureUtil.md5
  • SecureUtil.sha1
  • SecureUtil.hmac
  • SecureUtil.hmacMd5
  • SecureUtil.hmacSha1

非对称加密

  • SecureUtil.rsa
  • SecureUtil.dsa

uuid

  • SecureUtil.simpleUUID 方法提供无“-”的UUID

密钥生成

  • SecureUtil.generateKey 针对对称加密生成密钥
  • SecureUtil.generateKeyPair 生成密钥对(用于非对称加密)
  • SecureUtil.generateSignature 生成签名(用于非对称加密)

前言

最近有个需求,mysql数据库,需要按月分组统计,但是数据库有个time字段,一个日期字段,用哪个都无法直接分组使用,所以需要用到mysql自带的一个函数DATE_FORMAT

使用

DATE_FORMAT() 函数用于以不同的格式显示日期/时间数据。

语法

1
DATE_FORMAT(date,format)

date 参数是合法的日期。format 规定日期/时间的输出格式

可以使用的格式有:

格式 描述
%a 缩写星期名
%b 缩写月名
%c 月,数值
%D 带有英文前缀的月中的天
%d 月的天,数值(00-31)
%e 月的天,数值(0-31)
%f 微秒
%H 小时 (00-23)
%h 小时 (01-12)
%I 小时 (01-12)
%i 分钟,数值(00-59)
%j 年的天 (001-366)
%k 小时 (0-23)
%l 小时 (1-12)
%M 月名
%m 月,数值(00-12)
%p AM 或 PM
%r 时间,12-小时(hh:mm:ss AM 或 PM)
%S 秒(00-59)
%s 秒(00-59)
%T 时间, 24-小时 (hh:mm:ss)
%U 周 (00-53) 星期日是一周的第一天
%u 周 (00-53) 星期一是一周的第一天
%V 周 (01-53) 星期日是一周的第一天,与 %X 使用
%v 周 (01-53) 星期一是一周的第一天,与 %x 使用
%W 星期名
%w 周的天 (0=星期日, 6=星期六)
%X 年,其中的星期日是周的第一天,4 位,与 %V 使用
%x 年,其中的星期一是周的第一天,4 位,与 %v 使用
%Y 年,4 位
%y 年,2 位

下面的脚本使用 DATE_FORMAT() 函数来显示不同的格式。我们使用 NOW() 来获得当前的日期/时间:

1
2
3
4
DATE_FORMAT(NOW(),'%b %d %Y %h:%i %p')
DATE_FORMAT(NOW(),'%m-%d-%Y')
DATE_FORMAT(NOW(),'%d %b %y')
DATE_FORMAT(NOW(),'%d %b %Y %T:%f')

输出结果:

1
2
3
4
Dec 29 2008 11:45 PM
12-29-2008
29 Dec 08
29 Dec 2008 16:25:46.635
解决

现在我们需要对每天,每周,每月各个产品的销量进行统计

  • 按天统计

    1
    select DATE_FORMAT(start_time,'%Y%m%d') days,count(product_no) count from test group by days; 
  • 按周统计

    1
    select DATE_FORMAT(start_time,'%Y%u') weeks,count(product_no) count from test group by weeks; 
  • 按月统计

    1
    select DATE_FORMAT(start_time,'%Y%m') months,count(product_no) count from test group bymonths; 

前言

最近遇到了一个问题,根据idea报错看出了是循环依赖了,导致项目启动失败,下面记录下解决问题的过程

什么是循环依赖

Bean A 依赖 B,Bean B 依赖 A这种情况下出现循环依赖。
Bean A → Bean B → Bean A
更复杂的间接依赖造成的循环依赖如下。
Bean A → Bean B → Bean C → Bean D → Bean E → Bean A

解决方案

最有效的解决方式是增加@Lazy注解,延迟加载,先注入代理对象,当首次使用时再创建对象完成注入,代码如下

1
2
3
4
5
6
private SysMetaObjectService sysMetaObjectService;

@Autowired
public void setSysMetaObjectService(@Lazy SysMetaObjectService sysMetaObjectService) {
this.sysMetaObjectService = sysMetaObjectService;
}

其他网上说的直接用@Autowired注解亦或者是setter注入,发现并不管用,我这里用setter注入加上@Lazy注解才算管用

总结

发生循环依赖首先考虑是不是设计的有问题,为什么会产生循环依赖,这不符合java的低耦合原则,所以最应该考虑的是不是需要解耦,其他再考虑使用延迟加载等方案

前言

最近项目上遇到一个奇怪的问题,就是我传的json参数,而且用了Valid注解来校验参数,我确定这个参数传了,但是总是报这个参数不能为空,下面记录下解决方式

问题

下面是我的实体类里的两个字段,其他字段都没问题,都有值,唯独这俩字段没有值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
* x轴坐标
*/
@ApiModelProperty(value="x轴坐标", required = true)
@Excel( name = "x轴坐标", width = 15 )
@NotBlank(message = "x轴坐标不能为空")
private String xCoordinate;

/**
* y轴坐标
*/
@ApiModelProperty(value="y轴坐标", required = true)
@Excel( name = "y轴坐标", width = 15 )
@NotBlank(message = "y轴坐标不能为空")
private String yCoordinate;

所以我第一想到的是不是json转bean的问题,这样的参数命名是不是又问题,我把C改成小写,发现没有问题,多次测试后发现,如果参数第一个字母为小写,第二个字母为大写,就不能正常的从JSON中解析出来,如:xCoordinate,aLame,bId等参数都不能被正常的解析,而mySelf,poType等最前面不止一个字母小写的情况是可以用的

阅读全文 »

前言

因为经常部署项目,所以一些mysql的默认配置其实不太够用,尤其是并发连接比较高的时候,默认的mysql配置非常不够用,需要修改

配置
1
2
show variables like '%max_connection%'; 查看最大连接数
set global max_connections=1000; 重新设置最大连接数
1
2
3
4
5
6
7
8
# 查看当前线程的一些汇总
show status like 'Threads%';

| Threads_cached | 32 |
| Threads_connected | 10 |
| Threads_created | 50 |
| Threads_rejected | 0 |
| Threads_running | 1 |

Threads_connected :这个数值指的是打开的连接数.

Threads_running :这个数值指的是激活的连接数,这个数值一般远低于connected数值.

Threads_connected 跟show processlist结果相同,表示当前连接数。准确的来说,Threads_running是代表当前并发数

1
2
# 查询数据库当前设置的最大连接数
show variables like '%max_connection%';
1
2
#当前连接的所有线程
show processlist;

前言

最近我需要将一台电脑的docker镜像直接搬到另一台上,因为另一台服务器没有接入互联网,所以无法直接下载,经过查看,docker有两种导出镜像的方式,分别说一下

export和import

首先查看所有的容器

1
docker ps -a

导出镜像,使用如下命令

1
2
3
docker export ds2abda > a.tar

# 注意 ds2abda 是上面命令列出来的容器ID,不是镜像ID,不要搞错

命名执行完成后,会在宿主机当前目录下看到有一个a.tar的文件

然后我们把tar拷贝到另一台机器上,使用如下命名执行导入

1
2
3
docker import - new_a_server < a.tar

# 注意-后面的是要生成的镜像名称,再一个需要注意的是 < 箭头的方向,上面和这个是不一样的

导入后,使用如下命令查看是否导入成功

1
2
docker images
# 查看所有镜像
save和load

首先使用以下命令查看本机的镜像,和export不通过,export是查看容器

1
docker images

保存镜像

1
2
docker save abcde > a.tar
# 注意,这里的 abcde 是上面命令列出来的镜像ID,然后保存为a.tar文件

导入镜像

1
docker load < a.tar
两种方式对比

特别注意:两种方法不可混用
如果使用 import 导入 save 产生的文件,虽然导入不提示错误,但是启动容器时会提示失败,会出现类似”docker: Error response from daemon: Container command not found or does not exist“的错误。

1,文件大小不同

export 导出的镜像文件体积小于 save 保存的镜像

2,是否可以对镜像重命名
  • docker import 可以为镜像指定新名称
  • docker load 不能对载入的镜像重命名
3,是否可以同时将多个镜像打包到一个文件中
  • docker export 不支持
  • docker save 支持
4,是否包含镜像历史
  • export 导出(import 导入)是根据容器拿到的镜像,再导入时会丢失镜像所有的历史记录和元数据信息(即仅保存容器当时的快照状态),所以无法进行回滚操作。

  • save 保存(load 加载)的镜像,没有丢失镜像的历史,可以回滚到之前的层(layer)。

5,应用场景不同
  • docker export 的应用场景:主要用来制作基础镜像,比如我们从一个 ubuntu 镜像启动一个容器,然后安装一些软件和进行一些设置后,使用 docker export 保存为一个基础镜像。然后,把这个镜像分发给其他人使用,比如作为基础的开发环境。
  • docker save 的应用场景:如果我们的应用是使用 docker-compose.yml 编排的多个镜像组合,但我们要部署的客户服务器并不能连外网。这时就可以使用 docker save 将用到的镜像打个包,然后拷贝到客户服务器上使用 docker load 载入。
重名名镜像
1
2
3
4
docker tag [镜像id] [新镜像名称]:[新镜像标签] 

#例如
docker tag 93109ce1d590 test-py:3.7.13

前言

之前遇到过一个问题,需要查询日志,是linux服务器,但是日志文件很大,超过20G,日志输出特别快,所以直接tail -f 无法也很难截取到日志,所以就想根据关键字,用tail查看最近多少行的日志输出,再用grep搜索查看前后几行的信息

命令

根据关键字查看日志

1
cat web_info.log | grep “请求结果”

根据关键字查看后10行日志

1
cat web_info.log | grep “请求结果” -A 10

根据关键字查看前10行日志

1
cat web_info.log | grep “请求结果” -B 10

根据关键字查看前后10行日志,并显示出行号

1
cat -n web_info.log | grep “请求结果” -C 10

查看日志前 50 行

1
cat web_info.log | head -n 50

查看日志后 50 行,并显示出行号

1
cat -n web_info.log | tail -n 50

说明:

  • -A 表示关键字之后,After
  • -B 表示关键字之前,Before
  • -C 表示关键字前后,Context