MVC+RMI=同步刷新的人員管理系統

一個簡單的人員管理系統,採用MVC架構以及java分佈式。

視圖以及控制層在客戶端,模型層位於服務端。

實現功能如圖





當多用戶在瀏覽同一視圖時其中任何一個人對於人員數據的修改都會導致其他用戶的同一視圖的同步刷新。

這一功能的實現是通過模型層調用視圖層的刷新方法實現的。

系統代碼如下

視圖層:

package store;

import java.rmi.Remote;
import java.rmi.RemoteException;

public interface StoreView extends Remote
{
	/**註冊處理用戶動作的監聽器*/
	public void addUserGestureListener(StoreController ctrl)throws StoreException,RemoteException;
	/**在圖形界面上顯示數據,參數display指定顯示的數據*/
	public void showDisplay(Object display)throws StoreException,RemoteException;
	/**當模型層修改了數據庫中某個人員信息時同步刷新視圖層的圖形界面 */
	public void handleCustomerChange(Customer cust)throws StoreException,RemoteException;
}

爲了能夠被模型層訪問,視圖層接口爲遠程接口。

package store;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.Serializable;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.util.ArrayList;
import java.util.Set;

public class StoreViewImpl extends UnicastRemoteObject implements StoreView,Serializable
{
	private transient StoreGui gui;
	private StoreModel storeModel;
	private Object display;
	private ArrayList<StoreController> storeControllers=new ArrayList<StoreController>(10);
	protected StoreViewImpl(StoreModel model) throws RemoteException 
	{
		super();
		try{
			this.storeModel=model;
			model.addChangeListener(this);
		}catch(Exception e)
		{
			System.out.println("StoreViewImpl constructor "+e);
		}
		gui=new StoreGui();
		gui.setVisible(true);
		gui.addSelectionPanelListener(selectionPanelListeners);
		gui.addCustPanelListener(custPanelListeners);
	}
	//監聽圖形界面上查詢人員按鈕
	transient ActionListener custGetHandler=new ActionListener()
	{

		public void actionPerformed(ActionEvent e)
		{
			StoreController sc;
			long custId;
			custId=gui.getCustIdOnCustPanel();
			for(int i=0;i<storeControllers.size();i++)
			{
				sc=storeControllers.get(i);
				sc.handleGetCustomer(custId);
			}
			
		}
		
	};
	//監聽圖形界面上添加人員按鈕
	transient ActionListener custAddHandler=new ActionListener()
	{

		
		public void actionPerformed(ActionEvent e)
		{
			StoreController sc;
			for(int i=0;i<storeControllers.size();i++)
			{
				sc=storeControllers.get(i);
				sc.handleAddCustomerGesture(gui.getCustomerOnCustPanel());
			}
			
			
		}
		
	};
	//監聽圖形界面上刪除人員按鈕
	transient ActionListener custDeleteHandler=new ActionListener()
	{

		
		public void actionPerformed(ActionEvent e)
		{
			StoreController sc;
			for(int i=0;i<storeControllers.size();i++)
			{
				sc=storeControllers.get(i);
				sc.handleDeleteCustomerGesture(gui.getCustomerOnCustPanel());
			}
			
		}
		
	};
	//監聽圖形界面上更新人員按鈕
		transient ActionListener custUpdateHandler=new ActionListener()
		{

			
			public void actionPerformed(ActionEvent e)
			{
				StoreController sc;
				for(int i=0;i<storeControllers.size();i++)
				{
					sc=storeControllers.get(i);
					sc.handleUpdateCustomerGesture(gui.getCustomerOnCustPanel());
				}
				
			}
			
		};
	//監聽圖形界面上人員詳情信息按鈕
	transient ActionListener custDetailsPageHandler=new ActionListener()
	{
		public void actionPerformed(ActionEvent e) 
		{
			StoreController sc;
			long custId;
			custId=gui.getCustIdOnCustPanel();
			if(custId==-1)
			{
				try{
					showDisplay(new Customer(-1));
				}catch(Exception e1)
				{
					e1.printStackTrace();
				}
			}
			else
			{
				for(int i=0;i<storeControllers.size();i++)
				{
					sc=storeControllers.get(i);
					sc.handleGetCustomer(custId);
				}
			}
			
		}
		
	};
	//監聽圖形界面上所有人員清單按鈕
	transient ActionListener allCustsPageHandler=new ActionListener()
	{

		public void actionPerformed(ActionEvent e) 
		{
			StoreController sc;
			sc=storeControllers.get(0);
			sc.handleGetAllCustomer();
			
		}
		
	};
	//存儲監聽器
	transient ActionListener[] custPanelListeners={custGetHandler,custAddHandler,custDeleteHandler,custUpdateHandler};
	transient ActionListener[] selectionPanelListeners={custDetailsPageHandler,allCustsPageHandler};
	//註冊控制器
	public void addUserGestureListener(StoreController ctrl)
			throws StoreException, RemoteException {
		
		storeControllers.add(ctrl);
	}

	//在圖形界面上展示參數display指定的數據
	public void showDisplay(Object display) throws StoreException,
			RemoteException {
		
		if(!(display instanceof Exception))
		{
			this.display=display;
		}
		if(display instanceof Customer)
		{
			gui.refreshCustPanel((Customer)display);
		}
		if(display instanceof Set)
		{
			gui.refreshAllCustPanel((Set<Customer>)display);
		}
		if(display instanceof Exception)
		{
			gui.updateLog(((Exception)display).getMessage());
		}
	}

	/**刷新界面的人員信息*/
	public void handleCustomerChange(Customer cust) throws StoreException,
			RemoteException {
		long custIdOnPanel=-1;
		try{
			if(display instanceof Set)
			{
				gui.refreshAllCustPanel(storeModel.getAllCustomer());
				return;
			}
			if(display instanceof Customer)
			{
				custIdOnPanel=gui.getCustIdOnCustPanel();
				if(custIdOnPanel!=cust.getId())//只同步刷新在查詢相同人員信息的視圖
				{
					return;
					
				}
				gui.refreshCustPanel(cust);
			}
		}catch(Exception e)
		{
			System.out.println("StoreViewImpl processCustomer "+e);
		}
		
	}

}

Storeview的具體實現類StoreViewImpl


控制層接口以及具體實現如下

package store;

public interface StoreController 
{
	/**處理根據ID查詢人員的動作*/
	public void handleGetCustomer(long id);
	/**處理添加人員的動作*/
	public void handleAddCustomerGesture(Customer cust);
	/**處理刪除人員的動作*/
	public void handleDeleteCustomerGesture(Customer cust);
	/**處理更新人員的動作*/
	public void handleUpdateCustomerGesture(Customer cust);
	/**處理列出所有人員的動作*/
	public void handleGetAllCustomer();
}


package store;

import java.util.Set;

public class StoreControllerImpl implements StoreController
{
	private StoreModel storeModel;
	private StoreView storeView;
	public StoreControllerImpl(StoreModel model,StoreView view)
	{
		try{
			storeModel=model;
			storeView=view;
			view.addUserGestureListener(this);
		}catch(Exception e)
		{
			reportException(e);
		}
	}
	//報告異常信息
	private void reportException(Object o)
	{
		try{
			storeView.showDisplay(o);
		}catch(Exception e)
		{
			System.out.println("StoreControllerImpl reportException "+e);
		}
	}
	//處理根據ID查詢人員的動作
	public void handleGetCustomer(long id) 
	{
		Customer cust=null;
		try{
			cust=storeModel.getCustomr(id);//調用StoreModel對象去數據庫獲取指定ID的人員數據
			storeView.showDisplay(cust);//通過StoreView顯示數據
		}catch(Exception e)
		{
			reportException(e);
			cust=new Customer(id);
			try{
				storeView.showDisplay(cust);
			}catch(Exception ex)
			{
				reportException(ex);
			}
		}
		
	}

	//處理添加人員的動作
	public void handleAddCustomerGesture(Customer cust) 
	{
		try{
			storeModel.addCustomer(cust);
		}catch(Exception e)
		{
			reportException(e);
		}
		
	}

	//處理刪除人員的動作
	public void handleDeleteCustomerGesture(Customer cust)
	{

		try{
			storeModel.deleteCustomer(cust);
		}catch(Exception e)
		{
			reportException(e);
		}
	}

	//處理更新人員的動作
	public void handleUpdateCustomerGesture(Customer cust) 
	{
		

		try{
			storeModel.updateCustomer(cust);
		}catch(Exception e)
		{
			reportException(e);
		}
	}

	
	public void handleGetAllCustomer()
	{
		Set<Customer> customers=null;
		try{
			customers=storeModel.getAllCustomer();//通過StoreModel對象獲得所有人員信息
			storeView.showDisplay(customers);//通過StoreView顯示數據
		}catch(Exception e)
		{
			reportException(e);
		}
		
	}

}


StoreGui

package store;

import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionListener;
import java.util.Iterator;
import java.util.Set;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingConstants;
import javax.swing.table.DefaultTableModel;

public class StoreGui extends JFrame
{
	/**CardLayout 對象是容器的佈局管理器。
	 * 它將容器中的每個組件看作一張卡片。
	 * 一次只能看到一張卡片,容器則充當卡片的堆棧。
	 * 當容器第一次顯示時,第一個添加到 CardLayout 對象的組件爲可見組件。
	 * */
	private CardLayout card=new CardLayout();
	private JPanel carPanel=new JPanel();
	//包含各種按鈕的選擇面板上的組件
	private JPanel selPanel=new JPanel();
	private JButton custBt=new JButton("人員詳細信息");
	private JButton allCustBt=new JButton("所有人員清單");
	
	//顯示單個人員面板的組件
	private JPanel custPanel=new JPanel();
	private JLabel nameLb=new JLabel("姓名");
	private JLabel idLb=new JLabel("ID");
	private JLabel addrLb=new JLabel("地址");
	private JLabel ageLb=new JLabel("年齡");
	
	private JTextField nameTf=new JTextField(25);
	private JTextField idTf=new JTextField(25);
	private JTextField addrTf=new JTextField(25);
	private JTextField ageTf=new JTextField(25);
	private JButton getBt=new JButton("查詢人員");
	private JButton upBt=new JButton("更新人員");
	private JButton addBt=new JButton("添加人員");
	private JButton delBt=new JButton("刪除人員");
	
	//列舉所有人員的面板的組件
	private JPanel allCustPanel=new JPanel();
	private JLabel allCustLb=new JLabel("所有人員清單",SwingConstants.CENTER);//居中顯示
	private JTextArea allCustTa=new JTextArea();
	private JScrollPane allCustSp=new JScrollPane(allCustTa);
	
	//table頭
	String[]tableHeaders={"ID","姓名","地址","年齡"};
	JTable table;
	JScrollPane tablePane;
	DefaultTableModel tableModel;
	
	//日誌面板上的組件
	private JPanel logPanel=new JPanel();
	private JLabel logLb=new JLabel("操作日誌",SwingConstants.CENTER);
	private JTextArea logTa=new JTextArea(9,50);
	private JScrollPane logSp=new JScrollPane(logTa);
	
	public StoreGui()
	{
		buildDisplay();
	}
	public void refreshCustPanel(Customer cust)
	{
		showCard("Customer");
		if(cust==null||cust.getId()==-1)
		{
			idTf.setText(null);
			nameTf.setText(null);
			addrTf.setText(null);
			ageTf.setText(null);
			return;
		}
		else
		{
			idTf.setText(Long.toString(cust.getId()));
			nameTf.setText(cust.getName());
			addrTf.setText(cust.getAddr());
			ageTf.setText(Integer.toString(cust.getAge()));
		}
		
	}
	public void refreshAllCustPanel(Set<Customer> custs)
	{
		showCard("All customers");
		String newData[][]=new String[custs.size()][4];
		Iterator<Customer> iter=custs.iterator();
		int i=0;
		while(iter.hasNext())
		{
			Customer cust=iter.next();
			newData[i][0]=Long.toString(cust.getId());
			newData[i][1]=cust.getName();
			newData[i][2]=cust.getAddr();
			newData[i][3]=Integer.toString(cust.getAge());
			i++;
		}
		tableModel.setDataVector(newData, tableHeaders);
	}
	//在日誌面板中添加日誌信息
	public void updateLog(String msg)
	{
		logTa.append(msg+"\n");
	}
	public long getCustIdOnCustPanel()
	{
		try
		{
			return Long.parseLong(idTf.getText().trim());
	
		}catch(Exception e)
		{
			updateLog(e.getMessage());
			return -1;
		}
	}
	//獲得單個人員面板上用戶輸入的人員信息
	public Customer getCustomerOnCustPanel()
	{
		try
		{
			String custid=idTf.getText().trim();
			Long cid=custid.equals("")?0:Long.parseLong(custid);
			return new Customer(cid,
								nameTf.getText().trim(),
								addrTf.getText().trim(),
								Integer.parseInt(ageTf.getText().trim()));
		}catch(Exception e)
		{
			updateLog(e.getMessage());
			return null;
		}
	}
	private void showCard(String cardStr)
	{
		card.show(carPanel, cardStr);
	}
	/** 爲選擇面板中的兩個按鈕註冊監聽器*/
	public void addSelectionPanelListener(ActionListener a[])
	{
		int length=a.length;
		if(length!=2)
		{
			return;
		}
		else
		{
			custBt.addActionListener(a[0]);
			allCustBt.addActionListener(a[1]);
		}
	}
	/** 爲單個人員面板中的兩個按鈕註冊監聽器*/
	public void addCustPanelListener(ActionListener a[])
	{
		int length=a.length;
		if(length!=4)
		{
			return;
		}
		else
		{
			getBt.addActionListener(a[0]);
			addBt.addActionListener(a[1]);
			delBt.addActionListener(a[2]);
			upBt.addActionListener(a[3]);
		}
			
	}
	public static void main(String[]args)
	{
		new StoreGui().setVisible(true);;
		
	}
	//創建圖形界面
	private void buildDisplay()
	{
		setTitle("人員管理系統");
		buildSelectionPanel();
		buildCustPanel();
		buildAllCustPanel();
		buildLogPanel();
		
		/**carPanel採用cardLayout佈局管理器
		 * 包括custPanel和allCustPanel兩種卡片
		 * */
		carPanel.setLayout(card);
		carPanel.add(custPanel,"Customer");
		carPanel.add(allCustPanel,"All customers");
		this.setLayout(new BorderLayout());
		add(carPanel,BorderLayout.CENTER);
		add(selPanel,BorderLayout.NORTH);
		add(logPanel,BorderLayout.SOUTH);
		this.pack();
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
	}
	private void buildLogPanel()
	{
		logPanel.setLayout(new BorderLayout());
		logSp.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
		logSp.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
		logPanel.add(logLb,BorderLayout.NORTH);
		this.logPanel.add(logSp,BorderLayout.CENTER);
	}
	private void buildSelectionPanel()
	{
		selPanel.add(custBt);
		selPanel.add(allCustBt);
	}
	//創建單個人員面板
	private void buildCustPanel()
	{
		custPanel.setLayout(new GridLayout(6,2,2,2));
		custPanel.add(idLb);
		custPanel.add(idTf);
		custPanel.add(nameLb);
		custPanel.add(nameTf);
		custPanel.add(addrLb);
		custPanel.add(addrTf);
		custPanel.add(ageLb);
		custPanel.add(ageTf);
		custPanel.add(getBt);
		custPanel.add(upBt);
		custPanel.add(addBt);
		custPanel.add(delBt);
	}
	//創建所有人員面板
	private void buildAllCustPanel()
	{
		allCustPanel.setLayout(new BorderLayout());
		allCustPanel.add(allCustLb,BorderLayout.NORTH);
		allCustTa.setText("all customer display");
		tableModel=new DefaultTableModel(tableHeaders,10);
		table=new JTable(tableModel);
		tablePane=new JScrollPane(table);
		allCustPanel.add(tablePane,BorderLayout.CENTER);
		Dimension dim=new Dimension(500,150);
		table.setPreferredScrollableViewportSize(dim);
	}
}


客戶端程序入口

package store;

import java.rmi.RemoteException;

import javax.naming.Context;
import javax.naming.InitialContext;

public class StoreApp 
{
	public static void main(String[]args) throws RemoteException, StoreException
	{
		String url="rmi://localhost/";
		try{
			StoreModel model;
			StoreView view;
			StoreController ctrl;
			Context namingContext=new InitialContext();
			model=(StoreModel)namingContext.lookup(url+"storeModel");
			view=new StoreViewImpl(model);
			ctrl=new StoreControllerImpl(model,view);
		}catch(Exception e)
		{
			e.printStackTrace();
		}
	}
}


人員POJO

package store;

import java.io.Serializable;

public class Customer implements Serializable
{
	private long id;
	private String name="";
	private String addr="";
	private int age;
	public Customer(long id,String name,String addr,int age)
	{
		this.id=id;
		this.name=name;
		this.addr=addr;
		this.age=age;
	}
	public Customer(long id)
	{
		this.id=id;
	}
	public long getId()
	{
		return id;
	}
	public String getName()
	{
		return name;
	}
	public void setName(String name) 
	{
		this.name = name;
	}
	public String getAddr()
	{
		return addr;
	}
	public void setAddr(String addr)
	{
		this.addr = addr;
	}
	public int getAge()
	{
		return age;
	}
	public void setAge(int age) 
	{
		this.age = age;
	}
	public String toString()
	{
		return "Customer: "+id+" "+name+" "+addr+" "+age;
	}
}


模型層接口以及具體實現

package store;
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.util.Set;

public interface StoreModel extends Remote
{
	/**註冊視圖,以便當模型修改了數據庫中的人員信息時可以回調視圖的刷新界面方法*/
	public void addChangeListener(StoreView sv)throws StoreException,RemoteException;
	/**向數據庫中添加一個新的人員*/
	public void addCustomer(Customer cust)throws StoreException,RemoteException;
	/**向數據庫中刪除一個新的人員*/
	public void deleteCustomer(Customer cust)throws StoreException,RemoteException;
	/**更新數據庫中的人員*/
	public void updateCustomer(Customer cust)throws StoreException,RemoteException;
	/**根據參數ID檢索*/
	public Customer getCustomr(long id)throws StoreException,RemoteException;
	/**返回所有人員*/
	public Set<Customer> getAllCustomer()throws StoreException,RemoteException;
}


package store;

import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;

public class StoreModelImpl extends UnicastRemoteObject implements StoreModel
{
	private ArrayList<StoreView> changeListeners=new ArrayList<StoreView>(10);
	private DBService dbService;
	
	protected StoreModelImpl() throws RemoteException,StoreException 
	{
		super();
		try{
			dbService=new DBServiceImpl();
		}catch(Exception e)
		{
			throw new StoreException("數據庫異常");
		}
	}
	/**判斷數據庫中是否存在參數指定的人員ID*/
	protected boolean idExists(long id)
	{
		Statement stmt=null;
		try{
			stmt=dbService.getStatement();
			ResultSet result=stmt.executeQuery("select ID from customers where ID="+id);
			return result.next();
		}catch(Exception e)
		{
			return false;
		}finally
		{
			dbService.closeStatement(stmt);
		}
	}
	/**註冊視圖,以便當模型修改了數據庫中的人員信息時可以回調視圖的刷新界面的方法*/
	public void addChangeListener(StoreView sv) throws StoreException,
			RemoteException {
		
		changeListeners.add(sv);
	}

	/**當數據庫中人員信息發生變化時,同步刷新所有視圖*/
	private void fireModelChangeEvent(Customer cust)
	{
		StoreView v;
		for(int i=0;i<changeListeners.size();i++)
		{
			try{
				v=changeListeners.get(i);
				v.handleCustomerChange(cust);
			}catch(Exception e)
			{
				System.out.println(e.toString());
			}
		}
	}
	//向數據庫中添加一個新的人員
	public void addCustomer(Customer cust) throws StoreException,
			RemoteException {
		try {
			String sql="insert into customers values(0,'"+cust.getName()+"',"+cust.getAge()+",'"+cust.getAddr()+"')";
			dbService.modifyTable(sql);
			fireModelChangeEvent(cust);
			
		} catch (Exception e)
		{
			throw new StoreException("StoreModelImpl.addCustomer\n"+e);
		}
	}

	//向數據庫中刪除一個新的人員
	public void deleteCustomer(Customer cust) throws StoreException,
			RemoteException {
		
		try {
			String sql="delete from customers where id="+cust.getId();
			dbService.modifyTable(sql);
			fireModelChangeEvent(new Customer(cust.getId()));
			
		} catch (Exception e)
		{
			throw new StoreException("StoreModelImpl.deleteCustomer\n"+e);
		}
		
	}

	//向數據庫中更新一個新的人員
	public void updateCustomer(Customer cust) throws StoreException,
			RemoteException {
		try{
			if(!idExists(cust.getId()))
			{
				throw new StoreException("Customer "+cust.getId()+"Not Found");
			}
			
			String sql="update customers set "
						+"name='"+cust.getName()+
						"',age="+cust.getAge()+
						",address='"+cust.getAddr()+
						"'where id="+cust.getId();
			dbService.modifyTable(sql);
			fireModelChangeEvent(cust);//同步刷新所有視圖
		}catch(Exception e)
		{
			throw new StoreException("StoreModelImpl.updateCustomer\n"+e);
		}
		
	}

	/**根據ID檢索人員*/
	public Customer getCustomr(long id) throws StoreException, RemoteException {
		Statement stmt=null;
				try{
					if(!idExists(id))
					{
						throw new StoreException("Customer "+id+"Not Found");
					}
					stmt=dbService.getStatement();
					ResultSet rs=stmt.executeQuery("select id,name,address,age from customers where id="+id);
					rs.next();
					return new Customer(rs.getLong(1),rs.getString(2),rs.getString(3),rs.getInt(4));
				}catch(Exception e)
				{
					throw new StoreException("StoreDbImpl.getCustomer\n"+e);
				}finally
				{
					dbService.closeStatement(stmt);
				}
	}

	
	public Set<Customer> getAllCustomer() throws StoreException,
			RemoteException {
		Statement stmt=null;
		try{
			stmt=dbService.getStatement();
			ResultSet rs=stmt.executeQuery("select id,name,address,age from customers");
			Set<Customer> custSet=new HashSet<Customer>();
			Customer cust;
			while(rs.next())
			{
				cust=new Customer(rs.getLong(1),rs.getString(2),rs.getString(3),rs.getInt(4));
				custSet.add(cust);
			}
			return custSet;
		}catch(Exception e)
		{
			throw new StoreException("StoreDbImpl.getAllCustomer\n"+e);
		}finally
		{
			dbService.closeStatement(stmt);
		}
	}

}

服務端程序入口

package store;

import java.rmi.RMISecurityManager;
import javax.naming.Context;
import javax.naming.InitialContext;
public class StoreServer 
{
	public static void main(String[]args)
	{
		try
		{
			//System.setProperty("java.security.policy",StoreServer.class.getResource("client.policy").toString());
			//System.setSecurityManager(new RMISecurityManager());
			StoreModel storeModel=new StoreModelImpl();		
			Context namingContext=new InitialContext();
			
			namingContext.rebind("rmi://localhost:1099/storeModel",storeModel);
			System.out.println("註冊了1個對象");
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
	}
}


模型層使用的數據庫連接池

package store;

import java.sql.Connection;
import java.sql.SQLException;

public interface ConnectionPool
{
	/**
	 * 連接池接口,其中聲明瞭取出連接、釋放鏈接和關閉連接的方法*/
	/**從連接池中取出連接*/
	public Connection getConnection()throws SQLException;
	/**把連接放回連接池*/
	public void releaseConnection(Connection con)throws SQLException;
	/**關閉連接池*/
	public void close();
}


通過動態代理實現ConnectionPool

package store;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Iterator;

public class ConnectionPoolImpl implements ConnectionPool{

	private ConnectionProvider provider=new ConnectionProvider();
	private final ArrayList<Connection> pool=new ArrayList<Connection>();
	private int poolSize=10;
	
	public ConnectionPoolImpl(){}
	public ConnectionPoolImpl(int poolSize)
	{
		this.poolSize=poolSize;
	}
	/**從連接池中取出連接*/
	public Connection getConnection() throws SQLException 
	{
		synchronized(pool)//採用同步鎖控制連接池
		{
			if(!pool.isEmpty())
			{
				int last=pool.size()-1;
				Connection con=pool.remove(last);
				return con;
			}
		}
		Connection con=provider.getConnection();
		return getProxy(con,this);
	}
	

	/**把連接放回連接池*/
	public void releaseConnection(Connection con) throws SQLException {
		synchronized(pool)
		{
			int currSize=pool.size();
			if(currSize<poolSize)
			{
				pool.add(con);
				//System.out.println(con.getClass().getName());
				return;
			}
			
		}
		try{
			closeJdbcConnection(con);
		}catch(Exception e)
		{
			e.printStackTrace();
		}

	}
	private void closeJdbcConnection(Connection con)throws SQLException{
		ConnectionP conP=(ConnectionP)con;
		conP.getJdbcConnection().close();
	}
	protected void finalize()//垃圾回收時可能會調用
	{
		close();
	}
	/**關閉連接池*/
	public void close()
	{
		Iterator<Connection> iter=pool.iterator();
		while(iter.hasNext())
		{
			try{
				closeJdbcConnection(iter.next());//關閉真正的數據庫連接
			}catch(SQLException e)
			{
				e.printStackTrace();
			}
		}
		pool.clear();
	}
	/**返回動態連接代理*/
	private Connection getProxy(final Connection con,final ConnectionPool pool)
	{
		InvocationHandler handle=new InvocationHandler()
		{

			public Object invoke(Object proxy, Method method, Object[] args)
					throws Throwable {
				if(method.getName().equals("close"))
				{
					//System.out.println("代理類"+proxy.getClass().getName()+"調用releaseConnection()");
					pool.releaseConnection((Connection)proxy);
					return null;
				}
				else if(method.getName().equals("getJdbcConnection"))
				{
					return con;
				}
				else
				{
					return method.invoke(con, args);
				}
			}
			
		};
		return (Connection)Proxy.newProxyInstance(ConnectionP.class.getClassLoader(),new Class[]{ConnectionP.class},handle);
	}
	interface ConnectionP extends Connection
	{
		public Connection getJdbcConnection();//返回被代理的Connection對象
	}

}


獲取數據庫連接配置信息的類

package store;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class ConnectionProvider
{
	private String JDBC_DRIVER;
	private String DB_URL;
	private String DB_USER;
	private String DB_PASSWORD;
	public ConnectionProvider()
	{
		this.JDBC_DRIVER=PropertyReader.get("JDBC_DRIVER");
		this.DB_URL=PropertyReader.get("DB_URL");
		this.DB_USER=PropertyReader.get("DB_USER");
		this.DB_PASSWORD=PropertyReader.get("DB_PASSWORD");
		try
		{
			Class.forName(JDBC_DRIVER);
		}catch(Exception e)
		{
			e.printStackTrace();
		}
	}
	public Connection getConnection() throws SQLException
	{
		return DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD);
	}
}


加載db.conf配置文件

package store;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

public class PropertyReader 
{
	private static Properties ps;
	static
	{
		ps=new Properties();
		InputStream in=PropertyReader.class.getResourceAsStream("db.conf");
		try 
		{
			ps.load(in);
			in.close();
		} catch (IOException e) 
		{
			
			e.printStackTrace();
		}
		
		
	}
	public static String get(String key)
	{
		return (String)ps.get(key);
	}
}


最後效果圖:




發佈了55 篇原創文章 · 獲贊 9 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章