JavaWeb 速通Servlet(请求转发和请求重定向)

本文涉及的产品
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: JavaWeb——HttpServletRequest 和 HttpServletResponse 内容分享。

目录

一、HttpServletRequest

       1.简介 :

       2.常用方法 :

           1° getRequestURI() :

           2° getRequestURL() :

           3° getRemoteHost() :

           4° getHeader(String header) :

           5° getParameter(name) :

           6° getParameterValues(name) :

           7° getMethod() :

           8° setAttribute(key, value) :

           9° getAttribute(key) :

           10° getRequestDispatcher() :

       3.获取表单数据的演示 :

       4.使用细节 :

二、请求转发

       1.基本介绍 :

       2.应用实例 :

       3.请求转发细节 :

三、HttpServletResponse

       1.基本介绍 :

       2.常用方法 :

       3.乱码问题的解决办法 :

四、请求重定向

       1.基本介绍 :

       2.应用实例 :

       3.使用细节 :

五、Servlet(下)总结


一、HttpServletRequest

       1.简介 :

       HttpServletRequest对象代表客户端的请求,当客户端/浏览器通过HTTP协议访问服务器时,HTTP请求头中的所有信息都封装在这个对象中

       通过HttpServletRequest对象来调用相应的API,即可获取来自客户端的请求信息。

       HttpServletRequest接口的类图如下 :

image.gif 编辑

       2.常用方法 :

           1° getRequestURI() :

               获取请求的统一资源标识符(资源路径);eg : /Servlet_Demo/countServlet

           2° getRequestURL() :

               获取请求的统一资源定位符(绝对路径);eg : http://localhost:8080/Servlet_Demo/countServlet

               PS:URL是URI的一个子集(更具体)。

           3° getRemoteHost() :

               获取客户端的主机名

           4° getHeader(String header) :

               获取请求头

           5° getParameter(name) :

               获取请求的参数;(name可以是text,password,radio,select或textarea的name属性值)

           6° getParameterValues(name) :

               获取请求的参数(多个值);eg : checkbox返回的数组

           7° getMethod() :

               获取请求的方式;eg : GET, POST, etc.

           8° setAttribute(key, value) :

               设置域数据

           9° getAttribute(key) :

               获取域数据

           10° getRequestDispatcher() :

               获取请求转发对象(实现“请求转发”的核心对象)

      3.获取表单数据的演示 :

               静态页面registerEX.html如下 :

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Register</title>
    <style>
        table,tr,td {
            border:2px solid cornflowerblue;
            border-collapse: collapse;
            margin-left:auto;
            margin-right:auto;
            /*padding: 10px;*/
        }
        #tr_1 {
            text-align: center;
        }
    </style>
</head>
<body>
<form action="http://localhost:8080/Servlet_Demo/httpServletRequestMethods" method="post">
<table>
    <tr>
        <th colspan="2">User Register</th>
    </tr>
    <tr>
        <td>username:</td>
        <td><input type="text" name="username"/></td>
    </tr>
    <tr>
        <td>password:</td>
        <td><input type="password" name="password"/></td>
    </tr>
    <tr>
        <td>Choose your favorite fruit:</td>
        <td><input type="checkbox" name="fruit" value="apple"/>Apple<br/>
            <input type="checkbox" name="fruit" value="strawberry"/>Strawberry<br/>
            <input type="checkbox" name="fruit" value="grape"/>Grape</td>
    </tr>
    <tr id="tr_1">
        <td><input type="submit" value="register"/></td>
        <td><input type="reset" value="reset"/></td>
    </tr>
</table>
</form>
</body>
</html>

image.gif

               页面效果如下图所示 :

image.gif编辑

               HttpServletRequestMethods类代码如下 :

package down;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
    (1)若重写后的doPost方法中没有做任何处理,是默认的super.doPost(req, resp);
        这种情况下,浏览器会报405状态码(方法不允许)
    (2)HTTP请求的内容主要分为两大类 ———— 请求头和请求体(也叫请求参数)
 */
//通过注解方式配置url
@WebServlet(urlPatterns = {"/httpServletRequestMethods"})
public class HttpServletRequestMethods extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1.获取请求的统一资源标识符URI
        String requestURI = req.getRequestURI();
        System.out.println("URI = " + requestURI);
        //2.获取请求的统一资源定位符URL
        //PS:URL是URI的一个子集(更具体)。
        StringBuffer requestURL = req.getRequestURL();
        System.out.println(("URL = " + requestURL));
        //3.获取客户端的主机地址
        String remoteHost = req.getRemoteHost();
        System.out.println("Host's IP = " + remoteHost);
            //获取客户端的IP地址
        String remoteAddr = req.getRemoteAddr();
        System.out.println("Addr = " + remoteAddr);
        //4.获取请求头
            //客户端的主机名(IP + 端口)
        String host = req.getHeader("Host");
        System.out.println("Host = " + host);
            //请求的发起地址
        String referer = req.getHeader("Referer");
        System.out.println("Referer = " + referer);
            //请求的用户信息
        String userAgent = req.getHeader("User-Agent");
        System.out.println("User-Agent = " + userAgent);
        System.out.println("Browser = " + userAgent.split(" ")[userAgent.split(" ").length - 1]);
/*======================================获取表单数据======================================*/
        //5.获取请求的参数
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        System.out.println("text = " + username);
        System.out.println("password = " + password);
        //6.获取请求的参数(多个值)
        String[] fruits = req.getParameterValues("fruit");
        for (String fruit : fruits) {
            System.out.println("The checkbox elements you choose:" + fruit);
        }
        //7.获取请求的方式(GET POST etc)
        String method = req.getMethod();
        System.out.println("method = " + method);
    }
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);
    }
}

image.gif

               运行效果 :(如下GIF图)

image.gif编辑

       4.使用细节 :

       防止“表单提交的数据出现乱码”问题,可以在使用req.getParameter(string)方法前,调用req.setCharacterEncoding("utf-8")方法

      防止“服务器返回给浏览器的数据出现乱码”问题,可以在获取PrintWriter对象前,调用resp.setContentType("text/html; charset=utf-8")方法。(对应Http响应的响应头Content-Type)


二、请求转发

       1.基本介绍 :

       当业务比较复杂时,一次请求可能需要多个Servlet来完成(eg : Servlet链的流水作业)。如下图所示 :

image.gif 编辑

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

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

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

       常用方法如下——

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

           2.应用实例 :

                   要求定义VerifyServlet和ReplyServlet两个servlet资源,前者用于对表单提交的数据进行校验,并令Tomcat去调用ReplyServlet来处理校验后的数据;后者用于处理数据并反馈给浏览器。

                  register.html代码如下 :

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Register</title>
    </head>
    <body>
        <h1>User Register</h1>
        <form action="http://localhost:8080/Servlet_Demo/verifyServlet" method="post">
            username:<input type="text" name="username"/> <br/><br/>
            <input type="submit" value="register"/>
        </form>
    </body>
    </html>

    image.gif

                   VerifyServlet类代码如下 :

    package down.req;
    import jakarta.servlet.RequestDispatcher;
    import jakarta.servlet.ServletException;
    import jakarta.servlet.annotation.WebServlet;
    import jakarta.servlet.http.HttpServlet;
    import jakarta.servlet.http.HttpServletRequest;
    import jakarta.servlet.http.HttpServletResponse;
    import java.io.IOException;
    /**
     * @author : Cyan_RA9
     * @version : 21.0
     */
    @WebServlet(urlPatterns={"/verifyServlet"})
    public class VerifyServlet extends HttpServlet {
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            System.out.println("VerifyServlet's doPost is invoked~");
            req.setCharacterEncoding("utf-8");
            String username = req.getParameter("username");
            if ("Cyan".equals(username)) {
                req.setAttribute("status", "Manager");
            } else {
                req.setAttribute("status", "Employee");
            }
            /**
             (1) /replyServlet是要转发的servlet的url
             (2) "/"会被Tomcat解析成"/Servlet_Demo/",即当前Web工程路径
                如果开头没写/,默认会隐含一个/。
             (3) forward(request,response)表示把当前servlet的request对象和response对象,
                传递给下一个servlet使用 (相同)
             */
            //获取分发器
            RequestDispatcher requestDispatcher = req.getRequestDispatcher("/replyServlet");
            requestDispatcher.forward(req, resp);
        }
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            doPost(req, resp);
        }
    }

    image.gif

                  ReplyServlet类代码如下 :

    package down.req;
    import jakarta.servlet.ServletException;
    import jakarta.servlet.annotation.WebServlet;
    import jakarta.servlet.http.HttpServlet;
    import jakarta.servlet.http.HttpServletRequest;
    import jakarta.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import java.io.PrintWriter;
    /**
     * @author : Cyan_RA9
     * @version : 21.0
     */
    @WebServlet(urlPatterns = {"/replyServlet"})
    public class ReplyServlet extends HttpServlet {
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            System.out.println("ReplyServlet's doPost is invoked~");
            String username = req.getParameter("username");
            String status = (String) req.getAttribute("status");
            resp.setContentType("text/html; charset=utf-8");
            PrintWriter writer = resp.getWriter();
            writer.print("" +
                    "<table border=\"2px\"; bordercolor=\"pink\" cellspacing=\"0\" cellpadding=\"10px\">" +
                        "<tr>" +
                            "<td colspan = 2>The data you submitted : </td>" +
                        "</tr>" +
                        "<tr>" +
                            "<th>username: </th>" +
                            "<th>" + username + "</th>" +
                        "</tr>" + "<tr><th>status: </th><th>" + status + "</th>" +
                        "</tr>" +
                    "</table>");
            writer.flush();
            writer.close();
        }
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            doPost(req, resp);
        }
    }

    image.gif

                   运行效果 : (如下GIF图)

    image.gif编辑

           3.请求转发细节 :

      1.        浏览器地址栏的URL不会变化 (地址会保留在第1个servlet的url)。因为“请求转发”的整个过程都是在服务器端进行的,与浏览器没有关系;最终仍是Tomcat以HTTP响应的方式回显给浏览器。
      2.        同一次HTTP请求中可进行多次转发;同一次HTTP请求中,进行多次转发,多个Servlet可以共享request域/对象的数据(因为始终是同一个request对象)。
      3.        “请求转发”也可以转发到WEB-INF目录下(做项目使用)
      4.        “请求转发”不能访问当前WEB工程外的资源。(404)
      5.        因为浏览器地址栏会停止在第一个servlet,因此,如果刷新页面,会再次发出请求(并且会携带数据),所以在支付页面等情况下,不要使用请求转发,否则会造成重复支付。

      三、HttpServletResponse

             1.基本介绍 :

             每次发出HTTP请求,Tomcat都会创建一个HttpServletResponse对象传递给Servlet程序去使用

             HttpServletRequest表示请求过来的信息,而HttpServletResponse则表示所有响应的信息,如果需要设置返回给客户端的信息,通过HttpServletResponse对象来进行设置即可(最终仍是由Tomcat以HTTP响应的方式将数据返回给客户端)。

             HttpServletResponse类图如下 :

      image.gif 编辑

             2.常用方法 :

             1.字节流getOutputStream() :

                     常用于下载文件(处理二进制数据)

             2.字符流getWriter() :(之前举过的例子用过)

                     常用于回显字符串

             Δ细节:

                     两个流只能同时使用一个——使用了字节流,就不能再使用字符流,反之亦然,否则就会报错

             3.乱码问题的解决办法 :

             方式一 —— 老办法(最好用):

                    resp.setContentType("text/html; charset = utf-8");

                     setContentType方法会同时设置服务器端和客户端都使用utf-8字符集编码,并且还设置了响应头,但setContentType必须在获取流对象之前调用

             方式二 —— 新办法(也还行):

                     resp.setCharacterEncoding("utf-8");        //先设置服务器端使用utf-8编码

                     resp.setHeader("Content-Type", "text/html; charset = utf-8");        /*再通过响应头的方式设置浏览器端的编码 */


      四、请求重定向

             1.基本介绍 :

             请求重定向指:一个web资源收到客户端请求后,通知客户端去访问另外一个web资源,这称之为请求重定向。

             请求重定向中,负责重定向功能的servlet会将响应状态码修改为302(表示请求重定向),然后设置一个Location属性,用于告知浏览器下一次请求该访问哪个资源。[通过sendRedirect("/web工程名/web资源") 方法来实现]

             2.应用实例 :

                     有一个超链接的页面,要求该超链接导向一个servlet,而该servlet会通过“请求重定向”通知浏览器端去访问另外一个servlet。(Servlet此处采用注解方式配置)

                     redirection.html代码如下 :

      <!DOCTYPE html>
      <html lang="en">
      <head>
          <meta charset="UTF-8">
          <title>Redirection Demo</title>
      </head>
      <body>
          <h1>⭐408资料分享⭐</h1>
          <a href="http://localhost:8080/Servlet_Demo/old" target="_self">
              快点我!点我下载数据结构1800题!
          </a>
      </body>
      </html>

      image.gif

                     OldServlet类代码如下 :

      package down.resp;
      import jakarta.servlet.ServletException;
      import jakarta.servlet.annotation.WebServlet;
      import jakarta.servlet.http.HttpServlet;
      import jakarta.servlet.http.HttpServletRequest;
      import jakarta.servlet.http.HttpServletResponse;
      import java.io.IOException;
      /**
       * @author : Cyan_RA9
       * @version : 21.0
       */
      @WebServlet(urlPatterns = {"/old"})
      public class OldServlet extends HttpServlet {
          @Override
          protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
              /*
                  (1) sendRedirect方法本质上就会返回302(重定向)状态码,并且设置Location响应头;
                  (2) 与请求转发不同,“请求重定向”的解析不是在服务器端进行的,而是由浏览器解析;
                      此处的"/"会被浏览器解析为"http://localhost:8080/";
                  (3) So, “请求重定向”时,sendRedirect方法中的格式必须是“/Web应用名/Web资源”
                      注意第一个斜杠!(如果开头没有写斜杠,浏览器默认会以当前地址栏为准!注意区分!)
               */
              resp.sendRedirect("/Servlet_Demo/new");
          }
          @Override
          protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
              doPost(req, resp);
          }
      }

      image.gif

                    NewServlet类代码如下 :

      package down.resp;
      import jakarta.servlet.ServletException;
      import jakarta.servlet.annotation.WebServlet;
      import jakarta.servlet.http.HttpServlet;
      import jakarta.servlet.http.HttpServletRequest;
      import jakarta.servlet.http.HttpServletResponse;
      import java.io.IOException;
      import java.io.PrintWriter;
      /**
       * @author : Cyan_RA9
       * @version : 21.0
       */
      @WebServlet(urlPatterns={"/new"})
      public class NewServlet extends HttpServlet {
          @Override
          protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
              //注意此处MIME类型的使用
              resp.setContentType("application/x-tar; charset=utf-8");
              //如果想看到浏览器地址栏的变化,可以使用"text/html"MIME类型
              PrintWriter writer = resp.getWriter();
              writer.print("数据结构1800题pdf!");
              writer.flush();
              writer.close();
          }
          @Override
          protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
              doPost(req, resp);
          }
      }

      image.gif

                     运行效果 : (如下GIF图)

      image.gif编辑

             3.使用细节 :

            "302" 的最佳应用场景 —— 网站迁移。比如网站的域名变更,原域名是 www.CyanRA9.com 迁移到新域名 www.CyanRA9.cn,但是浏览器抓取的仍然是原来的域名,这时就可以通过一个请求重定向来解决问题。

              “请求重定向”的使用中,浏览器地址栏会发生变化(最终停留在新的web资源的URL),本质是两次HTTP请求

             “请求重定向”不能共享HttpServletRequest域中的数据,因为本质是两次HTTP请求,会生成两个不同的HttpServletRequest对象

             不能重定向到 /WEB-INF 下的资源(受保护)

             可以重定向 Web 工程以外的资源, 比如到其他网站(必应之类的)

             请求重定向有两种方式——

                    (1) resp.sendRedirect("/web项目名/web资源");        //推荐第一种!

                     (2) resp.setStatus(302);

                           resp.setHeader("Location", "/Servlet_Demo/new");

              可以使用getServletContext().getContextPath() 方法来获取当前Web项目的工程路径(动态获取工程路径),得到工程路径后,再以字符串拼接的形式(工程路径 + 具体的web资源)传递给sendRedirect方法,使URL的配置更加灵活。


      五、Servlet(下)总结

            (1)掌握HttpServletRequest的常用方法(eg : URL和URI的区别;获取请求头的方法;获取表单提交数据的多种方式

             (2) 掌握请求转发的底层原理(同一个域对象),以及如何实现请求转发。

            (3) 掌握HttpServletResponse回显数据给浏览器的具体步骤,以及如何解决乱码问题。

             (4) 掌握请求重定向的底层原理,以及重定向的具体实现(注意与请求转发格式的区别!)

             System.out.println("END---------------------------------------------------------------------------------");

      目录
      相关文章
      |
      2月前
      |
      JavaScript Java 容器
      servlet过滤器Filter简要回顾-过滤请求字符编码,/和/*和/**的区别
      本文简要回顾了Servlet过滤器Filter的概念和使用,通过实例演示了如何创建过滤器以过滤请求字符编码,并解释了在web.xml中配置过滤器时使用`/`、`/*`和`/**`的区别。
      servlet过滤器Filter简要回顾-过滤请求字符编码,/和/*和/**的区别
      |
      2月前
      |
      Java 应用服务中间件 Maven
      JavaWeb基础5——HTTP,Tomcat&Servlet
      JavaWeb技术栈、HTTP、get和post区别、响应状态码、请求响应格数据式、IDEA使用Tomcat、报错解决、Servlet的体系结构、IDEA使用模板创建Servlet
      JavaWeb基础5——HTTP,Tomcat&Servlet
      |
      5月前
      |
      SQL druid Java
      javaweb案例实训之基于jsp和servlet的用户管理开发[增删改查及登录注销]
      javaweb案例实训之基于jsp和servlet的用户管理开发[增删改查及登录注销]
      34 0
      |
      5月前
      |
      SQL 数据可视化 数据库
      基于jsp+servlet的javaweb实现最基本的用户注册登陆注销功能
      基于jsp+servlet的javaweb实现最基本的用户注册登陆注销功能
      23 0
      |
      6月前
      |
      存储 安全 JavaScript
      JavaWeb之Servlet(下)
      本文主要介绍了JavaWeb开发中关于请求、响应、会话和Servlet3.0注解的相关知识。首先讲解了请求(Request)的常用方法,以及处理请求乱码问题的几种方式。接着讨论了响应(Response)的方法,,以及设置全局初始化参数。然后介绍了会话(Session)的概念,包括其生命周期、如何设置和获取初始化参数,并对比了全局初始化参数和Servlet3.0的`@WebServlet`注解。文中给出了具体的代码示例和测试结果,帮助读者更好地理解和掌握这些概念。
      |
      6月前
      |
      Java 应用服务中间件 程序员
      JavaWeb之Servlet(上)
      本篇博文介绍了JavaWeb中Servlet的基本概念和应用。Servlet是用于交互式浏览和修改数据、生成动态Web内容的Java程序,通常运行在支持Java的应用服务器上。文章讲解了Servlet的工作模式,包括客户端请求、服务器调用Servlet以及响应返回客户端的过程。此外,还提到了Servlet API,特别是doGet和doPost方法用于处理请求和响应。作者通过创建第一个Servlet的步骤,展示了如何实现Servlet接口并配置web.xml文件。最后,文章简述了Servlet的工作原理和生命周期,强调了Servlet的单例特性以及初始化、服务和销毁的过程。
      |
      3月前
      |
      缓存 安全 Java
      Java服务器端技术:Servlet与JSP的集成与扩展
      Java服务器端技术:Servlet与JSP的集成与扩展
      33 3
      |
      3月前
      |
      存储 缓存 前端开发
      Servlet与JSP在Java Web应用中的性能调优策略
      Servlet与JSP在Java Web应用中的性能调优策略
      32 1
      |
      3月前
      |
      存储 Java 关系型数据库
      基于Servlet和JSP的Java Web应用开发指南
      基于Servlet和JSP的Java Web应用开发指南
      45 0
      |
      3月前
      |
      前端开发 安全 Java
      在Java服务器端开发的浩瀚宇宙中,Servlet与JSP犹如两颗璀璨的明星,它们联袂登场,共同编织出动态网站的绚丽篇章。
      在Java服务器端开发的浩瀚宇宙中,Servlet与JSP犹如两颗璀璨的明星,它们联袂登场,共同编织出动态网站的绚丽篇章。
      28 0