1 項目框架分析
1、功能
(1)註冊
(2)登錄
2、JSP
(1)login.jsp:登錄表單
(2)regist.jsp:註冊表單
(3)index.jsp:主頁(只有登錄成功才能看到)
3、Servlet
(1)LoginServlet
(2)RegistServlet
4、Service
(1)UserService:與用戶相關的業務類
5、Dao
(1)UserDao:與用戶相關的數據類
6、Domain
(1)User(對應數據庫,還要對應所有表單)
|——username
|——password
|——verifyCode
7、數據庫名:users.xml
<users>
<user username="xxx" password="xxx" />
<user username="xxx" password="xxx" />
</users>
2 項目框架搭建
1、創建空項目
2、導包
(1)CommonUtils
|——commons-beanutils.jar
|——commons-logging.jar
|——dom4j
3、建包
(1)org.lks.user.domian
|——User
(2)org.lks.user.dao
|——UserDao
(3)org.lks.user.service
|——UserService
(4)org.lks.user.web.servlet
|——LoginServlet
|——RegistServlet
4、jsp
(1)login.jsp
(2)regist.jsp
(3)index.jsp
5、在項目路徑中創建src/userdata/users.xml文件存儲用戶數據
(1)添加根元素<users>
(2)保證文件爲utf-8編碼
3 註冊功能流程分析
1、註冊
(1)regist.jsp
|——第一步:完成regist.jsp的基本功能
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Register</title>
</head>
<body>
<h1>Register</h1>
${requestScope.userExceptionMessage}
<form action="${pageContext.request.contextPath }/RegisterServlet" method="post">
Username: <input type="text" name="registerUsername" value="${requestScope.registerUsername }" /><br/>
Password: <input type="password" name="registerPassword" value="${requestScope.registerPassword }"/><br/>
<input type="submit" value="sign up" />
</form>
</body>
</html>
(2)RegistServlet
|——封裝表單數據,封裝到User對象中
|——調用service的regist()方法
|————如果這個方法沒有出問題,給頁面顯示成功信息。
|————如果這個方法拋出了異常,把錯誤信息保存到request域,轉發到regist.jsp(顯示錯誤信息)。
package org.lks.loginandregister.web.servlet;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Iterator;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.lks.loginandregister.service.UserException;
import org.lks.loginandregister.service.UserService;
@WebServlet(name="/RegisterServlet", urlPatterns= {"/RegisterServlet"})
public class RegisterServlet extends HttpServlet{
/**
* default serial version ID
*/
private static final long serialVersionUID = 1L;
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
UserService userService = new UserService();
Map<String,String[]> map = request.getParameterMap();
Iterator<String> iter = map.keySet().iterator();
Object obj = null;
try {
Class<?> clazz = Class.forName("org.lks.loginandregister.domain.User");
obj = clazz.getDeclaredConstructor().newInstance();
Method method = null;
Field field = null;
while(iter.hasNext()) {
String key = iter.next();
String keyAttribute = key.replace("register", "").toLowerCase();
field = clazz.getDeclaredField(keyAttribute);
String keyCapitalize = "";
if(key.length() == 1) {
keyCapitalize = keyAttribute.toUpperCase();
}else {
keyCapitalize = keyAttribute.substring(0,1).toUpperCase() + keyAttribute.substring(1);
}
method = clazz.getDeclaredMethod("set" + keyCapitalize, field.getType());
if(map.get(key).length == 1) {
method.invoke(obj, map.get(key)[0]);
}
}
}catch(Exception e) {
throw new RuntimeException(e);
}
try {
userService.register(obj);
}catch(UserException e) {
request.setAttribute("userExceptionMessage", e.getMessage());
request.getRequestDispatcher("/login/register.jsp").forward(request, response);
return;
}catch(Exception e) {
throw new RuntimeException(e);
}
response.sendRedirect(request.getContextPath() + "/login/login.jsp");
}
}
(3)UserService的regist()方法
|——沒有返回值,但註冊失敗拋出一個自定義異常,可以在異常中添加異常信息。(自定義異常類)
|——校驗用戶是否被註冊(通過用戶名查詢用戶)
|——添加用戶
public void register(Object obj) throws Exception {
User user = (User)obj;
if(userDao.findUserByUsername(user.getUsername()) == null) {
userDao.addUser(user);
}else {
throw new UserException("用戶已存在!");
}
}
(4)UserDao:通過業務分析,得到結果,需要提供兩個方法
|——按用戶名查詢用戶對象:findByUsernmae(String username)
|——插入一個用戶到數據庫中:void add(User user)
package org.lks.loginandregister.dao;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.net.URL;
import java.net.URLConnection;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
import org.lks.loginandregister.domain.User;
public class UserDao {
private static final URL USER_DATA_URL = UserDao.class.getClassLoader().getResource("org/lks/loginandregister/resource/users.xml");
/**
* Find user by name in users.xml
* @param username
* @return User
*/
public User findUserByUsername(String username) {
User result = null;
try {
SAXReader saxReader = new SAXReader();
Document xmlDocument = saxReader.read(USER_DATA_URL.openStream());
Element userElement = (Element)xmlDocument.selectSingleNode("//user[@username='" + username + "']");
if(userElement != null) {
result = new User();
String findUsername = userElement.attributeValue("username");
String findPassword = userElement.attributeValue("password");
result.setUsername(findUsername);
result.setPassword(findPassword);
}
}catch(Exception e) {
throw new RuntimeException(e);
}
return result;
}
/**
* add User to users.xml
* @param user
*/
public void addUser(User user) {
URLConnection urlConn = null;
InputStream input = null;
XMLWriter xmlWriter = null;
try {
SAXReader saxReader = new SAXReader();
urlConn = USER_DATA_URL.openConnection();
input = urlConn.getInputStream();
Document xmlDocument = saxReader.read(input);
input.close();
Element root = xmlDocument.getRootElement();
Element userElement = root.addElement("user");
userElement.addAttribute("username", user.getUsername());
userElement.addAttribute("password", user.getPassword());
OutputFormat outputFormat = new OutputFormat("\t",true);
outputFormat.setTrimText(true);
xmlWriter = new XMLWriter(new OutputStreamWriter(new FileOutputStream(USER_DATA_URL.getFile()), "UTF-8"),outputFormat);
xmlWriter.write(xmlDocument);
}catch(Exception e) {
throw new RuntimeException(e);
}finally {
try {
if(input != null) {
input.close();
}
if(xmlWriter != null) {
xmlWriter.close();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public static URL getURL() {
return UserDao.USER_DATA_URL;
}
}
2、工作
(1)在service層添加一個UserException
(2)dao:
|——User findByUsername(String username)
|——void add(User user)
(3)service
|——void regist() throws UserException
(4)servlet
|——封裝表單數據到User對象中
|——使用user調用service的regist方法
|————如果得到UserException,那麼把異常信息保存到request域中,轉發回regist.jsp
|————輸出“註冊成功”。
5 註冊功能流程圖
6 給註冊添加驗證碼
1、VerifyCode類
(1)BufferedImage getImage():獲取隨機的驗證碼圖片。
(2)String getText():獲取圖片上的文本。
(3)static output(BufferImage, OutputStream):把圖片寫入到指定的輸出流中。
2、VerifyCodeServlet類
(1)獲取驗證碼圖片。
(2)把驗證碼圖片上的文本保存到session中。
(3)把圖片響應到request的outputStream中。
3、regist.jsp
(1)添加<img src="指向Servlet" />
。
(2)添加一個文本框,用來輸入驗證碼
(3)“看不清,換一張”,是一個超鏈接,把上面的<img>
的src重新再次指向Servlet。爲了處理瀏覽器的緩存,需要使用時間來做參數。
4、修改registServlet類
(1)校驗驗證碼。
(2)錯誤:保存表單信息到request域、保存錯誤信息到request域,轉發回regist.jsp。
(3)正確:繼續向下執行。
驗證碼代碼:代碼
7 服務器端表單校驗
1、使用Map類型來裝載錯誤信息。
(1)key:表單項名稱。
(2)value:
|——非空:用戶名不能爲空,或者是“密碼不能爲空”。
|——長度:用戶名長度必須在3-20之間,密碼長度必須在6-20之間。
2、在校驗失敗時,向Map中添加錯誤信息,哪個字段出錯,就給哪個字段添加錯誤信息。
3、判斷Map是否爲空(長度是否爲0),如果不空,說明有錯誤存在,保存Map到request域中,保存user到request域(回顯),轉發回regist.jsp。
4、在regist.jsp頁面中,顯示Map中的錯誤信息。
代碼略。
8 登錄功能分析
1、頁面
(1)login.jsp:登錄表單
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Login</title>
</head>
<body>
<h1>Login</h1>
${requestScope.userExceptionMessage }
<form action="${pageContext.request.contextPath }/LoginServlet" method="post">
Username: <input type="text" name="loginUsername" value="${requestScope.loginUsername }" /><br/>
Password: <input type="password" name="loginPassword" value="${requestScope.loginPassword }" /><br/>
<input type="submit" value="sign in" />
</form>
</body>
</html>
2、LoginServlet
(1)獲取表單數據,封裝到User中。
(2)調用service的login()方法,傳遞user過去。
(3)service的login()方法
|——有異常:獲取異常信息,保存到request域,保存form,轉發到login.jsp
|——無異常:保存返回的user對象到session中,重定向到welcome.jsp(顯示當前用戶信息)
package org.lks.loginandregister.web.servlet;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Iterator;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.lks.loginandregister.service.UserException;
import org.lks.loginandregister.service.UserService;
/**
* Servlet implementation class LoginServlet
*/
@WebServlet(name="/LoginServlet",urlPatterns= {"/LoginServlet"})
public class LoginServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
UserService userService = new UserService();
Map<String,String[]> map = request.getParameterMap();
Iterator<String> iter = map.keySet().iterator();
Class<?> clazz = null;
Object obj = null;
try {
clazz = Class.forName("org.lks.loginandregister.domain.User");
obj = clazz.getDeclaredConstructor().newInstance();
Field field = null;
Method method = null;
while(iter.hasNext()) {
String key = iter.next();
String keyAttribute = key.replace("login", "").toLowerCase();
field = clazz.getDeclaredField(keyAttribute);
String keyCapitalize = "";
if(keyAttribute.length() == 1) {
keyCapitalize = keyAttribute.toUpperCase();
}else {
keyCapitalize = keyAttribute.substring(0,1).toUpperCase() + keyAttribute.substring(1);
}
method = clazz.getDeclaredMethod("set" + keyCapitalize, field.getType());
if(map.get(key).length == 1) {
method.invoke(obj, map.get(key)[0]);
}
}
}catch(Exception e) {
throw new RuntimeException(e);
}
try {
request.getSession().setAttribute("user", userService.login(obj));
}catch(UserException e) {
request.setAttribute("userExceptionMessage", e.getMessage());
request.getRequestDispatcher("/login/login.jsp").forward(request, response);
return ;
}catch(Exception e) {
throw new RuntimeException(e);
}
response.sendRedirect(request.getContextPath() + "/login/welcome.jsp");
}
}
3、UserService的login()方法
(1)使用用戶名查詢數據庫,得到返回的User
|——返回爲null,拋出異常,異常信息爲(用戶名不存在)
|——返回不爲null,獲取查詢出來的user的password和form的password進行比較。如果不同,拋出異常(密碼錯誤);如果相同,返回查詢結果。
public User login(Object obj) throws Exception{
User user = (User)obj;
User result = userDao.findUserByUsername(user.getUsername());
if(result != null) {
return result;
}else{
throw new UserException("用戶名或密碼錯誤!");
}
}
4、UserDao
(1)通過用戶名查詢用戶。