public void createImage(HttpServletResponse resp, HttpServletRequest request,String xcode) throws IOException { TraceLoggerUtil.info("执行微信端图片验证码接口请求参数:xcode{}",xcode); switch (random.nextInt(5)) { case 0: cs.setFilterFactory(new CurvesRippleFilterFactory(cs.getColorFactory())); break; case 1: cs.setFilterFactory(new MarbleRippleFilterFactory()); break; case 2: cs.setFilterFactory(new DoubleRippleFilterFactory()); break; case 3: cs.setFilterFactory(new WobbleRippleFilterFactory()); break; case 4: cs.setFilterFactory(new DiffuseRippleFilterFactory()); break; } HttpSession session = request.getSession(false); if (session == null) { session = request.getSession(); } if (ChkUtil.isEmpty(xcode)) { return; } setResponseHeaders(resp); String token = EncoderHelper.getChallangeAndWriteImage(cs, "png", resp.getOutputStream()); redisService.setex(xcode, token, 5*60); session.setAttribute(PubVariable.VERIFICATION_CODE_SESSION, token); } protected void setResponseHeaders(HttpServletResponse response) { response.setContentType("image/png"); response.setHeader("Cache-Control", "no-cache, no-store"); response.setHeader("Pragma", "no-cache"); long time = System.currentTimeMillis(); response.setDateHeader("Last-Modified", time); response.setDateHeader("Date", time); response.setDateHeader("Expires", time); }
今天遇到一个需求须要将生成验证码的接口修改成能够返回状态的接口。以前的代码是以流的形式直接返回后台,返回值为void。使用的是com.github.bingoohuang的jar包。前端
可是出现问题是如今须要返回带有状态的json串,而后将图片信息放在参数内,给前端在status为200的时候才展现图片信息。这时候能够将随机验证码图片进行Base64编码以后前端使用。git
如下贴代码:github
public String createImage(HttpServletResponse resp, HttpServletRequest request
,String xcode,String phone,String from ) {
JSONObject resultObject = new JSONObject();
TraceLoggerUtil.info("执行微信端图片验证码接口请求参数:xcode{},phone{},from{}",xcode,phone,from);
try{
/**
* from =1 的时候须要判断当前手机号是否存在 若是存在直接返回300 手机号已存在
*/
if (!ChkUtil.isEmpty(from) && "1".equals(from)) {
JSONObject phoneJson = JSONObject.parseObject(bgCustomerService.getCustomer(phone));
if (phoneJson.get(com.zw.rule.util.weChatUtil.consts.MsgConsts.RESPONSE_CODE).equals(com.zw.rule.util.weChatUtil.consts.MsgConsts.WECHAT_ERRO_CODE)) {
resultObject.put(com.zw.base.util.MsgConsts.WECHAT_RESPONSE_STATUS, com.zw.base.util.MsgConsts.WECHAT_ERROR_STATUS_CODE);
resultObject.put(com.zw.base.util.MsgConsts.WECHAT_RESPONSE_MESSAGE, "手机号已存在");
return resultObject.toString();
}
}
/**
* from =2 的时候须要判断当前手机号是否存在 若是存在直接返回300 手机号不存在
*/
if (!ChkUtil.isEmpty(phone) && "2".equals(phone)) {
JSONObject phoneJson = JSONObject.parseObject(bgCustomerService.getCustomer(phone));
if (phoneJson.get(com.zw.rule.util.weChatUtil.consts.MsgConsts.RESPONSE_CODE).equals(com.zw.rule.util.weChatUtil.consts.MsgConsts.SUCCESS_CODE)) {
resultObject.put(com.zw.base.util.MsgConsts.WECHAT_RESPONSE_STATUS, com.zw.base.util.MsgConsts.WECHAT_ERROR_STATUS_CODE);
resultObject.put(com.zw.base.util.MsgConsts.WECHAT_RESPONSE_MESSAGE, "手机号不存在");
return resultObject.toString();
}
}
// 禁止图像缓存,使得单击验证码能够刷新验证码图片
resp.setHeader("Pragma", "nocache");
resp.setHeader("Cache-Control", "no-cache");
resp.setDateHeader("Expires", 0);
resp.setContentType("image/jpeg");
resp.setHeader("Access-Control-Allow-Origin", "*");
BufferedImage bim = new BufferedImage(100, 40,
BufferedImage.TYPE_INT_RGB);
Font f = new Font("宋体",Font.BOLD ,20);
Graphics2D gc = bim.createGraphics();
//设置字体
gc.setFont(f);
// 设置图片填充颜色
gc.setColor(Color.yellow);
gc.fillRect(0, 0, 100, 40);
// 设置边框颜色
gc.setColor(Color.pink);
gc.drawRect(0, 0, 99, 39);
// 产生4位随机数
Random rand = new Random();
StringBuffer sb = new StringBuffer();
// 设置干扰线颜色
gc.setColor(Color.cyan);
for (int j = 0; j < 30; j++) {
int x = rand.nextInt(99);
int y = rand.nextInt(39);
int x1 = rand.nextInt(6);
int y1 = rand.nextInt(6);
// 往图片里面画干扰线
gc.drawLine(x, y, x + x1, y + y1);
}
for (int i = 0; i < 4; i++) {
int m = rand.nextInt(9);
// 将生成的数字写入到图片中去,int转成string
String str = String.valueOf(m);
// 设置字体颜色
gc.setColor(Color.RED);
gc.drawString(str, i * 20 + 20, 30);
sb.append(m);
}
// 将stringbuffer转成string
String sb1 = String.valueOf(sb);
redisService.setex(xcode, sb1, 5*60);
// 将图片以流的形式输出
ServletOutputStream sos = resp.getOutputStream();
//ImageIO.write(bim, "jpg", sos);
// 建立编码对象
Base64.Encoder base64 = Base64.getEncoder();
// 建立字符流
ByteArrayOutputStream bs = new ByteArrayOutputStream();
// 写入字符流
ImageIO.write(bim, "jpg", bs);
// 转码成字符串
String imgsrc = base64.encodeToString(bs.toByteArray());
resultObject.put("imgsrc",imgsrc);
resultObject.put(com.zw.base.util.MsgConsts.WECHAT_RESPONSE_STATUS, com.zw.base.util.MsgConsts.WECHAT_SUCCESS_STATUS_CODE);
resultObject.put(com.zw.base.util.MsgConsts.WECHAT_RESPONSE_MESSAGE, com.zw.base.util.MsgConsts.WECHAT_MESSAGE_SUCCESS);
}catch (Exception e){
TraceLoggerUtil.error(e.getMessage(),e);
resultObject.put(com.zw.base.util.MsgConsts.WECHAT_RESPONSE_STATUS, com.zw.base.util.MsgConsts.WECHAT_ERROR_STATUS_CODE);
resultObject.put(com.zw.base.util.MsgConsts.WECHAT_RESPONSE_MESSAGE, com.zw.base.util.MsgConsts.SYS_EXCEPTION);
return resultObject.toString();
}
return resultObject.toString();
}
如下代码有变动点:ajax
1.resp.setHeader("Access-Control-Allow-Origin", "*"); 这是因为前端使用ajax访问的时候跨域了,设置这个以后就不会跨域访问redis
2.Font f = new Font("宋体",Font.BOLD ,20); gc.setFont(f); 这里是因为字体偏小,因此调大字体为宋体20号json
3.gc.fillRect(0, 0, 100, 40); gc.drawRect(0, 0, 99, 39); int x = rand.nextInt(99); int y = rand.nextInt(39);跨域
我的理解这些数字都和最后返回的图片有关。返回前端图片为100*40那么 drawRect 的最后两个数字为 100-1 40-1 int x为100-1 int y 为40 -1xcode
4.gc.drawString(str, i * 20 + 20, 30); 这个根据图片的宽和高计算,最终数字的位置为20,40,60,80 高固定在30 缓存
以上这些须要根据前端须要自行调节。微信
前端使用方式为:
<img src=”data:image/jpg;base64,imgcode”> imgcode 就是返回回去的base64位的imgsrc
点击后动态的赋值便可。