介绍
在前面,我们学习的一次请求对应的就是一个Servlet,但是当我们的功能比较复杂时,一个Servlet很难满足我们的需求,往往需要几个Servlet进行协作完成,于是便有了请求转发[Dispatcher],Dispathcer可以实现请求转发功能,并且携带将本次的Request和Respond携带到下一个Servlet,实现一次请求访问多个Servlet,完成复杂的功能。
注意,上面只是一个简单示意图,实际上请求转发不是Servlet直接调用下一个Servlet,而是先返回tomcat,tomcat再调用下一个Servlet!!!
说明
- 请求转发是当Servlet被调用时,如果需要请求转发,那么这个Servlet会通知服务器,然后服务器来调用另外的Servlet
- Dispathcer是一个对象,这个对象是HttpServletRequest提供的,我们可以通过getDispathcer()方法获取对象,得到对象后我们就可以进行转发(通过forward方法),转发时把这次的request和response带上,转发对象的request和response和当前Servlet的request,response是一样的。
- HttpServletRequest是一个域对象,当我们需要将某些数据转发给下一个Servlet时,我们可以使用HttpServletRequest的setAttribute(String,Object)方法设置属性,而转发的Servlet通过getAttribut(String)方法就可以得到数据。
练习
我们使用请求转发来做一个练习,定义2个Servlet,一个Servlet实现用户的校验工作,一个实现显示的工作,这样每个Servlet就分工明确了,各司其职,通过请求转发来实现他们之间的调用。我们再创建一个登录页面,根据登录用户的不同来显示不同的页面。代码如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>请求转发练习</title>
</head>
<body>
<form action="http://localhost:8080/servlet/check" method="post">
用户名:<input type="text" name="username"><br>
密 码:<input type="password" name="password"><br>
<input type="submit" value="登录">
</form>
</body>
</html>
import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.IOException;
@WebServlet("/check")
public class CheckServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//得到提交的用户名
String username = request.getParameter("username");
//如果提交的用户名是root,我们就认为这是一个管理员
if ("root".equals(username)){
//设置域属性
request.setAttribute("identity","管理员");
}else {
request.setAttribute("identity","普通用户");
}
//得到Dispatcher对象
//getRequestDispatcher(String s);这个方法里面的参数填的是要转发的url
RequestDispatcher dispatcher = request.getRequestDispatcher("/show");
//进行转发,并把request和response带上
dispatcher.forward(request,response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request,response);
}
}
import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.IOException;
import java.io.PrintWriter;
@WebServlet("/show")
public class ShowServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//得到用户名
String username = request.getParameter("username");
//得到身份
String identity = (String)request.getAttribute("identity");
//设置响应的MIME和编码
response.setContentType("text/html;charset=utf-8");
//得到输出流
PrintWriter writer = response.getWriter();
//写回数据
writer.write("<h1>亲爱的:"+username+" 欢迎登录</h1>");
writer.write("<h1>您现在是"+identity+"登录</h1>");
//关闭流
writer.flush();
writer.close();
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request,response);
}
}
现在,我们来到登录页面进行测试,我们首先在用户名和密码都输入tom进行登录
发现登录后显示我是一个普通用户,接下来,我们再使用root进行登录
发现登录后显示我们是管理员登录,到此,我们就实现了这个功能,一个Servlet只实现一个功能,通过请求转发来实现不同Servlet之间的调用。
注意事项
- 我们使用请求转发,不会导致游览器地址栏的url发生变化
- 在请求转发中,虽然调用了多个Servlet,但是仍然是一次Http请求
- 可以转发到WEB-INF目录下
- 不能转发到当前这个Web资源外面去
- 多个Servlet之间可以共享request的数据