How to Build a Silent Printing Proxy for Windows Using Java and Spring Boot
This article explains the challenges of printing in a hybrid store‑warehouse environment, outlines the limitations of JavaScript‑based printing, and details a custom Java‑powered printing proxy that uses Spring Boot, printable APIs, executable packaging, and offset files to achieve silent, multi‑scenario printing on Windows.
1. Problems Faced by the Store‑Warehouse
The store combines retail and warehouse functions, requiring printing of receipts, tags, stickers, and accessories, often with multiple printers on a single PC. Operators need a simple, automated workflow that selects the correct printer and minimizes manual steps.
2. Limitations of Calling the Printer from JavaScript
2.1 JavaScript Constraints
Calling window.print() prints the whole page, not just the barcode or receipt data. Using an iframe still triggers the Windows print preview dialog, which is unnecessary for the store’s workflow.
2.2 Need for Silent Printing
Two common approaches exist: modifying Chrome flags (unstable across versions) or using a proxy program that receives print requests from the browser and prints silently. The latter is more reliable for the store’s specific scenarios.
3. Building a Custom Printing Proxy
3.1 Java Calls Windows Printer
Java can invoke the Windows print service via the javax.print API. The code below shows how to locate a printer by name and obtain a PrintService instance.
private PrintService findPrintService(String name) {
PrintService targetPrintService = null;
PrintService[] allPrintServices = PrintServiceLookup.lookupPrintServices(null, null);
if (allPrintServices != null) {
for (PrintService printService : allPrintServices) {
if (printService.getName().equals(name)) {
targetPrintService = printService;
break;
}
}
}
if (targetPrintService == null) {
// log missing printer
return null;
}
return targetPrintService;
}This method allows dynamic selection of printers when several are connected.
3.2 Generating Print Data
Three main strategies are used:
Template‑based printing (e.g., JasperSoft) for complex, stable layouts.
Using java.awt.print.Book to draw text and graphics directly for simple receipts.
Converting the content to an image and printing the image, which is flexible for barcode‑heavy outputs.
Example of drawing text with Book:
Book book = new Book();
book.append((graphics, pageFormat, pageIndex) -> {
graphics.setFont(new Font("Default", Font.BOLD, 12));
graphics.drawString("十二号字测试行", 0, 30);
// ... more drawing commands ...
return PAGE_EXISTS;
}, pf);Printing an image involves reading the image, adjusting the printable area, and sending the job:
BufferedImage image = ImageIO.read(inputStream);
PrinterJob job = PrinterJob.getPrinterJob();
job.setPrintService(targetPrintService);
PageFormat pageFormat = getPageFormat(image.getHeight(), image.getWidth());
job.setPrintable(new ImagePrintable(image, scale), pageFormat);
job.print(new HashPrintRequestAttributeSet());3.3 Multi‑Scenario Web‑Based Proxy
A lightweight Spring Boot web server exposes a single /print endpoint. Front‑end JavaScript posts the image and a type identifier; the server routes the request to the appropriate IPrintService implementation.
@RequestMapping("/print")
@ResponseBody
public WebResponse<Void> print(@RequestParam("type") String type,
@RequestParam("file") MultipartFile file) {
// delegate to specific print service based on type
}Print services are injected as a map keyed by the type parameter.
@Resource
private Map<String, IPrintService> printServiceMap;3.4 Packaging as a Stand‑Alone Executable
The Java application is bundled into a single JAR using the Maven Assembly plugin, then wrapped into an EXE with Launch4j. This eliminates the need for a separate Java runtime on the store PCs.
<!-- Maven Assembly plugin configuration (simplified) -->
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<id>assembly</id>
<phase>package</phase>
<goals><goal>single</goal></goals>
<configuration>
<descriptors>
<descriptor>src/main/assembly/assembly.xml</descriptor>
</descriptors>
</configuration>
</execution>
</executions>
</plugin> <!-- Launch4j plugin configuration (simplified) -->
<plugin>
<groupId>com.akathist.maven.plugins.launch4j</groupId>
<artifactId>launch4j-maven-plugin</artifactId>
<executions>
<execution>
<id>l4j-clui</id>
<phase>package</phase>
<goals><goal>launch4j</goal></goals>
<configuration>
<headerType>console</headerType>
<jar>${project.build.directory}/${project.build.finalName}.jar</jar>
<outfile>${project.build.directory}/printWebserver_1.0.exe</outfile>
<icon>src/main/resources/image/zzPrinter.ico</icon>
<singleInstance>
<mutexName>warestorePrintWebserver</mutexName>
</singleInstance>
<classPath>
<mainClass>org.springframework.boot.loader.JarLauncher</mainClass>
<addDependencies>true</addDependencies>
<jarLocation>lib/</jarLocation>
</classPath>
<jre>
<minVersion>1.8.0</minVersion>
<initialHeapSize>1024</initialHeapSize>
<maxHeapSize>2048</maxHeapSize>
</jre>
<versionInfo>
<fileVersion>1.0.0.0</fileVersion>
<txtFileVersion>1.0.0.0</txtFileVersion>
<fileDescription>zhuanzhuan warestore universal printing program</fileDescription>
<productName>printWebserver</productName>
<originalFilename>printWebserver.exe</originalFilename>
</versionInfo>
</configuration>
</execution>
</executions>
</plugin>Running the EXE starts the web service, allowing the front‑end to trigger silent printing via HTTP.
4. General Solution for Print Offset
Print media often shift due to pre‑printed patterns or roll changes. To provide a uniform adjustment, a plain‑text offset file is placed on the desktop (e.g., "打印机偏移参数.txt") containing X and Y offsets separated by a comma.
At startup the application reads this file and stores the offsets in a static entity. When creating the printable area, the offsets are added:
paper.setImageableArea(14.2D + localOffsetEntity.getxOffset(),
121.9D + localOffsetEntity.getyOffset(),
areaWidth, areaWidth * aspectRatio);5. Summary
The store’s front‑end is web‑based, so a web service proxy simplifies integration.
Reducing manual steps and preventing unexpected dialogs improves operator efficiency.
Providing a simple, configurable solution (offset file, executable packaging) ensures stability across diverse hardware scenarios.
Zhuanzhuan Tech
A platform for Zhuanzhuan R&D and industry peers to learn and exchange technology, regularly sharing frontline experience and cutting‑edge topics. We welcome practical discussions and sharing; contact waterystone with any questions.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
