Server
package com.csu.marden;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
private static final int PORT=44444;
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(PORT);
while(true){
try {
//服务器监听44444端口
Socket socket = serverSocket.accept();
//建立与客户端的连接
new JabberConnection(socket,new JabberDatabase()).start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
JabberConnection
package com.csu.marden;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.ArrayList;
public class JabberConnection extends Thread{
private Socket socket;
private JabberDatabase jabberDatabase;
public JabberConnection(Socket socket, com.csu.marden.JabberDatabase jabberDatabase) {
this.socket = socket;
this.jabberDatabase = jabberDatabase;
}
@Override
public void run() {
//客户端与服务器之间的通信载体是JabberMessage,所以服务端通过对象流读入/写出对象信息
try {
//对象输入流和输出流
ObjectInputStream ois=new ObjectInputStream(socket.getInputStream());
ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
//Jabber请求
JabberMessage request = (JabberMessage) ois.readObject();
//Jabber响应
JabberMessage response=new JabberMessage("");
//请求中的信息
String requestMessage = request.getMessage();
//对应的协议
String protocol="";
//协议后的信息
String data="";
//字符串处理
int index=requestMessage.indexOf(" ");
//字符串中没有空格
if(index==-1){
protocol=requestMessage;
}else{
protocol=requestMessage.substring(0,index);
data=requestMessage.substring(index+1,requestMessage.length());
}
//判断登陆(根据用户名判断)
if(protocol.equals("signin")){
//登陆成功
if(jabberDatabase.getUserID(data)!=-1){
response=new JabberMessage("signedin");
}else{
response=new JabberMessage("unknown-user");
}
}
//判断注册(默认邮箱地址为空)
if(protocol.equals("register")){
System.out.println(data);
jabberDatabase.addUser(data, "aaa@qq.com"); //输入邮箱
response=new JabberMessage("signedin");
}
//判断退出
if(protocol.equals("signout")){
socket.close();
}
//判断获取时间线(新增方法,获取用户关注的人,以及所发帖子内容,帖子编号,点赞人数)
if(protocol.equals("timeline")){
ArrayList<ArrayList<String>> list=jabberDatabase.getTimelineOfUserEx("kim"); //输入用户名
response=new JabberMessage("timeline",list);
}
//判断未关注的人员
if(protocol.equals("users")){
ArrayList<ArrayList<String>> list=jabberDatabase.getUsersNotFollowed(1); //输入用户id
response=new JabberMessage("users",list);
}
//判断发帖
if(protocol.equals("post")){
jabberDatabase.addJab("marden", data); //输入用户名
response=new JabberMessage("posted");
}
//判断点赞
if(protocol.equals("like")){
jabberDatabase.addLike(1, Integer.parseInt(data)); //输入用户id
response=new JabberMessage("posted");
}
//判断关注
if(protocol.equals("follow")){
jabberDatabase.addFollower(1, data); //输入用户id
response=new JabberMessage("posted");
}
//将消息写出到对象输出流
oos.writeObject(response);
} catch (IOException e) {
e.printStackTrace();
}catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Client
package com.csu.marden;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
public class Client {
public static void main(String[] args) throws UnknownHostException, IOException, ClassNotFoundException {
Socket socket = new Socket("192.168.1.8",44444);
//对象输入流和输出流
ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
ObjectInputStream ois=new ObjectInputStream(socket.getInputStream());
JabberMessage request=new JabberMessage("follow marden");
oos.writeObject(request);
JabberMessage response=(JabberMessage) ois.readObject();
System.out.println(response.getMessage()+":"+response.getData());
ois.close();
oos.close();
socket.close();
}
}
JabberDatabase
package com.csu.marden;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
public class JabberDatabase {
private static String dbcommand = "jdbc:mysql://localhost:3306/full_stack_assignment1";
private static String db = "root";
private static String pw = "root";
private Connection conn;
/**
* Returns the current database connection.
* @return the database connection.
*/
public Connection getConnection() {
return conn;
}
//修改useridb-------------->useridB
/**
* This method returns a list of the userids of users following the user with the userid in the parameter.
* @param userid the userid of the user.
* @return a list of the userids of users following the user.
*/
public ArrayList<String> getFollowerUserIDs(int userid) {
ArrayList<String> ret = new ArrayList<String>();
try {
PreparedStatement stmt = conn.prepareStatement("select userida from follows where useridB = ?");
stmt.setInt(1, userid);
ResultSet rs = stmt.executeQuery();
while (rs.next()) {
ret.add(rs.getObject("userida").toString());
}
} catch (SQLException e) {
e.printStackTrace();
}
return ret;
}
//修改userida-------------->useridA
/**
* This method returns a list of the userids of users being followed by the user in the parameter.
* @param userid The userid of the user.
* @return a list of the userids of users being followed by the user.
*/
public ArrayList<String> getFollowingUserIDs(int userid) {
ArrayList<String> ret = new ArrayList<String>();
try {
PreparedStatement stmt = conn.prepareStatement("select useridb from follows where useridA = ?");
stmt.setInt(1, userid);
ResultSet rs = stmt.executeQuery();
while (rs.next()) {
ret.add(rs.getObject("useridb").toString());
}
} catch (SQLException e) {
e.printStackTrace();
}
return ret;
}
//修改userida-------------->useridA,修改useridb-------------->useridB
/**
* This method returns a list of pairs of users who follow each other. Each pair is only listed once.
* @return a list of 'mutual' follows, i.e. users who follow each other.
*/
public ArrayList<ArrayList<String>> getMutualFollowUserIDs() {
ArrayList<ArrayList<String>> ret = new ArrayList<ArrayList<String>>();
try {
PreparedStatement stmt = conn.prepareStatement("select f1.useridA, f1.useridB from follows f1 inner join follows f2 on f1.useridA = f2.useridB and f1.useridB = f2.useridA");
ResultSet rs = stmt.executeQuery();
while (rs.next()) {
ArrayList<String> r = new ArrayList<String>();
r.add(rs.getObject("userida").toString());
r.add(rs.getObject("useridb").toString());
ret.add(r);
}
} catch (SQLException e) {
e.printStackTrace();
}
return removeDuplicates(ret);
}
//修改userida-------------->useridA,修改useridb-------------->useridB
/**
* This method returns a list of the usernames of users not followed by the user with the userid in the parameter.
* @param userid the userid of the user.
* @return a list of the usernames of users not followed by the user.
*/
public ArrayList<ArrayList<String>> getUsersNotFollowed(int userid) {
ArrayList<ArrayList<String>> ret = new ArrayList<ArrayList<String>>();
try {
PreparedStatement stmt = conn.prepareStatement("select username from jabberuser where userid not in (select useridB from follows where useridA = ?)");
stmt.setInt(1, userid);
ResultSet rs = stmt.executeQuery();
while (rs.next()) {
ArrayList<String> r = new ArrayList<String>();
r.add(rs.getObject("username").toString());
ret.add(r);
}
} catch (SQLException e) {
e.printStackTrace();
}
return ret;
}
/**
* This method returns list of [username, jabtext] pairs of jabs liked by the user.
* @param userid the userid of the user.
* @return a list of [username, jabtext] pairs of the jabs liked by the user.
*/
public ArrayList<ArrayList<String>> getLikesOfUser(int userid) {
ArrayList<ArrayList<String>> ret = new ArrayList<ArrayList<String>>();
try {
PreparedStatement stmt = conn.prepareStatement("select username, jabtext from jab natural join jabberuser where jabid in (select jabid from likes where userid = ?)");
stmt.setInt(1, userid);
ResultSet rs = stmt.executeQuery();
while (rs.next()) {
ArrayList<String> r = new ArrayList<String>();
r.add(rs.getObject("username").toString());
r.add(rs.getObject("jabtext").toString());
ret.add(r);
}
} catch (SQLException e) {
e.printStackTrace();
}
return ret;
}
/**
* This method returns the timeline of the user as [username, jabtext] pairs.
* @param username the username of the user.
* @return the timeline of the user.
*/
@Deprecated
public ArrayList<ArrayList<String>> getTimelineOfUser(String username) {
int userid = this.getUserID(username);
if (userid >= 0) {
return getTimelineOfUser(userid);
}
return null;
}
/**
* This method returns the timeline of the user. Each jab in the returned list has the following
* data: [username, jabtext, jabid, number-of-likes].
* @param username the username of the user.
* @return the timeline of the user.
*/
public ArrayList<ArrayList<String>> getTimelineOfUserEx(String username) {
int userid = this.getUserID(username);
if (userid >= 0) {
return getTimelineOfUserEx(userid);
}
return null;
}
/**
* This method returns the timeline of the user as [username, jabtext] pairs.
* @param userid the userid of the user.
* @return the timeline of the user.
*/
@Deprecated
public ArrayList<ArrayList<String>> getTimelineOfUser(int userid) {
ArrayList<ArrayList<String>> ret = new ArrayList<ArrayList<String>>();
try {
PreparedStatement stmt = conn.prepareStatement("select username, jabtext from jab natural join jabberuser where userid in (select useridB from follows where useridA = ?)");
stmt.setInt(1, userid);
ResultSet rs = stmt.executeQuery();
while (rs.next()) {
ArrayList<String> r = new ArrayList<String>();
r.add(rs.getObject("username").toString());
r.add(rs.getObject("jabtext").toString());
ret.add(r);
}
} catch (SQLException e) {
e.printStackTrace();
}
return ret;
}
/**
* This method returns the timeline of the user. Each jab in the returned list has the following
* data: [username, jabtext, jabid, number-of-likes].
* @param userid the userid of the user.
* @return the timeline of the user.
*/
public ArrayList<ArrayList<String>> getTimelineOfUserEx(int userid) {
ArrayList<ArrayList<String>> ret = new ArrayList<ArrayList<String>>();
try {
PreparedStatement stmt = conn.prepareStatement("select username, jabtext, jabid, (select count(jabid) from likes A where A.jabid = B.jabid group by A.jabid) as jabcount from jab B natural join jabberuser where userid in (select useridB from follows where useridA = ?)");
stmt.setInt(1, userid);
ResultSet rs = stmt.executeQuery();
while (rs.next()) {
ArrayList<String> r = new ArrayList<String>();
r.add(rs.getObject("username").toString());
r.add(rs.getObject("jabtext").toString());
r.add(rs.getObject("jabid").toString());
if (rs.getObject("jabcount") != null) {
r.add(rs.getObject("jabcount").toString());
}
else r.add("0");
ret.add(r);
}
} catch (SQLException e) {
e.printStackTrace();
}
return ret;
}
/**
* This method adds a jab from the user username.
* @param username the username of the user.
* @param jabtext the text of the jab.
*/
public void addJab(String username, String jabtext) {
int userid = getUserID(username);
int jabid = getNextJabID();
try {
PreparedStatement stmt = conn.prepareStatement("insert into jab (jabid,userid,jabtext) values (?,?,?)");
stmt.setInt(1, jabid);
stmt.setInt(2, userid);
stmt.setString(3, jabtext);
stmt.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}
}
/**
* This method adds a new user to the platform.
* @param username the username of the new user.
* @param emailadd the email address of the new user.
*/
public void addUser(String username, String emailadd) {
int newid = getNextUserID();
try {
PreparedStatement stmt = conn.prepareStatement("insert into jabberuser (userid,username,emailadd) values(?,?,?)");
stmt.setInt(1, newid);
stmt.setString(2, username);
stmt.setString(3, emailadd);
stmt.executeUpdate();
//addFollower(newid, newid);
} catch (SQLException e) {
e.printStackTrace();
}
}
/**
* This method adds a new follows relationship between users: the user userida follows the user useridb.
* @param userida the user who is doing the following.
* @param useridb the user being followed.
*/
public void addFollower(int userida, int useridb) {
try {
PreparedStatement stmt = conn.prepareStatement("insert into follows (values(?,?))");
stmt.setInt(1, userida);
stmt.setInt(2, useridb);
stmt.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}
}
/**
* This method adds a new follows relationship between users: userida follows user username.
* @param userida the user whow is doing the following.
* @param username the username of the user being followed.
*/
public void addFollower(int userida, String username) {
int useridb = this.getUserID(username);
if (useridb < 0) {
return;
}
try {
PreparedStatement stmt = conn.prepareStatement("insert into follows (useridA,useridB) values (?,?)");
stmt.setInt(1, userida);
stmt.setInt(2, useridb);
stmt.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}
}
/**
* This method adds a new like: the user with user id userid likes the jab with jab id jabid.
* @param userid the user.
* @param jabid the jab.
*/
public void addLike(int userid, int jabid) {
try {
PreparedStatement stmt = conn.prepareStatement("insert into likes (userid,jabid) values (?,?)");
stmt.setInt(1, userid);
stmt.setInt(2, jabid);
stmt.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}
}
/**
* This method returns a list of users with the most followers.
* @return a list of the users with the most followers.
*/
public ArrayList<String> getUsersWithMostFollowers() {
ArrayList<String> ret = new ArrayList<String>();
String query = "select useridb from follows group by useridb having count (useridb) >= all (select count(useridb) from follows group by useridb order by count(useridb));";
try {
PreparedStatement pstmt = conn.prepareStatement(query);
ResultSet rs = pstmt.executeQuery();
while (rs.next()) {
ret.add(rs.getObject("useridb").toString());
}
} catch (SQLException e) {
e.printStackTrace();
}
return ret;
}
private int getNextJabID() {
int maxid = -1;
try {
PreparedStatement stmt = conn.prepareStatement("select max(jabid) from jab");
ResultSet rs = stmt.executeQuery();
while (rs.next()) {
maxid = rs.getInt(1); // only one result.
}
} catch (SQLException e) {
e.printStackTrace();
}
if (maxid < 0) {
return maxid;
}
return maxid + 1;
}
/**
* A convenience method to get the userid of the user with user name username.
* @param username the username of the user.
* @return the userid of the user.
*/
public int getUserID(String username) {
int ret = -1;
try {
PreparedStatement stmt = conn.prepareStatement("select userid from jabberuser where username = ?");
stmt.setString(1, username);
ResultSet rs = stmt.executeQuery();
while (rs.next()) {
ret = rs.getInt(1); // only one result anyway.
}
} catch (SQLException e) {
e.printStackTrace();
}
return ret;
}
public int getNextUserID() {
String query = "select max(userid) from jabberuser";
int maxid = -1;
try (PreparedStatement stmt = conn.prepareStatement(query)) {
ResultSet rs = stmt.executeQuery();
while (rs.next()) {
maxid = rs.getInt(1);
}
} catch (SQLException e) {
e.printStackTrace();
}
if (maxid < 0) {
return maxid;
}
return maxid + 1;
}
private ArrayList<ArrayList<String>> removeDuplicates(ArrayList<ArrayList<String>> list) {
for (ArrayList<String> l: list) {
Collections.sort(l);
}
ArrayList<ArrayList<String>> ret = new ArrayList<ArrayList<String>>();
ret.add(list.get(0));
for (ArrayList<String> l: list) {
if (!ret.contains(l)) {
ret.add(l);
}
}
return ret;
}
/**
* Default constructor. Connects to the database.
*/
public JabberDatabase() {
connectToDatabase();
//resetDatabase();
}
/**
* Connects to the database. No need to call this as it is called by the default constuctor.
*/
public void connectToDatabase() {
try {
conn = DriverManager.getConnection(dbcommand,db,pw);
}catch(Exception e) {
e.printStackTrace();
}
}
}
JabberMessage
package com.csu.marden;
import java.io.Serializable;
import java.util.ArrayList;
public class JabberMessage implements Serializable{
private static final long serialVersionUID = 1L;
private String message;
private ArrayList<ArrayList<String>> response = new ArrayList<ArrayList<String>>();
public JabberMessage(String message) {
this.message = message;
response = null;
}
public JabberMessage(String message, ArrayList<ArrayList<String>> data) {
this.message = message;
response = data;
}
public ArrayList<ArrayList<String>> getData() {
return response;
}
public String getMessage() {
return message;
}
}