[Java][Servlet] 簡單驗證碼製作 - 使用Servlet

使用 Servlet 來製作簡單的驗證碼,結論也告訴我們 Servlet 不只可以當網頁,還可以製作成圖片等格式!
程式碼上都有註解,可以邊做邊了解,有問題歡迎留言討論~


一、程式結果
二、程式碼






一、程式結果

IdentityServlet.java

identity.html


二、程式碼

Project 類型: Dynamic Web Project
Project 名稱: servlet
Package 名稱: idv.ycc.servlet
Class 類型: Servlet
Class 名稱: IdentityServlet.java
Html 路徑: servlet/WebContent
Html 名稱: identity.html

如果要直接 copy 程式碼,請盡量用以上的名稱,避免出錯!
當然還是有其他細節,有問題可Google或留言詢問

IdentityServlet.java、identity.html 寫完後,記得 web.xml 那邊也要寫,這次有在那邊註冊網址,也就是用自己定義的網址,不然 identity.html 裡的 <img src> 會讀不到圖片


IdentityServlet.java

package idv.ycc.servlet;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageEncoder;

@WebServlet("/IdentityServlet")
public class IdentityServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
    
    //亂數字元字典
    //不包括 0, O, 1, I 等難以辨識之字元
    public static final char[] CHARS = {'2', '3', '4', '5', '6', '7', '8', 
               '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L',
               'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'};
    
    //亂數
    public static Random random = new Random(); 
    
    //取得六位亂數
    public static String getRandomString() {
        StringBuffer buffer = new StringBuffer();
        for (int i = 0; i < 6; i++)
            buffer.append(CHARS[random.nextInt(CHARS.length)]);
        return buffer.toString();
    }
    
    //取得隨機顏色
public static Color getRandomColor() {
    return new Color(random.nextInt(255), random.nextInt(255), random.nextInt(255));
}

//取得相反顏色
public static Color getReverseColor(Color c) {
    return new Color(255 - c.getRed(), 255 - c.getGreen(), 255 - c.getBlue());
}
       
    public IdentityServlet() {
        super();
    }
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("image/jpeg");    //設定此Servlet的類形(必要)

String randomString = getRandomString();  //亂數字串

//設定屬性setAttribute(key, value),放到session
//getSession(true) = getSesstion()
request.getSession(true).setAttribute("randomString", randomString);

int width = 100;  //圖片寬度
int height = 30;  //圖片高度

Color color = getRandomColor();           //取得亂數顏色,背景用
Color reverse = getReverseColor(color);   //取得上面反色,前景用

//建立一個彩色圖片
BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics2D g = bi.createGraphics();                   //建立繪圖對象
g.setFont(new Font(Font.SANS_SERIF, Font.BOLD, 16));  //設定字體
g.setColor(color);                                    //設定顏色
g.fillRect(0, 0, width, height);                      //畫填滿的矩形(背景)
g.setColor(reverse);                                  //設定顏色
g.drawString(randomString, 18, 20);                   //畫亂數字串

//畫矩形,最多100個,顏色以當下的顏色繪製,所以跟字串顏色一樣
for(int i = 0, n = random.nextInt(100); i < n; i++)
    g.drawRect(random.nextInt(width), random.nextInt(height), 1, 1);

ServletOutputStream out = response.getOutputStream();         //取得二進位資料(Binary Data)
JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);  //建立JPEG編碼器

encoder.encode(bi);   //對圖片進行編碼(JPEG stream)
out.flush();          //釋放緩衝區並輸出,沒寫等到緩衝區滿了會出現IOException的錯誤

}
}


identity.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script>
function reloadImage(){
//使用GET方式,把當下的時間轉為UNIX時間作為參數,所以參數不會重覆到
document.getElementById('identity').src = 'identityservlet?ts=' 
+ new Date().getTime();
}
</script>
</head>
<body>
    <!-- src: source,來源 -->
    <!-- onload: 在讀取<img>的時候,執行此方法 -->
    <!-- btn.disabled = false: 不禁用按鈕(預設為false,所以可不寫onload此方法) -->
    <img src="identityservlet" id="identity" onload="btn.disabled = false;"/>
    
    <input type=button value="重新產生驗證碼" onclick="reloadImage()" id="btn">
    <!-- 上下功能一樣,但建議用<button>,因為編排豐富、彈性高 -->
    <button type="button" onclick="reloadImage()">重新產生驗證碼</button>
</body>
</html>


web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.1"
         xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
                             http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">

    <!-- 瀏覽方式 -->
<servlet>
       <!-- <servlet-name>可以任意取,但必須唯一,因要給<servlet-mapping>, <filter>等使用 -->
       <servlet-name>IdentityServlet</servlet-name>
       <servlet-class>idv.ycc.servlet.IdentityServlet</servlet-class>
    </servlet>
<servlet-mapping>
       <!-- <servlet-mapping><servlet-name> 配對上面 <servlet><servlet-name> -->
       <!-- 並瀏覽其<servlet-class> -->
   <servlet-name>IdentityServlet</servlet-name>
       <!-- 配置其 Servlet 的地址 -->
   <url-pattern>/identityservlet</url-pattern>
</servlet-mapping>
                   
</web-app>



留言

這個網誌中的熱門文章

[日文] Google日文輸入法 簡單安裝說明

[面試] 日月光 設備工程師

[Windows] 還我 win7 相片檢視器!!