REQUEST对象
request对象是JSP中重要的对象,每个request对象封装着一次用户请求,并且所有的请求参数都被封装在request对象中,因此request对象是获取请求参数的重要途径。
除此之外,request可代表本次请求范围,所以还可用于操作request范围的属性。
1. 获取请求参数
Web应用是请求/响应架构的应用,浏览器发送请求时可能需要将一些请求参数发送给服务器,服务器端负责解析请求参数的就是JSP或Servlet,而JSP和Servlet取得请求参数的途径就是request。request是HttpServletRequest接口的实例,它提供了如下几个方法来获取请求参数:
String getParameter(String paramName):获取paramName请求参数的值。
Map getParameterMap():获取所有请求参数名和参数值所组成的Map对象。
Enumeration getParameterNames():获取所有请求参数名所组成的Enumeration对象。
String[] getParameterValues(String name):paramName请求参数的值,当该请求参数有多个值时,该方法将返回多个值所组成的数组。
客户端发送请求参数通常分两种情况:
GET方式的请求:直接在浏览器地址栏输入访问地址所发送的请求,或提交表单发送请求时,该表单对应的form元素没有设置method属性,或设置method属性为get,这几种请求都是GET方式的请求。GET方式的请求会将请求参数的名和值转换成字符串,并附加在原URL之后,因此可以在地址栏中看到请求参数名和值。且GET请求传送的数据量较小,一般不能大于2KB。
POST方式的请求:这种方式通常使用提交表单(由form HTML元素表示)的方式来发送,且需要设置form元素的method属性为post。POST方式传送的数据量较大,通常认为POST请求参数的大小不受限制,但往往取决于服务器的限制,POST请求传输的数据量总比GET传输的数据量大。而且POST方式发送的请求参数以及对应的值放在HTML HEADER中传输,用户不能在地址栏里看到请求参数值,安全性相对较高。
对比上面两种请求方式,由此可见我们通常应该采用POST方式发送请求。
几乎每个网站都会大量使用表单,表单用于收集用户信息,一旦用户提交请求,表单的信息将会提交给对应的处理程序,如果为form元素设置method属性为post,则表示发送POST请求。
下面是表单页面的代码。
Code
<%@ page contentType="text/html; charset=gb2312" language="java" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<TITLE>收集参数的表单页</TITLE>
</HEAD>
<BODY>
<FORM id="form1" METHOD="post" ACTION="request1.jsp">
用户名:<br>
<INPUT TYPE="text" NAME="name">
<hr>
性别:<br>
男:<INPUT TYPE="radio" NAME="gender" value="男">
女:<INPUT TYPE="radio" NAME="gender" value="女">
<hr>
喜欢的颜色:<br>
红:<INPUT TYPE="checkbox" NAME="color" value="红">
绿:<INPUT TYPE="checkbox" NAME="color" value="绿">
蓝:<INPUT TYPE="checkbox" NAME="color" value="蓝">
<hr>
来自的国家:<br>
<SELECT NAME="country">
<option value="中国">中国</option>
<option value="美国">美国</option>
<option value="俄罗斯">俄罗斯</option>
</SELECT>
<hr>
<INPUT TYPE="submit" value="提交">
<INPUT TYPE="reset" value="重置">
</FORM>
</BODY>
</HTML>
在该页面中输入相应信息后,单击“提交”按钮,表单域所代表的请求参数将通过request对象的getParameter()方法来取得。
并不是每个表单域都会生成请求参数的,而是有name属性的表单域才生成请求参数。关于表单域和请求参数的关系遵循如下4点:
每个有name属性的表单域对应一个请求参数。
如果有多个表单域有相同的name属性,则多个表单域生成一个请求参数,只是该参数有多个值。
表单域的name属性指定请求参数名,value指定请求参数值。
如果某个表单域设置了disabled="true"属性,则该表单域不再生成请求参数。
上面的表单页向request1.jsp页面发送请求,该页面的代码如下:
Code
<%@ page contentType="text/html; charset=gb2312" language="java" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<TITLE>获取请求参数</TITLE>
</HEAD>
<BODY>
<%
//设置request编码的字符集方式,简体中文使用gb2312字符集request.setCharacterEncoding("gb2312");
//下面依次获取表单域的值
String name = request.getParameter("name");
String gender = request.getParameter("gender");
//如果某个请求参数有多个值,将使用该方法获取多个值
String[] color = request.getParameterValues("color");
String national = request.getParameter("country");%>
<!-- 下面依次输出表单域的值 -->
您的名字:<%=name%><hr>
您的性别:<%=gender%><hr>
<!-- 输出复选框获取的数组值 -->
您喜欢的颜色:<%for(String c : color) {out.println(c + " ");}%>
<hr>
您来自的国家:<%=national%><hr>
</BODY>
</HTML>
在获取表单域的值之前,先设置request编码的字符集——如果POST请求的请求参数里包含非西欧字符,则必须在获取请求参数之前来取得调用setCharacterEncoding()方法设置编码的字符集。
因此发送请求的表单页采用gb2312字符集,所以该表单页发送的请求也将采用gb2312字符集,所以本页面需要先执行如下方法:
setCharacterEncoding("gb2312"):设置request编码所用的字符集。
如果需要传递的参数是普通字符串,而且仅需传递少量参数时,可以选择使用GET方式发送请求参数,GET方式发送的请求参数被附加到地址栏的URL之后,地址栏的URL将变成如下形式:
url?param1=value1¶m2=value2&…paramN=valueN:URL和参数之间以“?”分隔,而多个参数之间以“&”分隔。
通过setCharacterEncoding("gb2312")只能解决POST方式的编码问题,GET的话他就无能为力了,可以通过以下方式解决:
Code
//获取原始的请求参数值
String rawName = request.getParameter("name");
//将请求参数值使用ISO-8859-1字符串分解成字节数组
byte[] rawBytes = rawName.getBytes("ISO-8859-1");
//将字节数组重新编码成字符串
String name = new String(rawBytes , "gb2312");
2. 操作request范围的属性
HttpServletRequest还包含如下两个方法,用于设置和获取request范围的属性:
setAttribute(String attName , Object attValue):将attValue设置成request范围的属性。
Object getAttribute(String attName):获取request范围的属性。
当forward用户请求时,请求的参数和请求属性都不会丢失。看下一个JSP页面,这个JSP页面是个简单的表单页,用于提交用户请求。
Code
<%@ page contentType="text/html; charset=gb2312" language="java" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<TITLE>取钱的表单页</TITLE>
</HEAD>
<BODY>
<!-- 取钱的表单 -->
<form method="post" action="first.jsp">
取钱:<input type="text" name="balance">
<input type="submit" value="提交">
</form>
</BODY>
</HTML>
该页面向first.jsp页面请求后,balance参数将被提交到first.jsp页面,下面是first.jsp页面的实现代码。
Code
<%@ page contentType="text/html; charset=gb2312" language="java" import="java. util.*"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD><TITLE>request处理</TITLE>
</HEAD>
<BODY>
<%
//获取请求的钱数
String bal = request.getParameter("balance");
//将钱数的字符串转换成双精度浮点数double qian = Double.parseDouble(bal);
//对取出的钱进行判断
if (qian < 500){
out.println("给你" + qian + "块");
out.println("账户减少" + qian);
}else{
//创建了一个List对象
List<String> info = new ArrayList<String>();
info.add("1111111");
info.add("2222222");
info.add("3333333");
//将info对象放入request范围内
request.setAttribute("info" , info);%>
<!-- 实现转发 -->
<jsp:forward page="second.jsp"/>
<%}%>
</BODY>
</HTML>
first.jsp页面首先获取请求的取钱数,然后对请求的钱数进行判断。如果请求的钱数小于500,则允许直接取钱;否则将请求转发到second.jsp。转发之前,创建了一个List对象,并将该对象设置成request范围的info属性。
接下来在second.jsp页面中,不仅获取了请求的balance参数,而且还会获取request范围的info属性。second.jsp页面的代码如下:
Code
<%@ page contentType="text/html; charset=gb2312" language="java" import="java. util.*"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<TITLE>request处理</TITLE>
</HEAD>
<BODY>
<%
//取出请求参数
String bal = request.getParameter("balance");
double qian = Double.parseDouble(bal);
//取出request范围内的info属性
List<String> info = (List<String>)request.getAttribute("info");
for (String tmp : info){
out.println(tmp + "<br>");
}
out.println("取钱" + qian + "块");
out.println("账户减少" + qian);
%>
</BODY>
</HTML>
如果页面请求的钱数大于500时,请求将被转发到second.jsp页面处理,而且在second.jsp页面中可以获取到balance请求参数值,也可获取到request范围的info属性,这表明:forward用户请求时,请求参数和request范围的属性都不会丢失,即forward动作还是原来的请求,并未再次向服务器发送请求。
如果请求取钱的钱数为654,则页面的执行效果如图所示。
3. 执行forward或include
request还有一个功能就是执行forward和include,也就是代替JSP所提供的forward和include动作指令。前面我们需要forward时都是通过JSP提供的动作指令进行的,实际上request对象也可以执行forward。
HttpServletRequest类提供了一个getRequestDispatcher(String path)方法,其中path就是希望forward或者include的目标路径,该方法返回RequestDispatcher,该对象提供了如下两个方法:
forward(ServletRequest request, ServletResponse response):执行forward。
include(ServletRequest request, ServletResponse response):执行include。
如下代码行可以将a.jsp页面include到本页面中:
getRequestDispatcher("/a.jsp").include(request , response);
如下代码行则可以将请求forward到a.jsp页面:
getRequestDispatcher("/a.jsp").forward(request , response);
使用request的getRequestDispatcher(String path)方法时,该path字符串必须以斜线开头。