Tio Boot DocsTio Boot Docs
Home
  • java-db
  • api-table
  • jooq
  • mysql
  • postgresql
  • oceanbase
  • Enjoy
  • Tio Boot Admin
  • LLM
  • voice-agent
  • knowlege_base
  • ai_agent
  • ai-search
  • 案例
Abount
AI 检索
  • Github
  • Gitee
Home
  • java-db
  • api-table
  • jooq
  • mysql
  • postgresql
  • oceanbase
  • Enjoy
  • Tio Boot Admin
  • LLM
  • voice-agent
  • knowlege_base
  • ai_agent
  • ai-search
  • 案例
Abount
AI 检索
  • Github
  • Gitee
  • 01_tio-boot 简介

    • 01_tio-boot 简介
    • tio-boot:新一代高性能 Java Web 开发框架
    • tio-boot 入门示例
    • Tio-Boot 配置 : 现代化的配置方案
    • tio-boot 整合 Logback
    • tio-boot 整合 hotswap-classloader 实现热加载
    • 自行编译 tio-boot
    • 最新版本
    • 开发规范
  • 02_部署

    • 02_部署
    • 使用 Maven Profile 实现分环境打包 tio-boot 项目
    • Maven 项目配置详解:依赖与 Profiles 配置
    • tio-boot 打包成 FatJar
    • 使用 GraalVM 构建 tio-boot Native 程序
    • 使用 Docker 部署 tio-boot
    • 部署到 Fly.io
    • 部署到 AWS Lambda
    • 到阿里云云函数
    • 使用 Deploy 工具部署
    • 使用Systemctl启动项目
    • 使用 Jenkins 部署 Tio-Boot 项目
    • 使用 Nginx 反向代理 Tio-Boot
    • 使用 Supervisor 管理 Java 应用
    • 历史部署页与替代方案
    • 胖包与瘦包的打包与部署
  • 03_配置

    • 03_配置
    • 配置参数
    • 服务器监听器
    • 内置缓存系统 AbsCache
    • 使用 Redis 作为内部 Cache
    • 静态文件处理器
    • 基于域名的静态资源隔离
    • DecodeExceptionHandler
    • 开启虚拟线程(Virtual Thread)
    • 框架级错误通知
  • 04_原理

    • 04_原理
    • 生命周期
    • 请求处理流程
    • 重要的类
  • 05_json

    • 05_json
    • Json
    • 接受 JSON 和响应 JSON
    • 响应实体类
  • 06_web

    • 06_web
    • 概述
    • 接收请求参数
    • 接收日期参数
    • 接收数组参数
    • 返回字符串
    • 返回文本数据
    • 返回网页
    • 请求和响应字节
    • 文件上传
    • 文件下载
    • 返回视频文件并支持断点续传
    • http Session
    • Cookie
    • 重定向和转发
    • HttpRequest
    • HttpResponse
    • Resps
    • RespBodyVo
    • Controller拦截器
    • 请求拦截器
    • LoggingInterceptor
    • 全局异常处理器
    • 异步处理
    • 动态 返回 CSS 实现
    • 返回图片
    • 跨域
    • 添加 Controller
    • Transfer-Encoding: chunked 实时音频播放
    • Server-Sent Events (SSE)
    • handler入门
    • 返回 multipart
    • Handler 的请求方法与错误响应
    • 自定义 Handler 转发请求
    • 使用 HttpForwardHandler 转发所有请求
    • 常用工具类
    • HTTP Basic 认证
    • Http响应加密
    • 使用零拷贝发送大文件
    • 分片上传
    • 接口访问统计
    • 接口请求和响应数据记录
    • WebJars
    • JProtobuf
    • 测速
    • Gzip Bomb:使用压缩炸弹防御恶意爬虫
  • 07_validate

    • 07_validate
    • 数据紧校验规范
    • 参数校验
  • 08_websocket

    • 08_websocket
    • 使用 tio-boot 搭建 WebSocket 服务
    • WebSocket 聊天室项目示例
  • 09_java-db

    • 09_java-db
    • Db 工具类
    • java‑db
    • 操作数据库入门示例
    • SQL 模板 (SqlTemplates)
    • 数据源配置与使用
    • ActiveRecord
    • Db 工具类
    • 批量操作
    • Model
    • Model生成器
    • 注解
    • 异常处理
    • 数据库事务处理
    • Cache 缓存
    • Dialect 多数据库支持
    • 表关联操作
    • 复合主键
    • Oracle 支持
    • Enjoy SQL 模板
    • 整合 Enjoy 模板最佳实践
    • 多数据源支持
    • 独立使用 ActiveRecord
    • 调用存储过程
    • java-db 整合 Guava 的 Striped 锁优化
    • 生成 SQL
    • 通过实体类操作数据库
    • java-db 读写分离
    • Spring Boot 整合 Java-DB
    • like 查询
    • 常用操作示例
    • Druid 监控集成指南
    • SQL 统计
    • Db 与 PostgreSQL 业务实践
  • 10_api-table

    • 10_api-table
    • ApiTable 概述
    • 使用 ApiTable 连接 SQLite
    • 使用 ApiTable 连接 Mysql
    • 使用 ApiTable 连接 Postgres
    • 使用 ApiTable 连接 TDEngine
    • 使用 api-table 连接 oracle
    • 使用 api-table 连接 mysql and tdengine 多数据源
    • EasyExcel 导出
    • EasyExcel 导入
    • ApiTable 的权限与业务边界
    • ApiTable 联调与故障定位
    • ApiTable 实现增删改查
    • 数组类型
    • 单独使用 ApiTable
    • TQL(Table SQL)前端输入规范
  • 11_aop

    • 11_aop
    • JFinal-aop
    • Aop 工具类
    • 配置
    • 独立使用 JFinal Aop
    • @AImport
    • 自定义注解拦截器
    • 原理解析
  • 12_cache

    • 12_cache
    • Caffeine
    • CacheUtils 工具类
    • 使用 java-db 整合 ehcache
  • 13_认证和权限

    • 13_认证
    • FixedTokenInterceptor
    • TokenManager
    • 数据表
    • 匿名登录
    • 个人中心
    • 权限校验注解
    • Sa-Token
    • sa-token 登录注册
    • StpUtil.isLogin() 源码解析
  • 14_i18n

    • 14_i18n
    • i18n
  • 15_enjoy

    • 15_enjoy
    • tio-boot 整合 Enjoy 模版引擎文档
    • Tio-Boot 整合 Java-DB 与 Enjoy 模板引擎示例
    • 引擎配置
    • 表达式
    • 指令
    • 注释
    • 原样输出
    • Shared Method 扩展
    • Shared Object 扩展
    • Extension Method 扩展
    • Spring boot 整合
    • 独立使用 Enjoy
    • tio-boot enjoy 自定义指令 localeDate
    • PromptEngine
    • Enjoy 入门示例-擎渲染大模型请求体
    • Tio Boot + Enjoy:分页与 SEO 实战指南
    • TioBoot + Enjoy 生成 robots.txt 与 sitemap.xml:实战与SEO指南
    • Enjoy 使用示例
  • 16_定时任务

    • 16_定时任务
    • Quartz 定时任务集成指南
    • 分布式定时任务 xxl-jb
    • cron4j 使用指南
  • 17_tests

    • 17_tests
    • TioBootTest:环境与 AOP 初始化
    • 真实 HTTP 集成测试
    • 数据库集成测试与隔离
  • 18_mybatis

    • 18_mybatis
    • Tio-Boot 整合 MyBatis
    • 使用配置类方式整合 MyBatis
    • 整合数据源
    • 使用 mybatis-plus 整合 tdengine
    • 整合 mybatis-plus
  • 19_redis

    • 19_redis
    • 使用 Docker 安装 Redis
    • 使用 java-db 整合 Redis
    • Java DB Redis 相关 Api
    • redis 使用示例
    • 和 RedisTemplate 协作
    • 使用 Jedis 连接池接入 Redis
    • hutool RedisDS
    • Redisson
    • Caffeine 与 Redis 两级缓存
    • 使用 CacheUtils 整合 caffeine 和 redis 实现的两级缓存
  • 20_mongodb

    • 20_mongodb
    • tio-boot 使用 mongo-java-driver 操作 mongodb
  • 21_elastic-search

    • 21_elastic-search
    • Elasticsearch
    • JavaDB 整合 ElasticSearch
    • Elastic 工具类使用指南
    • Elastic-search 注意事项
    • ES 课程示例文档
  • 22_mq

    • 22_mq
    • Mica-mqtt
    • EMQX
    • Disruptor
  • 23_kafka

    • 23_kafka
    • Kafka
    • AWS MSK
  • 24_postgresql

    • 24_postgresql
    • PostgreSQL 安装
    • PostgreSQL 主键自增
    • PostgreSQL 日期类型
    • Postgresql 金融类型
    • PostgreSQL 数组类型
    • 索引
    • PostgreSQL 查询优化
    • 获取字段类型
    • PostgreSQL 全文检索
    • PostgreSQL 向量
    • PostgreSQL 优化向量查询
    • PostgreSQL 其他
  • 25_mysql

    • 25_mysql
    • 使用 Docker 运行 MySQL
    • 常见问题
  • 26_oceanbase

    • 26_oceanbase
    • 快速体验 OceanBase 社区版
    • 快速上手 OceanBase 数据库单机部署与管理
    • 诊断集群性能
    • 优化 SQL 性能指南
    • 待定
  • 27_oracle

    • 27_oracle
    • Oracle
  • 28_sqlserver

    • 28_sqlserver
    • SQL Server
  • 29_sqlite

    • 29_sqlite
    • SQLite
  • 30_integration_thirty_party

    • 30_integration_thirty_party
    • 整合 okhttp
    • 整合 GrpahQL
    • 集成 Mailjet
    • 整合 ip2region
    • 整合 GeoLite 离线库
    • 整合 Lark 机器人指南
    • 集成 Lark Mail 实现邮件发送
    • Thymeleaf
    • Swagger
    • Clerk 验证
    • 集成datadog
  • 31_tio

    • 31_tio
    • TioBootServer
    • 独立端口启动 TCP 服务器
    • 内置 TCP 处理器
    • 独立启动 UDPServer
    • 使用内置 UDPServer
    • t-io 消息处理流程
    • tio-运行原理详解
    • TioConfig
    • ChannelContext
    • Tio 工具类
    • 业务数据绑定
    • 业务数据解绑
    • 发送数据
    • 关闭连接
    • Packet
    • 监控: 心跳
    • 监控: 客户端的流量数据
    • 监控: 单条 TCP 连接的流量数据
    • 监控: 端口的流量数据
    • 单条通道统计: ChannelStat
    • 所有通道统计: GroupStat
    • 资源共享
    • 成员排序
    • SSL
    • DecodeRunnable
    • 使用 AsynchronousSocketChannel 响应数据
    • 拉黑 IP
    • 深入解析 Tio 源码:构建高性能 Java 网络应用
    • Https建立连接过程
  • 32_tio-utils

    • 32_tio-utils
    • tio-utils
    • EnvUtils 配置工具
    • Notification
    • Email
    • JSON
    • File
    • Base64
    • 上传和下载
    • Http
    • Telegram
    • RsaUtils
    • HttpUtils
    • ByteBufferUtils
    • 系统监控
    • 线程
    • 虚拟线程
    • 毫秒并发 ID (MCID) 生成方案
  • 33_tio-http-server

    • 33_tio-http-server
    • 使用 Tio-Http-Server 搭建简单的 HTTP 服务
    • tio-boot 添加 HttpRequestHandler
    • 在 Android 上使用 tio-boot 运行 HTTP 服务
    • tio-http-server-native
    • handler 常用操作
    • tio-http-server 与 tio-boot 的使用边界
  • 34_tio-websocket

    • 34_tio-websocket
    • WebSocket 服务器
    • WebSocket Client
    • TCP数据转发
  • 35_magic-script

    • 35_magic-script
    • tio-boot 与 magic-script 集成指南
  • 36_groovy

    • 36_groovy
    • tio-boot 整合 Groovy
    • 调试常用脚本
  • 37_spider

    • 37_spider
    • jsoup
    • 爬取 z-lib.io 数据
    • 整合 WebMagic
    • WebMagic 示例:爬取学校课程数据
    • Playwright
    • Flexmark (Markdown 处理器)
    • tio-boot 整合 Playwright
    • 缓存网页数据
  • 38_dubbo

    • 38_dubbo
    • 概述
    • dubbo 2.6.0
    • dubbo 2.6.0 调用过程
    • dubbo 3.2.0
  • 39_spring

    • 39_spring
    • Spring Boot Web 整合 Tio Boot
    • spring-boot-starter-webflux 整合 tio-boot
    • tio-boot 整合 spring-boot-starter
    • Tio Boot 整合 Spring Boot Starter db
    • Tio Boot 整合 Spring Boot Starter Data Redis 指南
  • 40_spring-cloud

    • 40_spring-cloud
    • tio-boot spring-cloud
  • 41_aio

    • 41_aio
    • ByteBuffer
    • AIO HTTP 服务器
    • 自定义和线程池和池化 ByteBuffer
    • AioHttpServer 应用示例 IP 属地查询
    • 手写 AIO Http 服务器
    • Java 21 中的虚拟线程与 AIO
  • 42_netty

    • 42_netty
    • Netty TCP Server
    • Netty Web Socket Server
    • 使用 protoc 生成 Java 包文件
    • Netty WebSocket Server 二进制数据传输
    • Netty 组件详解
  • 43_netty-boot

    • 43_netty-boot
    • Netty-Boot
    • 原理解析
    • 整合 Hot Reload
    • 整合 数据库
    • 整合 Redis
    • 整合 Elasticsearch
    • 整合 Dubbo
    • Listener
    • 文件上传
    • 拦截器
    • Spring Boot 整合 Netty-Boot
    • SSL 配置指南
    • ChannelInitializer
    • Reserve
  • 44_quarkus

    • 44_quarkus
    • Quarkus(无 HTTP)整合 tio-boot(有 HTTP)
    • tio-boot + Quarkus + Hibernate ORM Panache
    • tio-boot + Quarkus + Hibernate ORM Panache + jOOQ 整合方案
  • 45_jooq

    • 45_jooq
    • 使用配置类方式整合 jOOQ
    • tio-boot + jOOQ 事务管理
    • 批量操作与性能优化
    • 整合agroal
    • 代码生成与类型安全
    • 基于 Record / POJO 增删改查
    • UPSERT、批量更新、返回主键与高级 SQL
    • 的多表关联查询、DTO 投影、聚合统计与视图封装
    • 的窗口函数、CTE、JSON 查询与 PostgreSQL 高级 SQL 实战
    • tio-boot + jOOQ 的审计字段、乐观锁、数据权限与企业级 Repository 设计
    • 测试策略、SQL 日志、性能诊断与生产排障
    • 多租户、读写分离与多数据源设计
    • 代码生成治理、数据库迁移与团队协作规范实战
  • 46_media

    • 46_media
    • JAVE 提取视频中的声音
    • Jave 提取视频中的图片
    • 待定
  • 47_asr

    • 47_asr
    • Whisper-JNI
  • 48_tts

    • 48_tts
  • 49_ocr

    • 49_ocr
  • 50_native-media

    • 50_native-media
    • java-native-media
    • JNI 入门示例
    • mp3 拆分
    • mp4 转 mp3
    • 使用 libmp3lame 实现高质量 MP3 编码
    • Linux 编译
    • macOS 编译
    • 从 JAR 包中加载本地库文件
    • 支持的音频和视频格式
    • 任意格式转为 mp3
    • 通用格式转换
    • 通用格式拆分
    • 视频合并
    • VideoToHLS
    • split_video_to_hls 支持其他语言
    • 持久化 HLS 会话
    • 获取视频长度
    • 保存视频的最后一帧
    • 添加水印
    • linux版本
  • 51_cv

    • 51_cv
    • 使用 Java 运行 YOLOv8 ONNX 模型进行目标检测
    • tio-boot整合yolo
    • ONNX Runtime 推理说明
    • Paddle Structure
    • tio-boot 整合 Paddle Structure
    • tio-boot整合Paddle Structure 提取图片
    • U2Net 图片去背景原理
    • tio-boot 整合 U2Net 实现图片去背景
  • 52_telegram4j

    • 52_telegram4j
    • 数据库设计
    • 基于 HTTP 协议开发 Telegram 翻译机器人
    • 基于 MTProto 协议开发 Telegram 翻译机器人
    • 过滤旧消息
    • 保存机器人消息
    • 定时推送
    • 增加命令菜单
    • 使用 telegram-Client
    • 使用自定义 StoreLayout
    • 延迟测试
    • Reactor 错误处理
    • Telegram4J 常见错误处理指南
    • 处理回调查询
    • Reactor
    • 文档翻译
    • 使用 Tio-Boot 整合 tdlight
    • tio-boot 整合 TelegramBots
    • tio-boot 整合 Telegram-Bot-Utils
    • Telegram-Bot-Utils 使用指南
  • 53_telegram-bots

    • 53_telegram-bots
    • TelegramBots 入门指南
    • 使用工具库 telegram-bot-base 开发翻译机器人
  • 54_LLM

    • 54_LLM
    • 简介
    • 流式生成
    • 图片多模态输入
    • Google Gemini接入
    • google Vertex AI 接入
    • 请求记录
    • 限流和错误处理
    • 增强检索(RAG)
    • 结构化数据检索
    • AI 问答
    • 连接代码执行器
    • 待定
    • 模型编程能力评测
    • /zh/54_LLM/17.html
  • 55_voice-agent

    • 55_voice-agent
    • 整合Gemini realtime模型
    • Voice Agent 前端接入接口文档
    • 整合千问realtime模型
    • 打断支持
    • 主动介入
    • eleven labs
    • 基于 tio-boot + ElevenLabs 构建实时语音 Agent(支持打断与主动介入)
  • 56_knowlege_base

    • 56_knowlege_base
    • 学术论文
    • 数据库设计
    • 用户登录实现
    • 模型管理
    • 知识库管理
    • 文档拆分
    • 片段向量
    • 命中测试
    • 文档管理
    • 片段管理
    • 问题管理
    • 应用管理
    • 向量检索
    • 推理问答
    • 问答模块
    • 统计分析
    • 用户管理
    • api 管理
    • 存储文件到 S3
    • 文档解析优化
    • 片段汇总
    • 段落分块与检索
    • 多文档解析
    • 对话日志
    • 检索性能优化
    • Milvus
    • 文档解析方案和费用对比
    • 离线运行向量模型
    • 爬取网页数据
  • 57_ai_agent

    • 57_ai_agent
    • 数据库设计
    • 示例问题管理
    • 会话管理
    • 历史记录
    • Perplexity API
    • 意图识别
    • 智能问答
    • 文件上传与解析文档
    • 翻译
    • 名人搜索功能实现
    • Ai studio gemini youbue 问答使用说明
    • 自建 YouTube 字幕问答系统
    • 自建 获取 youtube 字幕服务
    • 使用 OpenAI ASR 实现语音识别接口(Java 后端示例)
    • 定向搜索
    • 16
    • 17
    • 18
    • 在 tio-boot 应用中整合 ai-agent
    • 接口文档
    • 自定义 ChatAskService
  • 58_ai-search

    • 58_ai-search
    • ai-search 项目简介
    • ai-search 数据库文档
    • ai-search SearxNG 搜索引擎
    • ai-search Jina Reader API
    • ai-search Jina Search API
    • ai-search 搜索、重排与读取内容
    • ai-search PDF 文件处理
    • ai-search 推理问答
    • Google Custom Search JSON API
    • ai-search 意图识别
    • ai-search 问题重写
    • ai-search 系统 API 接口 WebSocket 版本
    • ai-search 搜索代码实现 WebSocket 版本
    • ai-search 生成建议问
    • ai-search 生成问题标题
    • ai-search 历史记录
    • Discover API
    • 翻译
    • Tavily Search API 文档
    • 对接 Tavily Search
    • 火山引擎 DeepSeek
    • 对接 火山引擎 DeepSeek
    • ai-search 搜索代码实现 SSE 版本
    • jar 包部署
    • Docker 部署
    • 爬取一个静态网站的所有数据
    • 网页数据预处理
    • 网页数据检索与问答流程整合
  • 59_ai-coding

    • 59_ai-coding
    • Cline 提示词
    • Cline 提示词-中文版本
  • 60_java-uni-ai-server

    • 60_java-uni-ai-server
    • 语音合成系统
    • Fish.audio TTS 接口说明文档与 Java 客户端封装
    • 整合 fishaudio 到 java-uni-ai-server 项目
    • 待定
  • 61_java-llm-proxy

    • 61_java-llm-proxy
    • 使用tio-boot搭建多模型LLM代理服务
  • 62_java-kit-server

    • 62_java-kit-server
    • Java 执行 python 代码
    • 通过大模型执行 Python 代码
    • 执行 Python (Manim) 代码
    • 待定
    • 待定
    • 待定
    • 视频下载增加水印说明文档
  • 63_ai-brower

    • 63_ai-brower
    • AI Browser:基于用户指令的浏览器自动化系统
    • 提示词
    • dom构建- buildDomTree.js
    • dom构建- 将网页可点击元素提取与可视化
    • 提取网内容
    • 启动浏览器
    • 操作浏览器指令
    • 统一命令接口与人机协作
  • 64_文件存储

    • 64_文件存储
    • 文件上传数据表
    • 本地存储
    • 存储到 亚马逊 S3
    • 存储到 Cloudflare R2
    • 存储到 腾讯 COS
    • 上传文件到阿里云 OSS
  • 65_tio-boot-admin

    • 65_tio-boot-admin
    • 入门指南:使用框架内置配置
    • 手动初始化数据库
    • 配置职责、生效条件与扩展边界
    • 整合数据库
    • 与前端集成
    • 文件上传
    • 网络请求
    • 单图片管理(只读模式)
    • 多图片管理
    • 布尔值管理
    • 字段联动
    • Word 管理
    • PDF 管理
    • 文章管理
    • 富文本编辑器
    • 整合 Enjoy 模版引擎
    • 历史可选方案:Token 存储与 Sa-Token
    • 业务 API 与 H5 / 小程序联调
    • 方法路由与业务鉴权
    • 整合 Redis
    • 整合 Elasticsearch
    • 后端开发规范:tio-boot、java-db 与 Kv
    • 多表实现文件数据存储
  • 66_第三方登录注册

    • 66_第三方登录注册
    • 邮箱登录和注册
    • 邮箱重置密码
    • 腾讯云短信登录注册
    • 腾讯云短信重置密码
    • 阿里云短信登录和注册
    • 阿里云短信重置密码
    • 微信登录与绑定手机号
    • 支付宝登录与绑定手机号
    • 微信小程序手机号快捷登录
    • Google登录
    • 阿里云邮件推送验证邮箱
  • 67_pay

    • 支付集成
    • 微信小程序支付:普通支付
    • 微信支付:Native 扫码支付(PC 网页扫码)
  • 68_firebase

    • 68_firebase
    • 整合 google firebase
    • Firebase Storage
    • Firebase Authentication
    • 使用 Firebase Admin SDK 进行匿名用户管理与自定义状态标记
    • 导出用户
    • 登录注册
    • 注册回调
  • 69_clerk

    • 69_clerk
    • Clerk
  • 70_tio-im

    • 70_tio-im
    • 通讯协议文档
    • ChatPacket.proto 文档
    • java protobuf
    • 数据表设计
    • 创建工程
    • 登录
    • 历史消息
    • 发消息
  • 71_tio-mail-wing

    • 71_tio-mail-wing
    • tio-mail-wing简介
    • 任务1:实现POP3系统
    • 使用 getmail 验证 tio-mail-wing POP3 服务
    • 任务2:实现 SMTP 服务
    • 数据库初始化文档
    • 用户管理
    • 邮件管理
    • 任务3:实现 SMTP 服务 数据库版本
    • 任务4:实现 POP3 服务(数据库版本)
    • IMAP 协议
    • 拉取多封邮件
    • 任务5:实现 IMAP 服务(数据库版本)
    • IMAP实现讲解
    • IMAP 手动测试脚本
    • IMAP 认证机制
    • 主动推送
    • namesapce
    • CONDSTORE and QRESYNC
  • 72_tio-mcp-server

    • 72_tio-mcp-server
    • 实现 MCP Server 开发指南
    • MCP 协议
    • /zh/72_tio-mcp-server/11.html
  • 73_tio-sip

    • 73_tio-sip
    • SIP Server 第一版原理说明
    • SIP Server 第一版实战
    • 一、Windows 平台测试
    • SIP Server 第二版实战
    • SIP Server 第三版实战
    • 性能优化
    • 基于 MediaProcessor 对接 Realtime 模型说明
    • 对接大语言模型
    • 支持 G722 宽带语音
    • G722编码和解码
    • 会话级采样率转换
    • 增加 9196 回声测试分机
    • 语音系统链路说明
    • 一、Gemini Realtime 的打断机制
  • 74_tio-log-server

    • 74_tio-log-server
    • 简介
    • 收集 docker 日志
    • 入库
  • 75_性能测试

    • 75_性能测试
    • 压力测试 - tio-http-serer
    • 压力测试 - tio-boot
    • 压力测试 - tio-boot-native
    • 压力测试 - netty-boot
    • 性能测试对比
    • TechEmpower FrameworkBenchmarks
    • 压力测试 - tio-boot 12 C 32G
    • HTTP/1.1 Pipelining 性能测试报告
    • tio-boot vs Quarkus 性能对比测试报告
  • 76_tio-boot

    • 76_tio-boot
    • 源码阅读入口
    • Swagger 整合到 Tio-Boot 中的指南
    • 启动与关闭生命周期
    • HTTP 请求分发与路由优先级
    • 高性能网络编程中的 ByteBuffer 分配与回收策略
    • TioBootServerHandler 源码解析
  • 77_案例

    • 77_案例
    • 封装 IP 查询服务
    • tio-boot 案例 - 全局异常捕获与企业微信群通知
    • tio-boot 案例 - 文件上传和下载
    • tio-boot 案例 - 整合 ant design pro 增删改查
    • tio-boot 案例 - 流失响应
    • tio-boot 案例 - 增强检索
    • tio-boot 案例 - 整合 function call
    • tio-boot 案例 - 定时任务 监控 PostgreSQL、Redis 和 Elasticsearch
    • Tio-Boot 案例:使用 SQLite 整合到登录注册系统
    • tio-boot 案例 - 执行 shell 命令
    • /zh/77_%E6%A1%88%E4%BE%8B/11.html
    • /zh/77_%E6%A1%88%E4%BE%8B/12.html
    • /zh/77_%E6%A1%88%E4%BE%8B/13.html

微信小程序手机号快捷登录

  • 概述
  • 一、开通微信能力
  • 二、环境配置
  • 三、登录流程
  • 四、服务端接口
  • 五、服务端客户端实现
  • 六、身份服务实现
  • 七、路由配置
  • 八、uni-app 小程序端
  • 九、测试步骤
    • 9.1 后端和前端准备
    • 9.2 真机验证
    • 9.3 接口检查
  • 十、常见问题
  • 十一、安全注意事项
  • 参考资料

概述

微信小程序手机号快捷登录由微信小程序客户端、业务服务端和微信开放接口共同完成。用户在小程序中主动授权手机号后,客户端取得两个不同用途的一次性凭证:

  • uni.login 或 wx.login 返回的小程序登录 code,用于换取 openid 和 session_key。
  • getPhoneNumber 回调返回的手机号授权 code,用于换取经过微信验证的手机号。

两个 code 不能互换,也不能在客户端直接使用 AppSecret 调用微信接口。服务端完成凭证交换、账号关联和业务 Token 签发,客户端只接收业务登录结果。

本文介绍一套完整的手机号快捷登录流程,适用于 uni-app 微信小程序和基于 tio-boot 的 Java 服务端。

一、开通微信能力

登录微信公众平台,进入目标小程序后完成以下配置:

  1. 检查小程序主体、认证状态和服务类目。
  2. 查找“手机号快速验证组件”或“获取手机号”能力,按照后台提示开通并确认可用额度。不同主体的菜单名称可能不同,通常位于“付费管理”等相关入口。
  3. 在“开发管理 -> 开发设置”取得小程序 AppID 和 AppSecret。
  4. 在微信后台配置用户隐私保护指引,按实际用途声明手机号等个人信息的处理方式。
  5. 在“开发管理 -> 开发设置 -> 服务器域名”中配置后端 HTTPS 合法域名。

手机号授权必须由用户主动点击微信提供的授权按钮触发。应用自己的用户协议和隐私政策不能替代微信授权弹窗。

二、环境配置

AppID 必须与小程序客户端配置保持一致,AppSecret 只能保存在服务端环境变量中,不能放入前端代码、前端构建变量或日志。

WECHAT_MINI_APP_ID=你的小程序AppID
WECHAT_MINI_APP_SECRET=你的AppSecret

如果微信后台启用了接口 IP 白名单,还需要加入服务端访问微信接口时使用的真实公网出口 IP。手机 IP、开发电脑局域网 IP 和后端服务器公网出口 IP 不是同一个概念。

前端配置示例:

VITE_MP_API_BASE_URL=https://api.example.com/api/mi

源码内部业务路由以 /api/mi 开头。如果本地服务通过管理上下文暴露接口,地址也可能是:

VITE_MP_API_BASE_URL=http://127.0.0.1:8100/admin/api/mi

真机不能访问开发电脑的 127.0.0.1。本地真机测试时,应使用局域网 HTTPS 地址或可被手机访问的测试服务器,并在微信开发者工具中按开发阶段需要配置合法域名校验。

三、登录流程

用户点击手机号授权按钮
        |
        v
小程序 getPhoneNumber -> phoneCode
        |
        +-- uni.login -> loginCode
        |
        v
业务服务端接收 loginCode 和 phoneCode
        |
        +-- jscode2session -> openid、session_key
        +-- stable_token -> access_token
        +-- getuserphonenumber -> verified phone
        |
        v
服务端创建或关联业务账号
        |
        v
签发业务 token 返回客户端

服务端请求微信接口:

  1. GET https://api.weixin.qq.com/sns/jscode2session,使用 AppID、AppSecret 和 loginCode 换取 openid。
  2. POST https://api.weixin.qq.com/cgi-bin/stable_token,取得调用手机号接口所需的应用 access_token。该 token 应在服务端缓存,并在过期前刷新。
  3. POST https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=...,提交 phoneCode,取得微信验证后的手机号。
  4. 服务端根据手机号、AppID 和 OpenID 查询或创建业务账号,最后签发业务 token。

不要把 session_key、AppSecret、微信 access_token 或手机号授权凭证返回给客户端,也不要记录到日志中。

四、服务端接口

业务登录接口可以定义为:

POST /api/mi/auth/wechat/phone-login
Content-Type: application/json

请求体:

{
  "loginCode": "uni.login 返回的一次性 code",
  "phoneCode": "getPhoneNumber 回调中的一次性 code",
  "inviterUserId": "可选的邀请人 ID"
}

其中 inviterUserId 只能作为邀请关系的业务参数,不能用于确定当前登录用户身份。服务端必须以微信接口返回的 OpenID 和手机号为可信身份来源。

成功响应示例:

{
  "code": 1,
  "msg": "ok",
  "data": {
    "token": "业务登录 token",
    "expiresAt": "1735689600",
    "userId": "100001"
  }
}

建议的错误语义:

HTTP 状态含义
400参数错误、授权码失效或已被使用
409微信身份和手机号分别属于不同业务账号,存在归属冲突
429微信接口或业务接口触发频率限制
503微信配置、微信服务、Redis 或网络不可用

五、服务端客户端实现

下面的客户端只负责服务端调用微信接口。实际项目可以替换 HTTP 客户端和 JSON 工具,但不能把 AppSecret 下沉到前端。

package com.example.auth.integration;

import com.jfinal.kit.Kv;
import java.net.URI;
import java.net.URLEncoder;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.time.Instant;
import java.util.Map;
import nexus.io.tio.boot.exception.BusinessException;
import nexus.io.tio.utils.environment.EnvUtils;
import nexus.io.tio.utils.json.Json;

public class WechatMiniClient {
  private final HttpClient http = HttpClient.newBuilder()
      .connectTimeout(Duration.ofSeconds(5)).build();
  private String cachedToken;
  private String cachedAppId;
  private long tokenExpiresAt;

  public Kv session(String code) {
    String path = "/sns/jscode2session?appid=" + encode(appId())
        + "&secret=" + encode(secret())
        + "&js_code=" + encode(code)
        + "&grant_type=authorization_code";
    Kv result = request(path, null);
    check(result);
    return result;
  }

  public Kv phone(String code) {
    String token = accessToken(null);
    Kv result = request("/wxa/business/getuserphonenumber?access_token="
        + encode(token), Kv.by("code", code));
    Integer error = result.getInt("errcode");
    if (error != null && (error == 40001 || error == 40014 || error == 42001)) {
      token = accessToken(token);
      result = request("/wxa/business/getuserphonenumber?access_token="
          + encode(token), Kv.by("code", code));
    }
    check(result);
    Object phoneInfo = result.get("phone_info");
    if (!(phoneInfo instanceof Map<?, ?> values)) {
      throw unavailable();
    }
    return Kv.create().set(values);
  }

  private synchronized String accessToken(String rejectedToken) {
    String id = appId();
    long now = Instant.now().getEpochSecond();
    boolean rejected = rejectedToken != null && rejectedToken.equals(cachedToken);
    if (!rejected && id.equals(cachedAppId) && cachedToken != null
        && tokenExpiresAt > now) {
      return cachedToken;
    }
    Kv body = Kv.by("grant_type", "client_credential")
        .set("appid", id).set("secret", secret())
        .set("force_refresh", rejected);
    Kv result = request("/cgi-bin/stable_token", body);
    check(result);
    String token = result.getStr("access_token");
    Long expiresIn = result.getLong("expires_in");
    if (token == null || token.isBlank() || expiresIn == null || expiresIn <= 60) {
      throw unavailable();
    }
    cachedAppId = id;
    cachedToken = token;
    tokenExpiresAt = now + expiresIn - 60;
    return token;
  }

  private Kv request(String path, Kv body) {
    try {
      HttpRequest.Builder builder = HttpRequest.newBuilder(
          URI.create("https://api.weixin.qq.com" + path))
          .timeout(Duration.ofSeconds(10))
          .header("Accept", "application/json");
      if (body == null) {
        builder.GET();
      } else {
        builder.header("Content-Type", "application/json")
            .POST(HttpRequest.BodyPublishers.ofString(
                Json.getJson().toJson(body), StandardCharsets.UTF_8));
      }
      HttpResponse<String> response = http.send(
          builder.build(), HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8));
      if (response.statusCode() != 200) throw unavailable();
      Object parsed = Json.getJson().parse(response.body());
      if (!(parsed instanceof Map<?, ?> values)) throw unavailable();
      return Kv.create().set(values);
    } catch (InterruptedException e) {
      Thread.currentThread().interrupt();
      throw unavailable();
    } catch (Exception e) {
      throw unavailable();
    }
  }

  private void check(Kv result) {
    Integer error = result.getInt("errcode");
    if (error == null || error == 0) return;
    if (error == 40029 || error == 40163) {
      throw new BusinessException(400, "微信授权已失效,请重新点击登录");
    }
    if (error == 45011 || error == 45009) {
      throw new BusinessException(429, "微信请求频繁,请稍后重试");
    }
    throw unavailable();
  }

  public String appId() {
    return required("WECHAT_MINI_APP_ID");
  }

  private String secret() {
    return required("WECHAT_MINI_APP_SECRET");
  }

  private String required(String name) {
    String value = EnvUtils.get(name);
    if (value == null || value.isBlank()) {
      throw new BusinessException(503, "微信登录尚未配置");
    }
    return value.trim();
  }

  private static String encode(String value) {
    return URLEncoder.encode(value, StandardCharsets.UTF_8);
  }

  private static BusinessException unavailable() {
    return new BusinessException(503, "微信服务暂不可用");
  }
}

手机号接口的应用 access_token 可以缓存。只有收到明确的 token 无效错误时才刷新并重试一次;网络超时、已消费的手机号 code 和普通业务失败不能自动重试,因为手机号 code 是一次性凭证。

六、身份服务实现

服务层应同时校验两个微信接口的结果,并在数据库事务中完成账号关联。下面是核心逻辑示例:

package com.example.auth.service;

import com.jfinal.kit.Kv;
import com.example.auth.integration.WechatMiniClient;
import java.util.Map;
import nexus.io.jfinal.aop.Aop;
import nexus.io.tio.boot.exception.BusinessException;

public class WechatPhoneLoginService {
  public Kv login(String loginCode, String phoneCode) {
    WechatMiniClient client = Aop.get(WechatMiniClient.class);
    Kv session = client.session(loginCode);
    String openid = session.getStr("openid");
    if (openid == null || openid.isBlank()) {
      throw new BusinessException(503, "微信身份信息不可用");
    }

    Kv phoneInfo = client.phone(phoneCode);
    String phone = phoneInfo.getStr("purePhoneNumber");
    Object watermark = phoneInfo.get("watermark");
    String appId = watermark instanceof Map<?, ?> values
        ? String.valueOf(values.get("appid")) : null;
    if (phone == null || phone.isBlank() || !client.appId().equals(appId)) {
      throw new BusinessException(503, "微信手机号信息不可用");
    }

    // 在事务中按手机号、openid 和账号唯一约束完成查询、创建或绑定。
    // 手机号与微信身份分别属于不同账号时返回 409,不直接合并业务数据。
    return accountService().loginOrCreate(phone, openid,
        session.getStr("unionid"));
  }

  private AccountService accountService() {
    return Aop.get(AccountService.class);
  }
}

实际账号服务至少应处理以下情况:

情况处理方式
新微信、新手机号创建账号并绑定微信身份和手机号
新微信、已有手机号复用手机号账号并绑定微信身份
已有微信、未绑定手机号验证归属后补充手机号
手机号和微信分别属于不同账号返回 409,不自动合并
unionid 缺失仍可使用 AppID 和 OpenID 登录

数据库应为手机号和微信身份分别建立唯一约束,并在事务中处理并发创建,避免同一用户被重复注册。

七、路由配置

手机号快捷登录接口必须是公开路由,但公开只表示不需要业务 Token,不表示可以跳过微信凭证校验。

router.add(HttpMethod.POST, "/api/mi/auth/wechat/phone-login",
    authHandler::wechatPhoneLogin,
    Map.of(AuthInterceptor.ACCESS, AccessPolicy.PUBLIC));

Handler 示例:

public HttpResponse wechatPhoneLogin(HttpRequest request) {
  Kv body = request.getBodyObject(Kv.class);
  String loginCode = ParameterValidator.text(body.getStr("loginCode"),
      "loginCode", 256);
  String phoneCode = ParameterValidator.text(body.getStr("phoneCode"),
      "phoneCode", 256);
  String inviterUserId = body.getStr("inviterUserId");
  RespBodyVo result = service.login(loginCode, phoneCode, inviterUserId);
  return TioRequestContext.getResponse().respond(result);
}

八、uni-app 小程序端

微信小程序页面使用 open-type="getPhoneNumber",用户点击按钮后取得手机号授权 code,再调用 uni.login 取得登录 code。

<template>
  <button
    v-if="agreed"
    open-type="getPhoneNumber"
    :loading="busy"
    :disabled="busy"
    @getphonenumber="wechatPhone"
  >
    {{ busy ? '正在登录' : '手机号快捷登录' }}
  </button>
  <button v-else @click="showAgreement">手机号快捷登录</button>
</template>

<script setup>
import { ref } from 'vue'
import { api } from '@/services/api'

const agreed = ref(false)
const busy = ref(false)

async function wechatPhone(event) {
  if (busy.value || !agreed.value) return
  if (!event.detail?.code) {
    throw new Error('未获取到手机号授权,请重试或使用短信登录')
  }
  busy.value = true
  try {
    const loginResult = await new Promise((resolve, reject) => {
      uni.login({
        provider: 'weixin',
        timeout: 10000,
        success: resolve,
        fail: reject
      })
    })
    if (!loginResult.code) throw new Error('未获取到微信登录凭证')

    const data = await api('/auth/wechat/phone-login', {
      loginCode: loginResult.code,
      phoneCode: event.detail.code
    }, 'POST')
    saveSession(data)
  } finally {
    busy.value = false
  }
}
</script>

用户拒绝授权时保留短信验证码登录入口。前端不应提交用户手工填写的手机号作为微信认证结果,也不应自行拼接 OpenID 或用户 ID。

九、测试步骤

9.1 后端和前端准备

  1. 在微信公众平台完成认证、手机号能力开通和隐私指引配置。
  2. 将 AppID、AppSecret 配置到后端 .env 或部署环境变量。
  3. 确认小程序 manifest.json 中的 AppID 与服务端配置一致。
  4. 重启后端服务。
  5. 执行前端微信小程序构建命令,并将生成目录导入微信开发者工具。

9.2 真机验证

  1. 使用真实小程序 AppID 导入构建目录。
  2. 在开发者工具中添加开发者或体验者账号。
  3. 打开登录页并勾选用户协议和隐私政策。
  4. 点击“手机号快捷登录”。
  5. 在微信弹窗中确认手机号授权。
  6. 验证登录成功后是否跳转首页,并检查“我的”页面能否正常读取用户信息。
  7. 退出登录后再次登录,确认账号被复用而不是重复创建。

开发者工具的“不校验合法域名”只适合开发阶段。正式真机测试应使用 HTTPS 合法域名,并确认手机网络可以访问服务端。

9.3 接口检查

客户端调用的接口为:

POST https://你的接口域名/api/mi/auth/wechat/phone-login

请求体中应同时出现两个不同的字符串:

{
  "loginCode": "uni.login 返回的 code",
  "phoneCode": "getPhoneNumber 返回的 code"
}

登录成功后检查:

  • 服务端没有向日志输出 AppSecret、session_key、access_token 或完整 code。
  • 返回结果只包含业务 token、用户 ID 和过期时间等业务字段。
  • 数据库没有重复的手机号或微信身份绑定。
  • 后续需要登录的业务接口能够使用返回的业务 token。

十、常见问题

现象排查方向
点击按钮没有授权弹窗检查是否使用真实 AppID、按钮是否为 getPhoneNumber、用户是否已同意应用协议
手机号授权失败检查手机号能力是否开通、额度是否可用、隐私指引是否完成
授权码无效重新点击登录获取两个新 code,不要重复提交旧 code
真机请求失败检查 HTTPS 证书、request 合法域名、前端 API 地址和网络连通性
返回 503检查 AppID、AppSecret、微信服务、Redis 和服务端公网出口
返回 409手机号和微信身份已属于不同账号,应走已有账号处理流程,不直接改库合并
登录成功但后续接口未授权检查客户端是否保存业务 token,以及请求头是否为 Authorization: Bearer <token>

十一、安全注意事项

  1. AppSecret 只保存在服务端,不能提交到前端仓库。
  2. 不信任客户端传入的手机号、OpenID、UnionID 和用户 ID。
  3. 两个微信 code 均为一次性凭证,失败后重新获取,不自动重放。
  4. 业务账号创建和身份绑定应使用事务和唯一约束。
  5. 处理账号冲突时不要自动迁移订单、余额、资源或其他业务数据。
  6. 手机号属于个人信息,数据库访问、日志和错误响应应遵守最小化原则。
  7. 生产环境必须使用 HTTPS,并限制服务端错误信息,避免回显微信接口内部细节。

参考资料

  • 微信小程序登录
  • 微信小程序获取手机号
  • 获取稳定版接口调用凭据
  • uni-app 登录
Edit this page
Last Updated: 9/22/26, 10:01 AM
Contributors: Tong Li
Prev
支付宝登录与绑定手机号
Next
Google登录