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<ActivityUnroutine> activityUnroutineList = activityUnroutineMapper.queryActivityListById(goodid);
if(activityUnroutineList != null){
for (int i=0;i<activityUnroutineList.size();i++){
if (StringUtils.isNotEmpty(activityUnroutineList.get(i).getActivityName())){
String activityNames= activityUnroutineList.get(i).getActivityName();
if (activityNames.length()>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<picture.length;i++) {
if(picture[i].trim().length()>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<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();
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.
还有一点:后台代码中调用方法生成的图片,并不是保存到本地,还是服务器内存需要定时清除