最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java仿12306圖片驗證碼

 更新時間:2016年04月13日 14:12:32   作者:青狼的華麗變身  
這篇文章主要為大家詳細介紹了Java仿12306的圖片驗證碼的相關資料,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下

由于要做一個新項目,所以打算做一個簡單的圖片驗證碼。

先說說思路吧:在服務端,從一個文件夾里面找出8張圖片,再把8張圖片合并成一張大圖,在8個小圖里面隨機生成一個要用戶驗證的圖片分類,如小狗、啤酒等。在前端,訪問這個頁面時,把圖片加載上去,用戶在圖片上選擇提示所需要的圖片,當用戶點登陸時,根據用戶選擇的所有坐標判斷所選的圖片是不是實際上的驗證圖片。

先放兩張效果圖:

為了讓文件查找比較簡單,在圖片文件結構上可以這樣:

這樣方便生成用戶要選擇的Key圖片,和取出8張小圖合并成大圖。

上代碼:這是選擇8張圖片,并且在每張圖片選取時用遞歸保證選取的圖片不會重復。

//選取8個圖片
public static List<Object> getEightImages() {
 //保存取到的每一個圖片的path,保證圖片不會重復
 List<String> paths = new ArrayList<String>();
 
 File[] finalImages = new File[8];
 List<Object> object = new ArrayList<Object>();
 
 //保存tips
 String[] tips = new String[8];
 
 for (int i = 0; i < 8; i++) {
 //獲取隨機的二級目錄
 int dirIndex = getRandom(secondaryDirNumbers);
 File secondaryDir = getFiles()[dirIndex];
  
 //隨機到的文件夾名稱保存到tips中
 tips[i] = secondaryDir.getName();
  
 //獲取二級圖片目錄下的文件
 File[] images = secondaryDir.listFiles();
  
 int imageIndex = getRandom(imageRandomIndex);
 File image = images[imageIndex];
  
 //圖片去重
 image = dropSameImage(image, paths, tips, i); 
  
 paths.add(image.getPath());
 
 finalImages[i] = image;
  
 }
 object.add(finalImages);
 object.add(tips);
 return object;
} 

在生成這8張圖片中,用一個數組保存所有的文件分類。在這個分類里面可以用隨機數選取一個分類做為Key分類,就是用戶要選擇的所有圖片。由于數組是有序的,可以遍歷數組中的元素,獲取每個key分類圖片的位置,方便在用戶驗證時,進行匹配。

//獲取位置,返回的是第幾個圖片,而不是下標,從1開始,集合第一個元素為tip
 public static List<Object> getLocation(String[] tips) {
 List<Object> locations = new ArrayList<Object>();
 
 //獲取Key分類
 String tip = getTip(tips);
 locations.add(tip);
  
 int length = tips.length;
 for (int i = 0; i < length; i++) {
  if (tip.equals(tips[i])) {
 
  locations.add(i+1);
  }
 }
 return locations;
 }
 

選取了8張圖片后,接下來就是合并圖片。合并圖片可以用到BufferedImage這個類的方法:setRGB()這個方法如果不明白可以看下api文檔,上面有詳細的說明。

public static void mergeImage(File[] finalImages, HttpServletResponse response) throws IOException {
   
 //讀取圖片
 BufferedImage mergeImage = new BufferedImage(800, 400, BufferedImage.TYPE_INT_BGR);
  
 for (int i = 0; i < 8; i++) {
  File image = finalImages[i];
  
  BufferedImage bufferedImage = ImageIO.read(image);
  int width = bufferedImage.getWidth();
  int height = bufferedImage.getHeight();
  //從圖片中讀取RGB
  int[] imageBytes = new int[width*height];
  imageBytes = bufferedImage.getRGB(0, 0, width, height, imageBytes, 0, width);
  if ( i < 4) {
  mergeImage.setRGB(i*200, 0, width, height, imageBytes, 0, width);
  } else {
  mergeImage.setRGB((i -4 )*200, 200, width, height, imageBytes, 0, width);
  }  
  
 }
 
 
 ImageIO.write(mergeImage, "jpg", response.getOutputStream());
 //ImageIO.write(mergeImage, "jpg", destImage);
 }

在controller層中,先把key分類保存到session中,為用戶選擇圖片分類做提示和圖片驗證做判斷。然后把圖片流輸出到response中,就可以生成驗證圖片了。

response.setContentType("image/jpeg"); 
 response.setHeader("Pragma", "No-cache"); 
 response.setHeader("Cache-Control", "no-cache"); 
 response.setDateHeader("Expires", 0);
 
 List<Object> object = ImageSelectedHelper.getEightImages();
 File[] finalImages = (File[]) object.get(0);
 
 String[] tips = (String[]) object.get(1);
 //所有key的圖片位置,即用戶必須要選的圖片
 List<Object> locations = ImageSelectedHelper.getLocation(tips);
 
 String tip = locations.get(0).toString();
 System.out.println(tip);
 session.setAttribute("tip", tip);
 locations.remove(0);
 
 int length = locations.size();
 for (int i = 0; i < length; i++) {
  System.out.println("實際Key圖片位置:" + locations.get(i));
 }

 session.setAttribute("locations", locations);
 ImageMerge.mergeImage(finalImages, response);

在jsp中,為用戶的點擊生成小圖片標記。當用戶點圖片擊時,在父div上添加一個子div標簽,并且把他定位為relative, 并且設置zIndex,然后再這個div上添加一個img標簽,定位為absolute。在用戶的點擊時,可以獲取點擊事件,根據點擊事件獲取點擊坐標,然后減去父div的坐標,就可以獲取相對坐標??梢愿鶕约旱南埠枚ㄗ鴺嗽c,這里的坐標原點是第8個圖片的右下角?! ?/p>

<div><br> <div id="base"><br>  <img src="<%=request.getContextPath()%>/identify" style="width: 300px; height: 150px;" onclick="clickImg(event)" id="bigPicture"><br> </div><br> <br> </div><br><br>function clickImg(e) {
 var baseDiv = document.getElementById("base");
 var topValue = 0;
 var leftValue = 0;
 var obj = baseDiv;
 while (obj) {
  leftValue += obj.offsetLeft;
  topValue +=obj.offsetTop;
  obj = obj.offsetParent;
 }
 //解決firefox獲取不到點擊事件的問題
 var clickEvent = e ? e : (window.event ? window.event : null);
  
 var clickLeft = clickEvent.clientX + document.body.scrollLeft - document.body.clientLeft - 10;
 var clickTop = clickEvent.clientY + document.body.scrollTop - document.body.clientTop - 10;
 var divId = "img_" + index++;
 
 var divEle = document.createElement("div");
 
 divEle.setAttribute("id", divId);
 divEle.style.position = "relative";
 divEle.style.zIndex = index;
 divEle.style.width = "20px";
 divEle.style.height = "20px";
 divEle.style.display = "inline";
 
 divEle.style.top = clickTop - topValue - 150 + 10 + "px";
 divEle.style.left = clickLeft - leftValue - 300 + "px";
 
 divEle.setAttribute("onclick", "remove('" + divId + "')");
 baseDiv.appendChild(divEle);
 
 var imgEle = document.createElement("img");
 imgEle.src = "<%=request.getContextPath()%>/resources/timo.png";
 imgEle.style.width = "20px";
 imgEle.style.height = "20px";
 imgEle.style.top = "0px";
 imgEle.style.left = "0px";
 imgEle.style.position = "absolute";
 imgEle.style.zIndex = index;
 divEle.appendChild(imgEle);
 }

用戶選擇登錄后,服務器端根據用戶的選擇坐標進行判斷

public List<Integer> isPass(String result) {
  
 String[] xyLocations = result.split(",");
 //保存用戶選擇的坐標落在哪些圖片上
 List<Integer> list = new ArrayList<Integer>();
 //每一組坐標
 System.out.println("用戶選擇圖片數:"+xyLocations.length);
 for (String xyLocation : xyLocations) {
  String[] xy = xyLocation.split("\\|\\|");
  int x = Integer.parseInt(xy[0]);
  int y = Integer.parseInt(xy[1]);
  
  //8,4圖片區(qū)間
  if ( x > -75 && x <= 0) {
 
  if ( y > -75 && y <= 0) { //8號
   list.add(8);
 
  } else if ( y >= -150 && y <= -75 ) { //4號
   list.add(4);
  }
  } else if ( x > -150 && x <= -75) { //7,3圖片區(qū)間
   
  if ( y > -75 && y <= 0) { //7號
   list.add(7);
 
  } else if ( y >= -150 && y <= -75 ) { //3號
   list.add(3);
  }
  } else if ( x > -225 && x <= -150) { //6,2圖片區(qū)間
   
  if ( y > -75 && y <= 0) { //6號
   list.add(6);
 
  } else if ( y >= -150 && y <= -75 ) { //2號
   list.add(2);
  }
   
  } else if ( x >= -300 && x <= -225) { //5,1圖片區(qū)間
   
  if ( y > -75 && y <= 0) { //5號
   list.add(5);
 
  } else if ( y >= -150 && y <= -75 ) { //1號
   list.add(1);
  }
  } else {
  return null;
  }
 }
 return list;
 }

刷新生成新的圖片,由于ajax不支持二進制流,可以自己用原生的xmlHttpRequest對象加html5的blob來完成。

function refresh() {
 var url = "<%=request.getContextPath()%>/identify";
 var xhr = new XMLHttpRequest();
 xhr.open('GET', url, true);
 xhr.responseType = "blob";
 xhr.onload = function() {
 if (this.status == 200) {
  var blob = this.response;  
  //加載成功后釋放blob
  bigPicture.onload = function(e) {
  window.URL.revokeObjectURL(bigPicture.src);
  };
  bigPicture.src = window.URL.createObjectURL(blob);
 }
 }
 xhr.send();

 驗證碼整體代碼完成了,還有有一些細節(jié)要處理。

更多關于驗證碼的文章請點擊查看:《java驗證碼》

以上就是本文的全部內容,希望對大家的學習有所幫助。

相關文章

  • java虛擬機鉤子關閉函數addShutdownHook的操作

    java虛擬機鉤子關閉函數addShutdownHook的操作

    這篇文章主要介紹了java虛擬機鉤子關閉函數addShutdownHook的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-02-02
  • Spring控制Bean加載順序的操作方法

    Spring控制Bean加載順序的操作方法

    正常情況下,Spring 容器加載 Bean 的順序是不確定的,那么我們如果需要按順序加載 Bean 時應如何操作?本文將詳細講述我們如何才能控制 Bean 的加載順序,需要的朋友可以參考下
    2024-05-05
  • IDEA與模擬器安裝調試失敗的處理方法:INSTALL_PARSE_FAILED_NO_CERTIFICATES

    IDEA與模擬器安裝調試失敗的處理方法:INSTALL_PARSE_FAILED_NO_CERTIFICATES

    這篇文章主要介紹了IDEA與模擬器安裝調試失敗的處理方法:INSTALL_PARSE_FAILED_NO_CERTIFICATES,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-09-09
  • Java實現把文件及文件夾壓縮成zip

    Java實現把文件及文件夾壓縮成zip

    這篇文章主要介紹了Java實現把文件及文件夾壓縮成zip,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-03-03
  • java.lang.NoSuchMethodException: com.sun.proxy.$Proxy58.list錯誤解決辦法

    java.lang.NoSuchMethodException: com.sun.proxy.$Proxy58.list

    這篇文章主要介紹了java.lang.NoSuchMethodException: com.sun.proxy.$Proxy58.list錯誤解決辦法的相關資料,需要的朋友可以參考下
    2016-12-12
  • SpringBoot 如何實現異步編程

    SpringBoot 如何實現異步編程

    在SpringBoot的日常開發(fā)中,一般都是同步調用的,但實際中有很多場景非常適合使用異步來處理,本文就詳細的介紹一下SpringBoot 如何實現異步編程 ,具有一定的參考價值,感興趣的可以了解一下
    2021-12-12
  • Spring Boot 安全 API 構建之加密解密功能的實踐記錄

    Spring Boot 安全 API 構建之加密解密功能的實踐記錄

    本文詳述了如何在SpringBoot3.3環(huán)境中實施API加密的最佳實踐,包括選擇合適的加密算法,密鑰管理,數據加密,防止加密漏洞,安全日志記錄,測試和監(jiān)控等方面,同時,文章也對RSA非對稱加密和AES對稱加密的實現步驟進行了詳細的解析
    2024-10-10
  • Struts2 $,#,%詳解及實例代碼

    Struts2 $,#,%詳解及實例代碼

    這篇文章主要介紹了Struts2 $,#,%詳解及實例代碼的相關資料,需要的朋友可以參考下
    2016-12-12
  • SpringBoot+RabbitMq具體使用的幾種姿勢

    SpringBoot+RabbitMq具體使用的幾種姿勢

    這篇文章主要介紹了SpringBoot+RabbitMq具體使用的幾種姿勢,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-05-05
  • 學習Java之IO流的基礎概念詳解

    學習Java之IO流的基礎概念詳解

    這篇文章主要給大家介紹了Java中的IO流,我們首先要搞清楚一件事,就是為什么需要IO流這個東西,但在正式學習IO流的使用之前,小編有必要帶大家先了解一下IO流的基本概念,需要的朋友可以參考下
    2023-09-09

最新評論

昌邑市| 永修县| 贡觉县| 新郑市| 星子县| 元朗区| 阜南县| 酒泉市| 红原县| 龙胜| 昌都县| 泸水县| 池州市| 金沙县| 西乌珠穆沁旗| 安陆市| 太白县| 肥乡县| 鄂托克前旗| 威信县| 大英县| 安康市| 涪陵区| 大姚县| 佛坪县| 扎囊县| 玉林市| 武陟县| 乌拉特中旗| 湘潭县| 冀州市| 卓尼县| 华宁县| 定远县| 岑巩县| 金堂县| 郑州市| 大厂| 湄潭县| 准格尔旗| 济阳县|