参考文章:https://blog.csdn.net/scholar_man/article/details/78784163
打印机使用的是斑马打印机
条码样式
工具类ZplPrinter
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import javax.print.*;
import javax.print.attribute.standard.PrinterName;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
/**
* @description: 条形码工具类
* @author: haoxueyang
* @create: 2021-05-17 16:13
*/
@Configuration //使用@Configuration是为了setEnvironment环境变量的注入
public class ZplPrinter implements EnvironmentAware {
private String printerModelNumber = null;//打印机型号
private PrintService printService = null;//打印机服务
private byte[] dotFont;
private String begin = "^XA"; //标签格式以^XA开始
private String end = "^XZ"; //标签格式以^XZ结束
private String content = "";
/**
* tr接口发送给SAP数据所调用的SAP的接口地址
*/
private static String ZPL_PRINTER_FONT_FILE;
@Override
public void setEnvironment(Environment environment) {
this.ZPL_PRINTER_FONT_FILE = environment.getProperty("zpl.printer.file");
}
public ZplPrinter() {
}
/**
* 构造方法
*
* @param printerModelNumber 打印机型号
*/
public ZplPrinter(String printerModelNumber) {
this.printerModelNumber = printerModelNumber;
//加载字体
File file = new File(this.ZPL_PRINTER_FONT_FILE);
if (file.exists()) {
FileInputStream fis;
try {
fis = new FileInputStream(file);
dotFont = new byte[fis.available()];
fis.read(dotFont);
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
} else {
System.out.println("ts24.lib文件不存在");
}
//初始化打印机
PrintService[] services = PrintServiceLookup.lookupPrintServices(null, null);
PrintService defaultService = PrintServiceLookup.lookupDefaultPrintService();
System.out.println("默认的打印机" + defaultService.getName());
if (services != null && services.length > 0) {
for (PrintService service : services) {
if (printerModelNumber.equals(service.getName())) {
printService = service;
break;
}
}
}
if (printService == null) {
System.out.println("没有找到打印机:[" + printerModelNumber + "]");
//循环出所有的打印机
if (services != null && services.length > 0) {
System.out.println("可用的打印机列表:");
for (PrintService service : services) {
System.out.println("[" + service.getName() + "]");
}
}
} else {
System.out.println("找到打印机:[" + printerModelNumber + "]");
System.out.println("打印机名称:[" + printService.getAttribute(PrinterName.class).getValue() + "]");
}
}
/**
* 设置条形码
*
* @param barcode 条码字符
* @param zpl 条码样式模板
*/
public void setBarcode(String barcode, String zpl) {
content += zpl.replace("${data}", barcode);
}
/**
* 中文字符、英文字符(包含数字)混合
*
* @param str 中文、英文
* @param x x坐标
* @param y y坐标
* @param eh 英文字体高度height
* @param ew 英文字体宽度width
* @param es 英文字体间距spacing
* @param mx 中文x轴字体图形放大倍率。范围1-10,默认1
* @param my 中文y轴字体图形放大倍率。范围1-10,默认1
* @param ms 中文字体间距。24是个比较合适的值。
*/
public void setText(String str, int x, int y, int eh, int ew, int es, int mx, int my, int ms) {
byte[] ch = str2bytes(str);
for (int off = 0; off < ch.length; ) {
if (((int) ch[off] & 0x00ff) >= 0xA0) {
int qcode = ch[off] & 0xff;
int wcode = ch[off + 1] & 0xff;
content += String.format("^FO%d,%d^XG0000%01X%01X,%d,%d^FS\n", x, y, qcode, wcode, mx, my);
begin += String.format("~DG0000%02X%02X,00072,003,\n", qcode, wcode);
qcode = (qcode + 128 - 32) & 0x00ff;
wcode = (wcode + 128 - 32) & 0x00ff;
int offset = ((int) qcode - 16) * 94 * 72 + ((int) wcode - 1) * 72;
for (int j = 0; j < 72; j += 3) {
qcode = (int) dotFont[j + offset] & 0x00ff;
wcode = (int) dotFont[j + offset + 1] & 0x00ff;
int qcode1 = (int) dotFont[j + offset + 2] & 0x00ff;
begin += String.format("%02X%02X%02X\n", qcode, wcode, qcode1);
}
x = x + ms * mx;
off = off + 2;
} else if (((int) ch[off] & 0x00FF) < 0xA0) {
setChar(String.format("%c", ch[off]), x, y, eh, ew);
x = x + es;
off++;
}
}
}
/**
* 英文字符串(包含数字)
*
* @param str 英文字符串
* @param x x坐标
* @param y y坐标
* @param h 高度
* @param w 宽度
*/
public void setChar(String str, int x, int y, int h, int w) {
content += "^FO" + x + "," + y + "^A0," + h + "," + w + "^FD" + str + "^FS";
}
public void setLineChar(String str, int x, int y, int h, int w) {
content += "^FO" + x + "," + y + "^AF0," + h + "," + w + "^FD" + str + "^FS";
}
public void setColumnChar(String str, int x, int y, int h, int w) {
content += "^FO" + x + "," + y + "^AFR," + h + "," + w + "^FD" + str + "^FS";
}
/**
* 英文字符(包含数字)顺时针旋转90度
*
* @param str 英文字符串
* @param x x坐标
* @param y y坐标
* @param h 高度
* @param w 宽度
*/
public void setCharR(String str, int x, int y, int h, int w) {
content += "^FO" + x + "," + y + "^A0R," + h + "," + w + "^FD" + str + "^FS";
}
/**
* 获取完整的ZPL
*
* @return
*/
public String getZpl() {
return begin + content + end;
}
/**
* 重置ZPL指令,当需要打印多张纸的时候需要调用。
*/
public void resetZpl() {
begin = "^XA";
end = "^XZ";
content = "";
}
/**
* 打印
*
* @param zpl 完整的ZPL
*/
public void print(String zpl) {
if (printService == null) {
System.out.println("打印出错:没有找到打印机:[" + printerModelNumber + "]");
throw new BizException("打印出错:没有找到打印机:[" + printerModelNumber + "]");
}
DocPrintJob job = printService.createPrintJob();
byte[] by = zpl.getBytes();
DocFlavor flavor = DocFlavor.BYTE_ARRAY.AUTOSENSE;
Doc doc = new SimpleDoc(by, flavor, null);
try {
job.print(doc, null);
System.out.println("已打印");
} catch (PrintException e) {
e.printStackTrace();
}
}
/**
* 字符串转byte[]
*
* @param s
* @return
*/
private byte[] str2bytes(String s) {
if (null == s || "".equals(s)) {
return null;
}
byte[] abytes = null;
try {
abytes = s.getBytes("gb2312");
} catch (UnsupportedEncodingException ex) {
ex.printStackTrace();
}
return abytes;
}
}
ServiceImpl层
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.print.*;
import java.text.SimpleDateFormat;
@Service
public class IBaseDeviceServiceImpl extends ServiceImpl<BaseDeviceMapper, BaseDevice> implements IBaseDeviceService {
@Autowired
IBaseDeviceService service;
@Autowired
IHrUserService userService;
@Autowired
LogisticsOperatorServiceImpl logisticsOperatorService;
@Autowired
LogisticsPathPointServiceImpl logisticsPathPointService;
@Autowired
IBaseDeviceRelationService iBaseDeviceRelationService;
@Autowired
IWmInventoryService inventoryService;
@Autowired
IWmWarehouseService warehouseService;
@Autowired
IBaseLabelCodeConvertService labelCodeConvertService;
/**
* pda端打印机打印标签
* 1、需要把C://ts24.lib文件放到指定位置
*
* @param wrapper
*/
@Override
public void printPdaLabelCodeByPrinter(WmInventoryWrapper wrapper) throws PrintException {
//条码显示的数据
WmInventory inventory = inventoryService.getOne(new QueryWrapper<WmInventory>().eq("label_code", wrapper.getLabelCode()).last("limit 1"));
if (inventory != null) {
if (inventory.getAssociateWarehouseId() != null) {
WmWarehouse warehouse = warehouseService.getOneById(inventory.getAssociateWarehouseId());
if (warehouse != null) {
wrapper.setWarehouseCode(warehouse.getCode());//仓库code
wrapper.setWarehouseName(warehouse.getName());//仓库name
}
}
if (inventory.getMaterialId() != null) {
MaterialMapCache materialCache = MaterialMapCache.getInstance();
BaseMaterial material = materialCache.getIdKeyMap().get(inventory.getMaterialId());
if (material != null) {
wrapper.setMaterialCode(material.getCode());//物料code
wrapper.setMaterialName(material.getName());//物料名称
}
}
} else {
throw new BizException(wrapper.getLabelCode() + "标签不存在");
}
wrapper.setMaterialQuantity(inventory.getMaterialQuantity());//数量
if (inventory.getPackageType() != null) {
if (inventory.getPackageType() == Constant.PackageType.PACKAGE_TYPE_1) {
wrapper.setBoxType("整箱区满箱");
} else if (inventory.getPackageType() == Constant.PackageType.PACKAGE_TYPE_2) {
wrapper.setBoxType("整箱区不满箱");
} else if (inventory.getPackageType() == Constant.PackageType.PACKAGE_TYPE_3) {
wrapper.setBoxType("散装区");
}
}
if (inventory.getCreateTime() != null) {
wrapper.setCreateTime(inventory.getCreateTime());
}
BaseLabelCodeConvert labelCodeConvert = labelCodeConvertService.getOne(new QueryWrapper<BaseLabelCodeConvert>().eq("label_code", wrapper.getLabelCode()));
if (labelCodeConvert == null) {
throw new BizException("该标签["+wrapper.getLabelCode()+"]没有转换打印id");
}
wrapper.setLabelCode(labelCodeConvert.getId().toString());
//打印
this.printLabelCodeByPrinter(wrapper);
}
/**
* 公用方法:PC端和pda端公用打印方法
*
* @param wrapper
* @throws PrintException
*/
private void printLabelCodeByPrinter(WmInventoryWrapper wrapper) throws PrintException {
//条码设置
ZplPrinter zplPrinter = new ZplPrinter(wrapper.getPrintDeviceModelNumber());
//第一行
zplPrinter.setText("物料名称", 30, 60, 19, 19, 14, 1, 1, 22);//1.1
if (!StringUtils.isEmpty(wrapper.getMaterialName())) {
zplPrinter.setText(wrapper.getMaterialName(), 130, 60, 19, 19, 14, 1, 1, 22);//1.2
}
//第二行
zplPrinter.setText("物料编码", 30, 110, 18, 18, 13, 1, 1, 22);//2.1
if (!StringUtils.isEmpty(wrapper.getMaterialCode())) {
zplPrinter.setText(wrapper.getMaterialCode(), 130, 110, 18, 18, 13, 1, 1, 22);//2.2
}
//第三行
zplPrinter.setText("箱内数量", 30, 160, 18, 18, 13, 1, 1, 22);//3.1
zplPrinter.setText(wrapper.getMaterialQuantity().toString(), 130, 165, 18, 18, 13, 1, 1, 22);//3.2
zplPrinter.setText("箱子类型", 300, 160, 18, 18, 13, 1, 1, 22);//3.3
zplPrinter.setText(wrapper.getBoxType(), 400, 160, 18, 18, 13, 1, 1, 22);//3.4
//第四行 库存产生时间
zplPrinter.setText("库存产生时间", 120, 210, 18, 18, 15, 1, 1, 22);
if (wrapper.getCreateTime() != null) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyy-MM-dd");
zplPrinter.setText(simpleDateFormat.format(wrapper.getCreateTime()), 320, 215, 18, 18, 13, 1, 1, 22);
}
//表格线
//行线
zplPrinter.setLineChar("____", 30, 20, 2, 100); //第1条横线
zplPrinter.setLineChar("____", 60, 20, 2, 110); //第1条横线
zplPrinter.setLineChar("____", 30, 80, 2, 100); //第2条横线
zplPrinter.setLineChar("____", 60, 80, 2, 110); //第2条横线
zplPrinter.setLineChar("____", 30, 130, 2, 100); //第3条横线
zplPrinter.setLineChar("____", 60, 130, 2, 110); //第3条横线
zplPrinter.setLineChar("____", 30, 180, 2, 100); //第4条横线
zplPrinter.setLineChar("____", 60, 180, 2, 110); //第4条横线
zplPrinter.setLineChar("____", 30, 225, 2, 100); //第5条横线 即条形码上方横线
zplPrinter.setLineChar("____", 60, 225, 2, 110); //第5条横线 即条形码上方横线
zplPrinter.setLineChar("____", 30, 350, 2, 100); //第6条横线 即条形码下方横线
zplPrinter.setLineChar("____", 60, 350, 2, 110); //第6条横线 即条形码下方横线
//列线
zplPrinter.setColumnChar("____", 20, 40, 2, 60);//第1列竖线
zplPrinter.setColumnChar("____", 20, 60, 2, 60);//第1列竖线
zplPrinter.setColumnChar("_____", 120, 41, 2, 30);//第2列竖线
zplPrinter.setColumnChar("____", 120, 62, 2, 20);//第2列竖线
zplPrinter.setColumnChar("___", 290, 151, 1, 1);//第3列竖线 平均分列线
zplPrinter.setColumnChar("__", 290, 164, 1, 1);//第3列竖线 平均分列线
zplPrinter.setColumnChar("___", 390, 151, 1, 1);//第4列竖线
zplPrinter.setColumnChar("__", 390, 164, 1, 1);//第4列竖线
zplPrinter.setColumnChar("____", 550, 40, 2, 60);//第5列竖线
zplPrinter.setColumnChar("____", 550, 60, 2, 60);//第5列竖线
String barZpl = "^FO35,260^BY2,3.0,80^BCN,,Y,N,N^FD${data}^FS";//条码样式模板
zplPrinter.setBarcode(wrapper.getLabelCode(), barZpl);
//打印机打印条码
String printerZpl = zplPrinter.getZpl();
zplPrinter.print(printerZpl);
}
}
service层
public interface IBaseDeviceService extends IService<BaseDevice> {
/**
* pda端:打印机打印标签
*
* @param wrapper
*/
void printPdaLabelCodeByPrinter(WmInventoryWrapper wrapper) throws PrintException;
}
controller层
@Controller
@RequestMapping("/sys/baseDevice")
public class BaseDeviceController {
@Autowired
IBaseDeviceService service;
private static final Logger logger = LoggerFactory.getLogger(BaseDeviceController.class);
/**
* pda端:打印机打印标签
*
* @return
*/
@RequestMapping("/printLabelCodeByPrinter")
@ResponseBody
public JsonResult printLabelCodeByPrinter(@RequestBody WmInventoryWrapper wrapper) {
JsonResult jsonResult = new JsonResult();
try {
if (StringUtils.isEmpty(wrapper.getLabelCode())) {
return jsonResult.setMsg(Constant.Info.PARAM_ERR);
}
service.printPdaLabelCodeByPrinter(wrapper);
return jsonResult.setMsg("打印成功").setSuccess(true);
} catch (BizException | PrintException e) {
logger.error("接口报错【/getPage】", e);
jsonResult.setMsg(e.getMessage());
jsonResult.setSuccess(false);
}
return jsonResult;
}
}