使用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的云打印机, 可以检测网络等.
后续有什么改动再在本帖更新