知識點
①MVC設計模式
②文件上傳功能
③驗證碼的校驗
什么是MVC?
JavaWeb開發歷程
案例實現
1)環境搭建
用戶注冊
- 用戶信息的保存
- 用戶頭像的上傳
如果注冊成功會跳轉到登陸頁面
創建一個工程
將樣式,圖片和頁面放到webcontent目錄下
將需要用到的jar包放到lib目錄中
將工程發布到tomcat
2)用戶列表初始化
這個案例將賬戶數據存放在了集合中放到servlet的全局域.
知識點:監聽器
domain 實體類:User類
service 接口,用於處理業務邏輯
utils 工具類
listener 監聽器:初始化用戶信息監聽器
servlet servlet類
User.java

1 package com.imooc.domain; 2 3 public class User { 4 private String username; 5 private String password; 6 7 private String path; 8 9 public String getUsername() { 10 return username; 11 } 12 13 public void setUsername(String username) { 14 this.username = username; 15 } 16 17 public String getPassword() { 18 return password; 19 } 20 21 public void setPassword(String password) { 22 this.password = password; 23 } 24 25 public String getPath() { 26 return path; 27 } 28 29 public void setPath(String path) { 30 this.path = path; 31 } 32 33 @Override 34 public String toString() { 35 return "User [username=" + username + ", password=" + password + ", path=" + path + "]"; 36 } 37 38 39 }
監聽器
3)注冊頁面的表單校驗
注冊頁面的form表單
script標簽
4)用戶信息保存
form表單
接口
注冊servlet
5)上傳文件功能
原理分析:
但這時接收到的請求參數只有文件名,沒有文件
增加enctype屬性
原理:拿到請求后,對請求做一個相應的解析
fileload簡介:
官網地址:http://commons.apache.org/proper/commons-fileupload/
UploadServlet

1 package com.imooc.servlet; 2 3 import java.io.FileOutputStream; 4 import java.io.IOException; 5 import java.io.InputStream; 6 import java.io.OutputStream; 7 import java.util.List; 8 9 import javax.servlet.ServletException; 10 import javax.servlet.annotation.WebServlet; 11 import javax.servlet.http.HttpServlet; 12 import javax.servlet.http.HttpServletRequest; 13 import javax.servlet.http.HttpServletResponse; 14 15 import org.apache.commons.fileupload.FileItem; 16 import org.apache.commons.fileupload.FileUploadException; 17 import org.apache.commons.fileupload.disk.DiskFileItemFactory; 18 import org.apache.commons.fileupload.servlet.ServletFileUpload; 19 20 @WebServlet("/UploadServlet") 21 public class UploadServlet extends HttpServlet { 22 private static final long serialVersionUID = 1L; 23 24 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 25 26 // 1.創建磁盤文件項工廠 27 DiskFileItemFactory diskFileItemFactory = new DiskFileItemFactory(); 28 // 2.創建核心解析類 29 ServletFileUpload fileUpload = new ServletFileUpload(diskFileItemFactory); 30 // 3.解析請求對象,將請求分成幾個部分(FileItem) 31 try { 32 List<FileItem> list= fileUpload.parseRequest(request); 33 // 4.遍歷集合獲得每個部分的對象 34 for(FileItem fileItem:list){ 35 // 判斷是普通項還是文件上傳項 36 if(fileItem.isFormField()){ 37 // 普通項 38 // 獲得普通項的名稱: 39 String name = fileItem.getFieldName(); 40 // 獲得普通項的值: 41 String value = fileItem.getString("UTF-8"); 42 System.out.println(name+" "+value); 43 }else{ 44 // 文件上傳項 45 // 獲得文件的名稱: 46 String fileName = fileItem.getName(); 47 // 獲得文件的輸入流: 48 InputStream is = fileItem.getInputStream(); 49 // 需要將文件寫入到服務器的某個路徑即可: 50 String path = getServletContext().getRealPath("/upload"); 51 System.out.println(path); 52 // 創建輸出流 與 輸入流進行對接: 53 OutputStream os = new FileOutputStream(path+"\\"+fileName); 54 int len = 0; 55 byte[] b = new byte[1024]; 56 while((len = is.read(b))!=-1){ 57 os.write(b, 0, len); 58 } 59 is.close(); 60 os.close(); 61 } 62 } 63 } catch (FileUploadException e) { 64 // TODO Auto-generated catch block 65 e.printStackTrace(); 66 } 67 68 } 69 70 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 71 doGet(request, response); 72 } 73 74 }
6)用戶頭像上傳

1 package com.imooc.web.servlet; 2 3 import java.io.FileOutputStream; 4 import java.io.IOException; 5 import java.io.InputStream; 6 import java.io.OutputStream; 7 import java.util.HashMap; 8 import java.util.List; 9 import java.util.Map; 10 11 import javax.servlet.ServletException; 12 import javax.servlet.annotation.WebServlet; 13 import javax.servlet.http.HttpServlet; 14 import javax.servlet.http.HttpServletRequest; 15 import javax.servlet.http.HttpServletResponse; 16 17 import org.apache.commons.fileupload.FileItem; 18 import org.apache.commons.fileupload.FileUploadException; 19 import org.apache.commons.fileupload.disk.DiskFileItemFactory; 20 import org.apache.commons.fileupload.servlet.ServletFileUpload; 21 22 import com.imooc.domain.User; 23 import com.imooc.service.UserService; 24 import com.imooc.service.impl.UserServiceImpl; 25 import com.imooc.utils.UploadUtils; 26 27 @WebServlet("/RegistServlet") 28 public class RegistServlet extends HttpServlet { 29 private static final long serialVersionUID = 1L; 30 31 protected void doGet(HttpServletRequest request, HttpServletResponse response) 32 throws ServletException, IOException { 33 // 接收數據 34 // 創建Map集合用於保存數據: 35 Map<String,String> map = new HashMap<String,String>(); 36 // 文件上傳的代碼: 37 // 1.創建磁盤文件項工廠 38 DiskFileItemFactory diskFileItemFactory = new DiskFileItemFactory(); 39 // 2.創建核心解析類 40 ServletFileUpload fileUpload = new ServletFileUpload(diskFileItemFactory); 41 // 3.解析請求對象,將請求分成幾個部分(FileItem) 42 try { 43 List<FileItem> list = fileUpload.parseRequest(request); 44 // 4.遍歷集合獲得每個部分的對象 45 for (FileItem fileItem : list) { 46 // 判斷是普通項還是文件上傳項 47 if (fileItem.isFormField()) { 48 // 普通項--用戶名(username--輸入的值) 密碼 確認密碼 49 // 獲得普通項的名稱: 50 String name = fileItem.getFieldName(); 51 // 獲得普通項的值: 52 String value = fileItem.getString("UTF-8"); 53 // 保存數據: 54 map.put(name, value); 55 } else { 56 // 文件上傳項 57 // 獲得文件的名稱: 58 String fileName = fileItem.getName(); 59 // 獲得唯一文件名: 60 String uuidFileName = UploadUtils.getUuidFileName(fileName); 61 // 獲得文件的輸入流: 62 InputStream is = fileItem.getInputStream(); 63 // 需要將文件寫入到服務器的某個路徑即可: 64 String path = getServletContext().getRealPath("/upload"); 65 System.out.println(path);// D:/xxx/ddd/ 66 // 顯示圖片<img src="/regist_login/upload/a.jpg"> 67 // 創建輸出流 與 輸入流進行對接: 68 String url = path + "\\" + uuidFileName; 69 map.put("path", request.getContextPath()+"/upload/"+uuidFileName); 70 OutputStream os = new FileOutputStream(url); 71 int len = 0; 72 byte[] b = new byte[1024]; 73 while ((len = is.read(b)) != -1) { 74 os.write(b, 0, len); 75 } 76 is.close(); 77 os.close(); 78 } 79 } 80 } catch (FileUploadException e) { 81 // TODO Auto-generated catch block 82 e.printStackTrace(); 83 } 84 85 // 封裝數據 86 User user = new User(); 87 user.setUsername(map.get("username")); 88 user.setPassword(map.get("password")); 89 90 user.setPath(map.get("path")); 91 System.out.println(user); 92 // 處理數據 93 UserService userService = new UserServiceImpl(); 94 // 從ServletContext域中獲取用戶的集合即可 95 List<User> userList = (List<User>) getServletContext().getAttribute("userList"); 96 userService.regist(userList, user); 97 System.out.println(userList); 98 // 顯示處理結果 99 response.sendRedirect(request.getContextPath() + "/login.jsp"); 100 } 101 102 protected void doPost(HttpServletRequest request, HttpServletResponse response) 103 throws ServletException, IOException { 104 doGet(request, response); 105 } 106 107 }
7)解決文件名重名問題

1 package com.imooc.utils; 2 3 import java.util.UUID; 4 5 public class UploadUtils { 6 7 public static String getUuidFileName(String fileName){ 8 // 解決文件重名的問題: 9 // a.jpg -- 獲得后綴名.jpg -- 生成一段隨機字符串將a替換掉 xxdfwerw.jpg 10 int idx = fileName.lastIndexOf("."); 11 String exName = fileName.substring(idx);// .jpg 12 // 生成隨機字符串: 13 String uuidFileName = UUID.randomUUID().toString().replace("-", "")+exName; 14 15 return uuidFileName; 16 } 17 18 public static void main(String[] args) { 19 System.out.println(UploadUtils.getUuidFileName("a.jpg")); 20 } 21 }
8)登錄功能
用戶信息查詢
loginservlet

1 package com.imooc.web.servlet; 2 3 import java.io.IOException; 4 import java.util.List; 5 6 import javax.servlet.ServletException; 7 import javax.servlet.annotation.WebServlet; 8 import javax.servlet.http.HttpServlet; 9 import javax.servlet.http.HttpServletRequest; 10 import javax.servlet.http.HttpServletResponse; 11 12 import com.imooc.domain.User; 13 import com.imooc.service.UserService; 14 import com.imooc.service.impl.UserServiceImpl; 15 16 @WebServlet("/LoginServlet") 17 public class LoginServlet extends HttpServlet { 18 private static final long serialVersionUID = 1L; 19 20 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 21 22 // 接收數據: 23 String username = request.getParameter("username"); 24 String password = request.getParameter("password"); 25 // 封裝數據: 26 User user = new User(); 27 user.setUsername(username); 28 user.setPassword(password); 29 // 處理數據:完成登陸. 30 UserService userService = new UserServiceImpl(); 31 // 獲得用戶列表的集合: 32 List<User> userList = (List<User>)getServletContext().getAttribute("userList"); 33 User existUser = userService.login(userList,user); 34 // 顯示結果: 35 if(existUser == null){ 36 // 登錄失敗 37 request.setAttribute("msg", "用戶名或密碼錯誤!"); 38 request.getRequestDispatcher("/login.jsp").forward(request, response); 39 }else{ 40 // 登錄成功 41 // 將用戶信息保存: 42 request.getSession().setAttribute("existUser", existUser); 43 response.sendRedirect(request.getContextPath()+"/index.jsp"); 44 } 45 } 46 47 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 48 doGet(request, response); 49 } 50 51 }
接口實現類

1 package com.imooc.service.impl; 2 3 import java.util.List; 4 5 import com.imooc.domain.User; 6 import com.imooc.service.UserService; 7 8 public class UserServiceImpl implements UserService { 9 10 @Override 11 public void regist(List<User> userList, User user) { 12 // 保存用戶信息: 13 userList.add(user); 14 } 15 16 @Override 17 public User login(List<User> userList, User user) { 18 19 for (User existUser : userList) { 20 if(existUser.getUsername().equals(user.getUsername()) && existUser.getPassword().equals(user.getPassword())){ 21 return existUser; 22 } 23 } 24 25 return null; 26 } 27 28 }
首頁頭部:設置登錄成功和失敗的樣式

1 <c:if test="${ empty existUser }"> 2 <li><a href="${pageContext.request.contextPath }/login.jsp">登錄</a></li> 3 <li><a href="${pageContext.request.contextPath }/register.jsp">注冊</a></li> 4 </c:if> 5 <c:if test="${ not empty existUser}"> 6 <li> 7 <img class="profile_item" src="${ existUser.path }"> 8 </li> 9 </c:if>
9)驗證碼的生成與校驗
概述
生成
驗證碼生成准備工作:
servlet

1 package com.imooc.web.servlet; 2 3 import java.awt.Color; 4 import java.awt.Font; 5 import java.awt.Graphics; 6 import java.awt.Graphics2D; 7 import java.awt.image.BufferedImage; 8 import java.io.IOException; 9 import java.util.Random; 10 11 import javax.imageio.ImageIO; 12 import javax.servlet.ServletException; 13 import javax.servlet.annotation.WebServlet; 14 import javax.servlet.http.HttpServlet; 15 import javax.servlet.http.HttpServletRequest; 16 import javax.servlet.http.HttpServletResponse; 17 18 @WebServlet("/CheckImgServlet1") 19 public class CheckImgServlet1 extends HttpServlet { 20 private static final long serialVersionUID = 1L; 21 22 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 23 24 } 25 26 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 27 doGet(request, response); 28 } 29 30 }
頁面

1 <%@ page language="java" contentType="text/html; charset=UTF-8" 2 pageEncoding="UTF-8"%> 3 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> 4 <html> 5 <head> 6 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> 7 <title>Insert title here</title> 8 </head> 9 <body> 10 <form action="" method="post"> 11 驗證碼:<input type="text" name="checkcode"/><img src="${pageContext.request.contextPath }/CheckImgServlet"><br/> 12 <input type="submit" value="提交"> 13 </form> 14 </body> 15 </html>
將內存中圖片顯示到瀏覽器
servlet
字母隨機旋轉一定角度

1 package com.imooc.web.servlet; 2 3 import java.awt.Color; 4 import java.awt.Font; 5 import java.awt.Graphics; 6 import java.awt.Graphics2D; 7 import java.awt.image.BufferedImage; 8 import java.io.IOException; 9 import java.util.Random; 10 11 import javax.imageio.ImageIO; 12 import javax.servlet.ServletException; 13 import javax.servlet.annotation.WebServlet; 14 import javax.servlet.http.HttpServlet; 15 import javax.servlet.http.HttpServletRequest; 16 import javax.servlet.http.HttpServletResponse; 17 18 @WebServlet("/CheckImgServlet1") 19 public class CheckImgServlet1 extends HttpServlet { 20 private static final long serialVersionUID = 1L; 21 22 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 23 int width = 120; 24 int height = 30; 25 // 步驟一:在內存中生成一張圖片 26 BufferedImage bufferedImage = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB); 27 // 步驟二:操作該圖片,設置背景色及繪制邊框 28 Graphics graphics = bufferedImage.getGraphics(); 29 // 設置背景色 30 graphics.setColor(Color.YELLOW); 31 graphics.fillRect(0, 0, width, height); 32 // 繪制邊框 33 graphics.setColor(Color.BLUE); 34 graphics.drawRect(0, 0, width-1, height-1); 35 36 // 步驟三:生成隨機的四個字母或數字,寫入到圖片中 37 Graphics2D g2d = (Graphics2D)graphics; 38 g2d.setColor(Color.BLACK); 39 g2d.setFont(new Font("宋體",Font.BOLD,18));//a 4 3 r 40 41 String words = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; 42 Random random = new Random(); 43 int x = 10; 44 for(int i=0;i<4;i++){ 45 int idx = random.nextInt(words.length()); 46 // 獲得指定位置的字符 47 char ch = words.charAt(idx); 48 // 旋轉的角度 -30 到 30 之間 49 int jiaodu = random.nextInt(60) - 30; 50 // 將角度轉化成弧度: 51 double theta = jiaodu * Math.PI / 180; 52 g2d.rotate(theta, x, 20); 53 g2d.drawString(String.valueOf(ch), x, 20); 54 g2d.rotate(-theta, x, 20); 55 56 x+=30; 57 } 58 // 步驟四:將內存中的圖片,進行輸出 59 ImageIO.write(bufferedImage, "jpg", response.getOutputStream()); 60 } 61 62 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 63 doGet(request, response); 64 } 65 66 }
添加干擾線以及設置字母隨機顏色

1 package com.imooc.web.servlet; 2 3 import java.awt.Color; 4 import java.awt.Font; 5 import java.awt.Graphics; 6 import java.awt.Graphics2D; 7 import java.awt.image.BufferedImage; 8 import java.io.IOException; 9 import java.util.Random; 10 11 import javax.imageio.ImageIO; 12 import javax.servlet.ServletException; 13 import javax.servlet.annotation.WebServlet; 14 import javax.servlet.http.HttpServlet; 15 import javax.servlet.http.HttpServletRequest; 16 import javax.servlet.http.HttpServletResponse; 17 18 /** 19 * 生成驗證碼圖片 20 */ 21 @WebServlet("/CheckImgServlet") 22 public class CheckImgServlet extends HttpServlet { 23 24 public void doGet(HttpServletRequest request, HttpServletResponse response) 25 throws ServletException, IOException { 26 27 int width = 120; 28 int height = 30; 29 30 // 步驟一 繪制一張內存中圖片 31 BufferedImage bufferedImage = new BufferedImage(width, height, 32 BufferedImage.TYPE_INT_RGB); 33 34 // 步驟二 圖片繪制背景顏色 ---通過繪圖對象 35 Graphics graphics = bufferedImage.getGraphics();// 得到畫圖對象 --- 畫筆 36 // 繪制任何圖形之前 都必須指定一個顏色 37 graphics.setColor(getRandColor(200, 250)); 38 graphics.fillRect(0, 0, width, height); 39 40 // 步驟三 繪制邊框 41 graphics.setColor(Color.WHITE); 42 graphics.drawRect(0, 0, width - 1, height - 1); 43 44 // 步驟四 四個隨機數字 45 Graphics2D graphics2d = (Graphics2D) graphics; 46 // 設置輸出字體 47 graphics2d.setFont(new Font("宋體", Font.BOLD, 18)); 48 49 String words = 50 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890"; 51 // String words = "\u7684\u4e00\u4e86\u662f\u6211\u4e0d\u5728\u4eba\u4eec\u6709\u6765\u4ed6\u8fd9\u4e0a\u7740\u4e2a\u5730\u5230\u5927\u91cc\u8bf4\u5c31\u53bb\u5b50\u5f97\u4e5f\u548c\u90a3\u8981\u4e0b\u770b\u5929\u65f6\u8fc7\u51fa\u5c0f\u4e48\u8d77\u4f60\u90fd\u628a\u597d\u8fd8\u591a\u6ca1\u4e3a\u53c8\u53ef\u5bb6\u5b66\u53ea\u4ee5\u4e3b\u4f1a\u6837\u5e74\u60f3\u751f\u540c\u8001\u4e2d\u5341\u4ece\u81ea\u9762\u524d\u5934\u9053\u5b83\u540e\u7136\u8d70\u5f88\u50cf\u89c1\u4e24\u7528\u5979\u56fd\u52a8\u8fdb\u6210\u56de\u4ec0\u8fb9\u4f5c\u5bf9\u5f00\u800c\u5df1\u4e9b\u73b0\u5c71\u6c11\u5019\u7ecf\u53d1\u5de5\u5411\u4e8b\u547d\u7ed9\u957f\u6c34\u51e0\u4e49\u4e09\u58f0\u4e8e\u9ad8\u624b\u77e5\u7406\u773c\u5fd7\u70b9\u5fc3\u6218\u4e8c\u95ee\u4f46\u8eab\u65b9\u5b9e\u5403\u505a\u53eb\u5f53\u4f4f\u542c\u9769\u6253\u5462\u771f\u5168\u624d\u56db\u5df2\u6240\u654c\u4e4b\u6700\u5149\u4ea7\u60c5\u8def\u5206\u603b\u6761\u767d\u8bdd\u4e1c\u5e2d\u6b21\u4eb2\u5982\u88ab\u82b1\u53e3\u653e\u513f\u5e38\u6c14\u4e94\u7b2c\u4f7f\u5199\u519b\u5427\u6587\u8fd0\u518d\u679c\u600e\u5b9a\u8bb8\u5feb\u660e\u884c\u56e0\u522b\u98de\u5916\u6811\u7269\u6d3b\u90e8\u95e8\u65e0\u5f80\u8239\u671b\u65b0\u5e26\u961f\u5148\u529b\u5b8c\u5374\u7ad9\u4ee3\u5458\u673a\u66f4\u4e5d\u60a8\u6bcf\u98ce\u7ea7\u8ddf\u7b11\u554a\u5b69\u4e07\u5c11\u76f4\u610f\u591c\u6bd4\u9636\u8fde\u8f66\u91cd\u4fbf\u6597\u9a6c\u54ea\u5316\u592a\u6307\u53d8\u793e\u4f3c\u58eb\u8005\u5e72\u77f3\u6ee1\u65e5\u51b3\u767e\u539f\u62ff\u7fa4\u7a76\u5404\u516d\u672c\u601d\u89e3\u7acb\u6cb3\u6751\u516b\u96be\u65e9\u8bba\u5417\u6839\u5171\u8ba9\u76f8\u7814\u4eca\u5176\u4e66\u5750\u63a5\u5e94\u5173\u4fe1\u89c9\u6b65\u53cd\u5904\u8bb0\u5c06\u5343\u627e\u4e89\u9886\u6216\u5e08\u7ed3\u5757\u8dd1\u8c01\u8349\u8d8a\u5b57\u52a0\u811a\u7d27\u7231\u7b49\u4e60\u9635\u6015\u6708\u9752\u534a\u706b\u6cd5\u9898\u5efa\u8d76\u4f4d\u5531\u6d77\u4e03\u5973\u4efb\u4ef6\u611f\u51c6\u5f20\u56e2\u5c4b\u79bb\u8272\u8138\u7247\u79d1\u5012\u775b\u5229\u4e16\u521a\u4e14\u7531\u9001\u5207\u661f\u5bfc\u665a\u8868\u591f\u6574\u8ba4\u54cd\u96ea\u6d41\u672a\u573a\u8be5\u5e76\u5e95\u6df1\u523b\u5e73\u4f1f\u5fd9\u63d0\u786e\u8fd1\u4eae\u8f7b\u8bb2\u519c\u53e4\u9ed1\u544a\u754c\u62c9\u540d\u5440\u571f\u6e05\u9633\u7167\u529e\u53f2\u6539\u5386\u8f6c\u753b\u9020\u5634\u6b64\u6cbb\u5317\u5fc5\u670d\u96e8\u7a7f\u5185\u8bc6\u9a8c\u4f20\u4e1a\u83dc\u722c\u7761\u5174\u5f62\u91cf\u54b1\u89c2\u82e6\u4f53\u4f17\u901a\u51b2\u5408\u7834\u53cb\u5ea6\u672f\u996d\u516c\u65c1\u623f\u6781\u5357\u67aa\u8bfb\u6c99\u5c81\u7ebf\u91ce\u575a\u7a7a\u6536\u7b97\u81f3\u653f\u57ce\u52b3\u843d\u94b1\u7279\u56f4\u5f1f\u80dc\u6559\u70ed\u5c55\u5305\u6b4c\u7c7b\u6e10\u5f3a\u6570\u4e61\u547c\u6027\u97f3\u7b54\u54e5\u9645\u65e7\u795e\u5ea7\u7ae0\u5e2e\u5566\u53d7\u7cfb\u4ee4\u8df3\u975e\u4f55\u725b\u53d6\u5165\u5cb8\u6562\u6389\u5ffd\u79cd\u88c5\u9876\u6025\u6797\u505c\u606f\u53e5\u533a\u8863\u822c\u62a5\u53f6\u538b\u6162\u53d4\u80cc\u7ec6"; 52 Random random = new Random();// 生成隨機數 53 54 // 定義x坐標 55 int x = 10; 56 for (int i = 0; i < 4; i++) { 57 // 隨機顏色 58 graphics2d.setColor(new Color(20 + random.nextInt(110), 20 + random 59 .nextInt(110), 20 + random.nextInt(110))); 60 // 旋轉 -30 --- 30度 61 int jiaodu = random.nextInt(60) - 30; 62 // 換算弧度 63 double theta = jiaodu * Math.PI / 180; 64 65 // 生成一個隨機數字 66 int index = random.nextInt(words.length()); // 生成隨機數 0 到 length - 1 67 // 獲得字母數字 68 char c = words.charAt(index); 69 70 // 將c 輸出到圖片 71 graphics2d.rotate(theta, x, 20); 72 graphics2d.drawString(String.valueOf(c), x, 20); 73 graphics2d.rotate(-theta, x, 20); 74 x += 30; 75 } 76 77 // 步驟五 繪制干擾線 78 graphics.setColor(getRandColor(160, 200)); 79 int x1; 80 int x2; 81 int y1; 82 int y2; 83 for (int i = 0; i < 30; i++) { 84 x1 = random.nextInt(width); 85 x2 = random.nextInt(12); 86 y1 = random.nextInt(height); 87 y2 = random.nextInt(12); 88 graphics.drawLine(x1, y1, x1 + x2, x2 + y2); 89 } 90 91 // 將上面圖片輸出到瀏覽器 ImageIO 92 graphics.dispose();// 釋放資源 93 ImageIO.write(bufferedImage, "jpg", response.getOutputStream()); 94 95 } 96 97 98 public void doPost(HttpServletRequest request, HttpServletResponse response) 99 throws ServletException, IOException { 100 doGet(request, response); 101 } 102 103 /** 104 * 取其某一范圍的color 105 * 106 * @param fc 107 * int 范圍參數1 108 * @param bc 109 * int 范圍參數2 110 * @return Color 111 */ 112 private Color getRandColor(int fc, int bc) { 113 // 取其隨機顏色 114 Random random = new Random(); 115 if (fc > 255) { 116 fc = 255; 117 } 118 if (bc > 255) { 119 bc = 255; 120 } 121 int r = fc + random.nextInt(bc - fc); 122 int g = fc + random.nextInt(bc - fc); 123 int b = fc + random.nextInt(bc - fc); 124 return new Color(r, g, b); 125 } 126 127 }
實現驗證碼看不清更換一張的功能
頁面
瀏覽器有緩存 要更換每次請求的路徑 才能實現點擊更換圖片
校驗
checkImgServlet

1 package com.imooc.web.servlet; 2 3 import java.awt.Color; 4 import java.awt.Font; 5 import java.awt.Graphics; 6 import java.awt.Graphics2D; 7 import java.awt.image.BufferedImage; 8 import java.io.IOException; 9 import java.util.Random; 10 11 import javax.imageio.ImageIO; 12 import javax.servlet.ServletException; 13 import javax.servlet.annotation.WebServlet; 14 import javax.servlet.http.HttpServlet; 15 import javax.servlet.http.HttpServletRequest; 16 import javax.servlet.http.HttpServletResponse; 17 18 /** 19 * 生成驗證碼圖片 20 */ 21 @WebServlet("/CheckImgServlet") 22 public class CheckImgServlet extends HttpServlet { 23 24 public void doGet(HttpServletRequest request, HttpServletResponse response) 25 throws ServletException, IOException { 26 27 int width = 120; 28 int height = 30; 29 30 // 步驟一 繪制一張內存中圖片 31 BufferedImage bufferedImage = new BufferedImage(width, height, 32 BufferedImage.TYPE_INT_RGB); 33 34 // 步驟二 圖片繪制背景顏色 ---通過繪圖對象 35 Graphics graphics = bufferedImage.getGraphics();// 得到畫圖對象 --- 畫筆 36 // 繪制任何圖形之前 都必須指定一個顏色 37 graphics.setColor(getRandColor(200, 250)); 38 graphics.fillRect(0, 0, width, height); 39 40 // 步驟三 繪制邊框 41 graphics.setColor(Color.WHITE); 42 graphics.drawRect(0, 0, width - 1, height - 1); 43 44 // 步驟四 四個隨機數字 45 Graphics2D graphics2d = (Graphics2D) graphics; 46 // 設置輸出字體 47 graphics2d.setFont(new Font("宋體", Font.BOLD, 18)); 48 49 String words = 50 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890"; 51 // String words = "\u7684\u4e00\u4e86\u662f\u6211\u4e0d\u5728\u4eba\u4eec\u6709\u6765\u4ed6\u8fd9\u4e0a\u7740\u4e2a\u5730\u5230\u5927\u91cc\u8bf4\u5c31\u53bb\u5b50\u5f97\u4e5f\u548c\u90a3\u8981\u4e0b\u770b\u5929\u65f6\u8fc7\u51fa\u5c0f\u4e48\u8d77\u4f60\u90fd\u628a\u597d\u8fd8\u591a\u6ca1\u4e3a\u53c8\u53ef\u5bb6\u5b66\u53ea\u4ee5\u4e3b\u4f1a\u6837\u5e74\u60f3\u751f\u540c\u8001\u4e2d\u5341\u4ece\u81ea\u9762\u524d\u5934\u9053\u5b83\u540e\u7136\u8d70\u5f88\u50cf\u89c1\u4e24\u7528\u5979\u56fd\u52a8\u8fdb\u6210\u56de\u4ec0\u8fb9\u4f5c\u5bf9\u5f00\u800c\u5df1\u4e9b\u73b0\u5c71\u6c11\u5019\u7ecf\u53d1\u5de5\u5411\u4e8b\u547d\u7ed9\u957f\u6c34\u51e0\u4e49\u4e09\u58f0\u4e8e\u9ad8\u624b\u77e5\u7406\u773c\u5fd7\u70b9\u5fc3\u6218\u4e8c\u95ee\u4f46\u8eab\u65b9\u5b9e\u5403\u505a\u53eb\u5f53\u4f4f\u542c\u9769\u6253\u5462\u771f\u5168\u624d\u56db\u5df2\u6240\u654c\u4e4b\u6700\u5149\u4ea7\u60c5\u8def\u5206\u603b\u6761\u767d\u8bdd\u4e1c\u5e2d\u6b21\u4eb2\u5982\u88ab\u82b1\u53e3\u653e\u513f\u5e38\u6c14\u4e94\u7b2c\u4f7f\u5199\u519b\u5427\u6587\u8fd0\u518d\u679c\u600e\u5b9a\u8bb8\u5feb\u660e\u884c\u56e0\u522b\u98de\u5916\u6811\u7269\u6d3b\u90e8\u95e8\u65e0\u5f80\u8239\u671b\u65b0\u5e26\u961f\u5148\u529b\u5b8c\u5374\u7ad9\u4ee3\u5458\u673a\u66f4\u4e5d\u60a8\u6bcf\u98ce\u7ea7\u8ddf\u7b11\u554a\u5b69\u4e07\u5c11\u76f4\u610f\u591c\u6bd4\u9636\u8fde\u8f66\u91cd\u4fbf\u6597\u9a6c\u54ea\u5316\u592a\u6307\u53d8\u793e\u4f3c\u58eb\u8005\u5e72\u77f3\u6ee1\u65e5\u51b3\u767e\u539f\u62ff\u7fa4\u7a76\u5404\u516d\u672c\u601d\u89e3\u7acb\u6cb3\u6751\u516b\u96be\u65e9\u8bba\u5417\u6839\u5171\u8ba9\u76f8\u7814\u4eca\u5176\u4e66\u5750\u63a5\u5e94\u5173\u4fe1\u89c9\u6b65\u53cd\u5904\u8bb0\u5c06\u5343\u627e\u4e89\u9886\u6216\u5e08\u7ed3\u5757\u8dd1\u8c01\u8349\u8d8a\u5b57\u52a0\u811a\u7d27\u7231\u7b49\u4e60\u9635\u6015\u6708\u9752\u534a\u706b\u6cd5\u9898\u5efa\u8d76\u4f4d\u5531\u6d77\u4e03\u5973\u4efb\u4ef6\u611f\u51c6\u5f20\u56e2\u5c4b\u79bb\u8272\u8138\u7247\u79d1\u5012\u775b\u5229\u4e16\u521a\u4e14\u7531\u9001\u5207\u661f\u5bfc\u665a\u8868\u591f\u6574\u8ba4\u54cd\u96ea\u6d41\u672a\u573a\u8be5\u5e76\u5e95\u6df1\u523b\u5e73\u4f1f\u5fd9\u63d0\u786e\u8fd1\u4eae\u8f7b\u8bb2\u519c\u53e4\u9ed1\u544a\u754c\u62c9\u540d\u5440\u571f\u6e05\u9633\u7167\u529e\u53f2\u6539\u5386\u8f6c\u753b\u9020\u5634\u6b64\u6cbb\u5317\u5fc5\u670d\u96e8\u7a7f\u5185\u8bc6\u9a8c\u4f20\u4e1a\u83dc\u722c\u7761\u5174\u5f62\u91cf\u54b1\u89c2\u82e6\u4f53\u4f17\u901a\u51b2\u5408\u7834\u53cb\u5ea6\u672f\u996d\u516c\u65c1\u623f\u6781\u5357\u67aa\u8bfb\u6c99\u5c81\u7ebf\u91ce\u575a\u7a7a\u6536\u7b97\u81f3\u653f\u57ce\u52b3\u843d\u94b1\u7279\u56f4\u5f1f\u80dc\u6559\u70ed\u5c55\u5305\u6b4c\u7c7b\u6e10\u5f3a\u6570\u4e61\u547c\u6027\u97f3\u7b54\u54e5\u9645\u65e7\u795e\u5ea7\u7ae0\u5e2e\u5566\u53d7\u7cfb\u4ee4\u8df3\u975e\u4f55\u725b\u53d6\u5165\u5cb8\u6562\u6389\u5ffd\u79cd\u88c5\u9876\u6025\u6797\u505c\u606f\u53e5\u533a\u8863\u822c\u62a5\u53f6\u538b\u6162\u53d4\u80cc\u7ec6"; 52 Random random = new Random();// 生成隨機數 53 // 定義一個字符串,用於保存隨機產生的四個字母或數字 54 StringBuffer sb = new StringBuffer(); 55 // 定義x坐標 56 int x = 10; 57 for (int i = 0; i < 4; i++) { 58 // 隨機顏色 59 graphics2d.setColor(new Color(20 + random.nextInt(110), 20 + random 60 .nextInt(110), 20 + random.nextInt(110))); 61 // 旋轉 -30 --- 30度 62 int jiaodu = random.nextInt(60) - 30; 63 // 換算弧度 64 double theta = jiaodu * Math.PI / 180; 65 66 // 生成一個隨機數字 67 int index = random.nextInt(words.length()); // 生成隨機數 0 到 length - 1 68 // 獲得字母數字 69 char c = words.charAt(index); 70 // 將產生字符存入到StringBuffer中 71 sb.append(c); 72 // 將c 輸出到圖片 73 graphics2d.rotate(theta, x, 20); 74 graphics2d.drawString(String.valueOf(c), x, 20); 75 graphics2d.rotate(-theta, x, 20); 76 x += 30; 77 } 78 // 將產生的字符串存入到session中: 79 request.getSession().setAttribute("checkCode", sb.toString()); 80 81 // 步驟五 繪制干擾線 82 graphics.setColor(getRandColor(160, 200)); 83 int x1; 84 int x2; 85 int y1; 86 int y2; 87 for (int i = 0; i < 30; i++) { 88 x1 = random.nextInt(width); 89 x2 = random.nextInt(12); 90 y1 = random.nextInt(height); 91 y2 = random.nextInt(12); 92 graphics.drawLine(x1, y1, x1 + x2, x2 + y2); 93 } 94 95 // 將上面圖片輸出到瀏覽器 ImageIO 96 graphics.dispose();// 釋放資源 97 ImageIO.write(bufferedImage, "jpg", response.getOutputStream()); 98 99 } 100 101 102 public void doPost(HttpServletRequest request, HttpServletResponse response) 103 throws ServletException, IOException { 104 doGet(request, response); 105 } 106 107 /** 108 * 取其某一范圍的color 109 * 110 * @param fc 111 * int 范圍參數1 112 * @param bc 113 * int 范圍參數2 114 * @return Color 115 */ 116 private Color getRandColor(int fc, int bc) { 117 // 取其隨機顏色 118 Random random = new Random(); 119 if (fc > 255) { 120 fc = 255; 121 } 122 if (bc > 255) { 123 bc = 255; 124 } 125 int r = fc + random.nextInt(bc - fc); 126 int g = fc + random.nextInt(bc - fc); 127 int b = fc + random.nextInt(bc - fc); 128 return new Color(r, g, b); 129 } 130 131 }
loginServlet

1 package com.imooc.web.servlet; 2 3 import java.io.IOException; 4 import java.util.List; 5 6 import javax.servlet.ServletException; 7 import javax.servlet.annotation.WebServlet; 8 import javax.servlet.http.HttpServlet; 9 import javax.servlet.http.HttpServletRequest; 10 import javax.servlet.http.HttpServletResponse; 11 12 import com.imooc.domain.User; 13 import com.imooc.service.UserService; 14 import com.imooc.service.impl.UserServiceImpl; 15 16 @WebServlet("/LoginServlet") 17 public class LoginServlet extends HttpServlet { 18 private static final long serialVersionUID = 1L; 19 20 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 21 // 完成驗證碼的校驗: 22 // 獲得session中保存的驗證碼的信息 23 String code1 = (String)request.getSession().getAttribute("checkCode"); 24 // 接收前台表單提交的驗證碼的信息 25 String code2 = request.getParameter("checkCode"); 26 if(code2==null || !code2.equalsIgnoreCase(code1)){ 27 request.setAttribute("msg", "驗證碼輸入不正確!"); 28 request.getRequestDispatcher("/login.jsp").forward(request, response); 29 return; 30 } 31 32 // 接收數據: 33 String username = request.getParameter("username"); 34 String password = request.getParameter("password"); 35 // 封裝數據: 36 User user = new User(); 37 user.setUsername(username); 38 user.setPassword(password); 39 // 處理數據:完成登陸. 40 UserService userService = new UserServiceImpl(); 41 // 獲得用戶列表的集合: 42 List<User> userList = (List<User>)getServletContext().getAttribute("userList"); 43 User existUser = userService.login(userList,user); 44 // 顯示結果: 45 if(existUser == null){ 46 // 登錄失敗 47 request.setAttribute("msg", "用戶名或密碼錯誤!"); 48 request.getRequestDispatcher("/login.jsp").forward(request, response); 49 }else{ 50 // 登錄成功 51 // 將用戶信息保存: 52 request.getSession().setAttribute("existUser", existUser); 53 response.sendRedirect(request.getContextPath()+"/index.jsp"); 54 } 55 } 56 57 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 58 doGet(request, response); 59 } 60 61 }
Kaptcha驗證碼的介紹及入門
上面我們自己編寫的驗證碼代碼有一定的局限性,當驗證碼的樣式,比如寬高等需要改變時,得更改相應的源代碼,不是很方便
這時我們可以用第三方的驗證碼工具,如Kaptcha
首先我們要將Kaptcha的jar包引入到工程中
然后在web.xml中進行相應的配置

1 <?xml version="1.0" encoding="UTF-8"?> 2 <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> 3 4 <servlet> 5 <servlet-name>KaptchaServlet</servlet-name> 6 <servlet-class>com.google.code.kaptcha.servlet.KaptchaServlet</servlet-class> 7 8 <!-- 修改隨機的字母或數字的長度 --> 9 <init-param> 10 <param-name>kaptcha.textproducer.char.length</param-name> 11 <param-value>4</param-value> 12 </init-param> 13 14 <!-- 修改字體大小 --> 15 <init-param> 16 <param-name>kaptcha.textproducer.font.size</param-name> 17 <param-value>25</param-value> 18 </init-param> 19 <init-param> 20 <param-name>kaptcha.textproducer.char.space</param-name> 21 <param-value>10</param-value> 22 </init-param> 23 24 <!-- 修改圖片的寬高 --> 25 <init-param> 26 <param-name>kaptcha.image.width</param-name> 27 <param-value>120</param-value> 28 </init-param> 29 <init-param> 30 <param-name>kaptcha.image.height</param-name> 31 <param-value>30</param-value> 32 </init-param> 33 </servlet> 34 35 <servlet-mapping> 36 <servlet-name>KaptchaServlet</servlet-name> 37 <url-pattern>/KaptchaServlet</url-pattern> 38 </servlet-mapping> 39 40 41 <welcome-file-list> 42 <welcome-file>index.html</welcome-file> 43 <welcome-file>index.htm</welcome-file> 44 <welcome-file>index.jsp</welcome-file> 45 <welcome-file>default.html</welcome-file> 46 <welcome-file>default.htm</welcome-file> 47 <welcome-file>default.jsp</welcome-file> 48 </welcome-file-list> 49 </web-app>
配置參數介紹
配置前
配置后
Kaptcha驗證碼的校驗
1 // 獲得session中保存的驗證碼的信息 2 String code1 = (String)request.getSession().getAttribute(com.google.code.kaptcha.Constants.KAPTCHA_SESSION_KEY); 3