---转载自:https://www.cnblogs.com/mei0619/p/8341159.html

request对象的生成方式不是ServletRequest request = new ServletRequest();这种形式,而是ServletRequest request = new HttpServletRequest();

 为什么在Filter里要强制转换?

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

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

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 () 等等..

疑问解决。

关于Filter中ServletRequest和ServletResponse强转HttpServletRequest和HttpServletResponse的更多相关文章

  1. 关于Filter中ServletRequest和ServletResponse强转HttpServletRequest和HttpServletResponse安全问题(向下转型一定不安全吗?)

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOE ...

  2. 关于Filter中ServletRequest强转HttpServletRequest问题

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOE ...

  3. Servlet的生命周期及filter,servletRequest和servletResponse

    序,Web应用中,Servlet和Filter是很重要的两个概念,一定要理解透彻. 一.Servlet类 继承自HttpServlet,HttpServlet是一个抽象类,主要包含的方法有init,s ...

  4. javaWEB中的ServletRequest,ServletResponse的使用,及简化Servlet方法

    首先说一下ServletRequest,ServletResponse类的使用方法: public void service(ServletRequest request, ServletRespon ...

  5. Filter中request对象强转问题

    以下为过滤器doFIlter方法的源代码: public void doFilter(ServletRequest request, ServletResponse response, FilterC ...

  6. 在Java filter中调用service层方法

    在项目中遇到一个问题,在 Filter中注入 Serivce失败,注入的service始终为null.如下所示: public class WeiXinFilter implements Filter ...

  7. 两种include方式及filter中的dispatcher解析

    两种include方式 我自己写了一个original.jsp,另外有一个includedPage.jsp,我想在original.jsp中把includedPage.jsp引进来有两种方式: 1.& ...

  8. 如何在Java Filter 中注入 Service

    在项目中遇到一个问题,在 Filter中注入 Serivce失败,注入的service始终为null.如下所示: public class WeiXinFilter implements Filter ...

  9. java 过滤器Filter中chain.doFilter()之前和之后代码的执行顺序

    过滤器拦截到响应url的请求后会先执行doFilter()方法中chain.doFilter()之前的代码,然后执行下一个过滤器或者servelt.紧接着执行chain.doFilter()之后的代码 ...

随机推荐

  1. 51nod1127 最短的包含字符串 尺取法

    Bryce1010模板 #include <bits/stdc++.h> using namespace std; typedef long long LL; map<char,LL ...

  2. java实现九九乘法表

    public class Demo { public static void main(String[] args) { for (int i = 1; i < 10; i++) {      ...

  3. java awt 乱码问题

    问题:项目环境是utf-8,awt的元件比如label一直乱码 解决: (eclipse) 1.在你的具有main函数的类也即你应用运行的主类上点击右键,选择Run As中的Run Configura ...

  4. 关于如何读取XML文件的一个简单方法

    在平时开发系统功能的时候,我们经常会碰到一些需求需要经常性的发生变化,比如 系统版本.更新日志 等等.这个时候用一个XML文件来替代数据库,就会变的简便很多. 前段时候我也正好需要改个需求,是关于客户 ...

  5. Windowsforms 中 进程,线程

    进程: 进程是一个具有独立功能的程序关于某个数据集合的一次运行活动. 它可以申请和拥有系统资源,是一个动态的概念,是一个活动的实体. Process 类,用来操作进程. 命名空间:using Syst ...

  6. 工作记录 angular页面操作 MD5加密

    今天只是做页面,基于angularjs,有美工做的图打底,确实好用 密码保存,用到了C# MD5加密: https://www.cnblogs.com/healer007/p/5062189.html

  7. 策略模式--Java篇

    策略模式(Strategy):它定义了算法家族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化,不会影响到使用算法的客户. 下面将以商场打折为例子,说明策略模式.商场收银如何促销,用打折还是 ...

  8. [BZOJ1083][SCOI2005]繁忙的都市 最小生成树

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1083 由kruskal算法原理可知,我们对一张无向图做普通的最小生成树,连上的最后一条边就 ...

  9. Rxlifecycle使用详解,解决RxJava内存泄露问题

    http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/1122/3711.html

  10. mysql 的 case when then 用法 和null 的判断

    表:一个表 aa 有两个字段 id 和 sex ,第1条记录的sex 为空串  ('')  第二条记录的sex 为空  (null) 1. 用法: 第一种: select (case 字段名  whe ...