JavaWeb小记——重定向和内部转发

本文详细介绍了Servlet中重定向和内部转发的区别与应用场景。重定向涉及两次请求和响应,地址栏会改变,可用于外部资源访问;而内部转发是一次请求响应过程,地址栏不变,仅限于内部资源。重定向不能访问WEB-INF下的资源,但内部转发可以。此外,请求域对象request在内部转发中能保持数据共享,而在重定向中无法做到。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

重定向

原理图

重定向语句

重定向特点

内部转发

原理图

请求转发特点 

路径的书写

请求域对象request

特点

请求转发特点

重定向特点


重定向

原理图

重定向语句

response.setStatus(302);
response.setHeader("location","http://www.baidu.com");
//以上两条等于下面一条

response.sendRedirect("http://www.baidu.com");

重定向特点

1.两次请求,两次响应。

当浏览器向服务器中aServlet发送请求时,aServlet说 我执行不了,让bServlet去做吧,然后aServlet向浏览器响应302重定向状态码,再设置一个bServlet路径的响应头。浏览器再将请求发往bServlet,bServlet执行后再响应给浏览器。所以是两次请求,两次响应。

2.发送请求后,地址栏会发生变化。

比如下面一段代码

package org.xingyun.demo;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet(name = "Servletdemo2",value = "/demo2")
public class Servletdemo2 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.sendRedirect("http://www.baidu.com");
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}

请求后:

 3.可以访问外部站点资源,也可以访问内部的资源。

外部资源:

例如第二点,进入百度

内部资源:

response.sendRedirect("/MyServlet20230624_war_exploded/my.jsp");

4.无法访问WEB-INF下的资源

response.sendRedirect("/MyServlet20230624_war_exploded/WEB-INF/webINF.jsp");

5.访问内部站点资源时,需写上项目的上下文路径。

内部转发

原理图

简单案例:

package org.xingyun.demo2;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet(name = "ServletDemo6",value = "/demo6")
public class ServletDemo6 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("demo6收到请求了");
        request.getRequestDispatcher("/demo7").forward(request,response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}






package org.xingyun.demo2;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet(name = "ServletDemo7",value = "/demo7")
public class ServletDemo7 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("demo7收到请求了");
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}

运行结果:

请求转发特点 

1.一次请求,一次响应

在内部进行转发

2.地址栏不会发生变化

 

3.只能请求内部站点的资源 

 4.可以访问WEB-INF下的资源

5. 不用写项目的上下文路径

路径的书写

路径的书写: 
        建议以/开头
        服务器内部跳转路径 不需要加项目上下文路径  request.getRequestDispatcher("/myservlet2").forward(request, response);
    
        页面上的路径和重定向 需要加上项目的上下文路径
        <img src="/MyServlet/mydemo4" id="img1"></img>
        

        一般来说我们写相对路径

请求域对象request

特点

只能在一次请求和一次响应之间共享数据,一次请求响应后自动销毁。

请求转发特点

例:

我们先在demo6中用请求域对象存一个数据,用内部转发的方式转发到demo7,在demo7中取数据,看能否取到。

//demo6
@WebServlet(name = "ServletDemo6",value = "/demo6")
public class ServletDemo6 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("demo6收到请求了");
        int num = 100;
        request.setAttribute("num",num);
        request.getRequestDispatcher("/demo7").forward(request,response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}



//demo7
@WebServlet(name = "ServletDemo7",value = "/demo7")
public class ServletDemo7 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("demo7收到请求了");
        Integer num = (Integer) request.getAttribute("num");
        System.out.println(num);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}

运行结果:

可见,可以在demo7中取到数据,因为请求转发是一次请求,一次响应。

重定向特点

然后我们再使用重定向的方式转发,看能否取到

可见,取不到数据了,因为重定向是两次请求,两次响应。

用ServletContext全局域对象都可以取到数据,因为它范围最大。

什么时候用重定向,什么时候用内部转发
        如果,你要跳到外部站点,只能用重定向。
        如果,你要访问WEB-INF下的资源,只能用内部转发。
        如果,你把数据存到了 request 请求域中,你还要共享数据,你要用内部转发。
        如果我要重定向,跳转资源,还想要在跳转的资源间共享数据,那我们可以 Session或者ServletContext 全局域对象

补充知识

//request中的get方法


request.getAttribute()               //获得setAtrribute的数据
request.getAttributeNames()           //返回所有可用属性名的枚举
request.getAuthType()               //返回用于保护servlet的验证方法名称
request.getCharacterEncoding()        //返回字符编码方式
request.getClass()                   //返回一个类
request.getContentLength()            //返回请求体的长度(以字节数)
request.getContentType()              //得到请求体的MIME类型
request.getContextPath()               //获取当前系统的路径 获得应用名称
request.getCookies()                  //返回此次请求发送的Cookie对象
request.getDateHeader()               //用于将指定头信息的部分转换成方便转换为时间类型的长整数型
request.getHeader()                   //获取客户端的浏览器类型。
request.getHeaderNames()           //返回请求头包含的所有头名称的枚举。
request.getHeaders()               //获取一个name的多个值序列,返回请求给出的指定类型的所有HTTP头标的名称的枚举值
request.getInputStream()              //得到请求体中一行的二进制流
request.getIntHeader()                //以int的形式返回指定请求头的值。
request.getLocalAddr()                 //接收请求的接口的 InternetProtocol (IP) 地址

request.getLocale()                     //基于 Accept-Language 头,返回客户端将用来接受内容的首选 Locale 客户端语言环境

request.getLocales()                    //所有的语言环境
request.getLocalName()                  //接收请求的 Internet Protocol(IP) 接口的主机名

request.getLocalPort()                  //接收请求的接口的 InternetProtocol (IP) 端口号

request.getMethod()                     //请求方式
request.getParameter()                   //获得表单提交的数据
request.getParameterMap()                //返回类型是String[]
request.getParameterNames()              //将发送请求页面中form表单里所有具有name属性的表单对象获取(包括button).返回一个Enumeration类型的枚举
request.getParameterValues()             //将获取所有form表单中name属性为"name"的值.该方法返回一个数组.遍历数组就可得到value值
request.getPathInfo()                   //返回与客户端发出此请求时发送的URL相关联的额外路径信息。

request.getPathTranslated()           //映射到服务器实际路径之后的路径信息
request.getProtocol()                   //返回请求用的协议类型及版本号获取客户端向服务器端传送数据所依据的协议名称。
request.getQueryString()                //字符串形式的附加到URL后面的查询字符串,数据仍旧是URL编码的
request.getReader()                      //返回解码过了的请求体
request.getRealPath()                    //返回一虚拟路径的真实路径
request.getRemoteAddr()                  //返回发送此请求的客户端IP地址
request.getRemoteHost()                    //返回发送此请求的客户端主机名   获取客户端的名字
request.getRemotePort()                      //发送请求的客户主机端口
request.getRemoteUser()                   //返回包含在请求RUL中路径后面的查询字符串。如果没有查询字符串返回null
       
request.getRequestDispatcher()            //请求转发,获取请求过来的地址,与该地址共享一个Request

request.getRequestedSessionId()             //返回客户端制定的回话ID
request.getRequestURI()                    //请求的资源
request.getRequestURL()             //获取URL,包含域名,不包含请求内容

request.getScheme()                    // 返回请求用的计划名,  返回当前链接使用的协议 如:http.https及ftp等
request.getServerName()                //返回接受请求的服务器主机名获取服务器的名字。
request.getServerPort()                //返回服务器接受此请求所用的端口号 
request.getServletPath()                //返回请求调用servlet的URL部分
request.getSession()                    //返回与此请求关联的当前HttpSession,如果没有当前会话并且参数为true,则返回一个新会话
    
request.getUserPrincipal()            // 返回包含当前已经过验证的用户的名称的java.security.Principal对象。如果用户没有经过验证,则该方法返回null

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jmh-Ethereal

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值