一.准备步骤
1.1 pom.xml
<!-- 二维码 https://mvnrepository.com/artifact/com.google.zxing/core --> <dependency> <groupId>com.google.zxing</groupId> <artifactId>core</artifactId> <version>3.3.0</version> </dependency> <!-- https://mvnrepository.com/artifact/com.google.zxing/javase --> <dependency> <groupId>com.google.zxing</groupId> <artifactId>javase</artifactId> <version>3.3.0</version> </dependency>
1.2 准备一张logo图片,我的图片是服务器上的:http://xxx.xxx.xxx.xx:xxxx//qrCodeImg/logo.png
1.3 接口源码
1 package com.web.kds.hadoop_kafka.Controller; 2 3 import java.awt.BasicStroke; 4 import java.awt.Color; 5 import java.awt.Graphics2D; 6 import java.awt.RenderingHints; 7 import java.awt.image.BufferedImage; 8 import java.io.ByteArrayInputStream; 9 import java.io.ByteArrayOutputStream; 10 import java.io.File; 11 import sun.misc.BASE64Decoder; 12 import java.io.IOException; 13 import java.io.InputStream; 14 import java.net.URL; 15 import java.net.URLConnection; 16 import java.text.SimpleDateFormat; 17 import java.util.Date; 18 import java.util.Hashtable; 19 import java.util.UUID; 20 21 import javax.imageio.ImageIO; 22 import javax.servlet.ServletOutputStream; 23 import javax.servlet.http.HttpServletRequest; 24 import javax.servlet.http.HttpServletResponse; 25 26 import org.apache.tomcat.util.http.fileupload.servlet.ServletFileUpload; 27 import org.springframework.util.StringUtils; 28 import org.springframework.web.bind.annotation.PostMapping; 29 import org.springframework.web.bind.annotation.RequestBody; 30 import org.springframework.web.bind.annotation.RequestMapping; 31 import org.springframework.web.bind.annotation.RequestParam; 32 import org.springframework.web.bind.annotation.ResponseBody; 33 import org.springframework.web.bind.annotation.RestController; 34 import org.springframework.web.multipart.MultipartFile; 35 import org.springframework.web.multipart.MultipartHttpServletRequest; 36 37 import com.google.zxing.BarcodeFormat; 38 import com.google.zxing.EncodeHintType; 39 import com.google.zxing.MultiFormatWriter; 40 import com.google.zxing.WriterException; 41 import com.google.zxing.client.j2se.MatrixToImageWriter; 42 import com.google.zxing.common.BitMatrix; 43 import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel; 44 45 import sun.misc.BASE64Encoder; 46 47 @RestController 48 @RequestMapping("qrcode") 49 public class QrCodeController { 50 private static final int BLACK = 0xFF000000; 51 private static final int WHITE = 0xFFFFFFFF; 52 private static final int margin = 0; 53 private static final int LogoPart = 4; 54 private static final String logoPath ="http://xxx.xxx.xxx.xx:8081//qrCodeImg/logo.png"; 55 56 57 @RequestMapping("getfile") 58 public void getQrCodeFile(HttpServletResponse resp) throws Exception { 59 ServletOutputStream stream = resp.getOutputStream();; 60 String content = "www.baidu.com"; 61 int width = 260; 62 int height = 260; 63 BitMatrix bitMatrix = setBitMatrix(content, width, height); 64 65 BufferedImage image = toBufferedImage(bitMatrix); 66 // 加入LOGO水印效果 67 if (logoPath!=null &&!logoPath.equals("")) { 68 image = addLogo(image, logoPath); 69 } 70 // 可通过输出流输出到页面,也可直接保存到文件 71 ImageIO.write(image, "png", resp.getOutputStream()); 72 } 73 /** 74 * 生成二维码矩阵信息 75 * @param content 二维码图片内容 76 * @param width 二维码图片宽度 77 * @param height 二维码图片高度 78 */ 79 public static BitMatrix setBitMatrix(String content, int width, int height){ 80 Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>(); 81 hints.put(EncodeHintType.CHARACTER_SET, "UTF-8"); // 指定编码方式,防止中文乱码 82 hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H); // 指定纠错等级 83 hints.put(EncodeHintType.MARGIN, margin); // 指定二维码四周白色区域大小 84 BitMatrix bitMatrix = null; 85 try { 86 bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, width, height, hints); 87 } catch (WriterException e) { 88 e.printStackTrace(); 89 } 90 return bitMatrix; 91 } 92 93 94 95 /** 96 * 生成二维码图片 去白边 97 * @param matrix 二维码矩阵信息 98 */ 99 public static BufferedImage toBufferedImage(BitMatrix matrix) { 100 int width = matrix.getWidth(); 101 int height = matrix.getHeight(); 102 BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR); 103 for (int x = 0; x < width; x++) { 104 for (int y = 0; y < height; y++) { 105 image.setRGB(x, y, matrix.get(x, y) ? BLACK : WHITE); 106 } 107 } 108 return image; 109 } 110 /** 111 * 在二维码图片中添加logo图片 112 * @param image 二维码图片 113 * @param logoPath logo图片路径 114 * @throws IOException 115 */ 116 public static BufferedImage addLogo(BufferedImage image, String logoPath) throws IOException{ 117 BASE64Decoder base64de = new BASE64Decoder(); 118 Graphics2D g = image.createGraphics(); 119 //消除文字锯齿 120 g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,RenderingHints.VALUE_TEXT_ANTIALIAS_ON); 121 //消除画图锯齿 122 g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 123 124 //把Base64编码过的字节数组字符串解码转换成字节数组 125 byte[] b= base64de.decodeBuffer(downloadFile(logoPath)); 126 //将字节数组转化为输入流 127 InputStream is=new ByteArrayInputStream(b); 128 //将图片流写入ImageIO流 129 BufferedImage logoImage = ImageIO.read(is); 130 // 计算logo图片大小,可适应长方形图片,根据较短边生成正方形 131 int width = image.getWidth() < image.getHeight() ? image.getWidth() / LogoPart : image.getHeight() / LogoPart; 132 int height = width; 133 // 计算logo图片放置位置 134 int x = (image.getWidth()-width)/ 2; 135 int y = (image.getHeight()-height)/ 2; 136 int x1 = (image.getWidth()-width-10)/ 2; 137 int y1 = (image.getHeight()-height-10)/ 2; 138 // 边框颜色 139 g.setColor(Color.white); 140 // 画笔粗细 141 g.setStroke(new BasicStroke(5)); // 画笔粗细 142 //画图层,作用是在logo图片周围加点白边,显示更美观 143 g.fillRect(x1, y1, width+10, height+10); 144 //绘制logo边框, 145 g.drawRoundRect(x1, y1, width+10,height+10, 30, 30); 146 147 // 在二维码图片上绘制logo图片 148 g.drawImage(logoImage, x, y, width, height, null); 149 logoImage.flush(); 150 g.dispose(); 151 return image; 152 } 153 //将网络图片转base64 154 public static String downloadFile(String urlPath){ 155 ByteArrayOutputStream data = new ByteArrayOutputStream(); 156 try { 157 // 打开图片路径 158 URL url = new URL(urlPath); 159 URLConnection connection = url.openConnection(); 160 // 通过输入流获取图片数据 161 InputStream in = connection.getInputStream(); 162 byte[] by = new byte[1024]; 163 // 将内容读取内存中 164 int len = -1; 165 while ((len = in.read(by)) != -1) { 166 data.write(by, 0, len); 167 } 168 //关闭流 169 in.close(); 170 } catch (IOException e) { 171 e.printStackTrace(); 172 } 173 // 返回Base64编码过的字节数组字符串 174 BASE64Encoder encoder = new BASE64Encoder(); 175 return encoder.encode(data.toByteArray()); 176 } 177 178 }