JavaWeb实现生成二维码
在Java中,二维码的生成实现方式有很多种,可以使用QRCode.jar来实现,也可以使用ZXing开发。
ORCode.jar下载:
链接: https://pan.baidu.com/s/1XFK5xU5jVJUmSz4EU2v6NA 提取码: ein8
使用zxing需要使用到的jar包:
链接: https://pan.baidu.com/s/14FEiFXBl3f9YPbu4EMBfdA 提取码: 9c8r
也可以从maven仓库下载:http://central.maven.org/maven2/com/google/zxing/core/
下载后将jar包添加到项目中
jsp代码(form表单需要将enctype设置为multipart/form-data,表示表单数据由多部分组成,既有文本数据,也有二进制数据,enctype默认值是不能用于文件上传的。)一个下拉框用于选择是否生成带有logo的二维码,文本域用于获取生成二维码的内容
<form action="${path }/QRGeneratorServlet?methodName=creatorQR" enctype="multipart/form-data" method="post">
<select onchange="showUploadFile()" style="width:140px;height: 28px" name="type">
<option value ="1" selected="selected">无Logo</option>
<option value ="2">带Logo</option>
</select>
<hr>
<input type="file" name="file" id="logoFile" style="display:none;" /><br/>
<textarea placeholder="请输入内容" rows="5" cols="60" name="content"></textarea> <br/>
<input class="layui-btn" type="submit" value="生成二维码" />
</form>
</center>
Servlet代码
public void creatorQR(HttpServletRequest req, HttpServletResponse resp) throws Exception {
req.setCharacterEncoding("utf-8"); //设置编码
if (!ServletFileUpload.isMultipartContent(req)) {//是否为多部分上传
return; //这里可以抛个异常
}
DiskFileItemFactory factory = new DiskFileItemFactory();
// 设置内存临界值 - 超过后将产生临时文件并存储于临时目录中
factory.setSizeThreshold(1024 * 1024 * 3);
//省略了部分非关键代码
//文件上传路径
String uploadPath = req.getServletContext().getRealPath(FileUploadConstant.LOGO_PATH);
File uploadDir = new File(uploadPath);
if (!uploadDir.exists()) { // 如果目录不存在则创建
uploadDir.mkdir();
}
List<FileItem> formItems = null;
formItems = upload.parseRequest(req);
Iterator iter = formItems.iterator();
while (iter.hasNext()) {
//省略获取值和文件的代码
}
//生成地址
String destPath = req.getServletContext().getRealPath(FileUploadConstant.QR_PATH);
String qrName = "";
if(type == LogoEnum.NOT_CONTAIN_LOGO.getLogoFlag()){ //没有logo
qrName = QRCodeUtil.encode(content, destPath); //调用二维码工具方法
}else{ //内嵌Logo
String logoPath = req.getServletContext().getRealPath(FileUploadConstant.LOGO_PATH)+File.separator+fileName;
qrName = QRCodeUtil.encode(content,logoPath, destPath);
}
req.setAttribute("qrName",qrName); req.setAttribute("qrurl",FileUploadConstant.QR_URL+FileUploadConstant.QR_PATH+"//"+qrName);
req.getRequestDispatcher("/down.jsp").forward(req, resp);}
上面代码主要是获取到表单传过来的数据(文本域内容以及文件),判断是否生成带logo的二维码,调用二维码工具类相应的生成方法。
QRCodeUtil工具类部分代码(由于篇幅有限,只贴出关键代码)
//生成二维码,有logo的
public static String encode(String content, String imgPath, String destPath,
boolean needCompress) throws Exception {
BufferedImage image = QRCodeUtil.createQRImage(content,imgPath,
needCompress);
mkdirs(destPath); //当文件不存在时,创建多层目录
String file = System.currentTimeMillis()+".jpg";//文件名
ImageIO.write(image, FORMAT_NAME, new File(destPath+"/"+file));
return file;
}
//生成二维码方法
private static BufferedImage createQRImage(String content, String imgPath,
boolean needCompress) throws Exception {
Hashtable<EncodeHintType, Object> ht= new Hashtable<EncodeHintType, Object>();
//// 指定纠错等级
ht.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
//解码设置编码方式为utf-8 上面代码定义CHARSET是常量值为UTF-8
ht.put(EncodeHintType.CHARACTER_SET, "UTF-8");
ht.put(EncodeHintType.MARGIN, 1); //边距
BitMatrix bitMatrix = new MultiFormatWriter().encode(content,
BarcodeFormat.QR_CODE, QRCODE_SIZE, QRCODE_SIZE, ht);
int width = bitMatrix.getWidth();//获取宽度
int height = bitMatrix.getHeight();获取高度
//将BitMatrix转换成BufferedImage
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;
}
//调用insertImage方法 插入logo图片
QRCodeUtil.insertImage(image, imgPath, needCompress);
return image;
}
从上面代码可以看出先实例化一个Hashtable对象,key为EncodeHintType,值为Object
,将参数添加到Hashtable中,在MultiFormatWriter().encode()方法中分别放进需要的参数,包括上面实例化的Hashtable后,将返回的BitMatrix转换成BufferedImage,调用定义好的insertImage()方法将logo图片插入到二维码中
private static void insertImage(BufferedImage source, String imgPath,
boolean compress) throws Exception {
// 省略了对图片文件是否存在的判断的代码
Image src = ImageIO.read(new File(imgPath));
int width = src.getWidth(null);
int height = src.getHeight(null);
if (compress) {//压缩logo图片
if (width >65) {
width =65;
}
if (height >65) {
height =65;
}
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;
}
// 创建一个 Graphics2D,可以将它绘制到此 BufferedImage 中。
Graphics2D graph = source.createGraphics();
int x = (QRCODE_SIZE - width) / 2;
int y = (QRCODE_SIZE - height) / 2;
/*绘制图片,参数分别是加载图像,x,y是指定绘制图像矩形左上角的位置,width是
是指定绘制图像矩形的宽,width是指定绘制图像矩形的高,最后那个是绘制图像容器,这里设为null*/
graph.drawImage(src, x, y, width, height, null);
Shape shape = new RoundRectangle2D.Float(x, y, width, width, 6, 6);
graph.setStroke(new BasicStroke(3f)); //设garphics2D 上下文设置 Stroke
graph.draw(shape); //使用当前 Graphics2D 上下文的设置勾画 Shape 的轮廓。
graph.dispose();
}
上面代码主要使用Graphics2D对图像进行了绘制处理
由于代码较多而篇幅有限,只贴出部分代码。
效果