//1.创建服务器socket,并绑定端口号,可以自己指定。
ServerSocket ss = new ServerSocket(8888);
//循环监听客户端连接
while (true) {
//监听客户端连接,返回对应的socket对象.此方法在成功返回之前一直阻塞!
Socket socket = ss.accept();
//启动一个线程处理该连接
serverExecutors.submit(new myCall(socket));
}
}
static class myCall implements Callable {
Socket socket;
public myCall(Socket socket) {
this.socket = socket;
}
@Override
public Object call() throws Exception {
//处理请求
processData();
//返回响应
responseData();
return null;
}
private void processData() throws IOException {
//创建输入流,使用read()读取数据,如果未读取到数据,此方法将一直阻塞!
InputStream is = socket.getInputStream();
byte[] b = new byte[1024];
int read = is.read(b);
//获取请求的数据
System.out.println(new String(b, 0, read));
}
private void responseData() throws IOException {
//给客户端响应,获得输出流,发送数据
OutputStream os = socket.getOutputStream();
String str = "HTTP/1.1 200 OK " +
"Server: Apache-Coyote/1.1 " +
“Accept-Ranges: bytes\n” +
“ETag: W/“480-1543570084000”\n” +
“Last-Modified: Fri, 03 Dec 2020 17:47:04 GMT \n” +
“Content-Type: text/html \n” +
“Content-Length: 480 \n” +
“Date: Fri, 30 Nov 2018 16:39:05 GMT \n” +
“\n” +
“\n” +
“\n” +
" \n" +
“
“\n” +
" \n" +
" \n" +
" \n" +
" \n" +
" \n" +
" " +
" 响应的html数据,This is my HTML page. " +
" \n" +
“\n”;
os.write(str.getBytes());
os.flush();
}
}
}
复制代码
这里我们仅提供局域网的交互!在自己的电脑中浏览器中访问:http://localhost:8888/,随后运行main函数,即“启动服务器”,即可在浏览器中获取响应,完成一次请求和响应交互。也可以在局域网中将localhost换成自己的ip即可实现远程计算机访问!
下面是客户端浏览器显示的服务器发送的响应数据!
3 Web服务器与Servlet
================
上文中,我们已经模拟了一个简单的HTTP服务器,可以接收请求,发送响应,似乎也没那么难,然而,实际上我们这个服务器仅仅提供了非常简单的获取请求和响应数据的功能,其他的比如http请求中各种参数的解析,响应数据的处理,以及更底层的TCP连接复用,多线程IO,异常处理等功能则没有编写,这些功能需要编写大量的代码,并且进行多次的测试、优化,对于大部分菜鸡程序员来说(比如本人),是不具备这些底层功能的编写以及优化能力的!
在一个web中项目中,大多数程序员最关心的应该是业务层面的功能,而非网络传输、请求解析、发送响应等底层功能,实际上在我们开发的web项目中,确实也没有写这些网络通信的底层代码,仅仅是写的“业务代码”而已,为什么可以这样呢?这就是web服务器的功劳!我们只需要将编写的web应用放到web服务器指定的位置,随后启动web服务器,即可根据请求实现我们的业务功能。web服务器也是一个应用程序,专门用于处理TCP连接、接受HTTP请求、响应数据等底层的功能,简单的说就是处理网络请求与响应。这样,有了web服务器,对于大多数程序员来说,就能一心一意的实现业务功能,而不必关心网络通信这一底层功能!典型的web服务器就是tomcat。
到此,我们可以知道编写的“Web应用”是不具备处理网络请求的接收与响应的功能的,它仅仅是一个在中间工作程序,用于处理已经被Web服务器解析、封装好的网络请求。web服务器将接受到的请求转发给对应的web应用的处理程序,处理完毕之后再将结果响应给客户端。
**那么web服务器如何将封装好的请求传递给web应用,以及web应用如何将响应结果数据传递给web服务器,以及二者交互的数据的格式是怎样的,对于这种通用的问题,制定一个统一的标准最好了,所有的web项目都可以按照这个标准来开发,web服务器也按照这个标准来实现。这对于Java来说很简单,那就是抽象成为一个接口(
【一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义】
interface)即可,这就是Servlet,Servlet没有标准中文翻译,直译过来就是“小型应用程序”,Servlet就是一个Java中的接口而已,接口的作用是什么?对,就是标准、规范,Servlet就定义了通过Java开发web应用处理网络请求以及响应数据的接口规范。换一个说法, Servlet就是Java方便进行动态web应用开发的一个统一的标准(模版)。**
Servlet的简单规范如下:我们想要开发某个项目,只需要开发对应的Servlet实现,并将其对应到一个请求url地址,随后在方法里面编写业务逻辑即可,而请求和响应,都已被同样实现了Servlet标准的web服务器(比如tomcat)帮我们封装为ServletRequest和ServletResponse对象,当一个请求到来时,tomcat会将封装好的参数对象传递到Servlet的方法参数中,我们可以直接从ServletRequest参数对象中获取请求的参数,也可以通过ServletResponse参数对象发出响应。这样,就解决了web服务器和web应用数据交互的问题,所有的Java Web应用都可以按照这个模式/标准来开发。
因此,大部分人所说的web项目开发,主要就是Servlet开发。虽然现在都是基于框架开发,比如Spring MVC,但是Spring MVC只是对Servlet原生API进行封装,它的Controller方法就是Servlet方法的入口,内部的Service层和DAO层不过是为了方便开发而拆分出来的,它们的方法都直接或者间接的被Controller方法调用。
总结一下:Servlet就是一个sun制订的使用Java语言开发Web项目的一个规范,我们使用Servlet规范开发的Web项目,就能够运行在同样实现了Servlet规范的Web服务器中,这样的好处是,解析客户端网络请求、线程复用、响应数据给客户端等一系列底层的网络编程工作都由Web服务器帮我们完成了,而我们的“Web项目”仅仅需要编写Servlet的实现,在实现中仅仅需要编写业务逻辑就行了,随后我们还需要将指定的Servlet实现与指定的请求路径绑定。
Web服务器以多线程的形式处理请求,当一个请求到来的时候,Web服务器会使用一条线程帮我们将请求参数和响应数据都封装成为一个HttpServletRequest和HttpServletResponse对象,并将HttpServletRequest和HttpServletResponse传递给对应请求路径的Servlet实例,在Servlet的方法中的业务逻辑处理完之后,Web服务器又自动将我们的return返回的结果封装成对应的响应数据返回给客户端,总体而言就这么简单。
Servlet,甚至于我们编写的整个web应用程序,在一次请求与响应过程中,都是非常被动的一个角色,我们不需要手动创建Servlet对象,应用中也没有main方法,我们只需要将应用中某个Servlet和某个URL请求对应上,然后将web应用交给tomcat,随后启动tomcat,之后tomcat接受到请求之后就会自动映射到对应的Servlet,创建Servlet对象并调用Servlet的方法,这个方法中就是我们自己开发的处理请求的逻辑,从而完成一次请求和响应,因此tomcat由于支持Servlet和JSP的运行,因此也被称为Servlet/jSP容器!注意,一个Servlet只会实例化一次,但是一个请求对应着一个不同的线程,因此它们可能共用一个Servlet实例,所以我们开发的Servlet需要注意线程安全问题。
对于大部分程序员而言,他们不具备或者说不精通网络编程的能力,因此,使用Servlet规范开发Web项目对于他们而言是再好不过了(对我来说也是一样的)! 那么,不使用Servlet规范开发Web项目行不行呢?那肯定也是可以的呀,完全没问题,只不过这需要我们自己来解析请求、返回响应,比如说在“Web请求”部分的案例中,我们就只使用了一个类就给客户端浏览器响应了数据。当然,一个大型项目业务众多,各种请求,甚至包括文件上传、下载之类的,网络编程的实现远比这个案例复杂,那就相当于你自己开发一个项目的同时还顺便开发一个Web服务器了。当然,这就比较夸张了,实际上我们基于Netty就能比较轻松实现一个Web服务器,自己解析请求、响应,就能构建一个不遵循Servlet规范的Web项目。