1、Tomcat和Servlet的关系
之前提到过,Servlet是运行在Web容器里的,Tomcat作为容器的一种,在这里自然也要大概说说两者之间的大致关系。
首先,如上所述,Tomcat是Web应用服务器,是一个Servlet/JSP容器。它负责处理客户请求,把请求传送给Servlet,并将Servlet的响应传回给客户。而Servlet是运行在支持Java语言的服务器上的组件。
从HTTP协议中的请求和响应就可以得知,浏览器发出的请求是一个请求文本,而浏览器接收到的也应该是一个响应文本。而在Web服务器中,容器将其分别封装成了对象,以便于我们进行操作:
- Tomcat将HTTP请求文本接收并解析,然后封装成HttpServletRequest类型的request对象,所有的HTTP头数据读取可以通过request对象调用对应的方法查询到;
- Tomcat同时将响应的信息封装为HttpServletResponse类型的response对象,通过设置response属性就可以控制要输出到浏览器的内容,然后将response交给Tomcat,Tomcat就会将其变成响应文本的格式发送给浏览器
2、请求对象的由来
Servlet类中我们往往要覆盖两个方法,doGet和doPost,而它们都有两个参数,分别是HttpServletRequest和HttpServletResponse,分别为请求和响应。
实际上,这两个类型都是接口,具体的实现类实际上是由容器实现的,其实也就是我们上面已经说明了的,是由Tomcat服务器将请求和响应进行了分别的封装,然后拿给我们使用。
我们可以使用System.out.println方法分别打印doGet和doPost方法中的形参request和response,你可以在控制台看到:
- org.apache.catalina.connector.RequestFacade
- org.apache.catalina.connector.ResposneFacade
我们可以看下API,实际上也确实是这样说明的,以请求对象为例:
Extends the ServletRequest interface to provide request information for HTTP servlets.
The servlet container creates an HttpServletRequest object and passes it as an argument to the servlet‘s service methods (doGet, doPost, etc).
3、HttpServletRequest接口
如下API,可以看到,因为请求中大部分数据是直接封装进去的,所以基本上都是get方法:
拿 getParameter(String name) 这个方法来示例,该方法是获取随着请求一起传递过来的额外信息,常见的如我们的账户密码登陆的表单提交,其中的name对应的是表单中input的name属性值,这其实在提交后的过程中也是容器帮我们封装好的。
如果是诸如checkbox多选框表单的提交,那么获取值的时候则使用 getParameterValues(String name),返回的是String类型的数组。
其他的get方法这里不再详细进行展开,可以参看API。
4、响应重定向和请求转发
我们知道,请求到达Servlet之后,往往还需要进一步的跳转到其他页面,因为之前已经说过,Servlet现在的作用还是用来做控制,而不再进行页面资源输出了。
所以在Servlet中有两种跳转方式:
- 响应重定向
- 请求转发
4.1 响应重定向
标准意义上的“重定向”指的是HTTP重定向,它是HTTP协议规定的一种机制。
这种机制是这样工作的:当client向server发送一个请求,要求获取一个资源时,在server接收到这个请求后发现请求的这个资源实际存放在另一个位置,于是server在返回的response中写入那个请求资源的正确的URL,并设置reponse的状态码为301(表示这是一个要求浏览器重定向的response),当client接受到这个response后就会根据新的URL重新发起请求。重定向有一个典型的特症,即当一个请求被重定向以后,最终浏览器上显示的URL往往不再是开始时请求的那个URL了(浏览器地址会变化)。
HttpServletResponse中定义了响应重定向的方法 sendRedirect(String path),该方法向目标资源重新发送请求,生成新的响应,并且:
- 重定向使用GET方式提交
- 重定向生成的是新的请求,所以当前请求中的数据不会随着新的请求而传递
4.2 请求转发
请求转发也称之为服务器端重定向,它指的是服务器在处理request的过程中将request先后委托多个Servlet或JSP接替进行处理的过程。
最为常见的是先由一个Servlet处理(比如实现业务逻辑的计算),然后forward给一个JSP进行视图的渲染,或者forward给另一个Servlet进一步处理。使用服务器端重定向,浏览器地址不会发生变化。因为浏览器只执行了对某个页面A的请求,而这个页面的服务器内部的跳转(或许还经过了页面B和页面C的处理)情况浏览器是不知道的,它只知道自己获得的响应是A页面发回来的,甚至不知道服务器中有多个Servlet处理。
在Servlet中,要先使用HttpServletRequest请求中的 getRequestDispatcher(String path) 获取请求转发器对象,然后调用该对象的 forward(request, response) 方法进行跳转。
往往以连写的方式,如下示例:
request.getRequestDispatcher(String path).forward(request, response);