關於BaseServlet那些事

来源:http://www.cnblogs.com/zyuqiang/archive/2017/08/21/7406290.html
-Advertisement-
Play Games

@為什麼需要BaseServlet? 我們知道一個POST或者GET提交對應著一個Servlet, 無數的提交會讓Servlet頁面增加,我們希望一個Servlet就能處理很多提交的請求。 @BaseServlet 是一個繼承了HttpServlet的普通類,並不是Servlet類,所以不需要在we ...


@為什麼需要BaseServlet?  我們知道一個POST或者GET提交對應著一個Servlet, 無數的提交會讓Servlet頁面增加,我們希望一個Servlet就能處理很多提交的請求。

@BaseServlet 是一個繼承了HttpServlet的普通類,並不是Servlet類,所以不需要在web.xml中添加路徑。但是Servlet會繼承這個BaseServlet來實現一個Servlet處理多個提交請求 。

@一些要求 是: 客戶端發送請求時,必須提供一個參數(本文編寫的這個參數名字叫method,這個method和form中的那個method沒有半毛錢關係,只是一個變數名字而已),用來說明要調用Servlet中的那個處理方法; 其次,繼承了BaseServlet的Servlet中的處理請求的方法的原型必須與service方法相同,即返回值類型、參數都不需要和service方法相同。即如下的形式:

 public String XXX(HttpServletRequest request, HttpServletResponse 
                 response) throws ServletException, IOException {
    
        return null ;
    }

@POST和GET請求對於method參數的提供技巧 POST請求一般為表單形式,提供method參數的方式可以添加一個隱藏欄位 <input type="hidden" name="method" value="希望調用Servlet中的方法的名字"/>  ; @GET請求一般為超鏈接,提供method參數的方式直接在路徑後面加 ?method=方法名 

@POST和GET請求編碼處理 我們知道Servlet對POST請求和對GET請求的請求編碼不同,區別如下:

POST的請求
request.setCharacterEncoding("utf-8");
String name =  request.getParameter("name");
GET的請求
String name =  request.getParameter("name");
name = new String(name.getBytes("ISO-8859-1"),"utf-8");
POST和GET的響應編碼都是:
response.setContentType("text/html;charset=UTF-8");

為了使得servlet中的代碼簡潔,我們可以把兩種編碼的代碼放到BaseServlet中,但是,像上傳下載這種請求不適合用BaseServlet,所以我們一般把這種代碼寫在過濾器中,過濾器不是本文主要內容,如果你不會的話,可以不用過濾器,把編碼的代碼直接寫在servlet中的請求處理方法中即可 。 

@源碼

1 <%--get請求,傳遞過去method參數,指明調用TestServlet的fun2方法,並且傳遞一個參數param--%>
2 <a href="<c:url value='/TestServlet?method=fun2&param=哈哈'/>"> 點擊這裡啊</a>
3 <%--post請求--%>
4 <form action="<c:url value='/TestServlet'/>" method="post">
5    <input type="hidden" name="method" value="fun1"/>
6    <input type="text" name="param" value="我是表單參數" />
7    <input type="submit" name="提交"/>
8 </form>
請求jsp頁面
 1 package cn.demo1.baseServlet;
 2 
 3 import java.io.IOException;
 4 
 5 import javax.servlet.ServletException;
 6 import javax.servlet.http.HttpServletRequest;
 7 import javax.servlet.http.HttpServletResponse;
 8 /**
 9  * TestServlet 
10  *    實現了一個Servlet中多個請求處理方法
11  *    方法的的參數必須和service方法相同
12  *    客戶端必須傳遞過來method參數,說明是調用哪一個請求處理方法
13  * @author ZHAOYUQIANG
14  *
15  */
16 public class TestServlet extends BaseServlet {
17     /**
18      * 測試post傳遞過來的參數
19      * @param request
20      * @param response
21      * @return
22      * @throws ServletException
23      * @throws IOException
24      */
25     public String fun1(HttpServletRequest request, HttpServletResponse response)
26             throws ServletException, IOException {
27         String param = request.getParameter("param");
28         request.setAttribute("param", param);
29         return "f:/baseServlet/index.jsp" ;
30     }
31     /**
32      * 測試get請求傳遞過來的參數
33      * @param req
34      * @param resp
35      * @return
36      * @throws ServletException
37      * @throws IOException
38      */
39     public String fun2(HttpServletRequest request, HttpServletResponse response)
40             throws ServletException, IOException {
41         String param = request.getParameter("param");
42         request.setAttribute("param", param);
43         return "f:/baseServlet/index.jsp";
44     }
45 }
請求Servlet
  1 package cn.demo1.baseServlet;
  2 
  3 import java.io.IOException;
  4 import java.lang.reflect.Method;
  5 
  6 import javax.servlet.ServletException;
  7 import javax.servlet.http.HttpServlet;
  8 import javax.servlet.http.HttpServletRequest;
  9 import javax.servlet.http.HttpServletResponse;
 10 /**
 11  * BaseServlet[抽象類] 不需要在web.xml中添加路徑
 12  * @功能 1. 
 13  * @author ZHAOYUQIANG
 14  *
 15  */
 16 public abstract class BaseServlet extends HttpServlet {
 17     public void service(HttpServletRequest request, HttpServletResponse response)
 18             throws ServletException, IOException {
 19 //        response.setContentType("text/html;charset=UTF-8");//處理響應編碼
 20         /*
 21          * 設置POST和GET請求編碼
 22          */                
 23         /*
 24          * 1. 獲取參數,用來識別用戶想請求的方法
 25          *      method是用戶在瀏覽器地址欄中輸入的想要調用的方法,是個參數
 26          */
 27         String methodName = request.getParameter("method");
 28         /*
 29          * 2. 判斷用戶有沒有傳參數
 30          */
 31         if(methodName == null || methodName.trim().isEmpty()){
 32             throw new RuntimeException("您沒有傳遞method參數! 無法確定您要調用的方法!");
 33         }
 34         /**
 35          * 3. 判斷是哪一個方法,是哪一個就調用哪一個
 36          *    所用的技術是: 反射
 37          *        需要得到本類Class,然後調用它的getMethod,通過傳遞過來的方法名字進行得到Method對象
 38          *    這樣做的目的是: 以後像其他Servlet中的方法要修改或者添加新方法時,就不用在去修改這一塊代碼了
 39          */
 40         /*
 41          * 3.1.  得到當前類的對象
 42          */
 43         Class c = this.getClass();
 44         /*
 45          * 3.2.  通過傳遞過來的方法名(addUse等)得到Method對象
 46          *    導包 :java.lang.reflect.Method;
 47          */
 48         Method method = null ;
 49         try {
 50             method = c.getMethod(methodName, 
 51                     HttpServletRequest.class,HttpServletResponse.class);
 52         } catch (Exception e) {
 53             throw new RuntimeException("您要調用的方法"+methodName+",它不存在");
 54         } 
 55         try {
 56             /*
 57              * 3.3. 調用method表示的方法,即: 調用繼承該類的類中的方法
 58              *     反射調用: 用this來調用method表示的方法,並且傳遞參數req和resp
 59              */
 60             String result =(String)method.invoke(this, request,response);
 61             /**
 62              * 4. 處理從繼承這個類的類中返回的字元串(重定向和轉發)
 63              *     return "r:/index.jsp"; 和 return "f:/index.jsp";
 64              *      返回的是字元串,需要解讀字元串
 65              */
 66             /*
 67              * 4.1. 如果用戶返回的字元串為null,或者"",那麼什麼都不做
 68              */
 69             if(result == null || result.trim().isEmpty()){
 70                 return  ;
 71             }
 72             /*
 73              * 4.2. 解讀字元串1:判斷字元串中有沒有冒號
 74              *        沒有冒號預設表示轉發,反之再進行判斷
 75              */
 76             if(result.contains(":")){
 77                 /*
 78                  * 4.3. 解讀字元串2 : 先獲取冒號位置,然後截取首碼(操作,是重定向還是轉發)和尾碼(路徑)
 79                  */
 80                 int index = result.indexOf(":");
 81                 String operate = result.substring(0,index);
 82                 String path = result.substring(index+1);
 83                 /*
 84                  * 4.4. 進行處理,如果是r重定向,如果是f則轉發
 85                  */
 86                 if(operate.equalsIgnoreCase("r")){
 87                     response.sendRedirect(request.getContextPath()+path);
 88                 }else if(operate.equalsIgnoreCase("f")){
 89                     request.getRequestDispatcher(path).forward(request, response);
 90                 }else{
 91                     throw new RuntimeException("您指定的操作"+operate+
 92                             "不支持,請正確填寫:r和f");
 93                 }                                
 94             }else{
 95                 /*
 96                  * 沒有冒號預設轉發處理
 97                  */
 98                 request.getRequestDispatcher(result).forward(request, response);
 99             }                                            
100         } catch (Exception e) {
101             System.out.println("您要調用的方法"+methodName+",它內部拋出了異常");
102             throw new RuntimeException(e);
103         }            
104     }
105 }
BaseServlet
 1 package cn.demo1.baseServlet;
 2 
 3 import java.io.IOException;
 4 import javax.servlet.Filter;
 5 import javax.servlet.FilterChain;
 6 import javax.servlet.FilterConfig;
 7 import javax.servlet.ServletException;
 8 import javax.servlet.ServletRequest;
 9 import javax.servlet.ServletResponse;
10 import javax.servlet.http.HttpServletRequest;
11 
12 /**
13  * 輔助Servlet簡化編碼代碼
14  */
15 public class EncodingFilter implements Filter {
16 
17     public void destroy() {
18         // TODO Auto-generated method stub
19     }
20     public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
21         /*
22          * 處理post請求亂碼問題
23          */
24         request.setCharacterEncoding("utf-8");
25         /*
26          * 處理GET請求編碼問題
27          *   String name1 =  request.getParameter("name");
28          *   name2 = new String(name.getBytes("ISO-8859-1"),"utf-8");
29          *    GET不一樣,設置編碼後,servlet中獲取name,獲取應該是name2,都是如果如上寫的話,
30          *     getParameter("name")獲取的是name1 .
31          * 掉包request
32          *    1. 寫一個request的裝飾類
33          *    2. 放行時,使用我們自己的request
34          *    3. 但是POST方式依然使用request
35          */
36         HttpServletRequest req = (HttpServletRequest) request ;
37         if(req.getMethod().equals("GET")){
38             EncodingRequest er = new EncodingRequest(req);     
39             chain.doFilter(er, response);
40         }else if(req.getMethod().equals("POST")){
41             chain.doFilter(request, response);
42         }
43         response.setContentType("text/html;charset=UTF-8");
44     }
45 
46     public void init(FilterConfig fConfig) throws ServletException {
47         // TODO Auto-generated method stub
48     }
49 
50 }
EncodingFilter類
package cn.demo1.baseServlet;

import java.io.UnsupportedEncodingException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
/**
 * 輔助過濾器來處理GET編碼問題
 * @author ZHAOYUQIANG
 *
 */
public class EncodingRequest extends HttpServletRequestWrapper{
private HttpServletRequest request ;
    
    public EncodingRequest(HttpServletRequest request) {
        super(request);
        this.request = request ;
    }
    /**
     * 處理編碼問題
     */
    public String getParameter(String name) {
        String value = request.getParameter(name);
        /*
         * 處理編碼問題
         */
        try {
            value = new String (value.getBytes("ISO-8859-1"),"utf-8");
        } catch (UnsupportedEncodingException e) {
            // TODO Auto-generated catch block
            throw new RuntimeException(e);
        }
        
        return value;
    }

}
EncodingRequest類
1 <filter>
2     <display-name>EncodingFilter</display-name>
3     <filter-name>EncodingFilter</filter-name>
4     <filter-class>cn.demo1.baseServlet.EncodingFilter</filter-class>
5   </filter>
6   <filter-mapping>
7     <filter-name>EncodingFilter</filter-name>
8     <url-pattern>/TestServlet</url-pattern>
9   </filter-mapping>
過濾器的攔截配置

@項目下載

http://files.cnblogs.com/files/zyuqiang/webBlogTest.rar

 


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

-Advertisement-
Play Games
更多相關文章
  • 最近接手的 Apache HUE 項目性能出現了問題,線上經常出現響應時間過長或因為時間過長而無法服務等問題.老大讓我準備弄個性能分析工具,便於追蹤和分析平臺當前的瓶頸出現在哪裡. 那就搞起吧!先從代碼性能分析入手.本篇博客分享的也是代碼層面的性能分析. 之前用過的就有 插件. 這款插件主要可以用來 ...
  • AJAX = Asynchronous JavaScript and XML(非同步的 JavaScript 和 XML)。 Ajax作用:是用JavaScript向伺服器發送非同步請求,然後伺服器給出響應,然後以XML格式的文件返回給瀏覽器端! 非同步:當瀏覽器向伺服器發送請求的時候,不是整個頁面刷新, ...
  • <?php//簡單函數function show(){ echo "hello"; }show(); //有參數的函數function show($a){ echo "$a"; }show("world"); //有返回值的函數 function show(){ return "小V,你好!"; } ...
  • /** * 文檔註釋只定義在三個地方 : 類、常量、方法上 * 在類上定義文檔註釋用來說這個類設計及其解決問題等相關描述信息 * @author 作者 * @version 1.0 21/08/17 版本號 修改的版本號和最後修改 *的時間 * @see java.lang.String 參考的類, ...
  • PHP程式員閱讀Java語言實現設計模式的書,然後用Go語言實現。配以現實生活中的實例,幫助理解設計模式。本篇包括:策略、觀察者、裝飾者、工廠、單例、命令、適配器、外觀。 ...
  • HTTP協議 自從入坑以來,只要是跟web打交道,總是免不了這個HTTP協議,這是什麼鬼,讓我們一探究竟。(不周之處還請賜教!!!) 既然是協議,我們首先要問三個問題,誰跟誰的協議?協議是什麼?怎麼用? 第一個問題: 誰跟誰的協議? 所謂協議,至少需要兩方,甲方and乙方,我們先說下甲方and乙方到 ...
  • 題目鏈接 Problem Description There is a set including all positive integers that are not more then n. HazelFan wants to choose some integers from this set ...
  • what's the 操作系統? 首先,我們要知道,為什麼要有操作系統。現代的電腦系統主要是由一個或者多個處理器,主存、硬碟、鍵盤、滑鼠、顯示器、印表機、網路介面及其他輸入輸出設備組成。現代電腦的組成部分極其複雜,我們不可能全部瞭解完再去寫開發,所以就需要用到操作系統。程式員只需要做自己的本職開 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...