Java生成微信小程序二维码,5种实现方式,一个比一个简单

news2024/11/28 9:47:03

文章目录

  • 前言
  • 先看官网
  • 一、JDK自带的URLConnection方式
  • 二、Apache的HttpClient方式
  • 三、okhttp3方式
  • 四、Unirest方式
  • 五、RestTemplate方式
  • 其它细节
    • getAccessToken
    • 构建参数map
    • byte[]数组
  • 源码下载


前言

先介绍一下项目场景,主要是通过微信小程序二维码裂变分享,每个账号有专属邀请二维码,分享出去,有新人扫码入驻,就可以得到现金奖励或红包奖励。当然,产品设计会更丰富,不止有裂变模式,还有渠道推广模式,还有各种奖励规则,但核心实现都是生成二维码。对于如何生成微信小程序二维码,本文一共列举了5种实现方式,其中第1、2种是网上常见的方式,第3、4、5种封装的更为优雅,文末可打包下载开箱即用的全套源码,我更期待老铁的文末 投票 :哪种方式你更喜欢?
请添加图片描述


先看官网

项目主要用的是微信官方提供的服务端能力,考虑到涉及secrettoken等安全问题,所以从架构上设计的调用链路为前端->后端API->微信API。裂变的场景决定要选择获取不限制的小程序码接口,永久有效,数量暂无限制,接口英文名:getUnlimitedQRCode

官方地址:https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/qrcode-link/qr-code/getUnlimitedQRCode.html

在这里插入图片描述


一、JDK自带的URLConnection方式

在网上常见的方式,这是从 JDK1.1 开始就自带的Http请求方式,核心代码如下:

public byte[] getWechatQrcodeByHttpURL(String url, Map<String, Object> body) {
    HttpURLConnection httpURLConnection = null;
    try {
        httpURLConnection = (HttpURLConnection) new URL(url).openConnection();
        httpURLConnection.setRequestMethod("POST");
        // 发送POST请求必须设置如下两行
        httpURLConnection.setDoOutput(true);
        httpURLConnection.setDoInput(true);
        // 获取URLConnection对象对应的输出流
        PrintWriter printWriter = new PrintWriter(httpURLConnection.getOutputStream());
        // 发送请求参数
        printWriter.write(JSONObject.toJSONString(body));
        // flush输出流的缓冲
        printWriter.flush();
        //开始获取数据
        try (InputStream inputStream = httpURLConnection.getInputStream();
             ByteArrayOutputStream out = new ByteArrayOutputStream()) {
            byte[] buffer = new byte[1024];
            int len = -1;
            while ((len = inputStream.read(buffer)) != -1) {
                out.write(buffer, 0, len);
            }
            return out.toByteArray();
        }
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        if (httpURLConnection != null) {
            httpURLConnection.disconnect();
        }
    }
    return null;
}

JDK自带的方式,功能虽然可以实现,但代码看上去确实跟不上时代发展了!


二、Apache的HttpClient方式

HttpClient 相比于 JDK 自带的 URLConnection方式,代码做了封装,可读性和简洁度都显著提升!核心代码如下:

public byte[] getWechatQrcodeByHttpClient(String url, Map<String, Object> body) {
    CloseableHttpClient httpClient = HttpClientBuilder.create().build();
    HttpPost httpPost = new HttpPost(url);
    try {
        StringEntity entity = new StringEntity(JSONObject.toJSONString(body));
        entity.setContentType("image/png");
        httpPost.setEntity(entity);
        HttpResponse response = httpClient.execute(httpPost);
        try (InputStream inputStream = response.getEntity().getContent();
             ByteArrayOutputStream out = new ByteArrayOutputStream()) {
            byte[] buffer = new byte[1024];
            int len = -1;
            while ((len = inputStream.read(buffer)) != -1) {
                out.write(buffer, 0, len);
            }
            return out.toByteArray();
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}

Maven依赖:

<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.5.12</version>
</dependency>

三、okhttp3方式

okhttp3是Square公司开发,用于替代 HttpUrlConnection和Apache HttpClient方式,优雅的 API 设计,且链式调用,让你顺滑到底!

核心代码如下:

public byte[] getWechatQrcodeByOkhttp3(String url, Map<String, Object> body) {
    OkHttpClient client = new OkHttpClient().newBuilder().build();
    okhttp3.MediaType mediaType = okhttp3.MediaType.parse("application/json");
    RequestBody requestBody = RequestBody.create(mediaType, JSONObject.toJSONString(body));
    Request request = new Request.Builder().url(url).method("POST", requestBody).build();
    try {
        Response response = client.newCall(request).execute();
        if (response.isSuccessful()) {
            return response.body().bytes();
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
    return null;
}

Maven依赖:

<dependency>
    <groupId>com.squareup.okhttp3</groupId>
    <artifactId>okhttp</artifactId>
    <version>3.14.2</version>
</dependency>

四、Unirest方式

okhttp3方式其实不管是性能还是代码的链式调用,都已经非常优秀。但作为底层基于Apache HttpClient方式unirest-java,提供了更为便捷、链式调用、功能强大的API用于http请求!核心代码如下(一行代码搞定,屌爆了!!!):

public byte[] getWechatQrcodeByUnirest(String url, Map<String, Object> body) {
    return Unirest.post(url).body(JSONObject.toJSONString(body)).asBytes().getBody();
}

Maven依赖:

<dependency>
    <groupId>com.konghq</groupId>
    <artifactId>unirest-java</artifactId>
    <version>3.11.11</version>
</dependency>

五、RestTemplate方式

我之前写过一篇博文对RestTemplate.exchange结合案例进行了详细的介绍:RestTemplate.exchange各种用法(包括泛型等 --全),推荐阅读!

这也是我们项目实际使用的方式,使用Spring框架开发,还是强烈推荐使用Spring的RestTemplate,它是对于其它方式的高级封装,内部可以配置ClientHttpRequestFactory来指定底层请求方式:

  • 指定为SimpleClientHttpRequestFactory,则内部使用JDK自带的HttpURLConnection方式
  • 指定为HttpComponentsClientHttpRequestFactory,则内部使用Apache HttpClient方式
  • 指定为OkHttp3ClientHttpRequestFactory,则内部使用okhttp3方式

核心代码也是一行:

public byte[] getWechatQrcodeByRestTemplate(String url, Map<String, Object> body) {
    return restTemplate.exchange(url, HttpMethod.POST, new HttpEntity<>(body, null), byte[].class).getBody();
}

另外,RestTemplate在构造函数中默认增加了ByteArrayHttpMessageConverter,可以读取和写入字节数组的HttpMessageConverter的实现,默认情况下,此转换器支持所有媒体类型(media types)。

在这里插入图片描述


其它细节

getAccessToken

这是接口调用凭证,用restTemplate调用也是非常简洁,核心代码如下:

private String wechatQrcodeUrl = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=";
private String appid = "替换成你的appid";
private String s = "替换成你的secret";

public String getAccessToken() {
    String url = String.format(wechatAccessTokenUrl, appid, s);
    Map<String, String> responseBody = restTemplate.exchange(url, HttpMethod.GET, null, new ParameterizedTypeReference<Map<String, String>>() {}).getBody();
    if (responseBody == null || responseBody.get("errcode") != null) {
        // 获取失败
        System.out.println("getAccessToken失败:" + (responseBody == null ? "null" : responseBody.toString()));
        return null;
    }
    return responseBody.get("access_token");
}

对于access_token,建议保存到redis,2小时过期后再获取

构建参数map

body 就是参数Map,需要根据实际情况自行设定:

Map<String,Object> body = new HashMap<>();
// 场景码,与前端约定,最终是需要前端解析
body.put("scene", scene);
// 正式版为 "release",体验版为 "trial",开发版为 "develop"。默认是正式版。
body.put("env_version", envVersion);
// 透明,根据你的场景自行设置body参数
body.put("is_hyaline", true);

在这里插入图片描述

byte[]数组

为什么要先得到byte[]数组?,因为我们需要先判断返回结果是否包含errcode,如果不包含,才是图片Buffer!

如果不包含errorCode,那么byte[]数组不管是保存本地,还是转成Base64,或者上传到OSS,都非常湿滑了!

  • 保存本地
private void saveQrCodeToLocal(byte[] bytes) {
    try {
        InputStream inputStream = new ByteArrayInputStream(bytes);
        FileOutputStream out = new FileOutputStream("d:\\test.png");
        byte[] buffer = new byte[8192];
        int bytesRead = 0;
        while ((bytesRead = inputStream.read(buffer, 0, 8192)) != -1) {
            out.write(buffer, 0, bytesRead);
        }
        out.flush();
        inputStream.close();
        out.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}
  • Base64
Base64.getEncoder().encodeToString(bytes);
  • 上传OSS
    这是我们项目使用的, 底层做了封装,直接传byte[]即可,非常方便!

源码下载

源码都是经过实测的,可以直接使用!

下载地址:https://download.csdn.net/download/scm_2008/87398320

❤️ 博客主页:https://blog.csdn.net/scm_2008
❤️ 欢迎点赞👍 收藏留言✏️ 如有错误敬请指正!
❤️ 本文由 天罡gg 原创,首发于 CSDN博客🙉
❤️ 停下休息的时候不要忘了别人还在奔跑,希望大家抓紧时间学习,全力奔赴更美好的生活


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/180269.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

一时重构一时爽,一直重构一直爽

笔者&#xff08;后台技术汇&#xff09;恭祝各位大佬&#xff1a;2023年春节快乐&#xff0c;兔年祥瑞。距离上次更新&#xff0c;已经过去5个月有余了&#xff0c;有小伙伴疑惑笔者是不是删库跑路了..其实不是&#xff0c;这段时间是在参加一次比较大的项目重构&#xff08;目…

学习笔记 —— python代码耗时及内存占用测试方法

1、手写耗时测试 先看结果; 主要有三种方法&#xff0c;各自的时钟间隔如下&#xff1a; time.time() timeit time.time_ns() ( time is outputted in ns!). 可见方法2&#xff0c;即timeit 的时钟间隔最短。 注&#xff1a;最后一个是以ns为单位的&#xff0c;前两个是…

二叉树的概念与结构

文章目录前言一、树的概念及结构1.树的概念2.树的相关概念3.树的表示4. 树在实际中的运用二、二叉树概念及结构1.概念2.特殊的二叉树5.二叉树的性质6.二叉树的存储结构(1).顺序存储&#xff08;2&#xff09;.链式存储结语前言 因为二叉树的知识点太多&#xff0c;一篇文章讲不…

《真象还原》读书笔记——第一章 部署工作环境

环境&#xff1a; 由于平时使用 windows 系统 所以 linux 环境 使用了 linux子系统。 $ cat /proc/version Linux version 4.4.0-22000-Microsoft (MicrosoftMicrosoft.com) (gcc version 5.4.0 (GCC) )1.1 工欲善其事 必先利其器 操作环境很重要呀。 1.2 编译器 GCC: gc…

Java 23种设计模式(8.结构型模式-桥接模式)

结构型模式-桥接模式 代码分析 类图 代码 public interface Implementor {void operation(); }public class ConcreteImplementorA implements Implementor{Overridepublic void operation() {System.out.println("A");} }public class ConcreteImplementorB imple…

(Java高级教程)第四章必备前端基础知识-第二节3:CSS盒模型和浮动

文章目录一&#xff1a;盒模型&#xff08;1&#xff09;border&#xff08;2&#xff09;padding&#xff08;3&#xff09;margin二&#xff1a;flex布局一&#xff1a;盒模型 盒模型&#xff1a;在HTML中&#xff0c;每个标签&#xff08;或元素&#xff09;相当于是一个盒…

DaVinci:色彩匹配

z调色页面&#xff1a;色彩匹配Color&#xff1a;Color Match色彩匹配 Color Match调板是专业的一级调色工具&#xff0c;专门用于对视频图像进行精准的校色还原。色彩匹配时&#xff0c;先定位到视频中持有色卡的画面。在检视器左下角快捷菜单中选择“色卡” Color Chart工具&…

C 语言零基础入门教程(十二)

C enum(枚举) 枚举是 C 语言中的一种基本数据类型&#xff0c;它可以让数据更简洁&#xff0c;更易读。 枚举语法定义格式为&#xff1a; enum 枚举名 {枚举元素1,枚举元素2,……};接下来我们举个例子&#xff0c;比如&#xff1a;一星期有 7 天&#xff0c;如果不用枚举&…

【Linux】vim编辑器的使用

文章目录vim的基本概念vim指令集复制粘贴撤销、剪切光标定位vim的基本概念 vim是一款多模式的编辑器&#xff0c;在我们常用的模式有3~5种。分别是命令模式&#xff08;command mode&#xff09;、插入模式&#xff08;Insert mode&#xff09;和底行模式&#xff08; last lin…

【PHP 随记】—— ThinkPHP 配置数据库

&#x1f449;总目录&#x1f448;\large\colorbox{skyblue}{&#x1f449;总目录&#x1f448;}&#x1f449;总目录&#x1f448;​ 文章目录1、数据库连接及导入① 数据库连接② 数据库导入2、配置 ThinkPHP 数据库连接信息① 配置连接信息1、数据库连接及导入 ① 数据库连…

大数据分析案例-基于随机森林算法构建人口普查分析模型

&#x1f935;‍♂️ 个人主页&#xff1a;艾派森的个人主页 ✍&#x1f3fb;作者简介&#xff1a;Python学习者 &#x1f40b; 希望大家多多支持&#xff0c;我们一起进步&#xff01;&#x1f604; 如果文章对你有帮助的话&#xff0c; 欢迎评论 &#x1f4ac;点赞&#x1f4…

Datawhale 202301 设计模式 | 人工智能 现代方法 习题

Exercise 1 绪论 Q&#xff1a;用您自己的话来定义&#xff1a;&#xff08;a&#xff09;智能&#xff0c;&#xff08;b&#xff09;人工智能&#xff0c;&#xff08;c&#xff09;智能体&#xff0c;&#xff08;d&#xff09;理性&#xff0c;&#xff08;e&#xff09;逻…

【大数据趋势】1月24日 流动、固定汇率和货币政策独立性三者的三者选二,A股持续的会上涨。

前言&#xff1a;昨天写的被朋友看到&#xff0c;认为我写的太水&#xff0c;故意不提日常讨论的那个关键指标&#xff0c;所以下午重新修改了一下。 确定欧美大势市场形态1 - 美元指数 关键位置大概率不会一次就破&#xff0c;有较强反弹可能&#xff0c;带动美股反弹 作为长…

MH-100X微波运动传感器介绍

MH-100X微波运动传感器简介微波运动传感器是利用多普勒雷达原理设计的微波移动物体探测器。不同于一般的红外探测器&#xff0c;微波传感器通过通过检测物体反射的微波来探测物体的运动状况&#xff0c;检测对象将并不会局限于人体&#xff0c;还有很多其他的事物。微波传感器不…

java基础语法——条件判断与循环语句

目录 一、流程控制语句 流程控制语句分类 二、顺序结构 顺序结构概述 顺序结构图 三、选择结构 选择结构概述 选择结构(if语句1) 选择执行图1 选择结构(if语句2) 选择执行图2 选择结构(if语句3) 选择执行图3 选择结构(switch语句) switch语句执行流程图 四、 循环…

剪映电脑版超简单使用教程Mac

相机 我主要用到的两个键 点击开始创作导入本地视频 导入本地视频 将素材拖拽到时间线上 时间线面板操作 撤销、恢复、分割 撤销上一次操作也可以用快捷键 command z 定格、倒放、镜像、裁剪 剃刀 点击菜单的分割可以出来一个剃刀&#xff0c;分割更方便 选择模式 …

代码随想录算法训练营第十二天|239. 滑动窗口最大值| ● 347.前 K 个高频元素

239 滑动窗口最大值 看完题后的思路 这是一道典型的单调队列的题&#xff0c;如果不是之前刷过一遍&#xff0c;对这道题没有一点头绪。即使刷过&#xff0c;也只是留了个印象。 解题思路 对于本道题来说&#xff0c;到窗口右移&#xff0c;如果一个新元素a进入窗口&#x…

【Maven】分模块开发与设计与依赖管理

目录 一、分模块开发与设计 1. 分模块开发的意义 2. 分模块开发&#xff08;模块拆分&#xff09; 二、依赖管理 1. 依赖传递 2. 可选依赖 3. 排除依赖 4 可选依赖和排除依赖的区别 一、分模块开发与设计 1. 分模块开发的意义 问题导入 分模块开发对工程有什么好处…

ChatGPT - 横看成岭侧成峰

定义 ChatGPT 是什么&#xff1f; ChatGPT是由OpenAI开发的一个人工智能聊天机器人程序&#xff0c;由 OpenAI 公司于2022年11月推出。该程序使用基于GPT-3.5架构的大型语言模型并通过强化学习进行训练。 ChatGPT以对话方式进行交互&#xff0c;可以用于包括自动文本生成、自…

一起自学SLAM算法:8.3 LOAM算法

连载文章&#xff0c;长期更新&#xff0c;欢迎关注&#xff1a; 不管是Gmapping还是Cartographer&#xff0c;通常都是采用单线激光雷达作为输入并且只能在室内环境运行。虽然Cartographer支持2D建图和3D建图模式&#xff0c;但是Cartographer采用3D建图模式构建出来的地图格式…