关于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 () 等等..
疑问解决。
关于Filter中ServletRequest强转HttpServletRequest问题的更多相关文章
- 关于Filter中ServletRequest和ServletResponse强转HttpServletRequest和HttpServletResponse安全问题(向下转型一定不安全吗?)
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOE ...
- 关于Filter中ServletRequest和ServletResponse强转HttpServletRequest和HttpServletResponse
---转载自:https://www.cnblogs.com/mei0619/p/8341159.html request对象的生成方式不是ServletRequest request = new S ...
- Filter中request对象强转问题
以下为过滤器doFIlter方法的源代码: public void doFilter(ServletRequest request, ServletResponse response, FilterC ...
- 在Java filter中调用service层方法
在项目中遇到一个问题,在 Filter中注入 Serivce失败,注入的service始终为null.如下所示: public class WeiXinFilter implements Filter ...
- 如何在Java Filter 中注入 Service
在项目中遇到一个问题,在 Filter中注入 Serivce失败,注入的service始终为null.如下所示: public class WeiXinFilter implements Filter ...
- Filter中排除对指定URL的过滤
1. 我们可以在web.xml中配置filter来对指定的URL进行过滤,进行一些特殊操作如权限验证等. <!– session过滤filter –> <filter> < ...
- 如何在自定义Filter中优雅的实现静态资源放行
在javaweb开发中,过滤器Filter比较常用于类似登录的拦截等场景.但是,当过滤器的配置不当时就会把所有的请求都拦截,静态资源也会被拦截掉,导致静态页面加载不出来. 一般的解决方 ...
- 解决在Filter中读取Request中的流后,后续controller或restful接口中无法获取流的问题
首先我们来描述一下在开发中遇到的问题,场景如下: 比如我们要拦截所有请求,获取请求中的某个参数,进行相应的逻辑处理:比如我要获取所有请求中的公共参数 token,clientVersion等等:这个时 ...
- Filter 中注入失败问题
参考: https://www.cnblogs.com/digdeep/p/4770004.html?tvd https://www.cnblogs.com/EasonJim/p/7666009.ht ...
随机推荐
- vue使用iview Timeline 时间轴不显示问题
vue Timeline 时间轴不显示渲染的效果 官网代码 <Timeline pending> <TimelineItem>发布1.0版本</TimelineItem& ...
- Spring注解配置(1)——@Autowired
@Autowired 注释,它可以对类成员变量.方法及构造函数进行标注,完成自动装配的工作. 通过 @Autowired的使用来消除 set ,get方法.在使用@Autowired之前,我们对一个b ...
- C++笔记009:C++对C的扩展——“实用性”增加
原创笔记,转载请注明出处! 点击[关注],关注也是一种美德~ 笔记八中已经说到:在 C语言中定义了3个层次的作用域,即文件(编译单元).函数和复合语句. C语言中的变量都必须在作用域开始的位置定义! ...
- ubuntu—终端安装mysql
---恢复内容开始--- Step 1 : 安装指令 ~$ sudo apt-get install mysql-server Step 2: 查看是否正常安装 ~$ ps aux | grep my ...
- Linux查看MAC地址方法
注:一般默认的网卡文件名是eth0,根据IP地址对应的实际情况区判断是ethx即可. 1. ip -a . cat /sys/class/net/ens39/address 其中 HWaddr字段就 ...
- Change runlevel on CentOS 6.9/CentOS 7.5
1:CentOS 6.9 # 0 - halt (Do NOT set initdefault to this) # 1 - Single user mode # 2 - Multiuser, wit ...
- DataSet和泛型之间相互转换
取数据的时候,存储过程返回了多个结果集,后台用DataSet去接收这几个结果集,然后接收之后,需要将结果集转换为不同的实体,于是下面的代码便出现了. /// <summary> /// 将 ...
- C#获取本地磁盘信息
直接上干货简单易懂 //磁盘监控(远程/本地) //需要引用System.Management.dll public class RemoteMonitoring { private static s ...
- Currency Helper
using System; using Microsoft.Xrm.Sdk; using Microsoft.Crm.Sdk.Messages; /// <summary> /// 货币 ...
- 大数据学习--day03(运算符、流程控制语句)
运算符.流程控制语句 自增自减容易出错的地方: 扩展的赋值运算符 a+=b 等同于 a = a+b; 扩展的赋值运算符 隐含了一个类型的强制转换 & && 有何区别 & ...