诸如tomcat等web服务器中间件简化了我们web的开发成本,但有时候我们或许并不需要这么一个完备的服务器,只是希望做一个简单地处理或者做特殊用途的服务器。
本文将提供一个HTTP的服务器示例,采用Java的ServerSocket进行编码。随着计算机硬件的提升,以及Java地不断优化,使用Java网络编程实现web服务器在实际性能上已经开始可以跟C进行竞争。
以下代码分为两块:
1)HttpServer:主要包含一个ServerSocket,用于接收客户端请求。并通过线程池将请求从主线程剥离,分散到各个线程中去处理;
2)RequestHandler:实现了Runnable接口,将获取一个线程来处理各个请求;流的读取和响应遵循HTTP协议。
注意:编写Http服务器和一般的socket程序并没有太大不同,但是你需要遵循HTTP协议,这样对于采用HTTP协议的客户端或者其它服务器就可以直接进行HTTP请求来通讯。
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.*;
/**
* Http服务器端示例,端口设置为8080,编码设置为UTF-8
* @author lay
* @date 2019-01-01
*/
public class HttpServer {
private static final int port = 8080;
/**
* 启动HTTP服务器
*/
public void start() throws IOException {
// 初始化线程池
ThreadPoolExecutor executor = new ThreadPoolExecutor(10, 10, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<>());
// 初始化服务器socket
ServerSocket serverSocket = new ServerSocket(port);
System.out.println("ServerSocket启动完成");
while (true) {
// 阻塞等待socket连接
System.out.println("等待socket");
Socket socket = serverSocket.accept();
// 提交至线程池处理
executor.submit(new RequestHandler(socket));
System.out.println("提交线程池处理请求");
}
}
public static void main(String[] args) {
try {
new HttpServer().start();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
import java.io.*;
import java.net.Socket;
/**
* 请求处理类
* @author lay
* @date 2019-01-01
*/
public class RequestHandler implements Runnable {
/**
* HTTP响应头
*/
private static final String response = "http/1.1 200 ok";
private static final String splitStr = "\r\n";
private Socket socket;
private BufferedReader reader;
private BufferedWriter writer;
public RequestHandler(Socket socket) throws IOException {
this.socket = socket;
this.reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
this.writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
}
/**
* 响应结果
* @param content 响应内容
* @throws IOException IO异常抛出
*/
public void sendResponse(String content) throws IOException {
writer.write(String.format("%s%s", response, splitStr));
writer.write(splitStr);
writer.write(content);
}
/**
* 获得请求
* @return 请求文本
* @throws IOException IO异常抛出
*/
public String getRequest() throws IOException {
StringBuilder stringBuilder = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
stringBuilder.append(line);
stringBuilder.append(splitStr);
// 空字符串
if (line.isEmpty()) {
break;
}
}
System.out.println("request:\r\n" + stringBuilder);
return stringBuilder.toString();
}
@Override
public void run() {
try {
String request = getRequest();
// 这里直接把请求数据响应回去
sendResponse(request);
writer.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
请求处理器这里直接将请求的HTTP内容返回回去了,如果你使用浏览器请求8080端口,你会看到如下内容:
不过浏览器会默认请求一个icon,所以针对一个URL地址会有两个请求
你可以在ico请求的时候返回一个二进制的ico文件流,它将显示在浏览器的tab上。
1)我们可以像tomcat一样去支持Java Servlet api
2)支持如GET、POST、PUT、DELETE等restful请求
3)将程序配置进行XML配置
4)增加管理界面
5)请求跟踪处理
6)缓存、非阻塞IO、通道来增加性能
来自:https://www.cnblogs.com/lay2017/p/10206505.html
在以往的 Tomcat 项目中,一直习惯用 Ant 打包,使用 build.xml 配置,通过 ant -buildfile 的方式在机器上执行定时任务。虽然 Spring 本身支持定时任务,但都是服务一直运行时支持。
首先引入依赖,既然要进行智能联想,那么我们需要为提供联想的数据建立一个联想索引(而不是使用原来的数据索引),既然要建立索引,那么我们需要知道建立索引的数据来源。我们使用一个扩展自InputIterator的类来定义数据来源
本文是基于Java 8的HashMap进行分析,主要是介绍HashMap中的成员变量和类变量的用途,以及分析HashMap的数据结构。在HashMap中存在多个成员变量和类变量,搞清楚它们的用途有助于我们更深入了解HashMap,下面是它们的介绍:
Spring默认使用Jackson处理json数据。实际开发中,在业界中,使用非常受欢迎的fastjson来接受json数据。创建一个项目,在web目录下新建一个assets/js目录,加入jquery和json2的js文件,在lib下加入fastjson的jar文件。
求两个IP地址之间的IP个数,例如192.18.16.1~192.18.16.5,2001:DB8:0000:0023:0008:0800:200C:417C~2001:DB8:0:23:8:800:200C:417D之间的IP个数?
JSP和JSF这两种技术都基于Java,主要用于基于Web的应用程序。那么它们之间有什么区别?下面本篇文章就来给大家简单比较一下JSP和JSF,介绍JSP和JSF之间的区别有哪些,希望对大家有所帮助。
Java 堆空间:发生频率:5颗星造成原因1、无法在 Java 堆中分配对象 2、吞吐量增加 3、应用程序无意中保存了对象引用,对象无法被 GC 回收 4、应用程序过度使用 finalizer
今天看到某一篇文章的一句话 单例DCL 前面加 V 。就这句话让我把 单例模式 又仔细看了一遍。Java 中的 单例模式 是我们一直且经常使用的设计模式之一,大家都很熟悉,所以这篇文章仅仅做我自己记忆。
在任何Java面试当中多线程和并发方面的问题都是必不可少的一部分。如果你想获得更多职位,那么你应该准备很多关于多线程的问题。面试官会问面试者很多令人混淆的Java线程问题
拦截器功在对请求权限鉴定方面确实很有用处,在我所参与的这个项目之中,第三方的远程调用每个请求都需要参与鉴定,所以这样做非常方便,而且他是很独立的逻辑,这样做让业务逻辑代码很干净
内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!