一个请求:http://localhost:8080/FilterTest/ServletTest?name=%E4%B8%AD%E6%96%87 传送到Web服务器是不带编码的,可是web容器解码是有默认处理的编码,Tomcat就是用"ISO-8859-1"解码的,而后将请求交给相应的Servlet类处理。html
因此咱们能够写一个过滤器,在请求传给相应的Servlet类处理以前改变其编码。java
下面是一个简单的Demo。web
代码:数组
package cn.xiaol.servlet; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * @date 建立时间:2016年10月15日 下午11:15:10 * @Description TODO */ public class ServletTest extends HttpServlet { protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String name = req.getParameter("name"); System.out.println("GET后台打印:" + name); resp.getWriter().println("GET前台打印" + name); } protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String name = req.getParameter("name"); System.out.println("POST后台打印:" + name); resp.getWriter().println("POST前台打印" + name); } }
web.xml:服务器
<servlet> <servlet-name>ServletTest</servlet-name> <servlet-class>cn.xiaol.servlet.ServletTest</servlet-class> </servlet> <servlet-mapping> <servlet-name>ServletTest</servlet-name> <url-pattern>/ServletTest</url-pattern> </servlet-mapping>
请求后的结果:app
GET????涓枃
接下来,咱们写一个过滤器:ide
package cn.xiaol.filter; 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; /** * @date 建立时间:2016年10月16日 上午12:51:10 * @Description 编码过滤器 */ public class CharSetFilter implements Filter { // 默认编码为UTF-8 private String charset = "UTF-8"; @Override public void destroy() { } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { // 处理响应编码,不设置的话,后台打印显示中文,可是返回到前台的是乱码 response.setContentType("text/html;charset=UTF-8"); HttpServletRequest req = (HttpServletRequest) request; if (req.getMethod().equalsIgnoreCase("GET")) { if (!(req instanceof RequestWrapper)) { // 处理Get请求编码 // 用装饰者request替换了本来的request,执行过滤链 req = new RequestWrapper(req, charset); } } else { // 处理Post请求编码 req.setCharacterEncoding(charset); } // 用装饰者request替换了本来的request,执行过滤链 chain.doFilter(req, response); } @Override public void init(FilterConfig config) throws ServletException { // 从web.xml中读取编码信息 String charset = config.getInitParameter("charset"); // 若是不为空就替换咱们默认的UTF-8 if (charset != null && !charset.isEmpty()) { this.charset = charset; } } }
全部的request进来后,先判断是否是GET请求,若是不是就直接设置编码,放行。不然就替换成装饰模式的RequestWrapper。之因此要替换成RequestWrapper,是由于RequestWrapper做为装饰者,它的大部分方法咱们都不重写,只重写其中咱们想要改变的方法。post
下面是RequestWrapper的代码:this
package cn.xiaol.filter; import java.io.UnsupportedEncodingException; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; /** * @date 建立时间:2016年10月16日 上午12:09:12 * @Description 这是使用装饰模式后的request类 */ public class RequestWrapper extends HttpServletRequestWrapper { // 存放传进来的HttpServletRequest对象 private HttpServletRequest request; // 编码格式 private String charset; /** * 为了方便设置编码格式,增长一个编码格式入参 * * @param request * @param charset */ public RequestWrapper(HttpServletRequest request, String charset) { // 把引用传一份给父类,由于父类也是一个装饰者,实现了咱们不想重写的方法 super(request); this.request = request; this.charset = charset; } @Override public String getParameter(String key) { String value = request.getParameter(key); if (value == null)// 若是value为null就返回null return null; try { // Get请求的时候实际上是没有带编码格式的,是Web服务器,也就是Tomcat默认采用了ISO-8859-1 // 因此先用ISO-8859-1取数据,再转为UTF-8 return new String(value.getBytes("ISO-8859-1"), charset); } catch (UnsupportedEncodingException e) { throw new RuntimeException(e); } } @SuppressWarnings({ "unchecked", "rawtypes" }) @Override public Map getParameterMap() { Map<String, String[]> map = request.getParameterMap(); if (map == null) { return map; } for (String key : map.keySet()) {// 遍历全部的key String[] values = map.get(key);// 获得key的value字符串数组 for (int i = 0; i < values.length; i++) {// 遍历value字符串数组,设置编码 try { values[i] = new String(values[i].getBytes("ISO-8859-1"), charset); } catch (UnsupportedEncodingException e) { throw new RuntimeException(e); } } } return map; } }
这里重写了getParameter和getParameterMap方法,由于咱们须要用这些方法得到前台传入的参数。编码
web.xml:
<filter> <filter-name>CharsetFilter</filter-name> <filter-class>cn.xiaol.filter.CharSetFilter</filter-class> <!-- init-param初始化参数能够不给,由于在Filter中设置了默认编码为UTF-8 --> <init-param> <param-name>charset</param-name> <param-value>UTF-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>CharsetFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
请求后的结果:
GET前台打印中文
最后在这里提一下,get请求是将数据放入rul中,而后对中文进行UTF-8编码,再进行ISO-8859-1编码(为了缩短字符),然传给Web服务器。因此RequestWrapper中将传入参数先用ISO-8859-1编码getBytes获得byte数组,再用UTF-8转为String。
而post请求,是把数据进行UTF-8编码而后放在http请求体中传给服务器,因此CharSetFilter中,直接req.setCharacterEncoding("UTF-8")就能够正确显示中文了。
下面给出完整的Demo: