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 原因分析

请求与响应中内容的编码问题 - 图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. 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 getParameterMap();//获取请求对象中携带的所有键值对参数数据
在处理get得到的参数的乱码问题时,需要分别对上面三个进行处理。一般会用过滤器来处理乱码问题。

3 filter过滤器处理乱码问题

用装饰者模式。
实际装饰的是request对象。
无标题.png

  1. package com.itheima.anli00_filter;
  2. import java.io.IOException;
  3. import java.io.UnsupportedEncodingException;
  4. import java.util.Map;
  5. import java.util.Set;
  6. import javax.servlet.Filter;
  7. import javax.servlet.FilterChain;
  8. import javax.servlet.FilterConfig;
  9. import javax.servlet.ServletException;
  10. import javax.servlet.ServletRequest;
  11. import javax.servlet.ServletResponse;
  12. import javax.servlet.http.HttpServletRequest;
  13. import javax.servlet.http.HttpServletRequestWrapper;
  14. import javax.servlet.http.HttpServletResponse;
  15. /**
  16. * 我们自己采用装饰者模式,对reqeust对象进行增强的工具类
  17. */
  18. public class MyEncodingFilter implements Filter {
  19. public void destroy() {
  20. }
  21. public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
  22. //1:将request和response转成子接口类型
  23. HttpServletRequest r = (HttpServletRequest)request;
  24. HttpServletResponse res = (HttpServletResponse)response;
  25. //2:获取请求方式,如果是get请求,则使用装饰者模式解决乱码,如果是post请求,则直接面向原始的request对象,调用setCharacterEncoding方法解决乱码
  26. String method = r.getMethod();
  27. //3:先解决响应乱码问题
  28. res.setContentType("text/html;charset=utf-8");
  29. if("GET".equalsIgnoreCase(method)){
  30. //说明需要使用装饰者
  31. MyRequest z = new MyRequest(r);
  32. //放行,传递装饰后的对象
  33. chain.doFilter(z, res);
  34. }else{
  35. //可以直接解决
  36. r.setCharacterEncoding("utf-8");
  37. chain.doFilter(r, res);
  38. }
  39. }
  40. public void init(FilterConfig fConfig) throws ServletException {
  41. }
  42. }
  43. class MyRequest extends HttpServletRequestWrapper{
  44. //定义一个接口类型的成员变量,用于保存被装饰的对象
  45. private HttpServletRequest request ;
  46. //为了解决多次调用方法的时候,第一次不乱,之后反而乱码的问题,我们需要定义一个flag,让转换的过程仅执行一次
  47. private boolean flag = true;//默认可以进行转换
  48. public MyRequest(HttpServletRequest request) {
  49. super(request);
  50. this.request = request;
  51. }
  52. //增强方法;
  53. //1:增强getParameterMap
  54. public Map<String, String[]> getParameterMap() {
  55. //1:先使用request获取原始的浏览器传递过来的参数
  56. Map<String, String[]> map = request.getParameterMap();
  57. //2:此时如果map中有中文参数,一定是乱码的!!! 仅考虑get请求,post请求直接面向原始对象解决即可
  58. if(flag){
  59. Set<String> set = map.keySet();
  60. for (String key : set) {
  61. String[] vs = map.get(key);
  62. //对数组中的参数进行处理,处理后需要将参数重新保存回数组
  63. for(int i=0;i<vs.length;i++){
  64. //只要对数组的每一个元素进行了修改,那么map中的数组中的元素自然就跟着变化了(已经解决中文乱码了)
  65. try {
  66. vs[i]=new String(vs[i].getBytes("iso8859-1"),"utf-8");
  67. } catch (UnsupportedEncodingException e) {
  68. e.printStackTrace();
  69. throw new RuntimeException();
  70. }
  71. }
  72. }
  73. //修改flag为false
  74. flag = false;
  75. }
  76. //返回已经解决了乱码的map
  77. return map;
  78. }
  79. //重写getParameterValues方法,这个方法中的数据,都可以直接从map中获取,因为map已经解决了乱码
  80. @Override
  81. public String[] getParameterValues(String name) {
  82. return getParameterMap().get(name);
  83. }
  84. @Override
  85. public String getParameter(String name) {
  86. String[] vs = getParameterValues(name);
  87. if(vs==null){
  88. return "";
  89. }
  90. return vs[0];
  91. }
  92. }