(参考http://www.cnblogs.com/xdp-gacl/p/3908610.html 点击打开链接,以此为模板 自己做了整理、修改)
SUN公司推出JSP技术后,同时也推荐了两种web应用程序的开发模式,一种是JSP+JavaBean模式,一种是Servlet+JSP+JavaBean模式。
1.1 jsp+javabean开发模式架构
jsp+javabean开发模式的架构图,如下所示:
在jsp+javabean架构中,JSP负责控制逻辑、表现逻辑、业务对象(javabean)的调用。
JSP+JavaBean模式适合开发业务逻辑不太复杂的web应用程序,这种模式下,JavaBean用于封装业务数据,JSP即负责处理用户请求,又显示数据。
1.2 使用JSP+JavaBean开发模式,编写计算器
首先分析一下jsp和javabean各自的职责,jsp负责显示计算器(calculator)页面,供用户输入计算数据,并显示计算后的结 果,javaBean负责接收用户输入的计算数据并且进行计算,JavaBean具有firstNum、secondNum、result、 operator属性,并提供一个calculate()方法。
1)编写CalculatorBean,负责接收用户输入的计算数据并且进行计算
CalculatorBean类,代码如下:
1 package me.gacl.domain;
2
3 import java.math.BigDecimal;
4
5 /**
6 * @author gacl
7 * CalculatorBean用于接收输入参数和计算
8 */
9 public class CalculatorBean {
10
11 //用户输入的第一个数
12 private double firstNum;
13 //用户输入的第二个数
14 private double secondNum;
15 //用户选择的操作运算符
16 private char operator = '+';
17 //运算结果
18 private double result;
19
20 public double getFirstNum() {
21 return firstNum;
22 }
23
24 public void setFirstNum(double firstNum) {
25 this.firstNum = firstNum;
26 }
27
28 public double getSecondNum() {
29 return secondNum;
30 }
31
32 public void setSecondNum(double secondNum) {
33 this.secondNum = secondNum;
34 }
35
36 public char getOperator() {
37 return operator;
38 }
39
40 public void setOperator(char operator) {
41 this.operator = operator;
42 }
43
44 public double getResult() {
45 return result;
46 }
47
48 public void setResult(double result) {
49 this.result = result;
50 }
51
52 /**
53 * 用于计算
54 */
55 public void calculate() {
56
57 switch (this.operator) {
58 case '+': {
59 this.result = this.firstNum + this.secondNum;
60 break;
61 }
62 case '-': {
63 this.result = this.firstNum - this.secondNum;
64 break;
65 }
66 case '*': {
67 this.result = this.firstNum * this.secondNum;
68 break;
69 }
70 case '/': {
71 if (this.secondNum == 0) {
72 throw new RuntimeException("被除数不能为0!!!");
73 }
74 this.result = this.firstNum / this.secondNum;
75 // 四舍五入
76 this.result = new BigDecimal(this.result).setScale(2,
77 BigDecimal.ROUND_HALF_UP).doubleValue();
78 break;
79 }
80 default:
81 throw new RuntimeException("对不起,传入的运算符非法!!");
82 }
83 }
84 }
2)编写calculator.jsp,负责显示计算器(calculator)页面,供用户输入计算数据,并显示计算后的结果
calculator.jsp页面代码如下:
1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
2 <%--使用me.gacl.domain.CalculatorBean --%>
3
4 <%--接收用户输入的参数 --%>
5
6 <%
7 //使用CalculatorBean进行计算
8 calcBean.calculate();
9 %>
10
11
12
13 使用【jsp+javabean开发模式】开发的简单计算器
14
15
16
17
18 计算结果是:
19
20
21
22 =
23
24
25
26
53
54
运行效果,如下所示:
在平时的JavaWeb项目开发中,在不使用第三方mvc开发框架的情况下,通常会选择Servlet+JSP+JavaBean开发模式来开发JavaWeb项目,Servlet+JSP+JavaBean组合开发就是一种MVC开发模式了,控制器(Controller)采用Servlet、模型(Model)采用JavaBean、视图(View)采用JSP。在讲解Servlet+JSP+JavaBean开发模式之前,先简单了解一下MVC开发模式。
2.1 Web开发中的请求-响应模型
在Web世界里,具体步骤如下:
1) Web浏览器(如IE)发起请求,如访问http://www.iteye.com/
2) Web服务器(如Tomcat)接收请求,处理请求(比如用户新增,则将把用户保存一下),最后产生响应(一般为html)。
3) web服务器处理完成后,返回内容给web客户端(一般就是我们的浏览器),客户端对接收的内容进行处理(如web浏览器将会对接收到的html内容进行渲染以展示给客户)。
因此,在Web世界里:都是Web客户端发起请求,Web服务器接收、处理并产生响应。
一般Web服务器是不能主动通知Web客户端更新内容。虽然现在有些技术如服务器推(如Comet)、还有现在的HTML5 websocket可以实现Web服务器主动通知Web客户端。
到此我们了解了在web开发时的请求/响应模型,接下来我们看一下标准的MVC模型是什么。
2.2 MVC
2.2.1 标准MVC模型概述
MVC模型:是一种架构型的模式,本身不引入新功能,只是帮助我们将开发的结构组织的更加合理,使展示与模型分离、流程控制逻辑、业务逻辑调用与展示逻辑分离。如下图所示:
2.2.2 MVC(Model-View-Controller)的概念
Model(模型):数据模型,提供要展示的数据,因此包含数据和行为,可以认为是领域模型(domain)或JavaBean组件(包含数据和行为),不过现在一般都分离开来:Value Object(数据) 和 服务层(行为)。也就是模型提供了模型数据查询和模型数据的状态更新等功能,包括数据和业务。
View(视图):负责进行模型的展示,一般就是我们见到的用户界面,客户想看到的东西。
Controller(控制器):接收用户请求,委托给模型进行处理(状态改变),处理完毕后把返回的模型数据返回给视图,由视图负责展示。 也就是说控制器做了个调度员的工作。
从本文2.1 中的图,我们还看到,在标准的MVC中模型能主动推数据给视图进行更新(观察者设计模式,在模型上注册视图,当模型更新时自动更新视图),但在Web开发中模型是无法主动推给视图(无法主动更新用户界面),因为在Web开发是请求-响应模型。
那接下来我们看一下在Web里MVC是什么样子,我们称其为 Web MVC 来区别标准的MVC。
2.2.3 Web MVC概述
Web MVC中的M(模型)-V(视图)-C(控制器)概念和标准MVC概念一样,我们再看一下Web MVC标准架构,如下图所示:
在Web MVC模式下,模型无法主动推数据给视图,如果用户想要视图更新,需要再发送一次请求(即请求-响应模型)。
2.3 Servlet+JSP+JavaBean开发模式介绍
Servlet+JSP+JavaBean架构其实可以认为就是我们所说的Web MVC模型,只是控制器采用Servlet、模型采用JavaBean、视图采用JSP,如下所示:
具体示例代码:
1)模型(model)
2)视图(View)
3)控制器(controller)
从Servlet+JSP+JavaBean(Web MVC)架构可以看出,视图和模型分离了,控制逻辑和展示逻辑分离了。
2.4 Servlet+JSP+JavaBean开发模式的缺陷
Servlet+JSP+JavaBean(Web MVC)架构,虽然实现了视图和模型分离、控制逻辑和展示逻辑分离,但也有一些比较严重的缺点
2.4.1 JavaBean作为模型的缺点
此处模型使用JavaBean,JavaBean组件类既负责收集封装数据,又要进行业务逻辑处理,这样可能造成JavaBean组件类很庞大,所以一般现在项目都是采用三层架构,而不直接采用JavaBean
2.4.2 视图的缺点
现在被绑定在JSP,很难更换视图,比如Velocity、FreeMarker;比如我要支持Excel、PDF视图等等。
关于JavaWeb的两种开发模式的讲解就介绍到这里,下一篇将使用servlet+jsp+javabean来开发一个用户登录注册功能,以此来加深servlet+jsp+javabean开发模式的理解。
2.4.3 Servlet作为控制器的缺点
此处的控制器使用Servlet,使用Servlet作为控制器有以下几个缺点:
1)控制逻辑可能比较复杂,其实我们可以按照规约,如请求参数submitFlag=toLogin,我们其实可以直接调用toLogin方法,来简化控制逻辑;而且每个模块基本需要一个控制器,造成控制逻辑可能很复杂。现在流行的Web MVC框架(如Struts2)都支持"请求参数submitFlag=toAdd,就可以直接调用toAdd方法"这样的处理机制,在Struts2中类似这样的处理机制就称为"动态方法调用"
2)请求参数到模型的封装比较麻烦,如果能交给框架来做这件事情,我们可以从中得到解放。
请求参数到模型的封装代码:
1 // 1收集参数
2 String username = req.getParameter("username");
3 String password = req.getParameter("password");
4 // 2封装参数
5 UserBean user = new UserBean();
6 user.setUsername(username);
7 user.setPassword(password);
当有几十个甚至上百个参数需要封装到模型中时,这样写恐怕就痛苦万分了,要写几十次甚至上百次这样的代码,估计写到吐了,所以现在流行的Web MVC框架(如Struts2)都提供了非常方便的获取参数,封装参数到模型的机制,减少这些繁琐的工作。
3)选择下一个视图,严重依赖Servlet API,这样很难或基本不可能更换视图。
例如:使用Servlet API提供的request对象的getRequestDispatcher方法选择要展示给用户看的视图
1 private void toLogin(HttpServletRequest req, HttpServletResponse resp)
2 throws ServletException, IOException {
3 //使用Servlet API提供的request对象的getRequestDispatcher方法选择视图
4 // 此处和JSP视图技术紧密耦合,更换其他视图技术几乎不可能
5 request.getRequestDispatcher("/mvc/login.jsp").forward(request, response);
6 }
4)给视图传输要展示的模型数据,也需要使用Servlet API,更换视图技术也要一起更换,很麻烦。
例如:使用Servlet API提供的request对象给视图传输要展示的模型数据
//使用Servlet API提供的request对象给视图login.jsp传输要展示的模型数据(user)
request.setAttribute("user", user);
request.getRequestDispatcher("/mvc/login.jsp").forward(request, response)
Servlet+JSP+JavaBean模式(MVC)适合开发复杂的web应用,在这种模式下,servlet负责处理用户请求,jsp负责数据显示,javabean负责封装数据。 Servlet+JSP+JavaBean模式程序各个模块之间层次清晰,web开发推荐采用此种模式。
这里以一个最常用的用户登录注册程序来讲解Servlet+JSP+JavaBean开发模式,通过这个用户登录注册程序综合案例,把之前的学过的XML、Xpath、Servlet、jsp的知识点都串联起来。
3.1 创建MVC架构的Web项目
在MyEclipse中新创建一个webmvcframework项目,导入项目所需要的开发包(jar包),创建项目所需要的包,在Java开发中,架构的层次是以包的形式体现出来的。
一个良好的JavaWeb项目架构应该具有以上的11个包,这样显得层次分明,各个层之间的职责也很清晰明了,搭建JavaWeb项目架构时,就按照上面的1~11的序号顺序创建包:
domain→dao→dao.impl→service→service.impl→web.controller→web.UI→web.filter→web.listener→util→junit.test,包的层次创建好了,项目的架构也就定下来了,当然,在实际的项目开发中,也不一定是完完全全按照上面说的来创建包的层次结构,而是根据项目的实际情况,可能还需要创建其他的包,这个得根据项目的需要来定了
在src目录(类目录)下面,创建用于保存用户数据的xml文件(DB.xml)
在WEB-INF目录下创建一个pages目录,pages目录存放系统的一些受保护(不允许用户直接通过URL地址访问)的jsp页面,用户要想访问这些受保护的jsp页面,那么只能通过me.gacl.web.UI 这个包里面的Servlet
创建好的项目如下图(图-1)所示:
3.2 分层架构的代码编写
分层架构的代码也是按照【域模型层(domain)】→【数据访问层(dao、dao.impl)】→【业务处理层(service、service.impl)】→【表现层(web.controller、web.UI、web.filter、web.listener)】→【工具类(util)】→【测试类(junit.test)】的顺序进行编写的。
3.2.1 开发domain层
在me.gacl.domain包下创建一个User类
User类,具体代码如下:
1 package me.gacl.domain;
2
3 import java.io.Serializable;
4 import java.util.Date;
5 /**
6 * @author gacl
7 * 用户实体类
8 */
9 public class User implements Serializable {
10
11 private static final long serialVersionUID = -4313782718477229465L;
12
13 // 用户ID
14 private String id;
15 // 用户名
16 private String userName;
17 // 用户密码
18 private String userPwd;
19 // 用户邮箱
20 private String email;
21 // 用户生日
22 private Date birthday;
23
24 public String getId() {
25 return id;
26 }
27
28 public void setId(String id) {
29 this.id = id;
30 }
31
32 public String getUserName() {
33 return userName;
34 }
35
36 public void setUserName(String userName) {
37 this.userName = userName;
38 }
39
40 public String getUserPwd() {
41 return userPwd;
42 }
43
44 public void setUserPwd(String userPwd) {
45 this.userPwd = userPwd;
46 }
47
48 public String getEmail() {
49 return email;
50 }
51
52 public void setEmail(String email) {
53 this.email = email;
54 }
55
56 public Date getBirthday() {
57 return birthday;
58 }
59
60 public void setBirthday(Date birthday) {
61 this.birthday = birthday;
62 }
63 }
3.2.2 开发数据访问层(dao、dao.impl)
在me.gacl.dao包下创建一个IUserDao接口类,对于开发接口类,我习惯以字母I作类的前缀,这样一眼就看出当前这个类是一个接口,这也算是一种良好的开发习惯吧,通过看类名就可以方便区分出是接口还是具体的实现类。
IUserDao接口的具体代码如下:
1 package me.gacl.dao;
2
3 import me.gacl.domain.User;
4
5 public interface IUserDao {
6
7 /**
8 * 根据用户名和密码来查找用户
9 * @param userName
10 * @param userPwd
11 * @return 查到到的用户
12 */
13 User find(String userName, String userPwd);
14
15 /**
16 * 添加用户
17 * @param user
18 */
19 void add(User user);
20
21 /**根据用户名来查找用户
22 * @param userName
23 * @return 查到到的用户
24 */
25 User find(String userName);
26 }
对于接口中的方法定义,这个只能是根据具体的业务来分析需要定义哪些方法了,但是无论是多么复杂的业务,都离不开基本的CRUD(增删改查)操作,Dao层是直接和数据库交互的,所以Dao层的接口一般都会有增删改查这四种操作的相关方法。
在me.gacl.dao.impl包下创建一个UserDaoImpl类
UserDaoImpl类是IUserDao接口的具体实现类,对于接口的实现类命名方式,我习惯以"接口名(去除前缀I)+impl"形式或者"接口名+impl"形式来命名:IUserDao(接口)→UserDaoImpl(实现类)或者IUserDao(接口)→IUserDaoImpl(实现类),这也算是一些个人的编程习惯吧,平时看到的代码大多数都是以这两种形式中的一种来来命名接口的具体实现类的,反正就是要能够一眼看出接口对应的实现类是哪一个就可以了。
UserDaoImpl类的具体代码如下:
1 package me.gacl.dao.impl;
2
3 import java.text.SimpleDateFormat;
4 import org.dom4j.Document;
5 import org.dom4j.Element;
6 import me.gacl.dao.IUserDao;
7 import me.gacl.domain.User;
8 import me.gacl.util.XmlUtils;
9
10 /**
11 * IUserDao接口的实现类
12 * @author gacl
13 */
14 public class UserDaoImpl implements IUserDao {
15
16 @Override
17 public User find(String userName, String userPwd) {
18 try{
19 Document document = XmlUtils.getDocument();
20 //使用XPath表达式来操作XML节点
21 Element e = (Element) document.selectSingleNode("//user[@userName='"+userName+"' and @userPwd='"+userPwd+"']");
22 if(e==null){
23 return null;
24 }
25 User user = new User();
26 user.setId(e.attributeValue("id"));
27 user.setEmail(e.attributeValue("email"));
28 user.setUserPwd(e.attributeValue("userPwd"));
29 user.setUserName(e.attributeValue("userName"));
30 String birth = e.attributeValue("birthday");
31 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
32 user.setBirthday(sdf.parse(birth));
33
34 return user;
35
36 }catch (Exception e) {
37 throw new RuntimeException(e);
38 }
39 }
40
41 @SuppressWarnings("deprecation")
42 @Override
43 public void add(User user) {
44 try{
45 Document document = XmlUtils.getDocument();
46 Element root = document.getRootElement();
47 Element user_node = root.addElement("user"); //创建user结点,并挂到root
48 user_node.setAttributeValue("id", user.getId());
49 user_node.setAttributeValue("userName", user.getUserName());
50 user_node.setAttributeValue("userPwd", user.getUserPwd());
51 user_node.setAttributeValue("email", user.getEmail());
52
53 SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
54 user_node.setAttributeValue("birthday", sdf.format(user.getBirthday()));
55
56 XmlUtils.write2Xml(document);
57
58 }catch (Exception e) {
59 throw new RuntimeException(e);
60 }
61 }
62
63 @Override
64 public User find(String userName) {
65 try{
66 Document document = XmlUtils.getDocument();
67 Element e = (Element) document.selectSingleNode("//user[@userName='"+userName+"']");
68 if(e==null){
69 return null;
70 }
71 User user = new User();
72 user.setId(e.attributeValue("id"));
73 user.setEmail(e.attributeValue("email"));
74 user.setUserPwd(e.attributeValue("userPwd"));
75 user.setUserName(e.attributeValue("userName"));
76 String birth = e.attributeValue("birthday");
77 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
78 user.setBirthday(sdf.parse(birth));
79
80 return user;
81
82 }catch (Exception e) {
83 throw new RuntimeException(e);
84 }
85 }
86
87 }
3.2.3 开发service层(service层对web层提供所有的业务服务)
在me.gacl.service包中创建IUserService接口类
IUserService接口的具体代码如下:
1 package me.gacl.service;
2
3 import me.gacl.domain.User;
4 import me.gacl.exception.UserExistException;
5
6 public interface IUserService {
7
8 /**
9 * 提供注册服务
10 * @param user
11 * @throws UserExistException
12 */
13 void registerUser(User user) throws UserExistException;
14
15 /**
16 * 提供登录服务
17 * @param userName
18 * @param userPwd
19 * @return
20 */
21 User loginUser(String userName, String userPwd);
22 }
在me.gacl.service.impl包中创建UserServiceImpl类
UserServiceImpl类为IUserService接口的具体实现类,具体代码如下:
1 package me.gacl.service.impl;
2
3 import me.gacl.dao.IUserDao;
4 import me.gacl.dao.impl.UserDaoImpl;
5 import me.gacl.domain.User;
6 import me.gacl.exception.UserExistException;
7 import me.gacl.service.IUserService;
8
9 public class UserServiceImpl implements IUserService {
10
11 private IUserDao userDao = new UserDaoImpl();
12
13 @Override
14 public void registerUser(User user) throws UserExistException {
15 if (userDao.find(user.getUserName())!=null) {
16 //checked exception
17 //unchecked exception
18 //这里抛编译时异常的原因:是我想上一层程序处理这个异常,以给用户一个友好提示
19 throw new UserExistException("注册的用户名已存在!!!");
20 }
21 userDao.add(user);
22 }
23
24 @Override
25 public User loginUser(String userName, String userPwd) {
26 return userDao.find(userName, userPwd);
27 }
28
29 }
3.2.4 开发web层
第一步,开发注册功能
1)在me.gacl.web.UI包下写一个RegisterUIServlet为用户提供注册界面
RegisterUIServlet收到用户请求后,就跳到register.jsp
RegisterUIServlet的代码如下:
1 package me.gacl.web.UI;
2
3 import java.io.IOException;
4 import javax.servlet.ServletException;
5 import javax.servlet.http.HttpServlet;
6 import javax.servlet.http.HttpServletRequest;
7 import javax.servlet.http.HttpServletResponse;
8 /**
9 * @author gacl
10 * 为用户提供注册的用户界面的Servlet
11 * RegisterUIServlet负责为用户输出注册界面
12 * 当用户访问RegisterUIServlet时,就跳转到WEB-INF/pages目录下的register.jsp页面
13 */
14 public class RegisterUIServlet extends HttpServlet {
15
16 public void doGet(HttpServletRequest request, HttpServletResponse response)
17 throws ServletException, IOException {
18 request.getRequestDispatcher("/WEB-INF/pages/register.jsp").forward(request, response);
19 }
20
21 public void doPost(HttpServletRequest request, HttpServletResponse response)
22 throws ServletException, IOException {
23 doGet(request, response);
24 }
25
26 }
2)在/WEB-INF/pages/目录下编写用户注册的jsp页面register.jsp
凡是位于WEB-INF目录下的jsp页面是无法直接通过URL地址直接访问的,
在开发中如果项目中有一些敏感web资源不想被外界直接访问,那么可以考虑将这些敏感的web资源放到WEB-INF目录下,这样就可以禁止外界直接通过URL来访问了。
register.jsp页面的代码如下:
1 <%@ page language="java" pageEncoding="UTF-8"%>
2
3
4
5 用户注册
6
7
8
9
52
53
register.jsp中的
3)在me.gacl.web.controller包下编写用于处理用户登录的LoginServlet
LoginServlet的代码如下:
1 package me.gacl.web.controller;
2
3 import java.io.IOException;
4
5 import javax.servlet.ServletException;
6 import javax.servlet.http.HttpServlet;
7 import javax.servlet.http.HttpServletRequest;
8 import javax.servlet.http.HttpServletResponse;
9
10 import me.gacl.domain.User;
11 import me.gacl.service.IUserService;
12 import me.gacl.service.impl.UserServiceImpl;
13
14 /**
15 * 处理用户登录的servlet
16 * @author gacl
17 *
18 */
19 public class LoginServlet extends HttpServlet {
20
21 public void doGet(HttpServletRequest request, HttpServletResponse response)
22 throws ServletException, IOException {
23
24 //获取用户填写的登录用户名
25 String username = request.getParameter("username");
26 //获取用户填写的登录密码
27 String password = request.getParameter("password");
28
29 IUserService service = new UserServiceImpl();
30 //用户登录
31 User user = service.loginUser(username, password);
32 if(user==null){
33 String message = String.format(
34 "对不起,用户名或密码有误!!请重新登录!2秒后为您自动跳到登录页面!!
到此,用户登录的功能就算是开发完成了。
下面测试一下开发好的用户登录功能,输入URL地址:http://localhost:8080/webmvcframework/servlet/LoginUIServlet访问login.jsp页面,输入正确的用户名和密码进行登录,运行效果如下:
如果输入的用户名和密码错误,那么就无法登录成功,运行效果如下:
第三步,开发注销功能
在me.gacl.web.controller包下编写用于处理用户注销的LogoutServlet
LogoutServlet的代码如下:
1 package me.gacl.web.controller;
2
3 import java.io.IOException;
4 import java.text.MessageFormat;
5
6 import javax.servlet.ServletException;
7 import javax.servlet.http.HttpServlet;
8 import javax.servlet.http.HttpServletRequest;
9 import javax.servlet.http.HttpServletResponse;
10
11 public class LogoutServlet extends HttpServlet {
12
13 public void doGet(HttpServletRequest request, HttpServletResponse response)
14 throws ServletException, IOException {
15 //移除存储在session中的user对象,实现注销功能
16 request.getSession().removeAttribute("user");
17 //由于字符串中包含有单引号,在这种情况下使用MessageFormat.format方法拼接字符串时就会有问题
18 //MessageFormat.format方法只是把字符串中的单引号去掉,不会将内容填充到指定的占位符中
19 String tempStr1 = MessageFormat.format(
20 "注销成功!!3秒后为您自动跳到登录页面!!",
21 request.getContextPath()+"/servlet/LoginUIServlet");
22 System.out.println(tempStr1);//输出结果:注销成功!!3秒后为您自动跳到登录页面!!
23 System.out.println("---------------------------------------------------------");
24 /**
25 * 要想解决"如果要拼接的字符串包含有单引号,那么MessageFormat.format方法就只是把字符串中的单引号去掉,不会将内容填充到指定的占位符中"这个问题,
26 * 那么可以需要使用单引号引起来的字符串中使用2个单引号引起来,例如:""
27 * 这样MessageFormat.format("","index.jsp")就可以正常返回
28 *
29 */
30 String tempStr2 = MessageFormat.format(
31 "注销成功!!3秒后为您自动跳到登录页面!!",
32 request.getContextPath()+"/servlet/LoginUIServlet");
33 /**
34 * 输出结果:
35 * 注销成功!!3秒后为您自动跳到登录页面!!
36 *
37 */
38 System.out.println(tempStr2);
39
40 String message = String.format(
41 "注销成功!!3秒后为您自动跳到登录页面!!",
42 request.getContextPath()+"/servlet/LoginUIServlet");
43 request.setAttribute("message",message);
44 request.getRequestDispatcher("/message.jsp").forward(request, response);
45 }
46
47 public void doPost(HttpServletRequest request, HttpServletResponse response)
48 throws ServletException, IOException {
49 doGet(request, response);
50 }
51
52 }
用户登录成功后,会将登录的用户信息存储在session中,所以我们要将存储在session中的user删除掉,这样就可以实现用户注销了。
用户登录成功后就会跳转到index.jsp页面,在index.jsp页面中放一个【退出登陆】按钮,当点击【退出登陆】按钮时,就访问LogoutServlet,将用户注销。
index.jsp的代码如下:
1 <%@ page language="java" pageEncoding="UTF-8"%>
2 <%--为了避免在jsp页面中出现java代码,这里引入jstl标签库,利用jstl标签库提供的标签来做一些逻辑判断处理 --%>
3 <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
4
5
6
7 首页
8
14
15
16
17 孤傲苍狼的网站
18
19
20 注册
21 登陆
22
23
24 欢迎您:${user.userName}
25
26
27
28
29
测试开发好的注销功能,效果如下:
到此,所有的功能都开发完成了,测试也通过了。
3.3 开发总结
通过这个小例子,可以了解到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层
----------------------------------------------- 我是低调的分隔线 -----------------------------------------------