精华内容
下载资源
问答
  • nginx实现请求转发

    2020-09-30 07:19:13
    本文给大家分享的是使用nginx实现代理(请求转发)的教程及简单示例,非常实用,有需要的小伙伴可以参考下
  • 主要介绍了Java中Request请求转发详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
  • 主要介绍了JavaWeb请求转发和请求包含实现过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
  • 请求转发问题 内网环境跟外网隔离,现在外网的请求都需要一个专用服务器转接到内网处理,用app.UseRewriter转接, 从外网服务器转发到内网服务器的时候Header 里面的Authorization 居然丢失了,重新设置...
  • 主要介绍了详解spring mvc 请求转发和重定向,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
  • 主要介绍了Javaweb请求转发及重定向实现详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
  • 主要介绍了浅谈Spring Cloud zuul http请求转发原理,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
  • RequestDispatcher对象的forward方法在使用时应注意的问题
  • 请求转发与重定向详解代码,解读工作流程,详细内容在我的博客中有!
  • 请求转发

    千次阅读 2019-07-07 14:06:01
    //使用请求转发 req.getRequestDispatcher("page").forward(req, resp); 实例代码 package com.wf.servlet; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet....

    实现语句

    	//使用请求转发
    	req.getRequestDispatcher("要转发的地址").forward(req, resp);
    	
    

    地址:相对路径,直接书写servlet的别名既可。
    实例代码

    package com.wf.servlet;
    
    import java.io.IOException;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import com.wf.pojo.User;
    import com.wf.service.LoginService;
    import com.wf.service.impl.LoginServiceImpl;
    
    /**
     * 登录请求
     * @ClassName LoginServlet
     * @Description 
     * @Author Wangfei
     * @Date 2019年7月7日 上午10:00:44
     */
    public class LoginServlet extends HttpServlet {
    	@Override
    	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    		//请求编码格式
    		req.setCharacterEncoding("utf-8");
    		//设置响应编码格式
    		resp.setContentType("text/html;charset=utf-8");
    		//获取请求信息
    		String uname = req.getParameter("uname");
    //		//转编码格式支持中文
    //		uname = new String(uname.getBytes("iso8859-1"),"utf-8");
    		
    		String pwd = req.getParameter("pwd");
    		System.out.println(uname+":"+pwd);
    		//处理请求信息
    			//获取业务层对象
    			LoginService loginService = new LoginServiceImpl();
    			User user = loginService.checkLoginService(uname, pwd);
    			System.out.println(user);
    		//响应处理结果
    			if (user != null) {
    				resp.getWriter().write("登录成功");
    			}else {
    //				resp.getWriter().write("登录失败");
    				//使用请求转发
    				req.getRequestDispatcher("page").forward(req, resp);
    				return;
    			}
    	}
    
    }
    
    

    功能

    • 实现多个servlet联动操作处理请求,这样避免代码冗余,让servlet的职责更加明确。

    特点

    • 一次请求,浏览器地址栏信息不改变。

    注意

    • 请求转发后直接return结束即可。
    展开全文
  • 请求转发和请求包含

    千次阅读 2018-08-12 14:32:32
    Servlet 容器的作用是负责处理客户请求,当Servlet 容器获取到用户请求后,调用某个Servlet,并把Servlet 的执行结果返回给用户。  Servlet 容器的工作流程:  ● 当用户请求某个资源时,Servlet 容...

    1Servlet 容器

     编程中的容器我们可以理解为程序运行时需要的环境,那么Tomcat 就是Servlet 的运行环境,就是一个Servlet 容器。Servlet 容器的作用是负责处理客户请求,当Servlet 容器获取到用户请求后,调用某个Servlet,并把Servlet 的执行结果返回给用户。

     Servlet 容器的工作流程:

      当用户请求某个资源时,Servlet 容器使用ServletRequest 对象将用户的请求信息封装起来,然后调用 java Servlet API 中定义的Servlet 的生命周期方法,完成Servlet 的运行。

      ● Servlet 容器将Servlet 执行后需要返回用户的结果封装到 ServletResponse 对象中,最后由Servlet 容器发送给客户,完成对客户的一次服务过程。

      每一个Servlet 都会执行 init()service()destory() 三个方法,在启动时调用一次init) 方法对参数进行初始化,在该Servlet 生存期间每当收到对其的请求时都会调用Service() 方法对请求进行处理,当容器销毁时自动调用 destory() 方法对Servlet 进行销毁。

    2、请求转发和请求包含

      正是因为因为Servlet 中的service() 方法由Servlet 容器调用,所以一个 Servlet 的对象是无法调用另一个 Servlet 的方法的,但是在实际项目中,对于客户端请求做出的响应可能会复杂,需要多个Servlet 来协作完成,这就需要请求转发和请求包含技术了。但是,要注意,无论是请求转发还是请求包含,都是表示由多个Servlet 共同处理同一个请求。

    1)请求转发定义:

      Servlet(源组件)先对客户请求做一些预处理操作(一般是对响应头进行处理),然后把请求转发给其他Servlet(目标组件)来完成包括生成响应结果在内的后续操作。

      实现方法:request.getRequestDispatcher(“接收请求的Servlet 路径”). forward(request,response)

      getRequestDispatcher(String path)该方法的返回值类型是RequestDispatcher,请求发送器,该方法的参数是指明要接收请求的Servlet 的路径;

      forward(ServletRequest req,ServletResponse res)该方法是RequestDispatcher 接口的方法,将请求从一个 servlet 转发到服务器上的另一个资源(servletJSP 文件或 HTML 文件)。此方法允许一个 servlet 对请求进行初步处理,并使另一个资源生成响应。需要传递两个参数,这两个参数是当前Servlet request 对象和 response 对象传递过去的。

      forward() 方法的处理流程:

      清空用于存放响应正文(响应体)数据的缓冲区。

      如果目标组件为Servlet JSP,就调用它们的service() 方法,把该方法产生的响应结果发送到客户端,如果目标组件为文件系统中的静态 html 文档,就读去文档中的数据并把它发送到客户端。

      由于 forward() 方法先清空用于存放响应正文数据的缓冲区,因此servlet源组件生成的响应结果不会被发送到客户端,只有目标组件生成的结果才会被发送到客户端,所以对源组件叫留头不留体,目标组件为留体不留头

      如果源组件在进行请求转发之前,已经提交了响应结果(例如调用了flush close() 方法),那么forward() 方法会抛出IllegalStateException。为了避免该异常,不应该在源组件中提交响应结果,所以叫留体抛异常。

    2)请求包含定义:

      Servlet(源组件)把其他Servlet(目标组件)生成的响应结果包含到自身的响应结果中。

      实现方式:request.getRequestDispatcher(“接收请求的Servlet 路径”). include(request,response)

      include(ServletRequest request,ServletResponse response)该方法是RequestDispatcher 接口的方法,表示包含。它的参数同forward() 方法的参数一样都是由当前Servlet传递过去的。

      包含与转发相比,源组件与被包含的目标组件的输出数据都会被添加到响应结果中,在目标组件中对响应状态代码或者响应头所做的修改都会被忽略,所以对源组件来说是留头又留体,对目标组件为留体不留头

      注意:Servlet 源组件调用 RequestDispatcher forward include 方法时,都要把当前的 ServletRequest 对象和ServletResponse 对象作为参数传给 forward include 方法,这就使得源组件和目标组件共享同一个ServletRequest 对象和ServletResponse 对象,就实现了多个Servlet 协同处理同一个请求。

    附:RequestDispatcher 接口

      RequestDispatcher 接口中定义了两个方法:forward() 方法和 include() 方法,它们分别用于将请求转发到 RequestDispatcher 对象封装的资源和将 RequestDispatcher 对象封装的资源作为当前响应内容的一部分包含进来.

    3、请求转发(留头不留体,留体抛异常)

      AServlet(发送请求方):

    package web.servlet;
    
    import java.io.IOException;
    
    import javax.servlet.ServletException;
    
    import javax.servlet.http.HttpServlet;
    
    import javax.servlet.http.HttpServletRequest;
    
    import javax.servlet.http.HttpServletResponse;
    
    
    
    public class AServlet extends HttpServlet {
    
    
    
        public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {
    
             
    
            response.setContentType("text/html;charset=utf-8");
    
            response.getWriter().print("您好!");
    
            //response.getWriter().flush();//刷新会导致response的状态为已提交!
    
             
    
            // 转发不能在response提交之后,否则就会抛异常
    
            request.getRequestDispatcher("/BServlet").forward(request, response);

     

    BServlet(接收请求方):

    
    package web.servlet;
    
    import java.io.IOException;
    
    import javax.servlet.ServletException;
    
    import javax.servlet.http.HttpServlet;
    
    import javax.servlet.http.HttpServletRequest;
    
    import javax.servlet.http.HttpServletResponse;
    
    
    
    public class BServlet extends HttpServlet {
    
        public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {      
    
            response.getWriter().print("我很棒!");
    
        }
    
    }

    运行结果为:“我很棒!(不会输出你好!)。

      我对留头不留体的分析:

      对于发出请求的Aservlet是:留头不留体(设置的响应头可以留下,响应体被接收请求的 Bservlet 响应体覆盖); 留体抛异常,就是说只要请求转发了,就要将请求完全由 Bservlet 处理,Aservlet就不能插手了,如果Aservlet 也提交了对请求的处理,那么Bservlet 就不能处理请求了(因为请求已经被Aservlet 处理了,还处理啥) ,你安排人家处理请求,最终却由你处理了,当forward() 转发请求时,发现请求已经被处理,就会抛出异常。

      不过要注意,只有当AServlet 提交了处理(如例中手动flush将缓冲区内数据提交)才会抛出异常,如果没有提交,说明之前A对请求的处理还在缓冲区中,B就会直接将A的缓冲区清空,然后覆盖掉,就形成了之前的留头不留体。

     

    4、请求包含(留头又留体)

     CServlet(发送请求方):

    package web.servlet;
    
    import java.io.IOException;
    
    import javax.servlet.ServletException;
    
    import javax.servlet.http.HttpServlet;
    
    import javax.servlet.http.HttpServletRequest;
    
    import javax.servlet.http.HttpServletResponse;
    
    
    
    /**
    
     * 请求包含:留头又留体
    
     */
    
    public class CServlet extends HttpServlet {
    
    
    
        public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
             
    
            response.setContentType("text/html;charset=utf-8"); //设置内容类型
    
            response.getWriter().print("你好!");
    
            request.getRequestDispatcher("/DServlet").include(request, response);
    
        }
    
    }

     

      DServlet(接收请求方):

    package web.servlet;
    
    import java.io.IOException;
    
    import javax.servlet.ServletException;
    
    import javax.servlet.http.HttpServlet;
    
    import javax.servlet.http.HttpServletRequest;
    
    import javax.servlet.http.HttpServletResponse;
    
    
    
    public class DServlet extends HttpServlet {
    
        public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {     
    
            response.getWriter().print("我很棒!");
    
        }
    
    }

     

     运行结果为:你好!我很棒!

      结果说明请求包含是多个Servlet 共同处理一个请求的,并且发送方和接收方都能够留下响应体。

    5、请求转发和请求包含的比较

      (1)相同点:

      请求转发和请求包含都是在处理一个相同的请求,多个Servlet之间使用同一个 request 对象和 response 对象。

      (2)不同点:

      如果在AServlet中请求转发到BServlet,那么在AServlet中不允许再输出响应体,即不能使用response.getWriter() response.getOutputStream() 向客户端输出,这一工作交由BServlet来完成;如果是由AServlet请求包含BServlet,则没有这个限制。

      请求转发不能设置响应体,但是可以设置响应头,简单来说就是留头不留体,例如:response.setContentType("text/html;charset=utf-8”) 是可以留下来的;请求包含不仅可以设置响应头,还可以设置响应体,简单来说就是留头又留体

      请求转发大多应用在Servlet中,转发目标大多是jsp页面;请求包含大多应用在jsp页面中,完成多页面的合并。一般情况下经常使用的是请求转发。

    6、请求转发的应用:

      Servlet中向数据库获取数据,保存到request域中;

      转发到jsp页面,jsprequest域中获取数据,显示在页面上。

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

      对于客户端浏览器来说,转发是一个请求,重定向是两个请求;

      转发浏览器地址栏不变化,重定向会变成转发后的URL

      转发只能在一个项目内,而重定向没有限制,可以重定向到任意网址,如京东、淘宝等

      转发可以使用request 域传递数据,而重定向不能。因为转发是一个请求,重定向是两个请求;

      转发只有一个请求,原来是什么请求方式就是什么方式;而重定向两个请求,第一个可能为post 可能为get ,但是第二个请求一定是get

    小结:在浏览器地址栏中输入某个URL地址或者单击网页上的一个超链接时,浏览器发出的HTTP请求消息的请求方式为GET如果网页当中的

    表单元素的method属性被设置为“GET”,浏览器提交这个FORM表单时生成的HTTP请求消息的请求方式也为GET 

     

     

    展开全文
  • Request请求转发详解

    万次阅读 2020-07-07 16:16:46
    直接来,RequestDemo5代码,get请求和post请求都请求转发了,转发到RequestDemo6请求 RequestDemo5代码 package com.lingaolu.request; import javax.servlet.RequestDispatcher; import javax.servlet....

    直接来,RequestDemo5代码,get请求和post请求都请求转发了,转发到RequestDemo6请求

     RequestDemo5代码

    package com.lingaolu.request;
    
    import javax.servlet.RequestDispatcher;
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.*;
    import java.io.IOException;
    
    /**
     * @author 林高禄
     * @create 2020-07-07-12:06
     */
    @WebServlet("/requestDemo5")
    public class RequestDemo5 extends HttpServlet {
    
        @Override
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            System.out.println("requestDemo5进来了......post");
            RequestDispatcher requestDispatcher = request.getRequestDispatcher("/requestDemo6");
            requestDispatcher.forward(request,response);
        }
    
        @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            System.out.println("requestDemo5进来了......get");
            RequestDispatcher requestDispatcher = request.getRequestDispatcher("/requestDemo6");
            requestDispatcher.forward(request,response);
    
        }
    }
    

     

    RequestDemo6代码

    package com.lingaolu.request;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.*;
    import java.io.IOException;
    
    /**
     * @author 林高禄
     * @create 2020-07-07-12:06
     */
    @WebServlet("/requestDemo6")
    public class RequestDemo6 extends HttpServlet {
    
        @Override
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            System.out.println("requestDemo6进来了......post");
        }
    
        @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            System.out.println("requestDemo6进来了......get");
        }
    }
    

     

    浏览器访问/requestDemo5接口

    控制台输出

    从以上结果可以看出

    我们用Postman进行post请求一下

    后台输出:

    可见,get请求的转发会转发到get请求,post请求的转发,会转发到post请求

    我们改一下RequestDemo5的代码,转发到百度

    package com.lingaolu.request;
    
    import javax.servlet.RequestDispatcher;
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.*;
    import java.io.IOException;
    
    /**
     * @author 林高禄
     * @create 2020-07-07-12:06
     */
    @WebServlet("/requestDemo5")
    public class RequestDemo5 extends HttpServlet {
    
        @Override
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            System.out.println("requestDemo5进来了......post");
            RequestDispatcher requestDispatcher = request.getRequestDispatcher("/requestDemo6");
            requestDispatcher.forward(request,response);
        }
    
        @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            System.out.println("requestDemo5进来了......get");
            RequestDispatcher requestDispatcher = request.getRequestDispatcher("https://www.baidu.com/");
            requestDispatcher.forward(request,response);
    
        }
    }
    

    浏览器请求

     后台输出:

    从后台输出看出,requestDemo5请求进来了,从浏览器看出,转发失败了,而且从实际转发的路径上看,因为虚拟路径,所以请求转发只能转发到当前服务器内部的资源

    请求转发的特点总结:(与之对应的------重定向的详情与特点

    • 浏览器地址栏路径不发生变化
    • 转发只是一次请求,可共享数据Request共享数据
    • 哪种请求方式只能转发到那种请求方式
    • 请求转发只能转发到当前服务器内部的资源
    展开全文
  • 本文超详细的介绍了请求重定向、请求转发、请求包含的特点和区别,并使用一个小栗子结合丰富的图片文字来让读者更容易理解;并且配合代码、chrome调试工具来讲解三者的同与异。最后,通过一张表格,详细的列举了这三...

    ​ 在前几篇博文中我们学习了Servlet的基础知识,包括HttpServletRequest和HttpServletResponse对象,解析了Servlet是如何通过这一对黄金搭档来实现自身作为Controller的功能的。今天我们就来看看这两"兄弟"还可实现的另一功能。

    ​ 在某些情况下,对于客户端的某些请求,这个Servlet不想进行响应或者自己无法处理,就可以通过重定向、转发或包含来将此次请求转交给其他Serlvet来处理,我们通过下面一个小场景先来简单的了解下这三者的区别。

    一个小栗子:在企业A中,领导大黄有一个开发任务要分配下去,于是他喊来员工小李,说:“我这里有个需求…巴拉巴拉…”,那小李收到需求后,不想做或者做不了,那要他怎么处理呢?

    ​ 我们来看一看小李的几种处理方案。

    1.直接拒绝,推荐他人顶替(请求重定向)

    资源分配图

    ​ 从图中我们通过对话(😝箭头)可以看到,当领导大黄把任务分配给小李时,小李直接告诉大黄自己没空,让他去找小龙;于是大黄又找了小龙,并且把刚才给小李说过的话重新说了一遍,小龙收到需求后,加班加点把功能完成后,并直接向领导汇报,工作完成了。

    ​ 这也是重定向的思想,服务器告诉浏览器一个新的请求地址,浏览器再向新地址发起一次Http请求,即发起了两次Http请求(需求说了两遍);因为是浏览器重新发起一次请求,浏览器上的URL也发生变化,显示第二次请求的url(小龙);因为发起了两次Http请求,Serlvet容器也相应的分别为之创建ServletRequest和ServletResponse,因此两次请求收到的request、response是不同的

    ​ 下面我们来一起来看下在Servlet中是如何实现请求重定向的。我们新建个Servlet,命名为JumpTestServlet,其中的doGet()方法中代码如下:

    @WebServlet("/JumpTestServlet")
    public class JumpTestServlet extends HttpServlet {
    	//...
      
      protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //设置返回客户端的contentType
    		response.setContentType("text/html;charset=utf-8");
        
        //获取PrintWriter输出对象
        PrintWriter writer = response.getWriter();
        writer.println("我没空,你去找小龙吧!");
        //相对路径
        response.sendRedirect("./AnswerServlet");
        //绝对路径
        //response.sendRedirect("/FirstProject/AnswerServlet");
        //外部路径
        //response.sendRedirect("http://localhost:8080/FirstProject/AnswerServlet");
      }
    
    	//doPost()
    	//...
    }
    

    ​ 为了更好的模拟场景,我们对AnswerServlet的doGet()方法也进行了修改,代码如下:

    @WebServlet("/AnswerServlet")
    public class AnswerServlet extends HttpServlet {
    	//...
      
    	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		//设置返回客户端的contentType
    		response.setContentType("text/html;charset=utf-8");
        
    		获取PrintWriter输出对象
    		PrintWriter out = response.getWriter();
    		out.println("好的,功能已经开发完毕!");
    	}
    
    	//doPost()
    	//...
    }
    

    ​ 浏览器地址栏中输入http://localhost:8080/FirstProject/JumpTestServlet,运行结果为下图所示,我们可以看到,浏览器中url已经发生了改变,显示的是JumpTestServlet(小李)给其指定的url----AnswerServlet(小龙)。

    资源分配图

    ​ 为了探究两次请求(小李+小龙)给浏览器(领导大黄)的响应,我们来分别查看下这两次网络请求,首先下图是JumpTestServlet(小李),我们可以看到其响应状态码为302,响应头中增加了一个Location的header,通过Location来告知大黄去找小龙。但是注意绿框部分,返回的消息体的长度为0,即表示小李给领导大黄说的"我没空,你去找小龙吧!",领导大黄并没有接收到。

    资源分配图

    ​ 第二次对AnswerServlet(小龙)的访问就比较熟悉了,熟悉的绿灯泡旁的200字样,熟悉的Servlet的给出的响应被接收(Content-Length: 37)。

    资源分配图

    ​ 我们在再分析这两次请求的请求头、请求体,可以发现这两次Http请求除了请求行不一样外,其他都是相同的,也就是领导大黄对着两个人说了两遍一模一样的话

    ​ 为了加深理解,我们来看下HttpServletResponse接口中sendRedirect()源码中的解释,代码如下:

    /**
         * Sends a temporary redirect response to the client using the
         * specified redirect location URL and clears the buffer. The buffer will
         * be replaced with the data set by this method. Calling this method sets the
         * status code to {@link #SC_FOUND} 302 (Found).
         * This method can accept relative URLs;the servlet container must convert
         * the relative URL to an absolute URL
         * before sending the response to the client. If the location is relative 
         * without a leading '/' the container interprets it as relative to
         * the current request URI. If the location is relative with a leading
         * '/' the container interprets it as relative to the servlet container root.
         *
         * <p>If the response has already been committed, this method throws 
         * an IllegalStateException.
         * After using this method, the response should be considered
         * to be committed and should not be written to.
         *
         * @param		location	the redirect location URL
         * @exception	IOException	If an input or output exception occurs
         * @exception	IllegalStateException	If the response was committed or
     if a partial URL is given and cannot be converted into a valid URL
         */
    
    public void sendRedirect(String location) throws IOException;
    

    ​ 通过上面部分,我们可以看到,sendRedirect会使用指定的重定向location(入参)的URL向客户端发送临时重定向响应,并清除缓冲区(这也是为什么小李说的"我没空,你去找小龙吧!"没有传到客户端)。sendRedirect方法会将状态代码设置为 302(SC_FOUND)。

    sendRedirect可以接受相对路径和绝对路径,如果是一个相对路径,在发送至客户端前,Servlet容器会将相对的URL转换为绝对的URL。如果location是相对的而没有以’’\’‘开头,则Servlet容器会将其解释为相对于当前请求URI的相对位置,如果location有以’’\’'开头,则容器将其解释为相对于Servlet容器的根,即解释为"localhost:8080/",注意,此处没有项目名了,和ServletContext的根路径不同。sendRedirect还可接收一个以"http"或"https"开头的location,表明其可以重定向到外部应用中

    这里需要注意,在调用sendRedirect方法前,response如果已经被提交,此方法就会抛出一个IllegalStateException,这也和一个Http请求只能有一个对应的Http响应吻合。并且,在调用了sendRedirect后,Servlet中就不应该在通过response向客户端写入数据了。

    ​ 对于这里的相对、绝对的概念,我们不必深究,因为相对和绝对也都是个相对的概念。你可以有两种理解:

    1. 相对路径为没有以’’\’‘开头,即以"./“或”…/"开头的location;绝对路径为以’’\’'开头的location;以"http"或"https"开头的location为外部路径。这其中的相对就可以理解为相对于当前请求
    2. 所有没有以"http"或"https"开头的location为相对路径,而以"http"或"https"开头的location为绝对路径。这其中的相对就可以理解为相对于整个Servlet容器的。

    ​ 这两种方式只要理解一种即可,不必过多的纠结。

    2.外包出去,做个中间商(请求转发)

    资源分配图

    ​ 从图中我们通过对话可以看到,当领导大黄把任务分配给小李时,小李自己不想做,但是他没有告诉大黄,而是转头找到了小龙,并且把刚才大黄说过的话重新给小龙说了一遍(转述),小龙收到需求后,加班加点把功能完成后,然后告知领导大黄,工作已经完成了。注意,这里有点需要注意,图中所示是小龙这里直接告诉的领导,工作完成了,但是因为这项工作是小李委托给小龙来做的,领导大黄并不知情,所以大黄只会拍着小李的肩膀对他说:“小伙子,干的不错,有前途!”。至于小龙,只能呵呵了。

    ​ 我们将JumpTestServlet的doGet()方法修改如下,来看下请求转发的执行,代码如下:

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws 			ServletException, IOException {
      //设置返回客户端的contentType
      response.setContentType("text/html;charset=utf-8");
    
      //获取PrintWriter输出对象
      PrintWriter writer = response.getWriter();
      //这里暂且不提,我们后面再分析,为什么浏览器上没有显示这句话
      writer.println("我就是想说句话,看看浏览器能接收到么!");
      //相对路径
      request.getRequestDispatcher("./AnswerServlet").forward(request, response);
      //绝对路径
      //request.getRequestDispatcher("/AnswerServlet").forward(request, response);
    }
    

    ​ 浏览器地址栏中输入http://localhost:8080/FirstProject/JumpTestServlet,运行结果如下:

    资源分配图

    ​ 从上图可以看到,浏览器中的url并未发生变化, 对于领导大黄来讲,他一直都以为是小李在做这项工作;而最后小龙加班加点后完成的工作(“好的,功能已开发完毕!”)全部归功于小李。

    ​ 总结下请求转发,对于客户端(浏览器,领导大黄)来讲,他们不知道自己的Http请求被转发出去了,归根的原因就是在转发时,其将Serlvet容器为这次Http请求创建的HttpServletRequest、HttpServletResponse传递给了下个Servlet。

    ​ 为了加深理解,我们来看下接口RequestDispatcher源码中forward()的解释,代码如下:

    /**
         * Forwards a request from
         * a servlet to another resource (servlet, JSP file, or
         * HTML file) on the server. This method allows
         * one servlet to do preliminary processing of
         * a request and another resource to generate
         * the response.
         *
         * <p>For a <code>RequestDispatcher</code> obtained via 
         * <code>getRequestDispatcher()</code>, the <code>ServletRequest</code> 
         * object has its path elements and parameters adjusted to match
         * the path of the target resource.
         *
         * <p><code>forward</code> should be called before the response has been 
         * committed to the client (before response body output has been flushed). 
         * If the response already has been committed, this method throws
         * an <code>IllegalStateException</code>.
         * Uncommitted output in the response buffer is automatically cleared 
         * before the forward.
         *
         * <p>The request and response parameters must be either the same
         * objects as were passed to the calling servlet's service method or be
         * subclasses of the {@link ServletRequestWrapper} or
         * {@link ServletResponseWrapper} classes
         * that wrap them.
         *
         * <p>This method sets the dispatcher type of the given request to
         * <code>DispatcherType.FORWARD</code>.
         *
         * @param request a {@link ServletRequest} object that represents the
         * request the client makes of the servlet
         *
         * @param response a {@link ServletResponse} object that represents
         * the response the servlet returns to the client
         *
         * @throws ServletException if the target resource throws this exception
         *
         * @throws IOException if the target resource throws this exception
         *
         * @throws IllegalStateException if the response was already committed
         *
         * @see ServletRequest#getDispatcherType
         */
    public void forward(ServletRequest request, ServletResponse response)
      throws ServletException, IOException;
    

    ​ 上面内容很多哈,我们对其中的重点进行解释。forward方法只允许Servlet将请求转发到当前应用中的另一个资源,包括Servlet、Jsp、Html。forward方法在调用前一样不允许Response已经被提交,否则也会抛出异常,并且在调用forward会自动清空Response中未提交的输出数据,因此在调用forward中的Servlet中只可对request进行初步的处理,而不能向客户端发出响应(如果发了要么被清空,要么就会抛出异常)。

    3.找来外援,"强"强联合(请求包含)

    资源分配图

    ​ 从图中我们通过对话可以看到,当领导大黄把任务分配给小李时,小李自己一个人无法完成所有的工作,但是他没有告诉大黄,而是转头找到了小龙,告诉他这个需求,并且自己已经完成了一部分,剩下的咱们一起来做吧,小龙听后,欣然接受,于是两人合力,加班加点把功能完成,然后告知领导大黄,工作已经完成了。注意,这里和请求转发一样,工作完成了,但是因为这项工作是小李私下邀请小龙来帮忙的,领导大黄并不知情,所以大黄只会再次拍着小李的肩膀对他说:“小伙子,干的不错,有前途!”。至于小龙,又尴尬了一波。

    ​ 我们将JumpTestServlet的doGet()方法修改如下,来看下请求包含的执行,代码如下:

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws 			ServletException, IOException {
      //设置返回客户端的contentType
      response.setContentType("text/html;charset=utf-8");
    
      //获取PrintWriter输出对象
      PrintWriter writer = response.getWriter();
      //这里暂且不提,我们后面再分析,为什么浏览器上没有显示这句话
      writer.println("我就是想说句话,看看浏览器能接收到么!");
      //相对路径
      request.getRequestDispatcher("./AnswerServlet").include(request, response);
      //绝对路径
      //request.getRequestDispatcher("/AnswerServlet").include(request, response);
    }
    

    ​ 浏览器地址栏中输入http://localhost:8080/FirstProject/JumpTestServlet,运行结果如下:

    资源分配图

    ​ 从上图可以看到,浏览器中的url并未发生变化,因此领导大黄仍是不知内部的变化。不过请求包含和请求转发还是有些诧异的,比如上图中,JumpTestServlet中输出的"我就是想说句话,看看浏览器能接收到么!",和AnswerServlet中输出的"好的,功能已经开发完毕!"一同返回给了客户端。

    ​ 请求转发和请求包含为何会有如此的区别呢?这是因为在请求转发前,会自动的将所有的response中输出缓冲区中未提交的数据全部清空。而请求包含呢,则会保留缓冲区中未提交的输出数据

    ​ 为了加深理解,我们来看下接口RequestDispatcher源码中include()的解释,代码如下:

    	/**
         *
         * Includes the content of a resource (servlet, JSP page,
         * HTML file) in the response. In essence, this method enables 
         * programmatic server-side includes.
         *
         * <p>The {@link ServletResponse} object has its path elements
         * and parameters remain unchanged from the caller's. The included
         * servlet cannot change the response status code or set headers;
         * any attempt to make a change is ignored.
         *
         * <p>The request and response parameters must be either the same
         * objects as were passed to the calling servlet's service method or be
         * subclasses of the {@link ServletRequestWrapper} or
         * {@link ServletResponseWrapper} classes that wrap them.
         *
         * <p>This method sets the dispatcher type of the given request to
         * <code>DispatcherType.INCLUDE</code>.
         *
         * @param request a {@link ServletRequest} object that contains the
         * client's request
         *
         * @param response a {@link ServletResponse} object that contains the
         * servlet's response
         *
         * @throws ServletException if the included resource throws this
         * exception
         *
         * @throws IOException if the included resource throws this exception
         *
         * @see ServletRequest#getDispatcherType
         */
        public void include(ServletRequest request, ServletResponse response)
            throws ServletException, IOException;
    

    ​ 因为include和forward同属于RequestDispatcher中的方法,因此他俩差别不大。include方法同样只允许Servlet将请求转发到服务上的另一个资源;但是include方法跳转的Servlet无法修改resonse的响应状态(改了也不会生效);不过此方法会保留缓冲区中未提交的输出数据。

    4.几种方式的区别

    ​ 下面我们在通过几个在Serlvet容器中运行的示意图来看一下几种跳转方式的执行过程。

    ​ 请求重定向的执行过程如下:

    资源分配图

    ​ 请求转发的执行过程如下:

    资源分配图

    ​ 请求包含执行过程如下:

    资源分配图

    ​ 上面也讨论了这么多了,下面我们对三种方式的区别来进行一个总结,结果如下表所示:

    表现请求重定向请求转发请求包含
    浏览器中的url是否会发生变化←同左
    浏览器是否知道第二次请求是谁执行的←同左
    客户端发起了几次Http请求2次以上(含2次)1次←同左
    两个Servlet间可以共享request和response么不可以可以←同左
    可以跳转的资源范围当前应用的其他资源、当前tomcat上的其他应用、其他主机上的应用当前应用的其他资源←同左
    支持的location的格式\xxx,.\xxx, ..\xxx,http://,https://\xxx,.\xxx, ..\xxx←同左
    localtion以\开头相对的位置当前serlvet容器的根目录(到端口号后)当前Servlet上下文的根目录(到项目名)←同左
    执行跳转的Servet可以输出信息到客户端么不可以不可以可以,两个Servlet会将输出合并为一个响应给客户端

    5.总结

    ​ 看完本文,是不是对小李觉得特别气,当然这里只是举了这么一个小栗子,能帮助我们理解重定向、转发、包含之间的区别就好。这篇也不是什么鸡汤文,还是实实在在的技术问哈😝。

    ​ 这几种方式没有什么绝对的好坏之分,使用转发能稍微提高一丢丢的性能,因为客户端只发起了一次请求,对于客户端来讲也更省心;但是当需要跳转到应用之外时,就必须要使用重定向了。具体使用哪种跳转方式,还需大家自己评估。


    ​ 又到了分隔线以下,本文到此就结束了,本文内容全部都是由博主自己进行整理并结合自身的理解进行总结,如果有什么错误,还请批评指正。

    ​ Java web这一专栏会是一个系列博客,喜欢的话可以持续关注,如果本文对你有所帮助,还请还请点赞、评论加关注。

    ​ 有任何疑问,可以评论区留言。

    展开全文
  • 内含请求转发,过滤器,${}使用
  • 请求转发与重定向详解

    千次阅读 2018-06-08 00:07:03
    https://blog.csdn.net/Goskalrie/article/details/51217630(转载)转发和包含Servlet对象由Servlet容器创建,并且Servlet对象的service()方法也由容器调用。一个Servlet对象可否直接调用另一个Servlet对象的...
  • servlet中实现请求转发,用户登录,在servlet中验证用户名和密码.
  • 请求转发与重定向

    2016-05-24 05:56:04
    请求转发与重定向
  • spring boot 请求转发和重定向

    千次阅读 2020-12-01 15:44:16
    在尝试过滤器的时候牵扯到请求转发的场景,就顺手测试了一下。这里记录基本的使用套路。 1. 添加依赖 maven: <!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api --> <dependency&...
  • 请求转发和请求包含原理细解

    千次阅读 2017-12-04 09:27:51
    Servlet 容器的作用是负责处理客户请求,当Servlet 容器获取到用户请求后,调用某个Servlet,并把Servlet 的执行结果返回给用户。  Servlet 容器的工作流程:  ● 当用户请求某个资源时,Ser
  • HttpServletRequest请求转发

    千次阅读 2019-04-19 22:10:30
    通过地址栏请求web.xml配置的url,请求到对应得页面,在通过类似form表单提交请求到当前的get请求之后,即跳转到对应转发的界面。 import javax.servlet.ServletException; import javax.servlet.http.HttpServlet;...
  • nginx-请求转发

    2020-11-01 00:35:13
    1、请求转发 2、负载均衡 3、动静分离 二:启动nginx: 1、使用cmd启动nginx(查看进程会有两个nginx.exe运行,这个其实是nginx多路复用,在linux系统上更能体现) 注意:如果关闭cmd窗口,nginx不会停止,只能...
  • 重定向和请求转发的代码实现 - 02

    千次阅读 多人点赞 2020-09-10 20:20:36
    文章目录重定向实现RedirectSevletRedirectSevlet2运行结果请求转发实现DispatcherSevletDispatcherSevlet2运行结果 对请求转发和重定向不了解的可以看这个: ...重定向实现 通过RedirectSevlet重定向到RedirectSevlet2...
  • 在做微服务和单独集成等同构异构的项目过程中,可能会遇到做代理转发、请求转发等相关的功能,下面的代码(项目片段demo代码)可能具有一定的参与功能 下面代码仅供参考,具体还需要根据自己的项目情况对代码进行改造...
  • Nginx实现请求转发

    千次阅读 2020-06-28 23:34:15
    什么是请求转发? 环境配置 到官网下载nginx,这里使用的windows版本,最好使用Linux版本(性能好) 把下载好的文件解压,在Nginx.conf进行配置 (1)修改Nginx默认端口,把80修改为81 listen 81; server_name ...
  • 一、前言 请求和响应是对立关系。这篇技术博客主要讲解请求对象:HttpServletRequest 该对象代表客户端请求。...HttpServletRequest中。...请求转发代码如下: package com.xu.servlet; import javax.servlet.ServletEx
  • 重定向 请求转发 与cookie

    千次阅读 2020-03-11 17:25:23
    重定向与请求转发的比较 1: 重定向是两次请求,而请求转发是一次请求 解释:比如我们请求index.jsp页面,再由index.jsp页面重定向到success.jsp页面,那么在请求完index.jsp页面后,index.jsp直接给客户端一个响应...
  • Nginx 请求转发配置-工作记录

    千次阅读 2019-07-19 17:43:53
    Nginx 请求转发配置-工作记录前言当前Nginx 工作情况和新需求当前Nginx配置满足新需求的配置关键配置内容解析注意事项 前言 记录工作中的一次 Nginx 配置 当前Nginx 工作情况和新需求 当前 Nginx 工作情况: ...
  • 请求转发和重定向区别

    千次阅读 2019-03-17 21:20:56
    一、转发和重定向区别详解 作为一名程序员,特别是...RequestDispatcher.forward方法只能将请求转发给同一个WEB应用中的组件;而HttpServletResponse.sendRedirect 方法不仅可以重定向到当前应用程序中的其他资源,...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 409,707
精华内容 163,882
关键字:

请求转发