One of the interesting problems that I've found is that I often want my servlet to be a Spring-managed bean. That way, it can do all the dependency injection etc. But normally, you have to specify your servlets in web.xml, and that means your container (eg. Tomcat), not Spring, will create the servlet.
There is a way around this, using the HttpRequestHandlerServlet. My web.xml file includes these lines:
<servlet>
<servlet-name>dataProvider</servlet-name>
<servlet-class>
org.springframework.web.context.support.HttpRequestHandlerServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet>
<servlet-name>documentCreator</servlet-name>
<servlet-class>
org.springframework.web.context.support.HttpRequestHandlerServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dataProvider</servlet-name>
<url-pattern>/dataProvider/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>documentCreator</servlet-name>
<url-pattern>/documentCreator/*</url-pattern>
</servlet-mapping>
This tells Spring that it's going to use two of its beans as servlets, one called dataProvider, and the other called documentCreator. It will have to work out what those beans are, either using the xml configuration file or the annotations. I prefer the annotations, such as @Controller.
So what happens when Tomcat receives a request, eg GET /dataProvider/test
From the servlet-mapping section, it knows that it has to give that request to the first HttpRequestHandlerServlet that it created. That class knows that it has the name dataProvider, and it looks in the Spring context for a bean called dataProvider. Then it calls the handleRequest method on that bean.
My DataProvider class looks like this:
@Controller
public class DataProvider extends HttpServlet implements HttpRequestHandler {
@Autowired
private OtherBeanType otherBean
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) {
// my doGet method
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) {
// my doPost method
}
@Override
public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
if (request.getMethod().equalsIgnoreCase("GET")) {
doGet(request, response);
} else if (request.getMethod().equalsIgnoreCase("POST")) {
doPost(request, response);
}
}
}
I think it's a little unfortunate that we need that handleRequest() method (and if you use anything other than Get and Post, you'll need to add them in there). It would be nicer if the HttpRequestHandlerServlet could do that work for you, but that's just how it works for now.