[Servlet] 6: An article to understand the mutual calling and data sharing of Servlet objects

This article belongs to the third part of the back-end full set of notes

(Updating) [Getting started with the back end and getting into the soil! 】Java+Servlet+JDBC+SSM+SpringBoot+SpringCloud Basic Introduction_m0_57265007's Blog - An article on the CSDN blog, from getting started with the back end to entering the soil. Contains Java Basic + Advanced, MySQL, JDBC, Servlet, SSM, SpringBoot, SpringCloud, project notes. https://blog.csdn.net/m0_57265007/article/details/127962617?csdn_share_tail=%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22 %3A%22127962617%22%2C%22source%22%3A%22m0_57265007%22%7D

| Request object and response object life cycle

1. After the Http server receives the [Http Request Protocol Package] sent by the browser, it automatically generates a [Request Object] and a [Response Object] for the current [Http Request Protocol Package]

2. When the Http server calls the doGet/doPost method, it is responsible for passing [request object] and [response object] as actual parameters to the method to ensure that doGet/doPost is executed correctly

3. Before the Http server prepares to push the Http response protocol package, it is responsible for destroying the [Request Object] and [Response Object] associated with this request

4. [Request object] and [Response object] life cycle runs through the processing of a request

5. Visually speaking: [Request object] and [Response object] are equivalent to the spokesperson of the user on the server side


| Mutual calls between Servlets

Basic overview of Servlet calls

  • Some requests from the browser often require the coordinated processing of multiple Servlets on the server side.

  • The fundamental purpose of calling between multiple Servlets is to improve the user experience. Rules: No matter how many Servlets are involved in this request, the user only needs to [manually] notify the browser to initiate a request.

  • Calling rules between multiple Servlets: redirection solution, request forwarding solution


Redirect Servlet calls

principle

  • For the first time, the user notifies the browser to access OneServlet through [manual method]. After OneServlet finishes working, write the address of TwoServlet into the location attribute of the response header.

    Write the 302 status code to the status line. After the browser checks the 302 status, it looks for the location in the response header, and then automatically initiates a second request to the server immediately

  • That is: the browser sends at least two requests, but only the first request is sent manually by the user, and subsequent requests are sent automatically by the browser

  • In the redirection solution, the browser is notified to initiate the next request through the address bar, so the request method received by the resource file invoked through the redirection solution must be [GET]

  • Disadvantages: The redirection solution requires multiple round trips between the browser and the server, which consumes a lot of time on the number of round trips and increases the user's waiting time for the service

grammar

response.sendRedirect("请求地址");   //将地址写入到响应包中响应头中location属性
  • The request address can be: the URL of the external website / the alias of the Servlet implementation class object inside the server (that is, dynamic resources) / the internal static resources

  • If it is an internal resource, the composition of the URL is: /site name/alias corresponding to the Servlet object

example

<html>
  <head>
    <title>$Title$</title>
  </head>
  <body>
    <form action="/web4/s1" method="post">
      <input type="submit" value="重定向">
    </form>
  </body>
</html>

 

(The codes of Servlet1 and Servlet2 are exactly the same, but the numbers are different. Only the code of Servlet1 is shown here)

public class Servlet1 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //...
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=utf-8");  //设置content-Type中的字符规则为UTF-8,以保证显示到网页为中文
        PrintWriter out = resp.getWriter();   //获取输出流

        //提示S1的 POST被调用
        System.out.println("Servlet1 POST 被调用");

        //重定向到S2
        System.out.println("重定向到 /web4/s2");
        resp.sendRedirect("/web4/s2");
    }
}

 

public class Servlet2 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=utf-8");  //设置content-Type中的字符规则为UTF-8,以保证显示到网页为中文
        PrintWriter out = resp.getWriter();   //获取输出流

        //提示S2的 GET被调用
        System.out.println("Servlet2 GET被调用");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //...
    }
}

 

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">

    <!--Servlet1实现类 注册-->
    <servlet>
        <servlet-name>servlet1</servlet-name>
        <servlet-class>Servlet1</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>servlet1</servlet-name>
        <url-pattern>/s1</url-pattern>
    </servlet-mapping>

    <!--Servlet2实现类 注册-->
    <servlet>
        <servlet-name>servlet2</servlet-name>
        <servlet-class>Servlet2</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>servlet2</servlet-name>
        <url-pattern>/s2</url-pattern>
    </servlet-mapping>
    
</web-app>

 

Conclusion: The requests initiated automatically by redirection are all of GET type~

 

Request Forwarding Servlet Calls

principle

  • The first time the user manually requests the browser to access the OneServlet. After the work of OneServlet is completed, the current request object is used instead of the browser to send a request to Tomcat to apply for calling TwoServlet.

    After Tomcat receives this request, it automatically enters TwoServlet to complete the remaining tasks

  • In the request forwarding solution, the browser only sends one Http request protocol packet. All Servlets participating in this request share the same request protocol package, so the request method received by these Servlets is consistent with the request method sent by the browser

  • Number of requests: During the request forwarding process, the browser only sends one request (no matter how many Servlets are involved in this request, the user only needs to manually send one request through the browser)

  • Advantages: The call between Servlets occurs on the server computer, saving the number of round trips between the server and the browser and increasing the processing speed

grammar

RequestDispatcher  report = request.getRequestDispatcher("/资源文件名");   //通过当前请求对象生成资源文件申请报告对象
report.forward(当前请求对象,当前响应对象);   //将报告对象发送给Tomcat

  • Request forwarding is internal Tomcat scheduling, and tomcat only has scheduling power for resources inside the current website, so resource file names can only be static/dynamic resources inside the server

  • Pay attention to details when writing resource file names:

    • Since it is called internally by Tomcat, they are all in the same deployed website, so the resource file name [do not need to write the deployment alias of the website]! [Directly write the static/resource name that needs to be accessed]. Don't leave out the slash before the name: / 

    • If you write the website name, it will cause two website names in the URL, 404 error

example

  • The configuration file of web.xml is consistent with "Redirecting Servlet Call" in this section, so it will not be shown here


<html>
  <head>
    <title>$Title$</title>
  </head>
  <body>
    <form action="/web4/s1" method="post">
      <input type="submit" value="重定向">
    </form>

    <form action="/web4/s2" method="get">
      <input type="submit" value="请求转发">
    </form>
  </body>
</html>

 

public class Servlet1 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=utf-8");  //设置content-Type中的字符规则为UTF-8,以保证显示到网页为中文
        PrintWriter out = resp.getWriter();   //获取输出流

        //提示S1的 GET被调用
        System.out.println("Servlet1 GET 被调用");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //...
    }
}

 

public class Servlet2 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=utf-8");  //设置content-Type中的字符规则为UTF-8,以保证显示到网页为中文
        PrintWriter out = resp.getWriter();   //获取输出流

        //提示S2的 GET被调用
        System.out.println("Servlet2 GET被调用");

        //请求转发到S1
        System.out.println("请求转发到 /web4/s1");
        //重定向中的URL无需写部署在Tomcat的网站名(因为本来就是内部调用了),只需要写资源名即可
        RequestDispatcher report = req.getRequestDispatcher("/s1");   //通过当前请求对象生成资源文件申请报告对象
        //RequestDispatcher report = req.getRequestDispatcher("/web4/s1");   //错误写法!不需要写网站部署名web4
        report.forward(req,resp);   //将报告对象发送给Tomcat
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //...
    }
}

 

in conclusion:

The request method of other Servlets invoked by request forwarding is GET (because they share a request and response object)

The URL to request forwarding only needs to write the /resource name (because it is in the same website, Tomcat writes the website deployment alias in the URL by default)


| Data sharing between Servlets

Basic overview of Servlet data sharing

  • What is data sharing: After the work of OneServlet is completed, the generated data will be handed over to TwoServlet for use

  • Four data sharing schemes:

    • ServletContext interface [global scope object]

    • Cookie class

    • HttpSession interface [session scope object]

    • HttpServletRequest interface [request scope object]


ServletContext interface data sharing

basic introduction

  • ServletContext is an interface from the Servlet specification, and its implementation class is provided by the Http server

  • The object of the ServletContext implementation class is called [global scope object]

  • If multiple Servlets belong to the same website, you can use this method to share Servlet data

Principle Description

  • Each website has a global scope object, which is shared by all Servlets under the website

    For example: OneServlet can store a data in the global scope object, and other Servlets in the current website can get this data from the global scope object at this time for use

Global Scope Object Lifecycle

  • During Tomcat startup, a global scope object is automatically created in memory for the current website

  • During the running of Tomcat, a website has only one global scope object

  • During the running of Tomcat, the global scope object is always alive (the life cycle of the global scope object runs through the entire running period of the website)

  • When Tomcat is about to shut down, it is responsible for destroying the global scope objects in the current website

grammar

  • K is String, V is Object

//通过【请求对象】向Tomcat索要当前网站中【全局作用域对象】
ServletContext application = request.getServletContext();

//将数据添加到全局作用域对象作为【共享数据】
application.setAttribute("key1",数据);

//从全局作用域对象获取之前添加的共享数据【注意一下数据类型默认是Object,需要转换】
Object 数据 =  application.getAttribute("key1");

example

<html>
  <head>
    <title>$Title$</title>
  </head>
  <body>
    <form action="/web5/S1" method="get">
      <input type="text" name="v1">
      <input type="submit" value="发送数据v1到S1">
    </form>
  </body>
</html>

 

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    
    <servlet>
        <servlet-name>S1</servlet-name>
        <servlet-class>S1</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>S1</servlet-name>
        <url-pattern>/S1</url-pattern>
    </servlet-mapping>
    
    <servlet>
        <servlet-name>S2</servlet-name>
        <servlet-class>S2</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>S2</servlet-name>
        <url-pattern>/S2</url-pattern>
    </servlet-mapping>

</web-app>

 

public class S1 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String v1 = (String)req.getParameter("v1");
        System.out.println("收到了来自index的参数  v1 = " + v1);


        /*【把数据存入ServletContext】*/
        ServletContext application = req.getServletContext();   //通过【请求对象】向Tomcat索要当前网站中【全局作用域对象】
        application.setAttribute("key1",v1);   //将数据添加到全局作用域对象作为【共享数据】
        System.out.println("S1的数据成功存入全局作用域对象");

        /*【请求转发跳转到S2】*/
        System.out.println("正在从S1跳转到S2");
        System.out.println("=========================================================");
        RequestDispatcher report = req.getRequestDispatcher("/S2");
        report.forward(req,resp);
    }
}

public class S2 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("跳转到了S2");

        //从全局作用域对象拿到S1存入的值
        ServletContext application = req.getServletContext();
        String v2Fromv1 = (String)application.getAttribute("key1");
        System.out.println("S2拿到了从S1存入的数据: v2Fromv1 = " + v2Fromv1);
    }
}

 

Cookie class data sharing

basic introduction

  • It comes from a tool class in the Servlet specification, which exists in the servlet-api.jar provided by Tomcat

  • If two Servlets come from the same website and provide services for the same browser/user , it is recommended to use the Cookie object for data sharing

Principle Description

  • The user sends a request to the MyWeb website through the browser to apply for OneServlet for the first time, and OneServlet creates a cookie during operation to store data related to the current user

    After the work of OneServlet is completed, [Cookie is written to the response header] and returned to the current browser. After the browser receives the response packet, it stores the cookie in the browser's cache

    After a period of time, when the user sends a request to [myWeb website] to apply for TwoServlet again through [the same browser],

    The browser will [unconditionally write the cookie previously pushed by the myWeb website into the request header] and send it over

    At this time, when TwoServlet is running, it can obtain the shared data provided by OneServlet by reading the information in the cookie in the request header.

life cycle

  • By default, the Cookie object is stored in the browser's cache. So as long as the browser is closed, the Cookie object is destroyed

  • In the case of manual settings, the browser can be required to store the received Cookie on the hard disk of the client computer, and at the same time, it is necessary to specify the survival time of the Cookie on the hard disk.

    Within the survival time range, closing the browser, closing the client computer, and closing the server will not cause the cookie to be destroyed.

    When the time to live is reached, the cookie is automatically deleted from the hard disk

cookie.setMaxAge(60);  //cookie在客户端硬盘存活时间(单位:秒)  在此期间用户即使关闭浏览器,也不会导致Cookie销毁

grammar

  • Save data: Create a cookie object and save shared data (current user data) through the cookie construction method

    • A cookie is equivalent to a map. Only one key-value pair can be stored in a cookie

    • Both K and V can only be String, and Key cannot be Chinese, but V can be Chinese

Cookie card = new Cookie("key1","V");
resp.addCookie(card);   //将cookie写入到响应头,交给浏览器

Get Cookie data in other Servlets: call the request object to get the Cookie returned by the browser from the request header
 

//1.调用请求对象从请求头得到浏览器返回的Cookie
Cookie  cookieArray[] = request.getCookies();

//2.循环遍历数据得到每一个cookie的key 与 value
for(Cookie card:cookieArray){
    String key = card.getName();  //读取key  "key1"
    String value = card.getValue(); //读取value "abc"
}

example

The configuration of index and web.xml is the same as above, so it will not be shown here.

public class S1 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        Cookie card = new Cookie("key1","S1的值1");
        Cookie card2 = new Cookie("key2","S1的值2");
        Cookie card3 = new Cookie("key3","S1的值3");
        resp.addCookie(card);   //将cookie写入到响应头,交给浏览器
        resp.addCookie(card2);
        resp.addCookie(card3);

        resp.sendRedirect("/web5/S2");   //将地址写入到响应包中响应头中location属性
    }
}

 

public class S2 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("跳转到了S2");

        //1.调用请求对象从请求头得到浏览器返回的Cookie
        Cookie cookieArray[] = req.getCookies();

        //2.循环遍历数据得到每一个cookie的key 与 value
        int i = 1;
        for(Cookie card:cookieArray){
            String key = card.getName();  //读取key  "key1"
            String value = card.getValue(); //读取value "abc"
            System.out.println("数据" + i++ + ":" + key + " = " + value);
        }
    }
}

 

 

HttpSession interface data sharing

basic introduction

  • From the next interface of the Servlet specification. It exists in servlet-api.jar in Tomcat, and its implementation class is provided by the Http server

  • Developers are accustomed to refer to the HttpSession interface modified object as [session scope object]

  • If two Servlets come from the same website and provide services for the same browser/user , it is recommended to use the HttpSession object for data sharing

Principle Description

  • The difference between HttpSession and Cookie

    • [Storage location is different] Cookie: stored in the client computer (browser memory/hard disk); HttpSession: stored in the server computer memory

    • [Different data types that can be stored] Cookie: K can only be an English String, V can only be a String; HttpSession: the String of K can contain Chinese, and V can store any type of shared data Object

    • [Data Quantity] A Cookie object can only store one shared data; HttpSession uses a map collection to store shared data, so any number of shared data can be stored

  • HttpSession is stored in the memory of the server computer. How does it know which user the different HttpSession objects correspond to?

    • HttpSession associates users with HttpSession through cookies

life cycle

  • Cookies used when users associate with HttpSession can only be stored in the browser cache

  • When the browser is closed, it means that the relationship between the user and his HttpSession is cut off

  • Since Tomcat cannot detect when the browser is closed, it will not cause Tomcat to destroy the HttpSession associated with the browser when the browser is closed

    In order to solve this problem, Tomcat sets [idle time] for each HttpSession object , and the idle time is 30 minutes by default.

    If the current HttpSession object is idle for 30 minutes, Tomcat thinks that the user has given up his HttpSession, and Tomcat will destroy the HttpSession

  • Manually modify the HttpSession idle time:

    Set in web.xml <session-config><session-timeout>5</session-timeout></session-config>(unit: minute)

grammar

adding data

//1.调用请求对象向Tomcat索要当前用户在服务端的私人储物柜
HttpSession  session = request.getSession();  //如果当前用户还没有session对象,则服务端创建一个新的
HttpSession  session = request.getSession(false);  //如果当前用户还没有session对象,则服务端不会创建新的,会返回一个null

//2.将数据添加到用户私人储物柜
session.setAttribute("key1",共享数据)

 retrieve data

//1.调用请求对象向Tomcat索要当前用户在服务端的私人储物柜
HttpSession   session = request.getSession();
HttpSession  session = request.getSession(false);  //如果当前用户还没有session对象,则服务端不会创建新的,会返回一个null

//2.从会话作用域对象得到OneServlet提供的共享数据
Object 共享数据 = session.getAttribute("key1");

example

public class S1 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        //1.调用请求对象向Tomcat索要当前用户在服务端的私人储物柜
        HttpSession session = req.getSession();  //如果当前用户还没有session对象,则服务端创建一个新的

        //2.将数据添加到用户私人储物柜
        session.setAttribute("键1","值V1");

        //转到Servlet1中
        resp.sendRedirect("/web5/S2");   //将地址写入到响应包中响应头中location属性
    }
}

 

public class S2 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        //1.调用请求对象向Tomcat索要当前用户在服务端的私人储物柜
        HttpSession session = req.getSession();

        //2.从会话作用域对象得到OneServlet提供的共享数据
        Object o1 = session.getAttribute("键1");
        System.out.println(o1);
    }
}

 

 

HttpServletRequest interface data sharing

basic introduction

  • In the same website, if two Servlets are called through [request forwarding] , they share the same request protocol package with each other.

    And a request protocol package corresponds to only one request object, so servlets share the same request object,

    At this point, you can use this request object to share data between the two Servlets.

  • When the request object implements the data sharing function between Servlets, the developer refers to the request object as [request scope object]

grammar

//将数据添加到【请求作用域对象】中attribute属性
req.setAttribute("key1",数据); //数据类型可以任意类型Object

//从当前请求对象得到OneServlet写入到共享数据【当前Servlet必须和之前的Servlet共用一个请求对象。即请求转发】
Object 数据 = req.getAttribute("key1");

 example

public class S1 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        req.setAttribute("键1","值V"); //数据类型可以任意类型Object

        //请求转发
        RequestDispatcher  report = req.getRequestDispatcher("/S2");   //通过当前请求对象生成资源文件申请报告对象
        report.forward(req,resp);   //将报告对象发送给Tomcat

    }
}

 

public class S2 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("跳转到了S2");

        Object o1 = req.getAttribute("键1");
        System.out.println(o1);

    }
}

 

 

Guess you like

Origin blog.csdn.net/m0_57265007/article/details/128005937