Servlet
If you want to learn JavaWeb, a Jsp a Servlet is certainly not around, let’s talk about Servlet first
In the early days without servlets, a technology called CGI (Common Gateway Interface) was more popular, but it had some drawbacks
Such as:
As the number of clients increases, the response time becomes more and more unacceptable
Every time a request comes in, a new process is opened up to handle it, consuming system resources
Use platform-dependent languages (C, C++, Perl)
The emergence of Servlet solves these problems well
Some optimizations of servlets versus CGI
- Threads, not processes, are created for each request
- Use Java cross-platform language, with portability
- Servlets are managed by the JVM and do not need to worry about memory leaks, spills, etc
But don’t servlets have their drawbacks? Of course not
At the time, the biggest disadvantage of servlets was that they required a lot of verbose HTML code in the Servlet class
Doing so makes Java code and HTML code get mixed up in a way that makes people’s heads spin…. So Jsp was born
Jsp is also Servelt by nature, but it does not need to be compiled
A Jsp page is a text file with a.jsp extension
While JSPS are fading out of sight these days, servlets are not, and many of the underlying technologies actually use servlets
Is that why servlets are a must when we talk about JavaWeb
What is the Servlet
Servlets are actually Serverapplets, small service programs or service connectors
Java is a server-side program written in Java. The main function is to browse and modify data interactively and generate dynamic Web content
Like common protocols such as DNS, TCP/IP, and HTTP, servlets exist as a whole set of specifications
It also defines JavaWeb development standards as part of the J2EE standard
Servlets provide Java with a set of standards for handling Web requests, and we just need to follow those standards
In fact, either Struts2’s FilterDispatcher or SpringMVC’s DispatcherServlet
The bottom line is all implemented by implementing servlets or servlet-type extensions (such as GenericServlet), as mentioned above
Quoted from the article, with some modifications
How to use servlets
First, when we say servlets we really mean Servlet interfaces; Classes that implement these interfaces are called Servlet classes
The default implementation of servlets is GenericServlet, which is an abstract class that implements both the Servlet interface and the ServletConfig interface
public abstract class GenericServlet
implements Servlet.ServletConfig.Serializable {... }Copy the code
Instead of learning about servlets and the ServletConfig interface, let’s take a look at what you need to do to write your own Servlet class
The GenericServlet class is an abstract class that can be inherited directly or subclasses HttpServlet (HttpServlet is the base class of servlets implemented based on the Http protocol)
Our general approach is to inherit HttpServlet directly
The figure is in red because we have no imported dependencies. Yes, we need to import the dependencies using Maven before using the HttpServlet class
<dependencies>
<! Import the corresponding dependency, version can be modified according to their own environment -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
</dependencies>
Copy the code
After importing the dependencies and inheriting the HttpServlet abstract class, the relationships between components are as follows
As you can see, our custom class HelloServlet is now a Servlet class, and we can override some of its methods
There are many methods that can be overridden. The most common is doGet(); And the doPost ();
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doGet(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}
Copy the code
Let’s start with doGet(); Write a simple output statement in the
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("Test");
}
Copy the code
After writing this line of code, if we access the mapping of the Servlet program on a web page, the console outputs the string “Test”
Mapping is mentioned here, and yes, at this point our Servlet application is essentially just a special Java class
It is not accessible through a browser without registering it with a Web service; Then it’s pretty clear what to do next
- Set the currently created Maven project to a Web project (don’t do much if it already is)
- Register the Servlet in web.xml in the WEB-INF folder
<! -- Register servlet in web.xml -->
<servlet>
<! Give the servlet a mapping friendly name -->
<servlet-name>helloServlet</servlet-name>
<! -- Specify the location of the servlet -->
<servlet-class>com.molu.servlet.HelloServlet</servlet-class>
</servlet>
<! -- Configure mapping -->
<servlet-mapping>
<! Configure the mapping for the named servlet -->
<servlet-name>helloServlet</servlet-name>
<! -- Mapping path is /test-->
<url-pattern>/test</url-pattern>
</servlet-mapping>
Copy the code
With this configured, we started the server to do a simple access test on the web page
In addition to interacting with the background, we can also use doGet(); Method to write some simple front-end (that is, browser side) interaction code
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("Test");
// Do a simple front-end interaction test
PrintWriter writer = resp.getWriter();
// Print the string forward when accessing the Servlet
writer.print("helloServlet");
}
Copy the code
The Servlet principle
It’s amazing that we didn’t have to do too much complexity to access the custom servlet application in the browser and implement simple interaction on the front and back ends
There’s definitely a lot of black box work behind this loop, so let’s take a quick look at what the servlet does
First of all, what is the role of servlets? In my opinion, servlets are like a bridge between browser and server
As we type request after request into the browser, the server determines whether the content you are requesting is dynamic or static
-
If it is a static resource the server will feed you the static page directly, but if it is dynamic it will call our servlet container for processing
- The server will find the corresponding servlet based on the URL path you requested. If the servlet instance exists in memory, the container will read it and respond directly. Otherwise, you need to create an instance
-
To create a servlet instance, you need to perform initialization, which is to call init(); Method, do some preparatory work or resource preloading
-
After initialization, the servlet instance is ready to respond to requests and calls service() when a request comes in. methods
service();
Method makes some judgments about how the browser requests- Is called if the request is of the get type
doGet();
Method (the default request is GET)- That’s why we put the code in
doGet();
Method instead ofdoPost();
Reasons in the method
- That’s why we put the code in
-
Our request information is encapsulated in an initialized HttpServletRequest object, which is passed in as the first parameter when the HttpServlet instance is created
-
The HttpServlet service (); The HttpServletRequest method reads the HttpServletRequest parameters that encapsulate the request information and does the specific business logic processing (which we wrote in doGet(); Or the doPost (); Code in methods)
-
The servlet instance encapsulates the processed data in HttpServletResponse and responds to the browser, and we get the data we need
-
When the Servlet container is closed, the Servlet instance is destroyed at any time. In the meantime, the Servlet container calls the destroy() method of the Servlet to determine whether the Servlet should be released (or recycled)
ServletMapping extension
After starting the Web project, we can access our corresponding servlet application through the host name: port/project name /servlet mapping path
In this URL, except for the mapping path, most of them will not be changed at will. We can access different servlet programs through different mapping path
It is also possible to access the same servlet application through different mapping paths, depending on which
you wrote when registering.
For example, we could register multiple mapping paths for our helloServlet program
<! Configure multiple mappings for the same servlet application
<servlet-mapping>
<servlet-name>helloServlet</servlet-name>
<url-pattern>/test</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>helloServlet</servlet-name>
<url-pattern>/test1</url-pattern>
</servlet-mapping>
Copy the code
We can access our helloServlet through any of these mapping paths (requiring a server restart)
We can also use the wildcard (*) to achieve a uniform mapping of a class of paths
<servlet-mapping>
<servlet-name>helloServlet</servlet-name>
<url-pattern>/test/*</url-pattern>
</servlet-mapping>
Copy the code
When a mapping path is configured with wildcards, requests for urls that match the prefix will go through the configured servlet program
You can also specify a suffix, but be careful that wildcards are not preceded by “/”
Otherwise, an error will be reported
<url-pattern>*.hello</url-pattern>
Copy the code
Restart the server for testing
If you specify a suffix and you use a wildcard it doesn’t matter how you write it, right
What if, when writing a mapping path, you use wildcards (” /* “) and specify a mapping for a servlet program?
Let’s test it out:
// Write another simple servlet
public class TestServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter().print("TestServlet"); }}Copy the code
Specify the mapping for the servlet class
<! -- Register servlet in web.xml -->
<servlet>
<servlet-name>helloServlet</servlet-name>
<servlet-class>com.molu.servlet.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>helloServlet</servlet-name>
<url-pattern>/ *</url-pattern>
</servlet-mapping>
<! Register the servlet class you just wrote -->
<servlet>
<servlet-name>testServlet</servlet-name>
<servlet-class>com.molu.servlet.TestServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>testServlet</servlet-name>
<url-pattern>/test</url-pattern>
</servlet-mapping>
Copy the code
Now things are getting a little more complicated. The mapping path we configured for the helloServlet is “/*”. Normally, we would call the servlet whenever we request any path. Does it make sense for us to configure the mapping path for another servlet?
The answer is yes. Mapping paths have priorities. If the configured path conflicts with the mapping path configured with a wildcard, the user-defined path has a higher priority than the wildcard path
ServletContext
ServletContext stands for servlet context, which exists in every Web application and is globally unique, and can be shared by all servlet instances
The life cycle of the ServletContext follows the Web container, and it is created when the Web container is started and destroyed when it is closed
Let’s look at a simple application of servletContext
Since all servlet instances can share this context object and it exists as soon as the server is started;
Can we store some data in there that our servlet instance can read and communicate with? The answer is yes
In fact, one of the main uses of the servletContext is as a cache, where we can store data that hardly changes, thus improving the client experience
Let’s take a simple test:
Write a servlet class where our data is stored in a context object when called
public class SetServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
/ / call getServletContext (); The ServletContext method gets the ServletContext object
ServletContext context = this.getServletContext();
// Simulate a piece of data
String username = "Moluu";
// Store this data in a ServletContext as k v; To obtain the data, you only need to write the corresponding key
context.setAttribute("name",username);
// Indicates that the data setting is successful
PrintWriter writer = resp.getWriter().printf("OK"); }}Copy the code
Write a servlet class that can retrieve the data
public class GetServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// Get the ServletContext object
ServletContext context = this.getServletContext();
// Get the data stored in the context Object. Since the default type is Object, we can force it when we fetch it
String name = (String) context.getAttribute("name");
// Feed the data back to the front end
PrintWriter writer = resp.getWriter().printf("username => "+ name); }}Copy the code
Register the two servlet classes with the Web service
<servlet>
<servlet-name>get</servlet-name>
<servlet-class>com.molu.servlet.GetServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>get</servlet-name>
<url-pattern>/get</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>set</servlet-name>
<servlet-class>com.molu.servlet.SetServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>set</servlet-name>
<url-pattern>/set</url-pattern>
</servlet-mapping>
Copy the code
Try using GetServlet in the browser to retrieve data stored in context (if you must first call SetServlet once to store the data in)
Note that garbled characters may appear if the string is stored in Chinese.
This is normal as long as it’s not null it means it’s been fetched, so if you feel you need to verify it try printing it in the console at the back end
The question about this garbled code will be addressed later
So I’m not going to go into too much depth with ServletContext and it’s a little bit simpler, so if you’re interested you can test it out and play with it