您的位置:首页 > 编程语言 > Java开发

Spring MVC:图片验证码的生成与返回

2017-06-24 17:53 471 查看
参考项目: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

@Controller
public 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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息