而動態代理則能實現用哪個增強哪個,相對於使用裝飾者模式,代碼量簡單,而且代碼格式固定。
我們經常說增強的方式常用的有:
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方法中對原有的方法進行增強,從而解決亂碼問題。