Java“类爆炸”问题
在 Java Web 开发中,为每个 URL 都创建一个独立的 Servlet 类会导致类的数量剧增,从而造成所谓的“类爆炸”问题,给代码的维护和管理带来很大的困难。为了解决这个问题,我们可以采用以下方法:
-
使用框架:现在有很多Java Web框架可供选择,比如SpringMVC、Struts2等,这些框架提供了更为灵活的URL映射方式,可以将一组请求映射到一个控制器中,从而避免创建太多的Servlet类。
-
使用通用的Servlet:使用通用的Servlet类,可以将许多相似的操作放在同一个Servlet中处理,从而减少代码重复和类的数量。
-
使用注解:Java 5.0 引入了注解机制,通过使用注解可以将Servlet和URL之间的映射关系直接写在Servlet类上,从而避免在web.xml文件中进行配置。
-
使用模块化开发: 将一个功能模块封装为一个Jar包, 在其他应用中通过引入该Jar包的方式调用该模块,避免类的数量过多。
第二种方法的衍生:
通过使用反射,先定义一个MyServlet作为父类,去继承HttpServlet。然后在MyServlet里通过反射去获取子对象(子类的实例化)。
public class MyServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//约定传入参数flag作为名字,以值作为方法名称
String flag = request.getParameter("flag");
//哪个servlet实例,就是记录这个servlet的信息
//tomcat: 创建servlet : UserServlet this"本对象“
Class c = this.getClass();
// Constructor constructor = c.getConstructor();
// Object object = constructor.newInstance();
System.out.println(c);
try {
//获取该Servlet(UserServlet)的 名字为flag的方法对象 delete
Method method = c.getDeclaredMethod(flag, HttpServletRequest.class, HttpServletResponse.class);
//调用方法 相当于 new UserServlet().delete(request, response)
method.invoke(this, request, response);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
然后在MVC架构的Servlet包里,每个模块都只要写一个Servlet去继承自定义的MyServlet,再将每个模块的各种方法封装在一个Servlet里面,继而xml配置里只需要写一个映射地址来和前端链接。和前端约定个标识来确定方法名,再去调用子类里的方法,根据配置文件里的Servlet配置的映射的路径找到相应的Servlet类。
public class RoleServlet extends MyServlet {
public void list(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
···
}
public void delete(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
···
}
public void add(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
···
}
public void updateRolePage(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
···
}
public void updateRole(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
···
}
}
因为在当前的Servlet里找不到get或post方法,于是去他的父类里(自定义的MyServlet)寻找,找到后通过里面的MyServlet自己写的反射机制,去获取到当前的对象,再根据得到的方法名称,去执行Servlet中的方法,然后一层层处理完后,把数据响应回前端去,前端再进行对数据显示)
第三种方法的介绍:
- @WebServlet:用于将一个Servlet类和URL之间的映射关系直接写在Servlet类上。
@WebServlet("/hello")
public class HelloServlet extends HttpServlet {
// Servlet方法的实现
}
上面的代码中,@WebServlet注解指定了URL为“/hello”,这样用户访问“/hello”时就会执行HelloServlet中的代码。
- @WebFilter:用于实现请求过滤功能,与Servlet具有相似的用法。
@WebFilter(urlPatterns = {"/admin/*"})
public class AdminFilter implements Filter {
// 过滤器方法的实现
}
上面的代码中,@WebFilter注解指定了URL匹配规则为“/admin/*”,这样用户访问以“/admin/”开头的URL时就会执行AdminFilter中的代码。