前后台乱码问题自己由于也看过相关博客介绍过解决方法,但是自己本地测试后乱码发生的略有不同,故在此作出总结,并附上自己的环境
开发环境idea2019.3,tomcat8, windows7
使用chrome浏览器进行测试
1.前台向后台传送中文字符的情况介绍:
前台代码jsp文件
1 <%@ page contentType="text/html;charset=UTF-8" language="java" %> 2 3 <form action="requestPost.do" method="post"> 4 用户名:<input type="text" name="userName"/> 5 <input type="submit" value="post方式提交表单"> 6 </form> 7 8 <form action="requestGet.do" method="get"> 9 用户名:<input type="text" name="userName"/> 10 <input type="submit" value="get方式提交表单"> 11 </form>
后台代码servlet
1 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 2 3 //获取servletPath 4 String servletPath = request.getServletPath(); 5 //去除路径名后缀名中的.do 6 String methodName = servletPath.substring(1, servletPath.length()-3); 7 try { 8 //利用反射获取methodName对应的方法 9 Method method = getClass().getDeclaredMethod(methodName, HttpServletRequest.class, HttpServletResponse.class); 10 //利用反射调用相应的方法 11 method.invoke(this, request, response); 12 } catch (Exception e) { 13 e.printStackTrace(); 14 response.sendRedirect("error.jsp"); 15 } 16 } 17 18 19 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 20 // TODO Auto-generated method stub 21 doGet(request, response); 22 }
1 private void requestGet(HttpServletRequest request, HttpServletResponse response){ 2 System.out.println("requestGet"); 3 4 String userName = request.getParameter("userName"); 5 System.out.println("直接获取用户名: "+userName); 6 try { 7 request.setCharacterEncoding("UTF-8"); 8 userName = request.getParameter("userName"); 9 System.out.println("设置utf-8编码: "+userName); 10 11 userName = new String(userName.getBytes("ISO8859-1"), "utf-8"); 12 System.out.println("先ISO8859-1接收数据,后转UTF-8编码: "+ userName); 13 14 // response.setHeader("content-type", "text/html; charset=UTF-8"); 15 // response.getWriter().write(userName); 16 } catch (IOException e) { 17 e.printStackTrace(); 18 } 19 20 } 21
结果:
requestGet
直接获取用户名: 小红
设置utf-8编码: 小红
先ISO8859-1接收数据,后转UTF-8编码: ??
1 private void requestPost(HttpServletRequest request, HttpServletResponse response){ 2 System.out.println("requestPost"); 3 String userName = request.getParameter("userName"); 4 System.out.println("直接获取用户名: "+userName); 5 try { 6 request.setCharacterEncoding("UTF-8"); 7 userName = request.getParameter("userName"); 8 System.out.println("设置utf-8编码: "+userName); 9 10 userName = new String(userName.getBytes("ISO8859-1"), "utf-8"); 11 System.out.println("先ISO8859-1接收数据,后转UTF-8编码: "+ userName); 12 13 // response.setHeader("content-type", "text/html; charset=UTF-8"); 14 // response.getWriter().write(userName); 15 } catch (IOException e) { 16 e.printStackTrace(); 17 } 18 19 }
结果:
requestPost
直接获取用户名: ?°????
设置utf-8编码: ?°????
先ISO8859-1接收数据,后转UTF-8编码: 小明
从以上结果可以看出,对于前台的get请求方式,后台不需要对其对任何操作,中文字符不会出现乱码情况;
相反,对于post请求方式,后台需要将先使用先
ISO8859-1接收数据,后转UTF-8编码
才能保证中文不乱码。
另外,如果在web.xml中设置字符编码,则不管是post还是get皆不用做任何处理,下面的设置是防止前端输入的数据到了后台发生乱码现象。
1 <filter> 2 <filter-name>encoding-filter</filter-name> 3 <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> 4 <init-param> 5 <param-name>encoding</param-name> 6 <param-value>UTF-8</param-value> 7 </init-param> 8 <init-param> 9 <param-name>forceEncoding</param-name> 10 <param-value>true</param-value> 11 </init-param> 12 </filter> 13 <filter-mapping> 14 <filter-name>encoding-filter</filter-name> 15 <url-pattern>*.do</url-pattern> 16 </filter-mapping>
2.后台向前台输出带有中文字符的乱码现象:
前台代码:
1 <a href="query.do">Query</a><br/> 2 <a href="delete.do">Delete</a><br/> 3 <a href="update.do">update</a><br/>
后台代码servlet:
1 private void update(HttpServletRequest request, HttpServletResponse response){ 2 System.out.println("update"); 3 try { 4 /* 5 * 当输出数字时,需要将该数字转换成字符串形式,然后转化成字节数组进行输出 6 * 所以,当希望服务器输出什么浏览器就能看到什么,那么服务器端都要以字符串 7 * 的形式进行输出 8 * */ 9 10 response.setHeader("content-type", "text/html; charset=UTF-8"); 11 //response.getOutputStream().write(1);//前台显示不出1 12 response.getOutputStream().write((1+"").getBytes("UTF-8")); 13 } catch (IOException e) { 14 e.printStackTrace(); 15 } 16 } 17 18 private void delete(HttpServletRequest request, HttpServletResponse response){ 19 System.out.println("delete"); 20 try { 21 /* 22 *使用outputStream输出中文注意事项: 23 * 在服务端,数据以哪个码表输出,那么就要控制客户端以相应的码表打开, 24 * 比如response.getOutputStream().write("删除操作".getBytes("UTF-8"));//使用 25 * outputStream流向客户端浏览器输出中文,以utf-8的编码进行输出 26 * 此时就要控制客户端浏览器以utf-8的编码打开,否则前台显示时会出现中文乱码 27 * 可通过设置响应头控制浏览器的行为解决乱码问题: 28 * response.setHeader("content-type", "text/html; charset=UTF-8"); 29 * 通过设置响应头控制浏览器以utf-8的编码显示数据 30 * */ 31 response.setHeader("content-type", "text/html; charset=UTF-8"); 32 /*getbytes()是一个将字符转换成字节数组的过程,这个过程一定会查找码表,如果是 33 中文的操作系统环境,默认就是查找GB2312的码表,将字符转换成字节数组的过程就是将 34 中文转换成GB2312的码表上对应的数字, 35 比如:"中" 在GB2312的码表上对应的数字是98 36 getbytes()如果不带参数,那么就会根据操作系统的语言环境来选择转换码表,如果是中文操作系统, 37 那么就使用GB2312的码表 38 */ 39 response.getOutputStream().write("删除操作".getBytes("UTF-8")); 40 } catch (IOException e) { 41 e.printStackTrace(); 42 } 43 } 44 45 private void query(HttpServletRequest request, HttpServletResponse response){ 46 System.out.println("query"); 47 try { 48 /* 49 * 与outputStream相同 50 * 设置响应头来控制浏览器以指定的字符编码进行显示 51 * response.setHeader("content-type", "text/html; charset=UTF-8"); 52 * 它的等价写法: 53 * response.getWriter().write("<meta http-equiv='content-type' content='text/html'; charset='UTF-8'/>"); 54 * */ 55 response.setHeader("content-type", "text/html; charset=UTF-8"); 56 response.getWriter().write("查询操作"); 57 } catch (IOException e) { 58 e.printStackTrace(); 59 } 60 }
后台向前台输出中文时,不管是使用outputStream还是PrintWriter,只需要添加一句
response.setHeader("content-type", "text/html; charset=UTF-8");
就能够解决乱码问题,同时这里也顺便介绍了如果向前台输出数字时,需要将其转换成字符串再输出,否则会显示不正常。
本文主要参考的孤傲苍狼博客相关内容,但是自己亲自在自己电脑上测试的情况和其中有点不一样,具体差异原因不太清楚。