Java servlet and web containers. Building Java Applications with Servlets
Java Servlet is a server-side program written in the programming language of the same name, which receives signals from the client and sends responses back to it. It is the key element that forms the typical Java EE, in addition to JSP, EJB, XML and other related technologies. The application can be packaged into a WAR (Web AR chive) file for deployment on a web server. A server that can run a Java servlet is called a container. A program that runs on such a server can create dynamic web pages.
Java Servlet: Basics
The most popular and widely used containers are Tomcat and JBoss. Technically, a servlet is a normal Java class that has an extension for the Common Client-Server Protocol or HTTP. In practice, it is used to process requests through the HttpServlet GET and POST overrides, respectively. The Java Servlet container provides Http.ServletRequest and Http.ServletResponse, which are request-response objects. And is usually used in combination with JSP to generate dynamic content.
Typical model scenario:
Java Servlet Filters are Java plug-in components that are used to intercept and process requests before they are sent to servlets and respond after its code has completed, and before the container sends the response to the client.
Common tasks performed with filters:
Filters are enabled and configured in a deployment descriptor file (web.xml). Servlets and filters don't know about each other, so you can add or remove a filter simply by editing the web.xml. It is possible to have multiple filters for one resource or create a chain of filters for web.xml or run Java Servlet filters implementing the javax.servlet.Filter interface.
Parallel requests to the server are processed by threads, which provides important qualities of the web - multithreading and parallelism.
Main functions:
The need to use dynamic web pages
There are many reasons why a business would want to create dynamic web pages on the fly, such as when the data on the website changes frequently. News and weather sites typically rely on CGI to keep content fresh without requiring constant developer attention. E-commerce web pages that list current prices and inventory levels use CGI to fetch this content on demand, pulling it from the company's internal infrastructure.
Many users have experience using Java technology to create CGI-based web services, but Java Servlets are more efficient, more powerful, easier to use, and cheaper than traditional CGI alternatives.
Advantages of Java Servlets:
One of the best things about Java is its versatile nature. Of course, creating traditional desktop and even mobile applications is great. But what if you want to go off the beaten path and enter the territory of web application development in Java? The good news for you is that the language comes with a full-fledged Servlet API, which allows you to create reliable web applications without much hassle.
Building Java Applications with Servlets
So, we have already created the application configuration files. However, in its current state it literally does nothing. We want clients to be able to register using an HTML form, so the next thing we need to do is to create JSP files that will display the above form and client details once the registration is completed successfully. This is what we will do now.
We are working on the appearance
The appearance of the application will be defined by two JSP files - in the MVC context these are called views. The first one will be responsible for displaying the registration form and possible errors caused after checking the entered data. The second will be a regular welcome page that will show the details entered by the customer once the registration process has been successfully completed.
Here is the first JSP file:
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
Registration
$(violation).
The file contains simple HTML with a couple of additions. This is the beauty of JSP combined with JSTL and JEL. Notice how easy it is to check for validation errors using standard tags like<с:if>And
The registration form's action attribute points to the following URL: $(pageContext.request.contextPath)/processcustomer . This means that every time a customer tries to register, data will be sent to processcustomer regardless of the URL where the form is accessed. This is achieved through the functionality of objects accessible from the JSP file, such as request .
We'll soon see how the servlet binds to the processcustomer URL and how it interacts with the input. For now, let's look at the JSP file that is responsible for the welcome page:
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
Thank you for registering!
Your entered data:
Name:$(firstname)
Surname:$(lastname)
Email:$(email)
Now that we understand the page rendering, the next step is to create a servlet responsible for collecting client data from POST requests and validating the data in a simple way.
Writing a controller
Writing a servlet that can retrieve data from a registration form couldn't be easier. All we need to do is write a subclass of the HttpServlet class and implement its doGet() or doPost() methods (or both, if necessary). In this case, the servlet will interact with data coming from POST requests.
Here's what it looks like:
@WebServlet(name = "CustomerController", urlPatterns = "/processcustomer") public class CustomerController extends HttpServlet ( @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException ( RequestCustomer customer = RequestCustomer.fromRequestParameters(request); customer .setAsRequestAttributes(request); List violations = customer.validate(); if (!violations.isEmpty()) ( request.setAttribute("violations", violations); ) String url = determineUrl(violations); request.getRequestDispatcher(url ).forward(request, response); ) private String determineUrl(List violations) ( if (!violations.isEmpty()) ( return "/"; ) else ( return "/WEB-INF/views/customerinfo.jsp"; ) ) private static class RequestCustomer ( private final String firstName; private final String lastName; private final String email; private RequestCustomer(String firstName, String lastName, String email) ( this.firstName = firstName; this.lastName = lastName; this.email = email; ) public static RequestCustomer fromRequestParameters(HttpServletRequest request) ( return new RequestCustomer(request.getParameter("firstname"), request.getParameter("lastname"), request.getParameter("email")); ) public void setAsRequestAttributes(HttpServletRequest request) ( request.setAttribute("firstname", firstName); request.setAttribute("lastname", lastName); request.setAttribute("email", email); ) public List validate() ( List violations = new ArrayList<>(); if (!StringValidator.validate(firstName)) ( violations.add("First name is a required field"); ) if (!StringValidator.validate(lastName)) ( violations.add("Last name is a required field"); ) if ( !EmailValidator.validate(email)) ( violations.add("Email must be well formed"); ) return violations; ) ) )
The first thing to note here is the use of the @WebServlet(name ="CustomerController", urlPatterns = "/processcustomer") annotation. It tells the servlet container to use the CustomerController class to handle HTTP requests to /processcustomer . The same effect can be achieved by adding servlet mapping directives to web.xml like this, but since we are using Servlet Specification 3.1 we don't need to do this.
Here we have named the servlet CustomerController because it is considered good practice to use the servlet class name as the value of the name attribute of the @WebServlet annotation. Otherwise, some containers will not be able to match, resulting in a 404 error.
The CustomerController class itself does a few simple things. First, it collects form input using an implementation of the HttpServletRequest interface, which contains values corresponding to the firstname, lastname, and email fields of the form. It then sets these values as query attributes so they can be redisplayed either on the form or on the results page. Finally, validators check the correctness of the entered data.
Validators are simple classes that check certain properties, such as whether a string is empty or whether email looks like email. You can look at their implementation on the author’s GitLab.
The validation result influences the further course of events: if the data is not valid, the client is redirected through the RequestDispatcher object to the registration page, where the corresponding errors are displayed. If everything is in order, the welcome page is displayed.
So, we've created an entire web application in Java that allows you to register clients using an HTML form, a basic servlet, and a few JSP files. It's time to launch it.
Launch the application
To launch the application you need to do the following steps:
IntelliJ IDEA). When you deploy the project and run it, the default browser should launch with a registration window.
Conclusion
So, you have acquired all the skills needed to create your own web application in Java without having to resort to complex frameworks. All you need is a Servlet API, technology like JSP for rendering, and native Java tools. Great, right?
It's worth noting that the implementation of the CustomerController class highlights the strengths and weaknesses of servlets: on the one hand, it briefly shows how easy it is to process request parameters and send responses to the client in different formats. But this functionality comes at a price: both implementations of the HttpServletResponse and HttpServletResponse interfaces are regular service locators. This is not to say that this is a bad thing, since locators simply contain data. However, you need to remember that these implementations will always be bound to the servlet.
What are servlets? Servlets, in fact, are modules for processing HTTP and FTP requests, used to build portals (web gates).
The basis of these portals is the WEB server itself - a program that holds the server socket, receives and transmits data. Most often, to speed up work, the server is written not in Java, but in some other programming language (for example, C++).
A basic servlet works in conjunction with the server. It is to him that the server sends data and from him it receives the response sent to the client. In fact, the basic servlet is the "brains" of the server. The main function of this servlet is to read the client's request, decrypt it and, according to the decryption, pass the work to the servlet responsible for that type of information requested. Often, to achieve speed, the role of the basic servlet is played by the server itself. This is exactly the way that, say, Jacarta Tomcat works.
The figure shows a diagram of the transmission of calls (request) and responses (response) between the server and servlets. This diagram depicts the operation of an HTTP server, which has several JSP pages and two resources “/sample1” and “/sample2”, for the processing of which two servlets are responsible - “Sample1 Servlet” and “Sample2 Servlet”, respectively.
Let's take a step-by-step look at what is shown in the figure:
- client connects to server
- the server passes the request to the basic servlet ("Basic Servlet")
- the underlying servlet extracts the resource URI from the request
- if the URI points to "/sample1" then the request entirely(without changes) is passed to the servlet "Sample1 Servlet", which subsequently processes this request
- if the URI points to "/sample2", the server passes the request to the "Sample2 Servlet"
- in all other cases the request is passed to the "JSP Servlet" module
- The servlet to which control was transferred processes the data, creates a response, after which the response is sent back to the base servlet.
- the basic servlet, without processing the received data, immediately sends it back to the server
- the server issues data to the client
In this way, the task of processing a request is divided into logical parts, each of which is responsible for its own module, its own “software brick”. In fact, there may be many more steps in processing a request. For example, different modules may be responsible for the “GET” and “POST” methods.
Servlet Interface
What all these modules have in common is that they are interconnected end-to-end using the javax.servlet.Servlet interface
Let's look at this interface. It lists only 5 methods:
Public void init(ServletConfig config) throws ServletException This method is called to inform the servlet that it is enabled as a module to service client requests. The config parameter shares the javax.servlet.ServletConfig interface, which carries information about the server environment, servlet name, initial parameters and other goodies. The javax.servlet.ServletConfig interface will be discussed a little further. It is expected that after calling this function, the servlet will carefully store this config in a variable and will return it using another method: public ServletConfig getServletConfig() Having received system information using "getServletConfig()", the server may want to know the author's name, date creation, other information about the servlet, which is achieved by calling public String getServletInfo()
To process a request and get the result of its processing, use the function
Public void service(ServletRequest request, ServletResponse response) throws ServletException, java.io.IOException In this function, two tools are passed to the code that will process the data: one to receive data from the server, the other to send the result of the servlet. Accordingly, these are the request and response parameters, separating the javax.servlet.ServletRequest and javax.servlet.ServletResponse interfaces. All work with data is carried out through these interfaces, so let’s talk about them in more detail later.
After the server no longer needs this module, the method is called
Public void destroy() which completes all operations on the servlet object.
ServletConfig interface
4 methods, whose names speak for themselves, form the essence of the javax.servlet.ServletConfig interface:
Public String getServletName() public ServletContext getServletContext() public String getInitParameter(String name) public java.util.Enumeration getInitParameterNames()
I think the purpose of all functions is clear, except
Public ServletContext getServletContext() This method returns a link to a very useful tool for working with the server:
ServletContext interface
ServletContext is an interface that defines access to the following useful functions:
Public Object getAttribute(String name) public java.util.Enumeration getAttributeNames() public void setAttribute(String name, Object object) public void removeAttribute(String name) Four methods for working with attributes. The role of attributes is performed by any object of any class. The purpose of these functions is to transfer different objects between unrelated servlets. public String getInitParameter(String name) public java.util.Enumeration getInitParameterNames() Access the parameters with which the server was started. The host name, port and other useful information may also be located here. public int getMajorVersion() public int getMinorVersion() Returns the Servlet API versions. public String getMimeType(String file) Returns the MIME type associated with the file whose path is specified in the file variable. Remember how you had to define MIME in the SimpleWEBServer program and appreciate the convenience! public java.util.Set getResourcePaths() public java.net.URL getResource(String path) throws java.net.MalformedURLException public InputStream getResourceAsStream(String path) Returns paths to resources available to the server and the resources themselves as URLs and as streams data. public RequestDispatcher getRequestDispatcher(path) public RequestDispatcher getNamedDispatcher(name) RequestDispatcher is a tool for forwarding a request to another resource. These functions are needed to get the tool object for the specified resources. That is, let's say, in order to redirect a request to the servlet "sample1" from the servlet body, you can do this: getServletConfig().getServletContext().getNamedDispatcher("sample1").forward(request, response);
The RequestDispatcher class itself includes only two methods:
Public void forward(ServletRequest request, ServletResponse response) throws ServletException, java.io.IOException public void include(ServletRequest request, ServletResponse response) throws ServletException, java.io.IOException Moreover, the first one is for redirecting the request, and the second one is for including the result of the work the called servlet as a result of the current one. For example, servlet 1 prints the word "test 1", then calls include for servlet two, after which it prints the word "test 2". Servlet 2 simply prints the word " and ". The output of Servlet 1 will be the string "test 1 and test 2". public void log(String msg) Write something to the server log. public void log(String message, Throwable throwable) Define an exception and a phrase that will be written to the log when this exception is received. public String getRealPath(String path) Translates a path like "/index.html" to "http://host/contextPath/index.html" public String getServerInfo() Returns the server name. public ServletContext getContext(String uripath) This method allows you to exchange ServletContext between different resources on the same server. public String getServletContextName() Returns the name of the servlet that owns this ServletContect interface object.
ServletRequest interface
The ServletRequest interface is a tool for receiving HTTP request parameters. This interface has some methods identical in name and purpose to the ServletContext:
Public Object getAttribute(String name) public java.util.Enumeration getAttributeNames() public void setAttribute(String name, Object o) public void removeAttribute(java.lang.String name) public String getServerName() public RequestDispatcher getRequestDispatcher(String path)
The remaining methods allow you to conveniently work with the HTTP request header:
Public String getCharacterEncoding() public void setCharacterEncoding(String env) throws java.io.UnsupportedEncodingException Dealing with character encoding in HTTP header fields. The functions specify a method for decoding CGI queries from the %NN form into regular characters. For example, which standard - KOI8-R, windows-1251 or UTF-8 should be used to decrypt Cyrillic characters. public int getContentLength() public String getContentType() Reads the "Content-Length", "Content-Type" fields from an HTTP request. public jString getParameter(String name) public java.util.Enumeration getParameterNames() public String getParameterValues(String name) public java.util.Map getParameterMap() Functions for getting a field from an HTTP header and its value. public ServletInputStream getInputStream() throws java.io.IOException public java.io.BufferedReader getReader() throws java.io.IOException Get the incoming data stream or its "reader". Reader is used to read text information - it will automatically decrypt strings in accordance with the specified charset. Attention! There is a significant bug in version J2EE 1.3: when decoding the %25 character (the % character in Post and Get requests), Reader generates an error (the bug was noticed on Tomcat 4 and Resign servers). It is possible that a similar bug exists with other symbols. public String getProtocol() Get the HTTP protocol version of the request (for example, "HTTP/1.1"). public String getScheme() Returns the name of the request scheme. For example "http", "https", or "ftp". public int getServerPort() public String getRemoteAddr() public String getRemoteHost() public boolean isSecure() Server port, client IP address, client hostname and whether the connection is secure (via HTTPS) public java.util.Locale getLocale() public java.util.Enumeration getLocales() The client's preferred document language (result of processing the "Accept-Language" field)
ServletResponse Interface
The ServletResponse interface is a tool for sending data to the client. All methods in this tool serve exactly this purpose:
Public java.lang.String getCharacterEncoding() public void setLocale(java.util.Locale loc) public java.util.Locale getLocale() The first method returns the MIME encoding type (for example, UTF8) in which the information will be displayed. The second two methods also work with charset. They indicate the language used in the document (for example, Russian). public ServletOutputStream getOutputStream() throws java.io.IOException Returns the output stream for the servlet. This stream is used, for example, to output binary files. Text data can be output using java.io.Writer: public java.io.PrintWriter getWriter() throws java.io.IOException This method automatically converts strings to the charset specified in the getCharacterEncoding() and getLocale() methods. public void setContentLength(int len) This method sets the value of the HTTP header field "Content-Length" public void setContentType(String type) Method for sending the MIME content type of the document. HTTP header field "Content-Type". public void setBufferSize(int size) public int getBufferSize() public void flushBuffer() throws java.io.IOException public void resetBuffer() The fact is that the output stream is buffered. This means that the next piece of data will be issued to the client only after the buffer is full. These methods allow, respectively, to set the size of the sending buffer, get its size, initialize sending the contents of the buffer to the client without waiting for it to be filled, and also clear this buffer of data. public boolean isCommitted() This method can be used to get a flag indicating whether sending data to the client has already started. The flag will be positive if the HTTP response header has already been sent. public void reset() If the HTTP header has not yet been sent, then this method "resets" the HTTP header to its default values.
Predefined Servlet Types
The Java Servlet API, in addition to the interfaces itself, also contains several servlet classes that can serve as the basis for your programs.
The base class for all these classes is the abstract class javax.servlet.GenericServlet:
Public abstract class GenericServlet implements Servlet, ServletConfig, java.io.Serializable
As you can see from the definition of this class, it has all the methods of the Servlet and ServletConfig interfaces. The only method left unimplemented was
Public abstract void service(ServletRequest req, ServletResponse res) throws ServletException, java.io.IOException which was declared abstract.
Based on this class, another abstract class was created - javax.servlet.http.HttpServlet:
Public abstract class HttpServlet extends GenericServlet implements java.io.Serializable
This class was created in accordance with the concept of “even more convenience for the programmer” and has many useful methods:
Protected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, java.io.IOException protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, java.io.IOException protected void doHead(HttpServletRequest req, HttpServletResponse resp) throws ServletException, java .io.IOException protected void doOptions(HttpServletRequest req, HttpServletResponse resp) throws ServletException, java.io.IOException protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, java.io.IOException protected void doPut(HttpServletRequest req, HttpServletRes ponse resp) throws ServletException, java.io.IOException protected void doTrace(HttpServletRequest req, HttpServletResponse resp) throws ServletException, java.io.IOException protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, java.io.IOException protected void service(ServletRequest req , ServletResponse res) throws ServletException, java.io.IOException Various options service(ServletRequest req, ServletResponse res) for different HTTP methods from DELETE and GET to PUT and TRACE. And in order to conveniently receive data via the CGI interface without decrypting the header, the HttpServletRequest and HttpServletResponse classes were created, included with HttpServlet in the javax.servlet package.http protected long getLastModified(HttpServletRequest req) This method returns the time of the last modification of the HttpServletRequest object. It takes the time value from the "Date" field of the HTTP request header. If the field is not found, it returns -1.
Accordingly, we will analyze the HttpServletRequest and HttpServletResponse interfaces. They are descendants of ServletRequest and ServletResponse, respectively.
HttpServletRequest, in addition to the methods inherited from ServletRequest, also has the following useful methods:
Cookie getCookies() Returns a set of cookies sent by the client to the server.
The Cookie class, included in the same javax.servlet.http package, contains all possible information about a cookie. The most important methods of this class are
Int getMaxAge() String getName() String getValue() which returns, respectively, how much time this cookie has left to live, the name of the cookie and its value. Also Cookie(String name, String value) void setValue(String newValue) void setMaxAge(int expiry) to create a cookie, set its value and maximum age. long getDateHeader(String name) Returns the date from the HTTP header, if there is one. int getIntHeader(java.lang.String name) Returns the numeric value of the field named name from the HTTP request header String getMethod() Returns the HTTP request method. String getQueryString() String getRequestURI() StringBuffer getRequestURL() Returns the string contained in the document URL after the "?" character, the document URI, and the full URL. HttpSession getSession() HttpSession getSession(boolean create) boolean isRequestedSessionIdFromCookie() boolean isRequestedSessionIdFromURL() boolean isRequestedSessionIdValid() Functions. allowing you to work with such an important data transfer mechanism as sessions.
Sessions are needed to carry data from page to page for the user. For example, a user goes to page (1), where some data is sent to him for page (2), and that page saves some other things for page (3).
In principle, on page (1) you can send data to the user, then receive it on page (2), add something, send it to the user... Similarly, you will have to constantly send the entire set of data from the client to the server and back, many times. In addition to the fact that such forwarding is not always convenient, it also eats up traffic.
You can also do the same thing differently - use the session mechanism. This mechanism works as follows: the server saves the data sent by the user in a separate file - the session file. All data modification work will be done with the contents of this file. The client is given a “session key” (aka Session key, also known as Sesseion ID) - a unique pointer to a file containing data specifically for this user. Now, in order to obtain all the data relating to this client, the server only needs to know the session key. The advantage of this method is the convenience and speed of its use.
That's all the main methods of the HttpServletRequest interface. For a complete list of methods, see the Java Servlet API documentation.
Now about the HttpServletRequest interface. The main difference between the classes that share this interface is that the data is not displayed immediately. First, all the data is assembled into an HTTP response. The response is sent only after HttpServlet.service() completes.
And so, about the methods:
Void addHeader(String name, String value) void addIntHeader(String name, int value) void addDateHeader(String name, long date) Methods add parameters to the HTTP header. The last method sets the "Date" parameter. void addCookie(Cookie cookie) Method adds a cookie to the header boolean containsHeader(String name) Lets you know if the header already contains the specified parameter. String encodeURL(String url) String encodeRedirectURL(String url) The first method encodes characters using %NN replacement. The second method does the same and calls void sendRedirect(String location) void setStatus(int sc) void sendError(int sc) void sendError(int sc, String msg) The first one sets the return code, the second two send an error message. The interface specifies the following possible errors for the sc parameter, corresponding to the HTTP protocol return codes: SC_CONTINUE - Status code (100) SC_SWITCHING_PROTOCOLS - Status code (101) SC_OK - Status code (200) SC_CREATED - Status code (201) SC_ACCEPTED - Status code (202) ) SC_NON_AUTHORITATIVE_INFORMATION - Status code (203) SC_NO_CONTENT - Status code (204) SC_RESET_CONTENT - Status code (205) SC_PARTIAL_CONTENT - Status code (206) SC_MULTIPLE_CHOICES - Status code (300) SC_MOVED_PERMANENTLY - Status code (301) SC_MOVED_TE MPORARILY - Status code (302) SC_SEE_OTHER - Status code (303) SC_NOT_MODIFIED - Status code (304) SC_USE_PROXY - Status code (305) SC_BAD_REQUEST - Status code (400) SC_UNAUTHORIZED - Status code (401) SC_PAYMENT_REQUIRED - Status code (402) SC_FORBIDDEN - Status code (403) SC_NOT _FOUND - Status code (404) SC_METHOD_NOT_ALLOWED - Status code (405) SC_NOT_ACCEPTABLE - Status code (406) SC_PROXY_AUTHENTICATION_REQUIRED - Status code (407) SC_REQUEST_TIMEOUT - Status code (408) SC_CONFLICT - Status code (409) SC_GONE - Status code (410) SC_LENGTH _REQUIRED - Status code (411) SC_PRECONDITION_FAILED - Status code (412) SC_REQUEST_ENTITY_TOO_LARGE - Status code (413) SC_REQUEST_URI_TOO_LONG - Status code (414) SC_UNSUPPORTED_MEDIA_TYPE - Status code (415) SC_REQUESTED_RANGE_NOT_SATISFIABLE - Status code (416) ) SC_EXPECTATION_FAILED - Status code (417) SC_INTERNAL_SERVER_ERROR - Status code (500) SC_NOT_IMPLEMENTED - Status code (501) SC_BAD_GATEWAY - Status code (502) SC_SERVICE_UNAVAILABLE - Status code (503) SC_GATEWAY_TIMEOUT - Status code (504) SC_HTTP_VERSION_NOT_SUPPORTED - Status code (505)
That's all there is to say about HttpServletResponse
Using servlets in WEB applications
Let's now talk about using servlets in WEB applications. To do this, I will give two useful examples that may be useful in practice.
The first example shows methods for working with HttpServlet and outputting the contents of an HTML page in a compressed form. In theory, the HTML page in the browser response is displayed in plain text, but to reduce the amount of data sent, you can use GZIP compression. Modern browsers (at least browsers of the 4th generation and higher) support this method of sending text information and will display the page as if it had not been compressed.
import java. io.* ; import javax. servlet.* ; import javax. servlet. http.* ; import java. util. zip.* ; // the servlet is a descendant of HttpServlet public class ZipServlet extends HttpServlet ( // function for processing the GET method public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException ( // establish that the page is an HTML document response. setContentType("text/html" ); // take the "Accept-Encoding" parameter from the HTTP header String encodings = request. getHeader("Accept-Encoding" ); // take the "encoding" parameter - the previously specified document encoding String encodeFlag = request. getParameter("encoding" ); // Where will we output PrintWriter out; // if the "Accept-Encoding" field is present in the request if (encodings != null) ( // and if this field contains the value "gzip" and the encoding has not yet been set, if ((encodings. indexOf("gzip" ) != - 1 ) &&! encodeFlag. equals("none" )) ( // then where we output will be one and compress the text using GZIP out = new PrintWriter(new GZIPOutputStream(response. getOutputStream()) , false); // and set a flag for the browser that the document will be compressed response. setHeader("Content-Encoding" , "gzip" ); ) else out = response. getWriter(); ) else // otherwise we will output without compression out = response. getWriter(); out. println("This is a test!!!" ); // write the body of the document out. close(); // and close the output. //That's it, after this function completes its work, the document will be sent } }The second example shows how a servlet can be used to display a page continuously. This type of page display can be used, for example, in chats: to read new messages, you will not need to refresh the page every time, new messages will simply be downloaded over time. It should be taken into account that some proxy servers do not support this type of data transfer, but - alas - nothing can be done about it.
import java. io.* ; import javax. servlet.* ; // the program implements the Servlet interface class DoloadServlet implements Servlet ( ServletConfig config; // ServletConfig object public DoloadServlet() () // doing nothing // save config during initialization public void init(ServletConfig config) throws ServletException ( this. config = config;) // returns the saved config public ServletConfig getServletConfig() ( return config;) // information about the servlet public String getServletInfo() ( return "DoloadServlet" ;) public void destroy() () // doing nothing // Processing request public void service(ServletRequest request, ServletResponse response) throws ServletException, java. io. IOException( // we won’t parse the request, just right away // create an HTTP header: String head = "HTTP/1.0 200 OK\n" + + "Server: DoloadServlet\n" + "Content-Type: text/html; charset=UTF-8\n"+ "Connection: Keep-Alive\n" + "Content-Encoding: multipart/mixed\n"+ "Transfer-Encoding: chunked" + "Pragma: no-cache\n\n" ; // now add the initial data // for this example - 20 tags "" with line break for (int i = 0 ; i< 20 ; i++ ) head = head + "
\n" ; // take the output stream ServletOutputStream os = response. getOutputStream(); // write the header and initial data there os. print(head); // send everything recorded in the buffer to the client response. flushBuffer(); // start adding new lines: // these lines will look like this: line number, then "
\n" // each new line will appear once every 3 seconds int i = 0 ; while (true) ( // counter increment i++ ; // write the line os. print("" + i+ "
\n" ); // flushing the buffer response. flushBuffer(); // freeze the stream for 3 seconds try ( sleep(3000 );) catch (Exception e)() ) ) )
It remains to be said that the servlet mechanism is very flexible and allows you to do things that might require writing a separate WEB server (as, for example, in the case of a resupply servlet). The disadvantage of servlets is the low speed of the first launch (the servlet is simply compiled by a JIT machine), high memory consumption and the disadvantage of all Java programs is the low speed of working with strings. The latter circumstance becomes noticeable when working with servlets that accept text data in POST requests. A POST request to HttpServlet with a size of 50 kb when parsed using HttpServletRequest.getReader() can paralyze the server for a couple of minutes. The same applies to other java programs.
Let me give two small examples:
// given a string String text // example 1 // working with a string using the "+" operation for String String test1 = "" ; for (int i = 0 ; i< text. length(); i++ ) test1 += text. charAt(i); // example 2 // working with a string using a buffer char buf = new char [ text. length()]; for (int i = 0 ; i< text. length(); i++ ) buf[ i] = text. charAt(i); String sample2 = new String(buf);If you take small strings - up to 2-3 kb, then the differences in the work of the examples are insignificant, but if you take a text string of at least 10 kb in size, then in the first case the program will work with the string much slower. This is a feature of java and is a problem in implementing the functions of the String class. So if you want to write a fast servlet, avoid working with long strings using the String class, use, for example, the StringBuffer class. This warning applies primarily to receiving large texts from the network and to processing local files (for example, in the case of a text database for a guest book with a large number of messages).
Another problem concerns the multitasking of the WEB system. Don't forget that your servlet can be requested by multiple users at the same time. Often there are problems with data synchronization, information exchange between different computing threads of the same servlet, and the most common problem is the problem of synchronous access to files and other named system resources. For example, one program has opened a file for reading, while another is trying to write something there. As a result, the second program either receives an exception or waits until the file is free for writing. In this regard, I would like to draw your attention: do not leave unclosed threads behind you and close threads as soon as they are no longer needed. The stream, of course, will close automatically later, but this will only happen when the scavenger gets to it, and meanwhile the second program will still not have write access to the file.
In addition to multitasking, I would like to note that using the “Object getAttribute(String name)” and “void setAttribute(String name, Object object)” methods of the ServletContext interface, you can exchange data between servlets, including synchronizing ones.
Servlet is a java program that runs on the server side of a web application. Just as applets dynamically extend the functionality of a Web browser, servlets dynamically extend the functionality of a Web server.
Job servlet"and can be described as follows: when a request arrives from a client, the Web server, using a special configuration file, can determine which servlet needs to be executed. After this, the Web server launches the JVM, which in turn executes the servlet. The Servlet processes the request and transfers the contents to the Web - to the server (possibly in the form of an HTML page).The Web server sends a response to the client (an HTML page generated by the servlet).
A WEB server is essentially a kind of container that loads servlet"s, executes them, and, having received the result from them, sends it to the client.
Servlet in Web Application Architecture
Due to its power and flexibility, servlet"s can play a significant role in the system architecture. They can perform application tasks intended for the middleware, act as a proxy for the client, and even enhance the functionality of the middleware by adding support for new protocols and other features. The middleware functions as an application server in a so-called three-tier client-server system and sits between a lightweight client, such as a Web browser, and the data source.
Servlet as a proxy server
To support applets, servlets can act as their proxies. This may be important because Java security allows applets to connect only to the server from which they were downloaded. If the applet needs to connect to a database server located on another machine, servlet can create this connection for the applet.
Temporary and permanent servlet"s
Servlets can be started and stopped for each client request. They can also be launched when the Web server starts and exist until it stops. Temporary servlet"s are loaded on demand and offer a good way to save server resources for rarely used functions. Persistent servlets are loaded when the Web server starts and last until it is stopped. Servlets are installed as persistent extensions to the server if the cost of running them is very high ( e.g. establishing a database connection) if they offer persistent server-side functionality (such as the RMI service), or in cases where they need to respond to client requests as quickly as possible. There is no specific code to assign servlet"and permanent or temporary; this is a function of setting up the Web server.
Servlet life cycle, javax.servlet.Servlet
Servlets run on the Web server platform as part of the same process as the Web server itself. The Web server is responsible for initializing, invoking, and destroying each servlet instance. The web server interacts with the servlet through a simple interface: javax.servlet.Servlet.
The javax.servlet.Servlet interface includes three main methods:
- init()
- service()
- destroy()
and two helper methods:
- getServletConfig()
- getServletInfo()
Similarities between interfaces servlet"and the Java applet are obvious. That's exactly how it was designed! Java servlets are to Web servers what applets are to Web browsers. The applet runs in the Web browser, performing actions on its request through a special interface. The servlet does the same thing when working on a Web server.
Servlet initialization, init() method
When the servlet is first loaded, the init() method is called. This enables the servlet to do any setup work, such as opening files or establishing connections to their servers. If the servlet is installed permanently on the server, it is loaded when the server starts. Otherwise, the server activates the servlet when it receives the first request from a client to perform the service provided by that servlet.
It is guaranteed that the method init() will end before any other call to the servlet - such as a method call service(). note that init() will be called only once; it will not be called until the servlet is unloaded and then loaded by the server again.
Method init() takes one argument - a reference to an object ServletConfig, which contains the arguments to initialize the servlet. This object has a method getServletContext() returning an object ServletContext, which contains information about the servlet's environment.
Servlet core, service() method
Method service() is the heart of the servlet. Each request from the client results in one method call service(). This method reads the request and generates a response message using its two arguments ServletRequest and ServletResponse:
So there are two ways to pass information from the client to the servlet. The first is through passing values in request parameters. Parameter values can be inserted into the URL. The second way to pass information from a client to a servlet is through an InputStream (or Reader).
How the method works service() is essentially simple - it creates a response for every client request passed to it from the server. However, you must remember that there may be multiple parallel requests being processed at the same time. If the method service() requires any external resources, such as files, databases, then it is necessary to ensure that access to resources is thread-safe.
Unloading a servlet, destroy() method
Method destroy() Called to free all resources (such as open files and database connections) before unloading the servlet. This method can be empty if no finishing operations need to be performed. Before calling the method destroy() the server waits either for all maintenance operations to complete or for a certain amount of time to expire. This means that the method destroy() can be called during the execution of some long-running method service().
It is important to formalize the method destroy() in such a way as to avoid closing necessary resources until all calls service() will not complete.
Servlet configuration, getServletConfig() method
Method getServletConfig() returns a reference to an object that implements the interface ServletConfig. This object provides access to information about the servlet configuration, i.e. access to servlet initialization parameters and servlet context object ServletContext, which gives access to the servlet and its environment.
Servlet information, getServletInfo() method
Method getServletInfo() defined by the programmer creating the servlet to return a string containing information about the servlet, such as the author and version of the servlet.
ServletRequest interface
ServletRequest provides client information about the HTTP request parameters to the servlet, i.e. provides data including parameter name and values, attributes, and input stream. This information is passed to the method service().
Next servlet example shows how to get information from a parameter request method service():
Buffered Reader reader; String param1; String param2; public void service(ServletRequest request, ServletResponse response) ( reader = request.getReader(); param1 = request.getParameter("First"); param2 = request.getParameter("Second"); )
Additional information about the request is available to the servlet through methods, the main ones of which are shown in the following table:
getAttribute() | Returns the value of the specified attribute of this request. |
getContentLength() | Request size, if known. |
getContentType() | Returns the MIME type of the request body. |
getInputStream() | Returns an InputStream for reading binary data from the request body. |
GetParameterNames() | Returns an array of strings with the names of all parameters. |
getParameterValues() | Returns an array of values for the specified parameter. |
getProtocol() | Returns the protocol and version for the request as a string of the form |
getReader() | Returns a BufferedReader to retrieve text from the request body. |
getRealPath() | Returns the real path for the specified virtual path. |
getRemoteAddr() | IP address of the client that sent this request. |
getRemoteHost() | The host name of the client machine that sent this request. |
getScheme() | Returns the scheme used in the URL of this request (for example, https, http, ftp, etc.). |
getServerName() | The host name of the server that accepted this request. |
getServerPort() | Returns the port number used to receive this request. |
ServletResponse Interface
Interface ServletResponse is a tool for sending data to the client. All methods of this tool are used specifically to solve this problem:
Public java.lang.String getCharacterEncoding() public void setLocale(java.util.Locale loc) public java.util.Locale getLocale()
The first method returns the MIME encoding type (for example, UTF8) in which the information will be displayed. The second two methods also work with charset. They indicate the language used in the document (for example, Russian).
Public ServletOutputStream getOutputStream() throws java.io.IOException
The getOutputStream method returns the output stream for the servlet. This stream is used, for example, to output binary files. Text data can be output using java.io.Writer:
Public java.io.PrintWriter getWriter() throws java.io.IOException
The getWriter() method automatically converts strings to the charset specified in the getCharacterEncoding() and getLocale() methods.
Public void setContentLength(int len)
The setContentLength method sets the value of the HTTP header field "Content-Length"
Public void setContentType(String type)
The setContentType method is used to send the MIME content type of the document. HTTP header field "Content-Type".
The output data stream is buffered. This means that a piece of data will be issued to the client only after the buffer is full.
Public void setBufferSize(int size) public int getBufferSize() public void flushBuffer() throws java.io.IOException public void resetBuffer()
The above 4 methods allow, respectively, to set the size of the sending buffer, get its size, initialize sending the contents of the buffer to the client without waiting for it to be filled, and also clear this buffer of data.
Public boolean isCommitted()
Using the isCommitted method, you can get a flag indicating whether sending data to the client has already started. The flag will be positive if the HTTP response header has already been sent.
Public void reset()
If the HTTP header has not yet been sent, then the reset method "resets" the HTTP header to its default values.
JFreeChart charts in servlets
The JFreeChart graphics library can be used in servlets to create charts and display them on website pages as images. Details of the description and examples of using JFreeChart in servlets are presented.
Servlet with graphics library Chart.js
JNI in servlet
In some cases, it may be necessary to use JNI in a WEB application. An example of using JNI in servlets is presented.
JMS messages in a servlet
Servlet can be used to communicate JMS messages between applications. An example of using a servlet to send and read JMS messages in a JBoss container is presented.
Servlets are Java programs that run on the server side of a Web application. Just as applets dynamically extend the functionality of a Web browser, servlets dynamically extend the functionality of a Web server. Although servlets can serve any request, they are typically used to extend web servers. For such applications, Java Servlet technology defines HTTP-specific servlet classes. The javax.servlet and javax.servlet.http packages provide interfaces and classes for creating servlets.
- What is the structure of a web project?
- What is a servlet container? Servlet life cycle.
A servlet container is a program that manages the life cycle of servlets.
Servlet life cycle: it is managed by the servlet container, the first time the servlet is accessed, it is loaded into memory and the init() method is called. Throughout the application's operation, calls to the service() method occur to process client requests. When the application terminates, the destroy() method is called and the servlet is unloaded from memory.
- What are the tasks, functionality of a servlet container?
A servlet container can act as a full standalone web server, serve as a page provider for another web server such as Apache, or be integrated into a Java EE application server. Provides data exchange between the servlet and clients, undertakes such functions as creating a software environment for a functioning servlet, identifying and authorizing clients, organizing a session for each of them.
- What is the difference between sendRedirect() and forward()?
To call a JSP using a relative path, the forward() method is used; to access a JSP using an absolute path, the sendRedirect() method is used. The difference between these methods is that with the forward() method an already existing request request object is passed, and when the sendRedirect() method is called, a new request is generated. In the latter case, information should be transmitted with other objects. In addition, the forward() method works faster.
- What do you know about servlet filters?
Implementing the Filter interface allows you to create an object that intercepts the request and can transform the header and content of the client request. Filters do not create a request or response, but only modify them. The filter performs pre-processing of the request before it reaches the servlet, followed (if necessary) by processing the response coming from the servlet. The filter can interact with different types of resources, in particular, both servlets and JSP pages. Servlet filters can:
- intercept servlet initiation before the servlet is initiated.
- determine the content of the request before the servlet is initiated.
- modify the request headers and data into which the incoming request is packaged.
- modify the response headers and data into which the received response is packaged.
- intercept servlet initiation after the servlet is accessed.
A servlet filter can be configured to work on a single servlet or a group of servlets. The basis for creating filters is the javax.servlet.Filter interface, which implements three methods:
- void init(FilterConfig config) throws ServletException;
- void destroy();
- void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException;
The init() method is called before the filter starts running and sets up the filter's configuration object. The doFilter method does the actual work of the filter. Thus, the server calls init() once to run the filter, and then calls doFilter() as many times as requests are made directly to the filter. After the filter finishes its work, the destroy() method is called.
- Why do we need listeners in servlets?
Context and session listeners are classes that can keep track of when a context or session was initialized, or keep track of when they should be destroyed, and when attributes were added to or removed from a context or session. Servlet 2.4 extends the request listener model by allowing you to track how a request is created and destroyed, and how attributes are added to and removed from the servlet. Servlet 2.4 added the following classes:
- ServletRequestListener
- ServletRequestEvent
- ServletRequestAttributeListener
- ServletRequestAttributeEvent
- How to handle exceptions thrown by another servlet in an application?
Since the browser only understands HTML, when the application throws an exception, the servlet container will handle the exception and create an HTML response. This is similar to what happens with error codes like 404, 403, etc. The Servlet API provides support for native servlets to handle exceptions and errors, which we can specify in the deployment descriptor. The main task of such servlets is to handle an error or exception and send a clear HTML response to the user. For example, you can provide a link to the main page, as well as a description of some details about the error.
- What is a deployment descriptor?
The deployment descriptor is the configuration file of the artifact that will be deployed to the servlet container. In the Java Platform, Enterprise Edition specification, a deployment descriptor describes how a component, module, or application (such as a web or enterprise application) should be deployed.
This configuration file specifies deployment options for a module or application with specific settings, security options, and describes specific configuration requirements. The syntax for deployment descriptor files uses XML.
- How to implement a servlet launch with application launch?
The servlet container usually loads the servlet at the first client request, but sometimes it is necessary to load the servlet right at the start of the application (for example, if the servlet is large and will take a long time to load). To do this, you must use the load-on-startup element in the descriptor (or the loadOnStartup annotation), which will indicate whether the servlet should be loaded at startup.
The value must be int. If the value is negative, then the servlet will be loaded when the client requests it, and if it is 0 and further, then it will be loaded at the start of the application. The lower the number, the earlier the servlet will be in the download queue.
- What is a ServletConfig object?
The javax.servlet.ServletConfig interface is used to pass configuration information to the servlet. Each servlet has its own ServletConfig object, which the servlet container is responsible for instantiating. To set configuration parameters, use the init parameters in web.xml (or WebInitParam annotations). The getServletConfig() method is used to obtain the ServletConfig object of a given servlet.
- What is a ServletContext object?
The javax.servlet.ServletContext interface defines a set of methods that a servlet uses to communicate with its servlet container, for example, getting the MIME type of a file, dispatching requests, or writing to a log file. The ServletContext object is unique and is available to all servlets in a web application. We can use the ServletContext object when we need to provide access to one or more servlets to the initialized parameters of a web application. The element is used for this
Servlet containers can also provide context objects that are unique to a group of servlets. Each of the groups will be associated with its own set of host path URLs.
ServletContext has been extended in the Servlet 3 specification and provides the ability to programmatically add listeners and filters to an application. This interface also has many useful methods like getMimeType(), getResourceAsStream(), etc.
- What is the difference between ServletContext and ServletConfig?
Below are some differences:
- ServletConfig is a unique object for each servlet, while ServletContext is unique for the entire application.
- ServletConfig is used to provide initialization parameters to a servlet, and ServletContext is used to provide application initialization parameters to all servlets.
- We do not have the ability to set attributes in the ServletConfig object, while we can set attributes in the ServletContext object that will be available to other servlets.
- ServletResponse interface.
The ServletResponse interface is a tool for sending data to the client. All methods in this tool serve exactly this purpose.
- ServletRequest interface.
The ServletRequest interface is a tool for receiving HTTP request parameters. This interface has some methods identical in name and purpose to the ServletContext.
- What is Request Dispatcher?
The RequestDispatcher interface is used to pass a request to another resource (this could be HTML, JSP, or another servlet in the same application). We can use this to add content from another resource to the response. This interface is used for internal communication between servlets in the same context. The interface implements two methods:
- void forward(ServletRequest var1, ServletResponse var2) - forwards a request from a servlet to another resource (servlet, JSP or HTML file) on the server.
- void include(ServletRequest var1, ServletResponse var2) - includes the content of the resource (servlet, JSP or HTML page) in the response.
The interface can be accessed using the ServletContext getRequestDispatcher(String s) method. The path must start with / , which will be interpreted relative to the current context root path.
- How can you create a deadlock in a servlet?
A deadlock can be obtained by implementing a looped method call, for example by calling the doPost() method in the doGet() method and calling doGet() in the doPost() method.
- How to get the address of a servlet on the server?
To get the actual servlet path on the server, you can use this construct: getServletContext().getRealPath(request.getServletPath()).
- How to get server information from a servlet?
Server information can be obtained using the ServletContext object using the getServerInfo() method. Those. getServletContext().getServerInfo().
- How to get the client's IP address on the server?
Use request.getRemoteAddr() to get the client's ip in the servlet.
- What do you know about servlet wrapper classes?
The Servlet HTTP API provides two wrapper classes - HttpServletRequestWrapper and HttpServletResponseWrapper. They help developers implement their own implementations of the servlet's request and response types. We can extend these classes and override only the necessary methods to implement our own response and request object types. These classes are not used in standard servlet programming.