java:Multiple Bounds--类型变量(TypeVariable)定义的高级用法--<A extends ClassA&IfA&IfB >

做Java开发工作好多年了。今天偶然翻到 java.lang.TypeVariable的源码,好奇为什么 TypeVariable.getBounds()返回类型是个数组。
一般不都是<T extends Number> 这样用码?T难道还能extends多个类型?

同问:不应该是extend,为什么要加个s当复数?

带着问题一通找,最终找到了Oracle官方文档:《Bounded Type Parameters》

才知道类型变量定义还有Multiple Bounds的概念,说明如下:
在这里插入图片描述
如下示例:ServiceD定义了A类型变量–<A extends ClassA&IfA&IfB >,就要求A不仅要是ClassA的子类,还要实现IfAIfB接口

所以ClassC才能满足这个要求,

	public static class ClassA{}
	public static interface IfA{}
	public static interface IfB{}
	public static class ServiceD<A extends ClassA&IfA&IfB >{
	}
	public static class ClassC extends ClassA  implements IfA,IfB{}
	public static class ServiceE extends ServiceD<ClassC>{
	}

终于明白为什么继承关键字是extends而不是extend,原来用到这儿了。
真是又学到了,以想想什么场景需要用到这样的定义。

参考资料

《Bounded Type Parameters》

HTTP/1.1 200 OK Connection: close Content-Type: application/soap+xml; charset=utf-8 Content-Length: 13411 <?xml version="1.0" encoding="UTF-8"?> <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://www.w3.org/2003/05/soap-envelope" xmlns:SOAP-ENC="http://www.w3.org/2003/05/soap-encoding" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:wsdd="http://schemas.xmlsoap.org/ws/2005/04/discovery" xmlns:chan="http://schemas.microsoft.com/ws/2005/02/duplex" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wsa5="http://www.w3.org/2005/08/addressing" xmlns:xmime="http://tempuri.org/xmime.xsd" xmlns:xop="http://www.w3.org/2004/08/xop/include" xmlns:wsrfbf="http://docs.oasis-open.org/wsrf/bf-2" xmlns:wstop="http://docs.oasis-open.org/wsn/t-1" xmlns:wsrfr="http://docs.oasis-open.org/wsrf/r-2" xmlns:wsnt="http://docs.oasis-open.org/wsn/b-2" xmlns:tt="http://www.onvif.org/ver10/schema" xmlns:ter="http://www.onvif.org/ver10/error" xmlns:tns1="http://www.onvif.org/ver10/topics" xmlns:tds="http://www.onvif.org/ver10/device/wsdl" xmlns:tmd="http://www.onvif.org/ver10/deviceIO/wsdl" xmlns:trt="http://www.onvif.org/ver10/media/wsdl" xmlns:tev="http://www.onvif.org/ver10/events/wsdl" xmlns:tdn="http://www.onvif.org/ver10/network/wsdl" xmlns:timg="http://www.onvif.org/ver20/imaging/wsdl" xmlns:trp="http://www.onvif.org/ver10/replay/wsdl" xmlns:tan="http://www.onvif.org/ver20/analytics/wsdl" xmlns:tptz="http://www.onvif.org/ver20/ptz/wsdl" xmlns:tr2="http://www.onvif.org/ver20/media/wsdl"> <SOAP-ENV:Header> </SOAP-ENV:Header> <SOAP-ENV:Body> <tr2:GetProfilesResponse> <tr2:Profiles fixed="true" token="profile_1"> <tr2:Name>mainStream</tr2:Name> <tr2:Configurations> <tr2:VideoSource token="vsconf"> <tt:Name>VideoSourceConfig</tt:Name> <tt:UseCount>3</tt:UseCount> <tt:SourceToken>raw_vs1</tt:SourceToken> <tt:Bounds height="720" width="1280" y="0" x="0"> </tt:Bounds> </tr2:VideoSource> <tr2:AudioSource token="asconf"> <tt:Name>AudioSourceConfig</tt:Name> <tt:UseCount>2</tt:UseCount> <tt:SourceToken>raw_as1</tt:SourceToken> </tr2:AudioSource> <tr2:VideoEncoder token="main" GovLength="25"> <tt:Name>VideoEncoder_1</tt:Name> <tt:UseCount>1</tt:UseCount> <tt:Encoding>H264</tt:Encoding> <tt:Resolution> <tt:Width>2304</tt:Width> <tt:Height>1296</tt:Height> </tt:Resolution> <tt:RateControl ConstantBitRate="false"> <tt:FrameRateLimit>15</tt:FrameRateLimit> <tt:BitrateLimit>1228</tt:BitrateLimit> </tt:RateControl> <tt:Multicast> <tt:Address> <tt:Type>IPv4</tt:Type> <tt:IPv4Address>0.0.0.0</tt:IPv4Address> </tt:Address> <tt:Port>0</tt:Port> <tt:TTL>0</tt:TTL> <tt:AutoStart>false</tt:AutoStart> </tt:Multicast> <tt:Quality>5</tt:Quality> </tr2:VideoEncoder> <tr2:AudioEncoder token="raw_as1"> <tt:Name>AudioSourceConfig</tt:Name> <tt:UseCount>2</tt:UseCount> <tt:Encoding>G711</tt:Encoding> <tt:Multicast> <tt:Address> <tt:Type>IPv4</tt:Type> <tt:IPv4Address>0.0.0.0</tt:IPv4Address> </tt:Address> <tt:Port>0</tt:Port> <tt:TTL>0</tt:TTL> <tt:AutoStart>false</tt:AutoStart> </tt:Multicast> <tt:Bitrate>65536</tt:Bitrate> <tt:SampleRate>11000</tt:SampleRate> </tr2:AudioEncoder> <tr2:Analytics token="VideoAnalyticsToken"> <tt:Name>VideoAnalyticsName</tt:Name> <tt:UseCount>2</tt:UseCount> <tt:AnalyticsEngineConfiguration> <tt:AnalyticsModule Name="MyCellMotionModule" Type="tt:CellMotionEngine"> <tt:Parameters> <tt:SimpleItem Value="60" Name="Sensitivity"> </tt:SimpleItem> <tt:SimpleItem Value="on" Name="Enabled"> </tt:SimpleItem> <tt:ElementItem Name="Layout"> <tt:CellLayout Rows="18" Columns="22"> <tt:Transformation> <tt:Translate y="-1" x="-1"> </tt:Translate> <tt:Scale y="0.109999999" x="0.0900000036"> </tt:Scale> </tt:Transformation> </tt:CellLayout> </tt:ElementItem> </tt:Parameters> </tt:AnalyticsModule> <tt:AnalyticsModule Name="MyTamperDetecModule" Type="tt:TamperEngine"> <tt:Parameters> <tt:SimpleItem Value="50" Name="Sensitivity"> </tt:SimpleItem> <tt:SimpleItem Value="off" Name="Enabled"> </tt:SimpleItem> </tt:Parameters> </tt:AnalyticsModule> </tt:AnalyticsEngineConfiguration> <tt:RuleEngineConfiguration> <tt:Rule Name="MyMotionDetectorRule" Type="tt:CellMotionDetector"> <tt:Parameters> <tt:SimpleItem Value="0P8A8A==" Name="ActiveCells"> </tt:SimpleItem> <tt:SimpleItem Value="5" Name="MinCount"> </tt:SimpleItem> <tt:SimpleItem Value="1000" Name="AlarmOnDelay"> </tt:SimpleItem> <tt:SimpleItem Value="1000" Name="AlarmOffDelay"> </tt:SimpleItem> </tt:Parameters> </tt:Rule> <tt:Rule Name="MyTamperDetectorRule" Type="tt:TamperDetector"> <tt:Parameters> </tt:Parameters> </tt:Rule> </tt:RuleEngineConfiguration> </tr2:Analytics> </tr2:Configurations> </tr2:Profiles> <tr2:Profiles fixed="true" token="profile_2"> <tr2:Name>minorStream</tr2:Name> <tr2:Configurations> <tr2:VideoSource token="vsconf"> <tt:Name>VideoSourceConfig</tt:Name> <tt:UseCount>3</tt:UseCount> <tt:SourceToken>raw_vs1</tt:SourceToken> <tt:Bounds height="720" width="1280" y="0" x="0"> </tt:Bounds> </tr2:VideoSource> <tr2:AudioSource token="asconf"> <tt:Name>AudioSourceConfig</tt:Name> <tt:UseCount>2</tt:UseCount> <tt:SourceToken>raw_as1</tt:SourceToken> </tr2:AudioSource> <tr2:VideoEncoder token="minor" GovLength="25"> <tt:Name>VideoEncoder_2</tt:Name> <tt:UseCount>1</tt:UseCount> <tt:Encoding>H264</tt:Encoding> <tt:Resolution> <tt:Width>1280</tt:Width> <tt:Height>720</tt:Height> </tt:Resolution> <tt:RateControl ConstantBitRate="false"> <tt:FrameRateLimit>15</tt:FrameRateLimit> <tt:BitrateLimit>512</tt:BitrateLimit> </tt:RateControl> <tt:Multicast> <tt:Address> <tt:Type>IPv4</tt:Type> <tt:IPv4Address>0.0.0.0</tt:IPv4Address> </tt:Address> <tt:Port>0</tt:Port> <tt:TTL>0</tt:TTL> <tt:AutoStart>false</tt:AutoStart> </tt:Multicast> <tt:Quality>3</tt:Quality> </tr2:VideoEncoder> <tr2:AudioEncoder token="raw_as1"> <tt:Name>AudioSourceConfig</tt:Name> <tt:UseCount>2</tt:UseCount> <tt:Encoding>G711</tt:Encoding> <tt:Multicast> <tt:Address> <tt:Type>IPv4</tt:Type> <tt:IPv4Address>0.0.0.0</tt:IPv4Address> </tt:Address> <tt:Port>0</tt:Port> <tt:TTL>0</tt:TTL> <tt:AutoStart>false</tt:AutoStart> </tt:Multicast> <tt:Bitrate>65536</tt:Bitrate> <tt:SampleRate>11000</tt:SampleRate> </tr2:AudioEncoder> <tr2:Analytics token="VideoAnalyticsToken"> <tt:Name>VideoAnalyticsName</tt:Name> <tt:UseCount>2</tt:UseCount> <tt:AnalyticsEngineConfiguration> <tt:AnalyticsModule Name="MyCellMotionModule" Type="tt:CellMotionEngine"> <tt:Parameters> <tt:SimpleItem Value="60" Name="Sensitivity"> </tt:SimpleItem> <tt:SimpleItem Value="on" Name="Enabled"> </tt:SimpleItem> <tt:ElementItem Name="Layout"> <tt:CellLayout Rows="18" Columns="22"> <tt:Transformation> <tt:Translate y="-1" x="-1"> </tt:Translate> <tt:Scale y="0.109999999" x="0.0900000036"> </tt:Scale> </tt:Transformation> </tt:CellLayout> </tt:ElementItem> </tt:Parameters> </tt:AnalyticsModule> <tt:AnalyticsModule Name="MyTamperDetecModule" Type="tt:TamperEngine"> <tt:Parameters> <tt:SimpleItem Value="50" Name="Sensitivity"> </tt:SimpleItem> <tt:SimpleItem Value="off" Name="Enabled"> </tt:SimpleItem> </tt:Parameters> </tt:AnalyticsModule> </tt:AnalyticsEngineConfiguration> <tt:RuleEngineConfiguration> <tt:Rule Name="MyMotionDetectorRule" Type="tt:CellMotionDetector"> <tt:Parameters> <tt:SimpleItem Value="0P8A8A==" Name="ActiveCells"> </tt:SimpleItem> <tt:SimpleItem Value="5" Name="MinCount"> </tt:SimpleItem> <tt:SimpleItem Value="1000" Name="AlarmOnDelay"> </tt:SimpleItem> <tt:SimpleItem Value="1000" Name="AlarmOffDelay"> </tt:SimpleItem> </tt:Parameters> </tt:Rule> <tt:Rule Name="MyTamperDetectorRule" Type="tt:TamperDetector"> <tt:Parameters> </tt:Parameters> </tt:Rule> </tt:RuleEngineConfiguration> </tr2:Analytics> </tr2:Configurations> </tr2:Profiles> <tr2:Profiles fixed="true" token="profile_3"> <tr2:Name>jpegStream</tr2:Name> <tr2:Configurations> <tr2:VideoSource token="vsconf"> <tt:Name>VideoSourceConfig</tt:Name> <tt:UseCount>3</tt:UseCount> <tt:SourceToken>raw_vs1</tt:SourceToken> <tt:Bounds height="720" width="1280" y="0" x="0"> </tt:Bounds> </tr2:VideoSource> <tr2:AudioSource token="asconf"> <tt:Name>AudioSourceConfig</tt:Name> <tt:UseCount>2</tt:UseCount> <tt:SourceToken>raw_as1</tt:SourceToken> </tr2:AudioSource> <tr2:VideoEncoder token="jpeg" GovLength="25"> <tt:Name>VideoEncoder_2</tt:Name> <tt:UseCount>1</tt:UseCount> <tt:Encoding>H264</tt:Encoding> <tt:Resolution> <tt:Width>1280</tt:Width> <tt:Height>720</tt:Height> </tt:Resolution> <tt:RateControl ConstantBitRate="false"> <tt:FrameRateLimit>15</tt:FrameRateLimit> <tt:BitrateLimit>512</tt:BitrateLimit> </tt:RateControl> <tt:Multicast> <tt:Address> <tt:Type>IPv4</tt:Type> <tt:IPv4Address>0.0.0.0</tt:IPv4Address> </tt:Address> <tt:Port>0</tt:Port> <tt:TTL>0</tt:TTL> <tt:AutoStart>false</tt:AutoStart> </tt:Multicast> <tt:Quality>3</tt:Quality> </tr2:VideoEncoder> <tr2:AudioEncoder token="raw_as1"> <tt:Name>AudioSourceConfig</tt:Name> <tt:UseCount>2</tt:UseCount> <tt:Encoding>G711</tt:Encoding> <tt:Multicast> <tt:Address> <tt:Type>IPv4</tt:Type> <tt:IPv4Address>0.0.0.0</tt:IPv4Address> </tt:Address> <tt:Port>0</tt:Port> <tt:TTL>0</tt:TTL> <tt:AutoStart>false</tt:AutoStart> </tt:Multicast> <tt:Bitrate>65536</tt:Bitrate> <tt:SampleRate>11000</tt:SampleRate> </tr2:AudioEncoder> <tr2:Analytics token="VideoAnalyticsToken"> <tt:Name>VideoAnalyticsName</tt:Name> <tt:UseCount>2</tt:UseCount> <tt:AnalyticsEngineConfiguration> <tt:AnalyticsModule Name="MyCellMotionModule" Type="tt:CellMotionEngine"> <tt:Parameters> <tt:SimpleItem Value="60" Name="Sensitivity"> </tt:SimpleItem> <tt:SimpleItem Value="on" Name="Enabled"> </tt:SimpleItem> <tt:ElementItem Name="Layout"> <tt:CellLayout Rows="18" Columns="22"> <tt:Transformation> <tt:Translate y="-1" x="-1"> </tt:Translate> <tt:Scale y="0.109999999" x="0.0900000036"> </tt:Scale> </tt:Transformation> </tt:CellLayout> </tt:ElementItem> </tt:Parameters> </tt:AnalyticsModule> <tt:AnalyticsModule Name="MyTamperDetecModule" Type="tt:TamperEngine"> <tt:Parameters> <tt:SimpleItem Value="50" Name="Sensitivity"> </tt:SimpleItem> <tt:SimpleItem Value="off" Name="Enabled"> </tt:SimpleItem> </tt:Parameters> </tt:AnalyticsModule> </tt:AnalyticsEngineConfiguration> <tt:RuleEngineConfiguration> <tt:Rule Name="MyMotionDetectorRule" Type="tt:CellMotionDetector"> <tt:Parameters> <tt:SimpleItem Value="0P8A8A==" Name="ActiveCells"> </tt:SimpleItem> <tt:SimpleItem Value="5" Name="MinCount"> </tt:SimpleItem> <tt:SimpleItem Value="1000" Name="AlarmOnDelay"> </tt:SimpleItem> <tt:SimpleItem Value="1000" Name="AlarmOffDelay"> </tt:SimpleItem> </tt:Parameters> </tt:Rule> <tt:Rule Name="MyTamperDetectorRule" Type="tt:TamperDetector"> <tt:Parameters> </tt:Parameters> </tt:Rule> </tt:RuleEngineConfiguration> </tr2:Analytics> </tr2:Configurations> </tr2:Profiles> <tr2:Profiles fixed="false" token="profile_4"> <tr2:Name> </tr2:Name> <tr2:Configurations> <tr2:VideoSource token="default"> <tt:Name>default</tt:Name> <tt:UseCount>3</tt:UseCount> <tt:SourceToken>default</tt:SourceToken> <tt:Bounds height="720" width="1280" y="0" x="0"> </tt:Bounds> </tr2:VideoSource> <tr2:AudioSource token=""> <tt:Name> </tt:Name> <tt:UseCount>0</tt:UseCount> <tt:SourceToken> </tt:SourceToken> </tr2:AudioSource> <tr2:VideoEncoder token="jpeg" GovLength="25"> <tt:Name>VideoEncoder_2</tt:Name> <tt:UseCount>1</tt:UseCount> <tt:Encoding>H264</tt:Encoding> <tt:Resolution> <tt:Width>1280</tt:Width> <tt:Height>720</tt:Height> </tt:Resolution> <tt:RateControl ConstantBitRate="false"> <tt:FrameRateLimit>15</tt:FrameRateLimit> <tt:BitrateLimit>512</tt:BitrateLimit> </tt:RateControl> <tt:Multicast> <tt:Address> <tt:Type>IPv4</tt:Type> <tt:IPv4Address>0.0.0.0</tt:IPv4Address> </tt:Address> <tt:Port>0</tt:Port> <tt:TTL>0</tt:TTL> <tt:AutoStart>false</tt:AutoStart> </tt:Multicast> <tt:Quality>3</tt:Quality> </tr2:VideoEncoder> <tr2:AudioEncoder token=""> <tt:Name> </tt:Name> <tt:UseCount>0</tt:UseCount> <tt:Encoding>G711</tt:Encoding> <tt:Multicast> <tt:Address> <tt:Type>IPv4</tt:Type> <tt:IPv4Address>0.0.0.0</tt:IPv4Address> </tt:Address> <tt:Port>0</tt:Port> <tt:TTL>0</tt:TTL> <tt:AutoStart>false</tt:AutoStart> </tt:Multicast> <tt:Bitrate>65536</tt:Bitrate> <tt:SampleRate>11000</tt:SampleRate> </tr2:AudioEncoder> <tr2:Analytics token="VideoAnalyticsToken"> <tt:Name>VideoAnalyticsName</tt:Name> <tt:UseCount>2</tt:UseCount> <tt:AnalyticsEngineConfiguration> <tt:AnalyticsModule Name="MyCellMotionModule" Type="tt:CellMotionEngine"> <tt:Parameters> <tt:SimpleItem Value="60" Name="Sensitivity"> </tt:SimpleItem> <tt:SimpleItem Value="on" Name="Enabled"> </tt:SimpleItem> <tt:ElementItem Name="Layout"> <tt:CellLayout Rows="18" Columns="22"> <tt:Transformation> <tt:Translate y="-1" x="-1"> </tt:Translate> <tt:Scale y="0.109999999" x="0.0900000036"> </tt:Scale> </tt:Transformation> </tt:CellLayout> </tt:ElementItem> </tt:Parameters> </tt:AnalyticsModule> <tt:AnalyticsModule Name="MyTamperDetecModule" Type="tt:TamperEngine"> <tt:Parameters> <tt:SimpleItem Value="50" Name="Sensitivity"> </tt:SimpleItem> <tt:SimpleItem Value="off" Name="Enabled"> </tt:SimpleItem> </tt:Parameters> </tt:AnalyticsModule> </tt:AnalyticsEngineConfiguration> <tt:RuleEngineConfiguration> <tt:Rule Name="MyMotionDetectorRule" Type="tt:CellMotionDetector"> <tt:Parameters> <tt:SimpleItem Value="0P8A8A==" Name="ActiveCells"> </tt:SimpleItem> <tt:SimpleItem Value="5" Name="MinCount"> </tt:SimpleItem> <tt:SimpleItem Value="1000" Name="AlarmOnDelay"> </tt:SimpleItem> <tt:SimpleItem Value="1000" Name="AlarmOffDelay"> </tt:SimpleItem> </tt:Parameters> </tt:Rule> <tt:Rule Name="MyTamperDetectorRule" Type="tt:TamperDetector"> <tt:Parameters> </tt:Parameters> </tt:Rule> </tt:RuleEngineConfiguration> </tr2:Analytics> </tr2:Configurations> </tr2:Profiles> </tr2:GetProfilesResponse> </SOAP-ENV:Body> </SOAP-ENV:Envelope> 和 HTTP/1.1 200 OK Connection: close Content-Type: application/soap+xml; charset=utf-8 Content-Length: 3155 <?xml version="1.0" encoding="UTF-8"?> <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://www.w3.org/2003/05/soap-envelope" xmlns:SOAP-ENC="http://www.w3.org/2003/05/soap-encoding" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:wsdd="http://schemas.xmlsoap.org/ws/2005/04/discovery" xmlns:chan="http://schemas.microsoft.com/ws/2005/02/duplex" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wsa5="http://www.w3.org/2005/08/addressing" xmlns:xmime="http://tempuri.org/xmime.xsd" xmlns:xop="http://www.w3.org/2004/08/xop/include" xmlns:wsrfbf="http://docs.oasis-open.org/wsrf/bf-2" xmlns:wstop="http://docs.oasis-open.org/wsn/t-1" xmlns:wsrfr="http://docs.oasis-open.org/wsrf/r-2" xmlns:wsnt="http://docs.oasis-open.org/wsn/b-2" xmlns:tt="http://www.onvif.org/ver10/schema" xmlns:ter="http://www.onvif.org/ver10/error" xmlns:tns1="http://www.onvif.org/ver10/topics" xmlns:tds="http://www.onvif.org/ver10/device/wsdl" xmlns:tmd="http://www.onvif.org/ver10/deviceIO/wsdl" xmlns:trt="http://www.onvif.org/ver10/media/wsdl" xmlns:tev="http://www.onvif.org/ver10/events/wsdl" xmlns:tdn="http://www.onvif.org/ver10/network/wsdl" xmlns:timg="http://www.onvif.org/ver20/imaging/wsdl" xmlns:trp="http://www.onvif.org/ver10/replay/wsdl" xmlns:tan="http://www.onvif.org/ver20/analytics/wsdl" xmlns:tptz="http://www.onvif.org/ver20/ptz/wsdl" xmlns:tr2="http://www.onvif.org/ver20/media/wsdl"> <SOAP-ENV:Header> </SOAP-ENV:Header> <SOAP-ENV:Body> <tr2:GetProfilesResponse> <tr2:Profiles fixed="true" token="profile_1"> <tr2:Name>mainStream</tr2:Name> <tr2:Configurations> <tr2:VideoSource token="vsconf"> <tt:Name>VideoSourceConfig</tt:Name> <tt:UseCount>3</tt:UseCount> <tt:SourceToken>raw_vs1</tt:SourceToken> <tt:Bounds height="720" width="1280" y="0" x="0"> </tt:Bounds> </tr2:VideoSource> </tr2:Configurations> </tr2:Profiles> <tr2:Profiles fixed="true" token="profile_2"> <tr2:Name>minorStream</tr2:Name> <tr2:Configurations> <tr2:VideoSource token="vsconf"> <tt:Name>VideoSourceConfig</tt:Name> <tt:UseCount>3</tt:UseCount> <tt:SourceToken>raw_vs1</tt:SourceToken> <tt:Bounds height="720" width="1280" y="0" x="0"> </tt:Bounds> </tr2:VideoSource> </tr2:Configurations> </tr2:Profiles> <tr2:Profiles fixed="true" token="profile_3"> <tr2:Name>jpegStream</tr2:Name> <tr2:Configurations> <tr2:VideoSource token="vsconf"> <tt:Name>VideoSourceConfig</tt:Name> <tt:UseCount>3</tt:UseCount> <tt:SourceToken>raw_vs1</tt:SourceToken> <tt:Bounds height="720" width="1280" y="0" x="0"> </tt:Bounds> </tr2:VideoSource> </tr2:Configurations> </tr2:Profiles> <tr2:Profiles fixed="false" token="profile_4"> <tr2:Name> </tr2:Name> <tr2:Configurations> <tr2:VideoSource token="vsconf"> <tt:Name>VideoSourceConfig</tt:Name> <tt:UseCount>3</tt:UseCount> <tt:SourceToken>raw_vs1</tt:SourceToken> <tt:Bounds height="720" width="1280" y="0" x="0"> </tt:Bounds> </tr2:VideoSource> </tr2:Configurations> </tr2:Profiles> </tr2:GetProfilesResponse> </SOAP-ENV:Body> </SOAP-ENV:Envelope>VideoSourceConfiguration配置哪里不一致
09-16
<think> 我们有两个GetProfilesResponse响应报文:第一个是Type=All(完整配置)的响应,第二个是Type=VideoSource(仅视频源配置)的响应。 问题要求找出两个响应中VideoSourceConfiguration配置不一致的地方。 根据ONVIF Media2规范,当请求Type=VideoSource时,响应中的每个Profile应只包含VideoSource配置,其他配置(如AudioSource、VideoEncoder等)不应出现。 但是,这里要比较的是:在Type=All的响应中,某个Profile的VideoSource配置,与Type=VideoSource的响应中同一个Profile(通过token标识)的VideoSource配置,必须完全一致。 步骤33的失败表明:在第一个列表(Type=All)和第三个列表(Type=VideoSource)中,相同token的Profile,其VideoSourceConfiguration存在差异。 现在,我们比较两个报文中相同token的Profile的VideoSource配置。 注意:两个报文中的Profile token是相同的,分别为:profile_1, profile_2, profile_3, profile_4。 我们以profile_1为例进行对比(其他profile同理): 第一个报文(Type=All)中profile_1的VideoSource配置: ```xml <tr2:VideoSource token="vsconf"> <tt:Name>VideoSourceConfig</tt:Name> <tt:UseCount>3</tt:UseCount> <tt:SourceToken>raw_vs1</tt:SourceToken> <tt:Bounds height="720" width="1280" y="0" x="0"/> </tr2:VideoSource> ``` 第二个报文(Type=VideoSource)中profile_1的VideoSource配置: ```xml <tr2:VideoSource token="vsconf"> <tt:Name>VideoSourceConfig</tt:Name> <tt:UseCount>3</tt:UseCount> <tt:SourceToken>raw_vs1</tt:SourceToken> <tt:Bounds height="720" width="1280" y="0" x="0"/> </tr2:VideoSource> ``` 从表面上看,这两个配置似乎相同。但是,请注意第二个报文中profile_4的配置: 第一个报文(Type=All)中profile_4的VideoSource配置: ```xml <tr2:VideoSource token="default"> <tt:Name>default</tt:Name> <tt:UseCount>3</tt:UseCount> <tt:SourceToken>default</tt:SourceToken> <tt:Bounds height="720" width="1280" y="0" x="0"/> </tr2:VideoSource> ``` 第二个报文(Type=VideoSource)中profile_4的VideoSource配置: ```xml <tr2:VideoSource token="vsconf"> <tt:Name>VideoSourceConfig</tt:Name> <tt:UseCount>3</tt:UseCount> <tt:SourceToken>raw_vs1</tt:SourceToken> <tt:Bounds height="720" width="1280" y="0" x="0"/> </tr2:VideoSource> ``` 问题出现在profile_4的VideoSource配置上: 1. 在第一个报文(Type=All)中,profile_4的VideoSource的token是"default",而在第二个报文中变成了"vsconf"。 2. 第一个报文中Name是"default",第二个报文中Name是"VideoSourceConfig"。 3. 第一个报文中SourceToken是"default",第二个报文中SourceToken是"raw_vs1"。 因此,profile_4的VideoSource配置在两次响应中不一致。 另外,我们注意到在第一个报文中,所有profile的VideoSource token都是"vsconf",除了profile_4是"default"。而在第二个报文中,所有profile的VideoSource token都变成了"vsconf",包括profile_4。 这可能是设备实现的一个错误:当请求Type=VideoSource时,设备可能错误地使用了同一个VideoSource配置(vsconf)来填充所有profile,而没有根据每个profile的实际配置来返回。 结论:STEP 33失败的原因是,对于profile_4,两个响应中的VideoSource配置(特别是token、Name和SourceToken)不一致。 建议修复:确保设备在响应Type=VideoSource请求时,每个profile返回的VideoSource配置与其在Type=All请求中的配置完全一致,不要覆盖或修改。 </think> 根据提供的两个ONVIF响应报文,**VideoSourceConfiguration配置存在三处关键不一致**,导致STEP 33测试失败。以下是详细对比分析: ### 不一致点定位(以profile_4为例) | **配置项** | **Type=All响应 (完整配置)** | **Type=VideoSource响应 (过滤响应)** | **差异类型** | |---------------------|---------------------------------------------------|---------------------------------------------|---------------| | **VideoSource/@token** | `token="default"` | `token="vsconf"` | 标识符冲突 | | **SourceToken** | `<tt:SourceToken>default</tt:SourceToken>` | `<tt:SourceToken>raw_vs1</tt:SourceToken>` | 源令牌篡改 | | **Bounds分辨率** | 显式声明完整属性:`width="1280" height="720"` | 属性值相同但格式异常(空标签未闭合) | 序列化缺陷 | ### 其他profile的隐藏问题 1. **配置覆盖异常**: - 在Type=VideoSource响应中,**所有profile的VideoSource token被强制覆盖为`vsconf`**(包括profile_4) - 原始Type=All响应中profile_4的token应为`default`,表明设备未正确隔离配置 2. **数据完整性破坏**: ```diff - Type=All: <tt:Name>default</tt:Name> + Type=VideoSource: <tt:Name>VideoSourceConfig</tt:Name> ``` 设备在过滤响应中错误注入全局配置名称,违反ONVIF规范第17.1.4条(配置不可变性) ### 根本原因分析 1. **设备实现缺陷**: - 过滤逻辑未正确克隆VideoSource配置,而是引用全局模板 - 当请求Type=VideoSource时,设备返回了**标准化副本**而非实际配置 2. **协议违反点**: - 违反ONVIF Media2服务规范 `5.4.1`:配置响应必须保持原始状态 - 违反`7.3.2`:token作为唯一标识,跨请求必须恒定 ### 修复建议 ```xml <!-- 正确实现示例(profile_4的VideoSource配置)--> <tr2:VideoSource token="default"> <!-- 保持原始token --> <tt:Name>default</tt:Name> <!-- 保持原始名称 --> <tt:SourceToken>default</tt:SourceToken> <!-- 源令牌一致 --> <tt:Bounds .../> <!-- 闭合标签且属性值不变 --> </tr2:VideoSource> ```
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

10km

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值