本文共 6467 字,大约阅读时间需要 21 分钟。
我们使用装饰者对request进行增强,从而使得get和post使用request.getParameter()获得的数据没有乱码:
首先来一个Servlet,用于处理客户端请求:
package 装饰者模式解决乱码;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 DataServlet extends HttpServlet { private static final long serialVersionUID = 1L; public DataServlet() { super(); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //获得数据 String username = request.getParameter("username"); String password = request.getParameter("password"); System.out.println("前:" +username+"@"+password); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //获得数据 String username = request.getParameter("username"); String password = request.getParameter("password"); System.out.println("前:" +username+"@"+password); } }
创建HttpServletRequest的增强类,借助HttpServletRequestWrapper:
package 装饰者模式解决乱码;import java.io.UnsupportedEncodingException;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletRequestWrapper;/** * * sun 提供 HttpServletRequest 接口使用装饰者编写默认类,及所有的方法都没有增强的。 * * 之后我们只需要继承即可 * * 增强response对象,提供使用装饰者设计模式编写默认类:HttpServletResponseWrapper */public class MyRequest extends HttpServletRequestWrapper { //保持对接口的引用 private HttpServletRequest request; //构造方法 public MyRequest(HttpServletRequest request) { super(request); //赋值 this.request = request; } //重写某个方法 @Override public String getParameter(String name) { //首先获得参数,这是没有改变编码的值 String value = request.getParameter(name); //首先判断请求方式 String method = request.getMethod(); if ("GET".equals(method)) { try { value = new String(value.getBytes("ISO-8859-1"), "utf-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } }else { try { request.setCharacterEncoding("utf-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } } return value; }}
在客户端向服务器发送请求时,我们需要对其进行拦截:
package 装饰者模式解决乱码;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;public class EncodingFilter implements Filter { public EncodingFilter() { } public void destroy() { } public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { //强转 HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) res; //post编码 response.setCharacterEncoding("UTF-8"); //使用装饰者模式增强 MyRequest myRequest = new MyRequest(request); //放行 chain.doFilter(myRequest, response); System.out.println("我是中国人!"); /*//0 强转 HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) resp; //1 post乱码 request.setCharacterEncoding("UTF-8"); //2 使用装饰者增强request MyRequest myRequest = new MyRequest(request); chain.doFilter(myRequest, response);*/ } public void init(FilterConfig fConfig) throws ServletException { }}
客户端页面:
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>写一个Servlet:动态代理解决get方式乱码问题
package solveresponseencoding;import java.io.IOException;import javax.servlet.ServletException;import javax.servlet.annotation.WebServlet;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;@WebServlet("/DataServlet")public class DataServlet extends HttpServlet { private static final long serialVersionUID = 1L; public DataServlet() { super(); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //获得请求参数 String username = request.getParameter("username"); String password = request.getParameter("password"); //打印值 System.out.println(request.getMethod() + " : " + username + " @ " + password); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); }}
对请求进行拦截的过滤器:
package solveresponseencoding;import java.io.IOException;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;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.annotation.WebFilter;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;@WebFilter("/*")public class EncodingFilter implements Filter { public EncodingFilter() { } public void destroy() { } /* * 本方法会拦截所有请求,在本方法中对request进行增强 */ public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { //强转 final HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) res; //解决post乱码 request.setCharacterEncoding("utf-8"); //创建动态代理对象 HttpServletRequest myRequest = (HttpServletRequest) Proxy.newProxyInstance( EncodingFilter.class.getClassLoader(), new Class[]{HttpServletRequest.class}, new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //如果是getParameter方法,获取参数 if ("getParameter".equals(method.getName())) { String value = request.getParameter((String)args[0]); //System.out.println("value值为:"+value); //如果是get请求,就增强 if ("GET".equalsIgnoreCase(request.getMethod())) { value = new String(value.getBytes("ISO-8859-1"), "utf-8"); System.out.println("我是get方法:"); } return value; } return method.invoke(request, args); } }); chain.doFilter(myRequest, response); } public void init(FilterConfig fConfig) throws ServletException { }}
动态代理解决这个问题,将增强放到了过滤器中,不同之处他没有专门的增强类,而是通过动态代理技术在运行期间动态生成的,对于InvocationHandler接口采用了匿名内部类的方式。