1. 程式人生 > >動態代理解決網站字符集編碼

動態代理解決網站字符集編碼

1、首先看一個裝飾模式解決字符集編碼問題


  我們使用裝飾者對request進行增強,從而使得get和post使用request.getParameter()獲得的資料沒有亂碼:

  首先來一個Servlet,用於處理客戶端請求:

package 裝飾者模式解決亂碼;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class DataServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    public DataServlet() {
        super();
    }

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//獲得資料
		String username = request.getParameter("username");
		String password = request.getParameter("password");
		System.out.println("前:" +username+"@"+password);
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//獲得資料
		String username = request.getParameter("username");
		String password = request.getParameter("password");
		System.out.println("前:" +username+"@"+password);
	}
	
}


  建立HttpServletRequest的增強類,藉助HttpServletRequestWrapper:

package 裝飾者模式解決亂碼;

import java.io.UnsupportedEncodingException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;


/**
 *
 *  sun 提供 HttpServletRequest 介面使用裝飾者編寫預設類,及所有的方法都沒有增強的。
 *  * 之後我們只需要繼承即可
 *  
 *  增強response物件,提供使用裝飾者設計模式編寫預設類:HttpServletResponseWrapper
 */
public class MyRequest extends HttpServletRequestWrapper {
	//保持對介面的引用
	private HttpServletRequest request;
	//構造方法
	public MyRequest(HttpServletRequest request) {
		super(request);
		//賦值
		this.request = request;
	}
	//重寫某個方法
	@Override
	public String getParameter(String name) {
		//首先獲得引數,這是沒有改變編碼的值
		String value =  request.getParameter(name);
		//首先判斷請求方式
		String method = request.getMethod();
		if ("GET".equals(method)) {
			try {
				value = new String(value.getBytes("ISO-8859-1"), "utf-8");
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			}
		}else {
			try {
				request.setCharacterEncoding("utf-8");
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			}
		}
		return value;
	}

}


  在客戶端向伺服器傳送請求時,我們需要對其進行攔截:

package 裝飾者模式解決亂碼;

import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class EncodingFilter implements Filter {

    public EncodingFilter() {
    }

	public void destroy() {
	}

	public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
		//強轉
		HttpServletRequest request = (HttpServletRequest) req;
		HttpServletResponse response = (HttpServletResponse) res;
		//post編碼
		response.setCharacterEncoding("UTF-8");
		//使用裝飾者模式增強
		MyRequest myRequest = new MyRequest(request);
		//放行
		chain.doFilter(myRequest, response);
		System.out.println("我是中國人!");
		

			/*//0 強轉
			HttpServletRequest request = (HttpServletRequest) req;
			HttpServletResponse response = (HttpServletResponse) resp;			
			//1 post亂碼
			request.setCharacterEncoding("UTF-8");		
			//2 使用裝飾者增強request
			MyRequest myRequest = new MyRequest(request);		
			chain.doFilter(myRequest, response);*/
			
	}

	public void init(FilterConfig fConfig) throws ServletException {
	}

}

2、動態代理解決


  客戶端頁面:

<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>動態代理解決get方式亂碼問題</title>
</head>
<body>
	<form action="/proxy/DataServlet" method="get">
		使用者名稱:<input type="text" name="username" value="胡根得" /><br/>
		密碼:<input type="password" name=password value="就不告訴你"><br/>
		<input type="submit" value="提交get請求">
	</form>
</body>
</html>

  寫一個Servlet:

package solveresponseencoding;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/DataServlet")
public class DataServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    public DataServlet() {
        super();
    }

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//獲得請求引數
		String username = request.getParameter("username");
		String password = request.getParameter("password");
		//列印值
		System.out.println(request.getMethod() + " : " + username + " @ " + password);
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doGet(request, response);
	}

}


  對請求進行攔截的過濾器:

<span style="font-size:18px;">package solveresponseencoding;

import java.io.IOException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebFilter("/*")
public class EncodingFilter implements Filter {

    public EncodingFilter() {
    }

	public void destroy() {
	}
	/*
	 * 本方法會攔截所有請求,在本方法中對request進行增強
	 */
	public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
		//強轉
		final HttpServletRequest request = (HttpServletRequest) req;
		HttpServletResponse response = (HttpServletResponse) res;
		//解決post亂碼
		request.setCharacterEncoding("utf-8");
		//建立動態代理物件
		HttpServletRequest myRequest = (HttpServletRequest) Proxy.newProxyInstance(
				EncodingFilter.class.getClassLoader(), 
				new Class[]{HttpServletRequest.class},
				new InvocationHandler() {
					
					@Override
					public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
						//如果是getParameter方法,獲取引數
						if ("getParameter".equals(method.getName())) {
							String value = request.getParameter((String)args[0]);
							//System.out.println("value值為:"+value);
							//如果是get請求,就增強
							if ("GET".equalsIgnoreCase(request.getMethod())) {
								value = new String(value.getBytes("ISO-8859-1"), "utf-8");
								System.out.println("我是get方法:");
							}
							return value;
						}
						return method.invoke(request, args);
					}
				});
		chain.doFilter(myRequest, response);
	}

	public void init(FilterConfig fConfig) throws ServletException {
	}

}
</span>


  動態代理解決這個問題,將增強放到了過濾器中,不同之處他沒有專門的增強類,而是通過動態代理技術在執行期間動態生成的,對於InvocationHandler介面採用了匿名內部類的方式。