- 需求分析
需求:
不管是get请求还是post请求,只要我们调用request.getParameter(name)方法获取参数值,就不要产生乱码。
增强一个类中的方法有三种方式:
1.继承:
条件:必须要能够控制被增强类的构造方法
2.装饰者模式:
条件①:装饰者(增强的类)和被装饰者(被增强的类)都要实现同一个接口;
条件②:装饰者(增强的类)要获得被装饰者的引用
缺点:如果接口中的方法很多那么就要实现很多方法。
3.动态代理: 后续spring框架
同样也是基于接口实现的。 - 乱码产生原因分析
get方式 乱码原因
请求发送时会进行进行URL编码,编码格式为UTF-8
服务器接收时使用ISO-8859-1解码,不支持中文,此时已经产生乱码
手动调用request.getParameter(乱码)方法时,参数已经是乱码了
解决方法
将乱码使用ISO-8859-1编码,得到UTF-8编码后的数据
再使用UTF-8解码得到原数据
post方式乱码原因
请求发送的数据在请求体中
request对象接收数据后将数据放入缓冲区
缓冲区默认使用ISO-8859-1编码格式进行编码,不支持中文
ISO-8859-1不支持中文
手动调用request.getParameter()方法时,使用ISO-8859-1解码获得乱码
解决方法
将缓冲区编码格式设置为UTF-8,以UTF-8格式进行编码与解码 - 通用的字符集编码过滤器实现思路
创建一个类继承HttpServletRequestWrapper
这个类就是HttpServletRequest对象的增强类
重写强HttpServletReques的getParameter()方法
在过滤器的doFilter()方法里面将普通的request对象增强,并传递下去
继承关系:
public interface ServletRequest
public interface HttpServletRequest extends ServletRequest
public class HttpServletRequestWrapper extends ServletRequestWrapper implements HttpServletRequest
装饰者模式:
1被增强的类和增强的类需要实现相同的接口。
使增强类重与被增强类实现相同的方法
2在增强的类中获得被增强的类的引用。
用于增强类初始化
3重写增强request.getParameter()方法
实现增强功能
理解:
增强类就像是被增强类的哥哥,某些能力比弟弟强一些
缺点:接口中的方法过多,重写很多其他的方法 - 代码实现
sub.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>get提交方式</h1>
<form action="${ pageContext.request.contextPath }/ServletDemo1" method="get">
姓名:<input type="text" name="name"/><br>
<input type="submit" value="提交">
</form>
<h1>post提交方式</h1>
<form action="${ pageContext.request.contextPath }/ServletDemo1" method="post">
姓名:<input type="text" name="name"/><br>
<input type="submit" value="提交">
</form>
</body>
</html>
GenericEncodingFilter
public class GenericEncodingFilter implements Filter {
public void destroy() {
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest)request;
MyHttpServletRequest myReq = new MyHttpServletRequest(req);
chain.doFilter(myReq, response);
}
public void init(FilterConfig fConfig) throws ServletException {
}
}
ServletDemo1
public class ServletDemo1 extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//此时实际调用的MyHttpServletRequest中重写的方法
String parameter = request.getParameter("name");
System.out.println(parameter);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//此时实际调用的MyHttpServletRequest中重写的方法
String parameter = request.getParameter("name");
System.out.println(parameter);
}
}
MyHttpServletRequest
/**
* 自定义增强类-MyHttpServletRequest增强HttpServletReques的getParameter()方法
*
*
* 继承关系:
* public interface ServletRequest
* public interface HttpServletRequest extends ServletRequest
* public class HttpServletRequestWrapper extends ServletRequestWrapper implements HttpServletRequest
* 装饰者模式:
* 1被增强的类和增强的类需要实现相同的接口。
* 使增强类重与被增强类实现相同的方法
* 2在增强的类中获得被增强的类的引用。
* 用于增强类初始化
* 3重写增强request.getParameter()方法
* 实现增强功能
* 理解:
* 增强类就像是被增强类的哥哥,某些能力比弟弟强一些
* 缺点:接口中的方法过多,重写很多其他的方法
* 执行流程:
* sub.jsp->GenericEncodingFilter->ServletDemo1
* 1.提交数据
* 2.过滤器创建增强类MyHttpServletRequest对象并将对象作为参数传递给Servlet
* 3.执行增强类MyHttpServletRequest对象中的增强重写的getParameter()方法
*/
//1被增强的类和增强的类需要实现相同的接口-HttpServletRequest
public class MyHttpServletRequest extends HttpServletRequestWrapper{
private HttpServletRequest request;
//2在增强的类中获得被增强的类的引用。
public MyHttpServletRequest(HttpServletRequest request) {
super(request);
this.request = request;
}
@Override
//3重写增强request.getParameter()方法:
public String getParameter(String name) {
//判断请求方式
if("POST".equalsIgnoreCase(request.getMethod())){
// post方式的请求
/*
post方式乱码原因
请求发送的数据在请求体中
request对象接收数据后将数据放入缓冲区
缓冲区默认使用ISO-8859-1编码格式进行编码,不支持中文
ISO-8859-1不支持中文
手动调用request.getParameter()方法时,使用ISO-8859-1解码获得乱码
解决方法
将缓冲区编码格式设置为UTF-8,以UTF-8格式进行编码与解码
*/
try {
request.setCharacterEncoding("UTF-8");
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}else if("GET".equalsIgnoreCase(request.getMethod())){
// get方式的请求
/*
get方式 乱码原因
请求发送时会进行进行URL编码,编码格式为UTF-8
服务器接收时使用ISO-8859-1解码,不支持中文,此时已经产生乱码
手动调用request.getParameter(乱码)方法时,参数已经是乱码了
解决方法
将乱码使用ISO-8859-1编码,得到UTF-8编码后的数据
再使用UTF-8解码得到原数据
*/
String value = super.getParameter(name);
try {
//byte[] getBytes(Charset charset)
//使用给定的 charset 将此 String 编码到 byte 序列,并将结果存储到新的 byte 数组
//String(byte[] bytes, String charsetName)
//通过使用指定的 charset 解码指定的 byte 数组,构造一个新的 String。
//先编码再解码
value = new String(value.getBytes("ISO-8859-1"),"UTF-8");
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return value;
}
return super.getParameter(name);
}
}