在警报声中学习

使用java实现生成及打印条形码

使用的依赖

<dependency>
    <groupId>com.google.zxing</groupId>
    <artifactId>core</artifactId>
    <version>${zxing.code.version}</version>  (3.3.3)
</dependency>

<dependency>
    <groupId>com.google.zxing</groupId>
    <artifactId>javase</artifactId>
    <version>${zxing.javase.version}</version>  (3.3.3)
</dependency>

生成条形码的工具类

import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.Writer;
import com.google.zxing.WriterException;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.oned.Code128Writer;
import com.google.zxing.pdf417.PDF417Writer;
import org.apache.commons.lang3.StringUtils;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.HashMap;
import java.util.Map;

/**
 * @Description: 条形码工具类
 * @since:
 */
public class BarCodeUtils {
    /**
     * 默认图片宽度
     */
    private static final int DEFAULT_PICTURE_WIDTH = 400;

    /**
     * 默认图片高度
     */
    private static final int DEFAULT_PICTURE_HEIGHT = 200;

    /**
     * 默认条形码宽度
     */
    private static final int DEFAULT_BAR_CODE_WIDTH = 400;

    /**
     * 默认条形码高度
     */
    private static final int DEFAULT_BAR_CODE_HEIGHT = 100;

    /**
     * 默认字体大小
     */
    private static final int DEFAULT_FONT_SIZE = 15;


    /**
     * 设置 条形码参数
     */
    private static final Map<EncodeHintType, Object> hints = new HashMap<>();

    static {
        hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
    }

    /**
     * 获取条形码图片
     *
     * @param codeValue 条形码内容
     * @return 条形码图片
     */
    public static BufferedImage getBarCodeImage(String codeValue) {
        return getBarCodeImage(codeValue, DEFAULT_BAR_CODE_WIDTH, DEFAULT_BAR_CODE_HEIGHT);
    }

    /**
     * 获取条形码图片
     *
     * @param codeValue 条形码内容
     * @param width     宽度
     * @param height    高度
     * @return 条形码图片
     */
    public static BufferedImage getBarCodeImage(String codeValue, int width, int height) {
        // CODE_128是最常用的条形码格式
        return getBarCodeImage(codeValue, width, height, BarcodeFormat.CODE_128);
    }

    /**
     * 获取条形码图片
     *
     * @param codeValue     条形码内容
     * @param width         宽度
     * @param height        高度
     * @param barcodeFormat 条形码编码格式
     * @return 条形码图片
     */
    public static BufferedImage getBarCodeImage(String codeValue, int width, int height, BarcodeFormat barcodeFormat) {
        Writer writer;
        switch (barcodeFormat) {
            case CODE_128:
                // 最常见的条形码,但是不支持中文
                writer = new Code128Writer();
                break;
            case PDF_417:
                // 支持中文的条形码格式
                writer = new PDF417Writer();
                break;
            // 如果使用到其他格式,可以在这里添加
            default:
                writer = new Code128Writer();
        }

        // 编码内容, 编码类型, 宽度, 高度, 设置参数
        BitMatrix bitMatrix;
        try {
            bitMatrix = writer.encode(codeValue, barcodeFormat, width, height, hints);
        } catch (WriterException e) {
            throw new RuntimeException("条形码内容写入失败");
        }
        return MatrixToImageWriter.toBufferedImage(bitMatrix);
    }

    /**
     * 获取条形码
     *
     * @param codeValue 条形码内容
     * @param bottomStr 底部文字
     * @return
     */
    public static BufferedImage getBarCodeWithWords(String codeValue, String bottomStr) {
        return getBarCodeWithWords(codeValue, bottomStr, "", "", "");
    }

    /**
     * 获取条形码
     *
     * @param codeValue   条形码内容
     * @param bottomStr   底部文字
     * @param topLeftStr  左上角文字
     * @param topRightStr 右上角文字
     * @return
     */
    public static BufferedImage getBarCodeWithWords(String codeValue,
                                                    String bottomStr,
                                                    String bottomStr2,
                                                    String topLeftStr,
                                                    String topRightStr) {
        return getCodeWithWords(getBarCodeImage(codeValue),
                bottomStr,
                bottomStr2,
                topLeftStr,
                topRightStr,
                DEFAULT_PICTURE_WIDTH,
                DEFAULT_PICTURE_HEIGHT,
                0,
                -20,
                0,
                0,
                0,
                0,
                DEFAULT_FONT_SIZE);
    }

    /**
     * 获取条形码
     *
     * @param codeImage       条形码图片
     * @param firstBottomStr  底部文字首行
     * @param secondBottomStr 底部文字次行
     * @param topLeftStr      左上角文字
     * @param topRightStr     右上角文字
     * @param pictureWidth    图片宽度
     * @param pictureHeight   图片高度
     * @param codeOffsetX     条形码宽度
     * @param codeOffsetY     条形码高度
     * @param topLeftOffsetX  左上角文字X轴偏移量
     * @param topLeftOffsetY  左上角文字Y轴偏移量
     * @param topRightOffsetX 右上角文字X轴偏移量
     * @param topRightOffsetY 右上角文字Y轴偏移量
     * @param fontSize        字体大小
     * @return 条形码图片
     */
    public static BufferedImage getCodeWithWords(BufferedImage codeImage,
                                                 String firstBottomStr,
                                                 String secondBottomStr,
                                                 String topLeftStr,
                                                 String topRightStr,
                                                 int pictureWidth,
                                                 int pictureHeight,
                                                 int codeOffsetX,
                                                 int codeOffsetY,
                                                 int topLeftOffsetX,
                                                 int topLeftOffsetY,
                                                 int topRightOffsetX,
                                                 int topRightOffsetY,
                                                 int fontSize) {
        BufferedImage picImage = new BufferedImage(pictureWidth, pictureHeight, BufferedImage.TYPE_INT_RGB);

        Graphics2D g2d = picImage.createGraphics();
        // 抗锯齿
        setGraphics2D(g2d);
        // 设置白色
        setColorWhite(g2d, picImage.getWidth(), picImage.getHeight());

        // 条形码默认居中显示
        int codeStartX = (pictureWidth - codeImage.getWidth()) / 2 + codeOffsetX;
        int codeStartY = (pictureHeight - codeImage.getHeight()) / 2 + codeOffsetY;
        // 画条形码到新的面板
        g2d.drawImage(codeImage, codeStartX, codeStartY, codeImage.getWidth(), codeImage.getHeight(), null);

        // 画文字到新的面板
        g2d.setColor(Color.BLACK);
        // 字体、字型、字号
        g2d.setFont(new Font("微软雅黑", Font.PLAIN, fontSize));
        // 文字与条形码之间的间隔
        int wordAndCodeSpacing1 = 0;

        if (StringUtils.isNotEmpty(firstBottomStr)) {
            // 文字长度
            int strWidth = g2d.getFontMetrics().stringWidth(firstBottomStr);
            // 文字X轴开始坐标,这里是居中
            int strStartX = codeStartX + (codeImage.getWidth() - strWidth) / 2;
            // 文字Y轴开始坐标
            int strStartY = codeStartY + codeImage.getHeight() + fontSize + wordAndCodeSpacing1;
            // 画文字
            g2d.drawString(firstBottomStr, strStartX, strStartY);
        }

        // 文字与条形码之间的间隔
        int wordAndCodeSpacing2 = 30;

        if (StringUtils.isNotEmpty(secondBottomStr)) {
            // 文字长度
            int strWidth = g2d.getFontMetrics().stringWidth(secondBottomStr);
            // 文字X轴开始坐标,这里是居中
            int strStartX = codeStartX + (codeImage.getWidth() - strWidth) / 2;
            // 文字Y轴开始坐标
            int strStartY = codeStartY + codeImage.getHeight() + fontSize + wordAndCodeSpacing2;
            // 画文字
            g2d.drawString(secondBottomStr, strStartX, strStartY);
        }

        if (StringUtils.isNotEmpty(topLeftStr)) {
            // 文字长度
            int strWidth = g2d.getFontMetrics().stringWidth(topLeftStr);
            // 文字X轴开始坐标
            int strStartX = codeStartX + topLeftOffsetX;
            // 文字Y轴开始坐标
            int strStartY = codeStartY + topLeftOffsetY - wordAndCodeSpacing1;
            // 画文字
            g2d.drawString(topLeftStr, strStartX, strStartY);
        }

        if (StringUtils.isNotEmpty(topRightStr)) {
            // 文字长度
            int strWidth = g2d.getFontMetrics().stringWidth(topRightStr);
            // 文字X轴开始坐标,这里是居中
            int strStartX = codeStartX + codeImage.getWidth() - strWidth + topRightOffsetX;
            // 文字Y轴开始坐标
            int strStartY = codeStartY + topRightOffsetY - wordAndCodeSpacing1;
            // 画文字
            g2d.drawString(topRightStr, strStartX, strStartY);
        }

        g2d.dispose();
        picImage.flush();

        return picImage;
    }

    /**
     * 设置 Graphics2D 属性  (抗锯齿)
     *
     * @param g2d Graphics2D提供对几何形状、坐标转换、颜色管理和文本布局更为复杂的控制
     */
    private static void setGraphics2D(Graphics2D g2d) {
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_DEFAULT);
        Stroke s = new BasicStroke(1, BasicStroke.CAP_ROUND, BasicStroke.JOIN_MITER);
        g2d.setStroke(s);
    }

    /**
     * 设置背景为白色
     *
     * @param g2d Graphics2D提供对几何形状、坐标转换、颜色管理和文本布局更为复杂的控制
     */
    private static void setColorWhite(Graphics2D g2d, int width, int height) {
        g2d.setColor(Color.WHITE);
        //填充整个屏幕
        g2d.fillRect(0, 0, width, height);
        //设置笔刷
        g2d.setColor(Color.BLACK);
    }

}




测试

public static void getBarcode(String xxx) {
    
    
	InputStream inputStream = null;
    ByteArrayOutputStream os = null;
    try {
        log.info(Log.op(op).msg("开始转化条形码").kv("xxx", xxx).toString());
        BufferedImage image = BarCodeUtils.getBarCodeWithWords(xxx,
                                                               xxx, "", "");
        os = new ByteArrayOutputStream();
        // 转入输出流
        ImageIO.write(image, "png", os);
       
        // 直接导出到本地
        // ImageIO.write(image, "jpg", new File("D://AAAA.jpg"));
        inputStream = new ByteArrayInputStream(os.toByteArray());
        log.info(Log.op(op).msg("条形码转化结束").toString());
    } catch (Exception e) {
        throw MallExceptionCode.IO_ERROR.exp(e);
    } finally {
        if (inputStream != null) {
            try {
                inputStream.close();
            } catch (IOException e) {
            }
        }

        if (os != null) {
            try {
                os.close();
            } catch (IOException e) {
            }
        }
    }
}



补充

在本地跑的时候, 条形码下方的中文可以正常显示, 但是在服务器上不行, 中文会出现乱码, 原因是Linux系统上的jdk安装包下没有对应的字体

解决方案: 
可以将本地C:\Windows\Fonts目录下的字体安装到Linux中的/jre/lib/fonts 路径中添加字体支持,如:/usr/java/jdk1.8.0_231/jre/lib/fonts

也可能是字符集的原因

最后还是使用了快递100的云打印接口, https://api.kuaidi100.com/label/order 氪金的快乐. 
注意: 使用的content-Type在源码中有设置, api封装好了的, 我们只需设置基本参数即可, 参照api官网的调试代码
	如果打印不出来, 看下是不是网络的问题, 使用快递100的云打印机, 可以检测网络等.
	
后续有什么改动再在本帖更新	
posted @ 2023-02-08 16:18  颠三倒四不积极  阅读(1518)  评论(0编辑  收藏  举报