V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
abcbuzhiming
V2EX  ›  Java

servlet(容器?规范?实现?)为啥会在 url 路径这个问题上设计的如此古怪?

  •  1
     
  •   abcbuzhiming · 2017-05-16 20:05:35 +08:00 · 3494 次点击
    这是一个创建于 2752 天前的主题,其中的信息可能已经有所发展或是发生改变。
    我是最近才注意到这一点,其他有 http 实现的语言(框架),基本上,在 http 地址解析这个问题上,会倾向于把域名根路径“/”之后开始的部分视为一个整体,嗯,最多就是可能会把路径的最后部分——如果有后缀名的话——视为文件本身。比如 http://www.v2ex.com/aaa/bbb/ccc/ddd/123.txt。那么请求路径就是 /aaa/bbb/ccc/ddd/。这是一个整体,一般不会再拆分。但是在 servlet 的实现上,有两个东西,1 个叫 servletPath ( request.getServletPath()),一个叫 pathinfo ( request.getPathInfo())。而且很有意思的是,这两个东西的值是和 web.xml 配置文件中的 url-pattern 所采用的模式有关,我想了很长时间,没想明白这样的意义在哪里,为啥 servlet 在设计上没有把 /aaa/bbb/ccc/ddd/视为一个整体,而专门搞了 ServletPath,PathInfo。这应该是有某种作用的
    12 条回复    2017-05-17 23:47:33 +08:00
    sagaxu
        1
    sagaxu  
       2017-05-16 20:34:33 +08:00 via Android
    因为一个 webserver 上要跑多个 webapps 啊,/app1/path,/app2/path,...
    abcbuzhiming
        2
    abcbuzhiming  
    OP
       2017-05-16 21:19:29 +08:00
    @sagaxu 然而你说的这个 app 其实指的是 ContextPath

    http://blog.csdn.net/cooljia/article/details/187882
    你可以看这篇文章,说的很详细,
    Context Path + servlet path + path info = request uri
    这里的关键就是为啥会分 servlet path 和 path info。把 Context Path 单独列出来是可以理解的,作为隔离应用的措施,但是后两者是干嘛的呢
    echo1937
        3
    echo1937  
       2017-05-16 21:32:34 +08:00
    这个问题我在学习 Servlet 时也发现了,当时有类似想法,但没有深究。
    cheneydog
        4
    cheneydog  
       2017-05-16 21:50:11 +08:00
    区分 api 请求和静态文件请求的一种方式。
    SoloCompany
        5
    SoloCompany  
       2017-05-16 23:11:16 +08:00
    有什么问题吗?
    REQUEST_URI = /a/b/c.php/d/e/f?x=1
    SCRIPT_NAME = /a/b/c.php
    PATH_INFO = /d/e
    _GET = [ “ x ” => 1 ]

    是什么让你会觉得这是 java 发明的?
    abcbuzhiming
        6
    abcbuzhiming  
    OP
       2017-05-17 08:57:17 +08:00
    @cheneydog 如何个区分法,说明白一点,我专门去研究了 tomcat 对静态文件的默认处理,发现它默认是通过“/”这个路径映射的 servlet 处理的,此时整个静态文件地址都是 servletPath,pathinfo 为空了。如果按 servletPath 存在就按 api 请求理解的话,好像没有 servletpath 不存在的时候
    abcbuzhiming
        7
    abcbuzhiming  
    OP
       2017-05-17 09:01:23 +08:00
    @SoloCompany 你这有点强词夺理了,你提的 php 中的这个 pathinfo 是 CGI 中的标准,它最初的含义指的是描述你所调用的这个 php 文件在服务器上的真实位置。然而后来大部分 php 框架利用这点,把它当成了地址映射。CGI 和 servlet 是一回事吗? servlet 里的这个 pathinfo 可不是出现在 jsp 后面的,你要能证明 CGI 中的这个 pathinfo 和 servlet 存在渊源或者有原理设计上的类似,请给出证据
    SoloCompany
        8
    SoloCompany  
       2017-05-17 09:25:58 +08:00
    @abcbuzhiming #7 我用得着去证明吗?是不是一回事你自己不会判断?就你这语气本来不想再回复了,算是知道什么叫做永远叫不醒一个自以为是的人。这是最后一条回复,你自己爱怎么理解就怎么理解吧

    <servlet>
    <servlet-name>c.jsp</servlet-name>
    <jsp-file>/a/b/c.jsp</jsp-file>
    </servlet>

    <servlet-mapping>
    <servlet-name>c.jsp</servlet-name>
    <url-pattern>/a/b/c.jsp/*</url-pattern>
    </servlet-mapping>

    自己去看一下早期 jsp 引擎是怎么实现的
    以及后来 jsp 的默认 mapping 怎么又被规范为了 *.jsp, 而规范不支持 *.jsp/* 这种类型的 mapping 只能通过手工加入
    abcbuzhiming
        9
    abcbuzhiming  
    OP
       2017-05-17 21:57:42 +08:00
    @SoloCompany 首先,我为我的语气道歉,你是对的,我找了一圈,pathinfo 就是对应的 CGI 变量 pathinfo。这一点在 orcale 的文档里有描述,虽然我还是没找到这样设计的理由。貌似有点吸引早期的 CGI 程序的开发者的意思。另外你说的最后一句话,早期 jsp 引擎实现和后来被规范成*.jsp,我没有找到相关的资料,请不吝赐教
    SoloCompany
        10
    SoloCompany  
       2017-05-17 23:34:35 +08:00
    @abcbuzhiming 早期 jsp 引擎的实现和 php 是比较类似的,就是类似 *.jsp/* 都会被 jsp 引擎处理,只要路径中包含 jsp (并且文件存在),就会被映射
    但是会存在歧义
    比如 /1.jsp/2.jsp/3 并且这两个路径下的 jsp 文件都存在
    那应该是映射为 servletPath=/1.jsp, pathInfo=/2.jsp/3 呢
    还是 servletPath=/1.jsp/2.jsp, path=/3
    完全依赖引擎的实现, Servlet 规范里面并没有这种定义的支持.

    Servlet 规范的 mapping 只支持一个 *,即要么按文件名后缀 map ( pathInfo 永远是 null) 要么按前缀来 map, 而且必须是 ‘/*’ (/* 代表的就是 pathInfo)

    默认的 jsp servlet mapping 的定义是写在 CATALINA_BASE/web.xml 里面, 就是 *.jsp, 通过这个 mapping 的请求也一定没有 path info

    默认配置还有一个 DefaultServlet, 用来服务静态文件

    至于 tomcat 的 jsp 引擎什么时候变更为和规范一致,我已经不记得了,只记得很早的时候是可以 (带 path) 的,后来就不可以了,也很可能是 tomcat 一直都默认不可以带 path 而是其它引擎( resin / jetty 之类的) 可以
    搜了一下也只能找到这个帖子 http://tomcat.10.x6.nabble.com/troubleshooting-getPathInfo-in-jsp-files-td2158648.html

    最后,无论是哪个语言的 HTTP 服务引擎, 所面对的概念都没有什么太大差别, 基本上都遵循 CGI 的定义,你看 javadoc 的时候没看到 request.getXXX 的说明很多都有说明是相当于 CGI 的哪个环境变量吗?
    abcbuzhiming
        11
    abcbuzhiming  
    OP
       2017-05-17 23:39:37 +08:00
    @SoloCompany 最后那段话的意思,是不是可以说现有的 Http 服务器的技术源头,或者说鼻祖都来源于 CGI ?都受到 CGI 的历史影响?那这个地球上有没有完全和 CGI 无关的 Http 服务器实现啊?
    SoloCompany
        12
    SoloCompany  
       2017-05-17 23:47:33 +08:00
    @abcbuzhiming 我不觉得这算是什么技术源头吧,因为 CGI 是最早的服务器编程方式,所有人都熟悉,专家也熟悉,制订标准的时候肯定也会参考,但同时也会做一些修改,比如 CGI 的 SCRIPT_NAME 环境变量在 Servlet 里面就改名为了 ServletPath, javadoc 里面都相关映射的说明
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1052 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 21:33 · PVG 05:33 · LAX 13:33 · JFK 16:33
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.