BaseServlet 介紹


1. BaseServlet 的作用

  • 讓一個Servlet可以處理多種不同的請求,不同的請求調用Servlet的不同方法.

2. 實現原理

  • 客戶端發送請求時, 必須多給出一個參數, 用來說明要調用的方法!! 這樣,BaseServlet 通過該參數來
    調用目標方法.
  • 請求處理方法的簽名必須與 service 相同, 即方法的返回值和參數,以及聲明的異常都相同.

// 代碼示例
    public class AServlet extends HttpServlet{

        // service 方法
        public void service(HttpServletRequest req, HttpServletResponse resp)
                throws ServletException, IOException{

                // 獲取參數, 用來識別客戶端想請求的方法
                // 然后判斷是哪一個方法, 是哪一個方法,就調用哪一個方法.

                // 我們這里給參數的名字為 method
                String methodName = req.getParameter("method");

                if(methodName.equals("addUser")){
                    addUser(req,resp);
                }else if(methodName.equals("editUser")){
                    editUser(req,resp);
                }else if(methodName.equals("deleteUser")){
                    deleteUser(req,resp);
                }
        }

        // 添加客戶的方法
        public void addUser(HttpServletRequest req, HttpServletResponse resp)
                throws ServletException, IOException{

                System.out.println("addUser()....");
            }

        // 編輯客戶的方法
        public void editUser(HttpServletRequest req, HttpServletResponse resp)
                throws ServletException, IOException{

                System.out.println("addUser()....");
        }

        // 刪除客戶的方法
        public void deleteUser(HttpServletRequest req, HttpServletResponse resp)
                throws ServletException, IOException{

                System.out.println("addUser()....");
        }
    }


// 升級版
    /*
     * 思路:
     *     得到方法名稱, 是否可以通過反射來調用方法?
     * 步驟:
     *    1. 得到方法名, 通過方法名再得到 Method 類的對象
     *    2. 需要得到 class, 然后調用它的方法進行查詢! 得到 Method
     *    3. 我們要查詢的是當前類的方法, 所以我們需要得到當前類的 Class
     */

public abstact class BaseServlet extends HttpServlet{

    public void service(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException{

            // 獲取參數, 用來識別用戶想請求的方法
            String methodName = req.getParameter("method");

            // 判斷該參數是否存在, 不存在,拋出異常
            if(methodName == null || methodName.trim().isEmpty()){
                throw new RuntimeException("您沒有傳遞 method 參數! 無法確定您想調用的方法");
            }

            // 得到當前類的 class 對象
             Class c = this.getClass();

            // 查詢方法, 參數需要: 方法名和該方法的參數類型
            // 該方法的參數類型必須與 service 中的參數類型一致
            Method method = null;
            try{
                method = c.getMethod(methodName,
                                HttpServletRequest.class, HttpServletResponse.class);
            } catch(Exception e){
                throw new RuntimeException("您要調用的方法"+methodName+",它不存在!");
            }

            // 調用 method 方法
            // 反射調用, 第一參數表示當前類,
            // 正常調用: this.method(req,resp)
            try{
                method.invoke(this,req,resp);  
            } catch(Exception e){                    
                throw new RuntimeException(e);
            }
}

// AServlet 繼承 BaseServlet
public void class AServlet extends BaseServlet{
        // 添加客戶的方法
        public void addUser(HttpServletRequest req, HttpServletResponse resp)
                throws ServletException, IOException{

                System.out.println("addUser()....");
            }

        // 編輯客戶的方法
        public void editUser(HttpServletRequest req, HttpServletResponse resp)
                throws ServletException, IOException{

                System.out.println("addUser()....");
        }

        // 刪除客戶的方法
        public void deleteUser(HttpServletRequest req, HttpServletResponse resp)
                throws ServletException, IOException{

                System.out.println("addUser()....");
        }    
}

// 處理轉發和重定向問題
public void class BServlet extends BaseServlet{

        // 添加客戶的方法
        public String addUser(HttpServletRequest req, HttpServletResponse resp)
                throws ServletException, IOException{

                System.out.println("addUser()....");

                // 返回表示轉發的字符串, "f" 表示 forward
                return "f:/index.jsp";
            }

        // 編輯客戶的方法
        public String editUser(HttpServletRequest req, HttpServletResponse resp)
                throws ServletException, IOException{

                System.out.println("addUser()....");

                // 返回表示重定向的字符串, "r" 表示 redirect
                return "r:/index.jsp";
        }

        // 刪除客戶的方法
        public String deleteUser(HttpServletRequest req, HttpServletResponse resp)
                throws ServletException, IOException{

                System.out.println("addUser()....");

                return null;
        }    
}

// BaseServlet 升級
public void abstract BaseServlet extends HttpServlet{
    public void service(HttpServletRequest req, HttpServletResponse resp)
                throws ServletException,IOException{

            String methdoName = req.getParameter("method");

            if(methodName == null || methodName.trim().isEmpty()){
                throw new RuntimeException("您沒有傳遞method參數,無法確定要調用的方法!");
            }

            Class c = this.getClass();

            Method method=null;
            try{
                method = c.getMethod(methodName,
                            HttpServletRequest.class,HttpServletResponse.class);
            }catch(Exception e){
                throw new RuntimeException("您要調用的"+methodName+"方法,它不存在!");
            }

            // 調用 method 方法

            try{

                String result = (String)method.invoke(this,req,resp);

                /*
                 * 獲取請求處理方法執行后返回的字符串, 它表示轉發或重定向的路徑!
                 * 完成轉發或重定向.
                 *
                 *  如果用戶返回的字符串為 null, 或為 "", 那么我們什么也不做!
                 *
                 * 查看返回的字符串中是否包含冒號, 如果沒有, 表示轉發
                 * 如果有, 使用冒號分割字符串, 得到前綴和后綴!!
                 * 其中前綴如果是 f, 表示轉發, 如果是 r, 表示重定向, 后綴就是要轉發或重定向的路徑了!
                 */

                if(result == null || result.trim().isEmpty()){
                    return;
                }

                // 如果不為空
                if(result.contains(":")){
                    // 使用冒號分割字符串, 得到前綴和后綴
                    int index = result.indexOf(":"); // 獲取冒號的位置
                    String s = result.substring(0,index);  // 獲取前綴
                    String path = result.subString(index+1); // 獲取后綴, 即路徑

                    if(e.equalsIgnoreCase("r")){ // 如果前綴是 r, 重定向
                        resp.sendRedirect(req.getContextPath()+path);
                    }else if(e.equalsIgnoreCase("f")){
                        req.getRequestDispatcher(path).forward(req,resp);
                    } else {
                        throw new RuntimeException("您指定的操作:"+s+",當前版本不支持!");
                    }

                } else { // 沒有冒號, 默認為轉發
                    req.getRequestDispatcher(result).forward(req,resp);
                }


            }catch(Exception e){
                throw new RuntimeException(e);
            }
    }
}

參考資料:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM