利用google的開源庫
zxing
來實現二維碼的生成,並實際修復一些常見的問題java
項目地址: http://git.oschina.net/liuyueyi/quicksilvergit
二維碼生成,採用如今用得比較多的開源框架
Zxing
api
既然都不是本身來生成二維碼了,爲何要作這個東西呢? 我要生成二維碼直接用官方的api不就好了,你這個不是化蛇添足麼!!!安全
- 官方的接入比較麻煩,特別是你想定製生成個性化的二維碼時,須要瞭解到zxing內部的一些設置參數,這個工具則下降了這些成本,與zxing打交道的配置都有它來作,對外暴露一些友好的,易懂的參數配置 - 實現對實際二維碼生成工具的解耦,假設zxing被爆出了什麼安全漏洞,這裏進行切換別的框架相對成本更低 - 個性化的定製 (如加logo)
目標app
- 最開始是但願設計個通用的,與具體的二維碼生成工具解耦(即做爲一個適配器層),實際上沒這麼玩... - 制定對外暴露的配置項,用戶根據須要設置二維碼生成的參數,生成二維碼 - 即對用戶而言,就兩部,設置參數, 生成二維碼, 總得交互就兩個接口
設計框架
- 設置參數採用builder模式, 生成配置項 - 一個適配層,將配置項適配爲zxing的二維碼生成參數 - 實際的處理層,生成二維碼 - 輸出層,能夠根據需求選擇輸出方式(輸出爲stream, 文件, bufferedImage)
配置參數工具
約定二維碼生成的參數以下測試
/** * The message to put into QrCode */ private String msg; /** * qrcode center logo */ private String logo; /** * qrcode image width */ private Integer w; /** * qrcode image height */ private Integer h; /** * qrcode bgcolor, default white */ private Integer offColor; /** * qrcode msg color, default black */ private Integer onColor; /** * qrcode message's code, default UTF-8 */ private String code; /** * 0 - 4 */ private Integer padding; /** * error level, default H */ private ErrorCorrectionLevel errorCorrection; /** * output qrcode image type, default png */ private String picType; ``` - 二維碼生成 生成二維碼核心代碼 `QRCode code = Encoder.encode(qrCodeConfig.getMsg(), errorCorrectionLevel, qrCodeConfig.getHints());` 生成的code中, 就包含了二維碼矩陣, 剩下的就是將矩陣渲染輸出的問題, 輸出沒什麼好說的,這裏指出一點原生的zxing生成二維碼的白邊可能特別大,本工具類內部作了兼容,[點我查看大白邊修復指南](https://my.oschina.net/u/566591/blog/872770) ```java /** * 對 zxing 的 QRCodeWriter 進行擴展, 解決白邊過多的問題 * <p/> * 源碼參考 {@link com.google.zxing.qrcode.QRCodeWriter#encode(String, BarcodeFormat, int, int, Map)} */ private static BitMatrix encode(QrCodeConfig qrCodeConfig) throws WriterException { ErrorCorrectionLevel errorCorrectionLevel = ErrorCorrectionLevel.L; int quietZone = 1; if (qrCodeConfig.getHints() != null) { if (qrCodeConfig.getHints().containsKey(EncodeHintType.ERROR_CORRECTION)) { errorCorrectionLevel = ErrorCorrectionLevel.valueOf(qrCodeConfig.getHints().get(EncodeHintType.ERROR_CORRECTION).toString()); } if (qrCodeConfig.getHints().containsKey(EncodeHintType.MARGIN)) { quietZone = Integer.parseInt(qrCodeConfig.getHints().get(EncodeHintType.MARGIN).toString()); } if (quietZone > QUIET_ZONE_SIZE) { quietZone = QUIET_ZONE_SIZE; } else if (quietZone < 0) { quietZone = 0; } } QRCode code = Encoder.encode(qrCodeConfig.getMsg(), errorCorrectionLevel, qrCodeConfig.getHints()); return renderResult(code, qrCodeConfig.getW(), qrCodeConfig.getH(), quietZone); } ``` ## 3. 使用說明 寫完了就要開始實際用,寫了個測試類,貼出以下 ```java /** * 測試二維碼 */ @Test public void testGenQrCode() { String msg = "create qrcode!!!"; // 簡單的生成 QrCodeConfig qrCodeConfig = QrCodeGenWrapper.createQrCodeConfig() .setMsg(msg) .build(); try { boolean ans = QrCodeGenWrapper.asFile(qrCodeConfig, "qrcode/gen.png"); System.out.println(ans); } catch (Exception e) { System.out.println("create qrcode error! e: " + e); Assert.assertTrue(false); } //生成紅色的二維碼 300x300, 無邊框 try { boolean ans = QrCodeGenWrapper.createQrCodeConfig() .setMsg(msg) .setW(300) .setOnColor(0xffff0000) .setOffColor(0xffffffff) .setPadding(0) .asFile("qrcode/gen_300x300.png"); System.out.println(ans); } catch (Exception e) { System.out.println("create qrcode error! e: " + e); Assert.assertTrue(false); } // 生成帶logo的二維碼 try { String logo = "https://git.oschina.net/uploads/34/2334_liuyueyi.png"; boolean ans = QrCodeGenWrapper.createQrCodeConfig() .setMsg(msg) .setW(300) .setOnColor(0xffff0000) .setOffColor(0xffffffff) .setPadding(0) .setLogo(logo) .asFile("qrcode/gen_300x300_logo.png"); System.out.println(ans); } catch (Exception e) { System.out.println("create qrcode error! e: " + e); Assert.assertTrue(false); } // 根據本地文件生成待logo的二維碼 try { String logo = "qrcode/logo.png"; boolean ans = QrCodeGenWrapper.createQrCodeConfig() .setMsg(msg) .setW(300) .setOnColor(0xffff0000) .setOffColor(0xffffffff) .setPadding(0) .setLogo(logo) .asFile("qrcode/gen_300x300_logo_v2.png"); System.out.println(ans); } catch (Exception e) { System.out.println("create qrcode error! e: " + e); Assert.assertTrue(false); } }
從上面能夠看出,實際用的時候有兩種方式,沒什麼特別的,看本身需求選擇使用 - 先生成配置項, 而後根據配置項生成二維碼 - 設置參數,而後直接調用build的生成二維碼方法ui