This is the fourth day of my participation in the August More text Challenge. For details, see:August is more challenging

Servlet

Server Applet (Servlet) : Java Servlet. Is a server-side program written in Java. Its main function is to interactively browse and modify data to generate dynamic Web content. A Servlet in the narrow sense refers to an interface implemented by the Java language, and a Servlet in the broad sense refers to any class that implements the Servlet interface, which is generally understood as the latter.

The Servlet runs in a Java-enabled application server. Implementionally, servlets can respond to any type of request, but for the most part servlets are only used to extend Web servers based on the HTTP protocol.

The first to support the Servlet standard was JavaSoft’s Java Web Server. Since then, several other Java-based Web servers have started to support standard servlets.

The above text, which is referenced from Wikipedia, will be fully understood in a subsequent introduction to servlets

An introduction to

Here’s an introduction to servlets to see how the web-oriented building blocks in JavaEE work

Servlet application construction

As for Servlet application construction, Maven method is adopted. IDEA cancles direct construction of JavaEE application in the new version

Step 1: Create an empty Mavne project and introduce Servlet dependencies

<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>4.0.1</version>
</dependency>
Copy the code

Step 2: Create a new webapp directory under SRC /main, at the same level as the Java directory. The resources directory can be deleted

src
    main
        java
        webapp
Copy the code

Step 3: Create the following content in the WebApp directory, write XML information, and complete the construction according to the bottom right corner of IDEA

webapp
    WEB-INF
        web.xml
    index.jsp
Copy the code
<! -- web.xml -->
<! DOCTYPEweb-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
  <display-name>Archetype Created Web Application</display-name>
</web-app>
Copy the code
<! -- index.jsp -->
<html>
<body>
<h2>Hello World!</h2>
</body>
</html>
Copy the code

Step 4: Deploy Tomcat and configure path information in the upper right corner of IDEA

Step 5: Create a New Java class, the details are as follows, the core is to inherit HttpServlet, override service (), annotate @webservlet ()

@WebServlet("/test")
public class Servlet extends HttpServlet {
    @Override
    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
        System.out.println("..."); }}Copy the code

At this point, start Tomcat, enter the configured URL path, and see the information printed on the console

Servlet implementation Principle

A Servlet is a program that is located on the server side. Ordinary Java classes can inherit HttpServlet and be transformed into a Servlet program

As you can see, the Servlet program does not have a main method; it passively receives requests and returns responses

In simple terms, servlets are deployed on WEB application servers, such as the mainstream Tomcat, which manages servlets

Now, by opening the HttpServlet inheritance diagram with IDEA, you can see that

  1. The HttpServlet class extends from the GenericServlet class
  2. The GenericServlet class implements the Servlet interface

In other words, a Servlet is really an interface, a specification, in Java

Why inherit HttpServlet because HttpServlet is based on the Serlvet interface specification and provides a large number of available methods

The simple understanding is that ArrayList, as a concrete implementation class of the Collection interface, provides a large number of usage methods

As for the HTTP protocol for the communication between the server side and the WEB side, it can be understood as the data structure of the container and can be learned separately. It is unnecessary to study HTTP for the learning of servlets

Servlet life Cycle

A Servlet program has a life cycle, and the life cycle of servlets is essentially managed by the WEB container

void init(ServletConfig var1) throws ServletException;
void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;
void destroy(a);
Copy the code

These are some of the abstract methods defined in the Servlet interface and represent the life cycle of a Servlet program

There are three phases to the Servlet life cycle

Initial phase: When the request reaches the Servle program, the Servlet program instantiates the object and executes it only once

Service phase: This phase is a continuous request and response that can be executed multiple times

Destroy phase: The Servlet program destroys, only once

See the following example, combined with the Log information of the Tomcat console

@WebServlet("/test")
public class Servlet extends HttpServlet {
    @Override
    public void init(ServletConfig config) throws ServletException {
        System.out.println("Servlet initialization");
    }
    @Override
    public void service(ServletRequest req, ServletResponse res) {
        System.out.println("Servlet service");
    }
    @Override
    public void destroy(a) {
        System.out.println("Servlet destroyed"); }}Copy the code

At this point, run Tomcat and access the path, you can see the initial and service information is printed, and then close Tomcat, you can see the destruction information of the Servlet program before closing

Request and Response

For Servlet program, its main responsibility is to receive request data, return response data, the corresponding methods are HttpServletRequest, HttpServletResponse

HttpServlet is the Servlet implementation class, based on HttpServlet explain Servler program

It request

HttpServletRequest is responsible for receiving the data passed from the WEB to the server

  • getRequestURL(): Gets the complete URL when the client sends the request
  • getRequestURI(): Gets the relative URL in the project
  • getQueryString(): Gets the parameters of the request
  • getParameter(): Gets the specified parameter
  • getMethod(): Method of obtaining a request
  • getprotocol(): Obtains the HTTP version number

For more specific references, please refer to the JavaEE API manual

Request the code

If you pass a parameter in Chinese, you may have garbled characters because of Tomcat’s default encoding

For request methods, there are two kinds of GET request and POST request. It is worth noting that the higher version of Tomcat does not contain garbled characters for GET request

Of course, if you use the getQueryString () method, it will still be garbled. In this case, the request parameter is the getParameter () method

Now, the focus is to solve the POST request parameters garbled, the method is as follows

// Decodes characters according to utF-8 encoding
req.setCharacterEncoding("utf-8");
Copy the code

One point here is that if you pass data in a JSP page, you must do the following declaration tag, otherwise you will pass the Chinese GDK code, which is not garbled

<%@ page contentType="text/html; charset=UTF-8" language="java"% >Copy the code

Forward requests

When a request is received, the data can be forwarded to another Servlet program for processing, as shown in the following code examples

@WebServlet("/test")
public class Servlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        String userName = req.getParameter("userName");
        req.getRequestDispatcher("test01").forward(req, resp); }}Copy the code
@WebServlet("/test01")
public class Servlet01 extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        System.out.println("Successfully received forwarded request:" + req.getParameter("userName")); }}Copy the code

At this point, the first Servlet program no longer prints the parameters, and the request is forwarded to the second Servlert program

It is important to note that request forwarding is the behavior of the server and the address bar of the page does not change

Request a domain object

In the Request forwarding above, it can be seen that the second Servlet does not get the parameters, but can print them because the Servlet programs in a Request forwarding share a Request scope

If you look at the code carefully, when you do the request forwarding, in addition to specifying the forwarding address, the request and Response objects are also passed in

In addition to data obtained from the page request, you can manually add data to the Request scope

@WebServlet("/test")
public class Servlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        req.setAttribute("hxd"."hxd,gys!!!");
        req.getRequestDispatcher("test01").forward(req, resp); }}Copy the code
@WebServlet("/test01")
public class Servlet01 extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        System.out.println(req.getAttribute("hxd")); }}Copy the code

Two API methods are used for storing and fetching data from the request scope

  • req.setAttribute(String str, Object obj): Stores data in the form of keys
  • req.getAttribute(): Reads data according to the stored key

HttpServletResponse response

Now, introduce the Response object, which is used to return data in response to requests on the WEB side

There are two ways to respond to data: in character form and in byte form

@WebServlet("/test")
public class Servlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // Respond to data as a stream of characters
        PrintWriter writer = resp.getWriter();
        writer.write("123");
        // Respond to data as a byte stream
        ServletOutputStream stream = resp.getOutputStream();
        stream.write("456".getBytes()); }}Copy the code

Note that the two response modes cannot be used at the same time. The response object can only use one of the response modes

The second response will be ignored and may cause exception problems

Of course, one way can do multiple data responses, as shown below

PrintWriter writer = resp.getWriter();
writer.write("123");
writer.write("456");
Copy the code

In response to the code

Similarly, when using Chinese to do the response data, there will also be garbled code problem, the solution is as follows

@WebServlet("/test")
public class Servlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        // Specify the server code
        resp.setCharacterEncoding("UTF-8");
        // Specify the client decoding
        resp.setHeader("Content-Type"."text/html; charset=UTF-8");
        PrintWriter writer = resp.getWriter();
        writer.write("Good brother"); }}Copy the code

Note that the encoding and decoding modes of the server and client must be specified simultaneously to ensure consistency

redirect

Redirection, unlike request forwarding, redirects a page to another page

@WebServlet("/test")
public class Servlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        resp.setCharacterEncoding("UTF-8");
        resp.setHeader("Content-Type"."text/html; charset=UTF-8");
        resp.sendRedirect("index.jsp"); }}Copy the code
<%@ page contentType="text/html; charset=UTF-8" language="java"< HTML > <head> <title> title </title> </head> <body> <h1> </h1> </body> </html>Copy the code

At this point, any page that sends a request to the Servlet program will be redirected to another page

In simple terms, redirection is client behavior and the address bar changes

Request forwarding and redirection

Request forwarding and redirection are described in the request and response section above. Here we make a uniform comparison

Request forwarding occurs on the server and does not affect the address bar. In addition, request forwarding can only be performed on the server

Redirection is a behavior that occurs on the client. The server acts as an intermediary and affects the address bar. In addition, the server can redirect to any location on the Internet

Session management

In the previous request response, the server does not record anything to the client

Session management, that is, the server to the client access to do state processing, through two technologies Cookie, Session

Cookie

Access the cookies

Cookies are created by the server and stored in the session information of the client, as shown in the following example

@WebServlet("/test")
public class Servlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) {
        // Create a Cookie object
        Cookie cookie = new Cookie("userName"."Good brother");
        // Return the Cookie object to the clientresp.addCookie(cookie); }}Copy the code

At this point, open the browser console and you can see the responding Cookie data in storage

Similarly, the server can read the Cookie data stored by the client

@WebServlet("/test")
public class Servlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) {
        // Java only supports obtaining cookies as arrays
        Cookie[] cookies = req.getCookies();
        for(Cookie cookie : cookies) { System.out.println(cookie.getName()); System.out.println(cookie.getValue()); }}}Copy the code

Cookie expires

For Cookie sessions, there is a default duration, not specified by the stored browser

For cookies, the server can specify a valid time. There are three cases. The method to set the Cookie time is setMaxAge ().

// The unit is second, that is, the validity period of the Cookie is 10 seconds
cookie.setMaxAge(10);
// Negative integer, the Cookie survives until the browser closes
cookie.setMaxAge(-1);
// If this parameter is set to zero, the Cookie will be deleted
cookie.setMaxAge(0);
Copy the code

It is important to note that the Cookie is set to zero and is valid only for cookies with a specific lifetime specified

In addition, if the browser closes within the validity period of the Cookie, the Cookie does not expire directly, but only waits for the expiration of the time

Cookies that survive until the browser closes cannot be invalidated by the server

The Cookie path

For the storage of Cookie data, you can specify a path for it, which can be roughly divided into four categories

The method for setting the Cookie path is setPath ()

Class 1: Any Servlet program on the server can obtain the Cookie object setPath(“/”)

Type 2: The Servlet program that created the Cookie’s project path is available, this is the default setPath (“/ created path “)

Class 3: The Servlet program that specifies the project path can obtain the Cookie object setPath (“/ other path specified “)

Cookie details

There are a few things to note about the use of cookies

First, the Cookie’s key cannot and should not be in Chinese, which may lead to an error

Second, the same name Cookie storage, will override the previous Cookie by default

Third, cookies are limited in size and are generally only used to store important data

Fourth, Cookie exists in the browser, there is the possibility of being disabled by the browser

Session

The Session using

Sessions are special cookies that are used in much the same way

@WebServlet("/test")
public class Servlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) {
        // Obtain the Session object and create one if it does not exist
        HttpSession session = req.getSession();
        // Get the unique identifier of the Session object
        System.out.println(session.getId());
        // Obtain the creation time of the Session object
        System.out.println(session.getCreationTime());
        // Obtain the last access time of the Session object
        System.out.println(session.getLastAccessedTime());
        // Check whether the Session is a new object, that is, whether the server recorded the SessionSystem.out.println(session.isNew()); }}Copy the code

The unique identifier of a Session, the JSESSIONID, is stored in the browser and identifies a unique Session

Note that a meaningless change or deletion of the JSESSIONID will cause the server to think that there is no Session object and create a Session

In addition, the overwritten JSESSIONID is still recorded in the server. If the original JSESSIONID is written, the server will not consider it a new Session object

As a special Cookie, a Session also has a validity period. By default, the Session is closed by the browser, that is, the validity period of the Cookie is set to -1

The Session domain object

Like request, Session has specific domain objects

The Session domain object is valid only for one Session and data is not shared across multiple sessions, similar to the request domain

@WebServlet("/test")
public class Servlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) {
        HttpSession session = req.getSession();
        session.setAttribute("userName"."He");
        System.out.println(session.getId());
        System.out.println(session.getAttribute("userName")); }}Copy the code

You can remove the specified data from the Session domain object by removeAttribute ()

The Session is destroyed

There are several ways to destroy a Session object

The first option depends on the default Session expiration time on the Tomcat application server

Open the conf directory in Tomcat, where the following configuration exists for web.xml

<! If no operation is performed on the Session object within 30 minutes, the Session object will be closed. Otherwise, refresh the Session time -->
<session-config>
    <session-timeout>30</session-timeout>
</session-config>
Copy the code

The second is to specify the default duration of the Session object

Call the method getMaxInactiveInterval (), in seconds

Third: manual direct destruction, more use

Call invalidate () to destroy the Session object directly

Fourth: the browser is closed

The current browser is closed, and the Session Session is destroyed

ServletContext object

ServletContext concept

In each WEB Application started by a Tomcat Application server, there is only one ServletContext object, also known as the Application object, whose scope is the entire running time of the WEB Application

When an application is created, the ServletContext object is created; When an application is destroyed, the ServletContext object is destroyed

For ServletConetxt objects, it does two things

  1. Achieve global data sharing
  2. Stores information about the current application
@WebServlet("/test")
public class Servlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) {
        // Obtain information about the current application server
        System.out.println(getServletConfig());
        // Get information about the current WEB application
        System.out.println(getServletContext());
        // Get the fully qualified name of the current Servlet programSystem.out.println(getServletName()); }}Copy the code

Since the ServletContext object is created at server startup, the global scope object can be directly called to the corresponding method of the object

How to obtain a ServletContext object

There are four ways to get a ServletContext object. The example above describes one way to get a ServletContext object directly

@WebServlet("/test")
public class Servlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) {
        // Direct access
        ServletContext servletContext = getServletContext();
        // Request Object
        ServletContext servletContext1 = req.getServletContext();
        // Obtain the session object
        ServletContext servletContext2 = req.getSession().getServletContext();
        // Obtain the ServletConfig objectServletContext servletContext3 = getServletConfig().getServletContext(); }}Copy the code

ServletContext domain object

A ServletContext can also be used as a domain object, in much the same way as a request or session

@WebServlet("/test")
public class Servlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) {
        ServletContext servletContext = req.getServletContext();
        servletContext.setAttribute("userName"."He");
        System.out.println(servletContext.getAttribute("userName"));
        servletContext.removeAttribute("userName"); }}Copy the code

As you can see, the use method is consistent

Servlet three domain objects

There are now three domain objects in the Servlet: the Request domain object, the Session domain object, and the ServletContext domain object

Among the three domain objects, request has the smallest scope and is only valid in a request forwarding. ServletContext has the largest scope and will not fail until the server is shut down

Of course, because in real project development, the server is open for a long time, need to pay extra attention to the use of domain objects, do not let meaningless data occupy memory for a long time

For this reason, use the smaller scope of the Request domain object, session domain object, and avoid the ServletContext domain object

summary

As a JavaEE specification, Servlet has fallen behind The Times in terms of technology, and now most of the other technologies encapsulated based on the Servlet specification are used, such as Spring Servlet. Moreover, the original file upload and download of servlets is relatively simple, and most of them can be replaced by the toolkit provided by Apache