java生成矢量条形码二维码

本文详细介绍如何使用Java生成条形码和二维码的SVG矢量图形,包括代码实现和依赖库介绍,解决前端显示问题,提供清晰的示例代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

产品说条形码模糊,然后就生成了矢量的条形码给前端用。后面才知道前端是可以自己直接生成的。
还是记录一下
遇到一个奇怪的问题,在demo工程里面请求返回的流页面能直接显示出图形。但是在项目工程里面却返回的是xml形式的字符串。这里搞了一阵。后面无意间发现。直接返回String形式的svg文件内容,前端居然可以显示。然后后台直接返回了Sting形式给前端直接用。样式也是调好的。加了width="100%‘’方便前端控制宽度。之前直接返回流前端用不了。

参考代码

    <dependency>
            <groupId>com.google.zxing</groupId>
            <artifactId>core</artifactId>
            <version>2.2</version>
        </dependency>
        <dependency>
            <groupId>de.erichseifert.vectorgraphics2d</groupId>
            <artifactId>VectorGraphics2D</artifactId>
            <version>0.9.3</version>
        </dependency>
        <dependency>
            <groupId>net.sf.barcode4j</groupId>
            <artifactId>barcode4j</artifactId>
            <version>2.1</version>
        </dependency>


    @RequestMapping("/bar")
    @ResponseBody
    public String getbar(HttpServletResponse response,String code) {
        String res = null;
        try {
             res = BarcodeTestTools.getcode3(response,code);
             log.info("返回的结果={}",res);
             res = res.replace("<svg","<svg width=\"100%\"");
        } catch (Exception e) {
            System.out.println(e);
        }
        System.out.println("返回结果==="+res);
        return res;
    }

  public static String getcode3(HttpServletResponse response,String code) throws BarcodeCanvasSetupException, TransformerException, IOException {
        ServletOutputStream out = response.getOutputStream();
        response.reset();
        Double moduleWidth = Double.valueOf(1.0D);
        double dpi = 150;
        Double width = 5d;
        Code128Bean bean = new Code128Bean();
        String barcode = code;
        Integer barcodeLength = Integer.valueOf(barcode.length());
        if (barcodeLength.intValue() < 8)
        {
            moduleWidth = Double.valueOf(2.0D * width.doubleValue());
        }
        else if (barcodeLength.intValue() < 16)
        {
            moduleWidth = width;
        }
        if (moduleWidth.doubleValue() < 1.0D)
        {
            moduleWidth = Double.valueOf(1.0D);
        }
        bean.setModuleWidth(UnitConv.in2mm(moduleWidth.doubleValue() / dpi));
//        bean.setModuleWidth(80);
//        bean.setHeight(60);
        bean.setBarHeight(30);// 高度
//        bean.setQuietZone(10); // 向右偏移
        bean.setMsgPosition(HumanReadablePlacement.HRP_NONE);
        // 设置两侧是否加空白
        bean.doQuietZone(false);
        SVGCanvasProvider canvas = new SVGCanvasProvider(true, 0);
        bean.generateBarcode(canvas, barcode);
        DocumentFragment frag = canvas.getDOMFragment();
        TransformerFactory factory = TransformerFactory.newInstance();
        Transformer trans = factory.newTransformer();
        Source src = new DOMSource(frag);
          File tempFile = File.createTempFile("bar",".svg");
        Result res = new StreamResult(tempFile);// 入参file则写到文件里面; 这里没必要这么搞,直接StringWriter写过去就可以,参考下面更新部分         response.getOutputStream()就直接写到返回流里面
        trans.transform(src, res);
        FileReader fileReader = new FileReader(tempFile);
        BufferedReader bufferedReader = new BufferedReader(fileReader);
        StringBuilder sb = new StringBuilder();
        String line =bufferedReader.readLine();
        while (line!=null){
            System.out.println(line);
            sb.append(line);
            line = bufferedReader.readLine();

        }
        bufferedReader.close();
        fileReader.close();
        tempFile.delete();
        return sb.toString();
    }


二维码

  @RequestMapping("/qr")
    @ResponseBody
    public String jxxqr(HttpServletResponse response,String code,int size) throws IOException, WriterException {
        String res = Test.getQr(response,code,size);
        System.out.println("qr====="+res);
        return res;
    }

    public static String getQr(HttpServletResponse response,String code,int size) throws WriterException, IOException {
        double point_x = 0;
        double point_y = 0;
        final int blockSize = 1;
        SVGGraphics2D funcOld = new SVGGraphics2D(point_x, point_y, 40 * blockSize, 40 * blockSize);
        ExportQrCode.fill2VectorLine(funcOld,GetBitMatrix(code, size,ErrorCorrectionLevel.M), blockSize);

        File tempFile = File.createTempFile("bar",".svg");
        PrintStream psFile = new PrintStream(tempFile);
        psFile.append(funcOld.toString());
        psFile.close();

        FileReader fileReader = new FileReader(tempFile);
        BufferedReader bufferedReader = new BufferedReader(fileReader);
        StringBuilder sb = new StringBuilder();
        String line =bufferedReader.readLine();
        while (line!=null){
            sb.append(line);
            line = bufferedReader.readLine();
        }
        bufferedReader.close();
        fileReader.close();
        tempFile.delete();
        return sb.toString();
    }

页面
<!DOCTYPE html>
<html lang="en">
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
  <meta charset="utf-8">
  <meta name="description" content="particles.js is a lightweight JavaScript library for creating particles.">
  <meta name="author" content="Vincent Garreau" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
  <title>testsvg</title>
</head>

<style type="text/css">
    .svg-container {
        display: inline-block;
        position: relative;
        width: 100%;
        padding-bottom: 100%;
        vertical-align: middle;
        overflow: hidden;
    }
</style>
<body>

<div style="width: 100%;background-color: gray;height: 90px;">

</div>


<div style="width: 100%;height: 120px;">
    <div style="margin-left:10px;float: left;width: 45%;height:100px;background-color: #00FF00">
        <div class="svg-container" id="showbox">
        </div>
    </div>
    <div style="float: left;width: 45%;height:100px; background-color:green;margin-left: 5px; ">
        <div class="svg-container" id="showbox2" style="margin-top: -20px;">
         </div>
    </div>
</div>

<div style="height: 400px;width:100%;float: left;" data-test="写死的二维码">
    <svg version="1.2" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0mm" y="0mm" width="40mm" height="40mm" viewBox="0 0 40 40"><style type="text/css"><![CDATA[text { font:12px Dialog; }]]></style><rect x="9" y="9" width="1" height="7" style="fill:rgb(0,0,0);stroke:none" /><rect x="9" y="17" width="1" height="1" style="fill:rgb(0,0,0);stroke:none" /><rect x="9" y="21" width="1" height="1" style="fill:rgb(0,0,0);stroke:none" /><rect x="9" y="23" width="1" height="7" style="fill:rgb(0,0,0);stroke:none" /><rect x="10" y="9" width="1" height="1" style="fill:rgb(0,0,0);stroke:none" /><rect x="10" y="15" width="1" height="1" style="fill:rgb(0,0,0);stroke:none" /><rect x="10" y="19" width="1" height="1" style="fill:rgb(0,0,0);stroke:none" /><rect x="10" y="21" width="1" height="1" style="fill:rgb(0,0,0);stroke:none" /><rect x="10" y="23" width="1" height="1" style="fill:rgb(0,0,0);stroke:none" /><rect x="10" y="29" width="1" height="1" style="fill:rgb(0,0,0);stroke:none" /><rect x="11" y="9" width="1" height="1" style="fill:rgb(0,0,0);stroke:none" /><rect x="11" y="11" width="1" height="3" style="fill:rgb(0,0,0);stroke:none" /><rect x="11" y="15" width="1" height="1" style="fill:rgb(0,0,0);stroke:none" /><rect x="11" y="17" width="1" height="4" style="fill:rgb(0,0,0);stroke:none" /><rect x="11" y="23" width="1" height="1" style="fill:rgb(0,0,0);stroke:none" /><rect x="11" y="25" width="1" height="3" style="fill:rgb(0,0,0);stroke:none" /><rect x="11" y="29" width="1" height="1" style="fill:rgb(0,0,0);stroke:none" /><rect x="12" y="9" width="1" height="1" style="fill:rgb(0,0,0);stroke:none" /><rect x="12" y="11" width="1" height="3" style="fill:rgb(0,0,0);stroke:none" /><rect x="12" y="15" width="1" height="1" style="fill:rgb(0,0,0);stroke:none" /><rect x="12" y="17" width="1" height="2" style="fill:rgb(0,0,0);stroke:none" /><rect x="12" y="20" width="1" height="1" style="fill:rgb(0,0,0);stroke:none" /><rect x="12" y="23" width="1" height="1" style="fill:rgb(0,0,0);stroke:none" /><rect x="12" y="25" width="1" height="3" style="fill:rgb(0,0,0);stroke:none" /><rect x="12" y="29" width="1" height="1" style="fill:rgb(0,0,0);stroke:none" /><rect x="13" y="9" width="1" height="1" style="fill:rgb(0,0,0);stroke:none" /><rect x="13" y="11" width="1" height="3" style="fill:rgb(0,0,0);stroke:none" /><rect x="13" y="15" width="1" height="1" style="fill:rgb(0,0,0);stroke:none" /><rect x="13" y="17" width="1" height="2" style="fill:rgb(0,0,0);stroke:none" /><rect x="13" y="23" width="1" height="1" style="fill:rgb(0,0,0);stroke:none" /><rect x="13" y="25" width="1" height="3" style="fill:rgb(0,0,0);stroke:none" /><rect x="13" y="29" width="1" height="1" style="fill:rgb(0,0,0);stroke:none" /><rect x="14" y="9" width="1" height="1" style="fill:rgb(0,0,0);stroke:none" /><rect x="14" y="15" width="1" height="1" style="fill:rgb(0,0,0);stroke:none" /><rect x="14" y="17" width="1" height="1" style="fill:rgb(0,0,0);stroke:none" /><rect x="14" y="19" width="1" height="3" style="fill:rgb(0,0,0);stroke:none" /><rect x="14" y="23" width="1" height="1" style="fill:rgb(0,0,0);stroke:none" /><rect x="14" y="29" width="1" height="1" style="fill:rgb(0,0,0);stroke:none" /><rect x="15" y="9" width="1" height="7" style="fill:rgb(0,0,0);stroke:none" /><rect x="15" y="17" width="1" height="1" style="fill:rgb(0,0,0);stroke:none" /><rect x="15" y="19" width="1" height="1" style="fill:rgb(0,0,0);stroke:none" /><rect x="15" y="21" width="1" height="1" style="fill:rgb(0,0,0);stroke:none" /><rect x="15" y="23" width="1" height="7" style="fill:rgb(0,0,0);stroke:none" /><rect x="16" y="20" width="1" height="1" style="fill:rgb(0,0,0);stroke:none" /><rect x="17" y="11" width="1" height="6" style="fill:rgb(0,0,0);stroke:none" /><rect x="17" y="18" width="1" height="3" style="fill:rgb(0,0,0);stroke:none" /><rect x="17" y="22" width="1" height="1" style="fill:rgb(0,0,0);stroke:none" /><rect x="17" y="24" width="1" height="4" style="fill:rgb(0,0,0);stroke:none" /><rect x="17" y="29" width="1" height="1" style="fill:rgb(0,0,0);stroke:none" /><rect x="18" y="10" width="1" height="1" style="fill:rgb(0,0,0);stroke:none" /><rect x="18" y="13" width="1" height="2" style="fill:rgb(0,0,0);stroke:none" /><rect x="18" y="17" width="1" height="2" style="fill:rgb(0,0,0);stroke:none" /><rect x="18" y="20" width="1" height="1" style="fill:rgb(0,0,0);stroke:none" /><rect x="18" y="25" width="1" height="5" style="fill:rgb(0,0,0);stroke:none" /><rect x="19" y="10" width="1" height="2" style="fill:rgb(0,0,0);stroke:none" /><rect x="19" y="13" width="1" height="1" style="fill:rgb(0,0,0);stroke:none" /><rect x="19" y="15" width="1" height="1" style="fill:rgb(0,0,0);stroke:none" /><rect x="19" y="18" width="1" height="2" style="fill:rgb(0,0,0);stroke:none" /><rect x="19" y="21" width="1" height="3" style="fill:rgb(0,0,0);stroke:none" /><rect x="19" y="25" width="1" height="1" style="fill:rgb(0,0,0);stroke:none" /><rect x="19" y="27" width="1" height="1" style="fill:rgb(0,0,0);stroke:none" /><rect x="20" y="9" width="1" height="2" style="fill:rgb(0,0,0);stroke:none" /><rect x="20" y="14" width="1" height="1" style="fill:rgb(0,0,0);stroke:none" /><rect x="20" y="17" width="1" height="2" style="fill:rgb(0,0,0);stroke:none" /><rect x="20" y="20" width="1" height="1" style="fill:rgb(0,0,0);stroke:none" /><rect x="20" y="23" width="1" height="1" style="fill:rgb(0,0,0);stroke:none" /><rect x="20" y="25" width="1" height="2" style="fill:rgb(0,0,0);stroke:none" /><rect x="20" y="28" width="1" height="1" style="fill:rgb(0,0,0);stroke:none" /><rect x="21" y="10" width="1" height="1" style="fill:rgb(0,0,0);stroke:none" /><rect x="21" y="12" width="1" height="2" style="fill:rgb(0,0,0);stroke:none" /><rect x="21" y="15" width="1" height="1" style="fill:rgb(0,0,0);stroke:none" /><rect x="21" y="18" width="1" height="5" style="fill:rgb(0,0,0);stroke:none" /><rect x="21" y="26" width="1" height="4" style="fill:rgb(0,0,0);stroke:none" /><rect x="22" y="18" width="1" height="1" style="fill:rgb(0,0,0);stroke:none" /><rect x="22" y="20" width="1" height="1" style="fill:rgb(0,0,0);stroke:none" /><rect x="22" y="23" width="1" height="1" style="fill:rgb(0,0,0);stroke:none" /><rect x="22" y="25" width="1" height="2" style="fill:rgb(0,0,0);stroke:none" /><rect x="22" y="28" width="1" height="1" style="fill:rgb(0,0,0);stroke:none" /><rect x="23" y="9" width="1" height="7" style="fill:rgb(0,0,0);stroke:none" /><rect x="23" y="17" width="1" height="4" style="fill:rgb(0,0,0);stroke:none" /><rect x="23" y="26" width="1" height="3" style="fill:rgb(0,0,0);stroke:none" /><rect x="24" y="9" width="1" height="1" style="fill:rgb(0,0,0);stroke:none" /><rect x="24" y="15" width="1" height="1" style="fill:rgb(0,0,0);stroke:none" /><rect x="24" y="17" width="1" height="1" style="fill:rgb(0,0,0);stroke:none" /><rect x="24" y="19" width="1" height="1" style="fill:rgb(0,0,0);stroke:none" /><rect x="24" y="21" width="1" height="2" style="fill:rgb(0,0,0);stroke:none" /><rect x="24" y="24" width="1" height="1" style="fill:rgb(0,0,0);stroke:none" /><rect x="24" y="27" width="1" height="1" style="fill:rgb(0,0,0);stroke:none" /><rect x="24" y="29" width="1" height="1" style="fill:rgb(0,0,0);stroke:none" /><rect x="25" y="9" width="1" height="1" style="fill:rgb(0,0,0);stroke:none" /><rect x="25" y="11" width="1" height="3" style="fill:rgb(0,0,0);stroke:none" /><rect x="25" y="15" width="1" height="1" style="fill:rgb(0,0,0);stroke:none" /><rect x="25" y="17" width="1" height="1" style="fill:rgb(0,0,0);stroke:none" /><rect x="25" y="23" width="1" height="3" style="fill:rgb(0,0,0);stroke:none" /><rect x="26" y="9" width="1" height="1" style="fill:rgb(0,0,0);stroke:none" /><rect x="26" y="11" width="1" height="3" style="fill:rgb(0,0,0);stroke:none" /><rect x="26" y="15" width="1" height="1" style="fill:rgb(0,0,0);stroke:none" /><rect x="26" y="17" width="1" height="3" style="fill:rgb(0,0,0);stroke:none" /><rect x="26" y="26" width="1" height="1" style="fill:rgb(0,0,0);stroke:none" /><rect x="26" y="28" width="1" height="1" style="fill:rgb(0,0,0);stroke:none" /><rect x="27" y="9" width="1" height="1" style="fill:rgb(0,0,0);stroke:none" /><rect x="27" y="11" width="1" height="3" style="fill:rgb(0,0,0);stroke:none" /><rect x="27" y="15" width="1" height="1" style="fill:rgb(0,0,0);stroke:none" /><rect x="27" y="17" width="1" height="2" style="fill:rgb(0,0,0);stroke:none" /><rect x="27" y="20" width="1" height="1" style="fill:rgb(0,0,0);stroke:none" /><rect x="27" y="22" width="1" height="4" style="fill:rgb(0,0,0);stroke:none" /><rect x="27" y="29" width="1" height="1" style="fill:rgb(0,0,0);stroke:none" /><rect x="28" y="9" width="1" height="1" style="fill:rgb(0,0,0);stroke:none" /><rect x="28" y="15" width="1" height="1" style="fill:rgb(0,0,0);stroke:none" /><rect x="28" y="18" width="1" height="1" style="fill:rgb(0,0,0);stroke:none" /><rect x="28" y="20" width="1" height="2" style="fill:rgb(0,0,0);stroke:none" /><rect x="28" y="24" width="1" height="1" style="fill:rgb(0,0,0);stroke:none" /><rect x="28" y="28" width="1" height="1" style="fill:rgb(0,0,0);stroke:none" /><rect x="29" y="9" width="1" height="7" style="fill:rgb(0,0,0);stroke:none" /><rect x="29" y="18" width="1" height="3" style="fill:rgb(0,0,0);stroke:none" /><rect x="29" y="23" width="1" height="1" style="fill:rgb(0,0,0);stroke:none" /></svg>
</div>
<!-- scripts -->
<script th:src="@{/js/particles.js}"></script>
<script th:src="@{/js/app.js}"></script>
<script th:src="@{/js/jquery-3.4.1.min.js}"></script>
<script th:src="@{/js/layui/layui.js}"></script>
<script>

    $(function(){
        var ctxPath  = [[@{/}]];
        var ctxPath=[[${#httpServletRequest.getContextPath()}]]/;

        $.get(ctxPath +"/ban/qr?code=123456&size=40", function(result2){
            console.log(result2);
            $("#showbox2").html(result2);
        });
        $.get(ctxPath +"/ban/bar3?code=123456789", function(result){
            console.log(result);
            $("#showbox").html(result);
        });
    });

 </script>
</body>
</html>

2021-07-16 14:21:17 更新
优惠券换新版了,用矢量二维码和条形码。把之前的代码整理了一下。矢量的优点是随意放大不失真。这就很棒了!

实验发现,使用上面生成的二维码会出现白线,类似打印机坏了,一个像素没打印一样。
在这里插入图片描述
类似这种 谷歌找了一下,换了种方式后没有这个问题了 记录一下 生成的二维码很干净

另外值得注意的是 response.getOutputStream()不需要手动关闭。在servlet运行完毕时自动flush和close

 package com.mb.sleep.sleep.utils;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitArray;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import org.krysalis.barcode4j.HumanReadablePlacement;
import org.krysalis.barcode4j.impl.code128.Code128Bean;
import org.krysalis.barcode4j.output.BarcodeCanvasSetupException;
import org.krysalis.barcode4j.output.svg.SVGCanvasProvider;
import org.krysalis.barcode4j.tools.UnitConv;
import org.w3c.dom.DocumentFragment;

import javax.servlet.http.HttpServletResponse;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.IOException;
import java.io.StringWriter;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

public class BarQrCodeService {

    /**
     * 条形码
     *
     * @param code
     * @return
     * @throws BarcodeCanvasSetupException
     * @throws TransformerException
     * @throws IOException
     */
    public static String getBarCodeSVGStr(String code) throws Exception {
        Double moduleWidth = Double.valueOf(1.0D);
        //分辨率
        double dpi = 300;
        Double width = 6d;
        Code128Bean bean = new Code128Bean();
        String barcode = code;
        Integer barcodeLength = Integer.valueOf(barcode.length());
        if (barcodeLength.intValue() < 8) {
            moduleWidth = Double.valueOf(2.0D * width.doubleValue());
        } else if (barcodeLength.intValue() < 16) {
            moduleWidth = width;
        }
        if (moduleWidth.doubleValue() < 1.0D) {
            moduleWidth = Double.valueOf(1.0D);
        }
        bean.setModuleWidth(UnitConv.in2mm(moduleWidth.doubleValue() / dpi));
        bean.setBarHeight(30);// 高度
        bean.setQuietZone(60); // 向右偏移
        bean.setMsgPosition(HumanReadablePlacement.HRP_NONE);
        // 设置两侧是否加空白
        bean.doQuietZone(false);
        SVGCanvasProvider canvas = new SVGCanvasProvider(true, 0);
        bean.generateBarcode(canvas, barcode);
        DocumentFragment frag = canvas.getDOMFragment();
        TransformerFactory factory = TransformerFactory.newInstance();
        Transformer trans = factory.newTransformer();
        Source src = new DOMSource(frag);
        StringWriter outw = new StringWriter();
        trans.transform(src, new StreamResult(outw));
        return outw.toString();
    }

    /**
     * 条形码写流
     * @param response
     * @param code
     * @throws BarcodeCanvasSetupException
     * @throws TransformerException
     * @throws IOException
     */
    public static void getBarCodeSVGStrOut(HttpServletResponse response, String code) throws Exception {
        Double moduleWidth = Double.valueOf(1.0D);
        //分辨率
        double dpi = 300;
        Double width = 6d;
        Code128Bean bean = new Code128Bean();
        String barcode = code;
        Integer barcodeLength = Integer.valueOf(barcode.length());
        if (barcodeLength.intValue() < 8) {
            moduleWidth = Double.valueOf(2.0D * width.doubleValue());
        } else if (barcodeLength.intValue() < 16) {
            moduleWidth = width;
        }
        if (moduleWidth.doubleValue() < 1.0D) {
            moduleWidth = Double.valueOf(1.0D);
        }
        bean.setModuleWidth(UnitConv.in2mm(moduleWidth.doubleValue() / dpi));
        bean.setBarHeight(30);// 高度
        bean.setQuietZone(60); // 向右偏移
        bean.setMsgPosition(HumanReadablePlacement.HRP_NONE);
        // 设置两侧是否加空白
        bean.doQuietZone(false);
        SVGCanvasProvider canvas = new SVGCanvasProvider(true, 0);
        bean.generateBarcode(canvas, barcode);
        DocumentFragment frag = canvas.getDOMFragment();
        TransformerFactory factory = TransformerFactory.newInstance();
        Transformer trans = factory.newTransformer();
        Source src = new DOMSource(frag);
        trans.transform(src, new StreamResult(response.getOutputStream()));
    }

    /**
     * 二维码
     *
     * @param code
     * @param size
     * @return
     * @throws WriterException
     * @throws IOException
     */
    public static String getqrSVGStr(String code, int size) throws Exception {
        return createQRStr(code,size);
    }

    /**
     * 二维码 写流
     *
     * @param response
     * @param code
     * @param size
     * @return
     * @throws WriterException
     * @throws IOException
     */
    public static void getqrSVGStrOut(HttpServletResponse response, String code, int size) throws Exception {
        response.getOutputStream().write(createQRStr(code,size).getBytes(StandardCharsets.UTF_8));
    }

    /**
     * 生成svg字符串
     * @param code
     * @param size
     * @return
     * @throws Exception
     */
    private static String createQRStr(String code, int size) throws Exception {
        QRCodeWriter qrCodeWriter = new QRCodeWriter();
        Map<EncodeHintType, Object> hints = new HashMap<>();
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.L);
        hints.put(EncodeHintType.CHARACTER_SET, StandardCharsets.UTF_8.name());
        BitMatrix bitMatrix = qrCodeWriter.encode(code, BarcodeFormat.QR_CODE, size, size, hints);
        StringBuilder sbPath = new StringBuilder();
        int width = bitMatrix.getWidth();
        int height = bitMatrix.getHeight();
        BitArray row = new BitArray(width);
        for (int y = 0; y < height; ++y) {
            row = bitMatrix.getRow(y, row);
            for (int x = 0; x < width; ++x) {
                if (row.get(x)) {
                    sbPath.append(" M" + x + "," + y + "h1v1h-1z");
                }
            }
        }
        StringBuilder sb = new StringBuilder();
        sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
        sb.append("<svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" viewBox=\"0 0 ").append(width).append(" ").append(height).append("\" stroke=\"none\">\n");
        sb.append("<style type=\"text/css\">\n");
        sb.append(".black {fill:#000000;}\n");
        sb.append("</style>\n");
        sb.append("<path class=\"black\"  d=\"").append(sbPath).append("\"/>\n");
        sb.append("</svg>\n");
        return sb.toString();
    }

}

需要的依赖 

<!--zxing二维码生成 -->
<dependency>
    <groupId>com.google.zxing</groupId>
    <artifactId>core</artifactId>
    <version>3.3.1</version>
</dependency>
<dependency>
    <groupId>com.google.zxing</groupId>
    <artifactId>javase</artifactId>
    <version>3.2.1</version>
</dependency>
<dependency>
    <groupId>de.erichseifert.vectorgraphics2d</groupId>
    <artifactId>VectorGraphics2D</artifactId>
    <version>0.9.3</version>
</dependency>
<dependency>
    <groupId>net.sf.barcode4j</groupId>
    <artifactId>barcode4j</artifactId>
    <version>2.1</version>
</dependency>
<dependency>
    <groupId>de.erichseifert.vectorgraphics2d</groupId>
    <artifactId>VectorGraphics2D</artifactId>
    <version>0.9.3</version>
</dependency>


<think>我们正在回答用户的问题:如何在Java项目中正确集成ZXing库以生成二维码 根据引用[2]和引用[4],我们知道ZXing是一个开源的Java条码处理库,支持二维码生成与解析。 集成步骤通常包括: 1. 导入ZXing库(通过Maven或Gradle) 2. 编写生成二维码的代码 我们参考引用[3]和引用[4]中的依赖配置,但注意版本号可能不同,这里选择较新的稳定版本(如3.5.2或3.5.3) 由于用户没有指定构建工具,我们以Maven为例。 步骤: 1. 在pom.xml中添加依赖 2. 编写生成二维码的工具类 3. 测试生成二维码 注意:引用[3]中同时使用了OpenCV,但用户问题只要求生成二维码,所以只需ZXing的核心库和javase(用于生成图片)即可。 具体实现: 我们将创建一个工具类,提供生成二维码图片的方法,可以指定内容、宽度、高度、图片格式(如PNG)等。 另外,引用[1]提到支持自定义二维码,我们可以通过设置二维码的参数(如纠错级别、边距等)来实现。 代码示例: 我们将使用MultiFormatWriter来生成二维码,并写入到BufferedImage中,然后输出为文件。 考虑到用户可能需要在不同场景使用,我们提供生成到文件和生成字节数组两种方式。 根据以上思路,我们给出详细步骤。</think>### 在Java项目中集成ZXing生成二维码的完整指南 #### 步骤1:添加Maven依赖 在项目的`pom.xml`文件中添加以下依赖: ```xml <dependencies> <!-- ZXing核心库 --> <dependency> <groupId>com.google.zxing</groupId> <artifactId>core</artifactId> <version>3.5.2</version> </dependency> <!-- 图像处理支持 --> <dependency> <groupId>com.google.zxing</groupId> <artifactId>javase</artifactId> <version>3.5.2</version> </dependency> </dependencies> ``` **注意**:版本号可参考最新稳定版更新[^2][^4] #### 步骤2:创建二维码生成工具类 ```java import com.google.zxing.BarcodeFormat; import com.google.zxing.EncodeHintType; import com.google.zxing.MultiFormatWriter; import com.google.zxing.common.BitMatrix; import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel; import javax.imageio.ImageIO; import java.awt.image.BufferedImage; import java.io.File; import java.util.HashMap; import java.util.Map; public class QRCodeGenerator { public static void generateQRCode(String content, int width, int height, String filePath) throws Exception { Map<EncodeHintType, Object> hints = new HashMap<>(); hints.put(EncodeHintType.CHARACTER_SET, "UTF-8"); // 中文支持 hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H); // 纠错级别 hints.put(EncodeHintType.MARGIN, 1); // 二维码边距 // 生成二维码矩阵 BitMatrix bitMatrix = new MultiFormatWriter().encode( content, BarcodeFormat.QR_CODE, width, height, hints ); // 转换为BufferedImage BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { image.setRGB(x, y, bitMatrix.get(x, y) ? 0xFF000000 : 0xFFFFFFFF); } } // 保存为图片文件 ImageIO.write(image, "png", new File(filePath)); } } ``` #### 步骤3:调用生成方法 ```java public class Main { public static void main(String[] args) { try { // 生成包含URL的二维码 QRCodeGenerator.generateQRCode( "https://example.com", 300, 300, "qrcode.png" ); System.out.println("二维码生成成功!"); } catch (Exception e) { e.printStackTrace(); } } } ``` #### 关键参数说明 1. **纠错级别**(通过`ErrorCorrectionLevel`设置): - `L`:可恢复7%的数据 - `M`:可恢复15%的数据(默认) - `Q`:可恢复25%的数据 - `H`:可恢复30%的数据[^1] 2. **自定义选项**: ```java // 设置Logo(示例代码片段) Graphics2D graphics = image.createGraphics(); graphics.drawImage(logoImage, width/2-30, height/2-30, 60, 60, null); graphics.dispose(); ``` 3. **内容类型支持**: - 文本、URL、vCard联系人、WiFi配置等 - 示例:`WIFI:S:MyNetwork;T:WPA;P:MyPassword;;` #### 常见问题解决 1. **中文乱码**:确保设置`CHARACTER_SET`为`UTF-8` 2. **依赖冲突**:检查是否有旧版本ZXing依赖 3. **图片模糊**:增加分辨率(最小推荐300×300像素) #### 生成效果优化建议 1. 添加中心Logo时保持纠错级别为`H` 2. 深色背景使用浅色前景色:`image.setRGB(x, y, bitMatrix.get(x, y) ? 0xFFFFFFFF : 0xFF000000)` 3. 生成矢量图格式(SVG)可使用`com.google.zxing:javase`的`SVG`渲染器 > 提示:在Spring Boot项目中,可将二维码生成封装为REST接口直接输出图片流[^1][^4]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值