一、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
三、分层架构的代码编写
分层架构的代码也是按照【域模型层(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类
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作类的前缀,这样一眼就看出当前这个类是一个接口,这也算是一种良好的开发习惯吧,通过看类名就可以方便区分出是接口还是具体的实现类。
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类
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接口类
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类
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为用户提供注册界面
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
凡是位于WEB-INF目录下的jsp页面是无法直接通过URL地址直接访问的,
在开发中如果项目中有一些敏感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中的
手机扫一扫
移动阅读更方便
你可能感兴趣的文章