使用一个Servlet来处理所有请求
问题
在开发 JavaWeb 应用中,编写 Servlet 是一个必不可少的环节,但是一般情况下都是一个 Servlet 处理一个特定请求。一旦编写的 Servlet 越来越多,那么管理 Servlet 就会越来越麻烦了。
所以应该如何减少 Servlet 的数量呢?只需要一个 Servlet 来分发请求,将请求交给不同的方法来进行处理。但是方法都堆在一个类中那么也是很难管理,所以每一个类代表一个模块,每个模块下都有特定的方法来处理不同的请求。
方案
那么解决方案就是使用一个 Servlet 来处理所有请求,将请求分发到对应的类中再执行指定方法。
实现
接下来就是方案的实现,应该如何将请求转发到指定的方法呢?类与方法,可以想到使用反射的方式来实现,而前端与后端的交流大部分都在 URI 中。所以只要在 URI 中获取到类与方法名称即可处理指定请求了。通过结合 Spring ,使用 IOC 容器来获取到相应的实例。
代码
@WebServlet(urlPatterns = "*.do",name = "MyDispatcherServlet")
public class MyDispatcherServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) {
ApplicationContext context = WebApplicationContextUtils
.getWebApplicationContext(this.getServletContext());
String requestURI = req.getRequestURI();
requestURI = requestURI.substring(0, requestURI.indexOf(".do"));
System.out.println(requestURI);
///myServlet/course/test.do"
//将 URI 分解成一个数组
//例如URI=/myServlet/course/test---->["","myServlet","course","test"]
//split[0]与split[1]是固定的,split[2]代表着需要的实例,split[3]则是实例中要执行的方法
String[] split = requestURI.split("/");
//从 IOC 容器中获取实例
Object bean = context.getBean(split[2]);
//获取类对象
Class<?> aClass = bean.getClass();
try {
//使用反射获取到类对象的指定方法
Method method = aClass.getMethod(split[3], HttpServletRequest.class, HttpServletResponse.class);
//执行实例中指定方法
method.invoke(bean, req, resp);
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
}
}
以上就就是只使用一个 Servlet 来处理请求的实现 demo 了