在上一章讲解了何为Servlet,剖析其内部的源码研究其生命周期方法。上一章链接
这一章主要讲的是在Servlet中service方法调入的两个重要对象HttpServletRequest和HttpServletResponse。
目录
Request
首先,先看一张图
从上面的图可知,客户端将请求数据封装到request中传递给服务器。那么这请求数据里又包含了请求头、请求体、请求行。在这里只挑选几个比较需要知道的方法去分别演示三种请求数据的处理。
附:在第一章的时候提及过,request在service中实际的类型是org.apache.catalina.connector.RequestFacade,而RequestFacade实现HttpServletRequest接口,HttpServletRequest接口又继承ServletRequest接口。
获取请求行
请求行包括了请求方式、请求资源、协议三部分内容,通过request中的一些方法可以获取相关数据。
1.获取客户端IP
根据上面所附可知,在ServletRequest类中有一个方法来获取客户端的IP
public abstract String getRemoteAddr();
getRemoteAddr()在ServletRequest类中是一个抽象方法,具体的实现由遵守JavaEE标准的应用服务器来实现。在Tomcat中,实现这个抽象方法的类是RequestFacade,但其实是RequestFacade中有一个Request类的对象request去调用另一个同名方法。
【了解】究其源码,发现是coyote包中的一个Final类Request。该类实例化后许多参数不会被jvm的垃圾回收机制回收。并且该类所拥有的信息不会在初始化的时候就转换成可被用户直接使用的字符串的形式,大部分是以MessageBytes的形式存放,在被用户使用的时候才会进行转换,这样就大大提高了服务器的处理效率。
用例代码如下所示:
protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
String addr = req.getRemoteAddr();
System.out.println("IP:" + getIpAddr(req));
}
通过localhost:8080/java_web/A3Servlet和127.0.0.1:8080/java_web/A3Servlet分别访问后得到的结果如下:
第一个显示的结果为IPV6地址,localhost是域名,可以被赋予任意一个IP地址,但通常都是被赋予127.0.0.1或者IPV6的[::1]。当服务器和客户端在同一个电脑时,就会显示localhost的值,如果是他人电脑请求该Servlet,则会显示其客户端的真实地址。
2.获取请求方式以及获取客户端信息
请求方式中包括了GET、POST、PUT等,客户端信息包含了操作系统、浏览器等相关信息。
用例代码如下所示:
protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
String addr = req.getRemoteAddr();
System.out.println("IP:" + addr);
System.out.println("请求方式:" + req.getMethod());
String userAgent = req.getHeader("User-Agent");
if(userAgent.toLowerCase().contains("chrome")) {
System.out.println("谷歌访问");
} else if(userAgent.toLowerCase().contains("firefox")) {
System.out.println("火狐访问");
} else if(userAgent.toLowerCase().contains("msie")) {
System.out.println("IE访问");
}
System.out.println("User-Agent:" + userAgent);
}
通过Google Chrome浏览器和IE浏览器分别访问该Servlet,结果如下:
3.获取请求URL
源码部分依旧在coyote包中的一个Final类Request中。主要方法有:
String getScheme(); // 获取请求协议
String getServerName(); // 获取服务器名称
String getServerPort(); // 获取服务器端口号
String getContextPath(); // 获取项目名
String getServletPath(); // 获取Servlet路径名
String getQueryString(); // 获取参数部分
String getRequestURI(); // 获取请求URI
String getRequestURL(); // 获取请求URL
上面所列举的方法自行测试,请求行的部分就这么多,接下来讲请求头。
获取请求头
在请求头中有一个属性Referer用于防盗链,何为防盗链,就像在某个论坛的图片复制后不能被其他的网站显示出来。
Referer用于告诉服务器是从哪个页面链接过来的,服务器就可以作出相关处理。
在HttpServletRequest定义了四个方法来获取请求头:
//适用于单值请求头
String getHeader(String name);
//适用于单值int类型的请求