在上次的小案例中用到了转发的技术,今天来仔细聊聊转发和重定向的问题,以及一些小知识的汇总。

一、转发

1、转发的概念

转发主要是将浏览器的请求交给另外一个servlet或jsp来处理,借助request对象完成,在服务器内部跳转,浏览器的地址并不发生改变,并且浏览器并不知道服务器内部发生了跳转,整个过程只会发生一次请求,转发的调用者和被调用者都可以共享request对象和response对象。

2、使用方法

因为是将数据交到另外一个servlet或jsp来处理请求,所以第一步是将需要处理的数据绑定到request对象上,可以使用request.setAttribute(String name, Object obj)方法,其中name是绑定名,obj是绑定值;也可以使用request.getSession().setAttribute(String name, Object obj)方法,绑定到session对象上。

第二步是获取转发器,也就是完成转发这件事需要用到的工具。

RequestDispatcher rd = request.getRequestDispatcher(String url);

url参数是转发的目标地址,可以是servlet,也可以是一个jsp页面,可以使用相对路径,也可以使用绝对路径。

第三步是调用转发器的方法来转发。

rd.forward(request,response);

当然,如果熟练后,可以将第二步和第三步合并为一步。

request.getRequestDispatcher(String url).forward(request, response);

3、转发的优缺点

转发的优点一是安全性高,在内部发生跳转,浏览器地址不变;二是节省资源,转发只需要一次请求,就可以访问至少两个servlet或jsp页面。在实际开发中,转发用到的较多。

转发的缺点是只能在同一web应用内使用,不能转发到外部的url地址。

二、重定向

1、重定向的概念

重定向是指服务器通知浏览器向一个新的地址发送请求,由response对象完成,可以重定向到新的servlet(服务器内部),也可以重定向到外部url(外部应用),浏览器地址发生改变,浏览器知道发生了跳转,整个过程会产生两次请求,重定向的调用者和被调用者不能共享request对象和response对象。

2、使用方法

response.sendRedirect(String url);

url是重定向的地址,可以是绝对路径,也可以是相对路径。

3、重定向的优缺点

重定向的优点是不限制应用范围,可以重定向到服务器内部其他资源,也可以是外部的应用。

重定向的缺点是耗费请求资源,重定向整个过程发生了两次的请求,一个是资源消耗上比转发大,效率也比转发低;另外,因为浏览器的地址发生了变化,相对转发来讲,安全性没有转发高。

三、路径问题

不管是使用转发还是重定向,都会涉及到路径的问题,路径分为相对路径、绝对路径。

绝对路径是指以"/"开头的路径信息。相对路径是指不以"/"开头的路径信息。

在项目中如果要使用绝对路径,重定向的路径是从应用名(上下文)开始,因为重定向时,服务器不知道这个请求是否在应用内部还是外部,所以需要加上应用名;转发时的路径是从应用名之后开始,转发是发生在服务器内部,在同一应用下,可以不用写应用名。

为了避免直接将应用名写在地址里面,可以使用request.getContextPath()方法来替代。

四、POST请求和GET请求

在前几次的小例子中,会经常看见jsp页面写post请求和get请求,在后台处理请求的doPost和doGet方法,下面对post请求和get请求来做下说明。

1、get请求

浏览器在下列三种情况出现时,会发送get请求,一是直接输入某个地址,二是点击链接,三是表单默认的提交方式。

get请求会将请求参数添加到请求资源路径的后面,是在get请求的url中发送的,url中只能存放2k左右的数据,并且请求参数会显示在浏览器地址栏,安全性较低,get请求会被缓存,会被保留在浏览器历史记录中,get请求只应用于取回数据。

2、post请求

设置表单的method属性值为post,浏览器会发送post请求。

post请求会将请求参数放在http消息主体中发送,可以提交大量数据,不会显示在浏览器地址栏,相对安全,但是对于敏感数据需要进行手动加密处理,post请求不会被缓存,也不会被保留在浏览器历史记录中。

五、验证转发与重定向,分别使用相对路径、绝对路径

第一步,新建一个Maven项目,建好两个Servlet类,写好两个jsp页面

  1. package servlet;
  2.  
  3. import java.io.IOException;
  4. import javax.servlet.ServletException;
  5. import javax.servlet.http.HttpServlet;
  6. import javax.servlet.http.HttpServletRequest;
  7. import javax.servlet.http.HttpServletResponse;
  8.  
  9. /**
  10. * 测试转发和重定向,分别使用相对路径、绝对路径
  11. * @author 小川94
  12. * @date 2018年6月10日
  13. */
  14. public class FirstServlet extends HttpServlet {
  15. private static final long serialVersionUID = 1L;
  16.  
  17. public FirstServlet() {
  18. super();
  19. }
  20.  
  21. protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  22. System.out.println("FirstServlet--->>> 进入doGet方法,交由doPost方法处理...");
  23. doPost(request, response);
  24. }
  25.  
  26. protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  27. System.out.println("FirstServlet--->>> 执行POST请求...");
  28. // 转发到second.jsp,使用绝对路径(不需要带应用名)
  29. //request.getRequestDispatcher("/second/second.jsp").forward(request, response);
  30.  
  31. // 转发到second.jsp,使用相对路径(不需要带应用名)
  32. //request.getRequestDispatcher("second/second.jsp").forward(request, response);
  33.  
  34. // 重定向到second.jsp,使用绝对路径(需要带应用名),推荐使用第二种写法
  35. //response.sendRedirect("/servlet_day04/second/second.jsp");
  36. //response.sendRedirect(request.getContextPath()+"/second/second.jsp");
  37.  
  38. // 重定向到second.jsp,使用相对路径(不需要带应用名)
  39. //response.sendRedirect("second/second.jsp");
  40.  
  41. // 转发到SecondServlet,使用绝对路径(不需要带应用名)
  42. //request.getRequestDispatcher("/SecondServlet").forward(request, response);
  43.  
  44. // 转发到SecondServlet,使用相对路径(不需要带应用名)
  45. //request.getRequestDispatcher("SecondServlet").forward(request, response);
  46.  
  47. // 重定向到SecondServlet,使用绝对路径(需要带应用名),推荐使用第二种写法
  48. //response.sendRedirect("/servlet_day04/SecondServlet");
  49. //response.sendRedirect(request.getContextPath()+"/SecondServlet");
  50.  
  51. // 重定向到SecondServlet,使用相对路径(不需要带应用名)
  52. response.sendRedirect("SecondServlet");
  53. }
  54.  
  55. }
  1. package servlet;
  2.  
  3. import java.io.IOException;
  4. import java.io.PrintWriter;
  5.  
  6. import javax.servlet.ServletException;
  7. import javax.servlet.http.HttpServlet;
  8. import javax.servlet.http.HttpServletRequest;
  9. import javax.servlet.http.HttpServletResponse;
  10.  
  11. public class SecondServlet extends HttpServlet {
  12. private static final long serialVersionUID = 1L;
  13.  
  14. /**
  15. * @see HttpServlet#HttpServlet()
  16. */
  17. public SecondServlet() {
  18. super();
  19. }
  20.  
  21. protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  22. System.out.println("SecondServlet--->>> 进入doGet方法,交由doPost方法处理...");
  23. doPost(request, response);
  24. }
  25.  
  26. protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  27. System.out.println("SecondServlet--->>> 执行POST请求...");
  28. response.setContentType("text/html;charset=utf-8");
  29. PrintWriter pw = response.getWriter();
  30. pw.println("<h1>这是SecondServlet中的响应数据</h1>");
  31. pw.flush();
  32. pw.close();
  33. }
  34.  
  35. }
  1. <%@ page language="java" contentType="text/html; charset=UTF-8"
  2. pageEncoding="UTF-8"%>
  3. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
  4. <html>
  5. <head>
  6. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  7. <title>第一个jsp页面</title>
  8. </head>
  9. <body>
  10.  
  11. <h1>这是第一个jsp页面</h1>
  12. <hr>
  13. <!-- ../表示根目录 -->
  14. <a href="../FirstServlet">这是第一个GET请求</a>
  15. <br/>
  16. <!-- request.getContextPath()方法获取的是应用名 -->
  17. <a href="<%=request.getContextPath() %>/FirstServlet">这是第二个GET请求</a>
  18. </body>
  19. </html>
  1. <%@ page language="java" contentType="text/html; charset=UTF-8"
  2. pageEncoding="UTF-8"%>
  3. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
  4. <html>
  5. <head>
  6. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  7. <title>第二个jsp页面</title>
  8. </head>
  9. <body>
  10.  
  11. <h1>这是第二个jsp页面</h1>
  12. <hr>
  13.  
  14. </body>
  15. </html>

整个项目的目录结构如下图

第二步,分别使用相对路径和绝对路径测试转发和重定向

相对路径和绝对路径都是针对部署在Tomcat上文件的位置,不是工程目录结构,first文件夹和second文件夹下存放的是jsp页面,web-inf文件夹下存放的是编译的servlet的class文件。测试完你会发现使用相对路径是最省事的,但是如果你对相对路径不熟悉,那还是写绝对路径吧,好把控一些。

文章首发于我的个人公众号:悦乐书。喜欢分享一路上听过的歌,看过的电影,读过的书,敲过的代码,深夜的沉思。期待你的关注!

公众号后台输入关键字“Java学习电子书”,即可获得12本Java学习相关的电子书资源,如果经济能力允许,还请支持图书作者的纸质正版书籍,创作不易。

Servlet(四):转发与重定向、路径问题的更多相关文章

  1. Servlet中转发和重定向的路径问题【转】

    转发和重定向的路径问题 Servlet中有两种方式获得转发对象(RequestDispatcher):一种是通过HttpServletRequest的getRequestDispatcher()方法获 ...

  2. servlet的转发与重定向

    转发和重定向都能让浏览器获得另外一个URL所指向的资源,但两者的内部运行机制有着很大的区别. 1.转发:有两种方式获得转发对象(RequestDispatcher):一种是通过HttpServletR ...

  3. servlet请求转发于重定向

    请求的转发与重定向是Servlet控制页面跳转的主要方法,在Web应用中使用非常广泛. 一. 请求的转发 Servlet接收到浏览器端请求后,进行一定的处理,先不进行响应,而是在服务器端内部" ...

  4. Servlet中转发和重定向的区别

    Servlet中页面的跳转有两种方式:转发和重定向. 1.转发和重定向的区别 ①转发是服务器行为,重定向是客户端行为. ②转发是浏览器发生了一次请求,重定向至少是两次请求. ③转发地址栏中的url不会 ...

  5. servlet之转发与重定向的区别

    转发(服务器端跳转):  一次请求 <jsp:forward> request.getRequestDispatcher("new.jsp").forward(requ ...

  6. Servlet中转发和重定向的路径问题以及表单提交路径问题

    一.请求转发与响应重定向的种类 有两种方式获得Servlet转发对象(RequestDispatcher):一种是通过HttpServletRequest的getRequestDispatcher() ...

  7. Servlet & JSP - 转发与重定向的区别

    本文转载自:http://blog.csdn.net/kobejayandy/article/details/13762043 转发 转发的原理,可以通过下图展示: 浏览器的请求发送给组件 1,组件 ...

  8. [Java][Web] Servlet中转发和重定向比较

    Servlet中页面跳转的两种方式 请求转发 使用requestDispatcher对象 request.getRequestDispatcher("path").forward( ...

  9. servlet请求转发与重定向的差别------用生活实例来形象说明两者的差别

    1,请求重定向:client行为,response.sendRedirect(),从本质上讲等同于两次请求,前一次的请求对象不会保留,地址栏的URL地址会改变. 2,请求转发:server行为,req ...

  10. Servlet转发和重定向的区别

    附上视频教学的一张图: 区别: 1.转发产生一次请求,一次响应: 重定向产生2次请求 两次响应 2.转发客户端不可见的: 重定向客户端是可以察觉的. 3.转发时候url不变: 重定向URL会改变 案例 ...

随机推荐

  1. java.lang.NoSuchMethodException: tk.mybatis.mapper.provider.SpecialProvider.<init>()

    Caused by: org.apache.ibatis.builder.BuilderException: Error invoking SqlProvider method (tk.mybatis ...

  2. NLP入门(三)词形还原(Lemmatization)

      词形还原(Lemmatization)是文本预处理中的重要部分,与词干提取(stemming)很相似.   简单说来,词形还原就是去掉单词的词缀,提取单词的主干部分,通常提取后的单词会是字典中的单 ...

  3. 菜鸟入门【ASP.NET Core】15:MVC开发:ReturnUrl实现、Model后端验证 、Model前端验证

    ReturnUrl实现 我们要实现returnUrl,我们需要在注册(Register)方法中接收传进的returnUrl并给它默认值null,然后将它保存在ViewData里面 然后我们定义一个内部 ...

  4. [android] 绑定方式开启服务&调用服务的方法

    需求:后台开启一个唱歌服务,这个服务里面有个方法切换歌曲 新建一个SingService继承系统Service 重写onCreate()和onDestory()方法 填一个自定义的方法changeSi ...

  5. mybatis_05动态SQL_if和where

    If标签:作为判断入参来使用的,如果符合条件,则把if标签体内的SQL拼接上. 注意:用if进行判断是否为空时,不仅要判断null,也要判断空字符串‘’: Where标签:会去掉条件中的第一个and符 ...

  6. Android Material Design控件使用(二)——FloatButton TextInputEditText TextInputLayout 按钮和输入框

    FloatingActionButton 1. 使用FloatingActionButton的情形 FAB代表一个App或一个页面中最主要的操作,如果一个App的每个页面都有FAB,则通常表示该App ...

  7. C#设计模式之十九策略模式(Stragety Pattern)【行为型】

    一.引言 今天我们开始讲“行为型”设计模式的第七个模式,该模式是[策略模式],英文名称是:Stragety Pattern.在现实生活中,策略模式的例子也非常常见,例如,在一个公司中,会有各种工作人员 ...

  8. 设计模式—装饰模式的C++实现

    这是Bwar在2009年写的设计模式C++实现,代码均可编译可运行,一直存在自己的电脑里,曾经在团队技术分享中分享过,现搬到线上来. 1. 装饰模式简述 1.1 目的 动态地给一个对象添加一些额外的职 ...

  9. intellij error updating changes svn解决办法

    乌龟检出的svn版本为1.8,而1.8在IntelliJ 上跑起来貌似有问题, 经过多次尝试,当Format改为1.7后,问题被解决.

  10. JavaScript 基础(一) - JavaScript的引入方式,JavaScript 变量命名规则,JS 的五种基本数据类型,ECMAScript 算数运算符,逻辑运算符

    JavaScript的引入方式 直接编写 <!DOCTYPE html> <html lang="en"> <head> <meta ch ...