1 从服务器响应回浏览器的中文编码问题(response)
告诉浏览器,服务器响应回来的数据类型与编码格式。
设置中文编码:
response.setCharacterEncoding(“utf-8”);
response.setHeader(“Content-Type”,”text/html”);
或
response.setHeader(“Content-Type”,”text/html;charset=utf-8”);
实际开发中的使用的设置中文编码:
response.setContentType(“text/html;charset=utf-8”);
2 获取的从浏览器向服务器发送的数据(request)
2.1 post请求中参数中文乱码问题:
解决方式: request.setCharacterEncoding(“utf-8”);
2.2 get请求中参数中文乱码问题
2.2.1 原因分析
2.2.2 相关String类的构造方法和方法
String中的方法:
public byte[] | getBytes(Charset charset)
使用给定的 charset 将此 String 编码到 byte 序列,并将结果存储到新的 byte 数组。
String的构造方法:
public String(byte[] bytes, Charset charset)
通过使用指定的 charset 解码指定的 byte 数组,构造一个新的 String。新 String 的长度是字符集的函数,因此可能不等于 byte 数组的长度。
2.2.3 解决方案步骤:
1:使用乱码后的字符串用iso8859-1的编码格式进行编码会得到原来的字节数组。<br /> 2:使用字节数组,加utf-8的编码格式,进行解码,就会得到原来乱码前的原始字符串。
2.2.4 代码格式:
String 不乱的字符串=new String(乱码后的字符串.getBytes(“iso8859-1”),”utf-8”);
2.2.5 注意事项:
上述解决方案实际上是一个通用的解决方案。(无论get还是post都会生效),在实际开发中出于对性能的考虑,通常会分开处理get和post的中文乱码问题。
2.2.6 编写代码时要解决的乱码的三个方法
在HTTPServletRequest这个接口中,对操作请求体进行了优化,优化后一共封装了3个方法,可以直接使用这3个方法获取request对象中的参数:
String getParameter(“属性名”);// 仅根据一个名字获取一个值使用
String[] getParameterValues(“属性名”);//根据一个名字获取一个数组值使用,例如: 爱好
Map
在处理get得到的参数的乱码问题时,需要分别对上面三个进行处理。一般会用过滤器来处理乱码问题。
3 filter过滤器处理乱码问题
用装饰者模式。
实际装饰的是request对象。
package com.itheima.anli00_filter;import java.io.IOException;import java.io.UnsupportedEncodingException;import java.util.Map;import java.util.Set;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.HttpServletRequestWrapper;import javax.servlet.http.HttpServletResponse;/*** 我们自己采用装饰者模式,对reqeust对象进行增强的工具类*/public class MyEncodingFilter implements Filter {public void destroy() {}public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {//1:将request和response转成子接口类型HttpServletRequest r = (HttpServletRequest)request;HttpServletResponse res = (HttpServletResponse)response;//2:获取请求方式,如果是get请求,则使用装饰者模式解决乱码,如果是post请求,则直接面向原始的request对象,调用setCharacterEncoding方法解决乱码String method = r.getMethod();//3:先解决响应乱码问题res.setContentType("text/html;charset=utf-8");if("GET".equalsIgnoreCase(method)){//说明需要使用装饰者MyRequest z = new MyRequest(r);//放行,传递装饰后的对象chain.doFilter(z, res);}else{//可以直接解决r.setCharacterEncoding("utf-8");chain.doFilter(r, res);}}public void init(FilterConfig fConfig) throws ServletException {}}class MyRequest extends HttpServletRequestWrapper{//定义一个接口类型的成员变量,用于保存被装饰的对象private HttpServletRequest request ;//为了解决多次调用方法的时候,第一次不乱,之后反而乱码的问题,我们需要定义一个flag,让转换的过程仅执行一次private boolean flag = true;//默认可以进行转换public MyRequest(HttpServletRequest request) {super(request);this.request = request;}//增强方法;//1:增强getParameterMappublic Map<String, String[]> getParameterMap() {//1:先使用request获取原始的浏览器传递过来的参数Map<String, String[]> map = request.getParameterMap();//2:此时如果map中有中文参数,一定是乱码的!!! 仅考虑get请求,post请求直接面向原始对象解决即可if(flag){Set<String> set = map.keySet();for (String key : set) {String[] vs = map.get(key);//对数组中的参数进行处理,处理后需要将参数重新保存回数组for(int i=0;i<vs.length;i++){//只要对数组的每一个元素进行了修改,那么map中的数组中的元素自然就跟着变化了(已经解决中文乱码了)try {vs[i]=new String(vs[i].getBytes("iso8859-1"),"utf-8");} catch (UnsupportedEncodingException e) {e.printStackTrace();throw new RuntimeException();}}}//修改flag为falseflag = false;}//返回已经解决了乱码的mapreturn map;}//重写getParameterValues方法,这个方法中的数据,都可以直接从map中获取,因为map已经解决了乱码@Overridepublic String[] getParameterValues(String name) {return getParameterMap().get(name);}@Overridepublic String getParameter(String name) {String[] vs = getParameterValues(name);if(vs==null){return "";}return vs[0];}}
