javaweb注册登录案例(thinkphp注册登录源码)

一、Servlet+JSP+JavaBean开发模式(MVC)介绍  Servlet+JSP+JavaBean模式(MVC)适合开发复杂的web应用,在这种模式下,servlet负责处理用户请求,jsp负责数据显示,javabean负责封装数据。Servlet+JSP+JavaBean模式程序各个模块之间层次清晰,web开发推荐采用此种模式。  这里以一个最常用的用户登录注册程序来讲解Servl…

大家好,又见面了,我是你们的朋友全栈君。

一、Servlet+JSP+JavaBean开发模式(MVC)介绍

  Servlet+JSP+JavaBean模式(MVC)适合开发复杂的web应用,在这种模式下,servlet负责处理用户请求,jsp负责数据显示,javabean负责封装数据。 Servlet+JSP+JavaBean模式程序各个模块之间层次清晰,web开发推荐采用此种模式。

  这里以一个最常用的用户登录注册程序来讲解Servlet+JSP+JavaBean开发模式,通过这个用户登录注册程序综合案例,把之前的学过的XML、Xpath、Servlet、jsp的知识点都串联起来。

二、创建MVC架构的Web项目

  在MyEclipse中新创建一个webmvcframework项目,导入项目所需要的开发包(jar包),创建项目所需要的包,在java开发中,架构的层次是以包的形式体现出来的

项目所需要的开发包(jar包)
序号 开发包名称 描述
1 dom4j-1.6.1.jar dom4j用于操作XML文件
2 jaxen-1.1-beta-6.jar 用于解析XPath表达式
3 commons-beanutils-1.8.0.jar 工具类,用于处理bean对象
4 commons-logging.jar commons-beanutils-1.8.0.jar的依赖jar包
5 jstl.jar jstl标签库和EL表达式依赖包
6 standard.jar jstl标签库和EL表达式依赖包

一个良好的JavaWeb项目架构应该具有以上的11个包,这样显得层次分明,各个层之间的职责也很清晰明了,搭建JavaWeb项目架构时,就按照上面的1~11的序号顺序创建包:domain→dao→dao.impl→service→service.impl→web.controller→web.UI→web.filter→web.listener→util→junit.test,包的层次创建好了,项目的架构也就定下来了,当然,在实际的项目开发中,也不一定是完完全全按照

项目所需要的包
序号 包名 描述 所属层次
1 me.gacl.domain 存放系统的JavaBean类(只包含简单的属性以及属性对应的get和set方法,不包含具体的业务处理方法),提供给【数据访问层】、【业务处理层】、【Web层】来使用  domain(域模型)层
2 me.gacl.dao 存放访问数据库的操作接口类 数据访问层
3 me.gacl.dao.impl 存放访问数据库的操作接口的实现类
4 me.gacl.service 存放处理系统业务接口类 业务处理层
5 me.gacl.service.impl 存放处理系统业务接口的实现类
6 me.gacl.web.controller 存放作为系统控制器的Servlet Web层(表现层)
7 me.gacl.web.UI 存放为用户提供用户界面的servlet(UI指的是user interface)
8 me.gacl.web.filter 存放系统的用到的过滤器(Filter)
9 me.gacl.web.listener 存放系统的用到的监听器(Listener)
10 me.gacl.util 存放系统的通用工具类,提供给【数据访问层】、【业务处理层】、【Web层】来使用  
11 junit.test 存放系统的测试类

上面说的来创建包的层次结构,而是根据项目的实际情况,可能还需要创建其

他的包,这个得根据项目的需要来定了

  在src目录(类目录)下面,创建用于保存用户数据的xml文件(DB.xml)

  在WEB-INF目录下创建一个pages目录,pages目录存放系统的一些受保护(不允许用户直接通过URL地址访问)的jsp页面,用户要想访问这些受保护的jsp页面,那么只能通过me.gacl.web.UI这个包里面的Servlet

  创建好的项目如下图(图-1)所示:

  javaweb注册登录案例(thinkphp注册登录源码)

                图-1

三、分层架构的代码编写

  分层架构的代码也是按照【域模型层(domain)】→【数据访问层(dao、dao.impl)】→【业务处理层(service、service.impl)】→【表现层(web.controller、web.UI、web.filter、web.listener)】→【工具类(util)】→【测试类(junit.test)】的顺序进行编写的。

3.1、开发domain层

  在me.gacl.domain包下创建一个User类

  javaweb注册登录案例(thinkphp注册登录源码)

  User类具体代码如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
package
me.gacl.domain;
import
java.io.Serializable;
import
java.util.Date;
/**
* @author gacl
* 用户实体类
*/
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、开发数据访问层(dao、dao.impl)

  在me.gacl.dao包下创建一个IUserDao接口类,对于开发接口类,我习惯以字母I作类的前缀,这样一眼就看出当前这个类是一个接口,这也算是一种良好的开发习惯吧,通过看类名就可以方便区分出是接口还是具体的实现类。

  javaweb注册登录案例(thinkphp注册登录源码)

  IUserDao接口的具体代码如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package
me.gacl.dao;
import
me.gacl.domain.User;
public
interface
IUserDao {
/**
* 根据用户名和密码来查找用户
* @param userName
* @param userPwd
* @return 查到到的用户
*/
User find(String userName, String userPwd);
/**
* 添加用户
* @param user
*/
void
add(User user);
/**根据用户名来查找用户
* @param userName
* @return 查到到的用户
*/
User find(String userName);
}

  对于接口中的方法定义,这个只能是根据具体的业务来分析需要定义哪些方法了,但是无论是多么复杂的业务,都离不开基本的CRUD(增删改查)操作,Dao层是直接和数据库交互的,所以Dao层的接口一般都会有增删改查这四种操作的相关方法。

  在me.gacl.dao.impl包下创建一个UserDaoImpl类

  javaweb注册登录案例(thinkphp注册登录源码)

  UserDaoImpl类是IUserDao接口的具体实现类,对于接口的实现类命名方式,我习惯以”接口名(去除前缀I)+impl”形式或者”接口名+impl”形式来命名:IUserDao(接口)→UserDaoImpl(实现类)或者IUserDao(接口)→IUserDaoImpl(实现类),这也算是一些个人的编程习惯吧,平时看到的代码大多数都是以这两种形式中的一种来来命名接口的具体实现类的,反正就是要能够一眼看出接口对应的实现类是哪一个就可以了。

  UserDaoImpl类的具体代码如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
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接口的实现类
* @author gacl
*/
public
class
UserDaoImpl
implements
IUserDao {
@Override
public
User find(String userName, String userPwd) {
try
{
Document document = XmlUtils.getDocument();
//使用XPath表达式来操作XML节点
Element e = (Element) document.selectSingleNode(
"//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"
);
//创建user结点,并挂到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(
"//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、开发service层(service层对web层提供所有的业务服务)

  在me.gacl.service包中创建IUserService接口类

javaweb注册登录案例(thinkphp注册登录源码)

    IUserService接口的具体代码如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package
me.gacl.service;
import
me.gacl.domain.User;
import
me.gacl.exception.UserExistException;
public
interface
IUserService {
/**
* 提供注册服务
* @param user
* @throws UserExistException
*/
void
registerUser(User user)
throws
UserExistException;
/**
* 提供登录服务
* @param userName
* @param userPwd
* @return
*/
User loginUser(String userName, String userPwd);
}

  在me.gacl.service.impl包中创建UserServiceImpl类 

javaweb注册登录案例(thinkphp注册登录源码)

  UserServiceImpl类为IUserService接口的具体实现类,具体代码如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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
//这里抛编译时异常的原因:是我想上一层程序处理这个异常,以给用户一个友好提示
throw
new
UserExistException(
"注册的用户名已存在!!!"
);
}
userDao.add(user);
}
@Override
public
User loginUser(String userName, String userPwd) {
return
userDao.find(userName, userPwd);
}
}

3.4、开发web层

3.4.1、 开发注册功能

    1、在me.gacl.web.UI包下写一个RegisterUIServlet为用户提供注册界面  

javaweb注册登录案例(thinkphp注册登录源码)

  RegisterUIServlet收到用户请求后,就跳到register.jsp

  RegisterUIServlet的代码如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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
* 为用户提供注册的用户界面的Servlet
* RegisterUIServlet负责为用户输出注册界面
* 当用户访问RegisterUIServlet时,就跳转到WEB-INF/pages目录下的register.jsp页面
*/
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/目录下编写用户注册的jsp页面register.jsp

    javaweb注册登录案例(thinkphp注册登录源码)

    凡是位于WEB-INF目录下的jsp页面是无法直接通过URL地址直接访问的,

    javaweb注册登录案例(thinkphp注册登录源码)

    在开发中如果项目中有一些敏感web资源不想被外界直接访问,那么可以考虑将这些敏感的web资源放到WEB-INF目录下,这样就可以禁止外界直接通过URL来访问了。

  register.jsp页面的代码如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
<%@ page language=
"java"
pageEncoding=
"UTF-"
%>
<!DOCTYPE HTML>
<html>
<head>
<title>用户注册</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>确认密码</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=
"注册"
>
</td>
</tr>
</table>
</form>
</body>
</html>

  register.jsp中的<form action=”${pageContext.request.contextPath}/servlet/RegisterServlet” method=”post”>指明表单提交后,交给RegisterServlet进行处理

3、在me.gacl.web.controller包下编写用于处理用户注册的RegisterServlet

javaweb注册登录案例(thinkphp注册登录源码)

    RegisterServlet担任着以下几个职责:

  1、接收客户端提交到服务端的表单数据。

       2、校验表单数据的合法性,如果校验失败跳回到register.jsp,并回显错误信息。

  3、如果校验通过,调用service层向数据库中注册用户。

    为了方便RegisterServlet接收表单数据和校验表单数据,在此我设计一个用于校验注册表单数据RegisterFormbean,再写WebUtils工具类,封装客户端提交的表单数据到formbean中。

  在me.gacl.web.formbean包下创建一个用于校验注册表单数据RegisterFormbean

  javaweb注册登录案例(thinkphp注册登录源码)

  RegisterFormbean代码如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
package
me.gacl.web.formbean;
import
java.util.HashMap;
import
java.util.Map;
import
org.apache.commons.beanutils.locale.converters.DateLocaleConverter;
/**
* 封装的用户注册表单bean,用来接收register.jsp中的表单输入项的值
* RegisterFormBean中的属性与register.jsp中的表单输入项的name一一对应
* RegisterFormBean的职责除了负责接收register.jsp中的表单输入项的值之外还担任着校验表单输入项的值的合法性
* @author gacl
*
*/
public
class
RegisterFormBean {
//RegisterFormBean中的属性与register.jsp中的表单输入项的name一一对应
//<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;
/**
* 存储校验不通过时给用户的错误提示信息
*/
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方法负责校验表单输入项
* 表单输入项校验规则:
* private String userName; 用户名不能为空,并且要是-的字母 abcdABcd
* private String userPwd; 密码不能为空,并且要是-的数字
* private String confirmPwd; 两次密码要一致
* private String email; 可以为空,不为空要是一个合法的邮箱
* private String birthday; 可以为空,不为空时,要是一个合法的日期
*/
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"
,
"密码必须是-位的数字!!"
);
}
}
// private String password; 两次密码要一致
if
(
this
.confirmPwd !=
null
) {
if
(!
this
.confirmPwd.equals(
this
.userPwd)) {
isOk =
false
;
errors.put(
"confirmPwd"
,
"两次密码不一致!!"
);
}
}
// private String email; 可以为空,不为空要是一个合法的邮箱
if
(
this
.email !=
null
&& !
this
.email.trim().equals(
""
)) {
if
(!
this
.email.matches(
"\\w+@\\w+(\\.\\w+)+"
)) {
isOk =
false
;
errors.put(
"email"
,
"邮箱不是一个合法邮箱!!"
);
}
}
// private String birthday; 可以为空,不为空时,要是一个合法的日期
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"
,
"生日必须要是一个日期!!"
);
}
}
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包下创建一个WebUtils工具类,该工具类的功能就是封装客户端提交的表单数据到formbean中

javaweb注册登录案例(thinkphp注册登录源码)

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
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对象中的请求参数封装到bean中
*/
public
class
WebUtils {
/**
* 将request对象转换成T对象
* @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();
}
}

  最后看一下负责处理用户注册的RegisterServlet完整代码:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
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;
/**
* 处理用户注册的Servlet
* @author gacl
*
*/
public
class
RegisterServlet
extends
HttpServlet {
public
void
doGet(HttpServletRequest request, HttpServletResponse response)
throws
ServletException, IOException {
//将客户端提交的表单数据封装到RegisterFormBean对象中
RegisterFormBean formbean = WebUtils.requestBean(request,RegisterFormBean.
class
);
//校验用户注册填写的表单数据
if
(formbean.validate() ==
false
) {

//如果校验失败
//将封装了用户填写的表单数据的formbean对象发送回register.jsp页面的form表单中进行显示
request.setAttribute(
"formbean"
, formbean);
//校验失败就说明是用户填写的表单数据有问题,那么就跳转回register.jsp
request.getRequestDispatcher(
"/WEB-INF/pages/register.jsp"
).forward(request, response);
return
;
}
User user =
new
User();
try
{
// 注册字符串到日期的转换器
ConvertUtils.register(
new
DateLocaleConverter(), Date.
class
);
BeanUtils.copyProperties(user, formbean);
//把表单的数据填充到javabean中
user.setId(WebUtils.makeId());
//设置用户的Id属性
IUserService service =
new
UserServiceImpl();
//调用service层提供的注册用户服务实现用户注册
service.registerUser(user);
String message = String.format(
"注册成功!!秒后为您自动跳到登录页面!!<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"
,
"注册用户已存在!!"
);
request.setAttribute(
"formbean"
, formbean);
request.getRequestDispatcher(
"/WEB-INF/pages/register.jsp"
).forward(request, response);
}
catch
(Exception e) {
e.printStackTrace();
// 在后台记录异常
request.setAttribute(
"message"
,
"对不起,注册失败!!"
);
request.getRequestDispatcher(
"/message.jsp"
).forward(request,response);
}
}
public
void
doPost(HttpServletRequest request, HttpServletResponse response)
throws
ServletException, IOException {
doGet(request, response);
}
}

  用户注册时如果填写的表单数据校验不通过,那么服务器端就将一个存储了错误提示消息和表单数据的formbean对象存储到request对象中,然后发送回register.jsp页面,因此我们需要在register.jsp页面中取出request对象中formbean对象,然后将用户填写的表单数据重新回显到对应的表单项上面,将出错时的提示消息也显示到form表单上面,让用户知道是哪些数据填写不合法!

  修改register.jsp页面,代码如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
<%@ page language=
"java"
pageEncoding=
"UTF-"
%>
<!DOCTYPE HTML>
<html>
<head>
<title>用户注册</title>
</head>
<body style=
"text-align: center;"
>
<form action=
"${pageContext.request.contextPath}/servlet/RegisterServlet"
method=
"post"
>
<table width=
"%"
border=
""
>
<tr>
<td>用户名</td>
<td>
<%--使用EL表达式${}提取存储在request对象中的formbean对象中封装的表单数据(formbean.userName)以及错误提示消息(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>确认密码</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=
"注册"
>
</td>
</tr>
</table>
</form>
</body>
</html>

  到此,用户注册功能就算是开发完成了!

  下面测试一下开发好的用户注册功能:

    输入URL地址:http://localhost:8080/webmvcframework/servlet/RegisterUIServlet访问register.jsp页面,运行效果如下:

    javaweb注册登录案例(thinkphp注册登录源码)

  如果输入的表单项不符合校验规则,那么是无法进行注册的,运行效果如下:

    javaweb注册登录案例(thinkphp注册登录源码)

3.4.2、 开发登录功能

  1、在me.gacl.web.UI包下写一个LoginUIServlet为用户提供登录界面

  javaweb注册登录案例(thinkphp注册登录源码)

  LoginUIServlet收到用户请求后,就跳到login.jsp

  LoginUIServlet的代码如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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负责为用户输出登陆界面
* 当用户访问LoginUIServlet时,就跳转到WEB-INF/pages目录下的login.jsp页面
*/
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/目录下编写用户登录的jsp页面login.jsp

  javaweb注册登录案例(thinkphp注册登录源码)

  login.jsp页面的代码如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<%@ 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进行处理。

3、在me.gacl.web.controller包下编写用于处理用户登录的LoginServlet

javaweb注册登录案例(thinkphp注册登录源码)

  LoginServlet的代码如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
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 {
//获取用户填写的登录用户名
String username = request.getParameter(
"username"
);
//获取用户填写的登录密码
String password = request.getParameter(
"password"
);
IUserService service =
new
UserServiceImpl();
//用户登录
User user = service.loginUser(username, password);
if
(user==
null
){
String message = String.format(
"对不起,用户名或密码有误!!请重新登录!秒后为您自动跳到登录页面!!<meta http-equiv='refresh' content=';url=%s'"
,
request.getContextPath()+
"/servlet/LoginUIServlet"
);
request.setAttribute(
"message"
,message);
request.getRequestDispatcher(
"/message.jsp"
).forward(request, response);
return
;
}
//登录成功后,就将用户存储到session中
request.getSession().setAttribute(
"user"
, user);
String message = String.format(
"恭喜:%s,登陆成功!本页将在秒后跳到首页!!<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);
}
}

  到此,用户登录的功能就算是开发完成了。

  下面测试一下开发好的用户登录功能,输入URL地址:http://localhost:8080/webmvcframework/servlet/LoginUIServlet访问login.jsp页面,输入正确的用户名和密码进行登录,运行效果如下:

  javaweb注册登录案例(thinkphp注册登录源码)

  如果输入的用户名和密码错误,那么就无法登录成功,运行效果如下:

  javaweb注册登录案例(thinkphp注册登录源码)

3.4.3、 开发注销功能

  在me.gacl.web.controller包下编写用于处理用户注销的LogoutServlet

  LogoutServlet的代码如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
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 {
//移除存储在session中的user对象,实现注销功能
request.getSession().removeAttribute(
"user"
);
//由于字符串中包含有单引号,在这种情况下使用MessageFormat.format方法拼接字符串时就会有问题
//MessageFormat.format方法只是把字符串中的单引号去掉,不会将内容填充到指定的占位符中
String tempStr = MessageFormat.format(
"注销成功!!秒后为您自动跳到登录页面!!<meta http-equiv='refresh' content=';url={}'/>"
,
request.getContextPath()+
"/servlet/LoginUIServlet"
);
System.out.println(tempStr);
//输出结果:注销成功!!秒后为您自动跳到登录页面!!<meta http-equiv=refresh content=;url={}/>
System.out.println(
"---------------------------------------------------------"
);
/**
* 要想解决"如果要拼接的字符串包含有单引号,那么MessageFormat.format方法就只是把字符串中的单引号去掉,不会将内容填充到指定的占位符中"这个问题,
* 那么可以需要使用单引号引起来的字符串中使用个单引号引起来,例如:"<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(
"注销成功!!秒后为您自动跳到登录页面!!<meta http-equiv=''refresh'' content='';url={}''/>"
,
request.getContextPath()+
"/servlet/LoginUIServlet"
);
/**
* 输出结果:
* 注销成功!!秒后为您自动跳到登录页面!!
* <meta http-equiv='refresh' content=';url=/webmvcframework/servlet/LoginUIServlet'/>
*/
System.out.println(tempStr);
String message = String.format(
"注销成功!!秒后为您自动跳到登录页面!!<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);
}
}

  用户登录成功后,会将登录的用户信息存储在session中,所以我们要将存储在session中的user删除掉,这样就可以实现用户注销了。

  用户登录成功后就会跳转到index.jsp页面,在index.jsp页面中放一个【退出登陆】按钮,当点击【退出登陆】按钮时,就访问LogoutServlet,将用户注销。

  index.jsp的代码如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<%@ page language=
"java"
pageEncoding=
"UTF-"
%>
<%--为了避免在jsp页面中出现java代码,这里引入jstl标签库,利用jstl标签库提供的标签来做一些逻辑判断处理 --%>
<%@ taglib uri=
"http://java.sun.com/jsp/jstl/core"
prefix=
"c"
%>
<!DOCTYPE HTML>
<html>
<head>
<title>首页</title>
<script type=
"text/javascript"
>
function doLogout(){
//访问LogoutServlet注销当前登录的用户
window.location.href=
"${pageContext.request.contextPath}/servlet/LogoutServlet"
;
}
</script>
</head>
<body>
<h>孤傲苍狼的网站</h>
<hr/>
<c:
if
test=
"${user==null}"
>
<a href=
"${pageContext.request.contextPath}/servlet/RegisterUIServlet"
target=
"_blank"
>注册</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>

  测试开发好的注销功能,效果如下:

  javaweb注册登录案例(thinkphp注册登录源码)

  到此,所有的功能都开发完成了,测试也通过了。

四、开发总结

  通过这个小例子,可以了解到mvc分层架构的项目搭建,在平时的项目开发中,也都是按照如下的顺序来进行开发的:

  1、搭建开发环境

    1.1 创建web项目

    1.2 导入项目所需的开发包

    1.3 创建程序的包名,在java中是以包来体现项目的分层架构的

  2、开发domain

  把一张要操作的表当成一个VO类(VO类只定义属性以及属性对应的get和set方法,没有涉及到具体业务的操作方法),VO表示的是值对象,通俗地说,就是把表中的每一条记录当成一个对象,表中的每一个字段就作为这个对象的属性。每往表中插入一条记录,就相当于是把一个VO类的实例对象插入到数据表中,对数据表进行操作时,都是直接把一个VO类的对象写入到表中,一个VO类对象就是一条记录。每一个VO对象可以表示一张表中的一行记录,VO类的名称要和表的名称一致或者对应。

  3、开发dao

    3.1 DAO操作接口:每一个DAO操作接口规定了,一张表在一个项目中的具体操作方法,此接口的名称最好按照如下格式编写:“I表名称Dao”。

      ├DAO接口里面的所有方法按照以下的命名编写:

        ├更新数据库:doXxx()

        ├查询数据库:findXxx()或getXxx()

    3.2 DAO操作接口的实现类:实现类中完成具体的增删改查操作

      ├此实现类完成的只是数据库中最核心的操作,并没有专门处理数据库的打开和关闭,因为这些操作与具体的业务操作无关。

  4、开发service(service 对web层提供所有的业务服务)

  5、开发web层

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/127754.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • 电子商务网站安全_跨境电商有哪些平台

    电子商务网站安全_跨境电商有哪些平台电商网站安全应对之道(电商网站安全的威胁类型:https://blog.csdn.net/qq_29039705/article/details/80486795)一、预防逻辑漏洞进行业务流程梳理接口会发加签名和超时机制避免通过前端进行验证和现在减少暴露给用户的参数增加共享数据互斥机制不要相信用户输入检查用户输入二、预防越权操作任何涉及用户权限的操作均匀会话关联参数的加密及模糊化严格验证程序逻辑顺…

  • javascript如何去除对象的某个属性「建议收藏」

    js中其实是有delete这个关键字的varobj={key1:’value1′,key2:’value2′};deleteobj.key1;这样就能删除obj中的key1了。不过delete不能删除直接使用var定义的变量。比如:varvar1=’value1′;deletevar1;

  • Vue和Springboot实现SM4加密和解密(前端可加密,后端可加解密,MD5同理)

    Vue和Springboot实现SM4加密和解密(前端可加密,后端可加解密,MD5同理)Vue和Springboot实现SM4加密和解密(前端可加密,后端可加解密,MD5同理)前言一、前端加密输入的密码前置检测粘贴我的SM4.js代码在组件中调用加密结果二、Springboot后端进行SM4的解密和加密引入库复制我的SM4加解密代码调用方法总结前言网站配置https比较麻烦,所以为了我们的用户账户安全,密码在从前端传输到后端的过程中,最好加密一下,选用SM4有两个原因,一是国产加密算法,二是这个国密算法是对称的,只要加密和解密的key和vi相同,可以很容易的

  • python获取文件名后缀名_python获取文件名不含后缀名

    python获取文件名后缀名_python获取文件名不含后缀名importosfile_path=”/home/admin/Desktop/test.py”filepath,tempfilename=os.path.split(file_path)filename,extension=os.path.splitext(tempfilename)filepath文件目录filename文件名extension文件扩展名…

  • nodejs安装与环境变量配置[通俗易懂]

    nodejs安装与环境变量配置[通俗易懂]NodeJsNode.js简介发展史特性模块下载nodejs系统环境nodejs(msi)方式的安装nodejs(zip)方式的安装环境配置Linux下安装Node测试参考资料Node.js简介Node是一个让JavaScript运行在服务端的开发平台,它让JavaScript成为与PHP、Python、Perl、Ruby等服务端语言平起平坐的脚本语言。发布于2009年5月,由R…

  • jquery下载教程[通俗易懂]

    jquery下载教程[通俗易懂]jquery下载教程建议使用google浏览器下载,不建议使用IE浏览器(没有办法生成.js文件,只能复制粘贴)第一种方法第二种方法

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号