拿java的web開發爲例子,相信有很多小夥伴是做j2EE開發的,htpp請求,json數據傳輸都是工作中經常用的,查詢請求,添加請求,修改請求前端配個url,例如https://localhost/intsmaze/user/add?name=intsmaze。然後後端建立一個controler類(類上配置url映射/user),然後創建一個addUser方法(在方法上配置映射/add)。然後啓動web應用,前端發送的請求就會自動走到後端的addUser方法了。
但是你知道爲什麼這個請求走對應的方法嗎?下面讓我拿我大三期間基於TCP寫的服務端程序做例子來看看背後的原理吧。這個程序時一個超市管理系統,客戶端使用javaSwing編寫,服務端使用javaSE編寫,雙方通信使用TCP協議,數據存儲在mysql中。完整的項目上傳在github上https://github.com/intsmaze/Swing-TCP-mysql。
服務端啓動類,綁定端口。
public class LoginServer { private int port=1000; private ServerSocket serversocket; private ExecutorService executorservice; private final int POOL_SIZE=1;//一個CPU線程池中工作線程的數目 public LoginServer() throws Exception { serversocket=new ServerSocket(); serversocket.bind(new InetSocketAddress("127.0.0.1",port)); executorservice=Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()*POOL_SIZE); //當前CPU數*1就是總線程池數目 } public void service() { while(true) { Socket socket=null; try { socket=serversocket.accept(); executorservice.execute(new Handler(socket)); }catch(IOException e) { e.printStackTrace(); } } } public static void main(String[] args) throws Exception { new LoginServer().service(); } }
路徑映射方法
localhost/intsmaze/後面不同的路徑就是截取對應的字符串然後調用對應的方法
public class Handler implements Runnable{ public static final int SOLDERCONNECTION=0;//售貨員登錄 public static final int MANAGERADDSOLDER=7;//管理員添加售貨員 public static final int MANAGERDELETESOLDER=8;//管理員刪除售貨員 public static final int MANAGERMOIDFYSOLDER=9;//管理員修改售貨員 private Socket socket; private BufferedReader bufIn=null; private BufferedWriter bufOut=null; private Connection connection=null; private PreparedStatement preparedstatement=null; private ResultSet resultset=null; public Handler(Socket socket) throws IOException { this.socket=socket; bufIn=new BufferedReader(new InputStreamReader(socket.getInputStream())); bufOut=new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); } public void run() { try { String line=bufIn.readLine(); //讀取第一個選着功能 int i=Integer.valueOf(line); switch(i) { case SOLDERCONNECTION: solderConnection();//售貨員登錄0 break; case MANAGERADDSOLDER: managerAddSolder();//管理員添加售貨員7 break; case MANAGERDELETESOLDER: managerDeleteSolder();//管理員刪除售貨員8 break; case MANAGERMOIDFYSOLDER: managerModifySolder();//管理員修改售貨員9 break; } }catch(Exception e) { socketUtil.close(socket); } } public void solderConnection() throws Exception { String sr=null; //讀取賬號和密碼 String arr[] =bufIn.readLine().split("#");; connection=JdbcUtil.getConnection(); preparedstatement=connection.prepareStatement("SELECT * FROM solder WHERE solder_number=? and solder_password=?"); preparedstatement.setString(1,arr[0]); preparedstatement.setString(2,arr[1]); resultset=preparedstatement.executeQuery(); if(resultset.next()){ bufOut.write("ok\n");//回饋查詢信心 bufOut.flush(); sr=resultset.getInt(1)+"#"+resultset.getString(2)+"#"+resultset.getString(3)+"\n"; bufOut.write(sr); bufOut.flush(); } else { bufOut.write("no");//回饋查詢信心 bufOut.flush(); } JdbcUtil.release(resultset, preparedstatement, connection); } public void managerAddSolder() throws Exception { connection=JdbcUtil.getConnection(); String name=bufIn.readLine(); System.out.println(name); preparedstatement=connection.prepareStatement("insert into solder(solder_name) values(?) "); preparedstatement.setString(1,name); preparedstatement.executeUpdate();//執行更新 preparedstatement=connection.prepareStatement("select *from solder where solder_number=(select MAX(solder_number)from solder) "); resultset=preparedstatement.executeQuery();//執行更新 if(resultset.next()) { bufOut.write("ok\n");//回饋查詢信心 bufOut.flush(); String str=resultset.getString(1)+"#"+resultset.getString(2)+"#"+resultset.getString(3); bufOut.write(str+"\n");//回饋查詢信心 bufOut.flush(); } else { bufOut.write("no\n");//回饋查詢信心 bufOut.flush(); } JdbcUtil.release(resultset, preparedstatement, connection); } public void managerModifySolder() throws Exception { connection=JdbcUtil.getConnection(); String arr[] = null; String line=null; String number=bufIn.readLine(); preparedstatement=connection.prepareStatement("select *from solder WHERE solder_number=? "); preparedstatement.setString(1,number); resultset=preparedstatement.executeQuery(); if(resultset.next()) { bufOut.write("ok\n");//回饋查詢信心 bufOut.flush(); line=bufIn.readLine(); arr=line.split("#"); preparedstatement=connection.prepareStatement("update solder set solder_password=?,solder_name=? WHERE solder_number=? "); preparedstatement.setString(1,arr[2]); preparedstatement.setString(2,arr[1]); preparedstatement.setString(3,arr[0]); preparedstatement.executeUpdate();//執行更新 } else { bufOut.write("no\n");//回饋查詢信心 bufOut.flush(); } socket.close(); JdbcUtil.release(resultset, preparedstatement, connection); } public void managerDeleteSolder() throws Exception { connection=JdbcUtil.getConnection(); String number=bufIn.readLine(); preparedstatement=connection.prepareStatement("select *from solder WHERE solder_number=? "); preparedstatement.setString(1,number); resultset=preparedstatement.executeQuery(); if(resultset.next()) { bufOut.write("ok\n");//回饋查詢信心 bufOut.flush(); preparedstatement=connection.prepareStatement("delete from solder WHERE solder_number=? "); preparedstatement.setString(1,number); preparedstatement.executeUpdate();//執行更新 } else { bufOut.write("no\n");//回饋查詢信心 bufOut.flush(); } socket.close(); JdbcUtil.release(resultset, preparedstatement, connection); } }
以localhost/intsmaze/user/add?name=intsmaze的url來反向剖析tcp服務端如何接收,並調用對應方法。localhost是與服務器建立連接,然後發送intsmaze/user/add?name=intsmaze爲一個數據到服務器,服務器接收到該字符串後,根據/截取,然後判斷該請求是發給intsmaze的應用。然後通過user知道這個請求時user模塊(用戶管理模塊),然後通過add知道是調用添加用戶方法。?後面就是對於的參數獲取存入數據庫即可.
對上面的方法改進如下即可實現
String line=bufIn.readLine(); //讀取第一個選着功能 line的值爲intsmaze/user/add?name=intsmaze String arr[]=line.split("/"); String model=arr[1]; String method=arr[2].split("?")[0]; String param=arr[2].split("?")[1]; if(model.endsWith("user")) { if(method.equals("add")) { user.add(param); } } else if(model.equals("goods")) { ... } else if ...