最近一直在学习web,下面通过所做的网上购物系统来整理一下最近所学的知识以及学习过程中遇到的问题还有自己的认识。
对于一个web项目,个人觉得数据库是必不可少的,所以第一步要做的就是设计并实现数据库,而这一块我们就要考虑要做的项目中都需要哪些内容,也就是数据库中应该包含哪些表,表里面应该有哪些属性,然后就要考虑这些表之间的关系。而我做的这个简单的网购系统目前只包含三个表-->
会员表 (标号(主键),用户名,密码,电子邮箱,手机号码)
订单表 (标号(主键)订单编号,选购日期,数量,支付金额,购买者,商品类型)
商品表 (标号(主键)商品号,商品名称,商品单价,生产日期)
这个项目我们也是以小组的形式做的,那么在设计好数据库之后就开始分工。首先呢就要把前台界面和后台功能分开,一个人负责写操作类,其他人负责写界面和servlet类。
下面分别介绍一下各部分的功能
1操作类:对于这个web项目,用户要做的就是在页面上点击一些按钮,然后我们会将其中的信息提交到项目中的web.xml文件中,通过页面中<form>表单中的action来查找,进而找到相应的servlet类进行处理,而servlet类主要就是调用我们所写的操作类,而操作类里面的内容主要就是对数据库的操作(增,删,改,查),但并不是通过一个操作类来对数据库进行所有的操作。一个数据库中会包含多个表,对于每个表我们都要有单独的一个Dao类对其操作,虽然里面的功能都是增、删、改、差,但不同的是我们可以根据传递不同的参数来得到不同的结果,而每个表对应一个Dao在后期管理和改善时会比较方便。
2页面:这部分相对来说会比较简单,因为它不涉及太多的逻辑部分,做页面的目的就是把它做得漂亮,能让用户眼前一亮就可以了。
3servlet类:前面也已经说过了,servlet类主要就是调用操作类。而它具体的流程就是页面首先将要提交的信息通过<form>表单提交到request中,通过web.xml文件映射到相应的servlet类,再通过servlet类中的service方法中的request参数获取提交过来的信息,再对操作类进行操作。
下面就回忆一下我们网购系统的开发过程,并讲诉一下开发过程中遇到的问题以及要注意的地方。
首先是项目的运行流程:
然后我们就要看看要做这么一个项目应该包含哪些包,哪些类。
这个是我们已经做好之后的项目。由于我在这个项目中参与的是对后台的操作,所以下面介绍的主要是后台的实现。
首先我根据数据库中所包含的表来创建pojo包中的成员类,类中的属性就是表中包含的属性,以用户表为例:
public class User {
private int id;
private String user_name;
private String user_pwd;
private String user_tel;
private String user_email;
private int user_limit;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getUser_limit() {
return user_limit;
}
public void setUser_limit(int limit) {
this.user_limit = limit;
}
public String getUser_name() {
return user_name;
}
public void setUser_name(String user_name) {
this.user_name = user_name;
}
public String getUser_pwd() {
return user_pwd;
}
public void setUser_pwd(String user_pwd) {
this.user_pwd = user_pwd;
}
public String getUser_tel() {
return user_tel;
}
public void setUser_tel(String user_tel) {
this.user_tel = user_tel;
}
public String getUser_email() {
return user_email;
}
public void setUser_email(String user_email) {
this.user_email = user_email;
}
}
成员类中只要设置属性的set和get方法就可以了,而成员类的作用就是在servlet中方便我们把在request中获取的信息封装起来,便于操作。
然后就是Dao这个包中的对应于每个成员的操作类,同样以用户的操作类为例:
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import pojo.User;
/**
* 用户请求操作类
*
* @author Administrator
*
*/
public class UserDAO {
private static java.sql.Connection conn;// 数据库接口
/**
* 用户添加函数操作
*
*/
public static void addUser(User user) {
// 获取数据库接口
conn = Connection.getConnection();
String sqladd = "insert into user(user_name,user_pwd,user_tel,user_email,user_limit) values(?,?,?,?,?);";
try {
// 预编译
PreparedStatement pst = conn.prepareStatement(sqladd);
pst.setString(1, user.getUser_name());
pst.setString(2, user.getUser_pwd());
pst.setString(3, user.getUser_tel());
pst.setString(4, user.getUser_email());
pst.setInt(5, user.getUser_limit());
// 执行数据库代码
pst.executeUpdate();
pst.close();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 用户删除函数
*
* @param id
* (只需要传入用户Id)
*/
public static void deleteUser(int id) throws Exception {
// 获取数据库接口
conn = Connection.getConnection();
conn.setAutoCommit(false);
String sqldelete = "delete from User where id =" + id;
try {
Statement stm = conn.createStatement();
stm.executeUpdate(sqldelete);
// 提交结果
conn.commit();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 用户更新函数
*/
public static void updateUser(User user) {
// 获取数据库接口
conn = Connection.getConnection();
String sqlupdate = "update user set user_name=?,user_pwd=?,user_email=?,user_tel=?,user_limit=? where id = "
+ user.getId() + ";";
try {
// 预编译
PreparedStatement pst = conn.prepareStatement(sqlupdate);
pst.setString(1, user.getUser_name());
pst.setString(2, user.getUser_pwd());
pst.setString(4, user.getUser_tel());
pst.setString(3, user.getUser_email());
pst.setInt(5, user.getUser_limit());
// 执行代码
pst.executeUpdate();
pst.close();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 查询函数(用于操作登陆操作或者查询作用)
*
* @param user
*/
public static User checkLogin(String userName, String userPwd) {
// 获取数据库接口
conn = Connection.getConnection();
try {
String sqlcheck = "select * from user where user_name=? and user_pwd=?";
PreparedStatement pst = conn.prepareStatement(sqlcheck);
pst.setString(1, userName);
pst.setString(2, userPwd);
ResultSet rs = pst.executeQuery();
if (rs.next()) { // 如果数据库中有此用户,则返回此用户
User user = new User();
user.setId(rs.getInt(1));
user.setUser_name(rs.getString(2));
user.setUser_pwd(rs.getString(3));
user.setUser_tel(rs.getString(4));
user.setUser_email(rs.getString(5));
user.setUser_limit(rs.getInt(6));
return user;
}
} catch (Exception e) {
e.printStackTrace();
}
// 若返回为空 则查询不到此用户
return null;
}
/**
* 注册时检测该用户名是否已经被使用
*
* @param userName
* @return
*/
public static boolean checkUser(String userName) {
// 得到连接对象
conn = Connection.getConnection();
String sql = "select * from User where User_name = ?";
try {
PreparedStatement pst = conn.prepareStatement(sql);
pst.setString(1, userName);
ResultSet rs = pst.executeQuery();
return rs.next();
} catch (SQLException e) {
e.printStackTrace();
}
return false;
}
public static List<User> getUserList() {
List<User> userList = new ArrayList<User>();
// 获取数据库接口
conn = Connection.getConnection();
try {
String sqlcheck = "select * from user";
PreparedStatement pst = conn.prepareStatement(sqlcheck);
ResultSet rs = pst.executeQuery();
while (rs.next()) { // 如果数据库中有此用户,则返回此用户
User user = new User();
user.setId(rs.getInt(1));
user.setUser_name(rs.getString(2));
user.setUser_pwd(rs.getString(3));
user.setUser_email(rs.getString(4));
user.setUser_tel(rs.getString(5));
user.setUser_limit(rs.getInt(6));
userList.add(user);
}
return userList;
} catch (Exception e) {
e.printStackTrace();
}
// 若返回为空 则查询不到此用户
return null;
}
}
这个用户的操作类中有添加用户(需传入User对象),删除用户(根据用户id删除),更新用户(传入User对象),查找用户(根据用户名和密码查找),检测用户名是否已经被使用的方法(传入用户名),返回所有用户的列表方法。
接下来就是在servlet类中处理请求并调用dao类了。页面提交过来的信息是通过web.xml这个文件来找到对应的servlet类的,主要就是通过里面的<servlet>和<servlet-mapping>这两个标签来映射到servlet类的。
<servlet>
<servlet-name>名称(随意起)</servlet-name>
<servlet-class>包名.要映射的servlet类名</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>名称(随意起,但要和上面的名字一样)</servlet-name>
<url-pattern>提交过来的地址</url-pattern>
</servlet-mapping>
通过这两个标签就可以将页面上的信息提交到我们自己写的servlet类中,下面通过登录过程来展示一下整个的流程。
首先是登录界面(.jsp)
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<script type="text/javascript">
function checkLogin() {
var name = document.getElementById("user_name").value;
var pwd = document.getElementById("user_pwd").value;
if (name == "") {
alert("用户名不能为空!");
return false;
} else if (pwd == "") {
alert("密码不能为空!");
return false;
}
return true;
}
</script>
<title>网上购物</title>
</head>
<body>
<center>
<form action="homepage/login">
<h1 align="center">网上购物系统登录</h1>
<p align="center">
用户名:<input type="text" name="user_name" id="user_name" />
</p>
<p align="center">
密码:<input type="password" name="user_pwd" id="user_pwd" />
</p>
<a href=""><input type="submit" value="登陆"
οnclick="return checkLogin();" /></a> <a href="register.jsp">注册</a>
</form>
</center>
</body>
</html>
当点击登录时该页面会将用户名和密码提交到homepage/login这个地址上,然后就会在web.xml中查找这个地址,然后映射到对应的servlet类中。其中web.xml中的配置是:
<servlet>
<servlet-name>login</servlet-name>
<servlet-class>Servlet.LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>login</servlet-name>
<url-pattern>/homepage/login</url-pattern>
</servlet-mapping>
所以它会跳到Servlet包下面的LoginServlet类中,而LoginServlet类的主要内容是:
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import pojo.Goods;
import pojo.User;
import Dao.GoodsDAO;
import Dao.UserDAO;
public class LoginServlet extends HttpServlet {
public void service(HttpServletRequest request, HttpServletResponse response) {
try {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html; charset=UTF-8");
// 获取用户名和密码
String user_name = request.getParameter("user_name");
String user_pwd = request.getParameter("user_pwd");
// 检测数据库中是否存有该用户
User user = UserDAO.checkLogin(user_name, user_pwd);
if (user != null && user.getUser_limit() == 0) { // 判断登陆者为用户
request.getSession().setAttribute("user", user);
Goods goods = GoodsDAO.checkGood(1);
System.out.println("login->购买前商品数量:" + goods.getGoods_count());
// 将商品列表存到session中
request.getSession().setAttribute("goods", goods);
// 如果存有该用户则登陆成功,跳转到主商品界面
request.getRequestDispatcher("main.jsp").forward(request,
response);
} else if (user != null && user.getUser_limit() == 1) { // 管理员登陆
// 进入管理员界面
request.getRequestDispatcher("../admit/admit_main.jsp")
.forward(request, response);
} else {
// 登陆失败
System.out.println("shibai");
request.setAttribute("error",
"<span style='color:#cc0000'>登陆失败!</span>");
request.getRequestDispatcher("../error.jsp").forward(request,
response);
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 初始化商品
*
* @return
*/
public Goods initGoods() {
Goods goods = new Goods();
goods.setGoods_id(1);
goods.setId(1);
goods.setGoods_count(200);
goods.setGoods_date("2013/4/9");
goods.setGoods_name("ipad");
goods.setGoods_price(4000);
goods.setType_name("电子");
return goods;
}
}
这个类的作用就是先获取到request中传来的用户名和密码,然后到数据库中检测是否含有该用户,如果有的话再进行判断登陆者是用户还是管理员,用户的话就会进入商品界面,管理员就会进入管理界面。
这样登陆的过程就基本实现了,其他的servlet也基本是这样,都是获取信息,然后调用Dao方法完成对数据库的操作。
下面主要说一下我们遇到的问题:
1在做这个项目之前我们已经把大致的流程想好了,所以开发速度还是比较快的,但遇到最烦的问题就是页面的路径问题。尤其是当我们的界面过多的时候就会出现在web.xml中找不到对应的url地址,所以现在看到网页上出现404就不想理它了。而解决这个问题的办法我个人的理解就是可以多分文件夹,但尽量避免文件夹的嵌套。就是说可以在广度上延伸,但不要在深度上延伸。当然如果你觉得你有好方法来解决路径问题你可以在深度上延伸,但对于我这种路径一长就乱了的人来说,只有一个文件夹是最好的。
2 传递信息问题。最开始为了方便,只要用户登录成功,我们就把所有的信息都放到session中保管,之所以放到session中保管而不是在request中是因为它们的作用域不同,session是在整个的对话过程中都存在,而request只是在一次请求应答中,所以为了只要存放一次信息以后都不用管它们了就放到session中保管了,虽然这样方便,但也有一些缺点,那就是session的存放空间是有限的,如果存放的无用数据过多会在后面出现数据存放不下的情况。那么解决这个问题的方法就是把信息存到request中,这样在一次请求之后request就会自动消失,不会占用大量的空间。并且不要一次性把所有的信息都存起来,我们要根据当前所得到的信息来判断他需要哪些数据,一次只存放它需要的东西。
感受:
分工不明确:在做之前我们觉得每个人负责一个部分很好,这样每个人在编写的时候就不需要关心其他人的工作进度,最后只要把每个人做的整合到一起就好了,但后来发现这样做有一点不好,因为做完一个项目之后每个人只对他负责的那部分有了解,而对项目其他部分的了解就有些不足,那这样的分工显然是不合理的,完成一个项目之后我们不能只了解自己负责的部分,应该是对项目的整个流程都有了解,那分工的时候就不能按模块分工,而要按功能分工,这样每个人就会对项目的整体流程有所了解了。