JavaWeb 多個Servlet整合優化

来源:https://www.cnblogs.com/mrystar/archive/2022/07/25/16519232.html
-Advertisement-
Play Games

JavaWeb 多個Servlet整合優化 由於一個Servlet只能接收一個地址的http請求,如果系統複雜度提高,就會有很多Servlet類。例如,對銷售系統來說,可能會有OederInsertServlet, OrderUpdateServlet, OrderDeleteSerlvet, Or ...


JavaWeb 多個Servlet整合優化

由於一個Servlet只能接收一個地址的http請求,如果系統複雜度提高,就會有很多Servlet類。例如,對銷售系統來說,可能會有OederInsertServlet, OrderUpdateServlet, OrderDeleteSerlvet, OrderQueryServlet等多個OrderServlet來處理訂單這一種業務。看著就會很雜。如下圖。同時如果請求前或請求後有一些處理的話,對應的方法就需要寫很多次,維護難度也會提升

image-20220620195649124
image-20220620195649124

優化-同一個模塊多個操作

可以只用一個Servlet接收Order這一種業務所有的介面,通過在介面添加類似operate的標誌參數對不同的操作進行區分。

image-20220620195649124

代碼示例

protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String operate = req.getParameter("operate");
        if (null == operate){
            doRequireOperate(req, resp);
        }
        SUtils.logInfo("調用前操作");
        System.out.println("獲取到的操作名為:" + operate);
        switch (operate){
            case "insert":{
                System.out.println("do insert");
                doInsertOperate(req, resp);
                break;
            }
            case "update":{
                System.out.println("do update");
                doUpdateOperate(req, resp);
                break;
            }
            case "delete":{
                System.out.println("do delete");
                doDeleteOperate(req, resp);
                break;
            }
            case "query":{
                System.out.println("do query");
                doQueryOperate(req, resp);
                break;
            }
            default:{
                System.out.println("error");
            }
            SUtils.logInfo("調用後操作");
        }
    }

測試

本地訪問 http://localhost:8080/mvc/ver1?operate=insert

伺服器日誌輸出如下

image-20220620200656864

優化-使用反射

目前,對業務的操作是通過switch-case進行匹配處理的,如果操作數量增多則需要多增加case語句,代碼就會顯得臃腫。可以考慮通過反射調用具體的執行方法

示例代碼

下麵展示的是核心代碼

String operate = req.getParameter("operate");
System.out.println("獲取到的操作名為:" + operate);
        // 通過反射獲取對應的方法
        // 假定方法名均為do+${operate}+operate,駝峰,如operate為insert時,要調用的方法就是doInsertOperate
        // Method[] methods = this.getClass().getMethods();
        char[] chars = operate.toCharArray();
        chars[0] -= 32;
        String methodName = "do" + String.valueOf(chars) + "Operate";
        // Optional<Method> targetMethod = Arrays.stream(methods).filter(m -> m.getName().equals(methodName)).findFirst();
        try {
            Method taragetMethod = this.getClass().getDeclaredMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);
            taragetMethod.setAccessible(true);
            taragetMethod.invoke(this, req, resp);
        } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
            throw new RuntimeException(e);
        }

優化-多個業務模塊引入配置文件

當業務增多時,需要在每個業務裡面單獨寫反射調用方法較為複雜,可以也通過反射來調用業務模塊,再執行對應的方法,同時可以引入xml配置文件,來匹配對應的業務模塊

圖片

代碼示例

@WebServlet("/mvc/ver3/*")
public class Ver3Servlet extends HttpServlet {

    private Map<String, Object> beanControllerMap = new HashMap<>();

    // 初始化,讀取xml文件配置controller
    @Override
    public void init() throws ServletException {
        // super.init();
        System.out.println("aaa");
        try (InputStream beanConfigs = this.getClass().getClassLoader().getResourceAsStream("MvcVer3Config.xml")) {
            DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
            Document beanDocument = documentBuilder.parse(beanConfigs);
            Element documentElement = beanDocument.getDocumentElement();
            NodeList nodeList = beanDocument.getDocumentElement().getElementsByTagName("bean");
            for (int i = 0; i < nodeList.getLength(); i++) {
                if (Node.ELEMENT_NODE == nodeList.item(i).getNodeType()){
                    Element item = (Element) nodeList.item(i);
                    String beanName = item.getAttribute("id");
                    String className = item.getAttribute("class");
                    Class<?> beanClass = Class.forName(className);
                    Object bean = beanClass.getDeclaredConstructors()[0].newInstance();
                    beanControllerMap.put(beanName, bean);
                }
            }
            // documentElement.get
        } catch (IOException | ParserConfigurationException | SAXException | ClassNotFoundException |
                 InvocationTargetException | InstantiationException | IllegalAccessException e) {
            throw new RuntimeException(e);
        }
        System.out.println("aaa");

    }

    // 讀取路徑值,獲取對應的controller對象,反射調用對應方法
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String servletPath = req.getPathInfo();
        System.out.println(servletPath);
        String controllerName = servletPath.split("/")[1];
        String operateName = servletPath.split("/")[2];
        operateName = "do" + getFirstUpper(operateName) + "Operate";
        Object targetController = beanControllerMap.get(getFirstUpper(controllerName));
        Method targetMethod;
        try {
            targetMethod = targetController.getClass().getDeclaredMethod(operateName, HttpServletRequest.class, HttpServletResponse.class);
        } catch (NoSuchMethodException e) {
            ErrorResponse(req, resp, e.getMessage());
            e.printStackTrace();
            return;
        }
        try {
            targetMethod.invoke(targetController, req, resp);
        } catch (IllegalAccessException | InvocationTargetException e) {
            ErrorResponse(req, resp, e.getMessage());
            e.printStackTrace();
            return;
        }
        System.out.println("調用結束");
    }


    private void ErrorResponse(HttpServletRequest req, HttpServletResponse resp, String errorString) throws IOException {
        req.setCharacterEncoding("utf-8");
        resp.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=utf-8");
        PrintWriter out = resp.getWriter();
        out.println("<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\n");
        out.println("<HTML lang=\"ch\">");
        out.println("  <HEAD><TITLE>delete Servlet</TITLE></HEAD>");
        out.println("  <BODY>");
        out.print("所訪問的模塊不存在<br>");
        out.print(errorString);
        out.println("  </BODY>");
        out.println("</HTML>");
        out.flush();
        out.close();
        System.out.println("所訪問的模塊不存在");
    }

    private String getFirstUpper(String s){
        char[] chars = s.toCharArray();
        chars[0] -= 32;
        return String.valueOf(chars);
    }
}

解決多個業務配置問題,通過讀取配置文件初始化Servlet,在收到請求時,取到對應的Servlet進行處理

配置文件示例

<?xml version="1.0" encoding="utf-8" ?>
<beans>
    <bean id="A" class="com.javawebdemo.mvc.controller.AController"/>
    <bean id="B" class="com.javawebdemo.mvc.controller.BController"/>
    <bean id="C" class="com.javawebdemo.mvc.controller.CController"/>
    <bean id="D" class="com.javawebdemo.mvc.controller.DController"/>
</beans>

測試

啟動項目,訪問對應路徑

http://localhost:8080/mvc/ver3/a/query

圖片
頁面響應

圖片

調用成功


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 初識Js 1.前言 學習js的第一天,簡單瞭解了一下JS的誕生歷史,JS相關變數,關鍵字,命名規範,JS數據類型以及各種數據類型之間的轉換,JS運算符的使用,二進位,八進位,十進位,十六進位之間的換算。 2.JS的誕生歷史 1.JavaScript誕生於1995年,由Netscape(網景公司)研發 ...
  • 原文鏈接: 基於 Hexo 鍵入搜索功能 前言 本站基於Hexo搭建,用的 🦋 hexo-theme-butterfly 主題 v3.7.1,請註意最新的🦋 hexo-theme-butterfly 版本已經更新到 v4.2.2 。 如果你是 v3.7.1 之外的版本,可能有些地方會有出入,請留 ...
  • 本文,將另闢蹊徑,介紹一種使用濾鏡去構建圓角的獨特方式。 首先,我們來看這樣一個圖形: 一個矩形,沒什麼特別的,代碼如下: div { width: 200px; height: 40px; background-color: #000; } 如果,我們現在需要給這個矩形的兩端加上圓角,像是這樣,該 ...
  • 本文簡介 點贊 + 關註 + 收藏 = 學會了 在 JS 中,偽數組 是非常常見的,它也叫 類數組。偽數組可能會給 JS 初學者帶來一點困擾。 本文將詳細講解 什麼是偽數組,以及分別在 ES5 和 ES6 中將偽數組轉換成真正的數組 。 什麼是偽數組? 偽數組的主要特征:它是一個對象,並且該對象有 ...
  • 最近由於項目需求,需要醫學影像.dcm文件的預覽功能,功能完成後,基於原生Demo做一個開源分享。 心急的小伙伴可以先看如下基於原生js的全部代碼: 一、全部代碼 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta ...
  • 近期工作有涉及到數字大屏的需求,於是利用業餘時間,結合 Three.js 和 CSS實現賽博朋克2077風格視覺效果 實現炫酷 3D 數字地球大屏頁面。頁面使用 React + Three.js + Echarts + stylus 技術棧,本文涉及到的主要知識點包括:THREE.Spherical... ...
  • JavaScript進階內容——jQuery 我們在前面的文章中已經掌握了JavaScript的全部內容,現在讓我們瞭解一下JavaScript庫 這篇文章主要是為了為大家大致講解JavaScript庫以及使用方法,本篇不會完全講解jQuery的全部語法 如果希望完全掌握,可以參考網站jQuery ...
  • 1.創建虛擬環境 conda create --name yourEnv python=3.6 --name:也可以縮寫為 【-n】 yourEnv:是新創建的虛擬環境的名字,創建完,可以裝anaconda的目錄下找到envs/環境名 目錄 python=3.6:是python的版本號。也可以指定為 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...