原创

日常问题随笔 | 更新ing...

作者 | 浩说编程
来源 | 公众号:浩说编程
[  用"内容"服务读者 | 让"代码"服务大众  ]


21.09.07 | error while loading shared libraries: libasound.so.2

    问题描述:今天在linux中执行Appimage文件的时候提示报错。

    报错信息:error while loading shared libraries: libasound.so.2: cannot open shared object file: No such file or directory


    第一次尝试:根据报错信息,网上的说法是没有打包libasound2,给出的解决方案是:

sudo su # 切换到su 用户
apt update
apt install libasound2
    执行到第二条命令,出现以下提示:

    根据报错信息再次搜索,了解到此错误的原因:

    linux系统分为两种系列:

  1. RedHat系列,包括Redhat、Centos、Fedora...
  2. Debian系列,报货Debian、Ubuntu等
    RedHat系列的包管理工具使用的是:yum

    Debian系列的包管理工具使用的是:apt-get

    于是使用命令查看我的linux属于哪种系列:

cat /proc/version
    使用yum进行第二次尝试,在执行yum install libasound2 命令之后报错:
Error:Unable to find a match

    很明显是找不到这个包,所以系统应该没安装这个包。

    于是执行安装命令,进行第三次尝试:

//安装libasound.so.2的命令:
yum install alsa-lib-devel

    安装成功:


21.11.03 | 从List随机抽取一条数据

1  List<Integer> list = new ArrayList<>();
2 Random random = new Random();
3 int n = random.nextInt(list.size());
4 list.get(n);


22.01.12 | 对接微信公众平台验证token

    今天在做公众号扫码登录的时候,公众号需要先验证web应用的token


    在网上尝试了各种方案,总是有多多少少的问题,后来经过各种方案的结合,最终得到可以验证成功的版本:

    环境:springboot

    1、配置服务代理(这里我用的Nginx)

server {
location /{
#注意,代理之后的端口必须是8080或443,否则验证失败
proxy_pass http://你的ip:8080;
}
}

    2、controller

@Controller
@RequestMapping("/oauth")
public class OAuthController {

/**
* 微信公众号签名认证接口
* @Title: test
* @Description: TODO
* @param: @param signature
* @param: @param timestamp
* @param: @param nonce
* @param: @param echostr
* @param: @return
* @return: String
* @throws
*/
@RequestMapping("/wx")
public void test(HttpServletRequest request,HttpServletResponse response) {

String msgSignature = request.getParameter("signature");
String msgTimestamp = request.getParameter("timestamp");
String msgNonce = request.getParameter("nonce");
String echostr = request.getParameter("echostr");
PrintWriter print;
if (WeixinCheckoutUtil.verifyUrl(msgSignature, msgTimestamp, msgNonce)) {
try {
print = response.getWriter();
print.write(echostr);
print.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

    3、验证token,SHA-1算法

/**
* 签名认证工具类
* @ClassName: WeixinCheckoutUtil
* @Description:TODO
* @author: jp
* @date: 2019年6月13日 下午4:56:12
*
* @Copyright: 2019 www.tydic.com Inc. All rights reserved.
*
*/
public class WeixinCheckoutUtil {

// 与公众号配置信息中的Token要一致
private static String token = "";

/**
* 验证Token
* @param msgSignature 签名串,对应URL参数的signature
* @param timeStamp 时间戳,对应URL参数的timestamp
* @param nonce 随机串,对应URL参数的nonce
*
* @return 是否为安全签名
*/
public static boolean verifyUrl(String msgSignature, String timeStamp, String nonce) {
String signature =getSHA1(token, timeStamp, nonce);
if (!signature.equals(msgSignature)) {
throw new AesException(AesException.ValidateSignatureError);
}
return true;
}

/**
* 用SHA1算法验证Token
*
* @param token 票据
* @param timestamp 时间戳
* @param nonce 随机字符串
* @return 安全签名
*/
public static String getSHA1(String token, String timestamp, String nonce) {
try {
String[] array = new String[]{token, timestamp, nonce};
StringBuffer sb = new StringBuffer();
// 字符串排序
Arrays.sort(array);
for (int i = 0; i < 3; i++) {
sb.append(array[i]);
}
String str = sb.toString();
// SHA1签名生成
MessageDigest md = MessageDigest.getInstance("SHA-1");
md.update(str.getBytes());
byte[] digest = md.digest();

StringBuffer hexstr = new StringBuffer();
String shaHex = "";
for (int i = 0; i < digest.length; i++) {
shaHex = Integer.toHexString(digest[i] & 0xFF);
if (shaHex.length() < 2) {
hexstr.append(0);
}
hexstr.append(shaHex);
}
return hexstr.toString();
} catch (Exception e) {
e.printStackTrace();
//throw new AesException(AesException.ComputeSignatureError);
}
return null;
}
}


22.06.17 | VUE子组件向父组件传值

    一,子组件主动触发事件将数据传递给父组件
        1,在子组件上绑定某个事件以及事件触发的函数
        子组件代码

<template>
<div>
<Tree :data="treeData" show-checkbox ref="treeData"></Tree>

<Button type="success" @click="submit"></Button>
</div>

</template>

        事件在子组件中触发的函数

submit(){
this.$emit('getTreeData',this.$refs.treeData.getCheckedNodes());
},

        2,在父组件中绑定触发事件

<AuthTree  @getTreeData='testData'>
</AuthTree>

        父组件触发函数显示子组件传递的数据

testData(data){
console.log("parent");
console.log(data)
},

    原文链接:https://blog.csdn.net/weixin_43974311/article/details/111613331


22.07.22 | PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException

    问题描述:今天在项目内部调用外部的restful API,遇到了这个问题(HTTPS请求):


    原因是,https请求,需要SSL证书认证。

    解决方案:重写SimpleClientHttpRequestFactory抽象类的prepareConnection方法

/**
* 兼容调Https接口
* @Author mazq
* @Date 2020/06/04 17:16
* @Param
* @return
*/
public class HttpsClientRequestFactory extends SimpleClientHttpRequestFactory {

@Override
protected void prepareConnection(HttpURLConnection connection, String httpMethod) {
try {
if (!(connection instanceof HttpsURLConnection)) {// http协议
//throw new RuntimeException("An instance of HttpsURLConnection is expected");
super.prepareConnection(connection, httpMethod);
}
if (connection instanceof HttpsURLConnection) {// https协议,修改协议版本
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
// 信任任何链接
TrustStrategy anyTrustStrategy = new TrustStrategy() {
@Override
public boolean isTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
return true;
}
};
SSLContext ctx = SSLContexts.custom().useTLS().loadTrustMaterial(trustStore, anyTrustStrategy).build();
((HttpsURLConnection) connection).setSSLSocketFactory(ctx.getSocketFactory());
HttpsURLConnection httpsConnection = (HttpsURLConnection) connection;
super.prepareConnection(httpsConnection, httpMethod);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}

    封装请求工具类

/**
* <pre>
* RestTemplate 远程调用工具类
* </pre>
*
* <pre>
* @author mazq
* 修改记录
* 修改后版本: 修改人:修改日期: 2020/06/01 11:38 修改内容:
* </pre>
*/
@Component
public class RestTemplateUtils {

//这里是关键
public static RestTemplate geTemplate(){
return new RestTemplate(new HttpsClientRequestFactory());
}

/**
* GET请求调用方式
* @Author mazq
* @Date 2020/06/01 13:47
* @Param [url, responseType, uriVariables]
* @return org.springframework.http.ResponseEntity<T>
*/
public static <T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Map<String, ?> uriVariables) {
return geTemplate().getForEntity(url, responseType, uriVariables);
}

/**
* POST请求调用方式
* @Author mazq
* @Date 2020/06/01 13:47
* @Param [url, headers, body, responseType]
* @return org.springframework.http.ResponseEntity<T>
*/
public static <T> ResponseEntity<T> postForEntity(String url,HttpHeaders headers, Object requestBody , Class<T> responseType ){

HttpEntity<Object> requestEntity = new HttpEntity<Object>(requestBody, headers);
return geTemplate().postForEntity(url, requestEntity, responseType);
}

/**
* PUT请求调用方式
* @Author mazq
* @Date 2020/06/01 13:35
* @param url 请求URL
* @param headers 请求头参数
* @param requestBody 请求参数体
* @param responseType 返回对象类型
* @param uriVariables URL中的变量,与Map中的key对应
* @return ResponseEntity 响应对象封装类
*/
public static <T> ResponseEntity<T> put(String url, HttpHeaders headers, Object requestBody, Class<T> responseType, Map<String, ?> uriVariables) {
HttpEntity<Object> requestEntity = new HttpEntity<Object>(requestBody, headers);
return geTemplate().exchange(url, HttpMethod.PUT, requestEntity, responseType, uriVariables);
}

/**
* DELETE请求调用方式
* @Author mazq
* @Date 2020/06/01 13:37
* @param url 请求URL
* @param headers 请求头参数
* @param requestBody 请求参数体
* @param responseType 返回对象类型
* @param uriVariables URL中的变量,按顺序依次对应
* @return ResponseEntity 响应对象封装类
*/
public static <T> ResponseEntity<T> delete(String url, HttpHeaders headers, Object requestBody, Class<T> responseType, Object... uriVariables) {
HttpEntity<Object> requestEntity = new HttpEntity<Object>(requestBody, headers);
return geTemplate().exchange(url, HttpMethod.DELETE, requestEntity, responseType, uriVariables);
}

/**
* 通用调用方式
* @Author mazq
* @Date 2020/06/01 13:37
* @Param [url, method, requestEntity, responseType, uriVariables]
* @return org.springframework.http.ResponseEntity<T>
*/
public static <T> ResponseEntity<T> exchange(String url, HttpMethod method, HttpEntity<?> requestEntity, Class<T> responseType, Map<String, ?> uriVariables) {
return geTemplate().exchange(url, method, requestEntity, responseType, uriVariables);
}
}

    再次测试,调用成功,问题解决

        MultiValueMap<String, String> map= new LinkedMultiValueMap<String, String>();
map.add("username","admin");
map.add("password","OpenText1");
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
log.info("远程调用传递参数:");
log.info("headers" + headers);
log.info("params:" + map);
ResponseEntity<String> responseEntity = RestTemplateUtils.postForEntity("https://ecmqas.wuxibiologics.com/otcs/cs.exe/api/v1/auth",headers,map,String.class);
log.info("远程调用返回结果:" + responseEntity);


22.10.29 | 使用resttemplate调用外部put请求,提示‘400 bad request’

    今天在项目内部调用外部put类型api时出现以下报错:

    我请求的api的url地址是参数在中间的这种:/a/b/{参数}/c/{参数2}

    分析应该是参数传的方式不对,导致该错误

    解决方案尝试:

    在网上搜了一些相关问题后,参照网友的解决方案,做了以下尝试

    尝试1:使用exchange方法

HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);

MultiValueMap<String, String> map= new LinkedMultiValueMap<String, String>();

map.add(category_id,category_value);
MultiValueMap<String, String> map2= new LinkedMultiValueMap<String, String>();
map2.add("id",parent_id);
map2.add("category_id",category_id.split("_")[0]);
try{ //封装RestTemplate到工具类RestTemplateUtils ResponseEntity responseEntity = RestTemplateUtils.put("https://...../{id}/categories/{category_id}/",headers, map,String.class,map2);
}catch (Exception e){
log.error(e.getMessage());
}

//RestTemplate工具类RestTemplateUtils实现

/**
* PUT请求调用方式
* @param url 请求URL
* @param headers 请求头参数
* @param requestBody 请求参数体
* @param responseType 返回对象类型
* @param uriVariables URL中的变量,与Map中的key对应
* @return ResponseEntity 响应对象封装类
*/
public static <T> ResponseEntity<T> put(String url, HttpHeaders headers, Object requestBody, Class<T> responseType, Map<String, ?> uriVariables) {
HttpEntity<Object> requestEntity = new HttpEntity<Object>(requestBody, headers);
return geTemplate().exchange(url, HttpMethod.PUT, requestEntity, responseType, uriVariables);
}

    尝试结果:依然报错


    尝试2:使用put方法,修改工具类里的方法为put方法

     * PUT请求调用方式
* @param url 请求URL
* @param headers 请求头参数
* @param requestBody 请求参数体
* @param responseType 返回对象类型
* @param uriVariables URL中的变量,与Map中的key对应
* @return ResponseEntity 响应对象封装类
*/
public static <T> ResponseEntity<T> put(String url, HttpHeaders headers, Object requestBody, Class<T> responseType, Map<String, ?> uriVariables) {
HttpEntity<Object> requestEntity = new HttpEntity<Object>(requestBody, headers);
geTemplate().put(url, requestEntity,uriVariables);

return null;

}

    尝试结果:依然失败

    尝试3:在尝试了网上的各种方法都不奏效之后,我用自己修改的下面这种方法,成功解决问题!!!

    解决方案:修改url的传参·方式

//修改之前:
ResponseEntity<String> responseEntity = RestTemplateUtils.put("https://...../{id}/categories/{category_id}/",headers, map,String.class,map2);
//修改之后:

ResponseEntity<String> responseEntity = RestTemplateUtils.put("https://...../" + parent_id + "/categories/" + category_id.split("_")[0] + "/",headers,map,String.class,map2);

//也就是直接将参数放到url里

    尝试结果:请求成功!!!!


23.01.27 | 正则表达式校验字符串中的"汉字"

    方法有两种:

    1、Pattern.compile("[\u4e00-\u9fa5]").matcher("str").find()

    2、Pattern.matches("[\u4e00-\u9fa5]" , "str")

    经过测试,推荐使用第一种,因为第二种无法校验"包含汉字"的情况。


23.05.23 | 解析excel文件报错Strict OOXML isn't currently,please see bug #57699

    今天在代码中使用XSSFWorkbook读取excel文件报下图错误:


    原因分析:经调查,原因是Excel的保存格式选择错误
    解决方案:另存为上方箭头所指的格式即可解决问题


23.06.27 | java8筛选集合中重复的属性

Map<Object, Long> collect2 = archiveList.stream().collect(
Collectors.groupingBy( PDArchive::getFilename , Collectors.counting() ) );
System.out.println("重复计数情况:"+collect2);
List<Object> collect3 = collect2.keySet().stream().
filter(key -> collect2.get(key) > 1).collect(Collectors.toList());
System.out.println("重复的 : "+collect3);


23.11.18 | sql server management 无法修改表结构

在sql server management 中修改表结构提示报错:

"不允许保存更改,您所做的更改要求删除并重新创建以下表"

解决方法:

工具菜单-->选项-->Designers-->表设计器和数据库设计器-->把 阻止保存要求重新创建表的更改 对号去掉 点击确实,然后在保存修改后的表就OK了


24.01.10 | springboot 配置多数据源

基于 dynamic-datasource

pom文件添加依赖:

<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
<version>3.3.2</version>
</dependency>

修改配置文件:

spring:
datasource:
dynamic:
primary: mysql #设置默认的数据源
strict: false
datasource:
mysql:
url: jdbc:mysql://xx.xx.xx.xx:3306/dynamic
username: root
password: 123456
driver-class-name: com.mysql.jdbc.Driver # 3.2.0开始支持SPI可省略此配置
pgsql:
url: ENC(xxxxx) # 内置加密
username: ENC(xxxxx)
password: ENC(xxxxx)
driver-class-name: org.postgresql.Driver

配置注解:@DS(“mysql”)  方法或类上,参数名为配置文件中定义的数据源名称


正文到此结束
本文目录