Spring MVC:图片验证码的生成与返回
来源:互联网 发布:流行音乐知乎 编辑:程序博客网 时间:2024/06/06 16:51
参考项目:https://git.oschina.net/lonecloud/imageVerify
效果
代码
模型
//分类图片和保存图片数量和路径public class ImageGroup { private String name; //图片组名称 private int count;//图片组数量 private Set<String> paths=new HashSet<String>();//图片组图片路径 public ImageGroup(String name,int count,String...paths){ this.name=name; this.count=count; this.paths.addAll(Arrays.asList(paths)); } //省略getter和setter方法}
//生成的图片组public class GenerateImageGroup { private ImageGroup keyGroup;//关键图片组 private List<ImageGroup> unkeyGroups;//其他图片组 //省略getter和setter方法}
public class BufferedImageWrap { private boolean key;//是否关键图片 private String name; private BufferedImage bufferedImage; //省略getter和setter方法}
生成图片验证码的具体工具类
//用于生成随机图片并合并public class ImageGenerate { private static final int WIDTH=100;//一张图片的宽度 private static final int HEADER=30;//标题宽度 private static final int HEIGHT=100;//一张图片的高度 private static String realPath; private static Map<String,ImageGroup> imageGroups=new HashMap<>(); private static Map<Integer,Map<String,ImageGroup>> countImageGroups=new HashMap<>(); public static void init(){ initImageGroup(); initImageGroupMap(); } public static void initImageGroup(){ ImageGroup group=new ImageGroup("订书机",2,"dsj/1.jpg","dsj/2.jpg"); ImageGroup group0=new ImageGroup("书本",2,"book/1.jpg","book/2.jpg"); ImageGroup group1=new ImageGroup("蘑菇",2,"mg/1.jpg","mg/2.jpg"); ImageGroup group2=new ImageGroup("云",2,"cloud/1.jpg","cloud/2.jpg"); ImageGroup group3=new ImageGroup("吸铁石",2,"xts/1.jpg","xts/2.jpg"); ImageGroup group4=new ImageGroup("包包",4,"bb/1.jpg","bb/2.jpg","bb/3.jpg","bb/4.jpg"); ImageGroup group5=new ImageGroup("柚子",4,"yz/1.jpg","yz/2.jpg","yz/3.jpg","yz/4.jpg"); ImageGroup group6=new ImageGroup("糖葫芦",4,"thl/1.jpg","thl/2.jpg","thl/3.jpg","thl/4.jpg"); ImageGroup group7=new ImageGroup("老虎",4,"lh/1.jpg","lh/2.jpg","lh/3.jpg","lh/4.jpg"); ImageGroup group8=new ImageGroup("土豆",6,"td/1.jpg","td/2.jpg","td/3.jpg","td/4.jpg","td/5.jpg","td/6.jpg"); ImageGroup group9=new ImageGroup("仙人球",6,"xrq/1.jpg","xrq/2.jpg","xrq/3.jpg","xrq/4.jpg","xrq/5.jpg","xrq/6.jpg"); ImageGroup group10=new ImageGroup("兔子",6,"tz/1.jpg","tz/2.jpg","tz/3.jpg","tz/4.jpg","tz/5.jpg","tz/6.jpg"); initImageGroupMap(group,group0,group1,group2,group3,group4,group5,group6,group7,group8,group9,group10); } public static void initImageGroupMap(ImageGroup...groups){ for(ImageGroup group:groups){ imageGroups.put(group.getName(), group); if (!countImageGroups.containsKey(group.getCount())) { countImageGroups.put(group.getCount(), new HashMap<String,ImageGroup>()); } countImageGroups.get(group.getCount()).put(group.getName(), group); } } public static void Genreate(HttpServletResponse response,HttpSession session){ init(); realPath=session.getServletContext().getRealPath("/assets/"); GenerateImageGroup groups=getRandomImageGroup(); List<BufferedImageWrap> images= getBufferedImageGroups(groups); mergeAndReturn(images,response,session); } //合并图片并返回至页面 public static void mergeAndReturn(List<BufferedImageWrap> images, HttpServletResponse response,HttpSession session){ Collections.shuffle(images);//打乱原有顺序 BufferedImage targetImage=new BufferedImage( 4*WIDTH,HEADER+2*HEIGHT,BufferedImage.TYPE_INT_RGB); int x=0; int y=0; int order=0; List<Integer> keyOrders=new ArrayList<>();//存放关键图片所在位置(0-7) BufferedImage bufferedImage=null; boolean firstKey=true; for(BufferedImageWrap image:images){ bufferedImage=image.getBufferedImage(); int x1=0,y1=0; if(bufferedImage.getWidth()>WIDTH){ x1=RandomIntGenerate.getRandomInt(bufferedImage.getWidth()-WIDTH); } if(bufferedImage.getHeight()>HEIGHT){ y1=RandomIntGenerate.getRandomInt(bufferedImage.getHeight()-HEIGHT); } int[] rgb=bufferedImage.getRGB(x1,y1,WIDTH, HEIGHT,null, 0, WIDTH); if(image.isKey()){ if(firstKey){ Graphics2D g=(Graphics2D)targetImage.getGraphics(); g.setColor(Color.WHITE); g.fillRect(0, 0, 4*WIDTH, HEADER); g.setFont(new Font("宋体",Font.PLAIN,14)); g.setColor(Color.BLACK); g.drawString("请在图下选中所有的 ", 0, HEADER/2); g.setFont(new Font("宋体",Font.BOLD,16)); g.setColor(Color.RED); g.drawString(image.getName(), 150, HEADER/2); firstKey=false; } keyOrders.add(order); } x=(order%4)*WIDTH; y=order<4?HEADER:HEADER+HEIGHT; //System.out.println(x+"\n"+y); targetImage.setRGB(x, y, WIDTH, HEIGHT, rgb, 0, WIDTH); ++order; } session.setAttribute("verifyCode", keyOrders);//将关键图片所在序号存入session try { ImageIO.write(targetImage, "jpg", response.getOutputStream());//往页面写回合并的图片 } catch (IOException e) { e.printStackTrace(); } } public static List<BufferedImageWrap> getBufferedImageGroups(GenerateImageGroup generatedGroups){ List<BufferedImageWrap> imageWraps=new ArrayList<>(); for(String shortPath:generatedGroups.getKeyGroup().getPaths()){ imageWraps.add(new BufferedImageWrap(true,generatedGroups.getKeyGroup().getName(),realPath+shortPath)); } for(ImageGroup group:generatedGroups.getUnkeyGroups()){ for(String shortPath:group.getPaths()){ imageWraps.add(new BufferedImageWrap(false,"",realPath+shortPath)); } } return imageWraps; } public static GenerateImageGroup getRandomImageGroup(){ int randInt; String randName; int leftCount; ImageGroup keyImageGroup; List<ImageGroup> unKeyImageGroups=new ArrayList<>(); //获取关键图片组 randInt=RandomIntGenerate.getRandomInt(imageGroups.size()); randName=new ArrayList<String>(imageGroups.keySet()).get(randInt); keyImageGroup=imageGroups.get(randName); //移除已选关键图片组 Map<Integer,Map<String,ImageGroup>> tmpMap=new HashMap(countImageGroups); tmpMap.get(keyImageGroup.getCount()).remove(keyImageGroup.getName()); leftCount=8-keyImageGroup.getCount();//最终是用8张小图片合成一张 List<ImageGroup> groups=null; //非关键图片为6张时 if(leftCount==6){ //为偶数时,得到4+2非关键图片组 if(RandomIntGenerate.getRandomInt()%2==0){ groups=new ArrayList<ImageGroup>(tmpMap.get(4).values()); randInt=RandomIntGenerate.getRandomInt(groups.size()); unKeyImageGroups.add(groups.get(randInt)); groups=new ArrayList<ImageGroup>(tmpMap.get(2).values()); randInt=RandomIntGenerate.getRandomInt(groups.size()); unKeyImageGroups.add(groups.get(randInt)); } //奇数时,得到3*2张图片组 else{ groups=new ArrayList<ImageGroup>(tmpMap.get(2).values()); for(int i=0;i<3;i++){ randInt=RandomIntGenerate.getRandomInt(groups.size()); unKeyImageGroups.add(groups.get(randInt)); groups.remove(randInt); } } } else if(leftCount==4){ //得到1*4张图片组 if(RandomIntGenerate.getRandomInt()%2==0){ groups=new ArrayList<ImageGroup>(tmpMap.get(4).values()); randInt=RandomIntGenerate.getRandomInt(groups.size()); unKeyImageGroups.add(groups.get(randInt)); } //得到2*2张图片组 else{ groups=new ArrayList<ImageGroup>(tmpMap.get(2).values()); for(int i=0;i<2;i++){ randInt=RandomIntGenerate.getRandomInt(groups.size()); unKeyImageGroups.add(groups.get(randInt)); groups.remove(randInt); } } } else if(leftCount==2){ groups=new ArrayList<ImageGroup>(tmpMap.get(2).values()); randInt=RandomIntGenerate.getRandomInt(groups.size()); unKeyImageGroups.add(groups.get(randInt)); } return new GenerateImageGroup(keyImageGroup,unKeyImageGroups); }}
//用于生成随机数public class RandomIntGenerate { public static Random random=new Random(); public static int getRandomInt(){ return random.nextInt(); } public static int getRandomInt(int max){ return random.nextInt(max); }}
Controller
@Controllerpublic class VerifyCodeController { @RequestMapping("/getVerifyCode") public void getVerifyCode(HttpServletResponse response,HttpSession session){ ImageGenerate.Genreate(response, session); } @RequestMapping("/verify") @ResponseBody public String verify(String verifyCode,HttpSession session){ String [] coordinates=verifyCode.split(";"); List<Integer> orders=(List<Integer>)session.getAttribute("verifyCode"); if(coordinates.length!=orders.size()){ return "unpass"; } int order=0; for(String coordinate:coordinates){ String[] offsets=coordinate.split(","); order=getSelectedOrder(Integer.parseInt(offsets[0]),Integer.parseInt(offsets[1])); //System.out.println(order); if(!orders.contains(order)){ return "unpass"; } } //System.out.println(verifyCode); return "pass"; } //根据坐标确定用户选择了哪几张图片 public int getSelectedOrder(int x,int y){ int order; if(x>300){ order=3; } else if(x>200){ order=2; } else if(x>100){ order=1; } else{ order=0; } if(y>100){ order+=4; } return order; }}
页面代码
<!--/WEB-INF/pages/index.jsp--><html><head><meta charset="utf-8"><title>图片验证码实现</title><link rel="stylesheet" href="css/index.css"/><script src="js/jquery-3.2.1.min.js"></script></head><body><div class="img-wrapper"><img src="getVerifyCode.html"/></div><div class="btns-div"> <a href="javascript:void(0);" class="refresh-btn">换一张</a> <a href="javascript:void(0);" class="submit-btn">验证</a></div><script src="js/index.js"></script></body></html>
//js/index.js$(function(){ var maxWidth=400; var maxHeight=200; var offset=30; var verifyCode=""; $(".img-wrapper").click(function(e){ var offsetx=e.offsetX; var offsety=e.offsetY; if(offsety<30){ return ; } var leftVal=offsetx-12; var topVal=offsety-12; leftVal=leftVal<0?0:leftVal; leftVal=leftVal>maxWidth-24?maxWidth-24:leftVal; topVal=topVal<offset?offset:topVal; topVal=topVal>maxHeight+offset-24?maxHeight+offset-24:topVal; var pickDiv=$("<div class='pick-div'><img src='assets/pickon.png'/></div>"); pickDiv.css("position","absolute"); pickDiv.css("left",leftVal+"px"); pickDiv.css("top",topVal+"px"); verifyCode+=leftVal+","+(topVal-offset)+";"; //console.log(verifyCode); $(this).append(pickDiv); }); $(".img-wrapper").on("click",".pick-div",function(e){ //console.log(verifyCode); var target=$(this)[0].offsetLeft+","+$(this)[0].offsetTop+";"; verifyCode=verifyCode.replace(target,""); $(this).remove(); e.stopPropagation(); }); $(".refresh-btn").click(function(){ verifyCode=""; $(".pick-div").remove(); $(".img-wrapper img").attr("src","getVerifyCode.html?date="+new Date().getTime()); }); $(".submit-btn").click(function(){ verifyCode=verifyCode.substring(0,verifyCode.length-1);// console.log(verifyCode); $.ajax({ url:"verify.html", data:{"verifyCode":verifyCode}, type:"POST", //dataType:"json", success:function(data){ alert(data); $(".refresh-btn").click(); } }); });});
<!--css/index.css-->.img-wrapper{position:relative;}.img-wrapper img{ width:400px; height:230px;}.pick-div{position:absolute;}.pick-div img{ width:24px; height:24px;}.btns-div{ width:400px; text-align:center;}.btns-div a{ display:inline-block; line-height:30px; width:60px; color:#FFF; font-size:16px; text-align:center; text-decoration:none; border-radius:1px; background-color:#0AC516;}.btns-div a:hover{background-color:#0AAA16;}
相关配置
<!--springmvc-servlet.xml--><mvc:annotation-driven/> <context:component-scan base-package="com.imageverify.controller"/> <!-- 配置根视图 --> <mvc:view-controller path="/" view-name="index"/> <!-- 静态资源配置 --> <mvc:resources location="/assets/" mapping="/assets/**"/> <mvc:resources location="/js/" mapping="/js/**"/> <mvc:resources location="/css/" mapping="/css/**"/> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/pages/" /> <property name="suffix" value=".jsp" /> </bean>
完整代码请转到github:https://github.com/crazylai1996/image-verify-springmvc.git
阅读全文
0 0
- Spring MVC:图片验证码的生成与返回
- 基于spring MVC 的验证码生成
- MVC 生成图片验证码
- Spring MVC生成验证码
- Spring MVC 生成验证码
- spring MVC中引入captcha的插件生成图片验证码
- 在spring MVC中引入captcha的插件生成图片验证码
- Spring MVC 图片验证码
- Spring mvc与JKaptcha组合生成验证码
- Spring MVC返回BLOB类型的图片
- patchca整合Spring MVC生成超炫的验证码
- spring-mvc 运用 kaptcha实现验证码的生成
- patchca整合Spring MVC生成超炫的验证码
- patchca整合Spring MVC生成超炫的验证码
- patchca整合Spring MVC生成漂亮的验证码
- (spring mvc)使用google的kaptcha生成验证码
- patchca整合Spring MVC生成超炫的验证码
- spring mvc使用Google的kaptcha生成验证码
- Android主题Theme的了解
- Spring4整合Hibernate4.3
- MyBatis学习总结(一)——MyBatis快速入门
- R-CNN,SPP-NET, Fast-R-CNN,Faster-R-CNN, YOLO, SSD系列深度学习检测方法梳理
- 单片机时钟程序(3)control.h
- Spring MVC:图片验证码的生成与返回
- 第三方控件使用
- Python 爬虫(二)
- Codeforces 817A Treasure Hunt
- leetcode238. Product of Array Except Self
- JAVA字节转换
- 腾讯云FPGA的深度学习算法
- Android使用CountDownTimer实现短信验证码倒计时
- 使用百度地图SDK进行地址搜索、定位的工作小结