JavaWeb学习笔记(十一)--HttpServletRequest

4. request实现请求转发

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

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

request对象同时也是一个域对象,开发人员可以通过request对象在实现转发时,把数据通过request对象带给其他web资源处理。

  • setAttribute方法
  • getAttribute方法
  • getAttributeNames方法
  • removeAttribute方法

4.1 实现请求转发

访问HttpServletRequestDemo5,使用request将其转发到HttpServletRequestDemo6中,并在request中传递参数:

 1 /**
 2  * request实现请求转发,并传递数据
 3  */
 4 @WebServlet(name = "HttpServletRequestDemo5")
 5 public class HttpServletRequestDemo5 extends HttpServlet {
 6 
 7     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
 8         request.setAttribute("name", "bear");
 9         request.getRequestDispatcher("/HttpServletRequestDemo6").forward(request, response);
10  } 11 }
 1 /**
 2  * 获取request中存储的数据
 3  */
 4 @WebServlet(name = "HttpServletRequestDemo6")
 5 public class HttpServletRequestDemo6 extends HttpServlet {
 6 
 7     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
 8         response.getWriter().write((String)request.getAttribute("name"));
 9     }
10 }

运行结果:

ServletContext对象也可实现请求转发(JavaWeb学习笔记(八)--ServletConfig和ServletContext对象介绍):

this.getServletContext().getRequestDispatcher("/HttpServletRequestDemo6").forward(request, response);

 

4.2 转发时需要注意的细节:

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

例如,如下两种方式都会抛异常,所以最好在每个跳转后最好加上return语句

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    PrintWriter out = response.getWriter();
    out.write("aaaa");
    // 关闭流,将导致数据写到浏览器上
    out.close();
    request.getRequestDispatcher("/message.html").forward(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    if (true) {
        request.getRequestDispatcher("/form.html").forward(request, response);
    }
    // 下面这个会报java.lang.IllegalStateException: Cannot forward after response has been committed
    // 所以每个跳转后最好加上return语句
    request.getRequestDispatcher("/message.html").forward(request, response);
}

运行结果:

能输出aaaa或者跳转到form.html,但是代码会抛异常:

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

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    PrintWriter out = response.getWriter();
    // aaaa将不会在message.html中出现
    out.write("aaaa");
    request.getRequestDispatcher("/message.html").forward(request, response);
}

运行结果:

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

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

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

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

HttpServletResponse.sendRedirect方法重定向后,浏览器地址栏的URL会发生变化,由初始的URL变成重定向后的目标URL;RequestDispatcher.forward请求转发,浏览器地址栏URL不会变化。

HttpServletResponse.sendRedirect会有两次访问请求;RequestDispatcher.forward只有一次访问请求。

5. 利用referer实现防盗链

我们经常会遇到别人在微信群发了一个连接,点击进去后发现直接跳转到了网站首页,通过首页才能跳转到想看的网页。这个就利用了referer实现防盗链:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title></title>
  </head>
  <body>
      首页
      <a href="/HttpServletRequestDemo7">消息显示</a>
  </body>
</html>
/**
 * 利用referer实现防盗链
 */
@WebServlet(name = "HttpServletRequestDemo7")
public class HttpServletRequestDemo7 extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String referer = request.getHeader("referer");
        System.out.println(referer);
        if (referer == null || !referer.startsWith("http://localhost")) {
            response.sendRedirect("/index.jsp");
            return;
        }
        request.getRequestDispatcher("/message.html").forward(request, response);
    }
}

运行结果:

可以看到都是调用HttpServletRequestDemo7,直接输入(referer为null)是不能获取到message.html的,通过首页跳转才可以。

猜你喜欢

转载自www.cnblogs.com/songchj-bear/p/10493773.html