关于Servlet的model1模式与MV模式简单示例

来源:互联网 发布:淘宝开店交保证金 编辑:程序博客网 时间:2024/06/05 11:02

以登录为例吧。。。。。

三个页面:login.java和welcome.java和loginDL.java

当然,在配置文件中把这三个servlet先写好。。。其中,login.java中是用于显示出登录的界面,action=loginDL  

然后,在loginDL中对用户名和密码进行验证,如果正确,则跳转到welcome.....在welcome中,对数据库数据进行分页显示


对于分页,最快的方法是select * from tableName where id between ? and ?

但是,如果在结果集中有记录被删除时,那么就会有的显示页不能显示出我们想要的条目数

因此我们的解决方法是:

select top pageSize 字段名列表  from 表名  where id not in
(select top pageSize*(pageNow-1) id from 表名 )


当然,这个方法只对mysql数据库有效,对于Oracle,想都不用想,就是三层的select的语句了。。。。

“select a2.*,rownum rn from (select a1.*,rownum rn from (select * from shunping2) a1 where rownum<=" + end + ") a2 where rn>=" + start;

pw.print("<a href=login/welcome.jsp?pageNow=" + (pageNow-1) +">" + "(上一页)" + "</a>");



把界面和业务逻辑放在一起(Model1模式),[只有login,loginDL,welcome页面],有许多不合理的地方
如:
1.在loginCL.java和welcome.java中都操作了数据库,逻辑相似,有重复代码
2.整个框架没有清晰的层次,显得很乱
3.可读性差,维护性差


进行改进 :
1.进行分层,mv模式  model+view
2.将常用代码进行封装到类中


首先,从数据库中得到连接(封装类):
ConnDB.java中:
package com.steptwo.hsp;
import java.sql.*;


public class ConnDB {
private Connection conn = null;
public Connection getConn(){
try{
Class.forName("oracle.jdbc.driver.OracleDriver");
conn = DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521:ORCL","seven","angus");
}catch(Exception e){
e.printStackTrace();
}
return conn;
}
}

建立Model层,它对应数据库中的一条记录:
UserBean.java
package com.steptwo.hsp;
public class UserBean {
private int userId;
private String userName;
private String mail;
private int age;
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getMail() {
return mail;
}
public void setMail(String mail) {
this.mail = mail;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}

然后建一个处理类(处理表)------即操作UserBean类

在UserBeanDL中我们返回ArrayList集合,而不是返回ResultSet


原因:
1. 如果返回ResultSet,那么我们在使用Result时,是不能关闭与该ResultSet相互关联的数据库连接等资源,从而造成资源浪费。
2. 如果返回ResultSet,我们只能使用rs.getInt(?),rs.getString(?),这样的方法来得到结果,代码可读性不好,维护不方便。
因此,我们返回ArrayList集合,先把rs中的每条记录转化为一个UserBean对象ub,再把ub对象放入到ArrayList集合中。
当需要时,我们再从ArrayList中循环拿出数据,转化为UserBean对象,以供使用


UserBeanDL.java
package com.steptwo.hsp;
import java.sql.*;
import java.util.ArrayList;

public class UserBeanDL {
private Connection conn = null;
private PreparedStatement ps = null;
private ResultSet rs = null;
/////得到用于分页显示的数据
public ArrayList getResultByPage(int pageNow,int pageSzie) {
ArrayList al = new ArrayList();
try{

int rowCount = 0;//共有几条记录(查表)
int pageCount = 0;//共有多少页(计算)
int pageSize = 3;
///得到rowCount
ConnDB cd = new ConnDB();
conn = cd.getConn();
String sql = "select * from shunpingS";
ps = conn.prepareStatement(sql);
rs = ps.executeQuery();
if(rs.next()){
rowCount = rs.getInt(1);
}
if(rowCount%pageSize == 0){
pageCount = rowCount/pageSize;
}else{
pageCount = rowCount/pageSize + 1;
}
String sql2 = "……";
ps = conn.prepareStatement(sql2);
rs = ps.executeQuery();
while(rs.next()){
///将rs中的每条记录封装到UserBean ub
UserBean ub = new UserBean();
ub.setUserId(rs.getInt(1));
ub.setUserName(rs.getString(2));
ub.setAge(rs.getInt(3));
ub.setMail(rs.getString(4));
//将ub放入到集合中
al.add(ub);
}

}catch(Exception e){
e.printStackTrace();
}finally{
close();
return al;
}
}

//验证用户
public boolean checkUserExist(int u,String p){
boolean flag = false;
try{
conn = new ConnDB().getConn();
String sql = "select * from shunpingS where id=? and passWord=?";
ps = conn.prepareStatement(sql);
rs = ps.executeQuery();
ps.setInt(1, u);
ps.setString(2, p);
if(rs.next()){
flag = true;
}
}catch(Exception e){
e.printStackTrace();
}finally{
close();
}
return flag;
}
public void close(){
try{
if(rs!= null){
rs.close();
rs = null;
}
if(ps!= null){
ps.close();
ps = null;
}
if(conn!= null)
{
conn.close();
conn = null;
}
}catch(Exception e){
e.printStackTrace();
}
}
}

然后,在Welcome与LoginDL中,分别调用UserBeanDL中的方法,实现自己的逻辑。


在loginDL.java中,对其实例,调用 它的方法来验证

String u = req.getParameter("userName");
String p = req.getParameter("passWord");
UserBeanDL udl = new UserBeanDL();
if(udl.checkUserExist(Integer.parseInt(u), p))
{
res.sendRedirect("welcome");
}
else{
res.sendRedirect("login");
}

在 welcome.java中,同样对其调用,用于显示 :

UserBeanDL ubd = new UserBeanDL();
ArrayList al = null;
try {
al = ubd.getResultByPage(pageNow, pageSize);
} catch (Exception e) {
e.printStackTrace();
}
for(int i=0;i<al.size();i++){
UserBean ub = (UserBean)al.get(i);
pw.println("<tr>");
pw.println("<td>" + ub.getAge() + "</td>");
pw.println("<td>" + ub.getMail() + "</td>");
pw.println("<td>" + ub.getUserId() + "</td>");
pw.println("</tr>");

}

传值时:

UserBean ub = (UserBean)al.get(i);
<td> <a  href = DelUserCL?userid = " + ub.getUserId() + "" >删除用户</a></td>



注意一个地方:在用MV模式时,把表现与后台分隔开了,在分页的时候,在表现层要用到后台得到的rowCount值,这个问题当时 没研究出来。。

后来看韩顺平的视频,看到他用的方法是:在后台里,把它定义为一个成员变量

int pageCount = 0;

然后,写一个方法,

public int getPageCount(){
return this.pageCount;
}


这样,前面就可以通过int pageCount = ubd.getPageCount();来得到值了。。。

这种思想太值得学习了。。。。。。



//////////////////
//////////////////注意这种思想,当发现pageCount是由UserBeanDL计算而得,但是在此页要用到,
//////////////////此页已经有了UserBeanDL的实例,故在UserBeanDL中加一个方法,返回我们想要的参数即可。
//////////////////高!!!!!!!!!!!!!!!!