1 说明
  乱码问题:
    获取请求参数中的乱码问题;
      POST请求:request.setCharacterEncoding(“utf-8”);
      GET请求:new String(request.getParameter(“xxx”).getBytes(“iso-8859-1”), “utf-8”);
    响应的乱码问题:response.setContextType(“text/html;charset=utf-8”)。

  基本上在每个Servlet中都要处理乱码问题,所以应该把这个工作放到过滤器中来完成。

2 分析
  其实全站乱码问题的难点就是处理GET请求参数的问题。
  如果是POST请求,当执行目标Servlet时,Servlet中调用request.getParameter()方法时,就会根据request.setCharacterEncoding()设置的编码来转码!这说明在过滤器中调用request.setCharacterEncoding()方法会影响在目标Servlet中的request.getParameter()方法的行为!
  但是如果是GET请求,我们又如何能影响request.getParameter()方法的行为呢?这是不好做到的!我们不可能先调用request.getParameter()方法获取参数,然后手动转码后,再施加在到request中!因为request只有getParameter(),而没有setParameter()方法。

  处理GET请求参数编码问题,需要在Filter中放行时,把request对象给“调包”了,也就是让目标Servlet使用我们“调包”之后的request对象。这说明我们需要保证“调包”之后的request对象中所有方法都要与“调包”之前一样可以使用,并且getParameter()方法还要有能力返回转码之后的参数。

  这可能让你想起了“继承”,但是这里不能用继承,而是“装饰者模式(Decorator Pattern)”!
    下面是三种对a对象进行增强的手段:
      继承:AA类继承a对象的类型:A类,然后重写fun1()方法,其中重写的fun1()方法就是被增强的方法。但是,继承必须要知道a对象的真实类型,然后才能去继承。如果我们不知道a对象的确切类型,而只知道a对象是IA接口的实现类对象,那么就无法使用继承来增强a对象了;
      装饰者模式:AA类去实现a对象相同的接口:IA接口,还需要给AA类传递a对象,然后在AA类中所有的方法实现都是通过代理a对象的相同方法完成的,只有fun1()方法在代理a对象相同方法的前后添加了一些内容,这就是对fun1()方法进行了增强;
      动态代理:动态代理与装饰者模式比较相似,而且是通过反射来完成的。

  对request对象进行增强的条件,刚好符合装饰者模式的特点!因为我们不知道request对象的具体类型,但我们知道request是HttpServletRequest接口的实现类。这说明我们写一个类EncodingRequest,去实现HttpServletRequest接口,然后再把原来的request传递给EncodingRequest类!在EncodingRequest中对HttpServletRequest接口中的所有方法的实现都是通过代理原来的request对象来完成的,只有对getParameter()方法添加了增强代码!
  JavaEE已经给我们提供了一个HttpServletRequestWrapper类,它就是HttpServletRequest的包装类,但它做任何的增强!你可能会说,写一个装饰类,但不做增强,其目的是什么呢?使用这个装饰类的对象,和使用原有的request有什么分别呢?HttpServletRequestWrapper类虽然是HttpServletRequest的装饰类,但它不是用来直接使用的,而是用来让我们去继承的!当我们想写一个装饰类时,还要对所有不需要增强的方法做一次实现是很心烦的事情,但如果你去继承HttpServletRequestWrapper类,那么就只需要重写需要增强的方法即可了。

代码示例:

 import java.io.UnsupportedEncodingException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper; /**
* 装饰reqeust
*/
public class EncodingRequest extends HttpServletRequestWrapper {
private HttpServletRequest req;
public EncodingRequest(HttpServletRequest request) {
super(request);
this.req = request;
} public String getParameter(String name) {
String value = req.getParameter(name);
// 处理编码问题
try {
value = new String(value.getBytes("iso-8859-1"), "utf-8");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
return value;
}
}

EncodingRequest

 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; public class EncodingFilter implements Filter {
public void destroy() {} public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
// 处理post请求编码问题
request.setCharacterEncoding("utf-8");
HttpServletRequest req = (HttpServletRequest) request;
/*
* 处理GET请求的编码问题
* 调包request
* 1. 写一个request的装饰类
* 2. 在放行时,使用我们自己的request
*/
if(req.getMethod().equals("GET")) {
EncodingRequest er = new EncodingRequest(req);
chain.doFilter(er, response);
} else if(req.getMethod().equals("POST")) {
chain.doFilter(request, response);
}
} public void init(FilterConfig fConfig) throws ServletException {}
}

EncodingFilter

 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 AServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
String username = request.getParameter("username");
response.getWriter().println(username);
} public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
String username = request.getParameter("username");
response.getWriter().println(username);
}
}

AServlet

 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>"> <title>My JSP 'index.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
</head> <body>
<a href="<c:url value='/AServlet?username=张三'/>">点击这里</a><br/>
<form action="<c:url value='/AServlet'/>" method="post">
用户名:<input type="text" name="username" value="李四"/>
<input type="submit" value="提交"/>
</form>
</body>
</html>

index.jsp

 <?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
<display-name></display-name>
<servlet>
<servlet-name>AServlet</servlet-name>
<servlet-class>AServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>AServlet</servlet-name>
<url-pattern>/AServlet</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<filter>
<display-name>EncodingFilter</display-name>
<filter-name>EncodingFilter</filter-name>
<filter-class>EncodingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>EncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>

web.xml

filter应用案例三:解决全站编码问题的更多相关文章

  1. Java_Web学习笔记_过滤器应用案例(解决全站字符乱码)

    解决全站字符乱码(POST和GET中文编码问题) servlet: l  POST:request.setCharacterEncoding(“utf-8”); l  GET: String user ...

  2. JavaWeb乱码问题及统一全站编码(通过Filter实现)

    1. public class CharacterFilter implements Filter { private String characterEncoding = null; FilterC ...

  3. javaweb的Filter过滤器设置全站编码

    FIlter配置全站编码有一种方法是重写getParameter方法,也就是继承HttpServletRequestWrapper在重写getParameter方法,还有一种就是如下: public ...

  4. Filter学习(三)Filter(过滤器)常见应用

    一.统一全站字符编码 通过配置参数charset指明使用何种字符编码,以处理Html Form请求参数的中文问题: package com.web.filter; import java.io.IOE ...

  5. 案例学python——案例三:豆瓣电影信息入库

    闲扯皮 昨晚给高中的妹妹微信讲题,函数题,小姑娘都十二点了还迷迷糊糊.今天凌晨三点多,被连续的警报声给惊醒了,以为上海拉了防空警报,难不成地震,空袭?难道是楼下那个车主车子被堵了,长按喇叭?开窗看看, ...

  6. 【转】关于URL编码/javascript/js url 编码/url的三个js编码函数

    来源:http://www.cnblogs.com/huzi007/p/4174519.html 关于URL编码/javascript/js url 编码/url的三个js编码函数escape(),e ...

  7. 关于URL编码/javascript/js url 编码/url的三个js编码函数

    关于URL编码/javascript/js url 编码/url的三个js编码函数escape(),encodeURI(),encodeURIComponent() 本文为您讲述关于js(javasc ...

  8. 七、Dockerfile案例三(Mysql安装)

    七.Dockerfile案例三(Mysql安装) *特别提醒:新版的mysql:5.7数据库下的user表中已经没有Password字段了(5.5的user表还有) 一.查看docker hub上的版 ...

  9. iptables filter表案例、iptables nat表应用 使用介绍

    第7周第4次课(5月10日) 课程内容: 10.15 iptables filter表案例10.16/10.17/10.18 iptables nat表应用 扩展1. iptables应用在一个网段 ...

随机推荐

  1. Innodb锁机制:Next-Key Lock 浅谈

    数据库使用锁是为了支持更好的并发,提供数据的完整性和一致性.InnoDB是一个支持行锁的存储引擎,锁的类型有:共享锁(S).排他锁(X).意向共享(IS).意向排他(IX).为了提供更好的并发,Inn ...

  2. zmqsend for FFmpeg

    编译 FFmpeg 时,配置中添加 --enable-libzmq 就可以通过 tcp 通讯给 FFmpeg 发送命令 Usage: zmqsend [-h ip:port] TARGET COMMA ...

  3. vs版本转换工具

      [转]C#写的工程项目移植转换工具 – 支持VS2005/VS2010/VS2012/VS2013 经常用Visual Studio开发项目的是不是会经常遇到下面这种情况或者类似于这样的情况?用新 ...

  4. 2101 Problem A Snake Filled

    题目描述 “What a boring world!”Julyed felt so bored that she began to write numbers on the coordinate pa ...

  5. Divide and conquer:Telephone Lines(POJ 3662)

    电话线 题目大意:一堆电话线要你接,现在有N个接口,总线已经在1端,要你想办法接到N端去,电话公司发好心免费送你几段不用拉网线,剩下的费用等于剩余最长电话线的长度,要你求出最小的费用. 这一看又是一个 ...

  6. Android 中沉浸式状态栏实现

    Android 中沉浸式状态栏实现方式如下 计算状态栏高度及调用沉浸式状态栏的相关API方法 package com.example.status; import android.annotation ...

  7. LeetCode 202 Happy Number

    Problem: Write an algorithm to determine if a number is "happy". A happy number is a numbe ...

  8. py随笔

    while true,无限循环 str.isdigit判断是不是数字 +只能在两个两个相同的类型之间执行 iter(i)将i加入迭代器

  9. objective-c可变字典

     1 #pragma mark *****************************字典********************************  2 //        字典:通过ke ...

  10. java.util.ConcurrentModificationException

    遍历 List 的时候将 item remove 掉会抛出此异常