前言
我们之前讲解了很多关于Java的基础知识,那么问题来了,你会写一个简单的系统吗?答案是否定的!接下来我们就尝试着去编写最简单,最基本的项目后台。本章篇幅有点大,请耐心读完,并自主敲代码,那么你的成长是无限的!!!
步骤
1.需求分析
任何软件的开发都免不了需求分析,我们需要将客户的需求转化为程序业务逻辑,加之代码实现,需求分析这一块有专门的学习,感兴趣的同学可以去看看!
需求:
某学校长期以来都以纸质文件的方式来管理学生的资料,现在需要我们做一个学生信息管理系统,粗略需求如下:
- 系统需提供登陆功能,实现管理员登陆进行学生信息管理
- 系统可以管理本校所有学生信息,并实现基本的增删改查
当我们获取这两个粗略的需求,需要将其提升到业务设计上来。
2.概要设计
该系统为典型的MVC架构,项目整体架构为:
- 显示层(JSP、HTML、CSS、JS等):网页页面,用户直接访问
- 控制层(JAVA、SERVLET):用来处理显示层传入的请求
- 业务层(JAVA):实现具体业务,供控制层调用
- 数据访问层(JAVA):直接与数据库交互,供业务层调用
这里我们只分析后台实现,也就是业务层(Service)+数据访问层(Dao),现阶段开发环境为:win10+eclipse+oracle11g
3.详细设计
业务层:
- 系统用户登陆
- 查询全部学生信息
- 根据学生姓名模糊查询
- 删除学生信息
- 修改学生信息
- 新增学生信息
数据访问层:
- select * from user where username=? and password = ?
- select * from student
- select * from student where name like '%key%'
- delete from student where...
- update student set name=...
- insert into student values(...)...
4.数据库设计
初步观察,我们做的简单系统包含两个实体(学生和管理员)。
也就是说我们只需要两张表(学生表以及用户表)就可以做我们简单的项目啦!!!
- 通过powerDesigner进行数据库设计,导出SQL脚本
- 使用scott/tiger登陆oracle数据库执行导出的sql脚本,并加入测试数据
5.使用eclipse搭建web项目,确定项目主体(骨架)
新建动态web工程,命名为SMS(Student Manage System)
以上为项目设计的基本框架,其中各个层的包名命名规范基本如博主所写
6.编写实体类(学生类以及用户类)
package com.jwang.student.bo;
import java.io.Serializable;
/**
* 学生信息表
* @author jwang
*
*/
@SuppressWarnings("serial")
public class Student implements Serializable {
private String id;//主键id
private String name;//学生姓名
private String sex;//性别
private Integer age;//年龄
private String loc;//家庭住址
//无参构造器
public Student() {}
//有参构造器
public Student(String id, String name, String sex, Integer age, String loc) {
this.id = id;
this.name = name;
this.sex = sex;
this.age = age;
this.loc = loc;
}
//getter、setter方法
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getLoc() {
return loc;
}
public void setLoc(String loc) {
this.loc = loc;
}
//toString方法
@Override
public String toString() {
return "Student [id=" + id + ", name=" + name + ", sex=" + sex + ", age=" + age + ", loc=" + loc + "]";
}
}
package com.jwang.student.bo;
import java.io.Serializable;
/**
* 用户信息表
* @author jwang
*
*/
@SuppressWarnings("serial")
public class User implements Serializable {
private String id;//主键id
private String userName;//用户名
private String passWord;//密码
//无参构造器
public User() {}
//有参构造器
public User(String id, String userName, String passWord) {
this.id = id;
this.userName = userName;
this.passWord = passWord;
}
//getter、setter方法
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 getPassWord() {
return passWord;
}
public void setPassWord(String passWord) {
this.passWord = passWord;
}
//toString方法
@Override
public String toString() {
return "User [id=" + id + ", userName=" + userName + ", passWord=" + passWord + "]";
}
}
7.数据库连接工具类编写与测试
按照之前讲解JDBC的样例,将代码拷贝至util包下即可,不过你要改成该类专门用于获取数据库连接,加载properties文件获取连接信息。
package com.jwang.student.util;
import java.io.BufferedReader;
import java.io.FileReader;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;
/**
* 数据库连接类
* @author jwang
*
*/
public class DBConnection {
private Properties properties = new Properties();
private Connection conn;
//初始化连接
public DBConnection() {
try {
//加载文件db.properties
properties.load(new BufferedReader(new FileReader("src/db.properties")));
Class.forName(properties.getProperty("db_driver"));
this.conn = DriverManager.getConnection(properties.getProperty("db_url"),
properties.getProperty("db_user"), properties.getProperty("db_pass"));
} catch (Exception e) {
e.printStackTrace();
}
}
//获取连接
public Connection getConnection(){
return this.conn;
}
//关闭连接
public void close(){
if(this.conn != null){
try {
this.conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
##oracle 11g
db_driver=oracle.jdbc.driver.OracleDriver
db_url=jdbc:oracle:thin:@localhost:1521:orcl
db_user=scott
db_pass=tiger
首先编写测试类对我们的数据库连接工具类进行一个测试,因为我们不能保证代码写的完美无暇!
在test包下新建测试类,用于测试数据库连接。特别的:这里使用JUnit进行测试(我之前的博客有讲过)
package com.jwang.student.test;
import org.junit.Test;
import com.jwang.student.util.DBConnection;
public class DBConnTest {
//检查数据库连接工具类是否正常
@Test
public void testDBConn(){
DBConnection db = new DBConnection();
System.out.println(db.getConnection());
}
}
此处常见错误:
- 问题:java.lang.ClassNotFoundException: oracle.jdbc.driver.OracleDriver
- 原因:该错误为JDBC驱动包未导入或者连接串单词写错
- 解决:导入JDBC驱动包,检查驱动连接串是否写对
8.数据访问层(dao)编写与测试
需要特别留意的是:
- 该处实现类只需要一个Connection对象的属性已经足够了,通过外部注入进行获取
- 该处每一个方法无需关闭数据库连接,因为这是业务层该干的事情,每个业务层可能包换多个dao层方法
- 该处异常一律抛出,交给方法调用出,也就是service层处理
package com.jwang.student.dao;
import com.jwang.student.bo.User;
/**
* 用户类数据访问层接口
* @author jwang
*
*/
public interface UserDAO {
/**
* 用于用户管理员登陆,判断用户名与密码在数据库可否查到
* <li>如果登陆成功,返回true</li>
* <li>如果登陆失败,返回false</li>
* @param user 用户
* @return (true/false)
*/
public boolean doLogin(User user) throws Exception;
}
package com.jwang.student.dao;
import java.util.List;
import com.jwang.student.bo.Student;
/**
* 学生类数据访问层接口
* @author jwang
*
*/
public interface StudentDAO {
/**
* 查询所有学生的基本信息
* @return 学生集合
*/
public List<Student> findAllStudent() throws Exception;
/**
* 根据学生姓名模糊查询学生的基本信息
* @param name 学生姓名,模糊查询
* @return 学生集合
*/
public List<Student> findStudentByName(String name) throws Exception;
/**
* 根据学生id查询学生的基本信息
* @param id 学生id
* @return
*/
public Student findStudentById(String id) throws Exception;
/**
* 添加学生基本信息
* @param student
* @return
*/
public boolean addStudent(Student student) throws Exception;
/**
* 修改学生基本信息
* @param student
* @return
*/
public boolean updateStudent(Student student) throws Exception;
/**
* 删除指定id的学生信息
* @param id 学生id
* @return
*/
public boolean delStudent(String id) throws Exception;
}
接口实现如下:
package com.jwang.student.dao.impl;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import com.jwang.student.bo.User;
import com.jwang.student.dao.UserDAO;
public class UserDAOImpl implements UserDAO {
private Connection conn;
public UserDAOImpl(Connection conn) {
this.conn = conn;
}
@Override
public boolean doLogin(User user) throws Exception{
String sql = " select * from users where username=? and password=? ";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setString(1, user.getUserName());
pstmt.setString(2, user.getPassWord());
ResultSet rs = pstmt.executeQuery();
if(rs.next()){
return true;
}
return false;
}
}
package com.jwang.student.dao.impl;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
import com.jwang.student.bo.Student;
import com.jwang.student.dao.StudentDAO;
public class StudentDAOImpl implements StudentDAO {
private Connection conn;
public StudentDAOImpl(Connection conn) {
this.conn = conn;
}
@Override
public List<Student> findAllStudent() throws Exception{
List<Student> result = new ArrayList<>();
String sql = " select id,name,sex,age,loc from student ";
PreparedStatement pstmt = conn.prepareStatement(sql);
ResultSet rs = pstmt.executeQuery();
while(rs.next()){
Student student = new Student();
student.setId(rs.getString(1));
student.setName(rs.getString(2));
student.setSex(rs.getString(3));
student.setAge(rs.getInt(4));
student.setLoc(rs.getString(5));
result.add(student);
}
return result;
}
@Override
public List<Student> findStudentByName(String name) throws Exception{
List<Student> result = new ArrayList<>();
String sql = " select id,name,sex,age,loc from student where name like ? ";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setString(1, "%"+name+"%");
ResultSet rs = pstmt.executeQuery();
while(rs.next()){
Student student = new Student();
student.setId(rs.getString(1));
student.setName(rs.getString(2));
student.setSex(rs.getString(3));
student.setAge(rs.getInt(4));
student.setLoc(rs.getString(5));
result.add(student);
}
return result;
}
@Override
public Student findStudentById(String id) throws Exception{
Student student = null;
String sql = " select id,name,sex,age,loc from student where id = ? ";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setString(1, id);
ResultSet rs = pstmt.executeQuery();
if(rs.next()){
student = new Student();
student.setId(rs.getString(1));
student.setName(rs.getString(2));
student.setSex(rs.getString(3));
student.setAge(rs.getInt(4));
student.setLoc(rs.getString(5));
}
return student;
}
@Override
public boolean addStudent(Student student) throws Exception{
String sql = " insert into student values (?,?,?,?,?) ";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setString(1, student.getId());
pstmt.setString(2, student.getName());
pstmt.setString(3, student.getSex());
pstmt.setInt(4, student.getAge());
pstmt.setString(5, student.getLoc());
int num = pstmt.executeUpdate();
if(num > 0){
return true;
}
return false;
}
@Override
public boolean updateStudent(Student student) throws Exception{
String sql = " update student set name=?,sex=?,age=?,loc=? where id = ?";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setString(1, student.getName());
pstmt.setString(2, student.getSex());
pstmt.setInt(3, student.getAge());
pstmt.setString(4, student.getLoc());
pstmt.setString(5, student.getId());
int num = pstmt.executeUpdate();
if(num > 0){
return true;
}
return false;
}
@Override
public boolean delStudent(String id) throws Exception{
String sql = " delete from student where id = ?";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setString(1, id);
int num = pstmt.executeUpdate();
if(num > 0){
return true;
}
return false;
}
}
8.业务层(service)编写与测试
注意:
- 该处为业务层实现,需要对每个业务方法关闭数据库连接,保证事务安全
- 该层需要一个数据库连接类对象的属性,并且实例化,用于实例化DAO传递参数,也用于关闭连接
- 该层需要一个dao对象,以便于调用dao层的相关方法
package com.jwang.student.service;
import com.jwang.student.bo.User;
/**
* 用户类业务层接口
* @author jwang
*
*/
public interface UserService {
//用户登录
public boolean login(User user);
}
package com.jwang.student.service;
import java.util.List;
import com.jwang.student.bo.Student;
/**
* 学生类业务层接口
* @author jwang
*
*/
public interface StudentService {
//查询所有学生信息
public List<Student> listAllStudent();
//根据学生姓名模糊查询
public List<Student> listStudentByName(String name);
//增加学生
public boolean addStudent(Student student);
//修改学生
public boolean editStudent(Student student);
//根据学生id删除学生信息
public boolean delStudent(String id);
}
接口实现类如下:
package com.jwang.student.service.impl;
import com.jwang.student.bo.User;
import com.jwang.student.dao.UserDAO;
import com.jwang.student.dao.impl.UserDAOImpl;
import com.jwang.student.service.UserService;
import com.jwang.student.util.DBConnection;
public class UserServiceImpl implements UserService {
private DBConnection db = new DBConnection();
private UserDAO userDAO;
public UserServiceImpl() {
this.userDAO = new UserDAOImpl(db.getConnection());
}
@Override
public boolean login(User user) {
try {
return userDAO.doLogin(user);
} catch (Exception e) {
e.printStackTrace();
} finally {
this.db.close();
}
return false;
}
}
package com.jwang.student.service.impl;
import java.util.List;
import com.jwang.student.bo.Student;
import com.jwang.student.dao.StudentDAO;
import com.jwang.student.dao.impl.StudentDAOImpl;
import com.jwang.student.service.StudentService;
import com.jwang.student.util.DBConnection;
public class StudentServiceImpl implements StudentService {
private DBConnection db = new DBConnection();
private StudentDAO studentDAO;
public StudentServiceImpl() {
this.studentDAO = new StudentDAOImpl(db.getConnection());
}
@Override
public List<Student> listAllStudent() {
try {
return studentDAO.findAllStudent();
} catch (Exception e) {
e.printStackTrace();
}finally {
this.db.close();
}
return null;
}
@Override
public List<Student> listStudentByName(String name) {
try {
return studentDAO.findStudentByName(name);
} catch (Exception e) {
e.printStackTrace();
}finally {
this.db.close();
}
return null;
}
@Override
public boolean addStudent(Student student) {
try {
if(studentDAO.findStudentById(student.getId()) == null){
return studentDAO.addStudent(student);
}
} catch (Exception e) {
e.printStackTrace();
}finally {
this.db.close();
}
return false;
}
@Override
public boolean editStudent(Student student) {
try {
if(studentDAO.findStudentById(student.getId()) != null){
return studentDAO.updateStudent(student);
}
} catch (Exception e) {
e.printStackTrace();
}finally {
this.db.close();
}
return false;
}
@Override
public boolean delStudent(String id) {
try {
return studentDAO.delStudent(id);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
this.db.close();
}
return false;
}
}