最近公司业务需求将url转为二维码,但是遇到url太长,转成的二维码无法扫描,要先将url转成短码处理,自己写了一个测试,分享学习一下!
package alfri.test;
import java.awt.BasicStroke;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Shape;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Hashtable;
import java.util.List;
import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
@Controller
@Scope("singleton")
@RequestMapping("/test")
public class LongUrl2ShortUrl {
private static long num = 922337203685477580L;// 模拟发号器发出的数字
/**
* @Description: 请求生成二维码
* @author YL
* @date 2018-11-23下午11:54:37
* @param request
* @param response
*/
@RequestMapping("/getQRCode")
@ResponseBody
public void getQRCode(HttpServletRequest request, HttpServletResponse response) {
String longUrl = "https://www.baidu.com/"; // 长链接
String shortUrl = getShortUrl(longUrl, num++);// 短链接码
shortUrl = "http://127.0.0.1:8080/web/test/" + shortUrl;// 短连接拼接url
// 画出二维码
BufferedImage image = null;
ServletOutputStream iStream = null;
try {
image = QRCodeUtil.createImage(shortUrl, "", false);
iStream = response.getOutputStream();
ImageIO.write(image, "jpeg", iStream);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (iStream == null) {
try {
iStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
*
* @Description: 传入长链接及分发的数字
* @author YL
* @date 2018-11-23下午11:09:33
* @param longUrl
* @param num
* @return 短连接编码 (未做长度限制及打乱)
*/
private static String getShortUrl(String longUrl, long num) {
String shortUrl = tenTo62(num);
ShortUrl su = new ShortUrl();
su.setShorturl(shortUrl);
su.setLongurl(longUrl);
shortUrl = setShortUrl(su);// 数据库存储短链接码及长链接
return shortUrl;
}
/**
*
* @Description: 数据库存储短链接码及长链接
* @author YL
* @date 2018-11-23下午11:12:45
* @param su
* @return 短链接码
*/
private static String setShortUrl(ShortUrl su) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String datestr = sdf.format(new Date().getTime() + 60000);
su.setExpdate(datestr);
String sql = "SELECT longurl FROM ashorurl WHERE shorturl = :shorturl AND expdate >= now()";
String sqlStr = "INSERT INTO ashorurl (shorturl,longurl,expdate) VALUES (:shorturl,:longurl,:expdate) ";
List<ShortUrl> sulist = new ArrayList<>();
// sulist = jdbcTemplate.query(sql, su,ShortUrl.class);//执行sql语句
if (sulist.size() > 0) {
String shorturl = sulist.get(0).getShorturl();
return shorturl;
} else {
// jdbcTemplate.update(sqlStr, su);// 执行sql语句插入记录
return su.getShorturl();
}
}
/**
*
* @Description: 发号器分发的数字 十进制转62进制
* @author YL
* @date 2018-11-23下午11:10:42
* @param num
* @return 短链接码
*/
private static String tenTo62(long num) {
StringBuilder sb = new StringBuilder();
char[] charArray = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".toCharArray();
long remainder = 0;
do {
remainder = num % 62;
// System.out.println(remainder);
sb.append(charArray[(int) remainder]);
num = num / 62;
} while (num > 61);
sb.append(charArray[(int) num]);
StringBuffer sbStr = new StringBuffer();
char[] chars = sb.toString().toCharArray();
for (int i = chars.length - 1; i >= 0; i--) {
sbStr.append(chars[i]);
}
return sbStr.toString();
}
/**
* @Description: 扫描二维码重定向url
* @author YL
* @date 2018-11-23下午11:50:06
* @param shortUrl
* 短链接码
* @return
*/
@RequestMapping("/{shortUrl}")
public String testPathVariable(@PathVariable("shortUrl") String shortUrl) {
ShortUrl su = new ShortUrl();
su.setShorturl(shortUrl);
String longUrl = getLongUrl(su);
return "redirect:" + longUrl;
}
/**
* @Description: 获取长链接url
* @author YL
* @date 2018-11-23下午11:50:59
* @param su
* @return
*/
private String getLongUrl(ShortUrl su) {
String sql = "SELECT * FROM ashorurl WHERE shorturl = :shorturl AND expdate >= now()";
List<ShortUrl> sulist = new ArrayList<>();
// sulist = jdbcTemplate.query(sql, su, ShortUrl.class); //从数据库中查出长链接
String longurl = null;
if (sulist.size() > 0) {
longurl = sulist.get(0).getLongurl();
}
return longurl;
}
}
/**
* @ClassName: ShortUrl
* @Description: 短连接实体类
* @author Administrator
* @date 2018-11-23
*
*/
class ShortUrl {
String shorturl;// 短连接
String longurl;// 长链接
String expdate;// 失效时间
public String getShorturl() {
return shorturl;
}
public void setShorturl(String shorturl) {
this.shorturl = shorturl;
}
public String getLongurl() {
return longurl;
}
public void setLongurl(String longurl) {
this.longurl = longurl;
}
public String getExpdate() {
return expdate;
}
public void setExpdate(String expdate) {
this.expdate = expdate;
}
}
/**
* @ClassName: QRCodeUtil
* @Description: 二维码工具类
* @author Administrator
* @date 2018-11-23
*
*/
class QRCodeUtil {
private static final String CHARSET = "utf-8";
private static final String FORMAT_NAME = "JPG";
// 二维码尺寸
private static final int QRCODE_SIZE = 200;
// LOGO宽度
private static final int WIDTH = 60;
// LOGO高度
private static final int HEIGHT = 60;
/**
* @Description: 创建二维码图片
* @author YL
* @date 2018-11-23下午11:52:24
* @param content
* @param imgPath
* @param needCompress
* @return
* @throws Exception
*/
public static BufferedImage createImage(String content, String imgPath, boolean needCompress) throws Exception {
Hashtable hints = new Hashtable();
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.L);
hints.put(EncodeHintType.CHARACTER_SET, CHARSET);
hints.put(EncodeHintType.MARGIN, 1);
BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, QRCODE_SIZE, QRCODE_SIZE, hints);
int width = bitMatrix.getWidth();
int height = bitMatrix.getHeight();
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
image.setRGB(x, y, bitMatrix.get(x, y) ? 0xFF000000 : 0xFFFFFFFF);
}
}
if (imgPath == null || "".equals(imgPath)) {
return image;
}
// 插入图片
QRCodeUtil.insertImage(image, imgPath, needCompress);
return image;
}
/**
* @Description: 插入logo
* @author YL
* @date 2018-11-23下午11:52:45
* @param source
* @param imgPath
* @param needCompress
* @throws Exception
*/
private static void insertImage(BufferedImage source, String imgPath, boolean needCompress) throws Exception {
File file = new File(imgPath);
if (!file.exists()) {
System.err.println("" + imgPath + " 该文件不存在!");
return;
}
Image src = ImageIO.read(new File(imgPath));
int width = src.getWidth(null);
int height = src.getHeight(null);
if (needCompress) { // 压缩LOGO
if (width > WIDTH) {
width = WIDTH;
}
if (height > HEIGHT) {
height = HEIGHT;
}
Image image = src.getScaledInstance(width, height, Image.SCALE_SMOOTH);
BufferedImage tag = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics g = tag.getGraphics();
g.drawImage(image, 0, 0, null); // 绘制缩小后的图
g.dispose();
src = image;
}
// 插入LOGO
Graphics2D graph = source.createGraphics();
int x = (QRCODE_SIZE - width) / 2;
int y = (QRCODE_SIZE - height) / 2;
graph.drawImage(src, x, y, width, height, null);
Shape shape = new RoundRectangle2D.Float(x, y, width, width, 6, 6);
graph.setStroke(new BasicStroke(3f));
graph.draw(shape);
graph.dispose();
}
}