springboot二維碼生成
開發環境:jdk8
springboot: 2.3.3.RELEASE
1.引入相應的jar包
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
<version>3.3.0</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.45</version>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.7.2</version>
</dependency>
2.編寫工具類
CodeUtil.java
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;
public class CodeUtil {
public static BitMatrix generateQRCodeStream(String content, HttpServletResponse resp) {
// 給響應添加頭部資訊,主要是告訴浏覽器傳回的是圖檔流
resp.setHeader("Cache-Control", "no-store");
resp.setHeader("Pragma", "no-cache");
resp.setDateHeader("Expires", 0);
resp.setContentType("image/png");
// 設定圖檔的文字編碼以及内邊框距
Map<EncodeHintType, Object> hints = new HashMap<EncodeHintType, Object>();
hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
hints.put(EncodeHintType.MARGIN, 0);
BitMatrix bitMatrix;
try {
// 參數順序分别為:編碼内容,編碼類型,生成圖檔寬度,生成圖檔高度,設定參數
bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, 300, 300, hints);
} catch (WriterException e) {
e.printStackTrace();
return null;
}
return bitMatrix;
}
}
3.使用微信短連接配接
1)為什麼要使用短連接配接?
開發者用于生成二維碼的原連結(商品、支付二維碼等)太長導緻掃碼速度和成功率下降,将原長連結通過此接口轉成短連結再生成二維碼将大大提升掃碼速度和成功率。
相應的api文檔
https://developers.weixin.qq.com/doc/offiaccount/Account_Management/URL_Shortener.html
2)擷取access_token
OkhttpUtil.java
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import okhttp3.*;
import java.io.IOException;
public class OkhttpUtil {
public static JSONObject get(String url) throws IOException {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().url(url).build();
Response response = client.newCall(request).execute();
System.out.println(response);
String responseBody = response.body().string();
JSONObject jsonObject = JSON.parseObject(responseBody);
return jsonObject;
}
public static JSONObject post(String url,String param) throws IOException {
OkHttpClient client = new OkHttpClient();
MediaType mediaType = MediaType.parse("application/json;charset=utf-8");
Request request = new Request.Builder().url(url).post(RequestBody.create(param,mediaType)).build();
Response response = client.newCall(request).execute();
System.out.println(response);
String responseBody = response.body().string();
JSONObject jsonObject = JSON.parseObject(responseBody);
return jsonObject;
}
}
WXUtil.java
import com.alibaba.fastjson.JSONObject;
import java.io.IOException;
public class WXUtil {
public static String getToken(String appId, String appSecret) throws IOException {
//通路位址
String TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";
String APPID = appId;
String APPSECRET = appSecret;
String request_url = TOKEN_URL.replace("APPID", APPID).replace("APPSECRET", APPSECRET);
JSONObject jsonObject = OkhttpUtil.get(request_url);
return jsonObject.getString("access_token");
}
public static Result wxLongUrl2Short(String appId, String appSecret, String longUrl) throws IOException {
Result result = new Result();
String token = getToken(appId, appSecret);
String uri = "https://api.weixin.qq.com/cgi-bin/shorturl?access_token=ACCESS_TOKEN";
String url = uri.replace("ACCESS_TOKEN", token);
String param = "{\"action\":\"long2short\","
+ "\"long_url\":\"" + longUrl + "\"}";
// 調用接口建立菜單
JSONObject jsonObject = OkhttpUtil.post(url, param);
System.out.println(jsonObject);
if (null != jsonObject) {
result.setCode(jsonObject.getInteger("errcode"));
result.setData(jsonObject.getString("short_url"));
return result;
} else {
return null;
}
}
}
Result.java
public class Result<T> {
private int code;
private String message;
private T data;
public Result() {
}
public Result(T data) {
this.data = data;
}
public Result(int code, T data) {
this.code = code;
this.data = data;
}
public Result(int code, String message, T data) {
this.code = code;
this.message = message;
this.data = data;
}
@Override
public String toString() {
return "Result{" +
"code='" + code + '\'' +
", message='" + message + '\'' +
", data=" + data +
'}';
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}
4.二維碼的生成
controller層
package com.dingx.qrcode.controller;
import com.dingx.qrcode.utils.CodeUtil;
import com.dingx.qrcode.utils.Result;
import com.dingx.qrcode.utils.WXUtil;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Controller
public class QRCodeController {
private static String appId;
private static String appSecret;
@Value("${AppID}")
public void setAppId(String appId) {
QRCodeController.appId = appId;
}
@Value("${AppSecret}")
public void setAppSecret(String appSecret) {
QRCodeController.appSecret = appSecret;
}
@RequestMapping("generateQRCode64")
public void generateQRCode64(HttpServletRequest request, HttpServletResponse response){
long timpStamp = System.currentTimeMillis();
try {
// 将content的資訊先進行base64編碼以避免特殊字元造成的幹擾,之後拼接目标URL
String longUrl = "輸入你需要傳入的url";
// 将目标URL轉換成短的URL
Result result = WXUtil.wxLongUrl2Short(appId, appSecret, longUrl);
// 調用二維碼生成的工具類方法,傳入短的URL,生成二維碼
BitMatrix qRcodeImg = CodeUtil.generateQRCodeStream((String) result.getData(), response);
// 将二維碼以圖檔流的形式輸出到前端
MatrixToImageWriter.writeToStream(qRcodeImg, "png", response.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
}
}
}
配置檔案的配置
AppID =yourAppid
AppSecret =yourAppsercet
5.結束
如需添加更多功能,可自行添加。這裡不多贅述。
另,代碼未進行優化。請讀者自行操作。