Socket 多线程 JDBC综合编程一服务器端编程

来源:互联网 发布:三星电视上不了网络 编辑:程序博客网 时间:2024/06/01 18:32

  这部分程序与上一篇是配套的,实现后台对数据库的管理操作和客户端对数据库的请求响应。

     1:实现对Derby数据库的增,删,查,改管理.

     2:实现服务器端对客户端请求的监听,对数据库进行操作,返回结果信息给客户端。


实现服务器端界面如下:

                                                                               

查询操作结果显示如下:

                                                                               


具体代码如下:

 import java.sql.*;
 import java.awt.*;
 import java.awt.event.*;
 import javax.swing.*;
 import java.net.*;
 import java.io.*;
 public class Server
 {
public static void  main(String args[])
{
JFrame server = new ConnectFrame();
server.show();
}
 }
 class ConnectFrame extends JFrame implements ActionListener
 {
  private String st1=null;
private String st2=null;
private String st3=null;
private String st4=null;
private String st5=null;

private String stt1=null;
private String stt2=null;
private String stt3=null;
private String stt4=null;
private String stt5=null;

// 定义驱动加载和数据库所需要使用的一些东西
// 加载驱动,连接到数据库,利用SQL生成Statement,操作数据库(若为查找:生成结果集,在结果集里面操作)
private final String URL = "jdbc:derby:MyDbTest;create=true";
private String SQL = "";
private JLabel user = new JLabel("服务器端",SwingConstants.CENTER);

private Connection con = null;
private Statement sm = null;
private ResultSet rs = null;
/*
输入向数据库待输入学生的信息,用于扩增数据库
*/
private JLabel namelabel = new JLabel("姓名:",SwingConstants.RIGHT);
private JTextField name = new JTextField(5);
 
private JLabel numlabel = new JLabel("学号:",SwingConstants.RIGHT);
private JTextField num = new JTextField(10);
 
private JLabel sexlabel = new JLabel("性别:",SwingConstants.RIGHT);
private JTextField sex = new JTextField(5);
 
private JLabel gradelabel = new JLabel("平均分:",SwingConstants.RIGHT);
private JTextField grade = new JTextField(5);
 
private JLabel majorlabel = new JLabel("专业:",SwingConstants.RIGHT);
private JTextField major = new JTextField(10);
 
private JButton submit = new JButton("提交信息");
 
/*
 输入对数据库可操作所需要的信息
*/
private JLabel operation = new JLabel("对数据库进行操作",SwingConstants.CENTER);
//这里SwingConstants.CENTER 表示文本在单行输入文本中的初始位置
private JLabel namelabel2 = new JLabel("姓名:",SwingConstants.RIGHT);
private JTextField name2 = new JTextField(5);
 
private JLabel numlabel2 = new JLabel("学号:",SwingConstants.RIGHT);
private JTextField num2 = new JTextField(10);
 
private JLabel sexlabel2 = new JLabel("性别:",SwingConstants.RIGHT);
private JTextField sex2 = new JTextField(5);
 
private JLabel gradelabel2 = new JLabel("平均分:",SwingConstants.RIGHT);
private JTextField grade2 = new JTextField(5);
 
private JLabel majorlabel2 = new JLabel("专业:",SwingConstants.RIGHT);
private JTextField major2 = new JTextField(10);
 
// 执行操作的各个按钮
private JButton select = new JButton("查询");
private JButton delete = new JButton("删除");
private JButton update = new JButton("更新");
 
 /*
 用于显示操作的结果
*/
private JLabel  resultlabel = new JLabel("操作数据库的结果如下",SwingConstants.CENTER);
private JTextArea resultarea = new JTextArea(20,80);
 
// 初始化各项操作,包括界面布局以及信息传送,接收和数据库操作。
public ConnectFrame()
{  
        setTitle("数据库管理程序");
        setSize(580,500);
               // 与数据库建立联系,不能在点击事件中执行
      try{  // 加载Derby数据库驱动类
                 Class.forName("org.apache.derby.jdbc.EmbeddedDriver");
          }catch(Exception ex)
          {
               System.out.println("加载驱动类,实现连接失败");
           }
          // 在启动数据库时,应该先建立一个表
     try
        {  // 注意:这里定义的长度,即为表中列属性的长度,不够的会用空格补,直接从数据库获得的字符串会含有空格,最好进行trim()处理
               SQL = "CREATE TABLE Student(name char(15),num char(15),sex char(2),grade double,major char(10))";
               con = DriverManager.getConnection(URL); //利用URL与本地数据库建立连接
               sm = con.createStatement(); // 生成Statement对象,用于对数据库进行操作
               sm.executeUpdate(SQL);  // executeUpdate() 执行SQL更新语句,主要包括update,delete,insert语句
               sm.close();
       }catch(SQLException e)
      {
           System.out.println("初次建立数据库表失败: "+e);
      }
 
          addWindowListener(new WindowAdapter(){ // 创建关闭窗口的事件监听器
                   public void windowClosing(WindowEvent e)
                 {
                     System.exit(0);
                 }
          });
        CreateView();
            // 开启服务器子线程,进行客户端的监听相应,而服务器是直接操作本地数据库的
    new Thread(new Runnable(){ // 这采用匿名内部类的方式进行,也可以自定义Thread子类,实现run()方法重载,然后利用子类对象开启子线程
                     ServerSocket serversocket = null;
                     Socket socket = null;
                     DataInputStream in = null;
    DataOutputStream out = null;
  public void run() //这里 客户端只能实现对数据库的:查询和注册
 {
// 根据嵌入的信息,判断客户端要进行的操作
try
{    // 子线程中操作数据库,需要自定义相关对象,加载驱动(这是为了避免与服务器自己操作产生冲突)
Class.forName("org.apache.derby.jdbc.EmbeddedDriver");
serversocket = new ServerSocket(8850); // 服务器绑定8850端口,作为与客户端交互窗口
while(true) // 死循环等待客户端请求
{
socket = serversocket.accept();

  in = new DataInputStream(socket.getInputStream());

out = new DataOutputStream(socket.getOutputStream());

String line = new String("");

line = in.readUTF(); // 读取流中的内容,如果没有消息,该线程会在此陷入死等的阻塞状态

// 客户端根据操作,发送给服务器的是完整的SQL语句,服务器端获取后直接对数据库进行操作(这里根据SQL语句首字母,判断是哪种操作)

if(line.charAt(0)== 'I')

{

Connection con = DriverManager.getConnection(URL);

Statement sm = con.createStatement();

sm.executeUpdate(line);

resultarea.setText(" 客户端插入数据成功");

sm.close();con.close();

}else if(line.charAt(0)== 'S')

{

Connection con = DriverManager.getConnection(URL);

Statement sm = con.createStatement();

ResultSet rs = sm.executeQuery(line);  //executeQuery():SQL查询语句执行后,返回结果集


String result = GetServerString(rs); // 自定义函数,实现对结果集的操作

out.writeUTF(result); // 将返回的结果,通过流返回给客户端

resultarea.setText(" 客户端查询数据成功");

rs.close();sm.close();con.close();

}else

{

System.out.println("数据传输有误!");

}

/*
数据传输,服务器做出的相应处理,要分类型操作。
*/

in.close();out.close();socket.close(); // 最好先释放由Socket对象创建的流对象

            }

     }catch(Exception e)

    {

System.out.println("服务器接受客户端数据处理失误!");

    }

}
 public String GetServerString(ResultSet rs)
{

String result = new String("");

 try{

 if(!rs.next()) // 如果结果集为空(rs.next()返回false)不发送信息给客户端

         {

  System.out.println("该表中无该同学信息!");

  resultarea.setText("该表中客户端请求同学信息!");

        }else

       {

do

{

String getname= rs.getString("name").trim(); // 利用数据库的列属性名,获得某一行某列的数据。

result += getname;  // 注意这里由于定时数据结构大小的问题,结果中可能含有空格,采用trim()除去空格影响

for(int i=1;i<=15-getname.length();++i)

result += " ";


result += rs.getString("num").trim();

for(int i=1;i<=8;++i)

result += " ";

// 直接getString()获得的字符串,如果原始指定太大,会有空格填充

result += rs.getString("sex").trim();

for(int i=1;i<=8;++i)

result += " ";


String getgrade = rs.getString("grade").trim();

result += getgrade;

for(int i=1;i<=15-getgrade.length();++i)

result += " ";

// 表中最后一个元素,后面有换行和空格符(trim()函数可以将其清除掉)

String getmajor = rs.getString("major").trim();

result += getmajor;

result += "\n";  // 获得一个元组数据后,换行获得下面的数据

        }while(rs.next());

        }

}catch(SQLException e)

{

System.out.println("封装的查询操作失败 : "+e);

}

return result ;

         }

      }).start();

}
 
public void CreateView()  //  创建视图界面
{

resultarea.setEditable(false);

resultarea.setLineWrap(false); // 不可以自动换行

 

Container layout = getContentPane();

layout.setLayout(null);

// 添加用于创建新成员相关信息的控件

layout.add(user);

user.setBounds(150,5,200,25);

 

layout.add(namelabel);

namelabel.setBounds(5,40,40,22);

layout.add(name);

name.setBounds(50,40,60,22);

 

layout.add(numlabel);

numlabel.setBounds(110,40,40,22);

layout.add(num);

num.setBounds(155,40,80,22);

 

layout.add(sexlabel);

sexlabel.setBounds(240,40,40,22);

layout.add(sex);

sex.setBounds(285,40,30,22);

 

layout.add(gradelabel);

gradelabel.setBounds(320,40,55,22);

layout.add(grade);

grade.setBounds(385,40,40,22);

 

layout.add(majorlabel);

majorlabel.setBounds(425,40,40,22);

layout.add(major);

major.setBounds(470,40,60,22);

 

layout.add(submit);

submit.setBounds(200,80,100,25);

 

// 添加修改数据库需要输入的信息

layout.add(operation);

operation.setBounds(175,135,150,25);

 

layout.add(namelabel2);

namelabel2.setBounds(5,180,40,22);

layout.add(name2);

name2.setBounds(50,180,60,22);

 

layout.add(numlabel2);

numlabel2.setBounds(110,180,40,22);

layout.add(num2);

num2.setBounds(155,180,80,22);

 

layout.add(sexlabel2);

sexlabel2.setBounds(240,180,40,22);

layout.add(sex2);

sex2.setBounds(285,180,30,22);

 

layout.add(gradelabel2);

gradelabel2.setBounds(320,180,55,22);

layout.add(grade2);

grade2.setBounds(385,180,40,22);

 

layout.add(majorlabel2);

majorlabel2.setBounds(425,180,40,22);

layout.add(major2);

major2.setBounds(470,180,60,22);

 

// 数据库执行操作的按钮

layout.add(select);

select.setBounds(100,225,60,25);

 

layout.add(delete);

delete.setBounds(220,225,60,25);

 

layout.add(update);

update.setBounds(340,225,60,25);

 

// 显示操作结果,这里操作都要分情况进行

layout.add(resultlabel);

resultlabel.setBounds(175,270,150,25);

 

JScrollPane scrollpane = new JScrollPane(resultarea);

layout.add(scrollpane);

scrollpane.setBounds(80,300,360,150);

 

// 设置监听事件 获取焦点先后

submit.addActionListener(this);

select.addActionListener(this);

delete.addActionListener(this);

update.addActionListener(this);

}
public void GetString()
{  // 获得服务器端操作数据库的信息

stt1 = name2.getText().trim();

stt2 = num2.getText().trim();

stt3 = sex2.getText().trim();

stt4 = grade2.getText().trim();

stt5 = major2.getText().trim();

}
public void Select(ResultSet rs)
{   // append()是在当前行后面添加字符串,setText()则是将全部设置为啥字符串显示 
   // append是后续添加,setText()是全盘修改为当下
try{

do

{ // 考虑如何排列整齐

String getname = rs.getString("name").trim();

resultarea.append(getname);

for(int i=1;i<=15-getname.length();++i)

resultarea.append(" ");


resultarea.append(rs.getString("num").trim());

for(int i=1;i<=8;++i)

resultarea.append(" ");

// 直接getString()获得的字符串,如果原始指定太大,会有空格填充

resultarea.append(rs.getString("sex").trim());

for(int i=1;i<=8;++i)

resultarea.append(" ");


String getgrade = rs.getString("grade").trim();

resultarea.append(getgrade);

for(int i=1;i<=15-getgrade.length();++i)

   resultarea.append(" ");

// 表中最后一个元素,后面有换行和空格符(trim()函数可以将其清除掉)

String getmajor = rs.getString("major").trim();

resultarea.append(getmajor+"\n");

    }while(rs.next());  // 这里不能用while,会导致第一个无法输出,因为前面if判断

}catch(SQLException e)

{

System.out.println("封装的查询操作失败 : "+e);

}

}
public void Delete(String SQL)
{

try

{

sm = con.createStatement();

sm.executeUpdate(SQL);

resultarea.setText("  已成功删除相关信息");

System.out.println("删除学生信息成功");

sm.close();

}catch(SQLException e)

{

System.out.println("封装的删除操作失败 : "+e);

}

}
 
public void actionPerformed(ActionEvent evt)
{  
resultarea.setText("");
// 规定删除和更新必要的数据输入,减少判断情况!
if(evt.getSource()==submit)
{

st1 = name.getText().trim();

st2 = num.getText().trim();

st3 = sex.getText().trim();

st4 = grade.getText().trim();

st5 = major.getText().trim();


if(st1.length()==0||st2.length()==0||st3.length()==0||st4.length()==0||st5.length()==0)

{

resultarea.append("  请填入完整的数据!"+"\n");

return;

}else{

//获得输入信息,在数据库插入一个元组(判断是否漏项)

// 这里数字对应的字符串是否应该加上单引号,不应该

String line = "('"+st1+"','"+st2+"','"+st3+"',"+st4+",'"+st5+"')";

try{

SQL = "INSERT INTO Student VALUES"+line;

sm = con.createStatement();

sm.executeUpdate(SQL); //执行SQL的更新语句,包括update,delete和insert语句

System.out.println("插入学生信息成功!");

sm.close();

}catch(Exception e)

{
System.out.println("插入学生信息失败 : "+e);
}
}

}else if(evt.getSource()==select)

{

GetString();

// 查询,如果没有输入信息,全部打印,否则按输入查询

if(stt1.length()==0 && stt2.length()==0 && stt3.length()==0 && stt4.length()==0 && stt5.length()==0)

{

try

{

SQL = "SELECT * FROM Student";

sm = con.createStatement();

rs = sm.executeQuery(SQL);

/*  setText()与append()的区别,append()是在已有文本后面添加 */

resultarea.setText("");

if(!rs.next())

{

resultarea.append("  该表为空表!");

}else{

Select(rs);

}

rs.close();

sm.close();

}catch(Exception e)

{

System.out.println("  查找全表失败 : "+e);

}

}else if(stt2.length()!=0)

{

// 可以依据唯一码(主码),学号进行查询

try{

// SQL语句中:字符串都要用单引号括起来

// 这个语句是有问题的:'stt2'字符串值是stt2而不是文本框中的 : String SQL = "SELECT * FROM Student WHERE num LIKE 'stt2'"; 

/*

注意属性值空格符的填充,以及SQL语句字符串值

*/

SQL = "SELECT * FROM Student WHERE num LIKE '"+stt2+"%'";

sm = con.createStatement();

rs = sm.executeQuery(SQL);


resultarea.setText("");

if(!rs.next())

{

resultarea.append("  !!该表为空表!");

}else{

Select(rs);

}

rs.close();

sm.close();

}catch(Exception e)

{  // 这里抛出异常,说明SQL语句出现问题

System.out.println("查询该名学生失败 : "+e);

}


}else if(stt1.length()!=0 && stt5.length()!=0)
{

// 依据姓名和专业同时查询

try

{ // SQL语句,多个条件WHERE下同时满足,不能并列处理,需要用AND连接.

SQL = "SELECT * FROM Student WHERE name LIKE '"+stt1+"%'"+"AND major LIKE '"+stt5+"%'";

sm = con.createStatement();

rs = sm.executeQuery(SQL);


resultarea.setText("");

if(!rs.next())

{

resultarea.append("  !该表为空表!");

   }else{

Select(rs);

   }

rs.close();

sm.close(); 

        }catch(SQLException e)

       {

            System.out.println("查询失败"+e);

       }


}else if(stt1.length()!=0)

{

if(stt5.length()==0)

{

// 依据姓名查询

try

{

SQL = "SELECT * FROM Student WHERE name LIKE '"+stt1+"%'";

sm = con.createStatement();

rs = sm.executeQuery(SQL);


resultarea.setText("");

if(!rs.next())

{

resultarea.append("  !该表为空表!");

}else{

Select(rs);

   }

rs.close();

sm.close();

  }catch(SQLException e)

{

  System.out.println(e.toString());

}

 }
}else if(stt5.length()!=0)
{
if(stt1.length()==0)
{

// 依据专业查询

try

{

SQL = "SELECT * FROM Student WHERE major LIKE '"+stt5+"%'";

sm = con.createStatement();

rs = sm.executeQuery(SQL);


resultarea.setText("");

if(!rs.next())

{

resultarea.append("  !该表为空表!");

}else{

Select(rs);
   }

rs.close();

sm.close();

}catch(SQLException e)

{

System.out.println(e.toString());

}

     }
   }else
 {
resultarea.append("查询操作,至少要输入:姓名,学号,专业中的一项");
             }
}else if(evt.getSource()==delete)
{

GetString();

if(stt2.length()!=0)

{

// 依据唯一码:学号删除

SQL = "DELETE FROM Student WHERE num LIKE '"+stt2+"%'";

Delete(SQL);

}else if(stt1.length()!=0)

{

if(stt5.length()!=0)

{

// 依据姓名和专业删除

SQL = "DELETE FROM Student WHERE name LIKE '"+stt1+"%'"+"AND major LIKE '"+stt5+"%'";

Delete(SQL);

}else{

// 依据姓名删除

SQL = "DELETE FROM Student WHERE name LIKE '"+stt1+"%'";

Delete(SQL);

}

}else if(stt5.length()!=0)

{

// 依据专业删除

SQL = "DELETE FROM Student WHERE major LIKE '"+stt5+"%'";

Delete(SQL);

}else

{

resultarea.append("删除操作,至少要输入:姓名,学号,专业中的一项");

}

}else if(evt.getSource()==update)

        {

GetString();

if(stt1.length()==0||stt2.length()==0||stt3.length()==0||stt4.length()==0||stt5.length()==0)

{

resultarea.append("更新操作,必须输入完整信息");

}else

{   // 对表进行更新

try

{

SQL = "UPDATE Student SET name='"+stt1+"',num='"+stt2+"',sex='"+stt3+"',grade="+stt4+",major='"+stt5+"'"+

      " WHERE num LIKE '"+stt2+"%'";

sm = con.createStatement();

sm.executeUpdate(SQL);

resultarea.setText(" 已完成数据更新");

System.out.println("更新学生信息成功");

sm.close();

}catch(SQLException e)

{

  System.out.println(e.toString());

}

}

}

      } 

 }

 其实这里主要:实现客户端与服务器信息交互,判断客户端意图,执行相关操作,返回信息给客户端。 同时服务器自身实现对数据库的管理。

要运行上述程序,需要下载安装Derby数据库对应的jar包!

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 店铺不干了被告商标侵权怎么办 咸鱼违规被投诉侵犯商标权怎么办 房子买了70年后怎么办 买房付完首付后怎么办 手机b站忘记密码怎么办 护士电子注册没有激活码怎么办 大王卡变3g网是怎么办 无法解析服务器的dns地址怎么办 笔记本dns辅服务器未响应怎么办 原营业执照注销法人没在怎么办? 加盟骗局公安局工商局不管怎么办 发现老婆衣柜里有避孕套怎么办 2岁宝宝爱舔东西怎么办 痔疮手术后痛疼怎么办 长了内痔疮该怎么办 淘宝卖家遇到恶意买家怎么办 淘宝遇到恶意买家拍单怎么办 淘宝遇到买家恶意搞坏商品怎么办 木油味道很重怎么办 床垫外面布坏了怎么办 淘宝店铺动态评分低怎么办 实创倒闭返款怎么办 qq红包忘记支付密码怎么办 qq红包支付密码忘了怎么办 个人卖东西人家要发票怎么办 打了欠条找不到人怎么办 公章掉进水里了怎么办 手游吃鸡限制登入15分钟怎么办 宝宝的小鸡淹了怎么办 宝宝小鸡底下淹了怎么办 4岁宝宝拉稀水怎么办 2岁半宝宝对眼怎么办 孩子在幼儿园中午不睡觉怎么办 20天婴儿拉稀水怎么办 3个月婴儿拉水怎么办 两岁宝宝拉水怎么办 1岁半宝宝拉水怎么办 5周孩子小鸡长脂肪粒怎么办 小孩丁丁长歪了怎么办 2个月的婴儿咳嗽怎么办 2个月的宝宝干咳怎么办