欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

JavaWeb實(shí)現(xiàn)用戶登錄注冊(cè)功能實(shí)例代碼(基于Servlet+JSP+JavaBean模式)

 更新時(shí)間:2016年05月29日 09:50:03   作者:孤傲蒼狼  
這篇文章主要基于Servlet+JSP+JavaBean開(kāi)發(fā)模式實(shí)現(xiàn)JavaWeb用戶登錄注冊(cè)功能實(shí)例代碼,非常實(shí)用,本文介紹的非常詳細(xì),具有參考借鑒價(jià)值,感興趣的朋友一起看看吧

下面通過(guò)通過(guò)圖文并茂的方式給大家介紹JavaWeb實(shí)現(xiàn)用戶登錄注冊(cè)功能實(shí)例代碼,一起看看吧。

一、Servlet+JSP+JavaBean開(kāi)發(fā)模式(MVC)介紹

  Servlet+JSP+JavaBean模式(MVC)適合開(kāi)發(fā)復(fù)雜的web應(yīng)用,在這種模式下,servlet負(fù)責(zé)處理用戶請(qǐng)求,jsp負(fù)責(zé)數(shù)據(jù)顯示,javabean負(fù)責(zé)封裝數(shù)據(jù)。 Servlet+JSP+JavaBean模式程序各個(gè)模塊之間層次清晰,web開(kāi)發(fā)推薦采用此種模式。

  這里以一個(gè)最常用的用戶登錄注冊(cè)程序來(lái)講解Servlet+JSP+JavaBean開(kāi)發(fā)模式,通過(guò)這個(gè)用戶登錄注冊(cè)程序綜合案例,把之前的學(xué)過(guò)的XML、Xpath、Servlet、jsp的知識(shí)點(diǎn)都串聯(lián)起來(lái)。

二、創(chuàng)建MVC架構(gòu)的Web項(xiàng)目

  在MyEclipse中新創(chuàng)建一個(gè)webmvcframework項(xiàng)目,導(dǎo)入項(xiàng)目所需要的開(kāi)發(fā)包(jar包),創(chuàng)建項(xiàng)目所需要的包,在java開(kāi)發(fā)中,架構(gòu)的層次是以包的形式體現(xiàn)出來(lái)的

項(xiàng)目所需要的開(kāi)發(fā)包(jar包)
序號(hào) 開(kāi)發(fā)包名稱(chēng) 描述
1 dom4j-1.6.1.jar dom4j用于操作XML文件
2 jaxen-1.1-beta-6.jar 用于解析XPath表達(dá)式
3 commons-beanutils-1.8.0.jar 工具類(lèi),用于處理bean對(duì)象
4 commons-logging.jar commons-beanutils-1.8.0.jar的依賴(lài)jar包
5 jstl.jar jstl標(biāo)簽庫(kù)和EL表達(dá)式依賴(lài)包
6 standard.jar jstl標(biāo)簽庫(kù)和EL表達(dá)式依賴(lài)包

一個(gè)良好的JavaWeb項(xiàng)目架構(gòu)應(yīng)該具有以上的11個(gè)包,這樣顯得層次分明,各個(gè)層之間的職責(zé)也很清晰明了,搭建JavaWeb項(xiàng)目架構(gòu)時(shí),就按照上面的1~11的序號(hào)順序創(chuàng)建包:domain→dao→dao.impl→service→service.impl→web.controller→web.UI→web.filter→web.listener→util→junit.test,包的層次創(chuàng)建好了,項(xiàng)目的架構(gòu)也就定下來(lái)了,當(dāng)然,在實(shí)際的項(xiàng)目開(kāi)發(fā)中,也不一定是完完全全按照

項(xiàng)目所需要的包
序號(hào) 包名 描述 所屬層次
1 me.gacl.domain 存放系統(tǒng)的JavaBean類(lèi)(只包含簡(jiǎn)單的屬性以及屬性對(duì)應(yīng)的get和set方法,不包含具體的業(yè)務(wù)處理方法),提供給【數(shù)據(jù)訪問(wèn)層】、【業(yè)務(wù)處理層】、【W(wǎng)eb層】來(lái)使用  domain(域模型)層
2 me.gacl.dao 存放訪問(wèn)數(shù)據(jù)庫(kù)的操作接口類(lèi) 數(shù)據(jù)訪問(wèn)層
3 me.gacl.dao.impl 存放訪問(wèn)數(shù)據(jù)庫(kù)的操作接口的實(shí)現(xiàn)類(lèi)
4 me.gacl.service 存放處理系統(tǒng)業(yè)務(wù)接口類(lèi) 業(yè)務(wù)處理層
5 me.gacl.service.impl 存放處理系統(tǒng)業(yè)務(wù)接口的實(shí)現(xiàn)類(lèi)
6 me.gacl.web.controller 存放作為系統(tǒng)控制器的Servlet Web層(表現(xiàn)層)
7 me.gacl.web.UI 存放為用戶提供用戶界面的servlet(UI指的是user interface)
8 me.gacl.web.filter 存放系統(tǒng)的用到的過(guò)濾器(Filter)
9 me.gacl.web.listener 存放系統(tǒng)的用到的監(jiān)聽(tīng)器(Listener)
10 me.gacl.util 存放系統(tǒng)的通用工具類(lèi),提供給【數(shù)據(jù)訪問(wèn)層】、【業(yè)務(wù)處理層】、【W(wǎng)eb層】來(lái)使用  
11 junit.test 存放系統(tǒng)的測(cè)試類(lèi)

上面說(shuō)的來(lái)創(chuàng)建包的層次結(jié)構(gòu),而是根據(jù)項(xiàng)目的實(shí)際情況,可能還需要?jiǎng)?chuàng)建其

他的包,這個(gè)得根據(jù)項(xiàng)目的需要來(lái)定了

  在src目錄(類(lèi)目錄)下面,創(chuàng)建用于保存用戶數(shù)據(jù)的xml文件(DB.xml)

  在WEB-INF目錄下創(chuàng)建一個(gè)pages目錄,pages目錄存放系統(tǒng)的一些受保護(hù)(不允許用戶直接通過(guò)URL地址訪問(wèn))的jsp頁(yè)面,用戶要想訪問(wèn)這些受保護(hù)的jsp頁(yè)面,那么只能通過(guò)me.gacl.web.UI這個(gè)包里面的Servlet

  創(chuàng)建好的項(xiàng)目如下圖(圖-1)所示:

  

                圖-1

三、分層架構(gòu)的代碼編寫(xiě)

  分層架構(gòu)的代碼也是按照【域模型層(domain)】→【數(shù)據(jù)訪問(wèn)層(dao、dao.impl)】→【業(yè)務(wù)處理層(service、service.impl)】→【表現(xiàn)層(web.controller、web.UI、web.filter、web.listener)】→【工具類(lèi)(util)】→【測(cè)試類(lèi)(junit.test)】的順序進(jìn)行編寫(xiě)的。

3.1、開(kāi)發(fā)domain層

  在me.gacl.domain包下創(chuàng)建一個(gè)User類(lèi)

  

  User類(lèi)具體代碼如下:

package me.gacl.domain;
import java.io.Serializable;
import java.util.Date;
/**
* @author gacl
* 用戶實(shí)體類(lèi)
*/
public class User implements Serializable {
private static final long serialVersionUID = -L;
// 用戶ID
private String id;
// 用戶名
private String userName;
// 用戶密碼
private String userPwd;
// 用戶郵箱
private String email;
// 用戶生日
private Date birthday;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getUserPwd() {
return userPwd;
}
public void setUserPwd(String userPwd) {
this.userPwd = userPwd;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
}

3.2、開(kāi)發(fā)數(shù)據(jù)訪問(wèn)層(dao、dao.impl)

  在me.gacl.dao包下創(chuàng)建一個(gè)IUserDao接口類(lèi),對(duì)于開(kāi)發(fā)接口類(lèi),我習(xí)慣以字母I作類(lèi)的前綴,這樣一眼就看出當(dāng)前這個(gè)類(lèi)是一個(gè)接口,這也算是一種良好的開(kāi)發(fā)習(xí)慣吧,通過(guò)看類(lèi)名就可以方便區(qū)分出是接口還是具體的實(shí)現(xiàn)類(lèi)。

  

  IUserDao接口的具體代碼如下:

package me.gacl.dao;
import me.gacl.domain.User;
public interface IUserDao {
/**
* 根據(jù)用戶名和密碼來(lái)查找用戶
* @param userName
* @param userPwd
* @return 查到到的用戶
*/
User find(String userName, String userPwd);
/**
* 添加用戶
* @param user
*/
void add(User user);
/**根據(jù)用戶名來(lái)查找用戶
* @param userName
* @return 查到到的用戶
*/
User find(String userName);
}

  對(duì)于接口中的方法定義,這個(gè)只能是根據(jù)具體的業(yè)務(wù)來(lái)分析需要定義哪些方法了,但是無(wú)論是多么復(fù)雜的業(yè)務(wù),都離不開(kāi)基本的CRUD(增刪改查)操作,Dao層是直接和數(shù)據(jù)庫(kù)交互的,所以Dao層的接口一般都會(huì)有增刪改查這四種操作的相關(guān)方法。

  在me.gacl.dao.impl包下創(chuàng)建一個(gè)UserDaoImpl類(lèi)

  

  UserDaoImpl類(lèi)是IUserDao接口的具體實(shí)現(xiàn)類(lèi),對(duì)于接口的實(shí)現(xiàn)類(lèi)命名方式,我習(xí)慣以"接口名(去除前綴I)+impl"形式或者"接口名+impl"形式來(lái)命名:IUserDao(接口)→UserDaoImpl(實(shí)現(xiàn)類(lèi))或者IUserDao(接口)→IUserDaoImpl(實(shí)現(xiàn)類(lèi)),這也算是一些個(gè)人的編程習(xí)慣吧,平時(shí)看到的代碼大多數(shù)都是以這兩種形式中的一種來(lái)來(lái)命名接口的具體實(shí)現(xiàn)類(lèi)的,反正就是要能夠一眼看出接口對(duì)應(yīng)的實(shí)現(xiàn)類(lèi)是哪一個(gè)就可以了。

  UserDaoImpl類(lèi)的具體代碼如下:

package me.gacl.dao.impl;
import java.text.SimpleDateFormat;
import org.domj.Document;
import org.domj.Element;
import me.gacl.dao.IUserDao;
import me.gacl.domain.User;
import me.gacl.util.XmlUtils;
/**
* IUserDao接口的實(shí)現(xiàn)類(lèi)
* @author gacl
*/
public class UserDaoImpl implements IUserDao {
@Override
public User find(String userName, String userPwd) {
try{
Document document = XmlUtils.getDocument();
//使用XPath表達(dá)式來(lái)操作XML節(jié)點(diǎn)
Element e = (Element) document.selectSingleNode("http://user[@userName='"+userName+"' and @userPwd='"+userPwd+"']");
if(e==null){
return null;
}
User user = new User();
user.setId(e.attributeValue("id"));
user.setEmail(e.attributeValue("email"));
user.setUserPwd(e.attributeValue("userPwd"));
user.setUserName(e.attributeValue("userName"));
String birth = e.attributeValue("birthday");
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
user.setBirthday(sdf.parse(birth));
return user;
}catch (Exception e) {
throw new RuntimeException(e);
}
}
@SuppressWarnings("deprecation")
@Override
public void add(User user) {
try{
Document document = XmlUtils.getDocument();
Element root = document.getRootElement();
Element user_node = root.addElement("user"); //創(chuàng)建user結(jié)點(diǎn),并掛到root
user_node.setAttributeValue("id", user.getId());
user_node.setAttributeValue("userName", user.getUserName());
user_node.setAttributeValue("userPwd", user.getUserPwd());
user_node.setAttributeValue("email", user.getEmail());
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
user_node.setAttributeValue("birthday", sdf.format(user.getBirthday()));
XmlUtils.writeXml(document);
}catch (Exception e) {
throw new RuntimeException(e);
}
}
@Override
public User find(String userName) {
try{
Document document = XmlUtils.getDocument();
Element e = (Element) document.selectSingleNode("http://user[@userName='"+userName+"']");
if(e==null){
return null;
}
User user = new User();
user.setId(e.attributeValue("id"));
user.setEmail(e.attributeValue("email"));
user.setUserPwd(e.attributeValue("userPwd"));
user.setUserName(e.attributeValue("userName"));
String birth = e.attributeValue("birthday");
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
user.setBirthday(sdf.parse(birth));
return user;
}catch (Exception e) {
throw new RuntimeException(e);
}
}
}

3.3、開(kāi)發(fā)service層(service層對(duì)web層提供所有的業(yè)務(wù)服務(wù))

  在me.gacl.service包中創(chuàng)建IUserService接口類(lèi)

    IUserService接口的具體代碼如下:

package me.gacl.service;
import me.gacl.domain.User;
import me.gacl.exception.UserExistException;
public interface IUserService {
/**
* 提供注冊(cè)服務(wù)
* @param user
* @throws UserExistException
*/
void registerUser(User user) throws UserExistException;
/**
* 提供登錄服務(wù)
* @param userName
* @param userPwd
* @return
*/
User loginUser(String userName, String userPwd);
}

  在me.gacl.service.impl包中創(chuàng)建UserServiceImpl類(lèi) 

  UserServiceImpl類(lèi)為IUserService接口的具體實(shí)現(xiàn)類(lèi),具體代碼如下:

package me.gacl.service.impl;
import me.gacl.dao.IUserDao;
import me.gacl.dao.impl.UserDaoImpl;
import me.gacl.domain.User;
import me.gacl.exception.UserExistException;
import me.gacl.service.IUserService;
public class UserServiceImpl implements IUserService {
private IUserDao userDao = new UserDaoImpl();
@Override
public void registerUser(User user) throws UserExistException {
if (userDao.find(user.getUserName())!=null) {
//checked exception 
//unchecked exception
//這里拋編譯時(shí)異常的原因:是我想上一層程序處理這個(gè)異常,以給用戶一個(gè)友好提示
throw new UserExistException("注冊(cè)的用戶名已存在?。?!");
}
userDao.add(user);
}
@Override
public User loginUser(String userName, String userPwd) {
return userDao.find(userName, userPwd);
}
}

3.4、開(kāi)發(fā)web層

3.4.1、 開(kāi)發(fā)注冊(cè)功能

    1、在me.gacl.web.UI包下寫(xiě)一個(gè)RegisterUIServlet為用戶提供注冊(cè)界面  

  RegisterUIServlet收到用戶請(qǐng)求后,就跳到register.jsp

  RegisterUIServlet的代碼如下:

package me.gacl.web.UI;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @author gacl
* 為用戶提供注冊(cè)的用戶界面的Servlet
* RegisterUIServlet負(fù)責(zé)為用戶輸出注冊(cè)界面
* 當(dāng)用戶訪問(wèn)RegisterUIServlet時(shí),就跳轉(zhuǎn)到WEB-INF/pages目錄下的register.jsp頁(yè)面
*/
public class RegisterUIServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.getRequestDispatcher("/WEB-INF/pages/register.jsp").forward(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}

2、在/WEB-INF/pages/目錄下編寫(xiě)用戶注冊(cè)的jsp頁(yè)面register.jsp

    

    凡是位于WEB-INF目錄下的jsp頁(yè)面是無(wú)法直接通過(guò)URL地址直接訪問(wèn)的,

    

    在開(kāi)發(fā)中如果項(xiàng)目中有一些敏感web資源不想被外界直接訪問(wèn),那么可以考慮將這些敏感的web資源放到WEB-INF目錄下,這樣就可以禁止外界直接通過(guò)URL來(lái)訪問(wèn)了。

  register.jsp頁(yè)面的代碼如下:

<%@ page language="java" pageEncoding="UTF-"%>
<!DOCTYPE HTML>
<html>
<head>
<title>用戶注冊(cè)</title>
</head>
<body style="text-align: center;">
<form action="${pageContext.request.contextPath}/servlet/RegisterServlet" method="post">
<table width="%" border="">
<tr>
<td>用戶名</td>
<td>
<input type="text" name="userName">
</td>
</tr>
<tr>
<td>密碼</td>
<td>
<input type="password" name="userPwd">
</td>
</tr>
<tr>
<td>確認(rèn)密碼</td>
<td>
<input type="password" name="confirmPwd">
</td>
</tr>
<tr>
<td>郵箱</td>
<td>
<input type="text" name="email">
</td>
</tr>
<tr>
<td>生日</td>
<td>
<input type="text" name="birthday">
</td>
</tr>
<tr>
<td>
<input type="reset" value="清空">
</td>
<td>
<input type="submit" value="注冊(cè)">
</td>
</tr>
</table>
</form>
</body>
</html>

  register.jsp中的<form action="${pageContext.request.contextPath}/servlet/RegisterServlet" method="post">指明表單提交后,交給RegisterServlet進(jìn)行處理

3、在me.gacl.web.controller包下編寫(xiě)用于處理用戶注冊(cè)的RegisterServlet

    RegisterServlet擔(dān)任著以下幾個(gè)職責(zé):

  1、接收客戶端提交到服務(wù)端的表單數(shù)據(jù)。

       2、校驗(yàn)表單數(shù)據(jù)的合法性,如果校驗(yàn)失敗跳回到register.jsp,并回顯錯(cuò)誤信息。

  3、如果校驗(yàn)通過(guò),調(diào)用service層向數(shù)據(jù)庫(kù)中注冊(cè)用戶。

    為了方便RegisterServlet接收表單數(shù)據(jù)和校驗(yàn)表單數(shù)據(jù),在此我設(shè)計(jì)一個(gè)用于校驗(yàn)注冊(cè)表單數(shù)據(jù)RegisterFormbean,再寫(xiě)WebUtils工具類(lèi),封裝客戶端提交的表單數(shù)據(jù)到formbean中。

  在me.gacl.web.formbean包下創(chuàng)建一個(gè)用于校驗(yàn)注冊(cè)表單數(shù)據(jù)RegisterFormbean

  

  RegisterFormbean代碼如下:

package me.gacl.web.formbean;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.beanutils.locale.converters.DateLocaleConverter;
/**
* 封裝的用戶注冊(cè)表單bean,用來(lái)接收register.jsp中的表單輸入項(xiàng)的值
* RegisterFormBean中的屬性與register.jsp中的表單輸入項(xiàng)的name一一對(duì)應(yīng)
* RegisterFormBean的職責(zé)除了負(fù)責(zé)接收register.jsp中的表單輸入項(xiàng)的值之外還擔(dān)任著校驗(yàn)表單輸入項(xiàng)的值的合法性
* @author gacl
*
*/
public class RegisterFormBean {
//RegisterFormBean中的屬性與register.jsp中的表單輸入項(xiàng)的name一一對(duì)應(yīng)
//<input type="text" name="userName"/>
private String userName;
//<input type="password" name="userPwd"/>
private String userPwd;
//<input type="password" name="confirmPwd"/>
private String confirmPwd;
//<input type="text" name="email"/>
private String email;
//<input type="text" name="birthday"/>
private String birthday;
/**
* 存儲(chǔ)校驗(yàn)不通過(guò)時(shí)給用戶的錯(cuò)誤提示信息
*/
private Map<String, String> errors = new HashMap<String, String>();
public Map<String, String> getErrors() {
return errors;
}
public void setErrors(Map<String, String> errors) {
this.errors = errors;
}
/*
* validate方法負(fù)責(zé)校驗(yàn)表單輸入項(xiàng)
* 表單輸入項(xiàng)校驗(yàn)規(guī)則:
* private String userName; 用戶名不能為空,并且要是-的字母 abcdABcd 
* private String userPwd; 密碼不能為空,并且要是-的數(shù)字
* private String confirmPwd; 兩次密碼要一致
* private String email; 可以為空,不為空要是一個(gè)合法的郵箱 
* private String birthday; 可以為空,不為空時(shí),要是一個(gè)合法的日期
*/
public boolean validate() {
boolean isOk = true;
if (this.userName == null || this.userName.trim().equals("")) {
isOk = false;
errors.put("userName", "用戶名不能為空?。?);
} else {
if (!this.userName.matches("[a-zA-Z]{,}")) {
isOk = false;
errors.put("userName", "用戶名必須是-位的字母?。?);
}
}
if (this.userPwd == null || this.userPwd.trim().equals("")) {
isOk = false;
errors.put("userPwd", "密碼不能為空?。?);
} else {
if (!this.userPwd.matches("\\d{,}")) {
isOk = false;
errors.put("userPwd", "密碼必須是-位的數(shù)字?。?);
}
}
// private String password; 兩次密碼要一致
if (this.confirmPwd != null) {
if (!this.confirmPwd.equals(this.userPwd)) {
isOk = false;
errors.put("confirmPwd", "兩次密碼不一致?。?);
}
}
// private String email; 可以為空,不為空要是一個(gè)合法的郵箱
if (this.email != null && !this.email.trim().equals("")) {
if (!this.email.matches("\\w+@\\w+(\\.\\w+)+")) {
isOk = false;
errors.put("email", "郵箱不是一個(gè)合法郵箱??!");
}
}
// private String birthday; 可以為空,不為空時(shí),要是一個(gè)合法的日期
if (this.birthday != null && !this.birthday.trim().equals("")) {
try {
DateLocaleConverter conver = new DateLocaleConverter();
conver.convert(this.birthday);
} catch (Exception e) {
isOk = false;
errors.put("birthday", "生日必須要是一個(gè)日期?。?);
}
}
return isOk;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getUserPwd() {
return userPwd;
}
public void setUserPwd(String userPwd) {
this.userPwd = userPwd;
}
public String getConfirmPwd() {
return confirmPwd;
}
public void setConfirmPwd(String confirmPwd) {
this.confirmPwd = confirmPwd;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getBirthday() {
return birthday;
}
public void setBirthday(String birthday) {
this.birthday = birthday;
}
}

  在me.gacl.util包下創(chuàng)建一個(gè)WebUtils工具類(lèi),該工具類(lèi)的功能就是封裝客戶端提交的表單數(shù)據(jù)到formbean中

package me.gacl.util;
import java.util.Enumeration;
import java.util.UUID;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.beanutils.BeanUtils;
/**
* @author gacl
* 把request對(duì)象中的請(qǐng)求參數(shù)封裝到bean中
*/
public class WebUtils {
/**
* 將request對(duì)象轉(zhuǎn)換成T對(duì)象
* @param request 
* @param clazz
* @return
*/
public static <T> T requestBean(HttpServletRequest request,Class<T> clazz){
try{
T bean = clazz.newInstance();
Enumeration<String> e = request.getParameterNames(); 
while(e.hasMoreElements()){
String name = (String) e.nextElement();
String value = request.getParameter(name);
BeanUtils.setProperty(bean, name, value);
}
return bean;
}catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* 生成UUID
* @return
*/
public static String makeId(){
return UUID.randomUUID().toString();
}
}

  最后看一下負(fù)責(zé)處理用戶注冊(cè)的RegisterServlet完整代碼:

package me.gacl.web.controller;
import java.io.IOException;
import java.util.Date;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.locale.converters.DateLocaleConverter;
import me.gacl.domain.User;
import me.gacl.exception.UserExistException;
import me.gacl.service.IUserService;
import me.gacl.service.impl.UserServiceImpl;
import me.gacl.util.WebUtils;
import me.gacl.web.formbean.RegisterFormBean;
/**
* 處理用戶注冊(cè)的Servlet
* @author gacl
*
*/
public class RegisterServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//將客戶端提交的表單數(shù)據(jù)封裝到RegisterFormBean對(duì)象中
RegisterFormBean formbean = WebUtils.requestBean(request,RegisterFormBean.class);
//校驗(yàn)用戶注冊(cè)填寫(xiě)的表單數(shù)據(jù)
if (formbean.validate() == false) {//如果校驗(yàn)失敗
//將封裝了用戶填寫(xiě)的表單數(shù)據(jù)的formbean對(duì)象發(fā)送回register.jsp頁(yè)面的form表單中進(jìn)行顯示
request.setAttribute("formbean", formbean);
//校驗(yàn)失敗就說(shuō)明是用戶填寫(xiě)的表單數(shù)據(jù)有問(wèn)題,那么就跳轉(zhuǎn)回register.jsp
request.getRequestDispatcher("/WEB-INF/pages/register.jsp").forward(request, response);
return;
}
User user = new User();
try {
// 注冊(cè)字符串到日期的轉(zhuǎn)換器
ConvertUtils.register(new DateLocaleConverter(), Date.class);
BeanUtils.copyProperties(user, formbean);//把表單的數(shù)據(jù)填充到j(luò)avabean中
user.setId(WebUtils.makeId());//設(shè)置用戶的Id屬性
IUserService service = new UserServiceImpl();
//調(diào)用service層提供的注冊(cè)用戶服務(wù)實(shí)現(xiàn)用戶注冊(cè)
service.registerUser(user);
String message = String.format(
"注冊(cè)成功?。∶牒鬄槟詣?dòng)跳到登錄頁(yè)面??!<meta http-equiv='refresh' content=';url=%s'/>", 
request.getContextPath()+"/servlet/LoginUIServlet");
request.setAttribute("message",message);
request.getRequestDispatcher("/message.jsp").forward(request,response);
} catch (UserExistException e) {
formbean.getErrors().put("userName", "注冊(cè)用戶已存在?。?);
request.setAttribute("formbean", formbean);
request.getRequestDispatcher("/WEB-INF/pages/register.jsp").forward(request, response);
} catch (Exception e) {
e.printStackTrace(); // 在后臺(tái)記錄異常
request.setAttribute("message", "對(duì)不起,注冊(cè)失敗??!");
request.getRequestDispatcher("/message.jsp").forward(request,response);
}
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}

  用戶注冊(cè)時(shí)如果填寫(xiě)的表單數(shù)據(jù)校驗(yàn)不通過(guò),那么服務(wù)器端就將一個(gè)存儲(chǔ)了錯(cuò)誤提示消息和表單數(shù)據(jù)的formbean對(duì)象存儲(chǔ)到request對(duì)象中,然后發(fā)送回register.jsp頁(yè)面,因此我們需要在register.jsp頁(yè)面中取出request對(duì)象中formbean對(duì)象,然后將用戶填寫(xiě)的表單數(shù)據(jù)重新回顯到對(duì)應(yīng)的表單項(xiàng)上面,將出錯(cuò)時(shí)的提示消息也顯示到form表單上面,讓用戶知道是哪些數(shù)據(jù)填寫(xiě)不合法!

  修改register.jsp頁(yè)面,代碼如下:

<%@ page language="java" pageEncoding="UTF-"%>
<!DOCTYPE HTML>
<html>
<head>
<title>用戶注冊(cè)</title>
</head>
<body style="text-align: center;">
<form action="${pageContext.request.contextPath}/servlet/RegisterServlet" method="post">
<table width="%" border="">
<tr>
<td>用戶名</td>
<td>
<%--使用EL表達(dá)式${}提取存儲(chǔ)在request對(duì)象中的formbean對(duì)象中封裝的表單數(shù)據(jù)(formbean.userName)以及錯(cuò)誤提示消息(formbean.errors.userName)--%>
<input type="text" name="userName" value="${formbean.userName}">${formbean.errors.userName}
</td>
</tr>
<tr>
<td>密碼</td>
<td>
<input type="password" name="userPwd" value="${formbean.userPwd}">${formbean.errors.userPwd}
</td>
</tr>
<tr>
<td>確認(rèn)密碼</td>
<td>
<input type="password" name="confirmPwd" value="${formbean.confirmPwd}">${formbean.errors.confirmPwd}
</td>
</tr>
<tr>
<td>郵箱</td>
<td>
<input type="text" name="email" value="${formbean.email}">${formbean.errors.email}
</td>
</tr>
<tr>
<td>生日</td>
<td>
<input type="text" name="birthday" value="${formbean.birthday}">${formbean.errors.birthday}
</td>
</tr>
<tr>
<td>
<input type="reset" value="清空">
</td>
<td>
<input type="submit" value="注冊(cè)">
</td>
</tr>
</table>
</form>
</body>
</html>

  到此,用戶注冊(cè)功能就算是開(kāi)發(fā)完成了!

  下面測(cè)試一下開(kāi)發(fā)好的用戶注冊(cè)功能:

    輸入U(xiǎn)RL地址:http://localhost:8080/webmvcframework/servlet/RegisterUIServlet訪問(wèn)register.jsp頁(yè)面,運(yùn)行效果如下:

    

  如果輸入的表單項(xiàng)不符合校驗(yàn)規(guī)則,那么是無(wú)法進(jìn)行注冊(cè)的,運(yùn)行效果如下:

    

3.4.2、 開(kāi)發(fā)登錄功能

  1、在me.gacl.web.UI包下寫(xiě)一個(gè)LoginUIServlet為用戶提供登錄界面

  

  LoginUIServlet收到用戶請(qǐng)求后,就跳到login.jsp

  LoginUIServlet的代碼如下:

package me.gacl.web.UI;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @author gacl
* LoginUIServlet負(fù)責(zé)為用戶輸出登陸界面
* 當(dāng)用戶訪問(wèn)LoginUIServlet時(shí),就跳轉(zhuǎn)到WEB-INF/pages目錄下的login.jsp頁(yè)面
*/
public class LoginUIServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.getRequestDispatcher("/WEB-INF/pages/login.jsp").forward(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}

  2、在/WEB-INF/pages/目錄下編寫(xiě)用戶登錄的jsp頁(yè)面login.jsp

  

  login.jsp頁(yè)面的代碼如下:

<%@ page language="java" pageEncoding="UTF-"%>
<!DOCTYPE HTML>
<html>
<head>
<title>用戶登陸</title>
</head>
<body>
<form action="${pageContext.request.contextPath }/servlet/LoginServlet" method="post">
用戶名:<input type="text" name="username"><br/>
密碼:<input type="password" name="password"><br/>
<input type="submit" value="登陸">
</form>
</body>
</html>

  login.jsp中的<form action="${pageContext.request.contextPath}/servlet/LoginServlet" method="post">指明表單提交后,交給LoginServlet進(jìn)行處理。

3、在me.gacl.web.controller包下編寫(xiě)用于處理用戶登錄的LoginServlet

  LoginServlet的代碼如下:

package me.gacl.web.controller;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import me.gacl.domain.User;
import me.gacl.service.IUserService;
import me.gacl.service.impl.UserServiceImpl;
/**
* 處理用戶登錄的servlet
* @author gacl
*
*/
public class LoginServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//獲取用戶填寫(xiě)的登錄用戶名
String username = request.getParameter("username");
//獲取用戶填寫(xiě)的登錄密碼
String password = request.getParameter("password");
IUserService service = new UserServiceImpl();
//用戶登錄
User user = service.loginUser(username, password);
if(user==null){
String message = String.format(
"對(duì)不起,用戶名或密碼有誤??!請(qǐng)重新登錄!秒后為您自動(dòng)跳到登錄頁(yè)面?。?lt;meta http-equiv='refresh' content=';url=%s'", 
request.getContextPath()+"/servlet/LoginUIServlet");
request.setAttribute("message",message);
request.getRequestDispatcher("/message.jsp").forward(request, response);
return;
}
//登錄成功后,就將用戶存儲(chǔ)到session中
request.getSession().setAttribute("user", user);
String message = String.format(
"恭喜:%s,登陸成功!本頁(yè)將在秒后跳到首頁(yè)??!<meta http-equiv='refresh' content=';url=%s'", 
user.getUserName(),
request.getContextPath()+"/index.jsp");
request.setAttribute("message",message);
request.getRequestDispatcher("/message.jsp").forward(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}

  到此,用戶登錄的功能就算是開(kāi)發(fā)完成了。

  下面測(cè)試一下開(kāi)發(fā)好的用戶登錄功能,輸入U(xiǎn)RL地址:http://localhost:8080/webmvcframework/servlet/LoginUIServlet訪問(wèn)login.jsp頁(yè)面,輸入正確的用戶名和密碼進(jìn)行登錄,運(yùn)行效果如下:

  

  如果輸入的用戶名和密碼錯(cuò)誤,那么就無(wú)法登錄成功,運(yùn)行效果如下:

  

3.4.3、 開(kāi)發(fā)注銷(xiāo)功能

  在me.gacl.web.controller包下編寫(xiě)用于處理用戶注銷(xiāo)的LogoutServlet

  LogoutServlet的代碼如下:

package me.gacl.web.controller;
import java.io.IOException;
import java.text.MessageFormat;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class LogoutServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//移除存儲(chǔ)在session中的user對(duì)象,實(shí)現(xiàn)注銷(xiāo)功能
request.getSession().removeAttribute("user");
//由于字符串中包含有單引號(hào),在這種情況下使用MessageFormat.format方法拼接字符串時(shí)就會(huì)有問(wèn)題
//MessageFormat.format方法只是把字符串中的單引號(hào)去掉,不會(huì)將內(nèi)容填充到指定的占位符中
String tempStr = MessageFormat.format(
"注銷(xiāo)成功?。∶牒鬄槟詣?dòng)跳到登錄頁(yè)面??!<meta http-equiv='refresh' content=';url={}'/>", 
request.getContextPath()+"/servlet/LoginUIServlet");
System.out.println(tempStr);//輸出結(jié)果:注銷(xiāo)成功!!秒后為您自動(dòng)跳到登錄頁(yè)面?。?lt;meta http-equiv=refresh content=;url={}/>
System.out.println("---------------------------------------------------------");
/**
* 要想解決"如果要拼接的字符串包含有單引號(hào),那么MessageFormat.format方法就只是把字符串中的單引號(hào)去掉,不會(huì)將內(nèi)容填充到指定的占位符中"這個(gè)問(wèn)題,
* 那么可以需要使用單引號(hào)引起來(lái)的字符串中使用個(gè)單引號(hào)引起來(lái),例如:"<meta http-equiv=''refresh'' content='';url={}''/>"
* 這樣MessageFormat.format("<meta http-equiv=''refresh'' content='';url={}''/>","index.jsp")就可以正常返回
* <meta http-equiv=''refresh'' content='';url=index.jsp'/>
*/
String tempStr = MessageFormat.format(
"注銷(xiāo)成功?。∶牒鬄槟詣?dòng)跳到登錄頁(yè)面??!<meta http-equiv=''refresh'' content='';url={}''/>", 
request.getContextPath()+"/servlet/LoginUIServlet");
/**
* 輸出結(jié)果:
* 注銷(xiāo)成功??!秒后為您自動(dòng)跳到登錄頁(yè)面??!
* <meta http-equiv='refresh' content=';url=/webmvcframework/servlet/LoginUIServlet'/>
*/
System.out.println(tempStr);
String message = String.format(
"注銷(xiāo)成功!!秒后為您自動(dòng)跳到登錄頁(yè)面??!<meta http-equiv='refresh' content=';url=%s'/>", 
request.getContextPath()+"/servlet/LoginUIServlet");
request.setAttribute("message",message);
request.getRequestDispatcher("/message.jsp").forward(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}

  用戶登錄成功后,會(huì)將登錄的用戶信息存儲(chǔ)在session中,所以我們要將存儲(chǔ)在session中的user刪除掉,這樣就可以實(shí)現(xiàn)用戶注銷(xiāo)了。

  用戶登錄成功后就會(huì)跳轉(zhuǎn)到index.jsp頁(yè)面,在index.jsp頁(yè)面中放一個(gè)【退出登陸】按鈕,當(dāng)點(diǎn)擊【退出登陸】按鈕時(shí),就訪問(wèn)LogoutServlet,將用戶注銷(xiāo)。

  index.jsp的代碼如下:

<%@ page language="java" pageEncoding="UTF-"%>
<%--為了避免在jsp頁(yè)面中出現(xiàn)java代碼,這里引入jstl標(biāo)簽庫(kù),利用jstl標(biāo)簽庫(kù)提供的標(biāo)簽來(lái)做一些邏輯判斷處理 --%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<!DOCTYPE HTML>
<html>
<head>
<title>首頁(yè)</title>
<script type="text/javascript">
function doLogout(){
//訪問(wèn)LogoutServlet注銷(xiāo)當(dāng)前登錄的用戶
window.location.href="${pageContext.request.contextPath}/servlet/LogoutServlet";
}
</script>
</head>
<body>
<h>孤傲蒼狼的網(wǎng)站</h>
<hr/>
<c:if test="${user==null}">
<a href="${pageContext.request.contextPath}/servlet/RegisterUIServlet" target="_blank">注冊(cè)</a>
<a href="${pageContext.request.contextPath}/servlet/LoginUIServlet">登陸</a>
</c:if>
<c:if test="${user!=null}">
歡迎您:${user.userName}
<input type="button" value="退出登陸" onclick="doLogout()">
</c:if>
<hr/>
</body>
</html>

  測(cè)試開(kāi)發(fā)好的注銷(xiāo)功能,效果如下:

  

  到此,所有的功能都開(kāi)發(fā)完成了,測(cè)試也通過(guò)了。

四、開(kāi)發(fā)總結(jié)

  通過(guò)這個(gè)小例子,可以了解到mvc分層架構(gòu)的項(xiàng)目搭建,在平時(shí)的項(xiàng)目開(kāi)發(fā)中,也都是按照如下的順序來(lái)進(jìn)行開(kāi)發(fā)的:

  1、搭建開(kāi)發(fā)環(huán)境

    1.1 創(chuàng)建web項(xiàng)目

    1.2 導(dǎo)入項(xiàng)目所需的開(kāi)發(fā)包

    1.3 創(chuàng)建程序的包名,在java中是以包來(lái)體現(xiàn)項(xiàng)目的分層架構(gòu)的

  2、開(kāi)發(fā)domain

  把一張要操作的表當(dāng)成一個(gè)VO類(lèi)(VO類(lèi)只定義屬性以及屬性對(duì)應(yīng)的get和set方法,沒(méi)有涉及到具體業(yè)務(wù)的操作方法),VO表示的是值對(duì)象,通俗地說(shuō),就是把表中的每一條記錄當(dāng)成一個(gè)對(duì)象,表中的每一個(gè)字段就作為這個(gè)對(duì)象的屬性。每往表中插入一條記錄,就相當(dāng)于是把一個(gè)VO類(lèi)的實(shí)例對(duì)象插入到數(shù)據(jù)表中,對(duì)數(shù)據(jù)表進(jìn)行操作時(shí),都是直接把一個(gè)VO類(lèi)的對(duì)象寫(xiě)入到表中,一個(gè)VO類(lèi)對(duì)象就是一條記錄。每一個(gè)VO對(duì)象可以表示一張表中的一行記錄,VO類(lèi)的名稱(chēng)要和表的名稱(chēng)一致或者對(duì)應(yīng)。

  3、開(kāi)發(fā)dao

    3.1 DAO操作接口:每一個(gè)DAO操作接口規(guī)定了,一張表在一個(gè)項(xiàng)目中的具體操作方法,此接口的名稱(chēng)最好按照如下格式編寫(xiě):“I表名稱(chēng)Dao”。

      ├DAO接口里面的所有方法按照以下的命名編寫(xiě):

        ├更新數(shù)據(jù)庫(kù):doXxx()

        ├查詢(xún)數(shù)據(jù)庫(kù):findXxx()或getXxx()

    3.2 DAO操作接口的實(shí)現(xiàn)類(lèi):實(shí)現(xiàn)類(lèi)中完成具體的增刪改查操作

      ├此實(shí)現(xiàn)類(lèi)完成的只是數(shù)據(jù)庫(kù)中最核心的操作,并沒(méi)有專(zhuān)門(mén)處理數(shù)據(jù)庫(kù)的打開(kāi)和關(guān)閉,因?yàn)檫@些操作與具體的業(yè)務(wù)操作無(wú)關(guān)。

  4、開(kāi)發(fā)service(service 對(duì)web層提供所有的業(yè)務(wù)服務(wù))

  5、開(kāi)發(fā)web層

以上內(nèi)容是小編給大家介紹的JavaWeb實(shí)現(xiàn)用戶登錄注冊(cè)功能實(shí)例代碼(基于Servlet+JSP+JavaBean模式),希望對(duì)大家有所幫助!

相關(guān)文章

  • java中線程安全的list詳細(xì)特性和用法

    java中線程安全的list詳細(xì)特性和用法

    這篇文章主要給大家介紹了關(guān)于java中線程安全的list詳細(xì)特性和用法的相關(guān)資料,Java中有多種線程安全的List,其中比較常用的有Vector、Collections.synchronizedList()和CopyOnWriteArrayList三種方式,需要的朋友可以參考下
    2024-03-03
  • spring boot整合redis實(shí)現(xiàn)shiro的分布式session共享的方法

    spring boot整合redis實(shí)現(xiàn)shiro的分布式session共享的方法

    本篇文章主要介紹了spring boot整合redis實(shí)現(xiàn)shiro的分布式session共享的方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-01-01
  • java版微信公眾平臺(tái)消息接口應(yīng)用示例

    java版微信公眾平臺(tái)消息接口應(yīng)用示例

    這篇文章主要介紹了java版微信公眾平臺(tái)消息接口應(yīng)用,結(jié)合實(shí)例形式對(duì)比分析了PHP與java應(yīng)用微信公眾平臺(tái)接口的相關(guān)調(diào)用與操作技巧,需要的朋友可以參考下
    2017-07-07
  • 使用Nexus搭建Maven私服的方法步驟

    使用Nexus搭建Maven私服的方法步驟

    這篇文章主要介紹了使用Nexus搭建Maven私服的方法步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-06-06
  • java中response對(duì)象用法實(shí)例分析

    java中response對(duì)象用法實(shí)例分析

    這篇文章主要介紹了java中response對(duì)象用法,結(jié)合實(shí)例形式分析了Java中response對(duì)象的功能及具體使用技巧,需要的朋友可以參考下
    2015-12-12
  • 一文探尋Java裝箱和拆箱的奧妙

    一文探尋Java裝箱和拆箱的奧妙

    Java中的裝箱(boxing)和拆箱(unboxing)是指將基本數(shù)據(jù)類(lèi)型與其對(duì)應(yīng)的包裝類(lèi)之間進(jìn)行轉(zhuǎn)換的過(guò)程。本文就來(lái)帶大家探索一下Java裝箱和拆箱的奧妙吧
    2023-04-04
  • Java實(shí)現(xiàn)局域網(wǎng)聊天小程序

    Java實(shí)現(xiàn)局域網(wǎng)聊天小程序

    這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)局域網(wǎng)聊天小程序,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-05-05
  • Spark學(xué)習(xí)筆記之Spark中的RDD的具體使用

    Spark學(xué)習(xí)筆記之Spark中的RDD的具體使用

    這篇文章主要介紹了Spark學(xué)習(xí)筆記之Spark中的RDD的具體使用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-06-06
  • java使用jar包生成二維碼的示例代碼

    java使用jar包生成二維碼的示例代碼

    這篇文章主要介紹了java使用jar包生成二維碼的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-11-11
  • 深入了解Java核心類(lèi)庫(kù)--BigDecimal和System類(lèi)

    深入了解Java核心類(lèi)庫(kù)--BigDecimal和System類(lèi)

    這篇文章主要為大家詳細(xì)介紹了javaBigDecimal和System類(lèi)定義與使用的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能給你帶來(lái)幫助
    2021-07-07

最新評(píng)論