博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java学习不走弯路教程(13 HTTP服务器)
阅读量:5233 次
发布时间:2019-06-14

本文共 8496 字,大约阅读时间需要 28 分钟。

HTTP服务器

一. 前言

在前上一章教程中,介绍了Container容器。

本章将在上一章的基础上,进一步扩展程序。

注:

1.本文针对初学Java的同学训练学习思路,请不要太纠结于细节问题。
2.本文旨在达到抛砖引玉的效果,希望大家扩展本例子,以学到更多知识的精髓。

学习本章需要准备的知识:

1.读完本系列教程的前面章节。
2.了解Http协议,了解HTML。

二. 步入正题

话不多说,大家自己理解,下面步入正题:

本章我们通过浏览器来调用我们的程序。

首先我们看一下浏览器和服务器的交互过程:

比如点击页面上一个按钮提交请求的流程:

1. 浏览器发送请求和数据给服务器;
2. 服务器读完请求和数据后,根据请求的参数调用系统逻辑;
3. 然后将得到的结果用response方式传递给浏览器。

这个通讯过程采用HTTP协议。

所以,我们首先要按照HTTP协议的格式解析发送来的请求,

然后读取我们想要的数据。

下面我们做一个模拟服务器来接收浏览器发送来的请求,看一下请求的数据格式。

1 /** 2  *  3  * @author http://www.java123.vip 4  * 5  */ 6 public class MyServer { 7  8     private int port; 9     10     public MyServer(int port) {11         this.port = port;12     }13     14     public void startServer() {15         try {16             17             ServerSocket ss = new ServerSocket(port);18             System.out.println("listening at port:"+port);19             20             while(true) {21                 Socket s = ss.accept();22                 System.out.println("get connection:"+s.getInetAddress().toString());23                 24                 // 启动和浏览器通讯的线程25                 ClientThread clientThread = new ClientThread(s);26                 new Thread(clientThread).start();27             }28             29         } catch (IOException e) {30             e.printStackTrace();31         }32     }33     34     public static void main(String[] args) {35         MyServer fvs = new MyServer(8000);36         fvs.startServer();37     }38 }
1 /** 2  *  3  * @author http://www.java123.vip 4  * 5  */ 6 public class ClientThread implements Runnable{ 7  8     private Socket socket; 9     private BufferedReader br;10     private PrintWriter pw;11     12     public ClientThread(Socket socket) {13         try {14             15             InputStream is = socket.getInputStream();16             InputStreamReader isr = new InputStreamReader(is);17             br = new BufferedReader(isr);18             19             OutputStream os = socket.getOutputStream();20             OutputStreamWriter osw = new OutputStreamWriter(os);21             pw = new PrintWriter(osw,true);22             23         } catch (IOException e) {24             e.printStackTrace();25         }26     }27     28     public void run() {29 30         while(true) {31             try {32                 33                 String message = br.readLine();34                 // 输出所有得到的消息35                 System.out.println("get message:"+message);36                 37                 38             } catch(IOException e) {39                 e.printStackTrace();40             } catch (Exception e) {41                 e.printStackTrace();42             }43         }44     }45     46 }

 

我们做一个HTML页面如下:

 

HTML代码如下:

Insert title here
please input personid:

启动服务器:

在浏览器端输入1,点query按钮:

 

可以看到,浏览器向服务器发送了如下数据:

GET /person?personid=1 HTTP/1.1Host: localhost:8000Connection: keep-aliveCache-Control: max-age=0Upgrade-Insecure-Requests: 1User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8Accept-Encoding: gzip, deflate, brAccept-Language: ja,en-US;q=0.9,en;q=0.8,zh-CN;q=0.7,zh;q=0.6Cookie: qa_noticed=1; _ga=GA1.1.462590489.1538429997

 

最后接收一个空字符串表示发送请求完毕:

我们需要的信息[请求的路径(/person)和参数(personid=1)]都在第一行,所以我们在第一行数据过来的时候,把需要的信息保存起来。

数据发送完毕后,用得到的信息来查询数据库,得到查询结果。
再将查询结果发送Response传递给客户端。
代码如下:

1 /**  2  *   3  * @author http://www.java123.vip  4  *  5  */  6 public class ClientThread implements Runnable{  7   8     private Socket socket;  9     private BufferedReader br; 10     private PrintWriter pw; 11      12     public ClientThread(Socket socket) { 13         try { 14              15             InputStream is = socket.getInputStream(); 16             InputStreamReader isr = new InputStreamReader(is); 17             br = new BufferedReader(isr); 18              19             OutputStream os = socket.getOutputStream(); 20             OutputStreamWriter osw = new OutputStreamWriter(os); 21             pw = new PrintWriter(osw,true); 22              23         } catch (IOException e) { 24             e.printStackTrace(); 25         } 26     } 27      28     public void run() { 29  30         // 保存请求路径(/person) 31         String requestPath = "";  32         // 保存请求参数(personid=1) 33         Map
parameterMap = new HashMap
(); 34 35 while(true) { 36 try { 37 // 读取一行请求 38 String message = br.readLine(); 39 System.out.println("get message:"+message); 40 41 if(message == null) { 42 break; 43 } 44 45 // 用空格分隔请求的内容 46 String[] messageDetails = message.split(" "); 47 48 // 对于包含get的第一行,得到路径 /person 49 if(messageDetails[0].equalsIgnoreCase("get")) { 50 requestPath = messageDetails[1]; 51 } 52 53 // 请求发送完毕(读到空字符串)后,根据请求参数查数据 54 if("".equals(message)) { 55 56 // 把得到的(/person?personid=1)拆分出/person和personid=1 57 int endPos = requestPath.indexOf("?"); 58 if(endPos == -1) { 59 requestPath = requestPath.substring(1); 60 }else { 61 String paramString = requestPath.substring(endPos+1); 62 requestPath = requestPath.substring(1,endPos); 63 64 String[] params = paramString.split("&"); 65 for(int i = 0; i < params.length; i ++) { 66 String[] keyValue = params[i].split("="); 67 parameterMap.put(keyValue[0], keyValue[1]); 68 } 69 } 70 71 System.out.println("request path:"+requestPath); 72 73 // 保存数据库查询结果用 74 String data = ""; 75 76 // 处理 /person请求 77 if(requestPath.equals("person")) { 78 79 // 将参数personid=1发送给PersonController来查数据 80 PersonController personController = new PersonController(); 81 data = personController.queryPerson(parameterMap); 82 83 }else if(requestPath.equals("favicon.ico")){
//不处理 84 data = ""; 85 } 86 87 // 发送Reponse到浏览器 88 pw.println("HTTP/1.1 200 OK"); 89 pw.println("Content-Type: text/html"); 90 pw.println("Content-length: "+data.length()); 91 pw.println(); 92 pw.println(data); 93 pw.println(); 94 break; 95 } 96 97 } catch(IOException e) { 98 e.printStackTrace(); 99 } catch (Exception e) {100 e.printStackTrace();101 }102 }103 }104 105 }

对于每个请求,我们做了一个Controller类来负责具体的逻辑,代码如下:

1 /** 2  *  3  * @author http://www.java123.vip 4  * 5  */ 6 public class PersonController { 7  8     public String queryPerson(Map
requestParameterMap) { 9 10 // 得到请求参数11 String personId = requestParameterMap.get("personid");12 13 // 创建Service实例14 MyContainer container = MyContainer.getInstance();15 PersonService personService = (PersonService)container.getObject(PersonService.class);16 17 // 查询结果18 Person personResult = personService.getPerson(personId);19 20 // 封装结果21 StringBuffer result = new StringBuffer();22 result.append("id:"+personResult.id);23 result.append("
username:"+personResult.username);24 result.append("
password:"+personResult.passwd);25 26 // 返回结果27 return result.toString();28 }29 }

三. 测试

启动服务器:

在浏览器端输入1,点query按钮:

显示查询结果:

完整程序请大家从[]下载

如有问题,大家来我的网站进行提问。

版权声明:本教程版权归java123.vip所有,禁止任何形式的转载与引用。

转载于:https://www.cnblogs.com/java123-vip/p/9771043.html

你可能感兴趣的文章
USACO Arithmetic Progressions 【构造等差数列】
查看>>
测试Writer
查看>>
caioj1441:第k小的数Ⅰ
查看>>
Kattis之旅——Eight Queens
查看>>
小程序如何封装自定义组件(Toast)
查看>>
VS Code + Anaconda打造舒适的Python环境
查看>>
3.PHP 教程_PHP 语法
查看>>
readonly, const, static, static readonly 关键字实例说明
查看>>
Duilib扩展《01》— 双击、右键消息扩展
查看>>
6.1.2.10 超链接美化
查看>>
常用mac/unix/linux命令
查看>>
MongoDB Limit与Skip方法-7
查看>>
POJ1664|DFS水题
查看>>
[php]http的状态码
查看>>
利用Fiddler拦截接口请求并篡改数据
查看>>
python习题:unittest参数化-数据从文件或excel中读取
查看>>
Android控件之GridView探究
查看>>
在工程中要加入新的错误弹出方法
查看>>
在Spark中尽量少使用GroupByKey函数(转)
查看>>
PS 滤镜— — sparkle 效果
查看>>