之前已经详细讲解了Servlet/JSP的基础知识,包括Servlet和JSP的关系、Servlet基本的编写和配置,以及一个请求/响应过程中,HTTP服务器、web容器、Servlet是如何配合工作的。
对于一个web应用程序来说,请求/响应是其工作工程的基础,我们这里只考虑基于HTTP协议的请求/响应模型,HttpServletRequest代表请求及相关参数,HttpServletResponse代表响应及相关参数,这两个对象会随着一个请求的发起而建立,随着一个响应的结束而销毁被回收。当一个请求到来时,HttpServlet会执行service()方法,在其中判断当前HTTP的请求方式(包括GET、POST、PUT、DELETE、HEAD、OPTIONS、TRACE),并创建HttpSevletRequest和HttpServletResponse对象,传给请求方式对应的方法doXXX()。
关于HttpSevletRequest,相关的知识无非就是请求参数的获取、编码处理、文件上传接收、请求重定向等,下面把常用的知识点整理一下,并附上demo。
获取请求参数与标头
HttpSevletRequest里面封装了获取请求参数的方法,请求参数是以键值对的形式存储在其中的,下面是相关方法:
方法
说明
String getParameter(String key)
通过请求参数名称获取参数值
String[] getParameterValues(String key)
同上,有时候请求参数名称对应多个值
Enumeration getParameterNames()
获取所有参数名称
Map getParameterMap()
请求参数以Map对象返回
对于HTTP的标头(Header)信息,可以使用下面的方法来获得:
方法
说明
String getHeader(String key)
类似getParamater()
String[] getHeaders(String key)
类似getParamaterValues()
Enumeration getHeaderNames()
类似getParamaterNames()
请求参数编码处理
获取请求参数,编码是一定要考虑的,否则容易出现乱码,好在现在的框架帮我们完成了大部分编码处理的操作。什么情况下容易出现乱码呢?当客户端设置的编码和web容器使用的编码不一致时,最容易出现乱码。客户端的编码是我们自己设置的,web容器的编码一般是在一个请求中,在Content-Type表头中设置的,例如“ContentType: text/html;
charset=UTF-8”就是告诉web容器:“你web容器想要获取正确的参数,就得用UTF-8解码,否则出现了问题别怪我客户端没提醒你!”。我们可以在HttpServletRequest中通过getCharacterEncoding()方法获取当前请求的编码,若客户端没有在标头中设置编码信息,这个方法将返回null,然后web容器默认使用IOS-8859-1(这是大部分浏览器默认的字符集)解码。
下面我们只讨论POST和GET两种最常用的请求方式下的编码处理。
POST
客户端会将参数封装到请求中,假如客户端的编码方式是UTF-8,它在封装参数的时候,相当于执行下面这段代码:
String parameter = .URLEncoder.encode(value, "UTF-8");
然后web容器把请求和参数交给Servlet,在Servlet中取得请求参数时,若没有提前设置编码,则默认使用ISO-8859-1来解码,相当于执行了下面这段代码:
String parameter = .URLEncoder.encode(value, "ISO-8859-1");
因为编码和解码使用的字符集不一样,所以就出现了乱码。
解决方式是在客户端发起请求的Content-Type标头中设置编码(charset=UTF-8),在Servlet中获取请求参数前,调用request.setCharacterEncoding():
request.setCharacterEncoding("GBK");
GET
为什么POST和GET不一样呢?因为POST和GET的传参方式不同,在HttpServletRequest的API中对serCharacterEncoding()有如下说明:
Overides the name of the character encoding userd in the body of this request 意思就是这个方式只对请求Body中的字符编码才有用,也就是说这个方法基本上只对POST有用,因为GET传参是通过URL实现的,而URL的处理是HTTP服务器来完成的,并非Web容器,所以要使用GET方式传参,其编码处理方式就不同了。
还是上面的例子,客户端的编码方式是UTF-8,执行下面代码,通过GET方式请求:
String parameter = .URLEncoder.encode(value, "UTF-8"); 因为使用GET方式,所以web容器设置啥编码都没用了,默认使用ISO-8859-1解码:
String parameter = .URLEncoder.encode(value, "ISO-8859-1"); 然后我们得在Servlet中这样解码:
String parameter = new String(value.getBytes("ISO-8859-1"), "utf-8");
下面以一个例子来演示这两种请求方式在编码处理中的差别:
test-get.html
发送GET请求
test-post.html
发送POST请求
HelloServlet.java
@WebServlet("/hello.view")
public class HelloServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String name = request.getParameter("username");
name = new String(name.getBytes("ISO-8859-1"), "GBK");
System.out.println("GET:" + name);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("GBK");
String name = request.getParameter("username");
System.out.println("POST:" + name);
}
}