Once upon a time, there was a program ape. He said to his grandson earnestly, "son, if you write servlet s in the future, you'd better not rewrite the service method."
The grandson was greatly puzzled. The program ape said, "listen to Grandpa, it must be right. That's what grandpa's grandpa said..."
——Why shouldn't you override the service method?
If you have thought about this problem but have no solution for the time being, this article may give you some inspiration.
Let's take a specific example:
At that time, I was watching a masterpiece of sweet potato in osc. I saw that F12 in my right hand skillfully opened the developer tool of chrome, and I quickly pressed F5 in my left hand, and then I saw the result.


Smart you must have found out, except the first one named 12_ The request return status of 77118 is 200, and the others are 304. What is the difference between 200 and 304? This will be explained later.
Everything comes from the code. Let's put aside the theory and look at a specific code:
I wrote an index HTML, as follows:
<html> <body> <h3>I'm a test page . </h3> <h3>I'm a test page . </h3> <h3>I'm a test page . </h3> <h3>I'm a test page . </h3> <h3>I'm a test page . </h3> <h3>I'm a test page . </h3> <h3>I'm a test page . </h3> </body> </html>
Let's visit this page.
Image(2)
This is my first visit to this page (indicating that there is no local cache for this file):
Let's look at the headers of http requests and responses:

Picture: I
For comparison, let's refresh with F5 again:

Picture: II
There is an if modified since in the header of this request, and the status changes to 304 in the returned response. What's the matter? Remember 304 in the sweet potato article page. You will find that 304 mostly appears on the request for static resources.
Originally, for static resources:
- When the browser initiates a request for the first time (there is no if modified since in the request header), the server will tell the browser the last modified time of the resource in the response (last modified in the response header). (see figure I)
- The browser is also very smart. When you request this resource again (click the link, or F5, or enter, but not ctrl+F5), the browser will ask the server whether this resource has been modified since the last modification time told me last time (if modified since in the request header). (see Figure II)
- If the resource has not been modified, the server returns 304 status code and will not send the resource to the browser again. The browser is very interested in using the local cache file. (see Figure II)
Therefore, if all static resources have not changed, they will not be transmitted many times. No matter what browser or server should abide by this query convention. It looks great. It's smart, isn't it? The mechanism of this Convention is http cache negotiation -- another embodiment of the superiority of the convention over the configuration.
With the knowledge of cache negotiation, it is easy to understand why we should not rewrite the service. Starting from the code, let's look at a more complex example this time:
In this example, we request a controller (MeServlet) and then turn to a view (index.html). For simplicity, web Only the configuration of this servlet will be available in the XML:
<web-app> <servlet> <servlet-name>me</servlet-name> <servlet-class>com.me.web.MeServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>me</servlet-name> <url-pattern>/test</url-pattern> </servlet-mapping> </web-app> And then MeServlet: public class MeServlet extends HttpServlet { @Override protected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { /** * 1. Handle specific business: * -- Processing request parameters * -- Check cache * -- Processing specific data * -- Update cache */ doBizLogic(req, res); /** * 2. Turn to the specific view according to the processing results: * -- The assumption here is index html */ getServletContext() .getRequestDispatcher("/index.html").include(req, res); } public void doBizLogic(HttpServletRequest request, HttpServletResponse response) { System.out.println("do biz."); } }
You can see that the status code returned by each F5 refresh is 200. Let's take a look at the specific request and response headers:

We found that no matter how we refresh the page, each response status is 200, index HTML content is sent to the browser completely every time, which seems stupid. Why not cache negotiation like static resources? The reason is that cache negotiation is based on the Modified information in http request and response headers. Without this information, cache negotiation cannot be carried out. For dynamic content, the server cannot help us decide whether the content has changed, nor can it determine the last modification time of dynamic content for us.
Therefore, it will not help us add last modified in the response. We must do it ourselves. Let's slightly modify the MeServlet:
public class MeServlet extends HttpServlet { @Override protected long getLastModified(HttpServletRequest req) { /** * Here, you have to decide the last modification time of dynamic content. For example, you can return * -- The time when the data cache was last updated * -- For simplicity, let's assume that the last modification time is 1000 */ return 1000; } @Override protected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { /** * 1. Handle specific business: * -- Processing request parameters * -- Check cache * -- Processing specific data * -- Update cache */ doBizLogic(req, res); /** * 2. Turn to the specific view according to the processing results: * -- The assumption here is index html */ getServletContext() .getRequestDispatcher("/index.html").include(req, res); } public void doBizLogic(HttpServletRequest request, HttpServletResponse response) { System.out.println("do biz."); } }
You will see that the getLastModified method is rewritten, indicating that this method already exists in the HttpServlet. We use this method to tell the server how long the last content changes in this dynamic resource. Ideally, the server will call back this method by itself, which is too easy.
Let's visit it first: it is found that it is still 200 every time. The server does not tell the browser the last modification time, and the cache negotiation mechanism cannot work.
Don't get frustrated. Forget what we're going to explain -- why don't you rewrite the service method. You may have guessed that if you look at the implementation of the service method, you already understand that the service method implements the cache negotiation mechanism. If we rewrite it, we will remove the good mechanism.

Let's modify it again. This time, we rewrite doGet and complete the same logic in doGet:
public class MeServlet extends HttpServlet { @Override protected long getLastModified(HttpServletRequest req) { /** * Here, you have to decide the last modification time of dynamic content. For example, you can return * -- The time when the data cache was last updated * -- For simplicity, let's assume that the last modification time is 1000 */ return 1000; } @Override protected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { /** * 1. Handle specific business: * -- Processing request parameters * -- Check cache * -- Processing specific data * -- Update cache */ doBizLogic(req, res); /** * 2. Turn to the specific view according to the processing results: * -- The assumption here is index html */ getServletContext() .getRequestDispatcher("/index.html").include(req, res); } public void doBizLogic(HttpServletRequest request, HttpServletResponse response) { System.out.println("do biz."); } }
During this visit,

Finally, the last modified that I haven't seen for a long time appears. Enter the request page again. Ha ha, it becomes 304.

Now you may know why you should not rewrite the service method. It seems that it is to preserve the cache negotiation mechanism implemented by HttpServlet by default; In fact, there is another reason: disable the methods you do not rewrite in the servlet, such as post, head, etc., which improves the security to a certain extent.
So far, let's look at the practical benefits of the cache negotiation mechanism:
It's still the sweet potato article. Let's load it all (ctrl+F5) once,

We see that a total of 45 requests have been initiated, and the requested data volume is 198.93KB. Then press F5 to refresh:

There are only 36 requests this time, and the data volume is only 23.62KB
We see that this article is accessed by 9960 IDS, and each id may actually access this page many times (like me, the actual data may have to ask sweet potato). Then we see that many 304 static resources are common to the whole station:

If you are a frequent guest of osc, do not change the browser frequently, do not clean the cache frequently, and even other people's avatars can be common. For simplicity, we consider that each id can only visit this page once, and assume that all resources have been cached locally, we come to the following conclusion:
(198.93-23.62)×9960 = 1746086.6KB = 1705.1637M = 1.665G.
It's amazing. It's just a page. Don't forget, we also assume that all users only visit it once. Think about how many blog posts there are on osc. Add up
What is the flow? It's silver.
Fortunately, the browser and server have helped us to save money, so we don't need to care about this?? We see 12_ 77118 this request also takes up a lot of resources. If the article is longer and longer... It will be larger.

If sweet potato is willing, it can also let the request realize cache negotiation, which can further reduce the traffic.
Of course, the calculation here is not completely accurate, and the actual situation is much more complex, but the magnitude of this calculation should be correct and worthy of reference.
Another problem involved in traffic is bandwidth. Providing higher concurrency with smaller loans is what every webmaster should pursue. However, considering that osc is mainly news and one-time consumption, so... But it was a digression at that time.
Well, if you have the patience to see here, I think you may have a new understanding of service. Why shouldn't we rewrite this method.
There are exceptions to everything. If you need to implement a front-end controller, it's another matter, which is left to everyone to think for themselves.