jsp中Get提交方式的中文乱码解决办法
在jsp页面中,设置页面的存储编码和页面输出时的编码:
<%@page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
这样,就统一了编码为utf-8。
这种方式在post提交表单中含有中文时没有问题。但是在用get提交时,如果含有中文,就会出现类似于“?? ?”的乱码问题。为什么会这样呢?
自从Tomcat5.x开始,GET和POST方法提交的信息,Tomcat采用了不同的方式来处理编码,
对于POST请求,Tomcat会仍然使用request.setCharacterEncoding方法所设置的编码来处理,如果未设置,则使用默认的iso-8859-1编码。
而GET请求,则不同,Tomcat对于GET请求并不会考虑使用request.setCharacterEncoding方法设置的编码,而会永远使用iso-8859-1编码。
添加一句:URIEncoding="UTF-8"
由:
变为
使用
String name=
newString(request.getParameter("name").getBytes("ISO-8859-1"),"utf-8");转化编码
说明:将request方式获得name,进行解码:通过ISO-8859-1的方式去解码[字符串-->字节数组的过程,就是解码的过程]。然后另一种编码方式:utf-8的编码方式去编码[字节数组—>字符串的过程,就是编码的过程],从而获得正确的中文参数。
分析:因为get提交过来的参数,默认采取的是:iso-8859-1编码。而我们要知道很重要的一点是:iso-8859-1是单字节编码,本身不识别中文。
因此我们要正确获取传递过来的中文参数,首先要以iso-8859-1解码,将字符串还原成传递过来前的字符数组形式。然后再选择一种编码,可以识别的编码:utf-8,从而获得了传递过来的中文参数。
推荐使用第二种方式。
方案1和方案2的解决:都是针对tomcat服务器里的server.xml文件里,未曾设置过URIEncoding参数,
即:配置文件里是以下这样的。
反过来说:
如果在tomcat服务器里的server.xml文件设置过URIEncoding参数
这时候就不用考虑方案1和方案2。
解释:
因为此种方法正是方案1的做法,而且是一劳永逸的方法。配置了参数:URIEncoding="UTF-8"。这时候get方式传递过来的中文参数,就不会出现乱码问题了。因此,这时候就无需考虑方案2的做法,因为已经修改了get请求的默认编码:iso-8859-1编码为utf-8了。
因此,如果此时:在获取参数时,写上这行代码:
String name=
newString(request.getParameter("name").getBytes("ISO-8859-1"),"utf-8");以此来转化编码,就会出现乱码问题。
因为:name是通过utf-8进行编码的,而此时通过ISO-8859-1去进行解码,就会出现解码错误的情况,而解码出错的情况下,有通过utf-8去进行编码,来获得传递过来的中文参数:name,就会出现乱码情况。
所以,我们出先乱码时,看看server.xml间种是否对URIEncoding参数进行了配置,从而找出问题所在。
public void doGet(HttpServletRequest request,HttpServletResponse response)
throws ServletException, IOException {
String name = request.getParameter("name");// 获取参数
// name 以iso8859-1的方式编码为字节数组【字符-->字节】,然后以utf-8的方式解码为字符串【字节-->字符】
name = new String(name.getBytes("ISO-8859-1"), "UTF-8");
System.out.println("解码后---name:" + name);
}
其中总过包括:
(1)GetAndPost.jsp 【测试页面】 (2)RequestServlet2 【servlet】
(3)RequestFilter 【请求过滤器】(4)MyHttpServletRequestWrapper 【request增强类】
(5)web.xml页面配置
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
get方式请求
post方式请求
package com.zhku.jsj144.zk.filter.requestFilter;
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 RequestServlet2 extends HttpServlet{
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String name = request.getParameter("name");// 获取参数
//name 以iso8859-1的方式编码为字节数组【字符-->字节】, 然后以utf-8的方式解码为字符串【字节-->字符】
//name= new String(name.getBytes("ISO-8859-1"), "UTF-8");
System.out.println("解码后---name:"+ name);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request,response);
}
}
package com.zhku.jsj144.zk.filter.requestFilter;
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;
//解决全站的请求数据的乱码问题的过滤器
//获取参数的三种方式
//request.getParameter("");
//request.getParameterNames();
//request.getParameterMap();
public class RequestFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void destroy() {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse resp = (HttpServletResponse) response;
System.out.println("开始工作。。。。。。。。。。。。。。。。");
// String method = req.getMethod();//获取请求参数的方法
// //get方式请求
// if("get".equals(method)){
// 思路:获取参数有三种方式,我们的目的:就是对这三种方式进行改写:即增强它们的功能
// 装饰者模式,我们的思路时加强request,然后把加强后的request传递下去,这样,
// 在使用加强后的request的获得参数的三种方法,就可以获得设置编码后的,正确的中文参数了。
// ServletAPI
// 中提供了一个request对象的Decorator设计模式的默认实现类HttpServletRequestWrapper
// 注意:HttpServletRequestWrapper类实现了request 接口中的所有方法,
// 但这些方法的内部实现都是仅仅调用了一下所包装的的 request 对象的对应方法
// 我们继承:HttpServletRequestWrapper,然后达到自己的目的
MyHttpServletRequestWrapper myRequest = new MyHttpServletRequestWrapper(
req);
// req.setCharacterEncoding("utf-8");
// chain.doFilter(req,resp);//放行
// 增强后的request:myRequest--然后放行
chain.doFilter(myRequest, resp);// 放行
// }
// //post方式请求
// else{
// req.setCharacterEncoding("utf-8");
// chain.doFilter(req,resp);//放行
// }
}
}
package com.zhku.jsj144.zk.filter.requestFilter;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
//获取参数的三种方式
//方法1:request.getParameter(""); 返回类型:String
//方法2:request.getParameterNames(); 返回类型:String【】
//方法3:request.getParameterMap(); 返回类型:Map
//思路分析:重心放在方法3:request.getParameterMap();因为此方法,实际功能涵盖了方法1和方法2
//把方法3实现了,然后方法1和方法2调用方法3就可以了
//注意:通用方法getParameterMap是存在弊端的。
//因为当servlet种存在几行请求参数代码时:
//request.getParamger("aaa");request.getParamger("bbb");request.getParamger("ccc");
//每行代码都会:调用getParameterMap()方法,因此,每行代码执行时,都会获得三个参数:aaa,bbb,ccc的中文参数值,
//相当于:values[i]=newString(values[i].getBytes("iso-8859-1"),"utf-8");这行代码执行三次
//解释:代码执行第一次:中文参数,用iso-8859-1进行解码,然后用utf-8进行编码【因为一开始获得中文参数时是默认:iso-8859-1进行编码的】,所以
//此时是得到了正确的中文参数。 代码执行第二次:把正确的中文参数【utf-8编码过来的数值】,用iso-8859-1进行解码,然后用utf-8进行编码,此时
//获得了错误的中文参数,因为那个正确的中文参数,再次进行编码,解码用的是不同的码表,所以会出现乱码现象。 同理,代码执行第三次,也是跟代码执行第二次
//一样的结果,获得乱码。
//因此,我们要保证的是,对于获取过来的参数,我们只能获取一次,这样我们就可以获得正确的中文参数值了。
//解决思路:设置bool值,保证只进行一次获取,从而保证编码,解码的正确性。
//private boolean firstGet=false;//设置的bool数值
public class MyHttpServletRequestWrapper extends HttpServletRequestWrapper {
// 目的:获得原有的requset
private HttpServletRequest request;
// 有参构造函数,将原来的request获取,然后进行相关的加强后返回
public MyHttpServletRequestWrapper(HttpServletRequest request) {
super(request);
this.request = request;
}
@Override
public String getParameter(String name) {
Map map = getParameterMap();// 调用 getParameterMap()方法
String[] values = map.get(name);
// 要进一步判断是否为空
if (values != null) {
String value = values[0];// 返回数组的第一个元素
return value;
}
return null;
// return super.getParameter(name);
}
@Override
public String[] getParameterValues(String name) {
Map map = getParameterMap();// 调用 getParameterMap()方法
String[] values = map.get(name);
return values;
// return super.getParameterValues(name);
}
// 成员变量的bool数值,相当于一个全局变量
private boolean firstGet = false;// 设置的bool数值
// 默认是false,再调用一次后,即甚至为true。即不会第二次调用该方法
@Override
public Map getParameterMap() {
if (firstGet == false) {// 只有在第一次时,才会进行调用的操作
// 对于get和post的请求方式做不同的处理
String method = request.getMethod();
// post的请求方式
if ("post".equalsIgnoreCase(method)) {
try {
request.setCharacterEncoding("utf-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return super.getParameterMap();
}
// get的请求方式
else {
Map maps = request.getParameterMap();// 所有参数
Map newMaps = new HashMap();// 保存修改后的数据
// 遍历获取到的所有参数
for (int i = 0; i < maps.size(); i++) {
Set keySet = maps.keySet();
for (String key : keySet) {
String[] values = maps.get(key);// 得到数值
// 对数值进行重新编码,解码
for (int j = 0; j < values.length; j++) {
try {
values[i] = new String(
values[i].getBytes("iso-8859-1"),
"utf-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
// 因为java.util.Map所包装的HttpServletRequest对象的参数是不可改变的,
// 强行更改就会报java.lang.IllegalStateException:
// Nomodifications are allowed to a locked
// ParameterMap异常,
// 这个时候就会通过间接更改值的方式解决这个问题
// 所以 此段代码作废: maps.put(key, values);//maps对于原来的可以进行覆盖
// 正确思路:是重新new一个新的map,然后进行赋值,最后进行返回,即可达到要求
newMaps.put(key, values);// 用新的map进行保存
}
}
firstGet = true;// 设置为true后,是为了避免二次使用
// return maps;
return newMaps;// 修改后的maps
}
}
// 由于已经调用过了,所以直接返回上一次的数值即可,无须做任何处理
return super.getParameterMap();
}
}
RequestServlet
com.zhku.jsj144.zk.filter.requestFilter.RequestServlet
RequestServlet2
/requestServlet2