构建一个简单的基于MVC模式的JavaWeb

零晨三点半了,刚刚几个兄弟一起出去吼歌,才回来,这应该是我大学第二次去K歌,第一次是大一吧,之后每次兄弟喊我,我都不想去,因为我还是很害怕去KTV,或许是因为那里是我伤心的地方,也或许是因为我在那里失败过,所以内心一直都有点抵触,昨天是一室友的生日,也快过年,也是想和他们一起好好的玩一回,就放下一切去了,很久都没去吼歌了,嗓子现在都感觉哑哑的,今天一天仿佛没有干什么,有些不安,于是回来后把以前学习MVC时笔记写下来!
MVC设计模式是目前使用得比较多的一种设计模式,最早出现在Smalltalk中,后来广泛应用于Java Web 应用程序中。Model(模型)表示业务逻辑层,View(视图)代表表示层,Contraller(控制器)代表控制层!
在Java Web应用程序中,View部份一般用JSP和HTML构建。客户在View部份提交请求,在业务逻辑层处理后,把处理结果又返回给View部份显示出来。因此,View部份也是WEB应用程序的用户界面!
Controller部份一般由Servlet组成。当用户请求从View部分传过来时,Controller把该请求发给适当的业务逻辑组件处理,请求处理完成后,又返回给Controller.后者再把处理结果转发给适当的View组件显示。因此,Controller在视图层与业务逻辑层之间起到了桥梁作用,控制了它们两者之间的数据流向!
Model部分 包括业务逻辑层和数据库访问层。在JAVA WEB 应用程序中,业务逻辑层一般由JAVABEAN或EJB构建。EJB是J2EE的核心组件,可以构建分布式应用系统。与普通的JAVABEAN不同,它由二个接口和一个实现类组成,并且包含一些固有的用于控制容器生命周期的方法!
数据访问层也叫数据持久层,它主要负责与库打交道,用于从数据库中存取数据。在JAVA WEB应用中,我们常用JDBC API或Hibernate来构建数据持久层。例如,把与数据连接的代码以从数据库中存取数据的代码封装在不同的对象中,这样便于系统中其他业务逻辑组件调用它们。
这样,一个JAVA WEB应用程序划分为表示层,控制层,业务逻辑层和数据持久层,形成了一个多层系统。对于大型,复杂的WEB应用程序,这样的是十分必要的!
下面来构建一个简单的基于MVC模式的JAVA  WEB应用程序,我们按照MVC设计模式,用JSP,Servlet及Java Bean构建一个简单的登录系统。该系统要求当用户在登录页面上输入用户名和密码并提交后,系统将检查该用户中否已经注册,如果该用户已经注册,系统进入主页面,否则进入注册页面!
我们将 按以下步骤构建这个系统:
Step1:数据库的设计,使用MySQL作为数据库,构建数据表T_UserInfo;
Step2:构建视图组件:登录页面login.jsp,主页面main.jsp,以及注册页面register.jsp;
Step3:构建控制层组件,一个Servlet,;取名为LoginServlet.java;
Step4:构建业务逻辑层组件(Model组件),一个JavaBean,取名为LoginHandler.java;
Step5:构建数据访问层组件:珍上数据访问类,取名dbPool.java;
Step6:编译,打包程序;
Step7:部署该程序到Web服务器Tomcat中,然后运行!
该系统的工作流程图如下:

详细设计:
A:用户登录涉及数据库操作的用例!我们在MySQL中 建立一个T_UserInfo表,DDL语句如下:
None.gif create   table  T_UserInfo
None.gif(
None.gif    ID 
bigint   primary   key  auto_increment,
None.gif    userName 
varchar ( 20 ),
None.gif    userPwd 
varchar ( 20 )
None.gif)
None.gif
-- 并添加一条测试数据用户名及密码均为fengyan
None.gif
insert   into  T_UserInfo(userName,userPwd)  values ( ' fengyan ' , ' fengyan ' )
B:构建视图组件,由前面的分析可知本例有三个视图组件,分别是登录页面login.jsp,主页面main.jsp,以及注册页面register.jsp.它们之间的关系是当用户在登录页面login.jsp上填入用户名及密码并提交后,系统将 检测该用户是琐已经注册,如果已经注册则进入main.jsp,否则进入注册页面!
login.jsp代码如下:
ExpandedBlockStart.gif ContractedBlock.gif <% dot.gif @ page language="java" pageEncoding="GBK" %>
None.gif
<! DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" >
None.gif
< html:html  lang ="true" >
None.gif  
< head >
None.gif    
< html:base  />     
None.gif    
< title > login.jsp </ title >
None.gif  
</ head >   
None.gif  
< body >
None.gif  
< form  action ="servlet/LoginServlet"  method ="post"   >      
None.gif      
< table  border ="0" >
None.gif        
< tr >
None.gif          
< td > Login: </ td >
None.gif          
< td >< input  type ="text"  name ="userName"   /></ td >
None.gif        
</ tr >
None.gif        
< tr >
None.gif          
< td > Password: </ td >
None.gif          
< td >< input  type ="password"  name ="userPwd"   /></ td >
None.gif        
</ tr >
None.gif        
< tr >
None.gif          
< td  colspan ="2"  align ="center" >< input  type ="submit"  value ="login" ></ td >
None.gif        
</ tr >
None.gif      
</ table >
None.gif
</ form >
None.gif  
</ body >
None.gif
</ html:html >
None.gif

当用户按下登录后就提交给叫做LoginServlet的Servlet,以做进一步处理!

为方便起见,主页面main.jsp的内容设计的很简单。当用户登录成功后,系统转入main.jsp告诉用户已经登录成功,现已进入主页面。main.jsp代码如下:

ExpandedBlockStart.gif ContractedBlock.gif <% dot.gif @ page language="java" contentType="text/html; charset=GBK"
ExpandedBlockEnd.gif    pageEncoding
="GBK"
%>
None.gif
<! DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd" >
None.gif
< html >
None.gif
< head >
None.gif
< meta  http-equiv ="Content-Type"  content ="text/html; charset=GBK" >
None.gif
< title > Insert title here </ title >
None.gif
</ head >
None.gif
< body >
None.gif
<% = session.getAttribute( " userName " %> ,你成功登录,现已进入主页面!
None.gif
</ body >
None.gif
</ html >
注册页面,register.jsp的内容也设计的很简单。当用户登录失败后,系统进入register.jsp,告诉用户登录失败,代码如下:
ExpandedBlockStart.gif ContractedBlock.gif <% dot.gif @ page language="java" contentType="text/html; charset=GBK"
ExpandedBlockEnd.gif    pageEncoding
="GBK" %>
None.gif
<! DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd" >
None.gif
< html >
None.gif
< head >
None.gif
< meta  http-equiv ="Content-Type"  content ="text/html; charset=GBK" >
None.gif
< title > Insert title here </ title >
None.gif
</ head >
None.gif
< body >
None.gif
<% = session.getAttribute( " userName " %> ,你未能成功登录,现进入注册页面,请注册你的信息!
None.gif
</ body >
None.gif
</ html >

C:构建数据访问组件,先创建一个属性文件db.properties用于设置库连接信息代码如下:
None.gif DBDriver=com.mysql.jdbc.Driver
None.gifConnection=jdbc:mysql://localhost:3306/study
None.gifUser=root
None.gifPassword=root
本用例的数据访问组件是DbPool,代码如下:
None.gif package  data;
ExpandedBlockStart.gifContractedBlock.gif
/** */ /**
InBlock.gif * 数据访问组件
InBlock.gif * 
@author fengyan
InBlock.gif * @date 2007-01-06 03:25
ExpandedBlockEnd.gif 
*/

None.gif 
*/
None.gif
import  java.io.InputStream;
None.gif
import  java.sql.Connection;
None.gif
import  java.sql.DriverManager;
None.gif
import  java.sql.PreparedStatement;
None.gif
import  java.sql.ResultSet;
None.gif
import  java.util.Properties;
None.gif
ExpandedBlockStart.gifContractedBlock.gif
public   class  DbPool  dot.gif {
InBlock.gif
InBlock.gif    
private static DbPool instance = null;
InBlock.gif    
private DbPool()
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
super();
ExpandedSubBlockEnd.gif    }

InBlock.gif    
//取得连接
InBlock.gif
    public static synchronized Connection getConnection()
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
if(instance == null)
InBlock.gif            instance 
= new DbPool();
InBlock.gif        
return instance._getConnection();
ExpandedSubBlockEnd.gif    }

InBlock.gif    
private Connection _getConnection()
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
try
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            String dBDriver 
= null;
InBlock.gif            String connectionUrl 
= null;
InBlock.gif            String user 
= null;
InBlock.gif            String password 
= null;
InBlock.gif            
InBlock.gif            Properties p 
= new Properties();
InBlock.gif            InputStream inStream 
= getClass().getResourceAsStream("db.properties");
InBlock.gif            p.load(inStream);
InBlock.gif            
InBlock.gif            dBDriver 
=p.getProperty("DBDriver",dBDriver);
InBlock.gif            connectionUrl 
= p.getProperty("Connection",connectionUrl);
InBlock.gif            user 
= p.getProperty("User","");//默认值为空
InBlock.gif
            password = p.getProperty("Password","");
InBlock.gif            
InBlock.gif            
//加载驱动
InBlock.gif
            Class.forName(dBDriver).newInstance();
InBlock.gif            
return DriverManager.getConnection(connectionUrl+"?user="+user+"&password="+password);
InBlock.gif            
ExpandedSubBlockEnd.gif        }
catch(Exception e)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            System.out.println(e);
InBlock.gif            
return null;
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif    }

InBlock.gif    
InBlock.gif    
//释放资源
InBlock.gif
    public static void DBClose(Connection con ,PreparedStatement ps,ResultSet rs)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
try
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
if(rs !=  null)
InBlock.gif                rs.close();
InBlock.gif            
if(ps != null)
InBlock.gif                ps.close();
InBlock.gif            
if(con != null)
InBlock.gif                con.close();
ExpandedSubBlockEnd.gif        }
catch(Exception e)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            System.out.println(e);
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

None.gif
DbPool先从一个属性文件db.properties中获取数据库驱动程序名,URL,用户名和密码,然后利用这些信息连接数据库,取得连接!

D:构建模型组件,本用例的模型组件(或称为业务逻辑组件)是LoginHandler,代码如下:
None.gif package  model;
ExpandedBlockStart.gifContractedBlock.gif
/** */ /**
InBlock.gif * 模型组件
InBlock.gif * 
@author fengyan
InBlock.gif * date 2007-01-06 03:27
ExpandedBlockEnd.gif 
*/

None.gif
import  java.sql.Connection;
None.gif
import  java.sql.PreparedStatement;
None.gif
import  java.sql.ResultSet;
None.gif
import  java.util.ArrayList;
None.gif
None.gif
import  data.DbPool;
None.gif
ExpandedBlockStart.gifContractedBlock.gif
public   class  LoginHandler  dot.gif {
InBlock.gif
InBlock.gif    Connection con;
InBlock.gif    PreparedStatement ps;
InBlock.gif    ResultSet rs;
InBlock.gif    
InBlock.gif    
//检查是否已经注册
InBlock.gif
    public boolean checkLogin(ArrayList arr)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
//从数据访问组件中取得连接
InBlock.gif
        con = DbPool.getConnection();
InBlock.gif        
//得到Controller传入的用户输入的用户名及密码
InBlock.gif
        String userName = (String)arr.get(0);
InBlock.gif        String userPwd 
= (String)arr.get(1);
InBlock.gif        
InBlock.gif        String strSql 
= "select * from T_UserInfo where userName=? and userPwd=?";
InBlock.gif        
try
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            ps 
= con.prepareStatement(strSql);
InBlock.gif            ps.setString(
1,userName);
InBlock.gif            ps.setString(
2, userPwd);
InBlock.gif            rs 
= ps.executeQuery();
InBlock.gif            
if(rs.next())
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{    
InBlock.gif                
//释放资源
InBlock.gif
                DbPool.DBClose(con, ps, rs);            
InBlock.gif                
return true;
ExpandedSubBlockEnd.gif            }

InBlock.gif            
else
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
//释放资源
InBlock.gif
                DbPool.DBClose(con, ps, rs);
InBlock.gif                
return false;
ExpandedSubBlockEnd.gif            }
            
ExpandedSubBlockEnd.gif        }
catch(Exception e)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            System.out.println(e);
InBlock.gif            
return false;
ExpandedSubBlockEnd.gif        }

InBlock.gif        
ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

None.gif

E:本用例的控制组件是一个Servlet,叫做LoginServlet,代码如下
None.gif package  controller;
ExpandedBlockStart.gifContractedBlock.gif
/** */ /**
InBlock.gif * 控制器
InBlock.gif * 
@author fengyan
InBlock.gif * date 2007-01-06 03:29
ExpandedBlockEnd.gif 
*/

None.gif
import  java.io.IOException;
None.gif
import  java.io.PrintWriter;
None.gif
import  java.util.ArrayList;
None.gif
None.gif
import  javax.servlet.ServletException;
None.gif
import  javax.servlet.http.HttpServlet;
None.gif
import  javax.servlet.http.HttpServletRequest;
None.gif
import  javax.servlet.http.HttpServletResponse;
None.gif
import  javax.servlet.http.HttpSession;
None.gif
None.gif
import  model.LoginHandler;
None.gif
ExpandedBlockStart.gifContractedBlock.gif
public   class  LoginServlet  extends  HttpServlet  dot.gif {
InBlock.gif
InBlock.gif    
private static final String CONTENT_TYPE = "text/html;charset=GBK";
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
public LoginServlet() dot.gif{
InBlock.gif        
super();
ExpandedSubBlockEnd.gif    }

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
public void destroy() dot.gif{
InBlock.gif        
super.destroy(); // Just puts "destroy" string in log
InBlock.gif        
// Put your code here
ExpandedSubBlockEnd.gif
    }

InBlock.gif
InBlock.gif    
public void doGet(HttpServletRequest request, HttpServletResponse response)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
throws ServletException, IOException dot.gif{
InBlock.gif
InBlock.gif        doPost(request,response);
ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif    
InBlock.gif    
public void doPost(HttpServletRequest request, HttpServletResponse response)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
throws ServletException, IOException dot.gif{
InBlock.gif
InBlock.gif        
//从请求中取出用户名和密码
InBlock.gif
        String userName = request.getParameter("userName");
InBlock.gif        String userPwd 
= request.getParameter("userPwd");
InBlock.gif        
//生成一个ArrayList对象,并把用户名和密码的值存入该对象中
InBlock.gif
        ArrayList arr = new ArrayList();
InBlock.gif        arr.add(userName);
InBlock.gif        arr.add(userPwd);
InBlock.gif        
InBlock.gif        
//生成一个Session对象
InBlock.gif
        HttpSession session = request.getSession(true);
InBlock.gif        session.removeAttribute(
"userName");
InBlock.gif        session.setAttribute(
"userName", userName);
InBlock.gif        
InBlock.gif        
//调用模型组件
InBlock.gif
        LoginHandler login = new LoginHandler();
InBlock.gif        
boolean flag = login.checkLogin(arr);
InBlock.gif        
InBlock.gif        
//如果已注册
InBlock.gif
        if(flag)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            response.sendRedirect(
"/MVC/main.jsp");
ExpandedSubBlockEnd.gif        }

InBlock.gif        
else
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            response.sendRedirect(
"/MVC/register.jsp");
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif    }

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
public void init() throws ServletException dot.gif{
InBlock.gif        
// Put your code here
ExpandedSubBlockEnd.gif
    }

InBlock.gif
ExpandedBlockEnd.gif}

None.gif

该组件先处理Http POST请求,然后调用模型组件或业务逻辑组件LoginHandler检查该用户是否已注册如注册,则转入main.jsp,否则转入register.jsp,另外,Servlet都要在web.xml中声明,
None.gif <? xml version="1.0" encoding="UTF-8" ?>
None.gif
< web-app  version ="2.4"  
None.gif    xmlns
="http://java.sun.com/xml/ns/j2ee"  
None.gif    xmlns:xsi
="http://www.w3.org/2001/XMLSchema-instance"  
None.gif    xsi:schemaLocation
="http://java.sun.com/xml/ns/j2ee 
None.gif    http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
>
None.gif 
< welcome-file-list >
None.gif     
< welcome-file > /login.jsp </ welcome-file >
None.gif 
</ welcome-file-list >
None.gif  
< servlet >
None.gif    
< description > This is the description of my J2EE component </ description >
None.gif    
< display-name > This is the display name of my J2EE component </ display-name >
None.gif    
< servlet-name > LoginServlet </ servlet-name >
None.gif    
< servlet-class > controller.LoginServlet </ servlet-class >
None.gif  
</ servlet >
None.gif
None.gif  
< servlet-mapping >
None.gif    
< servlet-name > LoginServlet </ servlet-name >
None.gif    
< url-pattern > /servlet/LoginServlet </ url-pattern >
None.gif  
</ servlet-mapping >
None.gif
</ web-app >
None.gif

到此,整个系统完成设计!运行结果达到我们预期的的效果!

总结:上面结合使用JSP,Servlet和JavaBean构建了一个简单的基于MVC模式的登录系统。但我们看到在用这种方式构建的Java Web 应用系统中,控制器LonginController中包含重定向页面的名称,如下:

None.gif if (flag)
ExpandedBlockStart.gifContractedBlock.gif        
dot.gif {
InBlock.gif            response.sendRedirect(
"/MVC/main.jsp");
ExpandedBlockEnd.gif        }

None.gif        
else
ExpandedBlockStart.gifContractedBlock.gif        
dot.gif {
InBlock.gif            response.sendRedirect(
"/MVC/register.jsp");
ExpandedBlockEnd.gif        }

这样会使系统的视图组件与控制层组件耦合很紧密,不便于系统的扩展和维护。对于大型Java Web系统,这样的紧密耦合性会合系统的扩展和维护变的十分困难。为了解决这些问题,一些优秀的MVC框架出现了,而Struts就是其中应用最普遍的一个。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值