• 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
  • 相关阅读:
    C#的默认访问权限
    隐藏基类成员
    索引指示器的重载
    索引指示器
    vector
    string 函数
    细胞个数
    计蒜客 T1096 石头剪刀布
    计蒜客 T1125 判断字符串是否为回文
    计蒜客 T1152 成绩排序
  • 原文地址:https://www.cnblogs.com/fengmingyue/p/6075525.html
Copyright © 2020-2023  润新知