分类
Java 笔记 编程

DataSource health check failed

在项目中集成ShardingJDBC,启动报错:ConnectionCallback; isValid; nested exception is java.sql.SQLFeatureNotSupportedException: isValid

该项目是新做的,使用较新版本的Spring Boot 2.3,数据库连接词用Hikari。

用Sharding-JDBC蛮久了,之前一直是与DBCP2或Druid,没出过什么问题。这次集成Hikari,系统虽然报错但也能正常启动,仔细看源码,问题应该出在键康检查。

分类
Java

Java基于Runtime调用外部程序出现阻塞的解决

有时候在java代码中会调用一些外部程序,比如SwfTools来转换swf、ffmpeg来转换视频等。如果你的代码这样写:

Runtime.getRuntime().exec(command),会发现程序一下就执行完毕,而在命令行里要执行一会,是因为java没有等待外部程序的执行完毕,此时就需要使用阻塞,来等待外部程序执行结果:

InputStream stderr = process.getInputStream();
InputStreamReader isr = new InputStreamReader(stderr, "GBK");
BufferedReader br = new BufferedReader(isr);
String line = null;
while ((line = br.readLine()) != null)
  System.out.println(line);
int exitValue = process.waitFor();

对于一般的外部程序使用上面的阻塞代码就可以,至少pdf2swf.exe是没有问题的。

但是紧接着又发现对于ffmpeg来说,以上代码会让程序卡住不动,需要使用另一种方式,封装成了一个方法,如下:

分类
Web

设置WordPress内所有URL都在新标签页打开

WordPress默认情况下几乎所有URL链接都是在同一个标签页打开。这样的话,读者点击一个链接就会离开当前页面,如果读者想要查看原来的页面又要进行返回操作,在某些情况下用户体验不佳。但是,如果一个一个单独为每个链接添加新标签页打开的代码,工作量会很大,也容易造成遗漏。本文就介绍一种通过一次添加代码的操作,达到全站链接都在新标签页打开的方法。

打开当前正在使用的WordPress主题中的header.php 文件(在WordPress中该文件用于设置全局页面的顶部),在 的后面加上:

<base target="_blank">
分类
Nginx Web 笔记

Nginx https 反向代理 http

在Docker中运行WEB应用,由主机Nginx反向代理。由于Docker中的应用是http,而反向代理强制使用https,会遇到有些情况代理失败。

只要在配置中加上

proxy_set_header X-Forwarded-Proto https;

完整配置:

server {
    listen 80;
    listen [::]:80;
    server_name engr-z.com www.engr-z.com;
#    enforce https
    return 301 https://$server_name:443$request_uri;
}

server {
    listen 443 ssl;
    listen [::]:443 ssl;
    server_name engr-z.com www.engr-z.com;

    client_max_body_size 1G;

    ssl_certificate /data/www/cert/engr-z.com_nginx/cert.pem;
    ssl_certificate_key /data/www/cert/engr-z.com_nginx/cert.key;
    ssl_session_timeout 5m;
    ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4; #使用此加密套件。
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2; #使用该协议进行配置。
    ssl_prefer_server_ciphers on;

    location / {
        proxy_pass http://127.0.0.1:8001/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-Ip $remote_addr;
        proxy_set_header X-Forwarded-For $remote_addr;
        proxy_set_header X-Forwarded-Proto https;
#        proxy_cookie_path / /;
    }
}
分类
Bash Linux

怎样用 Bash 编程:循环

我使用过的所有编程语言都至少有两种循环结构来用来执行重复的操作。我经常使用 for 循环,然而我发现 while 和 until 循环也很有用处。

for 循环

我的理解是,在 bash 中实现的 for 命令比大部分语言灵活,因为它可以处理非数字的值;与之形成对比的是,诸如标准 C 语言的 for 循环只能处理数字类型的值。

Bash 版的 for 命令基本的结构很简单:

for Var in list1 ; do list2 ; done

解释一下:“对于 list1 中的每一个值,把 $Var 设置为那个值,使用该值执行 list2 中的程序语句;list1 中的值都执行完后,整个循环结束,退出循环。” list1 中的值可以是一个简单的显式字符串值,也可以是一个命令执行后的结果(“ 包含其内的命令执行的结果,本系列第二篇文章中有描述)。我经常使用这种结构。

分类
Java 笔记

阿里云自动动态地址解析

家里找电信开通了动态公网地址,每天IP会变一次。我的域名是在阿里云申请的,路由器只支持花生壳和公云的DDNS设置,每天手动变更一次域名指向麻烦,利用阿里云的API,写了一个动态更新的小工具。

首先在阿里云后台申请创建AccessKey:

分类
Bash

怎样用 Bash 编程:逻辑操作符和 shell 扩展

逻辑操作符是程序中进行判断的根本要素,也是执行不同的语句组合的依据。有时这也被称为流控制。

逻辑操作符

Bash 中有大量的用于不同条件表达式的逻辑操作符。最基本的是 if 控制结构,它判断一个条件,如果条件为真,就执行一些程序语句。操作符共有三类:文件、数字和非数字操作符。如果条件为真,所有的操作符返回真值(0),如果条件为假,返回假值(1)。

这些比较操作符的函数语法是,一个操作符加一个或两个参数放在中括号内,后面跟一系列程序语句,如果条件为真,程序语句执行,可能会有另一个程序语句列表,该列表在条件为假时执行:

if [ arg1 operator arg2 ] ; then list
或
if [ arg1 operator arg2 ] ; then list ; else list ; fi

像例子中那样,在比较表达式中,空格不能省略。中括号的每部分,[ 和 ],是跟 test 命令一样的传统的 Bash 符号:

if test arg1 operator arg2 ; then list

还有一个更新的语法能提供一点点便利,一些系统管理员比较喜欢用。这种格式对于不同版本的 Bash 和一些 shell 如 ksh(Korn shell)兼容性稍差。格式如下:

if [[ arg1 operator arg2 ]] ; then list
分类
Java 日记 笔记

Sharding JDBC Demo 2.0 (主从版)

从今年初接触Sharding JDBC 4.0到现在,近一年了,用来做日志和消息分表一直运行,没什么大的问题。前些天生产新上了一个服务,是因为Sharding JDBC把select for update语句解析为查询,在从库中执行,因为从库是只读权限所以报错。

之前没在测试环境发现这个问题,是因为测试环境数据库没有主从。想起当时刚接触Sharding JDBC写的Demo,于是整理一番,重新拉分支,并完善整个流程,模拟真实场景。

分类
Java

Spring 框架的设计理念与设计模式分析

Spring 的骨骼架构

Spring 总共有十几个组件,但是真正核心的组件只有几个,下面是 Spring 框架的总体架构图:

图 1 .Spring 框架的总体架构图

从上图中可以看出 Spring 框架中的核心组件只有三个:Core、Context 和 Beans。它们构建起了整个 Spring 的骨骼架构。没有它们就不可能有 AOP、Web 等上层的特性功能。下面也将主要从这三个组件入手分析 Spring。

分类
Web

JS保存文件到本地

将页面的JSON数据保存到本地:

var content = JSON.stringify(json对象);
var eleLink = document.createElement('a');
eleLink.download = "info.json";
eleLink.style.display = 'none';
// 字符内容转变成blob地址
var blob = new Blob([content]);
eleLink.href = URL.createObjectURL(blob);
// 触发点击
document.body.appendChild(eleLink);
eleLink.click();
// 然后移除
document.body.removeChild(eleLink);