Java学习不走弯路教程(13 HTTP服务器)

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代码如下:

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="http://localhost:8000/person" method="get">
please input personid:<input id="personid" name="personid"/><input type="submit" value="query"/>
</form>
</body>
</html>


启动服务器:

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

 

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

GET /person?personid=1 HTTP/1.1
Host: localhost:8000
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate, br
Accept-Language: ja,en-US;q=0.9,en;q=0.8,zh-CN;q=0.7,zh;q=0.6
Cookie: 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<String,String> parameterMap = new HashMap<String,String>();
 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<String,String> 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("<br/>username:"+personResult.username);
24         result.append("<br/>password:"+personResult.passwd);
25         
26         // 返回结果
27         return result.toString();
28     }
29 }

三. 测试

启动服务器:

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

显示查询结果:

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

如有问题,大家来我的网站进行提问。
https://www.java123.vip/qa

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

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值