二維碼在我們的日常生活中已經氾濫了,所以作爲死開發的我也沒能逃過給用戶創建二維碼這個功能的實現。好在輪子已經有大佬造好了。
我的環境是:
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目錄下,問題解決了。