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

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

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

     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
原创粉丝点击