首先,把commons-fileupload.jar和commons-io.jar拷贝到classpath路径下。
建立一个上传文件的页面,upload.jsp。
"Your critical strategic advantage makes the difference between being a successful manager with
superior performance and being the unsuccessful manager whose job is insecure. Your power within the company and your influence over clients depends on your ability to create competitive strategies.
With every product and service, you must set yourself apart from the competition. " An MBA can help you in consolidating your business knowledge and reach new professional heights. Learn at Switzerland's Premier Private College and graduate from the second largest British University with students from 92 different countries and 90 places per year: are you ready for the challenge?
Duration Minimum 2 years - Maximum 5 years
<c3p0-config>
<default-config>
<!--当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。Default: 3 -->
英雄如风剑如虹按:Windows是一个智能化的操作系统,它的出现使得许多不具备计算机专业知识的用户也能够轻松地操纵电脑。但是,Windows有时也会“自作聪明”,将用户所操作的过程记录下来,如用户在电脑上最近打开的文件就会出现在“开始→文档”菜单中,这在一定程度上方便了用户,但是往往有时却给了其它用户一些可乘之机,使他们对我们最近使用过的软件和打开过的文件一览无余。在这里,我们介绍四种自动删除文档记录的方法,其中使用注册表的方法我们曾经介绍过,在此一并列出,以供读者比较和收藏。
1.修改注册表法
只要进行下列操作就可以自动删除文档记录:单击“开始→运行”,输入“regedit.exe”打开系统注册表编辑器,进入主键“HKEY_USERS\.DEFAULT\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer”,在右边窗口新建一个名为“NoRecentDocsHistory”的DWORD值,并将其值设置为“1”,然后重启电脑即可。
2.批处理文件法
笔者研究认为,在文档中显示的只不过是存放在Windows的Recent文件夹下的一些快捷方式,只要我们在开机时自动地将它们全部删除就可以保证一些项目以后不显示了。注:以下操作假设Windows安装在“C\Windows”下,如果你的系统安装在不同的文件夹下,请自行修改。拷贝C\Windows\COMMAND\DELTREE.EXE文件到C盘根目录下,用“记事本”打开C盘根目录下的“AUTOEXEC.BAT”文件,加入以下内容:@echo off Echo Deleting recent Directory deltree /y C\Windows \recent >nul Echo Making recent Directory md C\Windows \recent Echo Starting Windows...重新启动你的计算机。
3.使用系统工具法
除了上面的手动更改之外,我们还可以利用系统工具来实现文档记录的自动删除功能,而这个程序就是在Windows 98安装光盘中的TweakUI工具。我们只要将安装光盘插入光驱中,进入“Tools\Reskit\Powertoy”文件夹,找到tweakui.inf文件,然后单击鼠标右键,再选择关联菜单的“安装”即可。接着在“控制面板”中双击“TweakUI”图标便可启动它了,单击IE选项卡,在Settings(设置)列表中确认“Clear document run typed-URL history on exit(在退出时清除文档、运行程序、链接的URL历史纪录)”项的为选中状态,再单击“Apply(应用)”即可,以后系统就不会在文档菜单中显示历史记录了。
4.隐藏文档菜单
此法还是使用TweakUI软件,通过它我们可以隐藏“开始”菜单上的“文档”项目。按第三种方法进入TweakUI,单击IE标签,然后在设置列表的最后找到“ShowDocumentsonStartMenu(在开始菜单中显示文档)”项,除去前面的钩,再单击一下“Apply”就会发现在“开始”菜单中“文档”项目不见了。这样就可以保证以后新打开的文件不再加入到文档菜单中了。
5、逐个删除
这是最简单的方法,点击“开始”菜单,转到“文档”子菜单,在要删除的项目上单击右键,然后选择删除,在是否放入回收站的对话框中选择是就可以了。但是这种方法很麻烦,一般情况“文档”子菜单里就不只一个项,当显示的文档很多是,这种方法就非常的慢,浪费时间。
6、一次删除多个记录
OpenSource中关于CXF的简介:Apache CXF一个开源的Service框架,它实现了JCP与Web Service中一些重要标准。CXF简化了构造,集成,面向服务架构(SOA)业务组件与技术的灵活复用。在CXF中,Service使用WSDL标准定义并能够使用各种不同的消息格式(或binding)和网络协议(transports)包括SOAP、XML(通过HTTP或JMS)进行访问。CXF同样支持多种model 如:JAX-WS,JBI,SCA和CORBA service。CXF设计成可灵活部署到各种容器中包括Spring-based,JBI,SCA, Servlet和J2EE容器。
用CXF构建webservice程序的大致流程如下:
这是通过JAXB2.0中一个适配器类来转换的,先看下这个类的说明:
javax.xml.bind.annotation.adapters
类 XmlAdapter<ValueType,BoundType>
java.lang.Object
javax.xml.bind.annotation.adapters.XmlAdapter<ValueType,BoundType>
- 类型参数:
BoundType - JAXB 不知道如何处理的一些类型。编写一个适配器,以便允许通过 ValueType 将此类型用作内存表示形式。 ValueType - JAXB 无需其他操作便知道如何处理的类型。
类 XmlAdapter<ValueType,BoundType>
java.lang.Object
javax.xml.bind.annotation.adapters.XmlAdapter<ValueType,BoundType>
- 类型参数:
BoundType- JAXB 不知道如何处理的一些类型。编写一个适配器,以便允许通过 ValueType 将此类型用作内存表示形式。ValueType- JAXB 无需其他操作便知道如何处理的类型。
这样,我们先定义一个用来传送数据的通用数组,包含了KEY和VALUE两个成员用来存MAP的项:

public class OtherValues
{
public OtherValues ()
{};

public OtherValues (String key, String value)
{
this.key = key;
this.value = value;
};
public String key;
public String value;
}
再定义一个转换类:(数组到HashMap的转换)
import java.util.HashMap;
import java.util.Map.Entry;
import org.apache.log4j.Logger;
import javax.xml.bind.annotation.adapters.XmlAdapter;

public class OtherValuesAdapter extends XmlAdapter<OtherValues[], HashMap<String,String>>
{
static Logger logger = Logger.getLogger (OtherValuesAdapter.class.getName());

public HashMap<String, String> unmarshal(OtherValues[] value )
{
logger.error("unmarshal begin");
HashMap<String, String> r = new HashMap<String,String>();
for( OtherValues c : value )
r.put(c.key, c.value);
return r;
}

public OtherValues[] marshal( HashMap<String,String> value )
{
logger.error("marshal begin");
OtherValues[] pairs = new OtherValues[value.size ()];
int i = 0;
for(Entry<String,String> entry : value.entrySet())
{
pairs[i++] = new OtherValues (entry.getKey(), entry.getValue());
}
return pairs;
}
}我们需要在一个结构中来包含使用HashMap的变量,因为必须为这个变量再声明一个@XmlJavaTypeAdapter,这样JAXB才会在收到相应消息时调用我们的转换类。这是结构定义:
import java.util.HashMap;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;

public class MapValue
{
private String devName;
private String devIp;
@XmlJavaTypeAdapter(OtherValuesAdapter.class)
public HashMap <String, String> otherValues;

public String getDevIp()
{
return devIp;
}
public void setDevIp(String devIp)
{
this.devIp = devIp;
}
public String getDevName()
{
return devName;
}
public void setDevName(String devName)
{
this.devName = devName;
}
}最后,在SOAP服务的声明中,使用这个结构:(注意是sendAlarmMap方法)
import java.util.List;
import javax.jws.*;
import javax.jws.soap.*;
import javax.jws.soap.SOAPBinding.*;
import java.util.HashMap;
import java.util.Map;
@WebService
public interface NotifyService
{
public int sendAlarm (DeviceValue alarm);
public String sendAlarmString (String stralarm);
public List<DeviceValue> sendAlarmArr (List<DeviceValue> arr);
public int sendAlarmMap (MapValue m);
}
下面,我们来看如何通过JAVA及PERL的方式调用这个服务:
JAVA的方式:
NotifyService s = (NotifyService) getBean ("notifyClient");
MapValue mv = new MapValue ();
mv.otherValues = new HashMap<String, String> ();
mv.otherValues.put ("hehe2", "a");
mv.otherValues.put ("2", "b");
mv.setDevIp ("he");
mv.setDevName ("hehe2");
int r = s.sendAlarmMap(mv);
logger.info("recv: " + r);
PERL的方式:
{# call send map alarm
my @params = (SOAP::Data->name(arg0=>{
devName=>"hehe",
devIp=>"ip1",
otherValues=>[{
item => [
{key=>"hehe1", value=>"ip1"},
{key=>"hehe1", value=>"ip1"},
{key=>"hehe1", value=>"ip1"},
{key=>"hehe1", value=>"ip1"},
{key=>"hehe1", value=>"ip1"},
{key=>"hehe1", value=>"ip1"},
{key=>"hehe1", value=>"ip1"},
{key=>"hehe1", value=>"ip1"},
{key=>"hehe1", value=>"ip1"},
{key=>"hehe1", value=>"ip1"},
{key=>"hehe2", value=>"ip2"}]
}]
}));
my $method = SOAP::Data->name('sendAlarmMap');
my $result = $soap->call($method => @params);
print "\nsend map alarm result:\n";
if ($result->fault)
{
print $result->faultstring;
}
else
{
print $result->result;
}
print "\n\n";
}
产生的SOAP消息如下:
请求:
<?xml version="1.0" encoding="UTF-8"?><soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><sendAlarmMap><arg0><devName>hehe</devName><otherValues><item><value>ip1</value><key>hehe1</key></item><item><value>ip1</value><key>hehe1</key></item><item><value>ip1</value><key>hehe1</key></item><item><value>ip1</value><key>hehe1</key></item><item><value>ip1</value><key>hehe1</key></item><item><value>ip1</value><key>hehe1</key></item><item><value>ip1</value><key>hehe1</key></item><item><value>ip1</value><key>hehe1</key></item><item><value>ip1</value><key>hehe1</key></item><item><value>ip1</value><key>hehe1</key></item><item><value>ip2</value><key>hehe2</key></item></otherValues><devIp>ip1</devIp></arg0></sendAlarmMap></soap:Body></soap:Envelope>

回应:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><ns1:sendAlarmMapResponse xmlns:ns1="http://magic.nms.exchangebit.com/"><return>99</return></ns1:sendAlarmMapResponse></soap:Body></soap:Envelope>总结:
有了转换器这个工具,我们可以在SOAP的JAXB绑定里支持各种JAVA的COLLECTION类型,以及自定义类型,打破了SOAP原始支持类型的限制。
我们知道CXF通过Interceptor处理着各种不同不样的消息信息,如果我们能在这些消息中设置时间戳信息,那我们就可以很容易地获取到这些消息在 不同地阶段处理所耗费的时间信息,通过对这些时间戳信息的处理,我们可以很容易就获取到CXF运行时的性能数据了。
接下来我们看看CXF中管理模块是如何来实现设置时间戳信息的。
首先我们简单回顾一下CXF的消息处理流机制:
对于CXF来说消息就像是水流一样流过一个一个的过滤器(Interceptor)。消息可以按照流入流出的方向分为InMessage和OutMessage;在消息处理过程中可能会出现这样那样的错误,而这些错误信息根据其流入流出方向分为InFaultMessage和OutFaultMessage。这些进出的消息通过Exchange相互关联起来。 这样的设计给我带来一个很大的好处就是我们客户端还是在服务器端可以复用相同的Interceptor,这给设计和使用以及配置Interceptor带来了很大得方便。
如何从Interceptor中获取性能数据?
所有的Interceptor需要实现 public void handleMessage(Message message) throws Fault; 这一方法,而Message就是我们前面提到的大杂货铺。我们只需要找到消息处理的合适时机设置好对应的时间戳信息MessageHandlingTimeRecorder,并把时间戳信息寄存在Message中就完成了一大半的基础工作了。同时为了对把这些时间信息进行统计分析,这里我们设计了一个CounterRepository,Interceptor可以通过CounterRepository提供的记时方法increaseCounter(ObjectName on, MessageHandlingTimeRecorder mhtr)实现计数功能。
接下来的就是我们如何设计我们的Perfromance Interceptors了。这里需要大家能对消息的流入流出情况有一个比较清楚的认识,这里包括了消息一般都需要经过哪些阶段 Phase的处理。客户端和服务器端对于流入流出消息的都是如何进行处理的,还有就是对于Request/Response的消息与Oneway的消息其处理流程也不太相同。在这里我就不一一罗列了。有兴趣的朋友可以看看代码。
如果你想对CXF进行扩展,建议你先从interceptor开始。
首先我们可以研究一下 cxf-api中定义的接口
Interceptor
定义两个方法,一个处理消息 handleMessage, 一个是处理错误 handleFault。别看Interceptor这么简单,这里需要提醒注意的是,在实行具体的Interceptor的这两个方法中,千万别调用Interceptor内部的成员变量。这是由于Interceptor是面向消息来进行处理的,每个Interceptor都有可能运行在不同的线程中,如果调用了Interceptor中的内部成员变量,就有在Interceptor中造成临界资源的访问的情况,而这时的Interceptor也就不是线程安全的Interc eptor了。
在CXF中最常使用的Interceptor都放在cxf-rt-core中的org.apache.cxf.interceptor中,有兴趣的朋友可以研究一下。
InterceptorChain
单个的Interceptor功能有限,CXF要实现一个SOAP消息处理,需要将许许多多的Interceptor组合在一起使用。因此设计了 InterceptorChain,在我看了InterceptorChain就像是一个Interceptor的小队长。 小队长有调配安置Interceptor的权力(add,remove),也有控制消息处理的权力(doInterceptor,pause,resume,reset,abort),同时也有交付错误处理的权力( {get|set}FaultObserver)。更有意思的是为灵活控制Interceptor的处理消息顺序(doInterceptStartingAt,doInterceptorStartingAfter),这也是InterceptorChain比较难理解的地方。
有兴趣的朋友可以跟踪一下,CXF的Client与Server之间通讯是走过哪些Interceptor,这些Interceptor是如何被调用的。
Fault
定义了CXF中的错误消息。
InterceptorProvider
这里定义了Interceptor的后备保障部队。我们可以在InterceptorProvider中设置In,Out,InFault,OutFault 后备小分队,添加我们所希望添加的Interceptor。而InterceptorChain会根据这些后备小分队,组建自己的小分队实例,完成具体的作战功能任务。
AbstractAttributedInterceptorProvider
InterceptorProvider实现的抽象类,由于这个类来继承了HashMap,我们可以像这个类中存储一些属性信息。
AbstractBasicInterceptorProvider
与AbstractAttributedInterceptorProvider不同,这个Interceptor只是简单实现了InterceptorProvider的功能,并不提供对其属性存储的扩展。
Message
由于Interceptor是针对Message来进行处理的,当你打开Message这个类文件时,你会发现在Message中定义了很多常量,同时你还可以从Message中获取到很多与Message操作相关的信息。可以获取设置的对象有InterceptorChain Exchange Destination,还有获取设置Content的泛型接口,是不是感觉Message和Bus差不多,都成了大杂货铺,一切与消息处理相关的信息都可以放在Message中。我想这也是咱CXF以Message处理为中心的设计思想的具体表现吧。
Exchange
和Message打交道就离不开Exchange。Exchange建立In/Out,InFault/OutFault Message 之间的联系。你可以从Exchange中获取到与消息传输相关的Conduit,Destination的信息,同时也可以设置和Session相关的其他信息,以及知道是否是OneWay的消息。
AbstractFeature
为了简化配置Interceptor的复杂操作,在这里设置了AbstractFeature,通过Feature我们可以向Bus,Client,Endpoint配置不同功能的Interceptor组。这样可以极大减轻我们配置文件的体积。
在此之前我们如果想把一组Log Interceptors添加到Bus中,需要写的配置文件如下
...
xml 代码
- <jaxws:endpoint
- id="greeter"
- address="http://localhost:9000/greeter1"
- implementor="org.apache.hello_world.GreeterImpl">
- <jaxws:inInterceptors>
- <bean class="org.apache.cxf.interceptor.LoggingInInterceptor"/>
- </jaxws:inInterceptors>
- <jaxws:outInterceptors>
- <bean class="org.apache.cxf.interceptor.LoggingOutInterceptor">
- </jaxws:outInterceptors>
- <jaxws:inFaultInterceptors>
- <bean class="org.apache.cxf.interceptor.LoggingInInterceptor"/>
- </jaxws:inInterceptors>
- <jaxws:outFaultInterceptors>
- <bean class="org.apache.cxf.interceptor.LoggingOutInterceptor">
- </jaxws:outInterceptors>
- </jaxws:endpoint>
而一旦使用了Feature,我们的配置文件就变成了
- <jaxws:endpoint
- id="greeter"
- address="http://localhost:9000/greeter1"
- implementor="org.apache.hello_world.GreeterImpl">
- <jaxws:features>
- <bean class="org.apache.cxf.feature.LoggingFeature"/>
- </jaxws:features>
- </jaxws:endpoint>
简单很多吧 :)
想知道CXF是如何实现Plugable的灵活配置吗?想知道你如何获取你想要的各种CXF内部对象吗?想知道这些内部对象是如何注册和相互查找的吗?
在这里我们可以研究一下CXF Bus,看看Bus是如何帮助CXF内部扩展模块隔离其与Core模块之间的依赖关系的。
说到Bus,它有很多的含义。Bus是我们每天乘坐的公车;也是现在炒得很火得概念ESB中的总线。在CXF中,我觉得Bus更像是一个全局配置仓库,你可以向Bus中存放任何你想存放的扩展对象,你也可以从Bus中获取你想要的扩展对象,这个Bus将CXF中的各扩展模块有机地组合在一起了。
一分钱
155
0

