動態代理解決表單提交的中文亂碼問題

        在上一篇播客中記錄了使用裝飾者設計模式來解決中文亂碼問題,使用這種方式好在有一個已有的基類HttpServletRequestWrapper讓我們繼承,如果沒有這個基類,則需要我們寫大量的代碼。

       而動態代理則能實現用哪個增強哪個,相對於使用裝飾者模式,代碼量簡單,而且代碼格式固定。 

我們經常說增強的方式常用的有:
1.繼承
2.實現
3.動態代理
4.裝飾者設計模式   

什麼是動態代理呢?

       動態代理:在程序運行時  動態創建類  此類代表代理類。

要解決中文亂碼問題,同樣需要過濾器,在過濾器中使用動態代理。

具體代碼如下:

final HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;

request.setCharacterEncoding("utf-8");
HttpServletRequest proxyRequest = (HttpServletRequest) Proxy.newProxyInstance(
		EncodeFilter.class.getClassLoader(),
		request.getClass().getInterfaces(), 
		new InvocationHandler() {
			
			@Override
			public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
				//增強方法名爲getParameter的方法
				if("getParameter".equals(method.getName())){
					//獲取請求方式
					String method2 = request.getMethod();
					//判斷是否爲get請求
					if("GET".equalsIgnoreCase(method2)){
						//轉碼
						String val = request.getParameter(args[0].toString());
						//將轉碼後的結果返回
						return new String(val.getBytes("iso-8859-1"),"utf-8");
					}
				}
				//執行該方法
				return method.invoke(request, args);
			}
		});
//放行
chain.doFilter(proxyRequest, response);
結合上述代碼分析各個參數的意義:

Proxy.newProxyInstance(參數1,參數2,參數3)

        參數1:當前類.getClass.getClassLoader

                     以前沒有 proxyRequest 這個類 動態創建這個類出來 加載到內存 需要用到類加載器。 

        參數2:目標類.getClass.getInterfaces() 獲得接口中的方法

                動態創建的類 沒有方法 方法要和目標類一樣 所以獲得目標的類接口的方法。

        參數3:執行處理類

       代理類的方法跟目標類的方法一樣 但沒有實現,所以要有一個InvocatioHandler

       invoke(Object proxy, Method method, Object[] args)中的三個參數:

  參數1:Object proxy 代理對象
  參數2:Method method 代理對象當前執行的方法的描述對象

參數3:當前執行的方法的實際參數

需要記住的是:目標類每調用一次執行方法 就執行一次代理類的invoke

具體執行流程爲:

        當請求過來時,先經過過濾器,之後過濾器放行,過濾器放行時傳入的request對象時動態代理後的request對象。當進入servlet中時,servlet中調用request.getParameter方法獲取請求的值時,由於這裏的request對象已經換成我們使用動態代理生成的proxyRequest 對象,所以它會進入過濾器中執行new InvocationHandler()中的invoke方法 ,invoke方法中對原有的方法進行增強,從而解決亂碼問題。



 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章