NodeJs
语法基本使用初始化项目 1npm init -y 创建文件 12# 新建src文件夹# 在src里新建index.html和index.css 安装jQuery 123# -S 的意思是 jquery安装好了,记录在package.json的 dependencies里# -S 等于 --save的简写npm i jquery -S index.html 12345678910111213141516171819202122<!DOCTYPE html><html lang="en"> <head> <meta charset="UTF-8"> <title>隔行变色</title> <script src="./index.js"></script> </head> <body> <ul> <li>这是第 1 个li</li> <li>这是第 2 个li</li> <li>这是第 3 个li</li> <li>这是第 4 个li</li> <li>这是第 5 个li</li> <li>这是第 6 个li</li> <li>这是第 7 个li</li> <li>这是第 8 个li</li> <li>这是第 9 个li</li> </ul> </body></html> index.js 1234567// 使用ES6的导入语法,导入jQueryimport $ from 'jquery'$(function(){ $("li:odd").css("background-color","red") $("li:even").css("background-color","pink")}) 运行index.html,就会报错,这时需要安装webpack 安装webpack ⛔ 安装webpack遇到的版本问题 要安装最新版本或特定版本,请运行以下命令之一: 123npm install --save-dev webpacknpm install --save-dev webpack@<version> 如果你使用 webpack 4+ 版本,你还需要安装 CLI。 1npm install --save-dev webpack-cli 1234567# 这个时候运行就会出问题# 需要安装webpack# @是指定版本# -D是指把版本信息记录到 devDepencies# devDepencies开发阶段会用到# -D 等于 --save-dev的简写npm insatll [email protected] [email protected] -D 创建webpack的配置文件webpack.config.js 123456789# 项目跟目录创建webpack配置文件,webpack.config.js# 使用Node.js的导出语法,向外导出一个webpack的配置对象modle.exports={ // 代表webpack的运行的模式, // 可选的值有两个 development 和 production mode : "development"} 修改package.json 1234# 在package.json的scripts节点下,新增dev脚本"scripts":{ "dev":"webpack"} 运行 12# 就会多了个dist的文件夹npm run dev 修改index.html的引入js路径 12# 修改index.html文件夹的scr导入路劲scr="./index.js" 改成 src="./dist/main.js" entry和output123456789101112const path = require("path")module.exports = { // 指定要最先处理的文件 entry:path.join(__dirname,"./src/index1.js"), // 指定生成的文件放在哪里 output:{ // 生成文件的目录 path:path.join(__dirname,"./dist2"), // 生成的文件名 filename:"bundle.js" }} 修改代码实时生效插件1npm install webpack-dev-server --save-dev 修改package.json 123"scripts": { "dev": "webpack serve"} 1npm i --save-dev html-webpack-plugin 修改webpack.config.json 12345678910111213const htmlplugin = require("html-webpack-plugin")plugin = new htmlplugin({ // 指定要服务的页面 template:"./src/index.html", // 复制到哪里去 filename:"./index.html"})module.exports = { mode:"development", plugins:[plugin]} 配置devServer12345678910module.exports = { mode:"development", plugins:[plugin], devServer:{ // 自动打开浏览器 open:true, // 端口 port:10086 }} loaderwebpack默认只处理js格式的文件,比如要处理CSS,需要安装 12npm install --save-dev css-loadernpm install --save-dev style-loader 在src下新建css文件夹,在css文件夹下新建一个index.css 在index.js导入css文件 12// 导入样式,在webpack中,所有的文件都可以用ES6语法导入import "./css/index.css" 配置webpack.config.js 12345678910111213// 先找到css-loader处理,再给style-loader处理module.exports = { mode:"development", module:{ // 所有第三方文件模块的匹配规则 rules:[ // 文件后缀的匹配规则 { test:/\.css$/,use:["style-loader","css-loader"] } ] }} less-loader在上面的css文件夹下,创建个index.less文件 12345678910// index.lesshtml,body,ul{ padding: 0; margin: 0; li{ line-height: 30px; padding-left: 20px; font-size: 12px; }} 12npm install less -Dnpm install less less-loader --save-dev 配置webpack.config.js 1234567891011121314module.exports = { mode:"development", module:{ // 所有第三方文件模块的匹配规则 rules:[ // 文件后缀的匹配规则 // 处理css {test:/\.css$/,use:["style-loader","css-loader"]}, // 处理less {test: /\.less$/, use: ["style-loader", "css-loader", "less-loader",], }, ] }} 图片loader没学 babel-loader没学 build打包优化自动清理dist目录下的旧文件1npm install --save-dev clean-webpack-plugin 12345678const { CleanWebpackPlugin } = require('clean-webpack-plugin');module.exports = { plugins:[plugin,new CleanWebpackPlugin()], output:{ path:path.join(__dirname,"./dist") }} Source Map一个信息文件,存储这位置信息,存储压缩混淆后的代码,所对应的转换钱的位置 123456module.exports = { mode:"development", // 生产的时候要关闭,也可以 设置 nosources-source-map // nosources-source-map 显示行号,不显示源码 devtool:"eval-source-map"} @的原理标识src源代码目录,从外往里找, 就可以不用使用../从里往外找 告诉webpack,@的目录 1234567module.exports = { resolve:{ alias:{ "@":path.join(__dirname,"./src/") } }} Eslint12345678910{ // 是否使用分号结尾 "semi": true, // 是否使用单引号 "singleQuote": false, // 最后一句话逗号结尾 "trailingComma": "none"} 在Vue项目的根目录中创建vue.config.js文件 12345678910# 在脚手架生成的代码添加module.exports = defineConfig({ # 要添加的代码 lintOnSave:false})# 或者module.exports = { lintOnSave:false} 入门应用1234567891011121314151617var http = require('http');http.createServer(function (request, response) { // 发送 HTTP 头部 // HTTP 状态值: 200 : OK // 内容类型: text/plain response.writeHead(200, {'Content-Type': 'text/plain'}); // 发送响应数据 "Hello World" response.end('Hello World\n');}).listen(8888);// 终端打印如下信息console.log('Server running at http://127.0.0.1:8888/');// 运行node server.js Npm升级 1npm i -g npm to update Node.jsmac安装 1brew install nodejs npm更换版本 12# npm更换npm install [email protected] -g node.js更换版本 12345678910111213141516171819202122# node更换sudo npm install n -g# 安装指定版本号的nodejs,记得使用sudosudo n 14.16.0# 切换nodejs版本号n# 输入n之后,打印的数据ο node/14.16.0------------------------------------------# 使用nvm更换版本brew install nvm# 查看远程版本nvm ls-remote# 安装制定版本号nvm install v15.3.2# 已经安装的版本号nvm ls# 切换已经安装的版本号nvm use 4.2 依赖管理 123456789101112131415161718192021# 安装但不写入package.json;npm install xxx# 安装并写入package.json的"dependencies"中npm install xxx –S# 安装并写入package.json的"devDependencies"中npm install xxx –D# 全局安装npm install xxx -g# 安装指定版本npm install [email protected]# 更新包npm install -g npm-check-updates# 检查可更新的模块ncu# 来更新package.json的依赖包到最新版本ncu -u node.js升级 12345678910111213# 更新npmnpm install -g npm# 清空npm缓存npm cache clean -f# 安装n模块npm install -g n# 升级node.js到最新稳定版n stable# 有时候需要sudo权限,或者安装好了之后要开启一个新的shell才能用到新的版本 https://www.bilibili.com/video/BV1vE411871g?p=120 安装源 依赖升级 123npm install -g npm-upgrade # 先全局安装 npm-upgradenpm-upgrade # 当前项目下的包全都更新npm-upgrade <package> # 当前项目下的指定包更新 ES6 & JS字符串转数字 遍历2 排序 排序 join方法 遍历 1JavaScript for...in .. foreach 1row.typeID.split(",").forEach(id=>{this.gameTypes.push(parseInt(id))}) NodJs项目部署到Vercel1.创建node项目 1npm init 2.安装依赖,package.json 123456{ "dependencies": { "@vercel/node": "^2.15.3", "express": "^4.18.2" }} 3.创建vercel.json 123456789101112131415{ "version": 2, "builds": [ { "src": "app.js", "use": "@vercel/node" } ], "routes": [ { "src": "/(.*)", "dest": "app.js" } ]} 4.创建app.js 1234567891011const express = require('express')const app = express()const port = 3000app.get('/', (req, res) => { res.send('Hello World!')})app.listen(port, () => { console.log(`Example app listening on port ${port}`)}) 5.像平常部署别的项目一样,部署这个项目就可以,部署好之后,就能看到首页的Hello World!
SpringBoot配置Gmail
申请应用程序验证码 配置二步验证 要配置二步验证,才能看到应用程序的选项 最后就能获取到应用程序验证码 引入代码 1234<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-mail</artifactId></dependency> application.properties文件配置 12345678910111213spring.mail.host=smtp.gmail.com# 邮件服务器端口号spring.mail.port=587# 邮件发送方的电子邮件地址spring.mail.username=你的Gmail邮箱账号# 邮件发送方的密码或应用程序专用密码一定要开启了两步验证spring.mail.password=应用程序专用密码# 启用TLS加密spring.mail.properties.mail.smtp.starttls.enable=true# 验证邮件服务器的身份spring.mail.properties.mail.smtp.auth=true# 邮件传输协议spring.mail.properties.mail.transport.protocol=smtp 配置的代码 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108@Servicepublic class EmailUtil implements EmailService{ private final Logger logger = LoggerFactory.getLogger(this.getClass()); //Spring Boot 提供了一个发送邮件的简单抽象,使用的是下面这个接口,这里直接注入即可使用 @Autowired private JavaMailSender mailSender; // 配置文件中我的谷歌邮箱 @Value("${spring.mail.username}") private String from; /** * 简单文本邮件 * @param to 收件人 * @param subject 主题 * @param content 内容 */ @Override public void sendSimpleMail(String to, String subject, String content) { //创建SimpleMailMessage对象 SimpleMailMessage message = new SimpleMailMessage(); //邮件发送人 message.setFrom(from); //邮件接收人 message.setTo(to); //邮件主题 message.setSubject(subject); //邮件内容 message.setText(content); //发送邮件 mailSender.send(message); } /** * html邮件 * @param to 收件人,多个时参数形式 :"[email protected],[email protected],[email protected]" * @param subject 主题 * @param content 内容 */ @Override public void sendHtmlMail(String to, String subject, String content) { //获取MimeMessage对象 MimeMessage message = mailSender.createMimeMessage(); MimeMessageHelper messageHelper; try { messageHelper = new MimeMessageHelper(message, true); //邮件发送人 messageHelper.setFrom(from); //邮件接收人,设置多个收件人地址 InternetAddress[] internetAddressTo = InternetAddress.parse(to); messageHelper.setTo(internetAddressTo); //messageHelper.setTo(to); //邮件主题 message.setSubject(subject); //邮件内容,html格式 messageHelper.setText(content, true); //发送 mailSender.send(message); //日志信息 logger.info("邮件已经发送。"); } catch (Exception e) { logger.error("发送邮件时发生异常!", e); } } /** * 带附件的邮件 * @param to 收件人 * @param subject 主题 * @param content 内容 * @param filePath 附件 */ @Override public void sendAttachmentsMail(String to, String subject, String content, String filePath) { MimeMessage message = mailSender.createMimeMessage(); try { MimeMessageHelper helper = new MimeMessageHelper(message, true); helper.setFrom(from); helper.setTo(to); helper.setSubject(subject); helper.setText(content, true); FileSystemResource file = new FileSystemResource(new File(filePath)); String fileName = filePath.substring(filePath.lastIndexOf(File.separator)); helper.addAttachment(fileName, file); mailSender.send(message); //日志信息 logger.info("邮件已经发送。"); } catch (Exception e) { logger.error("发送邮件时发生异常!", e); } } /** * 验证邮箱格式 * @param email * @return */ public boolean isEmail(String email) { if (email == null || email.length() < 1 || email.length() > 256) { return false; } Pattern pattern = Pattern.compile("^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*$"); return pattern.matcher(email).matches(); }} 1234567891011121314151617181920212223242526272829public interface EmailService { /** * 发送文本邮件 * * @param to 收件人 * @param subject 主题 * @param content 内容 */ void sendSimpleMail(String to, String subject, String content); /** * 发送HTML邮件 * * @param to 收件人 * @param subject 主题 * @param content 内容 */ public void sendHtmlMail(String to, String subject, String content); /** * 发送带附件的邮件 * * @param to 收件人 * @param subject 主题 * @param content 内容 * @param filePath 附件 */ public void sendAttachmentsMail(String to, String subject, String content, String filePath);} 123456789101112131415161718192021222324@Servicepublic class CodeUtil { @Autowired private StringRedisTemplate redisTemplate; public String generateVerificationCode() { // 生成6位随机数字验证码 return String.valueOf((int) ((Math.random() * 9 + 1) * 100000)); } // 验证验证码是否正确 public boolean verifyCode(String userId, String code,String key) { key = key + userId; String storedCode = redisTemplate.opsForValue().get(key); return code.equals(storedCode); } //删除redis中验证码 public void deleteCode(String userId,String key) { key = key + userId; redisTemplate.delete(key); }} 1234567//写在需要发送验证码的地方//存储时间 private static final int EXPIRATION_TIME_IN_MINUTES = 3; //键名 private static final String KEY_PREFIX =="xxx"; key=KEY_PREFIX+"123456"redisTemplate.opsForValue().set(key, 随机数字验证码, EXPIRATION_TIME_IN_MINUTES, TimeUnit.MINUTES);
Vue后台系统
项目由 Vue3 + Pina + JavaScript + Ant Design Vue 创建项目12345# 直接创建npm create vite@latest my-vue-app -- --template vue# 如果要创建ts或者自定义配置的项目就用这个npm create vite 引入Ant Design Vue1npm i --save [email protected] mian.js 删掉自带的style.css文件 12345678import {createApp} from 'vue'import Antd from 'ant-design-vue';import 'ant-design-vue/dist/reset.css';import App from './App.vue'const app = createApp(App);app.use(Antd)app.mount('#app'); 安装router1npm install vue-router@4 创建src/router/index.js文件 12345678910111213141516171819202122232425262728293031323334353637383940414243444546import { createWebHistory, createRouter } from 'vue-router'/** * Note: 路由配置项 * * hidden: true // 当设置 true 的时候该路由不会再侧边栏出现 如401,login等页面,或者如一些编辑页面/edit/1 * alwaysShow: true // 当你一个路由下面的 children 声明的路由大于1个时,自动会变成嵌套的模式--如组件页面 * // 只有一个时,会将那个子路由当做根路由显示在侧边栏--如引导页面 * // 若你想不管路由下面的 children 声明的个数都显示你的根路由 * // 你可以设置 alwaysShow: true,这样它就会忽略之前定义的规则,一直显示根路由 * redirect: noRedirect // 当设置 noRedirect 的时候该路由在面包屑导航中不可被点击 * name:'router-name' // 设定路由的名字,一定要填写不然使用<keep-alive>时会出现各种问题 * query: '{"id": 1, "name": "ry"}' // 访问路由的默认传递参数 * roles: ['admin', 'common'] // 访问路由的角色权限 * permissions: ['a:a:a', 'b:b:b'] // 访问路由的菜单权限 * meta : { noCache: true // 如果设置为true,则不会被 <keep-alive> 缓存(默认 false) title: 'title' // 设置该路由在侧边栏和面包屑中展示的名字 icon: 'svg-name' // 设置该路由的图标,对应路径src/assets/icons/svg breadcrumb: false // 如果设置为false,则不会在breadcrumb面包屑中显示 activeMenu: '/system/user' // 当路由设置了该属性,则会高亮相对应的侧边栏。 } */// 公共路由export const constantRoutes = [ { path: '/login', component: () => import('@/views/login'), hidden: true },]const router = createRouter({ history: createWebHistory(), routes: constantRoutes, scrollBehavior(to, from, savedPosition) { if (savedPosition) { return savedPosition } else { return { top: 0 } } },});export default router; 配置开发环境编辑vite.config.js 123456789101112131415161718192021import { defineConfig, loadEnv } from 'vite'import path from 'path'import vue from '@vitejs/plugin-vue'// https://vitejs.dev/config/export default defineConfig(({ mode, command }) => { return { plugins: [vue()], resolve: { // https://cn.vitejs.dev/config/#resolve-alias alias: { // 设置路径 '~': path.resolve(__dirname, './'), // 设置别名 '@': path.resolve(__dirname, './src') }, // https://cn.vitejs.dev/config/#resolve-extensions extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.vue'] } }}) 项目根目录创建环境配置文件 .env.development .env.prod 12345678# 页面标题VITE_APP_TITLE = 若依管理系统# 开发环境配置VITE_APP_ENV = 'development'# 若依管理系统/开发环境VITE_APP_BASE_API = '/dev-api' 安装sass12345npm install -D sass# 直接使用就可以<style lang="scss" scoped></style> 全局样式创建src/style/index.scss文件 123456789101112131415161718@import './demo.scss';html { height: 100vh; box-sizing: border-box;}body { height: 100vh; margin: 0; //-moz-osx-font-smoothing: grayscale; //-webkit-font-smoothing: antialiased; //text-rendering: optimizeLegibility; //font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, Arial, sans-serif;}#app { height: 100vh;} 创建src/style/demo.scss文件 1// 这个文件是用来写css的,前面导入的这个文件,所以后面只需要写就行了 导入scss,编辑main.js 1import './style/index.scss' Ant Design Vue Icon的使用123456789101112131415<template> <a-form class="login-from"> <a-form-item size> <a-input placeholder="请输入用户名" size="large"> <template #prefix> <UserOutlined/> </template> </a-input> </a-form-item> </a-form></template><script setup> import {UserOutlined, LockOutlined} from '@ant-design/icons-vue'</script> 安装Axios1npm install axios 创建 src/utils/request.js 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556import axios from 'axios'axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8'// 创建axios实例const service = axios.create({ // axios中请求配置有baseURL选项,表示请求URL公共部分 baseURL: import.meta.env.VITE_APP_BASE_API, // 超时 timeout: 10000})// request拦截器service.interceptors.request.use(config => { return config}, error => { console.log(error) Promise.reject(error)})// 响应拦截器service.interceptors.response.use(res => { // 未设置状态码则默认成功状态 const code = res.data.code || 200; if (code === 401) { return Promise.reject('无效的会话,或者会话已过期,请重新登录。') } else if (code === 500) { ElMessage({ message: msg, type: 'error' }) return Promise.reject(new Error(msg)) } else if (code === 601) { ElMessage({ message: msg, type: 'warning' }) return Promise.reject(new Error(msg)) } else if (code !== 200) { ElNotification.error({ title: msg }) return Promise.reject('error') } else { return Promise.resolve(res.data) } }, error => { console.log('err' + error) let { message } = error; if (message == "Network Error") { message = "后端接口连接异常"; } else if (message.includes("timeout")) { message = "系统接口请求超时"; } else if (message.includes("Request failed with status code")) { message = "系统接口" + message.substr(message.length - 3) + "异常"; } ElMessage({ message: message, type: 'error', duration: 5 * 1000 }) return Promise.reject(error) })export default service main.js 1import router from './router'
Mac
快捷键 描述 命令 一个应用多个窗口 切换 command+` 录屏幕 shift+command+5 截图 shift+command+4 重装系统 先一直按住不要松手:Common+R,再按开机键;非苹果键盘,按住微软键+R 上一级目录 command+↑ 网站链接 一招解决 Chrome / Edge 浏览器卡顿变慢视频掉帧问题 - 让浏览器重回丝般流畅 AltTab iphone强制重启 浏览器返回手势 放歌有噪音通过【活动监视器】程序终止【coreaudiod】进程: 聚焦搜索】中输入【activity monitor】 在窗口右上角的搜索栏里输入【coreaudiod】 选择【coreaudiod】进程后,点击窗口上方工具栏中的【停止按钮】(按钮图标为X) 只有mac不能访问github 打开https://github.com.ipaddress.com/ 打开https://fastly.net.ipaddress.com/github.global.ssl.fastly.net#ipinfo sudo vim /etc/hosts 1234# 这个ip从第一步获取到的140.82.112.4 github.com# 这个ip从第二步获取到的199.232.69.194 github.global.ssl.fastly.net 刷新:sudo killall -HUP mDNSResponder;say DNS cache has been flushed 启动台有问号的图标,点击没反应123# 执行了之后,自己新建的文件夹会重置defaults write com.apple.dock ResetLaunchPad -bool TRUEkillall Dock Mac OS X 访问 Windows共享文件夹 在Mac中,点击 Finder菜单的“前往” > “前往服务器”。在弹出的连接服务器对话框中输入「smb://Windows主机的IP地址」,点击“连接”。 一般需要输入Windows对应用户的名称和密码,然后弹出如下窗口,选择对应的文件夹,点击“好”即可进行远程访问 只使用搜狗输入法系统偏好设置 >> 键盘 >> 快捷键 >> 反选切换输入法的快捷键 网络踪迹1traceroute ap-southeast-1.signin.aws.amazon.com 安装mysql客户端1234567brew install mysql-client# 安装目录在/opt/homebrew/Cellar/mysql-client/8.0.33_1 # mysqldump的目录/opt/homebrew/opt/mysql-client/bin/mysqldump Iterm2Iterm2多窗口同时输入命令只需要输入快捷键 ⌘(command) + ⇧(shift) + i 调出复制过的文本历史快捷键:“shift+cmd+h” 按键回放回放一段时间内的你敲过的所有字符。快捷键:“cmd+alt+b”,如图会弹出一个进度条,按左右键就可以实现按键回放了。 CheatSheet1234brew install cheatsheet# 使用随便在一个软件中 长按`command` Navicat破解gitee脚本 mac安装 protobuf123brew install protobufprotoc --version/opt/homebrew/share/emacs/site-lisp/protobuf 视频格式转换12345brew install ffmpeg# 使用这个命令ffmpeg -i input.mov -c copy output.mp4 # 不要用这个命令,网上说是速度很慢ffmpeg -i input.mov output.mp4
虚拟机
VirtualBox增强功能Centos8123456789# 需要安装一定的依赖,例如:make gcc perlsudo yum install gcc perl make tar bzip2 elfutils-libelf-devel#同时安装的kernel-devel版本要和内核版本一致,安装对应版本sudo yum install -y "kernel-devel-uname-r == $(uname -r)"# 或者通过DNF安装所有:dnf install tar bzip2 kernel-devel-$(uname -r) kernel-headers perl gcc make elfutils-libelf-devel
Tron
波场官方trident-java文档 m1 mac Android protobuf 遇到的问题 tron中文文档 trc20离线签名的demo,有trxdent-java,就不需要这个了,使用http的方式可以看看 trc20离线签名的demo,有trxdent-java,就不需要这个了,使用http的方式可以看看,另外一个demo 要继续学习tron可以看看 打包依赖 下载源文件trident-java 这里选择main分支 进入trident-java文件夹,可以看到有build.gradle,如果是mac系统,修改一下依赖 1234567891011121314protoc { // 原来的依赖 artifact = 'com.google.protobuf:protoc:3.12.0' // 修改之后的依赖 artifact = 'com.google.protobuf:protoc:3.12.0:osx-x86_64' } plugins { grpc { // 原来的依赖 artifact = 'io.grpc:protoc-gen-grpc-java:1.31.0' // 修改之后的依赖 artifact = 'io.grpc:protoc-gen-grpc-java:1.31.0:osx-x86_64' } } IDEA打包 打包之后,在每个子模块的build/libs/xxx-jar 下面的操作就可以跟着开发文档了,创建项目 pom.xml 123456789101112131415161718192021222324252627<dependency> <groupId>org.tron.trident</groupId> <artifactId>abi</artifactId> <version>0.8.0</version> <scope>system</scope> <systemPath>${project.basedir}/src/main/resources/jar/abi-0.8.0.jar</systemPath></dependency><dependency> <groupId>org.tron.trident</groupId> <artifactId>utils</artifactId> <version>0.8.0</version> <scope>system</scope> <systemPath>${project.basedir}/src/main/resources/jar/utils-0.8.0.jar</systemPath></dependency><dependency> <groupId>org.tron.trident</groupId> <artifactId>core</artifactId> <version>0.8.0</version> <scope>system</scope> <systemPath>${project.basedir}/src/main/resources/jar/core-0.8.0.jar</systemPath></dependency><dependency> <groupId>io.grpc</groupId> <artifactId>grpc-all</artifactId> <version>1.48.1</version></dependency> 查询余额的代码 123456789101112131415public static String privateKey = "私钥"; public static String apiKey = "apiKey";//波场申请 @Test public void getCount() { //生成密钥对 KeyPair keyPair = new KeyPair(privateKey); //地址转换 System.out.println(keyPair.toHexAddress()); ApiWrapper wrapper = ApiWrapper.ofMainnet(privateKey,apiKey); //账号查询 Account account = wrapper.getAccount("账户地址"); //查询余额 System.out.println(account.getBalance()); System.out.println(account.getCreateTime()); } 转账示例 123456789101112131415161718192021public static String transferTrc(String fromAddress, String toAddress, String amount, String contractAddress, String privateKey) { ApiWrapper wrapper = ApiWrapper.ofNile(privateKey); String ret = ""; try { //根据合约地址获取封装好的合约 Contract contract = wrapper.getContract(contractAddress); //创建一个TRC20合约对象 Trc20Contract token = new Trc20Contract(contract, fromAddress, wrapper); //获取想要转移的数量 BigInteger sunAmountValue = Convert.toSun(amount, Convert.Unit.TRX).toBigInteger(); //设置最大手续费 long maxTrx = Convert.toSun("17", Convert.Unit.TRX).longValue(); ret = token.transfer(toAddress, sunAmountValue.longValue(), 0, "", maxTrx); System.out.println("哈希:" + ret); } catch (Exception e) { System.out.println("转移失败:" + e.getMessage().toString()); } finally { wrapper.close(); } return ret;}
Netty
Server 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162// 把 NettyServer 的创建交给 Spring 管理@Componentpublic class NettyServer { private Logger logger = LoggerFactory.getLogger(getClass()); @Value("${netty.port}") private Integer port; @Resource private NettyServerHandlerInitializer nettyServerHandlerInitializer; // boss 线程组,用于服务端接受客户端的连接 private EventLoopGroup bossGroup = new NioEventLoopGroup(); // worker 线程组,用于服务端接受客户端的数据读写 private EventLoopGroup workerGroup = new NioEventLoopGroup(); // Netty Server Channel private Channel channel; // 启动 Netty Server @PostConstruct public void start() throws InterruptedException { // 创建 ServerBootstrap 对象,用于 Netty Server 启动 ServerBootstrap bootstrap = new ServerBootstrap(); // 设置 ServerBootstrap 的各种属性 // 设置两个 EventLoopGroup 对象 bootstrap.group(bossGroup, workerGroup) // 指定 Channel 为服务端 NioServerSocketChannel .channel(NioServerSocketChannel.class) // 设置 Netty Server 的端口 .localAddress(new InetSocketAddress(port)) // 服务端 accept 队列的大小 .option(ChannelOption.SO_BACKLOG, 1024) // TCP Keepalive 机制,实现 TCP 层级的心跳保活功能 .childOption(ChannelOption.SO_KEEPALIVE, true) // 允许较小的数据包的发送,降低延迟 .childOption(ChannelOption.TCP_NODELAY, true) // 处理器 .childHandler(nettyServerHandlerInitializer); // 绑定端口,并同步等待成功,即启动服务端 ChannelFuture future = bootstrap.bind().sync(); if (future.isSuccess()) { channel = future.channel(); logger.info("[start][Netty Server 启动在 {} 端口]", port); } } // 关闭 Netty Server @PreDestroy public void shutdown() { // 关闭 Netty Server if (channel != null) { channel.close(); } // <3.2> 优雅关闭两个 EventLoopGroup 对象 bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); }} NettyServerHandlerInitializer 12345678910111213141516171819202122232425262728293031@Componentpublic class NettyServerHandlerInitializer extends ChannelInitializer<Channel> { /** * 心跳超时时间 */ private static final Integer READ_TIMEOUT_SECONDS = 3 * 60; @Resource private NettyServerHandler nettyServerHandler; @Override protected void initChannel(Channel ch) { // 获得 Channel 对应的 ChannelPipeline ChannelPipeline channelPipeline = ch.pipeline(); // 添加一堆 NettyServerHandler 到 ChannelPipeline 中 channelPipeline // 空闲检测 .addLast(new ReadTimeoutHandler(READ_TIMEOUT_SECONDS, TimeUnit.SECONDS)) // 编码器 .addLast(new InvocationEncoder()) // 解码器 .addLast(new InvocationDecoder()) // 消息分发器 .addLast(messageDispatcher) // 服务端处理器 .addLast(nettyServerHandler) ; }} 模拟启动Netty123ChannelFuture future = bootstrap.bind(port).sync();System.out.println("Netty 代理服务器启动,监听端口:" + port);future.channel().closeFuture().sync(); // 阻塞直到关闭 1234567891011121314151617181920212223242526272829303132333435363738394041424344public class NettyTest { public static void main(String[] args) throws InterruptedException { RiceCooker cooker = new RiceCooker(); // 模拟 bootstrap.bind().sync() cooker.start(); // 启动(阻塞直到准备好) // 模拟 future.channel().closeFuture().sync() new Thread(() -> { try { Thread.sleep(5000); // 模拟5秒后煮好饭 cooker.close(); // 自动关闭 } catch (InterruptedException ignored) {} }).start(); cooker.waitUntilClosed(); // 阻塞,直到关闭 }}class RiceCooker { boolean isStarted = false; boolean isClosed = false; // 启动电饭煲 public void start() throws InterruptedException { System.out.println("启动电饭煲..."); Thread.sleep(1000); // 模拟准备时间 isStarted = true; System.out.println("电饭煲开始煮饭!"); } // 等待“煮饭完成” public void waitUntilClosed() throws InterruptedException { while (!isClosed) { Thread.sleep(500); // 等待状态变化 } System.out.println("煮饭完成,电饭煲关闭。"); } public void close() { isClosed = true; }} 粘包模拟粘包问题123456789101112131415161718192021222324252627282930public class NettyServer { public static void main(String[] args) throws Exception { EventLoopGroup boss = new NioEventLoopGroup(); EventLoopGroup worker = new NioEventLoopGroup(); ServerBootstrap b = new ServerBootstrap(); b.group(boss, worker) .channel(NioServerSocketChannel.class) .childHandler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) { ChannelPipeline pipeline = ch.pipeline(); // 👇 没有拆包处理器,粘包将出现! pipeline.addLast(new ServerHandler()); } }); b.bind(8080).sync(); System.out.println("Server started on port 8080"); }}class ServerHandler extends SimpleChannelInboundHandler<ByteBuf> { @Override protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) { String received = msg.toString(CharsetUtil.UTF_8); System.out.println("数据长度:" + msg.readableBytes()); System.out.println("原始数据: [" + received + "]"); }} 1234567891011121314151617181920212223242526public class NettyClient { public static void main(String[] args) throws Exception { EventLoopGroup group = new NioEventLoopGroup(); Bootstrap bootstrap = new Bootstrap(); bootstrap.group(group) .channel(NioSocketChannel.class) .handler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) { ch.pipeline().addLast(new ChannelInboundHandlerAdapter() { @Override public void channelActive(ChannelHandlerContext ctx) { // 连续发多条消息,粘包一定会出现 for (int i = 0; i < 5; i++) { String msg = "msg" + i + "\n"; ctx.writeAndFlush(Unpooled.copiedBuffer(msg, CharsetUtil.UTF_8)); } } }); } }); bootstrap.connect("127.0.0.1", 8080).sync(); }} 服务端打印 12345678Server started on port 8080数据长度:25原始数据: [msg0msg1msg2msg3msg4] 这里错误情况,正常情况应该是 1234原始数据:[msg0]原始数据:[msg1]原始数据:[msg2]..... 方案1:换行符或自定义分隔符在服务端配置 1234// 按 \n 拆new LineBasedFrameDecoder(1024); // 按 "--" 拆new DelimiterBasedFrameDecoder(1024, Unpooled.wrappedBuffer("--".getBytes())); 1234567891011121314151617181920212223242526272829303132public class NettyServer { public static void main(String[] args) throws Exception { EventLoopGroup boss = new NioEventLoopGroup(); EventLoopGroup worker = new NioEventLoopGroup(); ServerBootstrap b = new ServerBootstrap(); b.group(boss, worker) .channel(NioServerSocketChannel.class) .childHandler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) { ChannelPipeline pipeline = ch.pipeline(); pipeline.addLast(new LineBasedFrameDecoder(1024));// pipeline.addLast(new DelimiterBasedFrameDecoder(1024, Unpooled.wrappedBuffer("--".getBytes()))); // 👇 没有拆包处理器,粘包将出现! pipeline.addLast(new ServerHandler()); } }); b.bind(8080).sync(); System.out.println("Server started on port 8080"); }}class ServerHandler extends SimpleChannelInboundHandler<ByteBuf> { @Override protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) { String received = msg.toString(CharsetUtil.UTF_8); System.out.println("数据长度:" + msg.readableBytes()); System.out.println("原始数据: [" + received + "]"); }} 控制台打印,这是正常的 1234567891011Server started on port 8080数据长度:4原始数据: [msg0]数据长度:4原始数据: [msg1]数据长度:4原始数据: [msg2]数据长度:4原始数据: [msg3]数据长度:4原始数据: [msg4] 方案2:固定长度12// 客户端每条消息必须正好 8 字节,否则解析错。pipeline.addLast(new FixedLengthFrameDecoder(8)); 方案三:LengthFieldBasedFrameDecoder
DataGrip
查看ddl和复制为insert语句 显示设置数据库颜色 显示树状结构 显示表的commnet 显示数据库DDL最后一次更新的时间 同步/比较两个表的数据结构用command 选中 两个想要比较的表,然后在其中一个表,选择 只显示不一样的字段 显示全部字段,绿色表示不一样 也可以比较两个库,还是刚才的方法,选中两个库,再比较 相当于Navicat的这个功能 复制功能标记1,选中表,Command + c 就是复制的表名 标记2,选中库,Command + c 就是复制的库名 右边的选项,让你复制出的SQL格式是什么样的,比如复制出insert的sql,或者update的sql,或者导出xml 或者,多条记录复制出一条sql语句,简单使用可以尝试 build-in: sql inserts sql updates scripted: sql-insert-multirow Sql-insert-statements 导出的功能使用mysqldump,导出整个库 Mac电脑需要安装,mysql-client 1234brew install mysql-client# 二进制目录(需要手动复制到上图的路径):/opt/homebrew/opt/mysql-client/bin/mysqldump 导入SQL要在库名上点右键 这个功能类似于