??xml version="1.0" encoding="utf-8" standalone="yes"?> openfire服务器是Zxmpp协议的,XMPP支持两种文g传输协议,SOCKS5 Bytestreams?In-Band BytestreamsQSOCKS5是直接发送二q制,而IBB是将文g转成base64码进行然后用message的Ş式进行传输,我这里仅实现了SOCKS5的文件代理传输?br />SOCKS5文g传输需要用C个协议,XEP-0065和XEP-0096 协商q程是三方互相发送xml来交换信息的q程Q通俗点就是三个h沟通一下传什么文件和怎么传文件?br />首先遵@XMP-0096协议Q初始方l目标方发送包含文件信息的xml q时q入XEP-0065协议阶段 代理方回复信息,告知初始方代理的jid、IP、端口等信息 然后p入连接阶D,也就是初始方和目标方分别和代理徏立socks5q接的过E。(关于SOCKS5协议q接Q我之后会补充)?br />目标ҎC理信息后和代理徏立socketq接(使用SOCKS5协议q接)Q连接成功后通知初始方用的代理jid 初始Ҏ到回复信息后p入二q制传输阶D,q时可以开始发送二q制了 {初始方流发送完毕后把socket关闭传输就完成了文件的传输?/p>
注意Qtype为result的回复信息用的id一定要和请求的信息id一栗?/font>
{
var array:Array = [];
array.push(new Vga("a",10));
array.push(new Vga("c",2));
array.push(new Vga("f",1.3));
array.push(new Vga("d",1.1));
array.push(new Vga("e",16));
array.push(new Vga("b",0));
trace(array.toString());
//output: [a,10],[c,2],[f,1.3],[d,1.1],[e,16],[b,0]
var defaultSort:Array = array.sort();//默认排序
trace(defaultSort.toString());
//output: [a,10],[b,0],[c,2],[d,1.1],[e,16],[f,1.3]
var sortFunArray:Array = array.sort(sortFun);//使用自定义方法排?/span>
trace(sortFunArray.toString());
//output: [b,0],[d,1.1],[f,1.3],[c,2],[a,10],[e,16]
}
/**自定义排序方?/span>*/
public function sortFun(a:Vga,b:Vga):int{
if(a.price < b.price){
return -1; //a在前,b在后
}else if(a.price == b.price){
return 0; //ab位置不变
}else{
return 1; //b在前,a在后
}
}
/**排序VO对象*/
public class Vga
{
public var name:String;
public var price:Number;
public function Vga(name:String,price:Number)
{
this.name = name;
this.price = price;
}
public function toString():String{
return "["+this.name+","+this.price+"]";
}
}
ArrayCollection排序
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
<mx:Script>
<![CDATA[
import mx.collections.SortField;
import mx.collections.Sort;
import mx.collections.ArrayCollection;
private var acSort:ArrayCollection=
new ArrayCollection([{id:0,userName:"zhangSan",age:21},
{id:2,userName:"liSi",age:24},
{id:1,userName:"wangWu",age:31}]);
private function sortAc():ArrayCollection{
var sort:Sort=new Sort();
//按照ID升序排序
sort.fields=[new SortField("id")];
//按照userName降序排序
sort.fields=[new SortField("userName",true,true)];
//先按ID升序,再按userName降序
sort.fields[new SortField("id"),new SortField("userName",true,true)];
acSort.sort=sort;
acSort.refresh();//更新
return acSort;
}
/*
其实看看API׃目了?br /> SortField () 构造函?nbsp;
public function SortField(name:String = null,
caseInsensitive:Boolean = false,
descending:Boolean = false,
numeric:Object = null)
参数
name:String (default = null) — 此字D는来进行比较的属性的名称。如果该对象为简单类型,则传?nbsp;null?nbsp;
caseInsensitive:Boolean (default = false) — 在对字符串进行排序时Q指C比较运符是否忽略值的大小写?br /> descending:Boolean (default = false) — 指示比较q算W是否按降序排列目?nbsp;
numeric:Object (default = null) — 指示比较q算W是否按~号而不按字母顺序比较排序项目?nbsp;
*/
]]>
</mx:Script>
</mx:Application>
]]>
XEP-0096定义文g传输协议Q提供了一个模块化框架使能交换被传输文件的信息以及参数的协商,也就是在传输文g之前协商要传输的文件信息?br />XEP-0065定义SOCKS5传输标准协议,提供用于在Q意两个XMPP用户之间建立字节ƈq行文g传输?br />Ҏ我的理解Q文件传输的q程分ؓ协商Q徏立socks5q接Q二q制传输q三个阶D?br />协商的过E最复杂Q然后是建立q接Q传输就比较单,下面一个一个来?br />协商包括初始斏V目标方、代理方Q初始方是发送文件方Q目标方x件接收方Q代理方是socks5代理服务器,<iq to="android@192.168.1.113/Spark 2.6.3" type="set" id="iq_13" from="iphone@192.168.1.113/xiff">
<si profile="http://jabber.org/protocol/si/profile/file-transfer" mime-type="text/plain" id="82B0C697-C1DE-93F9-103E-481C8E7A3BD8" xmlns="http://jabber.org/protocol/si">
<feature xmlns="http://jabber.org/protocol/feature-neg">
<x xmlns="jabber:x:data" type="form">
<field var="stream-method" type="list-single">
<option><value>http://jabber.org/protocol/bytestreams</value></option>
<option><value>http://jabber.org/protocol/ibb</value></option>
</field>
</x>
</feature>
<file xmlns="http://jabber.org/protocol/si/profile/file-transfer" name="img0545.png" size="152443"><desc>send</desc></file>
</si>
</iq>
目标Ҏ收到信息后发送回执,表示同意接收文g<iq id="iq_13" to="iphone@192.168.1.113/xiff" from="android@192.168.1.113/Spark 2.6.3" type="result">
<si xmlns="http://jabber.org/protocol/si">
<feature xmlns="http://jabber.org/protocol/feature-neg">
<x xmlns="jabber:x:data" type="submit">
<field var="stream-method">
<value>http://jabber.org/protocol/bytestreams</value>
<value>http://jabber.org/protocol/ibb</value>
</field>
</x>
</feature>
</si>
</iq>
初始方给服务器发送信息,h提供代理服务?/p>
<iq id="iq_15" type="get"><query xmlns="http://jabber.org/protocol/disco#items" /></iq>
服务器回复信息,告知可用的代?/p>
<iq type="result" id="iq_15" to="iphone@192.168.1.113/xiff">
<query xmlns="http://jabber.org/protocol/disco#items">
<item jid="proxy.192.168.1.113" name="Socks 5 Bytestreams Proxy"/>
<item jid="pubsub.192.168.1.113" name="Publish-Subscribe service"/>
<item jid="conference.192.168.1.113" name="公共戉K"/>
<item jid="search.192.168.1.113" name="User Search"/>
</query>
</iq>
q里选择name=“Socks 5 Bytestreams Proxy”的代理,初始方给q个代理发送信息获取代理连接信?/p>
<iq id="iq_17" to="proxy.192.168.1.113" type="get"><query xmlns="http://jabber.org/protocol/bytestreams" /></iq>
<iq type="result" id="iq_17" from="proxy.192.168.1.113" to="iphone@192.168.1.113/xiff">
<query xmlns="http://jabber.org/protocol/bytestreams">
<streamhost jid="proxy.192.168.1.113" host="192.168.1.113" port="7777"/>
</query>
</iq>
初始ҎC理信息后代理的信息发送给目标?/p>
<iq to="android@192.168.1.113/Spark 2.6.3" type="set" id="iq_19" from="iphone@192.168.1.113/xiff">
<query xmlns="http://jabber.org/protocol/bytestreams" mode="tcp" sid="82B0C697-C1DE-93F9-103E-481C8E7A3BD8">
<streamhost port="7777" host="192.168.1.113" jid="proxy.192.168.1.113" />
</query>
</iq>
<iq id="iq_19" to="iphone@192.168.1.113/xiff" type="result" from="android@192.168.1.113/Spark 2.6.3">
<query xmlns="http://jabber.org/protocol/bytestreams">
<streamhost-used jid="proxy.192.168.1.113"/>
</query>
</iq>
初始方开始与代理建立socketq接(也用SOCKS5协议)Q连接成功后l代理发送请求,要求ȀzL件流<iq to="proxy.192.168.1.113" type="set" id="iq_21" from="iphone@192.168.1.113/xiff">
<query xmlns="http://jabber.org/protocol/bytestreams" sid="82B0C697-C1DE-93F9-103E-481C8E7A3BD8">
<activate>android@192.168.1.113/Spark 2.6.3</activate>
</query>
</iq>
代理回复ȀzL功信?/p>
<iq type="result" id="iq_21" from="proxy.192.168.1.113" to="iphone@192.168.1.113/xiff"/>
]]>
1.修改web.xml文g?/p>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>*.action</url-pattern>
</filter-mapping>
只让qo器对加有.action后缀的\径有效,如果需要拦?jspQ加?.jspp了?/p>
但是q样如果有无后缀名的urlQ如/demo/Q就不能qo?/p>
2.修改struts2核心jar中的default.properties文g
把struts.action.extension=action,,
改ؓstruts.action.extension=action,do,jsp,
但我改了之后发现Ҏ没效果,不知Z
3.自定义一?/span>l承StrutsPrepareAndExecuteFilter的过滤器Q将配置换成自己自定义的qo器。(推荐此法Q?/span>
修改web.xml
q种Ҏ试验成功
ORM~存{略
1.事务U缓?session level cache)
session生命周期的缓?关闭sessionx?/p>
2.应用U?q程U缓?sessionFactory level cache)
某个应用中的׃n~存,多个事务可以׃n,在sessionFactory层实?所有sessionFactory创徏的session可以׃n.
3.分布式缓?/p>
多个JVM׃n的缓?通过q程机制实现~存数据同步,L实例修改数据,所有的JVM都要更新~存.
Hibernate数据~存
1.内部~存(session level)一U缓?/span>
是事务的缓?session中维护的一个Map,Map的key是包含了数据cd和id,从数据库加蝲的数据都会进入Map~存?通过session加蝲数据时会先在session~存里找,一U缓存是session的private数据,session实例消亡清除了,在应用中׃持在一ơ请求的开始和l束之间.
一般由Hibernate自动l护,也支持手动维?/p>
session.evit(Object obj) 持久化对象从一U缓存中清除.
session.clear() 清空一U缓?/p>
session.contains(Object obj) 判断指定的对象是否存在于一U缓存中.
session.flush() h一U缓存区的内?使缓存与数据库数据保持同?
2.二~存(sessionFactory level)
包含了应用和分布式的缓?由本sessionFactory的所有session实例׃n,session操作时会先查一U缓?然后查二U缓?最后再查物理数据库.要用二U缓存必要q行配置.
适合用缓存的数据
1.不会被其他应用修?/p>
包括直接用JDBC修改{?因ؓ其他应用修改了数据之后hibernateq不知道,不能自动更新~存,不过可以手动更新~存
2.数据大小可以接受,毕竟内存资源也不?/p>
3.数据更新频率?比如数据字典{常量数?
4.可能被系l频J?/p>
5.非关键的数据
6.不会被ƈ发访问的数据
常用的二U缓存插?/p>
EHCache org.hibernate.cache.EhCacheProvider
OSCache org.hibernate.cache.OSCacheProvider
SwarmCahe org.hibernate.cache.SwarmCacheProvider 提供了分布式
JBossCache org.hibernate.cache.TreeCacheProvider 提供了分布式
EHCache二~存配置Ҏ
1.启用二~存首先要在hibernate.cfg.xml配置
<hibernate-configuration>
<session-factory>
<!-- 配置二~存插gEHCache的Providerc?->
<property name="hibernate.cache.provider_class">
org.hibernate.cache.EhCacheProvider
</property>
<!-- 启动"查询~存" -->
<property name="hibernate.cache.use_query_cache">
true
</property>
</session-factory>
</hibernate-configuration>
2.然后配置cache的配|文件ehcache.xml
<ehcache>
<!-- maxElementsInMemory为缓存对象的最大数?
eternal讄是否永远不过?
timeToIdleSeconds对象处于I闲状态的最多秒?
timeToLiveSeconds对象处于~存状态的最多秒?
overflowtodisk内存不时是否启用磁盘缓?-->
<diskStore path="java.io.tmpdir"/>
<defaultCache maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="300" timeToLiveSeconds="600" overflowToDisk="true"/>
</ehcache>
3.最后要在映文?**.hbm.xml中指定实体的~存同步{略
<?xml version="1.0" encoding='UTF-8'?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >
<hibernate-mapping>
<class>
<!-- 讄该持久化cȝ二~存q发讉K{略-->
<cache usage="read-write"/>
<set name = "xxx">
<cache usage="read-only" />
</set>
</class>
</hibernate-mapping>
hibernate提供的缓存同步策?可以在usage中设|?/p>
read-only
只读
nonstrict-read-write
更新频率不高
read-write
严格可读?/p>
transactional(Ecache不支?
事务型缓?/p>