一、项目需求介绍
应用Java RMI构建一个分布式议程服务(Agenda Service)。不同的客户应能连接到这一共享的议程服务,并查询、添加和删除议程中的会晤(meeting)安排。服务程序应具备新用户注册、清除某一用户所有会晤安排等管理功能。
(1)功能要求
功能1、用户注册:
注册新用户,用户设置一个唯一的用户名以及一个对应密码。如果注册时提供的用户名已由其他用户使用,应反馈出错信息;成功注册后,反馈成功注册的信息。
功能2、添加议程:
已注册的用户可以添加一个新议程到其议程安排中。规定议程仅允许在两个已注册的用户间举行,不可创建无另一已注册用户的议程。 添加议程时提供的信息应包括:议程的起始时间start time和终止时间end time、描述本次议程的标签title、以及预约的另一用户名字otherUser。 成功添加议程后,它应既出现在发起该议程的用户的议程中,也应出现在该议程所预约的另一用户的议程中。 注意,用户不允许分身参加多个议程,即如果用户自己或被预约的用户已有一个议程安排与新议程在时间上相互重叠(冲突),该新议程将无法成功添加到议程管理系统中。 用户在添加议程后,获得适当的反馈信息以得知是成功地添加了新议程还是在添加过程出现了某些错误。
功能3、查询议程:
已注册的用户可以查询自己的议程中某一时间段(time interval)的所有议程安排。查询议程时提供的参数应包括所关注时间段的起始时间和终止时间; 查询结果返回该用户议程中在指定时间范围内找到的所有议程安排的列表, 在列表中给出每一议程的起始时间、终止时间、标签、以及被预约的另一用户的名字。
功能4、删除议程:
已注册的用户可以删除自己登记的某一议程安排。删除议程时,提供的参数除执行删除功能的用户的名字及其密码外, 还包括一个能惟一地标识待删除的议程的参数。
功能5、清除议程:
已注册的用户可以清除自己创建的所有议程安排。
(2)接口约定
客户程序通过命令行参数访问远程服务,客户端各功能的命令格式如下:
注册用户命令:
register:java client [localhost] [1099] register [username] [password]
添加议程命令:
add:java client [localhost] [1099] add [username] [password] [ScheduleUser] [label] [start] [end] [tile]
查询议程命令:
query:java client [localhost] [1099] query [username] [password] [start] [end]
删除议程命令:
delete:java client [localhost] [1099] clear [username] [password] [meetingid]
清空议程命令:
clear:java client [localhost] [1099] clear [username] [password]
二、项目设计
三、源代码
1.首先定义服务接口
package Meetingrmi;
/*define remote interface
* @author basara
* */
import java.rmi.*;
import java.sql.SQLException;
public interface ServiceInterface extends Remote {
public boolean register(String userName, String password) throws RemoteException, SQLException;
public boolean add(String userName, String password, String schedule_user, String title, String label, String startTime, String endTime) throws RemoteException;
public String[] query(String userName, String start, String end) throws RemoteException, SQLException;
public boolean delete(String userName, int meetingID) throws RemoteException, SQLException;
public boolean clear(String userName) throws RemoteException;
}
2.然后实现上述接口,定义操作数据库的具体方法
package Meetingrmi;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
@SuppressWarnings("serial")
public class ServiceImpl extends UnicastRemoteObject implements ServiceInterface {
public java.sql.Connection conn = null;
public java.sql.ResultSet rs = null;
java.sql.Statement st=null;
java.sql.Statement st1=null;
java.sql.Statement st2=null;
java.sql.Statement st3=null;
java.sql.Statement st4=null;
java.sql.Statement st5=null;
java.sql.Statement st6=null;
java.sql.Statement st7=null;
java.sql.Statement st8=null;
java.sql.Statement st9=null;
ResultSet a,b,c,d,e,f,g,h,i,j;
public ServiceImpl() throws RemoteException {
try {
//注册驱动
//com.microsoft.sqlserver.jdbc.SQLServerDriver
//Class.forName("org.objectweb.rmijdbc.Driver").newInstance();
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver").newInstance();
//创建数据库连接
String url = "jdbc:sqlserver://localhost:1433;"+"DatabaseName=MeetingManager;UserName = sa;PassWord = 123";
//创建执行对象
conn = DriverManager.getConnection(url);
st = conn.createStatement();
st1 = conn.createStatement();
st2 = conn.createStatement();
st3 = conn.createStatement();
st4 = conn.createStatement();
st5 = conn.createStatement();
st6 = conn.createStatement();
st7 = conn.createStatement();
st8 = conn.createStatement();
st9 = conn.createStatement();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public int register(String sql){
int num=0;
try{
num=st.executeUpdate(sql);
}
catch(SQLException e){}
return num;
}
public ResultSet query(String sql){
rs=null;
try{
rs=st.executeQuery(sql);
}
catch(SQLException e){
e.printStackTrace();
}
return rs;
}
public int add(String sql){
int num=0;
try{
num=st.executeUpdate(sql);
}catch(SQLException e){}
return num;
}
public int delete(String sql){
int num=0;
try{
num=st.executeUpdate(sql);
}
catch(SQLException e){}
//CloseDataBase();
return num;
}
public int clearAll(String sql){
int num=0;
try{
num=st.executeUpdate(sql);
}
catch(SQLException e){}
//CloseDataBase();
return num;
}
public void CloseDataBase(){
try{
conn.close();
st.close();
}
catch(Exception e){}
}
// add a meeting
@Override
public boolean add(String userName, String password, String schedule_user,
String title, String label, String startTime, String endTime) throws RemoteException {
boolean flag = false;
boolean flag1=true;
boolean flag2=true;
int meetingID = 0;
int rowCount=0;
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
Date startDate = null;
Date endDate = null;
try {
startDate = sdf.parse(startTime);
endDate = sdf.parse(endTime);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
a=st.executeQuery("select * from userinfo where userName='"+userName+"'");
j=st9.executeQuery("select * from userinfo where userName='"+schedule_user+"'");
if (a.next()&&j.next()) {
flag = true;
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// judge if user& schedule user have other meeting
try {
b=st1.executeQuery("select * from meeting where userName='"+userName+"'");
c=st2.executeQuery("select * from meeting where schedule_user='"+schedule_user+"'");
while(b.next()){
String StartString=b.getString(6);
String EndString=b.getString(7);
Date StartDate = sdf.parse(StartString);
Date EndDate = sdf.parse(EndString);
if((startDate.getTime()<=StartDate.getTime()&&endDate.getTime()>=StartDate.getTime())||
(startDate.getTime()<=EndDate.getTime()&&endDate.getTime()>=EndDate.getTime())){
System.out.println("预约人的时间有冲突!");//与user的时间冲突
flag1=false;
break;
}
}
while(c.next()){
String schedule_StartString=c.getString(6);
String schedule_EndString=c.getString(7);
Date schedule_StartDate = sdf.parse(schedule_StartString);
Date schedule_EndDate = sdf.parse(schedule_EndString);
if((startDate.getTime()<=schedule_StartDate.getTime()&&endDate.getTime()>=schedule_StartDate.getTime())||
(startDate.getTime()<=schedule_EndDate.getTime()&&endDate.getTime()>=schedule_EndDate.getTime()))
{
System.out.println("参会者的时间有冲突!");//与anotherUser的时间冲突
flag2=false;
break;
}
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if(flag&&flag1&&flag2){
try {
i=st8.executeQuery("select * from meeting");
while(i.next())
{
rowCount++;
}
meetingID=rowCount+1;
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String sql = "insert into meeting(meetingID,userName,schedule_user,title,label,startTime,endTime) values("
+meetingID+",'"+userName+"','"+schedule_user+"','"+title+"','"+label+"','"+startTime+"','"+endTime+"')";
add(sql);
System.out.println("增加会议成功!会议ID:" + meetingID);
return true;
}
else{
System.out.println("客户尚未预约或存在时间冲突!");
return false;
}
}
// clean all
@Override
public boolean clear(String userName) throws RemoteException {
boolean flag = false;
try {
d=st3.executeQuery("select * from userinfo where userName='"+userName+"'");
} catch (SQLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try {
if (d.next()) {
System.out.println("操作人已注册!");
flag = true;
}
} catch (SQLException e) {e.printStackTrace();}
if (flag) {
String sql="delete from meeting where userName='"+userName+"'";
clearAll(sql);
System.out.println(userName+"创建的会议已被清除!");
return true;
}
else {
System.out.println("操作人未注册!");
return false;
}
}
//delete a meeting
public boolean delete(String userName, int meetingID) throws RemoteException, SQLException {
boolean flag = false;
try {
e=st4.executeQuery("select * from userinfo where userName='"+userName+"'");
} catch (Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try {
if (e.next()) {
System.out.println("操作人已注册!");
flag = true;
}
} catch (SQLException e) {e.printStackTrace();}
if (flag) {
String sql="delete from meeting where userName='"+userName+"' and meetingID='"+meetingID+"'";
delete(sql);
System.out.println(userName+"创建的ID为"+meetingID+"的会议已被清除!");
return true;
}
else {
System.out.println("操作人未注册或密码错误!");
return false;}
}
//query meeting
@Override
public String[] query(String userName, String start, String end) throws RemoteException,SQLException {
boolean flag = false;
SimpleDateFormat sdf=new SimpleDateFormat("yy-MM-dd");
try {
f=st5.executeQuery("select * from userinfo where userName='"+userName+"'");
} catch (SQLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
String[] s = new String[100];
if (f.next()) {
System.out.println("操作人已注册!");
flag = true;
}
if (flag) {
Date startDate = null;
Date endDate = null;
try {
startDate = sdf.parse(start.trim());
endDate = sdf.parse(end.trim());
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String sql="select * from meeting where userName='"+userName+"'or schedule_user = '"+userName+"'and startTime>='"+startDate.toLocaleString()+"' and endTime<='"+endDate.toLocaleString()+"'";
try {
g=st6.executeQuery(sql);
} catch (SQLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
int i=0;
while (g.next()) {
s[i]="ID:"+g.getInt(1)+" 参会人:<"+g.getString(2)+"&"+g.getString(3)+"> "+"Title:"+g.getString(4)+" Label:"+g.getString(5);
i++;
}
return s;
}
else{
System.out.println("操作人未注册!");
String[] err= new String[1];
err[0]="查询失败,请检查是否已注册!";
return err;
}
}
//register
@Override
public boolean register(String userName, String password) throws RemoteException, SQLException {
try {
h=st7.executeQuery("select * from userinfo where userName='"+userName+"'");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (h.next()) {
System.out.println("客户端注册失败!其所使用的用户名已经存在!");
return false;
}
else{
String sql="insert into userinfo(userName,password) values ('"+userName+"','"+password+"')";
register(sql);
System.out.println("客户端注册成功!");
return true;
}
}
}
3.服务端
package Meetingrmi;
/*server of RMI*/
import java.rmi.Naming;
import java.rmi.registry.LocateRegistry;
public class Server {
private static int PORT = 8099;
public static void main(String[] args) {
String registryURL = "rmi://localhost:"+PORT+"/RMIServer";
try {
ServiceImpl service = new ServiceImpl();
LocateRegistry.createRegistry(PORT);
Naming.bind(registryURL, service);
System.out.println("-->Service Started");
} catch (Exception e) {
System.out.println(e);
}
}
}
4.客户端
package Meetingrmi;
import java.util.Scanner;
import java.net.MalformedURLException;
import java.rmi.*;
import java.sql.SQLException;
public class Client
{
static String userName;
static String password;
static String schedule_user;
static String title; static String label;
static String startTime; static String endTime;
static int meetingID;
private static int PORT = 8099;
public static void main(String[] args)
{
System.out.println("请在“Client”后面添加命令!");
System.out.println("命令列表:");
System.out.println("-r register 注册用户");
System.out.println("-a add 添加会议");
System.out.println("-q query 查询相关会议");
System.out.println("-d delete 删除相关会议");
System.out.println("-c clear 清除某预约人的所有会议");
System.out.println("end 结束程序");
args = new String[100];
args[0]="start";
//SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
String registryURL = "rmi://localhost:"+PORT+"/RMIServer";
ServiceInterface service = null;
try {
service = (ServiceInterface)Naming.lookup(registryURL);
Scanner scan = new Scanner(System.in);
while(!args[0].equals("end")){
System.out.println("请输入命令:(例如: -a)");
args[0]=scan.nextLine();
if(args[0].equals("-r"))
{
System.out.print("请输入用户名: ");
userName = scan.nextLine();
System.out.print("请输入密码: ");
password = scan.nextLine();
if (service.register(userName, password)) {
System.out.println("注册成功!");
}else{
System.out.println("注册失败!您所使用的用户名已经存在!");
}
}
else if(args[0].equals("-a"))
{
System.out.println("请依次输入预约人、密码、其他参会人、会议主题、标签、起始时间和终止时间,用回车符分隔:");
userName = scan.nextLine(); password = scan.nextLine();
schedule_user = scan.nextLine(); title = scan.nextLine();
label = scan.nextLine(); startTime = scan.nextLine();
endTime = scan.nextLine();
if (service.add(userName, password, schedule_user, title, label, startTime,endTime)) {
System.out.println("预约成功!");
}
else {
System.out.println("预约失败!请检查:");
System.out.println("1、您是否已注册");
System.out.println("2、您或者其他参会人已有会议安排");
System.out.println("3、会议时间是否存在冲突");
}
}
else if(args[0].equals("-q"))
{
System.out.println("请依次输入查询人、起始时间和终止时间,用回车符分隔:");
userName = scan.nextLine();
startTime = scan.nextLine();
endTime = scan.nextLine();
String[] queryresult= new String[100];
queryresult = service.query(userName,startTime,endTime);
if(queryresult.length>=1&&queryresult[0] != null){
for(int i=0;i<queryresult.length;i++){
if(queryresult[i] != null){
System.out.println(queryresult[i]);
}
}
}
else
{System.out.println("未查询到相关会议信息!");}
}
else if(args[0].equals("-d"))
{
System.out.println("请依次输入预约人和会议ID,用回车符分隔:");
userName = scan.nextLine();
meetingID = scan.nextInt();
if(service.delete(userName,meetingID))
System.out.println("删除成功!");
else
System.out.println("请检查预约人或会议ID是否输入有误!");
}
else if(args[0].equals("-c"))
{
System.out.println("请输入预约人:");
userName = scan.nextLine();
if(service.clear(userName)){
System.out.println("清除完成!");}
else {
System.out.println("操作失败!");
}
}
else
{System.out.println("非法命令!");}
}
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NotBoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
附数据库中两张表:
本项目中使用SQLServer数据库,有交互性,基本的事件冲突判断都具有,不足之处在于只在本机上进行实验,未曾在两台主机之间进行测试。
特此分享,代码结构尚不完善,望各位大神不吝赐教,共同进步!