You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Linux环境JBoss上Java Web应用对接Windows打印服务器的技术问询

Alright, let's break down how to get this working for your Java web app running on JBoss (Linux) targeting that Windows print server's Building1Room15 printer. Since CUPS isn't an option, we need to work directly with Windows' SMB printing protocol—this is the native way Windows shares printers over the network. Here's a step-by-step approach with code examples:


1. Use a Third-Party SMB Library for Windows Printer Access

Java's native javax.print API doesn't support SMB printing out of the box, so you'll need a library to handle the SMB connection to the Windows server. SMBJ is a modern, maintained replacement for the older JCIFS library and works well for this use case.

First, add the SMBJ dependency to your project (if using Maven):

<dependency>
    <groupId>com.hierynomus</groupId>
    <artifactId>smbj</artifactId>
    <version>0.10.0</version> <!-- Grab the latest stable version from Maven Central -->
</dependency>

2. Implement a Custom PrintServiceLookup for SMB Printers

Java's PrintServiceLookup allows you to extend its default printer discovery logic. We'll create a custom implementation that connects to the Windows server, finds the shared printer by name, and wraps it into a javax.print.PrintService instance that your app can use.

Custom Lookup Class

import com.hierynomus.smbj.SMBClient;
import com.hierynomus.smbj.auth.AuthenticationContext;
import com.hierynomus.smbj.connection.Connection;
import com.hierynomus.smbj.session.Session;
import com.hierynomus.smbj.share.PrinterShare;
import javax.print.PrintService;
import javax.print.PrintServiceLookup;
import javax.print.attribute.AttributeSet;
import java.util.ArrayList;
import java.util.List;

public class SMBPrintServiceLookup extends PrintServiceLookup {
    private final String printServerName;
    private final String domainOrUsername;
    private final String password;

    // Constructor: pass in your Windows server details and credentials
    public SMBPrintServiceLookup(String printServerName, String domainOrUsername, String password) {
        this.printServerName = printServerName;
        this.domainOrUsername = domainOrUsername;
        this.password = password;
    }

    @Override
    protected PrintService[] getPrintServices(String printerNameFilter, AttributeSet attributes) {
        List<PrintService> matchingPrinters = new ArrayList<>();
        try (SMBClient smbClient = new SMBClient()) {
            // Connect to the Windows print server
            try (Connection connection = smbClient.connect(printServerName)) {
                AuthenticationContext authCtx = new AuthenticationContext(
                    domainOrUsername, 
                    password.toCharArray(), 
                    null // Leave as null if not using a domain
                );
                try (Session session = connection.authenticate(authCtx)) {
                    // Connect to the specific printer share (Building1Room15)
                    PrinterShare printerShare = (PrinterShare) session.connectShare("Building1Room15");
                    // Wrap the SMB printer share into a Java PrintService implementation
                    matchingPrinters.add(new SMBPrintService(printerShare));
                }
            }
        } catch (Exception e) {
            // Handle exceptions gracefully in production (e.g., log errors)
            e.printStackTrace();
        }
        return matchingPrinters.toArray(new PrintService[0]);
    }

    @Override
    protected PrintService getDefaultPrintService() {
        // Return null or implement logic if you need a default printer
        return null;
    }
}

Custom PrintService Implementation

We need to wrap the SMB PrinterShare into a class that implements Java's PrintService interface. This bridges the SMB library to the standard Java printing API:

import com.hierynomus.smbj.share.PrinterShare;
import javax.print.Doc;
import javax.print.DocFlavor;
import javax.print.PrintService;
import javax.print.PrintServiceAttributeSet;
import javax.print.attribute.AttributeSet;
import javax.print.attribute.HashPrintServiceAttributeSet;
import javax.print.event.PrintServiceAttributeListener;

public class SMBPrintService implements PrintService {
    private final PrinterShare smbPrinter;
    private final PrintServiceAttributeSet printerAttributes;

    public SMBPrintService(PrinterShare smbPrinter) {
        this.smbPrinter = smbPrinter;
        this.printerAttributes = new HashPrintServiceAttributeSet();
        // Add relevant printer attributes here (e.g., printer name)
    }

    @Override
    public String getName() {
        return smbPrinter.getName();
    }

    @Override
    public DocFlavor[] getSupportedDocFlavors() {
        // Return the document formats your Windows printer supports
        // Common options: PDF, PostScript, or PCL
        return new DocFlavor[]{
            DocFlavor.INPUT_STREAM.PDF,
            DocFlavor.INPUT_STREAM.POSTSCRIPT
        };
    }

    @Override
    public boolean isDocFlavorSupported(DocFlavor flavor) {
        for (DocFlavor supported : getSupportedDocFlavors()) {
            if (supported.equals(flavor)) return true;
        }
        return false;
    }

    @Override
    public AttributeSet getUnsupportedAttributes(DocFlavor flavor, AttributeSet attributes) {
        // Implement logic to return unsupported attributes (if needed)
        return null;
    }

    @Override
    public PrintServiceAttributeSet getAttributes() {
        return printerAttributes;
    }

    @Override
    public void addPrintServiceAttributeListener(PrintServiceAttributeListener listener) {
        // Add listener logic if you need to track printer attribute changes
    }

    @Override
    public void removePrintServiceAttributeListener(PrintServiceAttributeListener listener) {
        // Remove listener logic
    }

    @Override
    public javax.print.PrintJob createPrintJob() {
        // Return a custom print job that uses the SMB printer share
        return new SMBPrintJob(smbPrinter);
    }
}

Custom PrintJob Implementation

Finally, create a PrintJob that handles sending the document to the SMB printer:

import com.hierynomus.smbj.share.PrinterShare;
import javax.print.Doc;
import javax.print.DocPrintJob;
import javax.print.PrintException;
import javax.print.event.PrintJobAttributeListener;
import javax.print.event.PrintJobListener;
import java.io.InputStream;

public class SMBPrintJob implements DocPrintJob {
    private final PrinterShare smbPrinter;

    public SMBPrintJob(PrinterShare smbPrinter) {
        this.smbPrinter = smbPrinter;
    }

    @Override
    public void print(Doc doc, javax.print.attribute.PrintRequestAttributeSet attributes) throws PrintException {
        try {
            // Get the document input stream (e.g., PDF file stream)
            InputStream docStream = (InputStream) doc.getDocData();
            // Send the document to the Windows printer via SMB
            smbPrinter.print(docStream, doc.getDocFlavor().getMediaType());
        } catch (Exception e) {
            throw new PrintException("Failed to send document to printer", e);
        }
    }

    @Override
    public void addPrintJobListener(PrintJobListener listener) {
        // Add print job event listener logic if needed
    }

    @Override
    public void removePrintJobListener(PrintJobListener listener) {
        // Remove print job listener logic
    }

    @Override
    public void addPrintJobAttributeListener(PrintJobAttributeListener listener) {
        // Add attribute listener logic if needed
    }

    @Override
    public void removePrintJobAttributeListener(PrintJobAttributeListener listener) {
        // Remove attribute listener logic
    }
}

3. Register the Custom Lookup and Find the Printer

In your web app (e.g., during initialization), register the custom SMBPrintServiceLookup and search for your printer:

// Initialize the lookup with your Windows server details
SMBPrintServiceLookup smbLookup = new SMBPrintServiceLookup(
    "Building1Room15", // Replace with your Windows print server hostname/IP
    "your-windows-username",
    "your-windows-password"
);

// Register the custom lookup with Java's print service system
PrintServiceLookup.registerServiceProvider(smbLookup);

// Find the printer by name
PrintService targetPrinter = null;
PrintService[] allServices = PrintServiceLookup.lookupPrintServices(null, null);
for (PrintService service : allServices) {
    if ("Building1Room15".equals(service.getName())) {
        targetPrinter = service;
        break;
    }
}

// Use the printer to print your document
if (targetPrinter != null) {
    DocPrintJob printJob = targetPrinter.createPrintJob();
    // Prepare your document (e.g., load a PDF as InputStream)
    // Doc doc = new SimpleDoc(pdfInputStream, DocFlavor.INPUT_STREAM.PDF, null);
    // printJob.print(doc, null);
} else {
    // Handle case where printer wasn't found
}

Key Notes for Production
  • Credentials: Store Windows credentials securely (e.g., JBoss vault, environment variables) instead of hardcoding them.
  • Permissions: Ensure the Windows user account has print access to the Building1Room15 printer share.
  • Error Handling: Add robust logging and exception handling for connection issues, printer access failures, and unsupported document formats.
  • Doc Formats: Verify which document formats your Windows printer supports—some may require converting your output to PCL or PostScript if PDF isn't natively supported.

内容的提问来源于stack exchange,提问作者Jason

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 10:56:21