http 服务器负责接收客户端请求,找资源,返回资源给客户端,比如 apache / nginx ,如果请求的是静态资源,比如 html / image , http 服务器就直接找到并返回给客户端了。
这个时候如果客户端请求比如 php , http 服务器自己无法解析 php 的文件,如果没有配置解释器那它就会直接把这个 php 的源码给展示了出来(当成了文本文件),如果 http 服务器配置了解释器,因此它知道 php 这种后缀的文件应该去请求 php-cgi ,于是它就去让 php-cgi 执行 php , php 完成处理后把结果给 http 服务器, http 服务器把结果再给客户端。另外为了解决非编译型语言每次都初始化应用基础环境的重复工作,于是出现了 fast-cgi 的标准( master 执行初始化后就变成常驻进程,开启 worker 来处理单个请求), php-fpm 就是这个标准的具体实现。
那 tomcat 跟上面对比,是不是也是类似于 php-cgi 实现的一种存在?是不是这样: jsp 请求过来了, http 服务器不知道怎么解析,一看配置,需要去找 tomcat ,于是转给 tomcat ,但是 java 程序是需要 JVM 环境的,所以 tomcat 建立在 JVM 之上执行,而 tomcat 本身是个容器,需要实际的 worker 来解析 jsp ,于是就去实例化一个 servlet 来解析,最后再一层层回归到客户端。
是不是这样理解的?
求指点。。。
其实主要是在研究 ApplicationContext 发现它可以引用装载自己的 ServletContext ,因为是个 phper (世界上最好的语言,你懂的~),对这个 Servlet 有点理解不能。。。
1
hcymk2 2016-09-02 11:01:05 +08:00 1
tomcat 可以单独运行 不需要 webserver 的
|
2
misaka19000 2016-09-02 11:10:12 +08:00 1
Tomcat 本身包含了连接器( connector )和容器( container )
前者可以看作用来获取 HTTP 请求的,后者则是对前者所获取到的请求做进一步的处理 |
3
jint 2016-09-02 11:17:26 +08:00 1
tomcat 是一个 servlet 容器,容器和 servlet 之间按照协议的约定来分工合作。
你思考这个问题的时候,把 JVM 透明化就好了。 |
4
jint 2016-09-02 11:18:00 +08:00 1
每一个 JSP ,归根到底也还是一个 Servlet 。
|
5
crazyxin1988 2016-09-02 11:27:09 +08:00 1
先谈谈 Java web 的体系
首先是 servlet 规范 这个协议是干嘛的呢? 就是规范了应用和容器的通信。简单的说,比如你用 SpringMVC 写了一个 web 应用, springmvc 是遵守 servlet 规范的,所以,它可以跑在任何遵循 servlet 规范的容器上,比如,它可以跑在 tomcat 上, tomcat 就是一个 servlet 容器,当然,它也可以跑在 jetty 上。 tomcat 是用 java 语言开发的,所以, tomcat 就是一个 java 应用,需要跑在 JVM 中,就是 java 虚拟机。 关于 cgi ,在 java 里很少接触,一般都是脚本语言里使用。 |
6
hduwzy 2016-09-02 11:35:17 +08:00 via Android 1
基本赞同,但是有一句不赞同。建立 servlet 不是用来解析 jsp 的, servlet 本身就能对请求做出响应。准确的讲是 jsp 被编译成一个 servlet ,是这个 servlet 对请求做出响应
|
7
julyclyde 2016-09-02 12:24:42 +08:00 1
建议把“应用和容器的”“通信”改为“调用关系”,更明确一些
要不然总有人会被带到沟里去 |
8
lml12377 OP @crazyxin1988 明白了,谢谢!
|
9
lml12377 OP @crazyxin1988 是不是这样:[php] 客户端 -> apache -> (cgi request) -> php -> (cgi response) -> apache -> 客户端,[java web] 客户端 -> tomcat -> (servlet request) -> applicationContext -> (servlet response) -> tomcat -> 客户端
|
10
lml12377 OP @lml12377 是不是 tomcat container , servletContext , applicationContext 都是 java 写出来的对象?
|
15
lml12377 OP @misaka19000 这个我再去研究下~
|
16
julyclyde 2016-09-02 14:55:14 +08:00 1
|
18
crazyxin1988 2016-09-02 21:08:37 +08:00 1
|
19
SoloCompany 2016-09-03 01:33:52 +08:00 1
你仔细看的话,会发现 tomcat 有一个隐藏在容器配置下的 web.xml ,
里面包含了所有规范内的内容(也就是 webapp 无需重复定义的内容) 最重要的有这两项配置 定义了 DefaultServlet 处理所有的没有路由的请求,主要是用于处理静态资源以及响应 404 定义了 JspServlet ,以及 mapping with *.jsp *.jspx 所以,在 Tomcat 里面,你可以认为所有的请求最终其实都是由一个 Servlet 来处理,包括静态资源 |
20
SoloCompany 2016-09-03 01:49:03 +08:00 1
Tomcat 只是一个很简单的容器,只支持单进程多线程一种,最大的优点就是一切内存都是共享的,麻烦的地方当然也在于共享内存和并发而无法避免的锁问题
Apache 有 prefork 和 worker 两种 MPM ,无论是哪种都是多进程(除非你把 ServerLimit 限制到 1 ), prefork 完全不需要考虑内存争夺, worker 因为支持线程并发控制要灵活的多但锁的问题当然也会存在 因为多进程, apache 开发必须依赖外部应用(比如数据库或 redis )才能存储状态,打个比方,就实现一个简单的计数器, servlet 直接放内存就行了, cgi 的话就必须要靠数据库或者 redis 了 |
21
guoziyan 2016-09-03 03:49:52 +08:00 1
并不是非编译型的语言每次请求需要初始化环境,而是无法常驻内存的语言才需要,比如 PHP
|
22
lml12377 OP @SoloCompany 是不是像 WSGI /servlet 这种都是各自的语言自己来实现的?比如 tomcat 是 servlet 容器,那静态请求来了, tomcat 创建默认的 servlet 来处理静态请求,动态页面请求比如 .jsp 就实例化一个内含 ApplicationContext 的 servlet 去处理?因为它们都是 java 编写的,所以它们之间嵌套,并最终在 JVM 这个环境上执行。
而不是像 apache + fpm , apache 只负责静态资源,动态资源每次申请创建新的解释器进程,通过 cgi 标准来通信。 是不是可以这样理解~ |
24
lml12377 OP @guoziyan 是不是常驻型的可以自己实现容器,容器内自己处理静态请求的同时处理动态请求,相当于它自己既充当了 http 服务器的角色,又充当了 application server 的角色(每次这么打比方都有点怕。。。)
假设我用 c 写了一个程序,本身可以处理静态请求比如 html / image ,而当用户请求 blog-list-p1.c 的时候,我还能用这个程序去连接数据库,编写可复用的组件,是不是这个就相当于 tomcat / servlet 或者 WSGI 实现的一种存在?并且还不需要 jvm 这种解释器。。。(好先进啊,你懂的。。。) |
25
lml12377 OP @SoloCompany 谢谢!有点头绪了~
|