Building our own Servlet
Note that for simplicity we will only look into the functionality of RESTful services which return JSON objects - we will ignore the model/view part of Spring MVC.
I usually like to write code in order to better understand a concept and make things less abstract. So let's just simply create our own servlet! All we need is an embedded tomcat dependency.
To get things started we'll create a tomcat instance, set it to port 7777 and create the default connector (more on that later - essentially it handles HTTP-protocol related stuff)
Next up we'll implement the Jakarta Servlet Spec (by extending the abstract HTTP version of it)
For now we'll only implement the doGet method the abstract base class (of course there is one for every HTTP verb). This allows us to handle GET requests and return a response! In this case we set the content type of the response to application/json and write our json content to the output stream for all requests that go to the base path. For all other requests we'll just return a 404 without any content. That's it!
By checking request.getPathInfo() we could compare this against all annotated controller request handlers, invoke the matching one and have a similar functionality to what Spring provides. But that would go too far for our small demo.
Let's wire the servlet into the servlet container!
First we create a servlet context in which you can provide a context-path that specifies which base path is routed to your servlet. If we just leave it empty like above any request going to http://localhost:7777/... will go to our dummy servlet.
After having specified the context we just add the servlet and provide the url pattern which should be routed to it. Similar to the Dispatcher Servlet of Spring, we'll handle all incoming requests at a central point:
With the above code we already have a working setup to make our first HTTP GET request. But first, let's add a filter to our setup to have this core concept covered as well. The most prominent use-cases for filters are usually authentication and compression but there are of course many more applications.
Similar to the servlet, we extend the Jakarta HttpFilter abstract class and implement the doFilter method. In this method we have the http request and response at our hand for manipulation.
A third argument, the filter chain is passed as well. We have to invoke it to continue the request processing if our filter determines that everything is in order. Essentially you can register a bunch of filters in your servlet container and all need to be invoked before your request reaches the servlet. This means every filter has the power to completely stop the processing of a request simply by not further invoking the filter chain.
In our example we have a very secure authentication process in place, it simply checks if the "my-auth" header is set and if so it proceeds with the processing of the request. If it's not set we won't invoke the filter chain but instead set the status code to 403, add a famous movie quote and return the response to the client.
Now let's add the filter to your servlet container as well!
This is quite verbose but essentially we create a filter definition where we specify the class we just created, specify the path (in our case everything) on which the filter is applied and add the mapping to the context.
Finally, let's get this thing started! If we put our above tomcat configuration in a main method and start the tomcat server we can send our first requests!
As expected if we don't specify our authentication header the filter will block our request:
But if we do add the header we get to our servlet!