一个Web App就是由一个或多个Servlet组成的,每个Servlet通过注解说明自己能处理的路径。例如:
上述HelloServlet能处理/hello这个路径的请求。
早期的Servlet需要在web.xml中配置映射路径,但最新Servlet版本只需要通过注解就可以完成映射。
因为浏览器发送请求的时候,还会有请求方法(HTTP Method):即GET、POST、PUT等不同类型的请求。因此,要处理GET请求,我们要覆写doGet()方法:
类似的,要处理POST请求,就需要覆写doPost()方法。
如果没有覆写doPost()方法,那么HelloServlet能不能处理POST /hello请求呢?
我们查看一下HttpServlet的doPost()方法就一目了然了:它会直接返回405或400错误。因此,一个Servlet如果映射到/hello,那么所有请求方法都会由这个Servlet处理,至于能不能返回200成功响应,要看有没有覆写对应的请求方法。
一个Webapp完全可以有多个Servlet,分别映射不同的路径。例如:
浏览器发出的HTTP请求总是由Web Server先接收,然后,根据Servlet配置的映射,不同的路径转发到不同的Servlet:
这种根据路径转发的功能我们一般称为Dispatch。映射到/的IndexServlet比较特殊,它实际上会接收所有未匹配的路径,相当于/*,因为Dispatcher的逻辑可以用伪代码实现如下:
HttpServletRequest
HttpServletRequest封装了一个HTTP请求,它实际上是从ServletRequest继承而来。最早设计Servlet时,设计者希望Servlet不仅能处理HTTP,也能处理类似SMTP等其他协议,因此,单独抽出了ServletRequest接口,但实际上除了HTTP外,并没有其他协议会用Servlet处理,所以这是一个过度设计。
我们通过HttpServletRequest提供的接口方法可以拿到HTTP请求的几乎全部信息,常用的方法有:
getMethod():返回请求方法,例如,“GET”,“POST”;
getRequestURI():返回请求路径,但不包括请求参数,例如,"/hello";
getQueryString():返回请求参数,例如,“name=Bob&a=1&b=2”;
getParameter(name):返回请求参数,GET请求从URL读取参数,POST请求从Body中读取参数;
getContentType():获取请求Body的类型,例如,“application/x-www-form-urlencoded”;
getContextPath():获取当前Webapp挂载的路径,对于ROOT来说,总是返回空字符串"";
getCookies():返回请求携带的所有Cookie;
getHeader(name):获取指定的Header,对Header名称不区分大小写;
getHeaderNames():返回所有Header名称;
getInputStream():如果该请求带有HTTP Body,该方法将打开一个输入流用于读取Body;
getReader():和getInputStream()类似,但打开的是Reader;
getRemoteAddr():返回客户端的IP地址;
getScheme():返回协议类型,例如,“http”,“https”;