jsp中Get提交方式的中文乱码解决办法

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编码。

三、针对问题的思考及其解决方案

1、方案1:配置tomcat的配置文件server.xml里这句:】

添加一句:URIEncoding="UTF-8"

由:

变为

2、方案2【设置解码编码方式】

使用

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参数进行了配置,从而找出问题所在。

 

五、servlet、过滤器解决编码问题

1、情况一:URIEncoding参数未设置【默认iso-8859-1】

【1】servlet

 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);
   }

【2】过滤器

其中总过包括:

(1)GetAndPost.jsp  【测试页面】 (2)RequestServlet2  【servlet】

(3)RequestFilter 【请求过滤器】(4)MyHttpServletRequestWrapper 【request增强类】

(5)web.xml页面配置  

(1)GetAndPost.jsp  【测试页面】

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>







	
	get方式请求
	
姓名:
post方式请求
姓名:


(2)RequestServlet2  【servlet】

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);
     }
 
}


(3)RequestFilter 【请求过滤器】

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);//放行
		// }
	}

}

(4)MyHttpServletRequestWrapper 【request增强类】

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();
	}
}

(5)web.xml页面配置   

 

 
    RequestServlet
com.zhku.jsj144.zk.filter.requestFilter.RequestServlet
  
  
    RequestServlet2
    /requestServlet2

 
  
    
                    

你可能感兴趣的:(javaweb学习)