filter应用案例三:解决全站编码问题

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类,那么就只需要重写需要增强的方法即可了。

代码示例:

 1 import java.io.UnsupportedEncodingException;
 2 import javax.servlet.http.HttpServletRequest;
 3 import javax.servlet.http.HttpServletRequestWrapper;
 4 
 5 /**
 6  * 装饰reqeust
 7  */
 8 public class EncodingRequest extends HttpServletRequestWrapper {
 9     private HttpServletRequest req;
10     public EncodingRequest(HttpServletRequest request) {
11         super(request);
12         this.req = request;
13     }
14 
15     public String getParameter(String name) {
16         String value = req.getParameter(name);
17         // 处理编码问题
18         try {
19             value = new String(value.getBytes("iso-8859-1"), "utf-8");
20         } catch (UnsupportedEncodingException e) {
21             throw new RuntimeException(e);
22         }
23         return value;
24     }
25 }
EncodingRequest
 1 import java.io.IOException;
 2 
 3 import javax.servlet.Filter;
 4 import javax.servlet.FilterChain;
 5 import javax.servlet.FilterConfig;
 6 import javax.servlet.ServletException;
 7 import javax.servlet.ServletRequest;
 8 import javax.servlet.ServletResponse;
 9 import javax.servlet.http.HttpServletRequest;
10 
11 public class EncodingFilter implements Filter {
12     public void destroy() {}
13     
14     public void doFilter(ServletRequest request, ServletResponse response,
15             FilterChain chain) throws IOException, ServletException {
16         // 处理post请求编码问题
17         request.setCharacterEncoding("utf-8");
18         HttpServletRequest req = (HttpServletRequest) request;
19         /*
20          * 处理GET请求的编码问题
21          * 调包request
22          * 1. 写一个request的装饰类
23          * 2. 在放行时,使用我们自己的request
24          */
25         if(req.getMethod().equals("GET")) {
26             EncodingRequest er = new EncodingRequest(req);
27             chain.doFilter(er, response);
28         } else if(req.getMethod().equals("POST")) {
29             chain.doFilter(request, response);
30         }
31     }
32     
33     public void init(FilterConfig fConfig) throws ServletException {}
34 }
EncodingFilter
 1 import java.io.IOException;
 2 
 3 import javax.servlet.ServletException;
 4 import javax.servlet.http.HttpServlet;
 5 import javax.servlet.http.HttpServletRequest;
 6 import javax.servlet.http.HttpServletResponse;
 7 
 8 public class AServlet extends HttpServlet {
 9     public void doGet(HttpServletRequest request, HttpServletResponse response)
10             throws ServletException, IOException {
11         response.setContentType("text/html;charset=utf-8");
12         String username = request.getParameter("username");
13         response.getWriter().println(username);
14     }
15 
16     public void doPost(HttpServletRequest request, HttpServletResponse response)
17             throws ServletException, IOException {
18         response.setContentType("text/html;charset=utf-8");
19         String username = request.getParameter("username");
20         response.getWriter().println(username);
21     }
22 }
AServlet
 1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
 2 <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
 3 <%
 4 String path = request.getContextPath();
 5 String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
 6 %>
 7 
 8 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 9 <html>
10   <head>
11     <base href="<%=basePath%>">
12     
13     <title>My JSP 'index.jsp' starting page</title>
14     <meta http-equiv="pragma" content="no-cache">
15     <meta http-equiv="cache-control" content="no-cache">
16     <meta http-equiv="expires" content="0">    
17     <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
18     <meta http-equiv="description" content="This is my page">
19     <!--
20     <link rel="stylesheet" type="text/css" href="styles.css">
21     -->
22   </head>
23   
24   <body>
25 <a href="<c:url value='/AServlet?username=张三'/>">点击这里</a><br/>
26 <form action="<c:url value='/AServlet'/>" method="post">
27 用户名:<input type="text" name="username" value="李四"/>
28 <input type="submit" value="提交"/>
29 </form>
30   </body>
31 </html>
index.jsp
 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <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">
 3   <display-name></display-name>
 4 <servlet>
 5     <servlet-name>AServlet</servlet-name>
 6     <servlet-class>AServlet</servlet-class>
 7   </servlet>
 8   <servlet-mapping>
 9     <servlet-name>AServlet</servlet-name>
10     <url-pattern>/AServlet</url-pattern>
11   </servlet-mapping>
12   <welcome-file-list>
13     <welcome-file>index.jsp</welcome-file>
14   </welcome-file-list>
15   <filter>
16     <display-name>EncodingFilter</display-name>
17     <filter-name>EncodingFilter</filter-name>
18     <filter-class>EncodingFilter</filter-class>
19   </filter>
20   <filter-mapping>
21     <filter-name>EncodingFilter</filter-name>
22     <url-pattern>/*</url-pattern>
23   </filter-mapping>
24 </web-app>
web.xml
原文地址:https://www.cnblogs.com/fengmingyue/p/6075525.html