JavaWeb 多个Servlet整合优化

打印 上一主题 下一主题

主题 829|帖子 829|积分 2487

JavaWeb 多个Servlet整合优化

由于一个Servlet只能接收一个地址的http请求,如果系统复杂度提高,就会有很多Servlet类。例如,对销售系统来说,可能会有OederInsertServlet, OrderUpdateServlet, OrderDeleteSerlvet, OrderQueryServlet等多个OrderServlet来处理订单这一种业务。看着就会很杂。如下图。同时如果请求前或请求后有一些处理的话,对应的方法就需要写很多次,维护难度也会提升


优化-同一个模块多个操作

可以只用一个Servlet接收Order这一种业务所有的接口,通过在接口添加类似operate的标志参数对不同的操作进行区分。

代码示例
  1. protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  2.         String operate = req.getParameter("operate");
  3.         if (null == operate){
  4.             doRequireOperate(req, resp);
  5.         }
  6.         SUtils.logInfo("调用前操作");
  7.         System.out.println("获取到的操作名为:" + operate);
  8.         switch (operate){
  9.             case "insert":{
  10. <?xml version="1.0" encoding="utf-8" ?>
  11. <beans>
  12.     <bean id="A" />
  13.     <bean id="B" />
  14.     <bean id="C" />
  15.     <bean id="D" />
  16. </beans>System.out.println("do insert");
  17. <?xml version="1.0" encoding="utf-8" ?>
  18. <beans>
  19.     <bean id="A" />
  20.     <bean id="B" />
  21.     <bean id="C" />
  22.     <bean id="D" />
  23. </beans>doInsertOperate(req, resp);
  24. <?xml version="1.0" encoding="utf-8" ?>
  25. <beans>
  26.     <bean id="A" />
  27.     <bean id="B" />
  28.     <bean id="C" />
  29.     <bean id="D" />
  30. </beans>break;
  31.             }
  32.             case "update":{
  33. <?xml version="1.0" encoding="utf-8" ?>
  34. <beans>
  35.     <bean id="A" />
  36.     <bean id="B" />
  37.     <bean id="C" />
  38.     <bean id="D" />
  39. </beans>System.out.println("do update");
  40. <?xml version="1.0" encoding="utf-8" ?>
  41. <beans>
  42.     <bean id="A" />
  43.     <bean id="B" />
  44.     <bean id="C" />
  45.     <bean id="D" />
  46. </beans>doUpdateOperate(req, resp);
  47. <?xml version="1.0" encoding="utf-8" ?>
  48. <beans>
  49.     <bean id="A" />
  50.     <bean id="B" />
  51.     <bean id="C" />
  52.     <bean id="D" />
  53. </beans>break;
  54.             }
  55.             case "delete":{
  56. <?xml version="1.0" encoding="utf-8" ?>
  57. <beans>
  58.     <bean id="A" />
  59.     <bean id="B" />
  60.     <bean id="C" />
  61.     <bean id="D" />
  62. </beans>System.out.println("do delete");
  63. <?xml version="1.0" encoding="utf-8" ?>
  64. <beans>
  65.     <bean id="A" />
  66.     <bean id="B" />
  67.     <bean id="C" />
  68.     <bean id="D" />
  69. </beans>doDeleteOperate(req, resp);
  70. <?xml version="1.0" encoding="utf-8" ?>
  71. <beans>
  72.     <bean id="A" />
  73.     <bean id="B" />
  74.     <bean id="C" />
  75.     <bean id="D" />
  76. </beans>break;
  77.             }
  78.             case "query":{
  79. <?xml version="1.0" encoding="utf-8" ?>
  80. <beans>
  81.     <bean id="A" />
  82.     <bean id="B" />
  83.     <bean id="C" />
  84.     <bean id="D" />
  85. </beans>System.out.println("do query");
  86. <?xml version="1.0" encoding="utf-8" ?>
  87. <beans>
  88.     <bean id="A" />
  89.     <bean id="B" />
  90.     <bean id="C" />
  91.     <bean id="D" />
  92. </beans>doQueryOperate(req, resp);
  93. <?xml version="1.0" encoding="utf-8" ?>
  94. <beans>
  95.     <bean id="A" />
  96.     <bean id="B" />
  97.     <bean id="C" />
  98.     <bean id="D" />
  99. </beans>break;
  100.             }
  101.             default:{
  102. <?xml version="1.0" encoding="utf-8" ?>
  103. <beans>
  104.     <bean id="A" />
  105.     <bean id="B" />
  106.     <bean id="C" />
  107.     <bean id="D" />
  108. </beans>System.out.println("error");
  109.             }
  110.             SUtils.logInfo("调用后操作");
  111.         }
  112.     }
复制代码
测试

本地访问 http://localhost:8080/mvc/ver1?operate=insert
服务器日志输出如下

优化-使用反射

目前,对业务的操作是通过switch-case进行匹配处理的,如果操作数量增多则需要多增加case语句,代码就会显得臃肿。可以考虑通过反射调用具体的执行方法
示例代码

下面展示的是核心代码
  1. String operate = req.getParameter("operate");
  2. System.out.println("获取到的操作名为:" + operate);
  3.         // 通过反射获取对应的方法
  4.         // 假定方法名均为do+${operate}+operate,驼峰,如operate为insert时,要调用的方法就是doInsertOperate
  5.         // Method[] methods = this.getClass().getMethods();
  6.         char[] chars = operate.toCharArray();
  7.         chars[0] -= 32;
  8.         String methodName = "do" + String.valueOf(chars) + "Operate";
  9.         // Optional<Method> targetMethod = Arrays.stream(methods).filter(m -> m.getName().equals(methodName)).findFirst();
  10.         try {
  11.             Method taragetMethod = this.getClass().getDeclaredMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);
  12.             taragetMethod.setAccessible(true);
  13.             taragetMethod.invoke(this, req, resp);
  14.         } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
  15.             throw new RuntimeException(e);
  16.         }
复制代码
优化-多个业务模块引入配置文件

当业务增多时,需要在每个业务里面单独写反射调用方法较为复杂,可以也通过反射来调用业务模块,再执行对应的方法,同时可以引入xml配置文件,来匹配对应的业务模块

代码示例
  1. @WebServlet("/mvc/ver3/*")
  2. public class Ver3Servlet extends HttpServlet {
  3.     private Map<String, Object> beanControllerMap = new HashMap<>();
  4.     // 初始化,读取xml文件配置controller
  5.     @Override
  6.     public void init() throws ServletException {
  7.         // super.init();
  8.         System.out.println("aaa");
  9.         try (InputStream beanConfigs = this.getClass().getClassLoader().getResourceAsStream("MvcVer3Config.xml")) {
  10.             DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
  11.             DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
  12.             Document beanDocument = documentBuilder.parse(beanConfigs);
  13.             Element documentElement = beanDocument.getDocumentElement();
  14.             NodeList nodeList = beanDocument.getDocumentElement().getElementsByTagName("bean");
  15.             for (int i = 0; i < nodeList.getLength(); i++) {
  16. <?xml version="1.0" encoding="utf-8" ?>
  17. <beans>
  18.     <bean id="A" />
  19.     <bean id="B" />
  20.     <bean id="C" />
  21.     <bean id="D" />
  22. </beans>if (Node.ELEMENT_NODE == nodeList.item(i).getNodeType()){
  23. <?xml version="1.0" encoding="utf-8" ?>
  24. <beans>
  25.     <bean id="A" />
  26.     <bean id="B" />
  27.     <bean id="C" />
  28.     <bean id="D" />
  29. </beans>    Element item = (Element) nodeList.item(i);
  30. <?xml version="1.0" encoding="utf-8" ?>
  31. <beans>
  32.     <bean id="A" />
  33.     <bean id="B" />
  34.     <bean id="C" />
  35.     <bean id="D" />
  36. </beans>    String beanName = item.getAttribute("id");
  37. <?xml version="1.0" encoding="utf-8" ?>
  38. <beans>
  39.     <bean id="A" />
  40.     <bean id="B" />
  41.     <bean id="C" />
  42.     <bean id="D" />
  43. </beans>    String className = item.getAttribute("class");
  44. <?xml version="1.0" encoding="utf-8" ?>
  45. <beans>
  46.     <bean id="A" />
  47.     <bean id="B" />
  48.     <bean id="C" />
  49.     <bean id="D" />
  50. </beans>    Class<?> beanClass = Class.forName(className);
  51. <?xml version="1.0" encoding="utf-8" ?>
  52. <beans>
  53.     <bean id="A" />
  54.     <bean id="B" />
  55.     <bean id="C" />
  56.     <bean id="D" />
  57. </beans>    Object bean = beanClass.getDeclaredConstructors()[0].newInstance();
  58. <?xml version="1.0" encoding="utf-8" ?>
  59. <beans>
  60.     <bean id="A" />
  61.     <bean id="B" />
  62.     <bean id="C" />
  63.     <bean id="D" />
  64. </beans>    beanControllerMap.put(beanName, bean);
  65. <?xml version="1.0" encoding="utf-8" ?>
  66. <beans>
  67.     <bean id="A" />
  68.     <bean id="B" />
  69.     <bean id="C" />
  70.     <bean id="D" />
  71. </beans>}
  72.             }
  73.             // documentElement.get
  74.         } catch (IOException | ParserConfigurationException | SAXException | ClassNotFoundException |
  75. <?xml version="1.0" encoding="utf-8" ?>
  76. <beans>
  77.     <bean id="A" />
  78.     <bean id="B" />
  79.     <bean id="C" />
  80.     <bean id="D" />
  81. </beans> InvocationTargetException | InstantiationException | IllegalAccessException e) {
  82.             throw new RuntimeException(e);
  83.         }
  84.         System.out.println("aaa");
  85.     }
  86.     // 读取路径值,获取对应的controller对象,反射调用对应方法
  87.     @Override
  88.     protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  89.         String servletPath = req.getPathInfo();
  90.         System.out.println(servletPath);
  91.         String controllerName = servletPath.split("/")[1];
  92.         String operateName = servletPath.split("/")[2];
  93.         operateName = "do" + getFirstUpper(operateName) + "Operate";
  94.         Object targetController = beanControllerMap.get(getFirstUpper(controllerName));
  95.         Method targetMethod;
  96.         try {
  97.             targetMethod = targetController.getClass().getDeclaredMethod(operateName, HttpServletRequest.class, HttpServletResponse.class);
  98.         } catch (NoSuchMethodException e) {
  99.             ErrorResponse(req, resp, e.getMessage());
  100.             e.printStackTrace();
  101.             return;
  102.         }
  103.         try {
  104.             targetMethod.invoke(targetController, req, resp);
  105.         } catch (IllegalAccessException | InvocationTargetException e) {
  106.             ErrorResponse(req, resp, e.getMessage());
  107.             e.printStackTrace();
  108.             return;
  109.         }
  110.         System.out.println("调用结束");
  111.     }
  112.     private void ErrorResponse(HttpServletRequest req, HttpServletResponse resp, String errorString) throws IOException {
  113.         req.setCharacterEncoding("utf-8");
  114.         resp.setCharacterEncoding("utf-8");
  115.         resp.setContentType("text/html;charset=utf-8");
  116.         PrintWriter out = resp.getWriter();
  117.         out.println("<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">\n");
  118.         out.println("<HTML lang="ch">");
  119.         out.println("  <HEAD><TITLE>delete Servlet</TITLE></HEAD>");
  120.         out.println("  <BODY>");
  121.         out.print("所访问的模块不存在
  122. ");
  123.         out.print(errorString);
  124.         out.println("  </BODY>");
  125.         out.println("</HTML>");
  126.         out.flush();
  127.         out.close();
  128.         System.out.println("所访问的模块不存在");
  129.     }
  130.     private String getFirstUpper(String s){
  131.         char[] chars = s.toCharArray();
  132.         chars[0] -= 32;
  133.         return String.valueOf(chars);
  134.     }
  135. }
复制代码
解决多个业务配置问题,通过读取配置文件初始化Servlet,在收到请求时,取到对应的Servlet进行处理
配置文件示例
  1. <?xml version="1.0" encoding="utf-8" ?>
  2. <beans>
  3.     <bean id="A" />
  4.     <bean id="B" />
  5.     <bean id="C" />
  6.     <bean id="D" />
  7. </beans>
复制代码
测试

启动项目,访问对应路径
http://localhost:8080/mvc/ver3/a/query

页面响应

调用成功

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

正序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

大号在练葵花宝典

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表