【通讯录管理系统】
(一)项目所需的技术:
1、XML相关技术
2、DOM4J相关技术
3、Xpath相关技术
4、MD5加密相关技术
5、图形界面JTable、历史集合Vector相关技术
拥有了上面的这些技术,可以写一个简单的“通讯录管理程序了”!
(二)实现方式:
首先需要对整个系统框架进行分层:
(三)代码分析演示:
(1)表现层:
LoginWin:
package cn.hncu.contact.ui;
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;
import cn.hncu.contact.dao.ContactDAO;
import cn.hncu.contact.dao.factory.ContactDAOfactory;
public class LoginWin extends JFrame{
ContactDAO dao=ContactDAOfactory.getContactDAO();
public LoginWin(String string) {
//界面基本默认参数设置
setTitle(string);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setBounds(200, 200, 300, 150);
Container c=getContentPane();
c.setLayout(new FlowLayout());
//显示表格的
//用户交互组件:----输入
JLabel jlb1=new JLabel("姓名");
c.add(jlb1);
final JTextField tfdName= new JTextField(20);
c.add(tfdName);
JLabel jlb2=new JLabel("密码");
c.add(jlb2);
final JPasswordField tfdPwd=new JPasswordField(20);
c.add(tfdPwd);
//用户交互组件:----按钮
JPanel jpl2=new JPanel();
c.add(jpl2,BorderLayout.SOUTH);
/*
* 登录按钮的事件交互
*/
JButton btnLogin=new JButton("登录");
jpl2.add(btnLogin);
btnLogin.setActionCommand("login");
btnLogin.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if(e.getActionCommand().equals("login")){
//1、收集参数
String name=tfdName.getText();
String pwd=new String(tfdPwd.getPassword());
//2、组织参数(略过,因为逻辑层没有写,JavaBean也就不用封装了)
//3、调用逻辑层(略过,直接在表现层调用DAO,不用在逻辑层调用DAO,小程序就简写了)
boolean boo=dao.login(name,pwd);
//4、根据逻辑层返回结果执行不同的结果页面
if(boo){
/*【注意】:
* 此时有个问题:
* --①某个用户登录成功后,ContactWin中的JTable会显示【当前用户】下的所有联系人的详细信息;
* --②当我们new ContactWin之后,该如何知道当前的ContactWin界面的用户就是已经登录的用户;
* --③ContactWin完全没有必然的联系,该如何将登录时候的用户传到登录后的界面中去呢?
* --④可以将当前登录时候调用的dao传给ContactWin界面,因为dao是唯一的;
* --⑤因为传的是同一个dao,用户肯定是同一个;
* --⑥但是我们在登录的同时要将所调用的dao作为当前dao存储记录下来,好让下个界面使用;
*
*/
new ContactWin(dao);
}else{
JOptionPane.showMessageDialog(LoginWin.this, "用户名或密码错误");
return;
}
}
}
});
/*
* 注册按钮的事件交互
*/
JButton btnReg=new JButton("注册");
jpl2.add(btnReg);
btnReg.setActionCommand("reg");
btnReg.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if(e.getActionCommand().equals("reg")){
String name=tfdName.getText();
String pwd=new String(tfdPwd.getPassword());
boolean boo=dao.reg(name, pwd);
if(boo){
System.out.println(boo);
}else{
System.out.println(boo);
}
}
}
});
/*
* 取消按钮的事件交互
*/
JButton btnCancel =new JButton("取消");
jpl2.add(btnCancel);
btnCancel.setActionCommand("cancel");
btnCancel.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if(e.getActionCommand().equals("cancel")){
System.exit(0);
}
}
});
setVisible(true);
}
public static void main(String[] args) {
new LoginWin("通讯录管理系统");
}
}
ContactWin:
package cn.hncu.contact.ui;
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Iterator;
import java.util.Vector;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.table.DefaultTableModel;
import cn.hncu.contact.dao.ContactDAO;
public class ContactWin extends JFrame{
/*
* 接收当前dao为参数中的dao
*/
private static ContactDAO dao=null;
public ContactWin(final ContactDAO dao){
/*
* 表现层默认参数设置
*/
setTitle("联系人管理");
setBounds(100, 100, 900, 400);
Container c=getContentPane();
/*
维护Table数据层数据
data the data of the table, a Vector of Vectors of Object values
columnNames vector containing the names of the new columns
*/
//①添加表头---将固定的表头添加到列名集合中
final Vector<String> columnNames =new Vector<String>();
columnNames.add("ID");
columnNames.add("Name");
columnNames.add("Sex");
columnNames.add("Tell");
columnNames.add("Addr");
//②添加表数据---从数据库中拿到所有的信息,然后逐行遍历并且添加到表格
Vector<Vector<Object>> data=new Vector<Vector<Object>>();
Vector<Vector<Object>> vv=dao.getAllContacts();
for(Vector<Object> v:vv){
data.add(v);
}
//③添加数据库中读取的所有信息加入到表格中
final DefaultTableModel dtm=new DefaultTableModel(data, columnNames);
final JTable jtable=new JTable(dtm);
jtable.removeColumn(jtable.getColumn("ID"));
c.add(new JScrollPane(jtable));
/*
* 用户交换数据的表现层
*/
JPanel jpl2=new JPanel();
JLabel jlb1=new JLabel("姓名");
jpl2.add(jlb1);
final JTextField tfdName=new JTextField(10);
jpl2.add(tfdName);
JLabel jlb2=new JLabel("性别");
jpl2.add(jlb2);
final JTextField tfdSex=new JTextField(10);
jpl2.add(tfdSex);
JLabel jlb3=new JLabel("电话");
jpl2.add(jlb3);
final JTextField tfdTel=new JTextField(10);
jpl2.add(tfdTel);
JLabel jlb4=new JLabel("地址");
jpl2.add(jlb4);
final JTextField tfdAddr=new JTextField(10);
jpl2.add(tfdAddr);
/*
* 按钮---实现逻辑层功能
*/
//按钮---添加
JButton btnAdd=new JButton("添加");
jpl2.add(btnAdd);
btnAdd.setActionCommand("add");
btnAdd.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if(e.getActionCommand().equals("add")){
//1、收集数据
//2、组织数据
String name=tfdName.getText();
String sex=tfdSex.getText();
String tell=tfdTel.getText();
String addr=tfdAddr.getText();
//3、调用数据层
boolean boo=dao.addContact(name,sex,tell,addr);
//4、根据调用结果返回不同结果页面
if(boo){
//回显---从数据库中读出所有信息添加到表格中
Vector<Vector<Object>> dataVector =dao.getAllContacts();
dtm.setDataVector(dataVector, columnNames);
jtable.removeColumn(jtable.getColumn("ID"));
}else{
JOptionPane.showMessageDialog(ContactWin.this, "此联系人已经存在");
}
}
}
});
//按钮---删除
JButton btnDel=new JButton("删除");
jpl2.add(btnDel);
btnDel.setActionCommand("del");
btnDel.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
int num=jtable.getSelectedRow();
if(num==-1){
JOptionPane.showMessageDialog(ContactWin.this, "请选择要删除的一行表格数据");
return;
}
//Object getValueAt(int row, int column) 返回 row 和 column 处单元格的属性值。
String id=(String) dtm.getValueAt(num, 0);
String name=(String) dtm.getValueAt(num, 1);
boolean boo=dao.delContact(id);
if(boo){
dtm.setDataVector(dao.getAllContacts(), columnNames);
JOptionPane.showMessageDialog(ContactWin.this, "联系人"+name+"已经删除成功!");
return;
}else{
JOptionPane.showMessageDialog(ContactWin.this, "联系人"+name+"删除失败!");
return;
}
}
});
//按钮---修改
JButton btnUpDate=new JButton("修改");
jpl2.add(btnUpDate);
btnUpDate.setActionCommand("update");
btnUpDate.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
int num=jtable.getSelectedRow();
if(num==-1){
JOptionPane.showMessageDialog(ContactWin.this, "请选择要修改的一行表格数据");
return;
}
String id=(String) dtm.getValueAt(num, 0);
//直接读取对应编辑框中的内容作为修改的值
String name=tfdName.getText();
String sex=tfdSex.getText();
String tell=tfdTel.getText();
String addr=tfdAddr.getText();
boolean boo=dao.upDateContact(id,name,sex,tell,addr);
if(boo){
dtm.setDataVector(dao.getAllContacts(), columnNames);
JOptionPane.showMessageDialog(ContactWin.this, "联系人修改成功");
return;
}else{
JOptionPane.showMessageDialog(ContactWin.this, "联系人修改失败");
return;
}
}
});
//按钮---查询
JButton btnQuery=new JButton("查询");
jpl2.add(btnQuery);
btnQuery.setActionCommand("query");
btnQuery.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("查询");
}
});
c.add(jpl2,BorderLayout.SOUTH);
setVisible(true);
}
public static void main(String[] args) {
new ContactWin(dao);
}
}
(2)DAO层:
(2-1)接口:
ContactDAO:
package cn.hncu.contact.dao;
import java.util.Vector;
public interface ContactDAO {
public boolean login(String name,String pwd);
public boolean reg(String name,String pwd);
public Vector<Vector<Object>> getAllContacts();
public boolean addContact(String name, String sex, String tell, String addr);
public boolean delContact(String id);
public boolean upDateContact(String id, String name, String sex, String tell, String addr);
}
(2-2)工厂:
ContactDAOfactory:
package cn.hncu.contact.dao.factory;
import cn.hncu.contact.dao.ContactDAO;
import cn.hncu.contact.dao.impl.ContactDAOImpl;
public class ContactDAOfactory {
private ContactDAOfactory(){
}
public static ContactDAO getContactDAO(){
return new ContactDAOImpl();
}
}
(2-3)实现类:
ContactDAOImpl:
package cn.hncu.contact.dao.impl;
import java.util.List;
import java.util.Vector;
import org.dom4j.Document;
import org.dom4j.Element;
import cn.hncu.contact.commons.DocumentFactory;
import cn.hncu.contact.dao.ContactDAO;
import cn.hncu.contact.utils.PwdUtils;
import cn.hncu.contact.utils.UUIDUtils;
public class ContactDAOImpl implements ContactDAO{
private Document dom=DocumentFactory.getDom();
private Element eCurrentUser=null;
/**
* 登录某一个用户
*/
@Override
public boolean login(String name, String pwd) {
//1、收集数据
//2、组织数据对密码进行MD5加密
String newPwd=PwdUtils.mkMD5Pwd(pwd);
//3、调用逻辑层
Element root=dom.getRootElement();
Element euser=(Element) root.selectSingleNode("/contacts/user[@name='"+name+"'][@pwd='"+newPwd+"']");
// Element euser =root.element("user");
if(euser!=null){
/*
* 将当前登录的用户元素记录下来,以供下次调用用户管理界面使用
*/
eCurrentUser=euser;
return true;
}
return false;
}
/**
* 用户注册
*/
@Override
public boolean reg(String name, String pwd) {
//1、收集参数
//2、组织参数
//判断此注册用户是否已经存在:::
Element root=dom.getRootElement();
List<Element>list=root.elements("user");
for(Element e:list){
if(name.equals(e.attribute("name"))){
return false;
}
}
String newPwd=PwdUtils.mkMD5Pwd(pwd);
Element user=root.addElement("user");
user.addAttribute("name", name);
user.addAttribute("pwd", newPwd);
//保存修改后的DOM树
DocumentFactory.save();
return true;
}
/**
* 获得所有的联系人
*/
@Override
public Vector<Vector<Object>> getAllContacts() {
Vector<Vector<Object>> vv=new Vector<Vector<Object>>();
List<Element> list=eCurrentUser.elements("contact");
for(Element e:list){
Vector<Object> v=new Vector<Object>();
v.add(e.attribute("id").getText());
v.add(e.elementText("name"));
v.add(e.elementText("sex"));
v.add(e.elementText("tell"));
v.add(e.elementText("addr"));
vv.add(v);
}
return vv;
}
/**
* 添加某一个联系人
*/
@Override
public boolean addContact(String name, String sex, String tell, String addr) {
List<Element> list=eCurrentUser.elements("contact");
//需要判断下联系人是否已经存在
for(Element e:list){
if(name.equals(e.elementText("name"))){
return false;
}
}
String id=UUIDUtils.getID();
Element eContact=eCurrentUser.addElement("contact").addAttribute("id", id);
eContact.addElement("name").setText(name);
eContact.addElement("sex").setText(sex);
eContact.addElement("tell").setText(tell);
eContact.addElement("addr").setText(addr);
//保存修改后的DOM树
DocumentFactory.save();
return true;
}
/**
* 删除一个联系人
*/
@Override
public boolean delContact(String id) {
//利用XPath直接找到要删除的联系人
Element contact=(Element) eCurrentUser.selectSingleNode("//contact[@id='"+id+"']");
boolean boo=contact.getParent().remove(contact);
if(boo){
DocumentFactory.save();
}
return boo;
}
/**
* 更新一个联系人
*/
@Override
public boolean upDateContact(String id, String name, String sex,
String tell, String addr) {
Element contact=(Element) eCurrentUser.selectSingleNode("//contact[@id='"+id+"']");
contact.element("name").setText(name);
contact.element("sex").setText(sex);
contact.element("tell").setText(tell);
contact.element("addr").setText(addr);
DocumentFactory.save();
return true;
}
}
(3)公共数据层:
DocumentFactory:
package cn.hncu.contact.commons;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
public class DocumentFactory {
private static File file = null;
private static Document dom = null;
private DocumentFactory() {
}
/**
*
* @return 获得DOM树
*/
public static Document getDom() {
try {
file = new File("./xml/contacts.xml");
SAXReader sax = new SAXReader();
dom = sax.read(file);
} catch (DocumentException e) {
throw new RuntimeException("xml数据库读取异常");
}
return dom;
}
/**
* 保存修改后的DOM树
*/
public static void save() {
try {
XMLWriter xw=new XMLWriter(new FileOutputStream(file),
OutputFormat.createPrettyPrint());
xw.write(dom);
xw.close();
} catch (IOException e) {
throw new RuntimeException("数据库写入失败");
}
}
}
(4)工具层:
PwdUtils:
package cn.hncu.contact.utils;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class PwdUtils {
public PwdUtils(){
}
public static String mkMD5Pwd(String pwd){
String newPwd="";
MessageDigest md;
try {
md = MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException("加密失败");
}
byte[] b=md.digest(pwd.getBytes());
/*
* 对b字节数组进一步处理转换成16进制
*/
for(byte i:b){
String s=Integer.toHexString(i&0xFF);
if(s.length()==1){
s="0"+s;
}
newPwd+=s;
}
newPwd=newPwd.toUpperCase();
return newPwd;
}
}
UUIDUtils:
package cn.hncu.contact.utils;
import java.util.UUID;
public class UUIDUtils {
private UUIDUtils(){
}
public static String getID(){
return UUID.randomUUID().toString().replace("-", "");
}
}
结果: