00 Java項目實戰之註冊登錄

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)通過用戶名查詢用戶。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章