浏览器与服务器交互的过程中,不可缺少的就是服务器从浏览器获取数据,服务器再返回给浏览器数据,在这个交互的过程中,经过了Http协议,而这个协议的编码形式和浏览器和服务器的编码形式是不同的,这时,就会产生交互过程的乱码,我们该如何解决这个问题呢?今天就此问题进行解决。
【单独处理】
一般提交数据采用的是GET或POST方法,这两种方式处理乱码是不同的。虽然代码不多,也就一句话就能解决问题,但是如果提交的数据很多,GET方式处理起来就太过于麻烦了,所以下面我们采用统一处理的方法来一起处理,就不需要一一单独解决了。
GET:
new String(value.getBytes("iso-8859-1"),"utf-8");
POST:
request.setCharacterEncoding("utf-8");
【统一处理】
1、过滤器(装饰者模式)
装饰类MyHttpServletResquest
被装饰类HttpServletRequestWrapper(提供里直接实现)、HttpServletRequest(接口需要将不需要增强的方法按照原来的方法进行执行,这样比较麻烦,所以用HttpServletRequestWrapper直接)。
注意点:增强类需要实现被增强类实现的所有接口;增强类必须在内部能够获得到被增强类引用。
//装饰者模式
public class MyHttpServletRequest extends HttpServletRequestWrapper{
private HttpServletRequest request;
//构造方法
public MyHttpServletRequest(HttpServletRequest request) {
super(request);
this.request=request;
}
@Override
public String getParameter(String name) {
//得到原来获取的值
String myName = request.getParameter(name);
//根据请求方式进行编码
if(request.getMethod().equalsIgnoreCase("get")){
try {
return new String(myName.getBytes("iso-8859-1"),"utf-8");
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return myName;
}
}
过滤器Filter
public void doFilter(ServletRequest req, ServletResponse response, FilterChain chain) throws IOException, ServletException {
//强转
HttpServletRequest request=(HttpServletRequest)req;
//统一处理
request.setCharacterEncoding("utf-8");
//实例化自己定义类,进行装饰原来的HttpServletRequest
MyHttpServletRequest myRequest=new MyHttpServletRequest(request);
//将装饰者myRequest的类传递下去
chain.doFilter(myRequest, response);
}
Servlet
String username = request.getParameter("username");
String password = request.getParameter("password");
System.out.println(username+"@"+password);
2、动态代理+过滤器
Proxy.newProxyInstance实例出代理者
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
//GET和POST提交都是HttpServletRequest、HttpServletResponse
//强制转换 final
final HttpServletRequest request=(HttpServletRequest)req;
HttpServletResponse response=(HttpServletResponse)resp;
try {
//统一设置编码
request.setCharacterEncoding("utf-8");
//代理者proxyRequest
HttpServletRequest proxyRequest=(HttpServletRequest)Proxy.newProxyInstance(
//创建类proxyRequest不在内存中,让类加载器加载,保证这个类在内存中加载一次
EncodingFilter.class.getClassLoader(),
//创建的类proxyRequest没有方法,通过被代理者,获得方法
request.getClass().getInterfaces(),
//写增强方法
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String requestMethod = request.getMethod();
if(requestMethod.equals("GET")){
String name = method.getName();
if(name.equals("getParameter")){
String value=request.getParameter(args[0].toString());
return new String(value.getBytes("iso-8859-1"),"utf-8");
}
}
return method.invoke(request, args);
}
});
chain.doFilter(proxyRequest, response);
} catch (Exception e) {
e.printStackTrace();
}
}
所谓动态代理,就是动态创建代理类,来代替被代理者处理问题,并且能处理的更好。举个不知道恰不恰当的例子,但能让我理解的例子吧。
举例:小明要买一台笔记本电脑,可以从厂家直接买到裸机。他也可以跟代理商购买,这样小明买到的不仅仅是裸机了,还佩戴了耳机、鼠标、贴膜,甚至是所谓正版激活的office等。虽然这样比跟厂家直接买花销会多一些,但也获得了更多的东西,更优质的服务,所以众多小明应该会选择从代理商那里购买电脑咯。
正如我们采用代理者处理乱码添加了过滤器,虽然这样服务器接受到请求需要先经过过滤器处理,降低了效率,但是能够统一处理乱码,大大减轻了一一处理乱码的繁琐压力,何乐而不为呢?