Java使用com.google.zxing生成二維碼在Linux環境中無法生成二維碼問題

二維碼在我們的日常生活中已經氾濫了,所以作爲死開發的我也沒能逃過給用戶創建二維碼這個功能的實現。好在輪子已經有大佬造好了。
我的環境是:
Spring boot項目
CentOS 7.4
Tomcat 8

代碼實現:

import java.awt.Color;

public class MatrixToLogoImageConfig {
    //logo默認邊框顏色
    public static final Color DEFAULT_BORDERCOLOR = Color.RED;
    //logo默認邊框寬度
    public static final int DEFAULT_BORDER = 2;
    //logo大小默認爲照片的1/5
    public static final int DEFAULT_LOGOPART = 5;

    private final Color borderColor;
    private final int logoPart;

    /**
     * Creates a default config with on color and off color
     * generating normal black-on-white barcodes.
     */
    public MatrixToLogoImageConfig() {
        this(DEFAULT_BORDERCOLOR, DEFAULT_LOGOPART);
    }


    public MatrixToLogoImageConfig(Color borderColor, int logoPart) {
        this.borderColor = borderColor;
        this.logoPart = logoPart;
    }


    public Color getBorderColor() {
        return borderColor;
    }


    public int getBorder() {
        return DEFAULT_BORDER;
    }


    public int getLogoPart() {
        return logoPart;
    }
}
import java.awt.BasicStroke;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Hashtable;

import javax.imageio.ImageIO;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.client.j2se.MatrixToImageConfig;
import com.google.zxing.client.j2se.MatrixToImageWriter;

import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;

public class MatrixToImageWriterEx {

    private static final MatrixToLogoImageConfig DEFAULT_CONFIG = new MatrixToLogoImageConfig();

    /**
     * 根據內容生成二維碼數據
     * @param content 二維碼文字內容[爲了信息安全性,一般都要先進行數據加密]
     * @param width 二維碼照片寬度
     * @param height 二維碼照片高度
     * @param filePath 文件路徑,帶文件名,.png或.jpg後綴
     */
    public static boolean createQRCode(String content, int width, int height, String filePath){

        // 判斷後綴
        String format = filePath.substring(filePath.length()-4);
        if (!format.equals(".jpg")) {
            if (!format.equals(".png")) {
                return false;
            }
        }

        Hashtable<EncodeHintType, Object> hints = new Hashtable<>();
        //設置字符編碼
        hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
        // 指定糾錯等級
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
        BitMatrix matrix = null;
        try {
            matrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, width, height, hints);
            MatrixToImageWriter.writeToFile(matrix, format.substring(format.length()-3), new File(filePath), new MatrixToImageConfig());
        } catch (WriterException|IOException e) {
            e.printStackTrace();
        }
        return true;
    }

    /**
     * 寫入二維碼、以及將照片logo寫入二維碼中
     * @param matrix 要寫入的二維碼
     * @param format 二維碼照片格式
     * @param imagePath 二維碼照片保存路徑
     * @param logoPath logo路徑
     * @param logoConfig logo配置對象
     */
    public static void writeToFile(BitMatrix matrix, String format, String imagePath, String logoPath, MatrixToLogoImageConfig logoConfig) throws IOException {
        MatrixToImageWriter.writeToFile(matrix, format, new File(imagePath), new MatrixToImageConfig());

        //添加logo圖片, 此處一定需要重新進行讀取,而不能直接使用二維碼的BufferedImage 對象
        BufferedImage img = ImageIO.read(new File(imagePath));
        MatrixToImageWriterEx.overlapImage(img, format, imagePath, logoPath, logoConfig);
    }

    /**
     * 將照片logo添加到二維碼中間
     * @param image 生成的二維碼照片對象
     * @param imagePath 照片保存路徑
     * @param logoPath logo照片路徑
     * @param formate 照片格式
     */
    public static void overlapImage(BufferedImage image, String formate, String imagePath, String logoPath, MatrixToLogoImageConfig logoConfig) {
        try {

            if (logoPath != null) {
                Graphics2D g = image.createGraphics();
                BufferedImage logo = ImageIO.read(new File(logoPath));
                //考慮到logo照片貼到二維碼中,建議大小不要超過二維碼的1/5;
                int width = image.getWidth() / logoConfig.getLogoPart();
                int height = image.getHeight() / logoConfig.getLogoPart();
                //logo起始位置,此目的是爲logo居中顯示
                int x = (image.getWidth() - width) / 2;
                int y = (image.getHeight() - height) / 2;
                //繪製圖
                g.drawImage(logo, x, y, width, height, null);

                //給logo畫邊框
                //構造一個具有指定線條寬度以及 cap 和 join 風格的默認值的實心 BasicStroke
                g.setStroke(new BasicStroke(logoConfig.getBorder()));
                g.setColor(logoConfig.getBorderColor());
                g.drawRect(x, y, width, height);
                g.dispose();
            }


            //寫入logo照片到二維碼
            ImageIO.write(image, formate, new File(imagePath));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

    public static void main(String[] a) throws Exception{
        boolean s = createQRCode("https://www.baidu.com/", 512, 512, "/home/key/erweima/iiiooop.png");
        System.out.println(s);
    }

方法的調用這裏就不貼出來了。
功能完成後,在我的開發環境中Win10+Tomcat 8,都是正常的,簡直完美。然後丟到測試環境(CentOS 7.4 + Tomcat 8)就完蛋了,無法生成二維碼。
然後查了一些網上的資料:
https://blog.csdn.net/lxltmac/article/details/86693392

linux系統圖形控件未啓動導致的。
這時需要在tomcat目錄下的bin/catalina.sh文件的對於地方加入-Djava.awt.headless=true /
在Linux服務器上搜索$JAVA_OPTS然後找到八處跟下面類似一樣的地方加上上面這個參數配置,如:
exec “$_RUNJDB” “$LOGGING_CONFIG” $LOGGING_MANAGER $JAVA_OPTS $CATALINA_OPTS
-Djava.endorsed.dirs="$JAVA_ENDORSED_DIRS" -classpath “$CLASSPATH”
-sourcepath “$CATALINA_HOME”/…/…/java
-Djava.security.manager
-Djava.security.policy=="$CATALINA_BASE"/conf/catalina.policy
-Dcatalina.base="$CATALINA_BASE"
-Dcatalina.home="$CATALINA_HOME"
-Djava.awt.headless=true \
-Djava.io.tmpdir="$CATALINA_TMPDIR"
org.apache.catalina.startup.Bootstrap “$@” start

我在我的tomcat中確實找到8個這種樣子的位置,依次添加“-Djava.awt.headless=true \”,重啓Tomcat:
報錯了:

Cannot find ./catalina.sh
The file is absent or does not have execute permission
This file is needed to run this program

因爲我是將這個文件下載到本地再修改的,修改完成再上傳到服務器上,造成了沒有讀寫權限,解決:
在tomcat的bin目錄下執行:

chmod +x *.sh

然後重啓tomcat成功,但是還是無法生成二維碼,也可能tomcat對我要存放二維碼那個文件夾沒有讀寫權限,然後我將存放二維碼的文件夾換到/home目錄下,問題解決了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章