概述:
如何从服务器端的某个资源访问另一个资源?从服务器端的某个资源访问另一个资源通常有两种访问方式:
一种叫做请求转发;
一种叫做请求重定向;
1、forward(请求转发)
如何理解请求转发:
从Servlet1,请求转发到Servlet2, Servlet1完成一部分的功能,再跳转到Servlet2,继续完成剩下的功能。
语法:
1
2 1request.getRequestDispatcher(String path).forward(request,response);
2
参数:path,表示跳转的目标的路径(资源的名称)。
打个比方:
老师交给班长一个工作任务,就是今晚帮忙关闭电脑;但是班长今晚有事情,不能做这个工作,他就把这个工作交给别人做了;改天老师来就看到电脑已经被关闭了在老师的眼里这个工作还是班长做的。
在web程序中,就是一个servlet可以把一个请求再发送给另一个servlet(类似于工作转移),但是对于客户端来说,它还是认为工作是第一个servlet完成的,第一个servlet把工作交给第二个servlet去完成的过程就叫做请求转发。
请求转发实现转发只使用了一次http请求,一次转发中request和response对象都是同一个;请求转发是一次请求一旦把请求参数放入到request中,则只要是请求转发,无论转发过程中经历多少个资源,则在这些资源中都可以获取放入request中的参数值请求转发是不会改变浏览器的请求路径的;编写请求转发的路径是不需要写项目名称的;请求转发的响应体是最后一个处理请求的servlet返回的信息。
请求转发流程图:
(1)使用请求转发转到s2页面
servlet1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 1@WebServlet("/forward/s1")
2public class Servlet1 extends HttpServlet{
3 private static final long serialVersionUID = 1L;
4 @Override
5 protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
6 resp.setContentType("text/html;charset=utf-8");
7 PrintWriter out=resp.getWriter();
8 //===========================================
9 //System.out.println("servlet1.service()");
10 System.out.println("servlet1……before");//控制台输出
11 out.println("servlet1……before");//网页输出
12 //---------------------------------------
13 //请求转发
14 req.getRequestDispatcher("/forward/s2").forward(req, resp);
15 //---------------------------------------
16 System.out.println("Servlet1……after");
17 out.println("Servlet1……after");
18 }
19}
20
servlet2:
1
2
3
4
5
6
7
8
9
10
11
12 1@WebServlet("/forward/s2")
2public class Servlet2 extends HttpServlet{
3 private static final long serialVersionUID = 1L;
4 @Override
5 protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
6 resp.setContentType("text/html;charset=utf-8");
7 PrintWriter out=resp.getWriter();
8 System.out.println("Servlet2……");
9 out.println("Servlet2……");
10 }
11}
12
在浏览器输入:http://localhost:9090/forward/s1 进行访问发现输出的是servlet2的数据,但是浏览器地址栏并没有变成s2;
控制台最后输出的数据证明页面最后还是跳转回了s1;
(2)分别在servlet1和servlet2中写入获取参数的代码,在浏览器地址栏输入参数:
1
2 1System.out.println("servlet1……before"+req.getParameter("name"));//控制台输出
2
1
2 1System.out.println("Servlet2……"+req.getParameter("name"));
2
可以看到servlet1和servlet2获取到的参数是一样的。
(3)在servlet1和servlet2中打印请求看输出的请求地址是否为同一个;
1
2 1System.out.println(req);
2
在控制台看到输出的地址不一样但是获得的参数是一样的,这说明他们共享的是同一个请求中的数据。
(4)WEB-INFO中的资源是受保护的不能直接访问,可以使用请求转发进行访问;
1
2
3 1//使用请求转发访问WEB-INF中的资源
2req.getRequestDispatcher("/WEB-INF/in.html").forward(req, resp);
3
请求转发的特点:
1:浏览器地址栏不发生改变,依然是/forward/s1,不是目标地址(/forward/s2)。
2:请求转发只发送一个请求。
3:共享同一个请求中的数据。
4:最终响应给浏览器的由Servlet2来完成。
5:请求转发不能跨域访问,只能跳转到当前web服务器中的资源。
6:请求转发可以访问WEB-INF目录中的资源。
2、redirect(重定向)
如何理解重定向:
通过各种方法将各种网络请求重新定个方向转到其它位置,如其它网址;
语法:
1
2 1response.sendRedirect(String url);
2
参数:url,表示目标资源地址。
打个比方:
老师交给班长一个工作任务,就是今晚帮忙关闭电脑;但是班长今晚有事情,不能做这个工作;班长就向老师反馈,我不能做这个工作,但是某个同学可以做;然后老师就又找这个同学去做这个事情;最终事情做完,老师知道是哪个同学完成的这个事情。
在web程序中,就是一个servlet1可以把请求再返回给客户端,由客户端再请求第二个servlet2去完成
但是对于客户端来说它是知道工作是第二个servlet2完成的;
在以上的描述中,第一个servlet1把工作返回了客户端,由客户端再交给第二个servlet2去完成,这个过程就叫做请求重定向,请求重定向是两次请求,两次请求的结果就是对应两个request,第一个request是客户端把参数发送给servlet1,在Servlet1输出了请求参数,在servlet1中使用重定向把一个请求路径返回给客户端浏览器;第二个request是浏览器再使用第一个servlet1返回的路径去访问servlet2。
URL重定向流程图:
(1)使用重定向跳转到servlet2,在浏览器地址栏输入:localhost:9090/redirect/s1。
1
2
3 1//使用URL重定向跳转到servlet2
2resp.sendRedirect("/redirect/s2");
3
回车之后地址栏变成了s2;
(2)在servlet1和servlet2中加入接受请求参数的代码,看他们能否获得同一个参数。
1
2
3 1//servlet1获取请求参数
2System.out.println("servlet1……before"+req.getParameter("name"));me"));
3
1
2
3 1//servlet2获取请求参数
2System.out.println("Servlet2……"+req.getParameter("name"));
3
在浏览器地址栏输入:localhost:9090/redirect/s1?name=wiil,发现servlet1获得了请求参数,而servlet2获得的值为null;从中可以看出URL重定向是两次独立的请求,所以不共享请求中的数据。
(3)使用URL进行跨域访问
1
2
3 1//使用URL重定向进行跨域访问百度
2resp.sendRedirect("https://baidu.com");
3
在浏览器地址栏输入:localhost:9090/redirect/s1,回车之后跳转到百度,如下图:
重定向的特点:
1:浏览器地址栏发生改变,从/redirect/s1,变成目标地址(/redirect/s2)。
2:URL重定向发了两次请求。
3:因为URL重定向是两次独立的请求,所以不共享请求中的数据。
4:最终响应给浏览器的由Servlet2来决定(相当于把目标地址拷贝到浏览器地址栏,敲回车)。
5:URL重定向能跨域访问,可以访问其他应用中的资源。
6:URL重定向不能访问WEB-INF目录中的资源。
3、forward和redirect的区别
D1:请求转发一个请求一个request对象;
请求重定向两次请求两个request对象。
D2:使用请求转发浏览器的url是不会发生改变的;
使用请求重定向浏览器的url是会发生变化的。
D3:使用请求转发只要是在这个转发流程中,每一个servlet都可以获取请求参数;
使用重定向, 只是第一次浏览器给某个servlet发送的请求参数可以被接收到,重定向的servlet是接收不到请求参数的(需要把请求参数再次传递)。
D4:请求转发可以访问应用WEB-INF下的资源;而请求重定向是不可以访问应用WEB-INF下的资源;所以以上的问题就牵扯了如果考虑资源的安全性,可以把资源放到本应用的WEB-INF下,这样使用重定向方式不能访问(也就意味着使用浏览器不能访问) 客户从别的地方使用浏览器就不能访问这个资源,只能使用请求转发从后台程序访问。
D5:使用请求重定向可以从本系统的某个资源访问别的系统的某个资源。
D6:传递的数据类型不同:
转发的request对象可以传递各种类型的数据,包括对象。
重定向只能传递字符串。
D7:调转的时间不同:
转发时:执行跳转语句时就会立刻跳转;
重定向:整个页面执行完之后才执行跳转。
应用场景:
1、转发:访问servlet处理业务逻辑,然后forward到jsp显示处理结果,浏览器里URL不变。
2、重定向:提交表单,处理成功后redirect到另一个jsp,防止表单重复提交,浏览器里URL变了。
请求转发全部代码:
servlet1:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 1@WebServlet("/forward/s1")
2public class Servlet1 extends HttpServlet{
3 private static final long serialVersionUID = 1L;
4
5 @Override
6 protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
7 System.out.println(req);
8 resp.setContentType("text/html;charset=utf-8");
9 PrintWriter out=resp.getWriter();
10 //===========================================
11 //System.out.println("servlet1.service()");
12 System.out.println("servlet1……before"+req.getParameter("name"));//控制台输出
13 out.println("servlet1……before");//网页输出
14 //---------------------------------------
15 //请求转发
16 //没有加:/,使用当前资源的相对路径
17 //资源路径:/forward/s1,相对路劲,找到最后一个/,之前的部分就是相对路径:/forward
18 //req.getRequestDispatcher("/forward/s2").forward(req, resp);
19 //使用请求转发访问WEB-INF中的资源
20 req.getRequestDispatcher("/WEB-INF/in.html").forward(req, resp);
21 //---------------------------------------
22 System.out.println("Servlet1……after");
23 out.println("Servlet1……after");
24 }
25}
26
27
servlet2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 1@WebServlet("/forward/s2")
2public class Servlet2 extends HttpServlet{
3 private static final long serialVersionUID = 1L;
4
5 @Override
6 protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
7 System.out.println(req);
8 //System.out.println("servlet2.service()");
9 resp.setContentType("text/html;charset=utf-8");
10 PrintWriter out=resp.getWriter();
11 //===========================================
12 System.out.println("Servlet2……"+req.getParameter("name"));
13 out.println("Servlet2……");
14 }
15}
16
in.html
1
2
3
4
5
6
7
8
9
10
11 1<!DOCTYPE html>
2<html>
3<head>
4<meta charset="UTF-8">
5<title>in.html</title>
6</head>
7<body>
8 WEB-INF中的资源
9</body>
10</html>
11
重定向全部代码:
servlet1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 1@WebServlet("/redirect/s1")
2public class Servlet1 extends HttpServlet{
3 private static final long serialVersionUID = 1L;
4
5 @Override
6 protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
7 System.out.println(req);
8 resp.setContentType("text/html;charset=utf-8");
9 PrintWriter out=resp.getWriter();
10 //===========================================
11 System.out.println("servlet1……before"+req.getParameter("name"));
12 out.println("servlet1……before");
13 //---------------------------------------
14 //使用URL重定向跳转到servlet2
15 //resp.sendRedirect("/redirect/s2");
16 //使用URL重定向进行跨域访问百度
17 resp.sendRedirect("https://baidu.com");
18 //---------------------------------------
19 System.out.println("Servlet1……after");
20 out.println("Servlet1……after");
21 }
22}
23
24
servlet2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 1@WebServlet("/redirect/s2")
2public class Servlet2 extends HttpServlet{
3 private static final long serialVersionUID = 1L;
4
5 @Override
6 protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
7 System.out.println(req);
8 //System.out.println("servlet2.service()");
9 resp.setContentType("text/html;charset=utf-8");
10 PrintWriter out=resp.getWriter();
11 //===========================================
12 System.out.println("Servlet2……"+req.getParameter("name"));
13 out.println("Servlet2……");
14 }
15}
16