• 关于Filter中ServletRequest强转HttpServletRequest问题


    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
      HttpServletRequest req = (HttpServletRequest) request;
      HttpServletResponse resp = (HttpServletResponse) response;

      }

        因为要用到HttpServletRequest中的方法,我对ServletRequest进行了强转,然后问题解决。可是后来一想不对啊,我们知道我们对子类实现进行向上转型得到父类对象是安全的,因为子类会完全继承父类的方法,我们向上转型为父类,当我们调用父类的方法其实在子类实现中是能完全找到的。反之向下转型是不安全的,我们子类除了完全继承父类的方法外还会拓展自己的方法,所以我们在调用子类方法时可能在父类实现中是找不到的,所以向下转型不安全。

       可是本例中的实现却让我们困惑,我们不仅实现了向下转型,同时还调用了子类拓展的方法,是父类没有的,可是却实现了。这不是和我们所学矛盾吗?后来看了API和一些资料我终于明白了,这和我们所学其实并不冲突!我们先看API:

       public interface HttpServletRequest extends ServletRequest

       终于找到原因了,原来HttpServletRequest和ServletRequest都是接口,他们都只是定义了方法却没有提供相关实现。所以我们看到的ServletRequest request中的request对象其实并不是我们ServletRequest 的一个具体实现。

       这里我们要看我们提出的问题是否安全,其实主要看request 对象的具体实现类究竟是继承的哪个接口,如果继承自HttpServletRequest接口那么我们向下转型使用HttpServletRequest接口的方法就是安全的。测试如下:

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    if(request instanceof HttpServletRequest){
    System.out.println("-------------");
    }
    HttpServletRequest req = (HttpServletRequest) request;
    if(req instanceof HttpServletRequest){
          System.out.println("我是右边类的实例");
    }
    HttpServletResponse resp = (HttpServletResponse) response;
    }

       输出:

    -------------

     我是右边类的实例

       证明我们的request对象的确是HttpServletRequest的一个实例。

     也就是说doFilter的参数request对象的生成方式不是ServletRequest request = new ServletRequest();这种形式,而是ServletRequest request = new HttpServletRequest();这种形式,参数里的request不是父类ServletRequest的对象,而是HttpServletRequest的上转型对象:

      根据《java面向对象程序设计(第2版)》,一个父类类型的对象如果是用子类new出来的时候(ServletRequest request = new HttpServletRequest();//就是这行代码), 就不能称之为父类对象,而是一个子类的上转型对象。这两者是有区别的,区别的其中一点就是父类对象不可强制转换为子类对象,而子类的上转型对象可以强制转换回子类对象。

      再说一下为什么在Filter里要强制转换?

      答:ServletRequest request;这个是将子类对象赋给父类引用,他运行时的类型是子类,编译时的类型是父类,但是在运行时,父类类型对象调用的方法如果子类里面有,那就执行子类里面的方法,如果编译时的类型也就是父类没有调用的那个方法,则报错。所以在那里要做一个强制类型转换,否则就会报错。

    HttpServletRequest比ServletRequest多了一些针对于Http协议的方法.如getHeader (String name), getMethod () ,getSession () 等等..

       疑问解决。

  • 相关阅读:
    [工作札记]01: CS系统中分页控件的制作
    【非技术】试占新型肺炎的情况与发展趋势
    给培训学校讲解ORM框架的课件
    SAAS云平台搭建札记: (二) Linux Ubutu下.Net Core整套运行环境的搭建
    SAAS云平台搭建札记: (一) 浅论SAAS多租户自助云服务平台的产品、服务和订单
    开源三维地球GIS引擎Cesium常用功能的开发
    Asp.net管理信息系统中数据统计功能的实现
    [Thrift]学习使用Thrift
    使用Netty实现一下简单RPC
    [Redis]Redis做简单的分布式限流
  • 原文地址:https://www.cnblogs.com/gwyy/p/9078135.html
Copyright © 2020-2023  润新知