private BufferedImage image; private int imageWidth = 750; //图片的宽度 private int imageHeight = 1350; //图片的高度 @Override public String queryFindEntityGoodPictureDetail(Long id, Long groupId, Long memberId, String url) throws Exception { int H_title = 300; //头部高度 int H_activity = 430; //活动高度 int H_mainPic = 700; //广告高度 int H_tip = 300; //商品价格栏 int tip_2_top = (H_title+H_mainPic); MallEntityGood mallEntityGood=mallEntityGoodMapper.queryFindEntityGoodPictureDetail(id,groupId); image = new BufferedImage(imageWidth, imageHeight, BufferedImage.TYPE_INT_RGB); //设置图片的背景色 Graphics2D main = image.createGraphics(); main.setColor(Color.white); main.fillRect(0, 0, imageWidth, imageHeight); //***********************页面头部 Graphics title = image.createGraphics(); title.setColor(Color.BLACK); // 设置字体 Font titleFont = new Font("宋体", Font.BOLD, 52); title.setFont(titleFont); // 如果商品名大于12个字符,截取12个字符在第一行中显示,剩余的在第二行显示 // 完成之后优化 考虑用户在使用英文的前提下 每行字数乘两倍 if(mallEntityGood.getName().length()>14) { String goodName1=mallEntityGood.getName().substring(0,14); if(mallEntityGood.getName().length()>14 && mallEntityGood.getName().length()<27){ String goodName2=mallEntityGood.getName().substring(14); title.drawString(URLDecoder.decode(goodName2, "UTF-8"), 20, (H_title)/3+80); }else if(mallEntityGood.getName().length()>27){ String goodName2=mallEntityGood.getName().substring(14,27); title.drawString(URLDecoder.decode(goodName2, "UTF-8")+"...", 20, (H_title)/3+80); } title.drawString(URLDecoder.decode(goodName1, "UTF-8"), 20, (H_title)/3+5); }else { title.drawString(URLDecoder.decode(mallEntityGood.getName(), "UTF-8"), 20, (H_title)/3+5); } // 获取商品所参加的活动 // 标题之下(商品所属活动) Graphics activity = image.createGraphics(); activity.setColor(Color.red); Font activityFont = new Font("宋体", Font.BOLD, 38); activity.setFont(activityFont); String goodid=String.valueOf(id); List activityUnroutineList = activityUnroutineMapper.queryActivityListById(goodid); if(activityUnroutineList != null){ for (int i=0;i 20){ activity.drawString( "活动:"+URLDecoder.decode(activityNames, "UTF-8").substring(0,21)+"...", 20, (H_activity)/2); }else { activity.drawString( "活动:"+URLDecoder.decode(activityNames, "UTF-8"), 20, (H_activity)/2); } break; } } }else{ String activityName=""; activity.drawString( activityName, 20, (H_activity)/2); } //***********************插入中间广告图 Graphics mainPic = image.getGraphics(); BufferedImage bimg = null; // 获取商品图片 if(mallEntityGood.getPicture()!=null) { String[] picture = mallEntityGood.getPicture().trim().split(","); for(int i=0;i 0){ bimg=ImageIO.read(new URL(picture[i]).openStream()); mainPic.drawImage(bimg, 0, H_title, imageWidth, H_mainPic, null); mainPic.dispose(); break; } } } // 价格以及小图标的排布 Graphics2D tip = image.createGraphics(); tip.setColor(Color.red); Font tipFont = new Font("宋体", Font.BOLD, 52); tip.setFont(tipFont); DecimalFormat df = new DecimalFormat(".00"); tip.drawString("¥"+ df.format(mallEntityGood.getPromotionPrice()/100), 300, tip_2_top+(H_tip)/2-40); Font btnFont = new Font("宋体", Font.PLAIN, 26); Graphics2D btn1 = image.createGraphics(); btn1.setColor(Color.red); btn1.setFont(btnFont); Graphics mainPic3 = image.getGraphics(); BufferedImage bimg3 = null; String imgurl3="http://ebank007.oss-cn-hangzhou.aliyuncs.com/20180731173813D9PJ9Q.jpg"; bimg3=ImageIO.read(new URL(imgurl3).openStream()); int width = bimg3.getWidth(); int height = bimg3.getHeight(); mainPic3.drawImage(bimg3, 580, tip_2_top+(H_tip)/2-80, width, height, null); mainPic3.dispose(); Font btnFont2 = new Font("宋体", Font.PLAIN, 36); Graphics2D btn2 = image.createGraphics(); btn2.setColor(Color.black); btn2.setFont(btnFont2); String salePrice="原价"; btn2.drawString(URLDecoder.decode(salePrice, "UTF-8")+": ¥"+df.format(mallEntityGood.getSalePrice()/100), 300, tip_2_top+(H_tip)/2+30); btn2.drawString("------------", 300, tip_2_top+(H_tip)/2+30); // 确定二维码所在的位置 Graphics2D tip1 = image.createGraphics(); tip1.setColor(Color.black); Font tipFont2 = new Font("宋体", Font.PLAIN, 28); tip1.setFont(tipFont2); String ccLog="长按识别二维码"; tip1.drawString("["+URLDecoder.decode(ccLog, "UTF-8")+"]", 35, tip_2_top+(H_tip)/2+180); // 用户分享链接二维码 String shareGoodQRcode=url+"/api/oAuth2/goodDetailShare?gid="+id+"&"+"memberid="+memberId+"&"+"groupId="+groupId; int qrcode_height=250; int qrcode_width=250; BufferedImage image = createImage1(shareGoodQRcode, qrcode_width, qrcode_height); // 确定二维码在图中的位置 Graphics mainPic1 = this.image.getGraphics(); if(image!=null){ mainPic1.drawImage(image, 20, tip_2_top+30, qrcode_width, qrcode_height, null); mainPic1.dispose(); } String uuid = UUID.randomUUID().toString(); createImage(uuid+".png"); // 内存中文件存储的文件夹的位置 /* File dir=new File(uuid+".png"); File[] lst=dir.listFiles(); for (File f:lst){ // 三天自动清除文件(失效处理) if (new Date().getTime()-f.lastModified()>24*60*60*1000*3){ f.delete(); } }*/ File dir=new File(uuid+".png"); if (new Date().getTime()-dir.lastModified()>24*60*60*1000*3){ dir.delete(); } InputStream in = null; byte[] data = null; //读取图片字节数组 try { in = new FileInputStream(uuid+".png"); data = new byte[in.available()]; in.read(data); in.close(); } catch (IOException e) { e.printStackTrace(); } //对字节数组Base64编码 BASE64Encoder encoder = new BASE64Encoder(); return encoder.encode(data); //返回Base64编码过的字节数组字符串 // FileImageInputStream input = new FileImageInputStream(new File("1.png")); // ByteArrayOutputStream output = new ByteArrayOutputStream(); // byte[] buf = new byte[1024]; // int numBytesRead = 0; // while ((numBytesRead = input.read(buf)) != -1) { // output.write(buf, 0, numBytesRead); // } // byte[] data = output.toByteArray(); // output.close(); // input.close(); // return data; } /** * 二维码图片的生成 * @param content 链接 * @param qrcode_width 二维码宽 * @param qrcode_height 二维码高 * @return * @throws Exception */ public static BufferedImage createImage1(String content, int qrcode_width, int qrcode_height) throws Exception { Hashtable hints = new Hashtable (); hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H); hints.put(EncodeHintType.CHARACTER_SET, "utf-8"); hints.put(EncodeHintType.MARGIN, 1); BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, qrcode_width, qrcode_height, 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); } } return image; } //生成图片文件 @SuppressWarnings("restriction") public void createImage(String fileLocation) { BufferedOutputStream bos = null; if(image != null) { try { FileOutputStream fos = new FileOutputStream(fileLocation); bos = new BufferedOutputStream(fos); JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(bos); encoder.encode(image); fos.close(); bos.close(); } catch (Exception e) { e.printStackTrace(); } finally { if (bos != null) {//关闭输出流 try { bos.close(); } catch (IOException e) { e.printStackTrace(); } } } } } 需要注意的是:后台数据合成的图片后 返回Base64 String时 前端微信显示会出现中文乱码 这一点是因为,开发时window本地下,系统中含有宋体.楷体等资源,而在服务器上 是没有这些字体的需要导入TTF相匹配的肢体文件,之后重启nginx中tomcat. 还有一点:后台代码中调用方法生成的图片,并不是保存到本地,还是服务器内存需要定时清除