您的位置:首页 > 产品设计 > UI/UE

request对象

2016-07-16 11:12 531 查看

HttpServletRequest介绍

HttpServletRequest对象代表客户端的请求,当客户端通过HTTP协议访问服务器时,HTTP请求头中的所有信息都封装在这个对象中,开发人员通过这个对象的方法,可以获得客户这些信息。

Request常用方法

获得客户机信息

getRequestURL方法返回客户端发出请求时的完整URL。

getRequestURI方法返回请求行中的资源名部分。

URI——用于标识(任意)一个资源,如
/news/1.html
c:\abc\a.txt


URL——用于标识互联网上的一个资源,如
http://www.sina.com/news/1.html


所以URI包含URL。

getQueryString方法返回请求行中的参数部分。

getPathInfo方法返回请求URL中的额外路径信息。额外路径信息是请求URL中的位于Servlet的路径之后和查询参数之前的内容,它以“/”开头。

getRemoteAddr方法返回发出请求的客户机的IP地址。

getRemoteHost方法返回发出请求的客户机的完整主机名。

getRemotePort方法返回客户机所使用的网络端口号。

getLocalAddr方法返回WEB服务器的IP地址。

getLocalName方法返回WEB服务器的主机名。

范例:通过request对象获取客户端请求信息。

// request的常用方法
public class RequestDemo1 extends HttpServlet {

protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// getRequestURI()得到你访问的资源
System.out.println(request.getRequestURI()); // 打印/day06/RequestDemo1
System.out.println(request.getRequestURL()); // 打印http://localhost:8080/day06/RequestDemo1
// http://localhost:8080/day06/RequestDemo1?name=aaa System.out.println(request.getQueryString());
System.out.println("----------------------------------");
System.out.println(request.getRemoteAddr()); // 打印127.0.0.1
System.out.println(request.getRemoteHost());
System.out.println(request.getRemotePort());
System.out.println(request.getMethod()); // 得到请求URL地址时使用的方法
}

protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}

}


运行:



获得客户机请求头

getHeader(string name)方法:String。

getHeaders(String name)方法:Enumeration。

getHeaderNames()方法。

范例:通过request对象获取客户端请求头信息。

// 获取请求头
public class RequestDemo2 extends HttpServlet {

protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("------------------获取请求头方式1------------------");
String headValue = request.getHeader("Accept-Encoding"); // 根据请求头的名字获取对应的请求头的值
System.out.println(headValue);
System.out.println("------------------获取请求头方式2------------------");
Enumeration<String> e = request.getHeaders("Accept-Encoding"); // 根据请求头的名字获取所有对应请求头的值
while(e.hasMoreElements()) {
String value = e.nextElement();
System.out.println(value);
}
System.out.println("------------------获取请求头方式3------------------");
e = request.getHeaderNames(); // 获取所有的请求头
while(e.hasMoreElements()) {
String name = e.nextElement();
String value = request.getHeader(name);
System.out.println(name+"="+value);
}
}

protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}

}


获得客户机请求参数(客户端提交的数据)

getParameter(String)方法(常用)。

getParameterValues(String name)方法(常用)。

getParameterNames()方法(不常用)。

getParameterMap()方法(编写框架时常用)。

比如现在有如下的form表单——test.html:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>带数据给RequestDemo2</title>
</head>
<body>
<!-- url后面如果跟了中文数据,要编码后再提交 -->
<a href="/day06/RequestDemo2?username=zzz">点点</a>

<form action="/day06/RequestDemo2" method="post">
用户名1:<input type="text" name="username"><br/>
用户名2:<input type="text" name="username"><br/>
密码:<input type="text" name="password"><br/>
<input type="submit" value="提交">
</form>
</body>
</html>


必须注意:url后面如果跟了中文数据,要编码后再提交。如:

<a href="/day06/RequestDemo2?username=中国">点点</a>


在form表单中填写数据,然后提交到RequestDemo2这个Servlet进行处理,填写的表单数据如下:



在服务器端使用getParameter方法和getParameterValues方法接收表单参数,代码如下:

// 获取请求数据(获取请求数据时一般来说都要先检查再使用)
public class RequestDemo2 extends HttpServlet {

protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("-----------------获取数据方式1----------------------");
String value = request.getParameter("username");
// 获取请求数据时一般来说都要先检查再使用
if(value!=null && !value.trim().equals("")) {
System.out.println(value);
}
System.out.println("-----------------获取数据方式2----------------------");
String[] values = request.getParameterValues("username");
/*
for(String v : values) {
System.out.println(v);
}
*/
// 获取数组数据的技巧,可以避免values数组为null时引发的空指针异常错误!
for(int i=0;values!=null && i<values.length;i++) {
System.out.println(values[i]);
}
}

protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}

}


在服务器端使用getParameterNames方法接收表单参数,代码如下:

// 获取请求数据(获取请求数据时一般来说都要先检查再使用)
public class RequestDemo2 extends HttpServlet {

protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("-----------------获取数据方式3----------------------");
Enumeration<String> e = request.getParameterNames(); // 获取所有的参数名
while(e.hasMoreElements()) {
String name = e.nextElement(); // username password
value = request.getParameter(name);
System.out.println(name+"="+value);
}
}

protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}

}


在服务器端使用getParameterMap方法接收表单参数。

此时要通过一个JavaBean来封装从表单提交过来的数据,设计一个表示用户的JavaBean——User.java。

public class User {
private String username[];
private String password;
public String[] getUsername() {
return username;
}
public void setUsername(String[] username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}

}


在服务器端使用getParameterMap方法接收表单参数,然后用map集合的数据填充bean。

// 获取请求数据(获取请求数据时一般来说都要先检查再使用)
public class RequestDemo2 extends HttpServlet {

protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("-----------------获取数据方式4----------------------");
Map<String, String[]> map = request.getParameterMap();

User user = new User();
try {
/*
* 在实际开发中,非常实用
* 用map集合的数据填充bean
*/
BeanUtils.populate(user, map);

/*
* 在实际开发中,也是非常实用
* 从formbean将属性拷贝到user中去,bean的拷贝
*/
// BeanUtils.copyProperties(user, formbean);
} catch (Exception e1) {
e1.printStackTrace();
}
System.out.println(user);
}

protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}

}


此时涉及到Beanutils工具包的使用,可参考我的笔记内省

在服务器端使用getInputStream方法接收表单参数,通常用在获取文件上传上。

// 获取请求数据(获取请求数据时一般来说都要先检查再使用)
public class RequestDemo2 extends HttpServlet {

protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("-----------------获取数据方式5----------------------");
// 通常用在获取文件上传上
InputStream in = request.getInputStream();
int len = 0;
byte[] buffer = new byte[1024];
while((len=in.read(buffer)) != -1) {
System.out.println(new String(buffer, 0, len));
}
}

protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}

}


以上代码运行之后,没有显示出数据,我不知道为什么,谁能告诉下我!!!

各种表单输入项数据的获取

比如现在有如下的form表单——form.html:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>各种表单输入项数据的获取</title>
</head>
<body>
<form action="/day06/RequestDemo3" method="post">
用户名:<input type="text" name="username"><br/>
密码:<input type="password" name="password"><br/>
性别:
<input type="radio" name="gender" value="male">男
<input type="radio" name="gender" value="female">女<br/>
所在地:
<select name="city">
<option value="beijing">北京</option> <!-- value代表提交给服务器的值,每一个数据必须要有一个名称,服务器根据名称获取对应的值-->
<option value="shanghai">上海</option>
<option value="wuhan">武汉</option>
</select><br/>
爱好:
<input type="checkbox" name="likes" value="sing">唱歌
<input type="checkbox" name="likes" value="dance">跳舞
<input type="checkbox" name="likes" value="basketball">篮球
<input type="checkbox" name="likes" value="football">足球<br/>
备注: <textarea rows="6" cols="60" name="description"></textarea><br/>
大头照: <input type="file" name="image"><br/>
<input type="hidden" name="id" value="123456"> <!-- 隐藏输入项 -->
<input type="submit" value="提交">
</form>
</body>
</html>


value代表提交给服务器的值,每一个数据必须要有一个名称(name),服务器根据名称(name)获取对应的值(value)。

在form表单中填写数据,然后提交到RequestDemo3这个Servlet进行处理,填写的表单数据如下:



在服务器端接收表单参数,代码如下:

public class RequestDemo3 extends HttpServlet {

protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println(request.getParameter("username"));
System.out.println(request.getParameter("password"));
System.out.println(request.getParameter("gender"));
System.out.println(request.getParameter("city"));

String[] likes = request.getParameterValues("likes");
for(int i=0;likes!=null && i<likes.length;i++) {
System.out.println(likes[i]);
}

System.out.println(request.getParameter("description"));
System.out.println(request.getParameter("id"));
}

protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}

}


防盗链

Servlet——RequestDemo9代码:

// 防盗链
public class RequestDemo9 extends HttpServlet {

protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 得到来访者从哪个资源来访问服务器
String referer = request.getHeader("Referer");
/*
* 若来访者直接在浏览器地址栏输入http://localhost:8080/day06/RequestDemo9,
* 即来访者没从任何页面点过来,则referer == null
*/
if(referer == null || !referer.startsWith("http://localhost")) {
// 必须得用重定向,要明确告诉来访者跳到首页上面去了
response.sendRedirect("/day06/index.jsp");
return; // 重定向完了之后后面的代码不需要执行,所以要return
}

String data = "凤姐日记";
response.setContentType("text/html;charset=UTF-8");
response.getWriter().write(data);

}

protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}

}


index.jsp:

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<a href="/day06/ResponseDemo6">查看图书</a>
<br/>看广告<br/>
<a href="/day06/RequestDemo9">看凤姐</a>
</body>
</html>


运行结果:

在浏览器地址栏输入
http://localhost:8080/day06/RequestDemo9
,并回车,此时跳转到首页。



点击
看凤姐




request接收表单提交中文参数乱码问题

以POST方式提交表单中文参数的乱码问题

例如有如下的form表单页面:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>request接收中文参数乱码问题</title>
</head>
<body>
<form action="/day06/RequestDemo4" method="post">
用户名:<input type="text" name="username"><br/>
<input type="submit" value="提交">
</form>
</body>
</html>




此时在服务器端接收中文参数时就会出现中文乱码,如下所示:

public class RequestDemo4 extends HttpServlet {

protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String username = request.getParameter("username");
System.out.println(username);
}

protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}

}




post方式提交中文数据乱码产生的原因和解决办法

用抽象一点的图来表示:



用具体一点的图来表示:



可以看到,之所以会产生乱码,就是因为服务器和客户端沟通的编码不一致造成的,因此解决的办法是:在客户端和服务器之间设置一个统一的编码,之后就按照此编码进行数据的传输和接收。

由于客户端是以UTF-8字符编码将表单数据传输到服务器端的,因此服务器也需要设置以UTF-8字符编码进行接收,要想完成此操作,服务器可以直接使用从ServletRequest接口继承而来的”setCharacterEncoding(charset)”方法进行统一的编码设置。修改后的代码如下:

// 解决post提交的乱码
public class RequestDemo4 extends HttpServlet {

protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("UTF-8"); // 只对客户机的post方式提交有效
String username = request.getParameter("username");
System.out.println(username);
}

protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}

}


使用
request.setCharacterEncoding("UTF-8");
设置服务器以UTF-8的编码接收数据后,此时就不会产生中文乱码问题了。

以GET方式提交表单中文参数的乱码问题

例如有如下的form表单页面:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>request接收中文参数乱码问题</title>
</head>
<body>
<form action="/day06/RequestDemo4" method="get">
用户名:<input type="text" name="username"><br/>
<input type="submit" value="提交">
</form>
</body>
</html>




此时在服务器端接收中文参数时就会出现中文乱码,如下所示:

public class RequestDemo4 extends HttpServlet {

protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String username = request.getParameter("username");
System.out.println(username);
}

protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}

}




get方式提交中文数据乱码产生的原因和解决办法



post/get方式提交中文数据乱码产生的原因都是一样的。

对于以get方式传输的数据,request即使设置了以指定的编码接收数据也是无效的(因为它只对客户机的post方式提交有效),客户端以UTF-8的编码传输数据到服务器端,而服务器端的request对象使用的是ISO8859-1这个字符编码来接收数据,服务器和客户端沟通的编码不一致因此才会产生中文乱码的。解决办法:在接收到数据后,先获取request对象以ISO8859-1字符编码接收到的原始数据的字节数组,然后通过字节数组以指定的编码构建字符串,解决乱码问题。

// 解决get提交的乱码(手工处理)
public class RequestDemo4 extends HttpServlet {

protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String username = request.getParameter("username");
username = new String(username.getBytes("ISO8859-1"), "UTF-8");
System.out.println(username);
}

protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}

}


此时还有一个解决办法,即修改tomcat服务器的配置文件conf/server.xml,切记此方法在实际开发中不要使用。

阅读文档http://localhost:8080/docs/config/http.html,可发现两个属性:
URIEncoding
useBodyEncodingForURI




在tomcat服务器的配置文件conf/server.xml中找到如下代码,并添加属性
URIEncoding=UTF-8
或者
useBodyEncodingForURI=true


<Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>


由于我使用的是tomcat8,所以在不指定属性
URIEncoding=UTF-8
的情况下,默认就是UTF-8,所以不用修改。

public class RequestDemo4 extends HttpServlet {

protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String username = request.getParameter("username");
System.out.println(username);
}

protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}

}


以上代码输出正常,不会显示乱码。

以超链接形式传递中文参数的乱码问题

客户端想传输数据到服务器,可以通过表单提交的形式,也可以通过超链接后面加参数的形式,例如:

<a href="/day06/RequestDemo4?username=中国">点点</a>


点击超链接,数据是以get的方式传输到服务器的,所以接收中文数据时也会产生中文乱码问题,而解决中文乱码问题的方式与上述的以get方式提交表单中文数据乱码处理问题的方式一致,如下所示:

String username = request.getParameter("username");
username = new String(username.getBytes("ISO8859-1"), "UTF-8");


另外,需要提的一点就是URL地址后面如果跟了中文数据,那么中文参数最好使用URL编码进行处理,如下所示:

<a href="day06/RequestDemo4?username=<%=URLEncoder.encode('中国', 'UTF-8')%>">点点</a>


总之:超链接提交的中文,服务器想不乱码,也只能手工处理。

一道测试题

例如有如下的form表单页面:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>request接收中文参数乱码问题</title>
</head>
<body>
<form action="/day06/RequestDemo4" method="post">
用户名:<input type="text" name="username"><br/>
<input type="submit" value="提交">
</form>
</body>
</html>




运行如下代码,在浏览器显示的会不会是乱码?

public class RequestDemo4 extends HttpServlet {

protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("UTF-8"); // 只对客户机的post方式提交有效
String username = request.getParameter("username");

response.setCharacterEncoding("GBK");
response.setContentType("text/html;charset=GBK");
response.getWriter().write(username);
}

protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}

}


解:不会。

因为以上代码相当于:

public class RequestDemo4 extends HttpServlet {

protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String username = "中国";

response.setCharacterEncoding("GBK");
response.setContentType("text/html;charset=GBK");
response.getWriter().write(username);
}

protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}

}


所以在浏览器显示时不会是乱码。

Request对象实现请求转发

请求转发的基本概念

请求转发:指一个web资源收到客户端请求后,通知服务器去调用另外一个web资源进行处理。

请求转发的应用场景:MVC设计模式。

M

model,即javabean。

V

view,即jsp。

C

controller,即servlet。

在Servlet中实现请求转发的方式:request对象提供了一个getRequestDispatcher方法,该方法返回一个RequestDispatcher对象,调用这个对象的forward方法可以实现请求转发。

例如:请求RequestDemo5这个Servlet,RequestDemo5将请求转发到message.jsp页面。

public class RequestDemo5 extends HttpServlet {

// mvc设计模式(m--model(javabean) v--view(jsp) c--controller(servlet))
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String data = "aaaaaaaa";

// 每一个请求都有一个request,每个的数据都存在对应的request里面,跳到jsp,jsp显示各自的数据
request.setAttribute("data", data);

// request实现转发
request.getRequestDispatcher("/message.jsp").forward(request, response);;
}

protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}

}


request对象同时也是一个域对象(Map容器),开发人员通过request对象在实现转发时,把数据通过request对象带给其它web资源处理。

message.jsp页面代码如下:

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Request对象实现请求转发</title>
</head>
<body>

使用普通方式取出存储在request对象中的数据:
<%
String data = (String)request.getAttribute("data");
out.write(data);
%><br/>
使用EL表达式取出存储在request对象中的数据:
${data }
</body>
</html>


运行结果如下:



请求转发的特点:

客户端只发一次请求,而服务器端有多个资源调用。

客户端浏览器地址栏没有发生变化。

request对象作为一个域对象(Map容器)使用时,主要是通过以下的四个方法来操作:

setAttribute(String name,Object o)方法,将数据作为request对象的一个属性存放到request对象中,例如:request.setAttribute(“data”, data);

getAttribute(String name)方法,获取request对象的name属性的属性值,例如:request.getAttribute(“data”);

removeAttribute(String name)方法,移除request对象的name属性,例如:request.removeAttribute(“data”);

getAttributeNames方法,获取request对象的所有属性名,返回的是一个枚举,例如:
Enumeration<String> attrNames = request.getAttributeNames();


请求重定向和请求转发的区别

一个web资源收到客户端请求后,通知服务器去调用另外一个web资源进行处理,称之为请求转发。

一个web资源收到客户端请求后,通知浏览器去访问另外一个web资源,称之为请求重定向。

RequestDispatcher.forward方法只能将请求转发给同一个WEB应用中的组件;而HttpServletResponse.sendRedirect方法可以重定向到同一个站点上的其他应用程序中的资源,甚至是使用绝对URL重定向到其他站点的资源。

如果传递给HttpServletResponse.sendRedirect方法的相对URL以“/”开头,它是相对于整个WEB站点的根目录;如果创建RequestDispatcher对象时指定的相对URL以“/”开头,它是相对于当前WEB应用程序的根目录。

调用HttpServletResponse.sendRedirect方法重定向的访问过程结束后,浏览器地址栏中显示的URL会发生改变,由初始的URL地址变成重定向的目标URL;调用RequestDispatcher.forward方法的请求转发过程结束后,浏览器地址栏保持初始的URL地址不变。

HttpServletResponse.sendRedirect方法对浏览器的请求直接作出响应,响应的结果就是告诉浏览器去重新发出对另外一个URL的访问请求;RequestDispatcher.forward方法在服务器端内部将请求转发给另外一个资源,浏览器只知道发出了请求并得到了响应结果,并不知道在服务器程序内部发生了转发行为。

RequestDispatcher.forward方法的调用者与被调用者之间共享相同的request对象和response对象,它们属于同一个访问请求和响应过程;而HttpServletResponse.sendRedirect方法调用者与被调用者使用各自的request对象和response对象,它们属于两个独立的访问请求和响应过程。

请求转发的细节

forward方法用于将请求转发到RequestDispatcher对象封装的资源上。

如果在调用forward方法之前,在Servlet程序中写入的部分内容已经被真正地传送到了客户端,forward方法将抛出IllegalStateException异常。

例,以下代码会抛出异常:
java.lang.IllegalStateException: Cannot forward after response has been committed


public class RequestDemo6 extends HttpServlet {

protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String data = "aaaaaa";

PrintWriter writer = response.getWriter();
writer.write(data);
writer.close();

/*
* 以下跳转会导致: java.lang.IllegalStateException: Cannot forward after
* response has been committed
*/
request.getRequestDispatcher("/message.jsp").forward(request, response);
}

protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}

}


虽然你不会写出以上愚蠢的代码,但是你会写出如下糟糕的代码,这是在所难免的。

public class RequestDemo6 extends HttpServlet {

protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String data = "aaaaaa";

if(true) {
request.getRequestDispatcher("/index.jsp").forward(request, response);
}

/*
* 以下跳转会导致: java.lang.IllegalStateException: Cannot forward after
* response has been committed
*/
request.getRequestDispatcher("/message.jsp").forward(request, response);
}

protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}

}


所以要记住:每次跳转之后一定要return。

public class RequestDemo6 extends HttpServlet {

protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String data = "aaaaaa";

if(true) {
request.getRequestDispatcher("/index.jsp").forward(request, response);
return; // 每次跳转之后一定要return
}

request.getRequestDispatcher("/message.jsp").forward(request, response);
}

protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}

}


如果在调用forward方法之前向Servlet引擎的缓冲区中写入了内容,只要写入到缓冲区中的内容还没有被真正输出到客户端,forward方法就可以被正常执行,原来写入到输出缓冲区中的内容将被清空,但是,已写入到HttpServletResponse对象中的响应头字段信息保持有效。

// forward的细节,forward时,会清空response中的数据
public class RequestDemo7 extends HttpServlet {

protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String data = "aaaaaa";
response.getWriter().write(data);

// 跳转之前会把原来写入response的数据清空
request.getRequestDispatcher("/index.jsp").forward(request, response);
}

protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}

}


请求转发的运行流程



























RequestDispatcher的include方法

include方法:

RequestDispatcher.include方法用于将RequestDispatcher对象封装的资源内容作为当前响应内容的一部分包含进来,从而实现可编程的服务器端包含功能。

被包含的Servlet程序不能改变响应消息的状态码和响应头,如果它里面存在这样的语句,这些语句的执行结果将被忽略。

在WEB应用程序的根目录,新建一个public目录,然后再在此目录下新建两个jsp——head.jsp/foot.jsp。注意:用include实现页面包含,被包含页面不要出现全局架构标签。



head.jsp:

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>

head<br/>


foot.jsp:

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>

foot<br/>


RequestDemo8代码:

// 用include实现页面包含,被包含页面不要出现全局架构标签
public class RequestDemo8 extends HttpServlet {

protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.getRequestDispatcher("/public/head.jsp").include(request, response);
response.getWriter().write("hahahahahaha<br/>");
request.getRequestDispatcher("/public/foot.jsp").include(request, response);
}

protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}

}


web工程中URL地址的推荐写法

在JavaWeb开发中,只要是写URL地址,那么建议最好以”/”开头,也就是使用绝对路径的方式,那么这个”/”到底代表什么呢?可以用如下的方式来记忆”/”:如果”/”是给服务器用的,则代表当前的web工程,如果”/”是给浏览器用的,则代表webapps目录。

“/”代表当前web工程的常见应用场景

ServletContext.getRealPath(String path)获取资源的绝对路径

this.getServletContext().getRealPath("/form.html");


ServletContext.getRealPath(“/form.html”)是用来获取服务器上的某个资源,那么这个”/”就是给服务器用的,”/”此时代表的就是web工程。ServletContext.getRealPath(“/form.html”)表示的就是读取web工程下的form.html这个资源,只要明白了”/”代表的具体含义,就可以很快写出要访问的web资源的绝对路径。

在服务器端forward到其他页面。

request.getRequestDispatcher("/form.html").forward(request, response);


客户端请求某个web资源,服务器跳转到另外一个web资源,这个forward也是给服务器用的,那么这个”/”就是给服务器用的,所以此时”/”代表的就是web工程。

使用include指令或者
<jsp:include>
标签引入页面。

<%@include file="/jspfragments/head.jspf" %>


<jsp:include page="/jspfragments/demo.jsp" />


此时”/”代表的都是web工程。

ServletContext.getResourceAsStream(String path)获取资源的流对象。

this.getServletContext().getResourceAsStream("/public/foot.jsp");


“/”代表webapps目录的常见应用场景

使用sendRedirect实现请求重定向。

response.sendRedirect("/day06/form2.html");


服务器发送一个URL地址给浏览器,浏览器拿到URL地址之后,再去请求服务器,所以这个”/”是给浏览器使用的,此时”/”代表的就是webapps目录。“/day06/form2.html”这个地址指的就是“webapps\day06\form2.html”。

response.sendRedirect(“/项目名称/文件夹目录/页面”);这种写法是将项目名称写死在程序中的做法,不灵活,万一哪天项目名称变了,此时就得改程序,所以推荐使用下面的灵活写法:

将:

response.sendRedirect("/day06/form2.html");


这种写法改成:

response.sendRedirect(request.getContextPath()+"/index.jsp");


request.getContextPath()获取到的内容就是”/day06”,这样就比较灵活了,使用request.getContextPath()代替”/项目名称”,推荐使用这种方式,灵活方便!

使用超链接跳转。

<a href="/day06/form.html">点点</a>


这是客户端浏览器使用的超链接跳转,这个”/”是给浏览器使用的,此时”/”代表的就是webapps目录。

使用超链接访问web资源,绝对路径的写法推荐使用下面的写法改进:

<a href="${pageContext.request.contextPath}/form.html">点点</a>


这样就可以避免在路径中出现项目的名称,使用${pageContext.request.contextPath}取代”/day06”。

form表单提交。

<form action="/day06/form.html">

</form>


这是客户端浏览器将form表单提交到服务器,所以这个”/”是给浏览器使用的,此时”/”代表的就是webapps目录。

对于form表单提交中action属性绝对路径的写法,也推荐使用如下的方式改进:

<form action="${pageContext.request.contextPath}/form.html">

</form>


${pageContext.request.contextPath}
得到的就是”/day06”,
${pageContext.request.contextPath}
的效果等同于request.getContextPath(),两者获取到的都是”/项目名称”。

js脚本和css样式文件的引用。

<%--使用绝对路径的方式引用js脚本--%>
<script type="text/javascript" src="${pageContext.request.contextPath}/js/index.js"></script>
<%--${pageContext.request.contextPath}与request.getContextPath()写法是得到的效果是一样的--%>
<script type="text/javascript" src="<%=request.getContextPath()%>/js/login.js"></script>
<%--使用绝对路径的方式引用css样式--%>
<link rel="stylesheet" href="${pageContext.request.contextPath}/css/index.css" type="text/css"/>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: