Giter VIP home page Giter VIP logo

notes's Introduction

Summary

notes's People

Stargazers

 avatar  avatar

Watchers

 avatar

notes's Issues

Mac Navicat Premium 12 试用时间重置

重置步骤

参考zhile佬博客,因为博客写的已经很详细了,这里就不再重复,由于时间比较久,脚本已经失效,所以我按照zhile佬的思路重写了脚本。

新脚本

#!/bin/bash
VER=121 # 你使用的Navicat Premium版本号,12.0.x为120,12.1.x为121,以此类推。
DSTR=$(date +%Y%m%d)
echo $DSTR
defaults write ~/Library/Preferences/com.prect.NavicatPremium12.plist ptc$VER $DSTR
defaults write ~/Library/Preferences/com.prect.NavicatPremium12.plist ptcl$VER $DSTR

echo $DSTR > ~/Library/Application\ Support/PremiumSoft\ CyberTech/Navicat\ CC/Navicat\ Premium/.tc$VER

操作说明

使用本文中脚本替代zhile佬博客的脚本重置,其余操作不变。🫡致敬zhile佬!

2023年11月20日亲测有效

swagger-resources 404

接口文档异常

报错页面

image

http://127.0.0.1:8040/swagger-resources 接口404

解决方法:增加@EnableSwagger2注解配置

vscode rust-analyzer 提示 Failed to spawn one or more proc-macro servers.

Mac os 环境下 安装好rust环境,使用vscoderust-analyzer报错

Failed to spawn one or more proc-macro servers.

- cannot find proc-macro-srv, the workspace `/Users/xxxx/vscode/rust/guessing_game` is missing a sysroot

Failed to find sysroot for Cargo.toml file /Users/xxxx/vscode/rust/guessing_game/Cargo.toml. Is rust-src installed? can't load standard library from sysroot

/Users/xxxx/.rustup/toolchains/stable-x86_64-apple-darwin

(discovered via `rustc --print sysroot`)

try installing the Rust source the same way you installed rustc

解决方案

# 安装 rust-src
sudo rustup component add rust-src

vscode 中重启一下rust-analyzer插件之后就能解决。

Ubuntu 安装firefox报错

在Ubuntu上安装firefox时提示

Running Firefox as *** in a regular user's session is not supported.  ($XDG_RUNTIME_DIR is /run/user/1001 which is owned by runner.)

需要修改目录权限

sudo chown -R root:root /run/user/1001

Linux yum 安装 Redis 踩坑

安装命令

yum install -y redis

启动报错

启动命令service redis start,以下是具体报错信息

[root@master01 etc]# systemctl status redis.service
● redis.service - Redis persistent key-value database
   Loaded: loaded (/usr/lib/systemd/system/redis.service; disabled; vendor pres>
   Active: failed (Result: exit-code) since Mon 2023-09-04 11:39:56 CST; 6min a>
  Process: 51746 ExecStart=/usr/bin/redis-server /etc/redis.conf --supervised s>
 Main PID: 51746 (code=exited, status=217/USER)

9月 04 11:39:56 master01 systemd[1]: Starting Redis persistent key-value databa>
9月 04 11:39:56 master01 systemd[1]: redis.service: Main process exited, code=e>
9月 04 11:39:56 master01 systemd[1]: redis.service: Failed with result 'exit-co>
9月 04 11:39:56 master01 systemd[1]: Failed to start Redis persistent key-value>

分析以后发现是没有权限导致的,以下是解决方案

mkdir /var/lib/redis;
mkdir /var/log/redis;
groupadd redis;
useradd -M redis -g redis -s /sbin/nologin;
chown -R redis:redis /var/lib/redis;
chown -R redis:redis /var/log/redis;
chmod 644 /etc/redis.conf;

依次执行之后再使用service redis start 就能成功启动

Nginx 配置 WebSocket 代理

# 匹配路径
location /websocket {
    proxy_set_header  Host $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:8040/websocket;
    
    # 关键配置 start
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    # 关键配置 end
} 

Linux yum 安装 nginx 踩坑

安装命令

yum install -y nginx

访问nginx报错

  1. 403 Forbidden
  2. 404 Not Found

在nginx.conf在找到nginx error log查看发现提示Permission denied

2023/09/04 18:02:49 [crit] 109854#0: *14 stat() "/home/front-end/admin/" failed (13: Permission denied), client: 127.0.0.1, server: localhost, request: "GET / HTTP/1.1", host: "127.0.0.1:8096"
2023/09/04 18:02:49 [crit] 109854#0: *14 stat() "/home/front-end/admin/index.html" failed (13: Permission denied), client: 127.0.0.1, server: localhost, request: "GET / HTTP/1.1", host: "127.0.0.1:8096"

有两种解决方案
image

  1. 将nginx,conf中的user nginx 改为 user root,增加目录操作权限,但是可能会有风险。
  2. 增加nginx,给予nginx用户操作权限。
groupadd nginx;
useradd -M nginx -g nginx -s /sbin/nologin;
# 修改目录权限
chown -R nginx:nginx /home/front-end/admin/;
chmod +x /home/front-end/admin/;

vuepress 踩坑

前因

打算使用vuepress做博客,项目结构以及配置都按官方文档设置,运行npm run docs:dev也是正常的,但是npm run docs:build打包的时候一直报错,下面是部分报错日志

(undefined) assets/js/styles.8f3dca9f.js from Terser
Error: error:0308010C:digital envelope routines::unsupported
    at new Hash (node:internal/crypto/hash:69:19)
    at Object.createHash (node:crypto:133:10)
    at /Users/zhangwentao/vscode/notes/node_modules/terser-webpack-plugin/dist/index.js:217:37
    at Array.forEach (<anonymous>)
    at TerserPlugin.optimizeFn (/Users/zhangwentao/vscode/notes/node_modules/terser-webpack-plugin/dist/index.js:160:259)
    at _next0 (eval at create (/Users/zhangwentao/vscode/notes/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:13:1)
    at eval (eval at create (/Users/zhangwentao/vscode/notes/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:30:1)
(undefined) assets/js/1.7f771cfb.js from Terser

解决方法

有两种解决方法

  1. 降级node版本
    经过验证node 16 版本下npm run docs:build 是正常的,在node 18版本下运行就会出现这个错误
  2. 设置环境变量(未验证)
    具体的操作方式 webpack/webpack#14532

解决中文乱码

起因

在接口接收url参数的时候出现中文乱码

// 乱码
url?name=测试   ->  url?name=娴嬭瘯

前端接口传入的name是测试,但是服务端接收到的是娴嬭瘯

转换正常中文方案

  1. 找到在的编码和原来编码,在这里输入乱码内容

    image

    找到转换正常的编码,UTF-8 就是原来的编码,GBK 就是现在的编码

  2. 将乱码从现在的编码转换成原来的编码

     // 需要找到现在的编码和原来编码 才能转换成正常中文
     String newName = new String(name.getBytes("GBK"), StandardCharsets.UTF_8)

书单 & 学习方向

  • #2
  • #1
  • MySQL 官方文档
  • 计算机网络自顶向下
  • Redis 深度历险
  • Java 并发编程的艺术
  • Java 并发编程实战
  • 大话设计模式
  • 数据结构与算法分析
  • Spring 源码,SpringMVC 源码,JUC源码

yum 安装 nginx 缺少依赖报错

错误信息

[root@localhost sbin]# yum install -y nginx
已加载插件:fastestmirror
Loading mirror speeds from cached hostfile
正在解决依赖关系
--> 正在检查事务
---> 软件包 nginx.x86_64.1.1.24.0-1.el7.ngx 将被 安装
--> 正在处理依赖关系 libpcre2-8.so.0()(64bit),它被软件包 1:nginx-1.24.0-1.el7.ngx.x86_64 需要
--> 解决依赖关系完成
错误:软件包:1:nginx-1.24.0-1.el7.ngx.x86_64 (nginx)
          需要:libpcre2-8.so.0()(64bit)
 您可以尝试添加 --skip-broken 选项来解决该问题
 您可以尝试执行:rpm -Va --nofiles --nodigest

解决方法

下载1依赖到本地安装

  1. 下载
wget http://mirror.centos.org/centos/7/os/x86_64/Packages/pcre2-10.23-2.el7.x86_64.rpm
  1. 安装
rpm -ivh pcre2-10.23-2.el7.x86_64.rpm

再尝试安装命令nginx命令即可

Footnotes

  1. 网页下载地址:https://centos.pkgs.org/7/centos-x86_64/pcre2-10.23-2.el7.x86_64.rpm.html

Java RSA 接口签名认证实现

前因

在业务上需要暴露一些接口提供给第三方,经过讨论决定使用RSA1签名来做接口认证。

签名认证

生成签名

        String appSecret = "...private_key...";

        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PKCS8EncodedKeySpec privateSpec = new PKCS8EncodedKeySpec(Base64.decode(appSecret));

        PrivateKey privateKey = keyFactory.generatePrivate(privateSpec);

        // Create a Signature object
        Signature sign = Signature.getInstance("SHA256withRSA");

        // sign
        sign.initSign(privateKey);
        sign.update("Hello, World!".getBytes("UTF-8"));
        byte[] signature = sign.sign();
        System.out.println("Signature: " + Base64.encode(signature));

验证签名

       String appKey = "...public_key..."
        // Decode the keys
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        X509EncodedKeySpec publicSpec = new X509EncodedKeySpec(Base64.decode(appKey));

        PublicKey publicKey = keyFactory.generatePublic(publicSpec);

        // Verify
        Signature verifySig = Signature.getInstance("SHA256withRSA");
        verifySig.initVerify(publicKey);
        verifySig.update("Hello, World!".getBytes("UTF-8"));
        boolean isCorrect = verifySig.verify(signature);
        System.out.println("Signature correct: " + isCorrect);

完整的工具方法

import cn.hutool.core.codec.Base64;
import cn.hutool.crypto.SecureUtil;

import java.nio.charset.StandardCharsets;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

/**
 * Description: RSA 工具
 */
public class RSAUtil {

    /**
     * 验证签名
     * @param publicKey 公钥
     * @param sign      签名
     * @param data      数据
     * @return          是否验证通过
     * @throws Exception 异常
     */
    public static boolean verify(String publicKey, String sign, String data) {
        X509EncodedKeySpec publicSpec = new X509EncodedKeySpec(Base64.decode(publicKey));
        PublicKey key = SecureUtil.generatePublicKey("RSA", publicSpec);
        // Verify
        try {
            Signature verifySig = Signature.getInstance("SHA256withRSA");
            verifySig.initVerify(key);
            verifySig.update(data.getBytes(StandardCharsets.UTF_8));
            return verifySig.verify(Base64.decode(sign));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 生成签名
     * @param privateKey 私钥
     * @param data       数据
     * @return           签名
     */
    public static String sign(String privateKey, String data) throws Exception {
        PKCS8EncodedKeySpec privateSpec = new PKCS8EncodedKeySpec(Base64.decode(privateKey));
        PrivateKey key = SecureUtil.generatePrivateKey("RSA", privateSpec);

        // Create a Signature object
        Signature sign = Signature.getInstance("SHA256withRSA");
        // Sign
        sign.initSign(key);
        sign.update(data.getBytes(StandardCharsets.UTF_8));
        byte[] signature = sign.sign();
        return Base64.encode(signature);
    }
}

Python pycryptodome 实现

安装 pycryptodome

pip install pycryptodome

实现代码

import base64
import http.client
import json
import time
import Crypto
from Crypto.PublicKey import RSA
from Crypto.Signature import pkcs1_15
from Crypto.Hash import SHA256


appKey = "...public_key..."
app_secret = """-----BEGIN RSA PRIVATE KEY-----
...private_key...
-----END RSA PRIVATE KEY-----"""


def sign(data, private_key):
    key = RSA.import_key(private_key)
    h = SHA256.new(data.encode('utf-8'))
    signature = pkcs1_15.new(key).sign(h)
    return base64.b64encode(signature).decode('utf-8')

def verify(public_key, sign, data):
    public_key = RSA.import_key(public_key)
    sign_bytes = b64decode(sign)
    hash = SHA256.new(data.encode('utf-8'))
    return pkcs1_15.new(public_key).verify(hash, sign_bytes)

记录一些问题

最早使用的是 hutool工具实现签名认证,但是在测试过程中发现Python中生成的签名无法认证,由此改成 Java 中基础库来实现

Footnotes

  1. RSA wikipedia

处理非文件上传时的 Multipart 请求解析错误

前因

在处理非文件上传的请求时,Spring抛出了一个关于Multipart请求解析的错误。

错误日志

Failed to parse multipart servlet request; nested exception is java.io.IOException: The temporary upload location [/tmp/tomcat.8656187483509135391.8020/work/Tomcat/localhost/ROOT] is not valid

org.springframework.web.multipart.MultipartException: Failed to parse multipart servlet request; nested exception is java.io.IOException: The temporary upload location [/tmp/tomcat.8656187483509135391.8020/work/Tomcat/localhost/ROOT] is not valid

这个错误在描述上来看是发生在文件上传接口,但是报错的接口是非上传文件接口,之前没有遇到过所以记录一下

出现原因

  • 请求头设置不正确,经过排查前端请求接口请求头Content-Type设置成了multipart/form-data,所以会出现非上传接口出现MultipartException
  • Servlet临时目录不存在Servlet接收上传文件时会在/tmp目录下创建临时目录提高性能,所以在服务启动的时候会创建tmp/tomcat.8656187483509135391.8020/work/Tomcat/localhost/ROOT临时目录,但是由于CentOS 会清除临时文件,所以才会出现这个报错

解决方法

1. 修改配置

  • 设置正确的请求头
  • 检查/tmp/tomcat.8656187483509135391.8020/work/Tomcat/localhost/ROOT是否正常,避免再出现这样的问题,手动配置指定路径
    spring:
     servlet:
      multipart:
        location: /path/to

2. 设置CentOS 清除临时目录忽略

在下面这个文件中增加一行配置

/usr/lib/tmpfiles.d/tmp.conf

增加内容

X /tmp/tomcat.*

以上两个方案选其一即可

另外收获

在查看Spring Boot 源码的时候看到下面这段代码👇

 /**
  * Create a new {@link MultipartConfigElement} using the properties.
  * @return a new {@link MultipartConfigElement} configured using there properties
  * */
public MultipartConfigElement createMultipartConfig() {
     MultipartConfigFactory factory = new MultipartConfigFactory();
     PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull();
     map.from(this.fileSizeThreshold).to(factory::setFileSizeThreshold);
     map.from(this.location).whenHasText().to(factory::setLocation);
     map.from(this.maxRequestSize).to(factory::setMaxRequestSize);
     map.from(this.maxFileSize).to(factory::setMaxFileSize);
     return factory.createMultipartConfig();
}

在生成写入MultipartConfigFactory属性时,PropertyMapper减少了很多if,可读性更强也更加优雅,在日常开发中实用性很强

自定义 action 让其他项目使用

背景

近期使用 issuesblog,突发奇想能不能将 issues blog 生成概览信息同步到项目的README.md中,再加上刚学了Rust,就准备来实现这个action,这里主要流程就是使用github api获取项目issues,再将issues生成概览信息,action 项目 关于代码实现比较简单,主要是记录怎么才能让其他项目使用。

配置 action.yml

action项目需要在根目录下建立一个action.yml,并且这个项目需要是使用者能访问。

name: 'blog-archive'
description: 'issues blog sync README.md Summary'
branding:
  icon: 'activity'
  color: 'white'

inputs:
  api-github-token:
    description: 'github api token'
    required: true
    default: ''
    
  repo:
    description: 'sync github issues repo name'
    required: true
    default: ''

  owner:
    description: 'sync github issues repo owner'
    required: true
    default: ''

  git-user-name:
    description: 'update user name'
    required: true
    default: ''

  git-user-email:
    description: 'update user email'
    required: true
    default: ''

runs:
  using: "composite"

  steps:
    - run: echo "${{ github.action_path }}" >> $GITHUB_PATH
      shell: bash
    - name: Set up Rust
      uses: actions-rs/toolchain@v1
      with:
        toolchain: stable 
    - name: Run blog-archive
      run: |
        cd ${{ github.action_path }}
        cargo run -- ${{ inputs.api-github-token }} ${{ inputs.owner }} ${{ inputs.repo }}
        ls
        pwd
      shell: bash
    - name: Checkout code
      uses: actions/checkout@v2
    - name: sync README.md
      shell: bash
      run: |
        pwd
        ls
        cat ${{ github.action_path }}/output.txt
        cat ${{ github.action_path }}/output.txt > README.md
        git config user.name ${{ inputs.git-user-name }}
        git config user.email ${{ inputs.git-user-email }}
        git add README.md
        git commit -m "Update README.md with issues blog"
        git push
  • 使用其他人的action原理就是把其他的action项目获取到自己项目工作流空间中执行
  • ${{ github.action_path }} 是action项目路径,确定执行文件路径是否正确
  • 其他项目使用只需要引入owner/repo@tag or branch,owner 是用户,repo 是仓库名,@后面可以版本号,也可以是分支,例如刚刚创建的action项目就是zhang-cn/blog-archive@main,在其他项目中action引入使用就可以。

Linux 安装 python

检查服务器python版本

  • 检查命令
# 如果有符合要求的版本就不用再安装了
whereis python

注意:不要随意卸载系统已安装python版本#13

选择python版本

  • 查看版本
  • 下载python版本.tgz
# wget 直接下载,如果网速慢 可以先下载到本地再上传到服务器
wget https://www.python.org/ftp/python/3.9.0/Python-3.9.0.tgz

解压.tgz

# 在下载目录下解压
tar -zxvf Python-3.9.0.tgz

安装编译python源码环境

yum install -y gcc patch libffi-devel python-devel  zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-devel tk-devel gdbm-devel db4-devel libpcap-devel xz-devel

编译安装python

  1. 配置编译目录
# 进入解压目录
cd Python-3.9.0
./configure --prefix=/usr/local/python3.9.0/
  1. 编译
make && make install
  1. 配置环境变量
# python
PATH=/usr/local/python3.9.0/bin:$PATH
# 保存后,刷新配置文件
source /etc/profile

# python 全局配置 python3.9
ln -s /usr/local/python3.9.0/bin/python3 /usr/bin/python3.9
ln -s /usr/local/python3.9.0/bin/pip3 /usr/bin/pip

# 也可以直接指向 python,但是如果/usr/bin/下已经有python,需要先修改,请谨慎操作
mv /usr/bin/python /usr/bin/python.bak
ln -s /usr/local/python3.9.0/bin/python3 /usr/bin/python

# 检查安装
python3.9 -V
python -V

git 动态设置用户信息

前因

在开发公司项目和个人项目都在同一个主机时出现一个很尴尬的问题,git设置了user.nameuser.email,在提交代码时难免出现个人项目使用公司的邮箱提交或者是公司项目用了个人的邮箱去提交,因为git项目本地的设置只作用于这个项目,不会影响到其他项目,因此想了一个解决办法那就是在项目clone到本地的时候根据域名设置项目本地的user.nameuser.email

实现脚本custom-clone.sh

#!/bin/bash

GREEN='\033[0;32m'
NC='\033[0m'
YELLOW='\033[0;33m'

# 检查是否提供了仓库URL
if [ "$#" -ne 1 ]; then
  echo "Usage: custom-clone.sh <repository_url>"
  exit 1
fi

# 获取仓库URL
repository_url="$1"

# 克隆仓库
git clone "$repository_url"

# 进入克隆的仓库目录
repository_name=$(basename "$repository_url" .git)
cd "$repository_name"

git config --local user.name "xxx"

# 获取远程仓库的URL
remote_url=$(git config --get remote.origin.url)

# 提取邮箱域名部分
if [[ $remote_url =~ @(.+)$ ]]; then
  domain="${BASH_REMATCH[1]}"
  # 根据域名设置本地项目的邮箱地址
  case "$domain" in
    *github.com*)
      git config --local user.email "[email protected]"
      echo -e "This domain is ${GREEN}github.com${NC}"
      echo -e "Set up user.name: ${GREEN}$(git config user.name)${NC}"
      echo -e "Set up user.email: ${GREEN}$(git config user.email)${NC}" 
      ;;
    *xx.com*)
      git config --local user.email "[email protected]"
      echo -e "This domain is ${GREEN}xx.com${NC}"
      echo -e "Set up user.name: ${GREEN}$(git config user.name)${NC}"
      echo -e "Set up user.email: ${GREEN}$(git config user.email)${NC}"
      ;;
    *)
      # 设置一个默认邮箱地址,如果没有匹配的域名
      git config --local user.email "[email protected]"
      echo -e "This domain unrecognized ${YELLOW}$domain${NC}"
      echo -e "Set up default user.name: ${GREEN}$(git config user.name)${NC}"
      echo -e "Set up default user.email: ${GREEN}$(git config user.email)${NC}"
      ;;
  esac
fi

执行 chmod +x custom-clone.sh 增加执行权限

配置git 别名

  1. 编辑全局配置文件
git config --global --edit
  1. 设置别名
[alias]
    custom-clone = "!/path/to/custom-clone.sh"
  1. 保存设置

执行命令

git custom-clone url

一切配置好之后只需替换url为实际项目地址就能实现拉取项目时根据配置的域名动态写入用户信息

使用 Optional 优化代码

Optional 优化之前

// 查询用户角色关联表
SysUserRoleRel userRoleRel = userRoleRelMapper.selectOne(new LambdaQueryWrapper<SysUserRoleRel>()
                    .eq(SysUserRoleRel::getUserId, userInfo.getId()));
// 获取用户角色名称
if (Objects.nonNull(userRoleRel)){
      // 查询角色信息
      SysRoleInfo roleInfo = roleInfoMapper.selectById(userRoleRel.getRoleId());
      if (Objects.nonNull(roleInfo)) {
          userResp.setRoleName(roleInfo.getRoleName());
          userResp.setRoleId(roleInfo.getId());
      }
}

Optional 优化之后 🤩

// 查询用户角色关联表
SysUserRoleRel userRoleRel = userRoleRelMapper.selectOne(new LambdaQueryWrapper<SysUserRoleRel>()
                    .eq(SysUserRoleRel::getUserId, userInfo.getId()));
// 获取用户角色名称
Optional.ofNullable(userRoleRel)
                    .map(SysUserRoleRel::getRoleId)
                    .map(roleId -> roleInfoMapper.selectById(roleId))
                    .ifPresent(sysRoleInfo -> {
                        userResp.setRoleName(sysRoleInfo.getRoleName());
                        userResp.setRoleId(sysRoleInfo.getId());
                    });

Note

Optional#mapSysUserRoleRel::getRoleId -> roleInfoMapper.selectById(roleId) 最后获取到了sysRoleInfo,中间如果有空值就不会执行后面的方法。

`Spring Boot` 适配部署 `TongWeb7`

项目适配

修改pom文件,jar -> war

<packaging>war</packaging>

继承配置SpringBootServletInitializer

两种方式选其一

  1. 启动类直接继承
public class DemoApplication extends SpringBootServletInitializer {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

    // 增加configure实现
    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
        return builder.sources(DemoApplication.class);
    }
}
  1. 自定义一个类
public class Demo extends SpringBootServletInitializer {
    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
        return builder.sources(DemoApplication.class);
    }
}

Spring Boot适配TongWeb7只需要更改打包方式,打包成war部署,与Tomcat的war包并无差别

TongWeb 部署war

创建虚拟主机

在创建虚拟主机,只需设置好主机名称即可(每个服务或应用对应一个虚拟主机)
image

创建http通道

  1. 设置http通道名称
  2. 设置监听端口(应用端口)
  3. 设置虚拟主机,选择刚刚创建的虚拟主机
image

这三个地方设置后就一直点下一步完成创建即可

服务部署

  1. 上传本地已经编译好的 war
  2. 完成上传之后点击开始部署
  3. 设置应用名称和应用前缀
  4. 设置虚拟主机选择刚刚创建的虚拟主机
  5. 设置完成之后一直点下一步直到完成
image

服务http路径 http://ip:port/应用前缀port 是创建http通道时设置的监听端口

war服务日志在TongWeb目录下的 logs/server.log

Cloudflare 设置 Origin Rules

设置原因

阿里云服务器80443无法使用,导致配置好cloudflare之后出现404,所以使用Origin Rules转发到指定端口

设置过程

  1. Rules > Origin Rules 增加规则
  2. 匹配字段选择hostname
  3. 匹配规则选择equals
  4. 匹配内容内容填入xx.com
  5. Destination Port 自定义重写
# 设置 Origin Rules 之前
 https://xx.com -> cloudflare -> 原服务器ip:80或443

# 设置 Origin Rules 之后
 https://xx.com -> cloudflare -> 原服务器ip:自定义重写端口

设置示例

image

Rust 跨平台编译

前因

在使用某些工具时,一些适配版本并没有提供对应平台的安装包,例如aarch64等,但因为使用的是Rust所以可以尝试自己编译。

编译配置

  1. 下载跨平台编译支持

    根据自己系统,以及编译平台选择对应的支持,例如我的系统是Mac os x86,想要编译aarch64包,选择Mac os下载aarch64-unknown-linux-gnu-x86_64-darwin.tar.gz

  2. Rust 安装target
    查看 Rust 编译支持target

    rustup target list
    

    根据自己需求选择合适 target (我这里编译到aarch64,选择aarch64-unknown-linux-gnu)

    # Mac os 需要sudo管理员权限才能安装
    sudo rustup target add aarch64-unknown-linux-gnu
    
  3. 配置 .cargo/config

    [target.aarch64-unknown-linux-gnu]
    linker = "/path/aarch64-unknown-linux-gnu/bin/aarch64-unknown-linux-gnu-gcc"
    

    linker替换成刚刚下载的跨平台编译支持包路径,也可以设置环境变量,替换成 linker = "aarch64-unknown-linux-gnu-gcc"

  4. 编译

    cargo build --release --target aarch64-unknown-linux-gnu
    

    target/aarch64-unknown-linux-gnu/release目录下就能看到编译之后的aarch64

参考文档

  1. Cross-compiling
  2. rust 交叉编译

解决 Error creating bean with name 'defaultValidator' 问题

前因

这次是第二次遇到这个问题了,上一次忘记记录导致这次处理了很久才解决。

报错日志

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'defaultValidator' defined in class path resource [org/springframework/boot/autoconfigure/validation/ValidationAutoConfiguration.class]: Invocation of init method failed; nested exception is java.lang.NoClassDefFoundError: Could not initialize class org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1699) ~[spring-beans-5.0.8.RELEASE.jar!/:5.0.8.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:573) ~[spring-beans-5.0.8.RELEASE.jar!/:5.0.8.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:495) ~[spring-beans-5.0.8.RELEASE.jar!/:5.0.8.RELEASE]
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:317) ~[spring-beans-5.0.8.RELEASE.jar!/:5.0.8.RELEASE]

出现原因

本质上因为依赖冲突导致,之所以花费了不少时间解决这个问题,是因为依赖groupId 写错导致。

解决方法

  1. 排除依赖
    排除Spring Boot 中的 org.hibernate.validator
<dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-web</artifactId>
     <version>${version}</version>
     <exclusions>
           <exclusion>
                <!-- 注意 groupId 不要与下面弄混了 -->
               <groupId>org.hibernate.validator</groupId>
               <artifactId>hibernate-validator</artifactId>
           </exclusion>
     </exclusions>
 </dependency>
  1. 引入指定版本
<dependency>
    <!-- 注意 groupId 不要与上面弄混了 -->
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>5.2.4.Final</version>
 </dependency>

yum 报错,无法使用

背景

在中标麒麟Linux master01 4.19.90-17.5.ky10.aarch64服务器上升级安装python #12 之后发现yum无法使用了,报错信息如下

[root@master01 yum-src]# yum
Traceback (most recent call last):
  File "/usr/bin/yum", line 57, in <module>
    from dnf.cli import main
ModuleNotFoundError: No module named 'dnf'

大多数博客都是让修改/usr/bin/yum中第一行,将#!/usr/bin/python3 改为重新安装之后的python环境路径,请先尝试这个方法能不能解决,如不能解决请继续看下去

报错原因

在重新安装python环境的时候执行了rpm -qa|grep python3|xargs rpm -ev --allmatches --nodepswhereis python3 |xargs rm -frvyum依赖的python环境全部删除了,导致yum执行报错

解决步骤

中标麒麟rpm

rpm 包准备

在线下载,也可以先下载到本地再上传到服务器

wget https://update.cs2c.com.cn/NS/V10/V10SP1/os/adv/lic/appstore/x86_64/Packages/python3-3.7.4-8.se.01.ky10.x86_64.rpm
wget https://update.cs2c.com.cn/NS/V10/V10SP1.1/os/adv/lic/base/aarch64/Packages/python3-libdnf-0.37.2-2.ky10.aarch64.rpm
wget https://update.cs2c.com.cn/NS/V10/V10SP1.1/os/adv/lic/base/aarch64/Packages/python3-setuptools-40.4.3-4.ky10.noarch.rpm
wget https://update.cs2c.com.cn/NS/V10/V10SP1.1/os/adv/lic/base/aarch64/Packages/python3-rpm-generators-9-1.ky10.noarch.rpm
wget https://update.cs2c.com.cn/NS/V10/V10SP1.1/os/adv/lic/base/aarch64/Packages/python3-rpm-4.15.1-12.ky10.aarch64.rpm
wget https://update.cs2c.com.cn/NS/V10/V10SP1/os/adv/lic/updates/aarch64/Packages/python3-gpg-1.13.1-6.ky10.ky10.aarch64.rpm

安装依赖

  1. 安装python rpm
rpm -ivh python3-3.7.4-8.se.01.ky10.x86_64.rpm
  1. 拷贝dnfgpg hawkey
    找一台相同环境yum正常的服务器,查询对应包位置拷贝过去
# 查找dnf 、gpg  和 hawkey 位置
find / -name gpg

正常情况下dnf 包在/usr/lib/python3.7/site-packages/下,gpghawkey都在/usr/lib64/python3.7/site-packages/ 路径下,将这三个包拷贝到yum 有问题的服务器/usr/lib/python3.7/site-packages/目录下

依赖包路径可能会有所不同,主要区别于python的版本,例如如果yum使用的是python2.7的话,依赖包路径应该是/usr/lib/python2.7/site-packages/

  1. 安装其他依赖

必须按照顺序安装

rpm -ivh python3-libdnf-0.37.2-2.ky10.aarch64.rpm
rpm -ivh python3-setuptools-40.4.3-4.ky10.noarch.rpm
rpm -ivh python3-rpm-generators-9-1.ky10.noarch.rpm
rpm -ivh python3-rpm-4.15.1-12.ky10.aarch64.rpm
rpm -ivh python3-libcomps-0.1.8-20.ky10.aarch64.rpm
  1. 执行yum 检查是否正常

依赖缺失错误输出

# 缺少 dnf
[root@master01 yum-src]# yum
Traceback (most recent call last):
  File "/usr/bin/yum", line 57, in <module>
    from dnf.cli import main
ModuleNotFoundError: No module named 'dnf'

# 缺少 python3-libdnf
Traceback (most recent call last):
  File "/usr/bin/yum", line 57, in <module>
    from dnf.cli import main
  File "/usr/local/python3/lib/python3.7/site-packages/dnf/__init__.py", line 30, in <module>
    import dnf.base
  File "/usr/local/python3/lib/python3.7/site-packages/dnf/base.py", line 29, in <module>
    import libdnf.transaction
ModuleNotFoundError: No module named 'libdnf'

# 缺少 python3-rpm
[root@master01 yum-src]# yum
Traceback (most recent call last):
  File "/usr/bin/yum", line 57, in <module>
    from dnf.cli import main
  File "/usr/lib/python3.7/site-packages/dnf/__init__.py", line 30, in <module>
    import dnf.base
  File "/usr/lib/python3.7/site-packages/dnf/base.py", line 31, in <module>
    from dnf.comps import CompsQuery
  File "/usr/lib/python3.7/site-packages/dnf/comps.py", line 27, in <module>
    from dnf.exceptions import CompsError
  File "/usr/lib/python3.7/site-packages/dnf/exceptions.py", line 22, in <module>
    import dnf.util
  File "/usr/lib/python3.7/site-packages/dnf/util.py", line 30, in <module>
    import dnf.callback
  File "/usr/lib/python3.7/site-packages/dnf/callback.py", line 22, in <module>
    import dnf.yum.rpmtrans
  File "/usr/lib/python3.7/site-packages/dnf/yum/rpmtrans.py", line 26, in <module>
    import rpm
ModuleNotFoundError: No module named 'rpm'


# 缺少python3-libcomps
[root@master01 yum-src]# yum
Traceback (most recent call last):
  File "/usr/bin/yum", line 57, in <module>
    from dnf.cli import main
  File "/usr/lib/python3.7/site-packages/dnf/__init__.py", line 30, in <module>
    import dnf.base
  File "/usr/lib/python3.7/site-packages/dnf/base.py", line 31, in <module>
    from dnf.comps import CompsQuery
  File "/usr/lib/python3.7/site-packages/dnf/comps.py", line 36, in <module>
    import libcomps
ModuleNotFoundError: No module named 'libcomps'

# 缺少 gpg
[root@master01 yum-src]# yum
Traceback (most recent call last):
  File "/usr/lib/python3.7/site-packages/dnf/crypto.py", line 35, in <module>
    from gpg import Context
ModuleNotFoundError: No module named 'gpg'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/bin/yum", line 57, in <module>
    from dnf.cli import main
  File "/usr/lib/python3.7/site-packages/dnf/__init__.py", line 30, in <module>
    import dnf.base
  File "/usr/lib/python3.7/site-packages/dnf/base.py", line 34, in <module>
    from dnf.db.history import SwdbInterface
  File "/usr/lib/python3.7/site-packages/dnf/db/history.py", line 28, in <module>
    from dnf.yum import misc
  File "/usr/lib/python3.7/site-packages/dnf/yum/misc.py", line 30, in <module>
    import dnf.crypto
  File "/usr/lib/python3.7/site-packages/dnf/crypto.py", line 38, in <module>
    import gpgme
ModuleNotFoundError: No module named 'gpgme'

# 缺少hawkey
[root@master01 yum-src]# yum
Traceback (most recent call last):
  File "/usr/bin/yum", line 57, in <module>
    from dnf.cli import main
  File "/usr/lib/python3.7/site-packages/dnf/__init__.py", line 30, in <module>
    import dnf.base
  File "/usr/lib/python3.7/site-packages/dnf/base.py", line 44, in <module>
    import dnf.conf
  File "/usr/lib/python3.7/site-packages/dnf/conf/__init__.py", line 40, in <module>
    from dnf.conf.config import PRIO_DEFAULT, PRIO_MAINCONFIG, PRIO_AUTOMATICCONFIG
  File "/usr/lib/python3.7/site-packages/dnf/conf/config.py", line 33, in <module>
    import hawkey
ModuleNotFoundError: No module named 'hawkey'

检查/usr/lib/python3.7/site-packages/(不同版本可能有所差异,具体要看yum使用的python版本)下是否存在对应包,如果不存在,请按照上述方式安装相关依赖。

MySQL迁移DM数据库

项目基本情况

现有技术框架SpringBoot、Mybatis-plus、MySQL等,需要将MySQL替换成DM数据库。

达梦数据初始化配置

  1. 设置大小写不敏感,最大程度兼容Mybatis-plus代码(可以减少很多适配工作量和莫名其妙的报错)
  2. DM数据库没有库的概念,只有模式,一般来说默认创建表结构都是关联到以数据库用户名下的表结构中。

数据库连接客户端

  1. Mac
    Mac 没有DM数据库连接的客户端,可以使用idea去连接
  2. WIndows
    可以在官网下载DM客户端,或者这里下载 提取码:dy3a, 客户端使用说明在DM客户端执行SQL执行之后需要手动点击提交数据才会写入数据(手动执行SQL写入数据未生效,这个问题排查了一上午)。

DM数据库表结构初始化

从MySQL中导出所有表结构,转换成DM数据库支持表结构和字段,Windows DM客户端安装之后提供了一个数据迁移工具,表比较多的情况下可以使用它来转换,也可以使用chatgpt来转换。

表结构转换的坑

  1. id自增,MySQL 中id自增语法与DM中不一样
# MySQL 主键自增,使用AUTO_INCREMENT
`id` int(14) PRIMARY KEY NOT NULL AUTO_INCREMENT COMMENT 'id'

# DM 主键自增,使用  IDENTITY (1, 1) 
"id" INT PRIMARY KEY IDENTITY (1, 1) COMMENT 'id',
  1. `` 和 “” 符号问题,在DM数据库中不支持``,“”在达梦数据库中能够保证不会转换成大写,因为DM数据库默认会把字段转换成大写。
  2. longtext不支持,需要转换成DM中的CLOD,但是使用CLOD后在测试中查询CLOD字段会报错,提示Data type mismatch
// 报错代码,排查之后将value 字段改为varchar(2048),测试正常
Param p = new LambdaQueryChainWrapper<>(baseMappingMapper)
             .eq(Param::getValue, 1)
             .one();
  1. 更新时间问题,DM不支持根据数据更新时触发更新时间字段更新,有两种方案处理:
  • 设置触发器,数据更新时触发更新时间更新。

  • Mybatis-plus 字段设置使用@TableField(fill = FieldFill.INSERT_UPDATE)@TableField(fill = FieldFill.INSERT)实现。

  1. double不支持,可以考虑转换成Number类型

项目数据库配置

  1. SpringBoot 配置
  • 配置文件
# 这里使用Druid不是因为迁移DM才使用的
spring:
  datasource:
    url: jdbc:dm://ip:port?zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=utf-8
    username: 用户名
    password: 密码
    platform: DM
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: dm.jdbc.driver.DmDriver
  • pom 依赖
<dependency>
   <groupId>com.dameng</groupId>
   <artifactId>DmJdbcDriver18</artifactId>
   <version>8.1.1.193</version>
</dependency>
  1. MyBatis-plus 配置
    将DbType设置成DbType.DM,如果DbType没有DM枚举,需要升级Mybatis-plus版本
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();

        // 添加分页插件
        PaginationInnerInterceptor pageInterceptor = new PaginationInnerInterceptor();
        // 设置请求的页面大于最大页后操作,true调回到首页,false继续请求。默认false
        pageInterceptor.setOverflow(false);
        // 单页分页条数限制,默认无限制
        pageInterceptor.setMaxLimit(500L);
        // 设置数据库类型
        pageInterceptor.setDbType(DbType.DM);

        interceptor.addInnerInterceptor(pageInterceptor);
        return interceptor;
    }

测试过程中发现的问题

  1. Fail to cast string 报错
# 报错SQL
# age 是 int 类型,但是传入不能转成int类型的字符串会报错,提示Fail to cast string
select * from tb where age = "十八"
  1. 自增列插入报错
# 打开自增列插入
SET IDENTITY_INSERT table_name ON

# 插入sql

# 关闭自增列插入
SET IDENTITY_INSERT table_name OFF

Mac 命令行

# 查看服务ip 端口通信是否正常,类似于telnet
nc -vz -w 2 ip port

软考备考

计算机基础

  1. 页式存储计算
    • 给出页大小和逻辑地址,计算出物理地址
      因为逻辑地址=页号+页内地址,物理地址=块号+页内地址,页大小二进制位数=页内地址位数,将二进制逻辑地址去页内地址位数就能得到页号,通过页号找到块号,得到物理地址。
      也可以通过计算方式
      若给定一个逻辑地址空间中的地址为A,页面大小为L,则
      页号P = INT[A/L]
      页内地址d = [A] MOD L
  2. 文件索引计算
    文件索引具有直接地址、1~n级索引的方式,通常给出块大小和索引地址大小,计算存储位置。
    索引表大小 = 块大小/索引地址大小
    索引表开始位置=上一个位置+1
    索引表结束位置=索引表大小+索引表开始位置-1
    存储文件最大值=所有地址项数量x块大小

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.