java利用zxing生成二维码
首先需要相应jar包
maven依赖添加
<dependency> <groupId>com.google.zxing</groupId> <artifactId>core</artifactId> <version>3.3.0</version> </dependency> <dependency> <groupId>com.google.zxing</groupId> <artifactId>javase</artifactId> <version>3.3.0</version> </dependency>
直接写在controller里面的二维码生成
private static final int WIDTH = 60; private static final int HEIGHT = 60; private static final String CHARSET = "UTF-8"; private static final String FORMAT_NAME = "JPG"; @GetMapping(value = "/showQRCode/{id}") public void showQRCode(@PathVariable("id") String id,HttpServletResponse resp) throws Exception { xxxSignAddress xxxSignAddress = districtService.selectRegionById(id); String content = xxxSignAddress.toString(); Map<EncodeHintType,Object> config = new HashMap<>(); config.put(EncodeHintType.CHARACTER_SET,CHARSET);//字符编码 config.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);//纠错等级 config.put(EncodeHintType.MARGIN, 0); BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE,WIDTH,HEIGHT,config); Path file = new File("g:/QRCode"+File.separator+IdGen.uuid()+".png").toPath(); MatrixToImageWriter.writeToPath(bitMatrix,FORMAT_NAME,file); System.out.println("二维码生成完毕,已经保存至相关路径中。"); // 下面是将其path保存到数据库,并以流的形式返回给前端,这里需要HttpServletResponse的相应输出流 File filePath=new File(file.toString()); String path=filePath.getAbsolutePath(); xxxSignAddress gsa = new xxxSignAddress(); gsa.setId(id); gsa.setName(xxxSignAddress.getName()); gsa.setCustomer(xxxSignAddress.getCustomer()); gsa.setPath(path); districtService.savePath(gsa); OutputStream os = resp.getOutputStream();//取得输出流 MatrixToImageWriter.writeToStream(bitMatrix, FORMAT_NAME, os);//写入文件刷新 }
然后优化提出来一个二维码生成的工具类,和controller,这里考虑了既要将二维码显示在前端,也要将二维码保存下来,并将路径保存到相应数据库中
工具类如下:
package com.xxx.cloud.common.utils; import java.awt.image.BufferedImage; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.nio.file.Path; import java.util.HashMap; import java.util.Map; import javax.imageio.ImageIO; import org.springframework.core.io.FileSystemResource; import org.springframework.core.io.InputStreamResource; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import com.google.zxing.BarcodeFormat; import com.google.zxing.BinaryBitmap; import com.google.zxing.EncodeHintType; import com.google.zxing.MultiFormatReader; import com.google.zxing.MultiFormatWriter; import com.google.zxing.NotFoundException; import com.google.zxing.Result; import com.google.zxing.client.j2se.BufferedImageLuminanceSource; import com.google.zxing.client.j2se.MatrixToImageWriter; import com.google.zxing.common.BitMatrix; import com.google.zxing.common.HybridBinarizer; import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel; public class QRCodeUtil { private static final int WIDTH = 60; private static final int HEIGHT = 60; private static final String CHARSET = "UTF-8"; public static final String FORMAT_NAME = "JPG"; public static Map<String,Object> createQRCode(String content) throws Exception { Map<EncodeHintType,Object> config = new HashMap<>(); config.put(EncodeHintType.CHARACTER_SET,CHARSET);//字符编码 config.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);//纠错等级 config.put(EncodeHintType.MARGIN, 0); BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE,WIDTH,HEIGHT,config); Path file = new File("g:/QRCode"+File.separator+IdGen.uuid()+".png").toPath(); MatrixToImageWriter.writeToPath(bitMatrix,FORMAT_NAME,file); System.out.println("二维码生成完毕,已经保存至相关路径中。"); File filePath=new File(file.toString()); String path=filePath.getAbsolutePath(); Map<String,Object> data = new HashMap<String,Object>(); data.put("qrcode", bitMatrix); data.put("path", path); return data; } }
如上代码为了在controller中保存路径到数据库,同时为了将二维码刷新到前端,故而将路径和二维码生成的图像通过map返回来,在controller中取出并作适当类型转换,然后就可以实现。
controller代码如下:
@GetMapping(value = "/showQRCode/{id}") public void showQRCode(@PathVariable("id") String id,HttpServletResponse resp) throws Exception { xxxSignAddress xxxSignAddress = districtService.selectRegionById(id); String content = xxxSignAddress.toString(); Map<String,Object> data = QRCodeUtil.createQRCode(content); String path = (String) data.get("path"); BitMatrix bitMatrix = (BitMatrix) data.get("qrcode"); xxxSignAddress gsa = new xxxSignAddress(); gsa.setId(id); gsa.setName(xxxSignAddress.getName()); gsa.setCustomer(xxxSignAddress.getCustomer()); gsa.setPath(path); districtService.savePath(gsa); OutputStream os = resp.getOutputStream();//取得输出流 MatrixToImageWriter.writeToStream(bitMatrix, QRCodeUtil.FORMAT_NAME, os);//写入文件刷新 }
测试均ok,如下
解析二维码的代码也放上
// 解析二维码 public static void readQRCode(File file){ try { MultiFormatReader formatReader = new MultiFormatReader(); BufferedImage image = ImageIO.read(file); BinaryBitmap binaryBitmap = new BinaryBitmap(new HybridBinarizer(new BufferedImageLuminanceSource(image))); HashMap hints = new HashMap(); hints.put(EncodeHintType.CHARACTER_SET, CHARSET); Result result = formatReader.decode(binaryBitmap, hints); } catch (NotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
再次优化的返回Base64字节码和二维码url的代码
1 @GetMapping(value = "/showQRCode/{id}") 2 public ResponseObj showQRCode(@PathVariable("id") String id, HttpServletResponse resp) throws Exception { 3 ResponseObj response = new ResponseObj(); 4 response.setMessage("二维码生成并显示成功"); 5 response.setStatus(Defined.STATUS_SUCCESS); 6 xxxSignAddress xxxSignAddress = districtService.selectRegionById(id); 7 String content ="signAddressId:"+xxxSignAddress.getId(); 8 Map<String, Object> dataInfo = QRCodeUtil.createQRCode(content); 9 BitMatrix bitMatrix = (BitMatrix) dataInfo.get("qrcode"); 10 // 输出流转换为输入流,并上传二维码 11 ByteArrayOutputStream bos = new ByteArrayOutputStream(); 12 MatrixToImageWriter.writeToStream(bitMatrix, QRCodeUtil.FORMAT_NAME, bos);// 写入文件刷新 13 ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray()); 14 String path = upload(bis, "png"); 15 xxxSignAddress gsa = new xxxSignAddress(); 16 gsa.setId(id); 17 gsa.setUpdateBy(getCurrentUser().getAccount().getUserId()); 18 gsa.setUpdateTime(DateUtil.getNowTimestamp()); 19 gsa.setPath(path); 20 districtService.savePath(gsa); 21 ByteArrayInputStream is = new ByteArrayInputStream(bos.toByteArray()); 22 int i = is.available(); // 得到文件大小 23 byte bytes[] = new byte[i]; 24 is.read(bytes); // 读数据 25 is.close(); 26 //对字节数组Base64编码 27 BASE64Encoder encoder = new BASE64Encoder(); 28 String QRStr = encoder.encode(bytes);//返回Base64编码过的字节数组字符串 29 Map<String,Object> data = new HashMap<String,Object>(); 30 data.put("QRStr", QRStr); 31 data.put("QRUrl", aliConstants.aliyunHostOuter+"/"+path); 32 response.setData(data); 33 return response; 34 }
运行结果
生成含logo的二维码
补充代码
private static final int BLACK = 0xFF000000;
private static final int WHITE = 0xFFFFFFFF;
1 public static BufferedImage createQRCodeWithLogo(String data, String charset, Hashtable<EncodeHintType, ?> hint, 2 int width, int height, File logoFile) { 3 try { 4 BufferedImage qrcode = createQRCodeLogo(data); 5 BufferedImage logo = ImageIO.read(logoFile); 6 int deltaHeight = height - logo.getHeight(); 7 int deltaWidth = width - logo.getWidth(); 8 9 BufferedImage combined = new BufferedImage(height, width, BufferedImage.TYPE_INT_ARGB); 10 Graphics2D g = (Graphics2D) combined.getGraphics(); 11 g.drawImage(qrcode, 0, 0, null); 12 g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f)); 13 g.drawImage(logo, (int) Math.round(deltaWidth / 2), (int) Math.round(deltaHeight / 2), null); 14 15 return combined; 16 } catch (IOException e) { 17 throw new RuntimeException(e.getMessage(), e); 18 } catch (Exception e) { 19 throw new RuntimeException(e.getMessage(), e); 20 } 21 } 22 23 public static BufferedImage createQRCodeLogo(String data) throws Exception { 24 Map<EncodeHintType,Object> config = new HashMap<>(); 25 config.put(EncodeHintType.CHARACTER_SET,CHARSET);//字符编码 26 config.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);//纠错等级 27 config.put(EncodeHintType.MARGIN, 0); 28 BitMatrix bitMatrix = new MultiFormatWriter().encode(data, BarcodeFormat.QR_CODE,WIDTH,HEIGHT,config); 29 return toBufferedImage(bitMatrix); 30 } 31 32 33 34 public static BufferedImage toBufferedImage(BitMatrix matrix) { 35 int width = matrix.getWidth(); 36 int height = matrix.getHeight(); 37 BufferedImage image = new BufferedImage(width, height, 38 BufferedImage.TYPE_INT_RGB); 39 for (int x = 0; x < width; x++) { 40 for (int y = 0; y < height; y++) { 41 image.setRGB(x, y, matrix.get(x, y) ? BLACK : WHITE); 42 } 43 } 44 return image; 45 } 46 /* public static void main(String[] args) throws IOException, NotFoundException{ 47 String data = "http://www.baidu.com"; 48 File logoFile = new File("G:/打印二维码logo.png"); 49 Hashtable<EncodeHintType,Object> config = new Hashtable<>(); 50 config.put(EncodeHintType.CHARACTER_SET,CHARSET);//字符编码 51 config.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);//纠错等级 52 config.put(EncodeHintType.MARGIN, 0); 53 BufferedImage image = QRCodeUtil.createQRCodeWithLogo(data,CHARSET, config,WIDTH,HEIGHT,logoFile); 54 ImageIO.write(image, "png", new File("g:/xxx_zxing_logo.png")); 55 }*/ 56 57 public static Map<String,Object> getQRCodeWithLogo(File logoFile,String content){ 58 Hashtable<EncodeHintType,Object> config = new Hashtable<>(); 59 config.put(EncodeHintType.CHARACTER_SET,CHARSET);//字符编码 60 config.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);//纠错等级 61 config.put(EncodeHintType.MARGIN, 0); 62 BufferedImage image = QRCodeUtil.createQRCodeWithLogo(content,CHARSET, config,WIDTH,HEIGHT,logoFile); 63 Map<String,Object> data = new HashMap<String,Object>(); 64 data.put("qrcode", image); 65 return data; 66 }
本博主支持并坚持原创,本博客文章将以原创为主。