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

原创粉丝点击