About neohope

一直在努力,还没想过要放弃...

使用NiuParser进行分词及词性标注

1、下载并解压
http://www.niuparser.com/

2、语法

[USAGE]
         NiuParser-v1.3.0-mt-win.exe    <Action>        <OPTIONS>
[ACTION]
        --WS    :  Word Segmentation.
        --POS   :  Part-Of-Speech Tagging.
        --NER   :  Named Entity Recognition.
        --CHK   :  Chunking (shallow syntactic parsing).
        --CP    :  Constituent Parser.
        --DP    :  Dependency Parser.
        --SRL   :  Semantic Role Label.
[OPITION]
>>   Get Options of Word Segmentation
                 NiuParser-v1.3.0-mt-win.exe    --WS
>>   Get Options of POS Tagging
                 NiuParser-v1.3.0-mt-win.exe    --POS
>>   Get Options of Named Entity Recognition
                 NiuParser-v1.3.0-mt-win.exe    --NER
>>   Get Options of Base Phrase Chunking
                 NiuParser-v1.3.0-mt-win.exe    --CHK
>>   Get Options of Constituent Parser
                 NiuParser-v1.3.0-mt-win.exe    --CP
>>   Get Options of Dependency Parser
                 NiuParser-v1.3.0-mt-win.exe    --DP

3、测试例子
en.txt

Don't ever let somebody tell you you can't do something, not even me. 
You got a dream, you gotta protect it. 
People can’t do something themselves, they wanna tell you you can’t do it. 
If you want something, go get it. 
Period.

zh.txt

别让别人告诉你你成不了才,即使是我也不行。
如果你有梦想的话,就要去捍卫它。
那些一事无成的人想告诉你你也成不了大器。
如果你有理想的话,就要去努力实现。
就这样。

4、执行语句

NiuParser-v1.3.0-mt-win.exe --WS -c niuparser.config -in en.txt -out enws.txt
NiuParser-v1.3.0-mt-win.exe --POS -c niuparser.config -in enws.txt -out enpos.txt

NiuParser-v1.3.0-mt-win.exe --WS -c niuparser.config -in zh.txt -out zhws.txt
NiuParser-v1.3.0-mt-win.exe --POS -c niuparser.config -in zhws.txt -out zhpos.txt

5、测试结果
enpos.txt

Don't/NR ever/NN let/VV somebody/NR tell/NR you/NR you/NR can't/NN d/NN o/VV something/JJ ,/NN not/VV even/NR me./NN 
You/NR go/NN t/NN a/AD dream,/VV you/NR gotta/NR protect/NN it./NN 
People/NR can/NR ’/PU t/NN d/NN o/VV something/JJ t/NN hemselves/NN ,/PU the/DT y/NN wanna/NR tell/NR you/NR you/NR can/NR ’/PU t/NN do/VV it./NN 
If/NR you/NR want/VV something/JJ ,/NN go/NN get/VV it./NN 

zhpos.txt

别/AD 让/VV 别人/NN 告诉/VV 你/PN 你/PN 成/VV 不/AD 了/VV 才/AD ,/PU 即使/CS 是/VC 我/PN 也/AD 不/AD 行/VV 。/PU 
如果/CS 你/PN 有/VE 梦想/NN 的话/SP ,/PU 就/AD 要/VV 去/VV 捍卫/VV 它/PN 。/PU 
那些/DT 一事无成/CD 的/DEG 人/NN 想/VV 告诉/VV 你/PN 你/PN 也/AD 成/VV 不/AD 了/VV 大器/NN 。/PU 
如果/CS 你/PN 有/VE 理想/NN 的话/SP ,/PU 就/AD 要/VV 去/VV 努力/AD 实现/VV 。/PU 

使用THULANC进行分词及词性标注

1、首先到这里下载程序及模型
http://thulac.thunlp.org/

2、解压,我用的是java版本的程序

3、基本语法

java -jar THULAC_lite_java_run.jar [-t2s] [-seg_only] [-deli delimeter] [-user userword.txt] -input input_file -output output_file

其中:
-t2s                将句子从繁体转化为简体
-seg_only           只进行分词,不进行词性标注
-deli delimeter     设置词与词性间的分隔符,默认为下划线_
-filter             使用过滤器去除一些没有意义的词语,例如“可以”。
-user userword.txt  设置用户词典,用户词典中的词会被打上uw标签。词典中每一个词一行,UTF8编码(python版暂无)
-model_dir dir      设置模型文件所在文件夹,默认为models/
-input input_file   设置从文件读入,默认为命令行输入
-output output_file 设置输出到文件中,默认为命令行输出

4、测试例子
en.txt

Don't ever let somebody tell you you can't do something, not even me. 
You got a dream, you gotta protect it. 
People can’t do something themselves, they wanna tell you you can’t do it. 
If you want something, go get it. 
Period.

zh.txt

别让别人告诉你你成不了才,即使是我也不行。
如果你有梦想的话,就要去捍卫它。
那些一事无成的人想告诉你你也成不了大器。
如果你有理想的话,就要去努力实现。
就这样。

5、执行语句

java -jar THULAC_lite_java_run.jar -input en.txt -output enout.txt
java -jar THULAC_lite_java_run.jar -input zh.txt -output zhout.txt

6、测试结果
enout.txt

Don_n '_w t_g ever_nz let_x somebody_x tell_np you_np you_np can_np '_w t_g d_g o_v something_x ,_w not_np even_np me._np 
You_np got_np a_v dream_np ,_w you_np gotta_x protect_x it._x 
People_x can??_n t_g d_g o_v something_x themselves_x ,_w they_x wanna_n tell_np you_np you_np can??_n t_g do_v it._m 
If_v you_np want_x something_x ,_w go_v get_np it._m 
Period._x 

zhout.txt

别_d 让_v 别人_r 告诉_v 你你_r 成_v 不_d 了_v 才_n ,_w 即使_c 是_v 我_r 也_d 不行_a 。_w 
如果_c 你_r 有_v 梦想_n 的_u 话_n ,_w 就要_d 去_v 捍卫_v 它_r 。_w 
那些_r 一事无成_id 的_u 人_n 想_v 告诉_v 你你_r 也_d 成_v 不_d 了_v 大器_n 。_w 
如果_c 你_r 有_v 理想_n 的_u 话_n ,_w 就要_d 去_v 努力_a 实现_v 。_w 
就_d 这样_r 。_w 

使用NLTK进行分词及词性标注

1、首先是安装
1.1、安装Python 3.4
注意要用32位版本
http://www.python.org/downloads/

1.2、安装Numpy
注意两点,一是不一定所有版本都有windows安装包,二是要找支持python3.4的安装包
http://sourceforge.net/projects/numpy/files/NumPy/

1.3、安装NLTK
注意3.2版本有bug,不要用。
http://pypi.python.org/pypi/nltk

2、下载NLT Data
方法1:
在python中运行:

import nltk
nltk.download()

方法2:
到下面的地址,直接去找链接,然后自己下载解压
https://raw.githubusercontent.com/nltk/nltk_data/gh-pages/index.xml

3、进行分词
3.1、设置环境变量

set PYTHON_HOME=C:\NeoLanguages\Python34_x86
set PATH=%PYTHON_HOME%;%PATH%
set NLTK_DATA=D:\NLP\NLTK\nltk_data
@python

3.2、py文件

#!usr/bin/python

import nltk

#测试句子
sentence = "Don’t ever let somebody tell you you can’t do something, not even me. \
You got a dream, you gotta protect it. People can’t do something themselves, \
they wanna tell you you can’t do it. If you want something, go get it. Period."

#分词
tokens = nltk.word_tokenize(sentence)

#词性标注
tagged = nltk.pos_tag(tokens)

#句法分析
entities = nltk.chunk.ne_chunk(tagged)

3.3、逐句运行

D:\MyProjects\NLP\NLTK>python
Python 3.4.4 (v3.4.4:737efcadf5a6, Dec 20 2015, 19:28:18) [MSC v.1600 32 bit (In
tel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import nltk
>>> sentence = "Don’t ever let somebody tell you you can’t do something, not e
ven me. \
... You got a dream, you gotta protect it. People can’t do something themselves
, \
... they wanna tell you you can’t do it. If you want something, go get it. Peri
od."
>>> tokens = nltk.word_tokenize(sentence)
>>> tagged = nltk.pos_tag(tokens)
>>> entities = nltk.chunk.ne_chunk(tagged)

>>> tokens
['Don’t', 'ever', 'let', 'somebody', 'tell', 'you', 'you', 'can’t', 'do', 'som
ething', ',', 'not', 'even', 'me', '.', 'You', 'got', 'a', 'dream', ',', 'you',
'got', 'ta', 'protect', 'it', '.', 'People', 'can’t', 'do', 'something', 'thems
elves', ',', 'they', 'wan', 'na', 'tell', 'you', 'you', 'can’t', 'do', 'it', '.
', 'If', 'you', 'want', 'something', ',', 'go', 'get', 'it', '.', 'Period', '.']

>>> tagged
[('Don’t', 'NNP'), ('ever', 'RB'), ('let', 'VB'), ('somebody', 'NN'), ('tell',
'VB'), ('you', 'PRP'), ('you', 'PRP'), ('can’t', 'VBP'), ('do', 'VB'), ('someth
ing', 'NN'), (',', ','), ('not', 'RB'), ('even', 'RB'), ('me', 'PRP'), ('.', '.'
), ('You', 'PRP'), ('got', 'VBD'), ('a', 'DT'), ('dream', 'NN'), (',', ','), ('y
ou', 'PRP'), ('got', 'VBD'), ('ta', 'JJ'), ('protect', 'NN'), ('it', 'PRP'), ('.
', '.'), ('People', 'NNS'), ('can’t', 'VBP'), ('do', 'VBP'), ('something', 'NN'
), ('themselves', 'PRP'), (',', ','), ('they', 'PRP'), ('wan', 'VBP'), ('na', 'T
O'), ('tell', 'VB'), ('you', 'PRP'), ('you', 'PRP'), ('can’t', 'VBP'), ('do', '
VB'), ('it', 'PRP'), ('.', '.'), ('If', 'IN'), ('you', 'PRP'), ('want', 'VBP'),
('something', 'NN'), (',', ','), ('go', 'VBP'), ('get', 'VB'), ('it', 'PRP'), ('
.', '.'), ('Period', 'NNP'), ('.', '.')]

>>> entities
Tree('S', [('Don’t', 'NNP'), ('ever', 'RB'), ('let', 'VB'), ('somebody', 'NN'),
 ('tell', 'VB'), ('you', 'PRP'), ('you', 'PRP'), ('can’t', 'VBP'), ('do', 'VB')
, ('something', 'NN'), (',', ','), ('not', 'RB'), ('even', 'RB'), ('me', 'PRP'),
 ('.', '.'), ('You', 'PRP'), ('got', 'VBD'), ('a', 'DT'), ('dream', 'NN'), (',',
 ','), ('you', 'PRP'), ('got', 'VBD'), ('ta', 'JJ'), ('protect', 'NN'), ('it', '
PRP'), ('.', '.'), ('People', 'NNS'), ('can’t', 'VBP'), ('do', 'VBP'), ('someth
ing', 'NN'), ('themselves', 'PRP'), (',', ','), ('they', 'PRP'), ('wan', 'VBP'),
 ('na', 'TO'), ('tell', 'VB'), ('you', 'PRP'), ('you', 'PRP'), ('can’t', 'VBP')
, ('do', 'VB'), ('it', 'PRP'), ('.', '.'), ('If', 'IN'), ('you', 'PRP'), ('want'
, 'VBP'), ('something', 'NN'), (',', ','), ('go', 'VBP'), ('get', 'VB'), ('it',
'PRP'), ('.', '.'), Tree('PERSON', [('Period', 'NNP')]), ('.', '.')])
>>>

搭建DokuWiki(IIS)

1、下载dokuwiki的安装包
dokuwiki

2、解压文件

3、IIS安装GCI模块
(控制面板-》添加删除Windows功能)

4、IIS安装PHP模块
http://php.iis.net/

5、在IIS上添加网站,路径指向解压目录

6、IIS上将程序池修改为
“No Managed Code”

7、调整权限,让下面几个目录对IUSR可写
data
conf

8、浏览install.php

9、进行设置

10、对网站添加”IIS Request Filtering”,让下面几个目录,不可以通过HTTP进行访问
/data/
/conf/
/bin/
/inc/

11、搞定

AXIS2跳过HTTPS证书验证的几种方式

AXIS2启用HTTPS,只需要设置truststore及密码,然后对于HTTPS协议,就会自动启用SSL通信了。

System.setProperty("javax.net.ssl.trustStore", PATH_TO_TRUSTSTORE);        
System.setProperty("javax.net.ssl.trustStorePassword", PASSWORD_OF_TRUSTSTORE);

但有时,基于种种原因,比如证书链有问题,比如证书HOST有问题,比如证书本身就有问题,说多了都是泪,这是后就要绕过HTTPS的证书验证了。总起来说,AXIS2有下面几种方式可以跳过HTTPS证书验证:

1、通过设置TrustAllTrustManager来绕过证书验证
这是一种局部设置方式,方式适合用wsdl2java生成stub代码的程序来执行,比如,客户端可以:

SSLContext sslCtx = SSLContext.getInstance("TLS");
sslCtx.init(null, new TrustManager[] {new TrustAllTrustManager()}, null);
stub._getServiceClient().getOptions().setProperty(HTTPConstants.CUSTOM_PROTOCOL_HANDLER,
    new Protocol("https",(ProtocolSocketFactory)new SSLProtocolSocketFactory(sslCtx),443));

2、通过设置CUSTOM_PROTOCOL_HANDLER来绕过证书验证
这是一种全局设置的方式。

Protocol myProtocolHandler = new Protocol("https", new NeoSecureSocketFactory(), 443);
//中心端注册CUSTOM_PROTOCOL_HANDLER
messageContext.getOptions().setProperty(HTTPConstants.CUSTOM_PROTOCOL_HANDLER, myProtocolHandler);
//客户端注册CUSTOM_PROTOCOL_HANDLER
stub._getServiceClient().getOptions().setProperty(HTTPConstants.CUSTOM_PROTOCOL_HANDLER, myProtocolHandler); 

3、注册Protocol来绕过证书验证
这是一种全局设置的方式。

Protocol.registerProtocol("https", new Protocol("https", new NeoSecureSocketFactory(), 443)); 

4、最后是NeoSecureSocketFactory.java

package com.neohope.axis2test;

import javax.net.ssl.*;
import java.io.*;
import java.net.*;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;
import javax.net.SocketFactory;
import org.apache.commons.httpclient.ConnectTimeoutException;
import org.apache.commons.httpclient.params.HttpConnectionParams;
import org.apache.commons.httpclient.protocol.ProtocolSocketFactory;

/**
 *
 * @author Hansen
 */
public class NeoSecureSocketFactory implements ProtocolSocketFactory {
    
    private static SSLContext ssl = null;  
    
    private static TrustManager[ ] getTrustManagers() {
        TrustManager[ ] certs = new TrustManager[ ] {
                new X509TrustManager() {
                    public X509Certificate[ ] getAcceptedIssuers() { return null; }
                    public void checkClientTrusted(X509Certificate[ ] certs, String t) { }
                    public void checkServerTrusted(X509Certificate[ ] certs, String t) { }
                }
        };
        return certs;
    }
    
    private static SSLContext createSSLContext() {  
        try {  
            TrustManager[] trustManagers = getTrustManagers();  
            SSLContext sslContext = SSLContext.getInstance("TLS");  
            sslContext.init(null, trustManagers, null);  
  
            return sslContext;  
        } catch (KeyManagementException e) {  
            ; 
        } catch (NoSuchAlgorithmException e) { 
            ;
        }
        return null;  
    }  
  
    private static SSLContext getSSLContext() {  
        if (ssl == null) {  
            ssl = createSSLContext();  
        }  
        return ssl;  
    }  

    @Override
    public Socket createSocket(String host, int port, InetAddress clientHost, int clientPort) throws IOException, UnknownHostException {
        return getSSLContext().getSocketFactory().createSocket(host, port,  
                clientHost, clientPort); 
    }

    @Override
    public Socket createSocket(String host, int port, InetAddress clientHost, int clientPort, HttpConnectionParams params) throws IOException, UnknownHostException, ConnectTimeoutException {
        if (params == null) {  
            throw new IllegalArgumentException("Parameters may not be null");  
        }  
        int timeout = params.getConnectionTimeout();  
        SocketFactory socketfactory = getSSLContext().getSocketFactory();  
        if (timeout == 0) {  
            return socketfactory.createSocket(host, port, clientHost,  
                    clientPort);  
        }  
  
        Socket socket = socketfactory.createSocket();  
        SocketAddress localaddr = new InetSocketAddress(clientHost, clientPort);  
        SocketAddress remoteaddr = new InetSocketAddress(host, port);  
        socket.bind(localaddr);  
        try {  
            socket.connect(remoteaddr, timeout);  
        } catch (Exception e) {  
            throw new ConnectTimeoutException(e.getMessage(), e);  
        }  
  
        return socket;  
    }

    @Override
    public Socket createSocket(String host, int port) throws IOException, UnknownHostException {
         return getSSLContext().getSocketFactory().createSocket(host, port); 
    }
}

AXIS2无法从SOAP MTOM/XOP消息中获取附件

最近,同事在与其他厂商做IHE测试,测试的CASE多数都可以通过。唯独一个测试无法通过:对方需要通过MTOM/XOP消息发送一个文件到我们的服务,我们可以正常的收到消息,但无法解析消息得到附件。

经过沟通,发现另一个厂商居然是用CPP自己手动拼接的SOAP消息,也是醉了。

首先是解决了几个命名空间填写不正确的问题,调整完毕以后,AXIS2会报下面的错误:

org.apache.axiom.om.OMException: javax.xml.stream.XMLStreamException: Expected xop:Include as the sole child of an element information item (see section 3.2 of http://www.w3.org/TR/xop10/). This is due to the fact that the element (<xdsb:Document id="Document01">   </xdsb:Document>)  (OMElement obtained after axis2 processing)  that should contains the base64 value of document, is empty. But observing the same message sniffed from wireshark it seems that the Document is present.

这个问题好诡异啊。

经过一番搜索,在apache找到了答案:
由于对方发送附件时,多了一个换行符(XOP协议明确规定不允许的),导致了该错误的发生:

<xdsb:Document id="Document01"><xop:Include href="cid:1.11a262e2-bf65-1e01-28a7-000c29c7ee2b@apache.org" xmlns:xop="http://www.w3.org/2004/08/xop/include"/>
</xdsb:Document>

去掉换行符以后,就好了:

<xdsb:Document id="Document01"><xop:Include href="cid:1.11a262e2-bf65-1e01-28a7-000c29c7ee2b@apache.org" xmlns:xop="http://www.w3.org/2004/08/xop/include"/></xdsb:Document>

这个也是醉了。

大家如果收发SOAP消息,还是不要手工拼接这样写的好啊。

SUN PKIX、AXIS2及C#在HTTPS认证方式的区别

最近尝试了用两级自签名证书来验证SUN PKIX、AXIS2及C#在HTTPS认证方式的区别。
两级证书为:
1、CA证书NMyCA1024
2、服务器证书serversigned

其中,AXIS2通过验证是最简单的,
1、服务端设置serversigned证书的Key Store
2、客户端设置NMyCA1024或serversigned的Trust Store
3、通过验证。

如果要SUN PKIX通过验证(Oracle的JDK/JRE自带)
1、那需要服务端设置serversigned证书的Key Store
2、客户端设置NMyCA1024或serversigned的Trust Store
3、客户端把NMyCA1024证书导入JDK或JRE的CA证书列表cacerts
4、通过验证。

如果要C#通过验证
1、那需要服务端设置serversigned证书的P12文件
2、客户端设置NMyCA1024或serversigned的Trust Store
3、客户端双击NMyCA1024证书导入IE的CA证书列表
4、通过验证。

写在博客500篇

最近做了一些改变,删除并合并了几篇文章,把几篇非技术文章移到另外的网站,最近又重新整理了一下分类。

今天发现,经过了几年的努力,已经发布了499篇博客了,加上这一篇,已经500篇。

虽然没有什么高深的内容,访问量也不高,但一路坚持下来也并没有那么容易,还是有些成就感的。

希望自己可以保持初学者的心态、有一颗平常心;
希望自己可以保持自己的好奇心、求知欲;
希望自己可以保持自己积极、乐观的心态;
希望自己的生活可以变得更美好:)

希望后面可以慢慢加入一些比较深入的内容,如果有时间的话。

不知道博客何时可以达到1000篇,希望自己可以继续坚持下去。

IHE测试ITI-11与ITI-12的WSDL的问题分析

前两天,公司同事在搞IHE测试的内容,在准备其中的两个测试ITI-11与ITI-12时,发现通过VS自带的WSDL命令是无法生成相应代码的。

其具体的WSDL内容,大家可以Google下面的内容来查找:
Appendix A: Web Service Definition for Retrieve Specific Information for Display and Retrieve Document for Display Transaction

经过一些尝试,发现:
1、该附录中,有两个WSDL文件,两个只差一行
2、两个文件格式都是错误的

这标准出的也太坑爹了吧。

具体修改方式如下:
1、字符集修改为utf-8
2、在文件最后,增加节点结束节点“definitions”
3、types节点增加前缀,变为“s:types”
4、所有的mime:content type=”text/html”,都修改为mime:content type=”text/xml”
然后就OK了

修改后的WSDL文件如下:

<?xml version="1.0" encoding="utf-8"?>
<definitions 
  xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
	xmlns:s="http://www.w3.org/2001/XMLSchema"
	xmlns:s0="http://rsna.org/ihe/IHERetrieveForDisplay"
	xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/" 
	xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"
	targetNamespace="http://rsna.org/ihe/IHERetrieveForDisplay" 
	xmlns="http://schemas.xmlsoap.org/wsdl/">
 <!-- Defines the types available for the parameters -->
 <!-- May also include the return type definitions -->
	<s:types>
		<s:schema elementFormDefault="qualified" targetNamespace="http://rsna.org/ihe/IHERetrieveForDisplay">
 <!-- Add any items that control the returned values list or type here -->
 <!-- Add or remove items in the actual supplied WSDL to show the available types. -->
			<s:simpleType name="summaryRequestType">
				<s:restriction base="s:string">
					<s:enumeration value="SUMMARY" />
					<s:enumeration value="SUMMARY-RADIOLOGY" />
					<s:enumeration value="SUMMARY-CARDIOLOGY" />
					<s:enumeration value="SUMMARY-LABORATORY" />
					<s:enumeration value="SUMMARY-SURGERY" />
					<s:enumeration value="SUMMARY-EMERGENCY" />
					<s:enumeration value="SUMMARY-DISCHARGE" />
					<s:enumeration value="SUMMARY-ICU" />
					<s:enumeration value="SUMMARY-RX" />
				</s:restriction>
			</s:simpleType>

			<s:simpleType name="listRequestType">
				<s:restriction base="s:string">
					<s:enumeration value="LIST-ALLERGIES" />
					<s:enumeration value="LIST-MEDS" />
				</s:restriction>
			</s:simpleType>
 <!-- Please list all content types available, and remove those not available. -->
			<s:simpleType name="contentType">
				<s:restriction base="s:string">
					<s:enumeration value="text/html" />
				</s:restriction>
			</s:simpleType>

 <!-- Indicates that this item is a returned rows restriction -->
			<s:simpleType name="ReturnedResultCount" type="s:positiveInteger" />
 <!-- Please use the string "Search" as a prefix for all search criteria, and list below -->
 <!-- Indicates that this item is a search string -->
			<s:simpleType name="SearchString" type="s:string" />

		</s:schema>
	</s:types>
	<message name="RetrieveSummaryInfoHttpGetIn">
  <!-- Add other parameters here if they are available, using types defined above. -->
		<part name="requestType" type="summaryRequestType" />
		<part name="patientID" type="SearchString" />
		<part name="lowerDateTime" type="s:dateTime" />
		<part name="upperDateTime" type="s:dateTime" />
		<part name="mostRecentResults" type="ReturnedResultCount" />
	</message>
	<message name="RetrieveSummaryInfoHttpGetOut">
  <!-- If a complex type is defined for the return value, then it is suggested that -->
 <!-- it be used here instead of s0:string. If a complex type is allowed as one -->
 <!-- of the options, but an arbitrarily formatted string is also allowed, then create -->
 <!-- a union type here that allows either option. -->
		<part name="Body" element="s0:string" />
	</message>
	<message name="RetrieveListInfoHttpGetIn">
 <!-- Add other parameters here if they are available, using types defined above. -->
		<part name="requestType" type="listRequestType" />
		<part name="patientID" type="SearchString" />
	</message>
	<message name="RetrieveListInfoHttpGetOut">
 <!-- If a complex type is defined for the return value, then it is suggested that -->
  <!-- it be used here instead of s0:string. If a complex type is allowed as one -->
 <!-- of the options, but an arbitrarily formatted string is also allowed, then create -->
 <!-- a union type here that allows either option. -->
		<part name="Body" element="s0:string" />
	</message>
	<message name="RetrieveDocumentHttpGetIn">
 <!-- Add other parameters here if they are available, using types defined above. -->

 <!-- It is recommended that one of the sub-types of SearchUID is chosen here -->
 <!-- Especially if SearchStudyUID is allowed, then the display client can know that -->
  <!-- it is permissible to use a dicom uid here -->
		<part name="documentUID" type="SearchString" />
		<part name="contentType" type="contentType" />
	</message>
	<message name="RetrieveDocumentHttpGetOut">
 <!-- If a complex type is defined for the return value, then it is suggested that -->
 <!-- it be used here instead of s:string. If a complex type is allowed as one -->
  <!-- of the options, but an arbitrarily formatted string is also allowed, then create -->
 <!-- a union type here that allows either option. -->
		<part name="Body" element="s:string" />
	</message>

	<portType name="IHERetrieveForDisplayHttpGet">
		<operation name="RetrieveSummaryInfo">
			<input message="s0:RetrieveSummaryInfoHttpGetIn" />
			<output message="s0:RetrieveSummaryInfoHttpGetOut" />
		</operation>
		<operation name="RetrieveListInfo">

			<input message="s0:RetrieveListInfoHttpGetIn" />
			<output message="s0:RetrieveListInfoHttpGetOut" />
		</operation>
		<operation name="RetrieveDocument">
			<input message="s0:RetrieveDocumentHttpGetIn" />
			<output message="s0:RetrieveDocumentHttpGetOut" />
		</operation>
	</portType>

	<binding name="IHERetrieveForDisplayHttpGet" type="s0:IHERetrieveForDisplayHttpGet">
		<http:binding verb="GET" />
		<operation name="RetrieveSummaryInfo">
			<http:operation location="/IHERetrieveSummaryInfo" />
			<input>
				<http:urlEncoded />
			</input>
			<output>
        <mime:content type="text/xml" />
				<!--mime:content type="text/html" /-->
			</output>
		</operation>
		<operation name="RetrieveListInfo">
			<http:operation location="/IHERetrieveListInfo" />
			<input>
				<http:urlEncoded />
			</input>
			<output>
        <mime:content type="text/xml" />
				<!--mime:content type="text/html" /-->
			</output>
		</operation>

		<operation name="RetrieveDocument">
			<http:operation location="/IHERetrieveDocument" />
			<input>
				<http:urlEncoded />
			</input>
      <!-- The type of the output should be restricted on a per-server basis to the types -->
      <!-- actually provided. -->
			<output>
        <mime:content type="text/xml" />
				<!--mime:content type="text/html" />
				<mime:content type="application/x-hl7-cda-level-one+xml" />
				<mime:content type="application/pdf" />
				<mime:content type="image/jpeg" /-->
			</output>
		</operation>
	</binding>
 <!-- Bind the actual service here -->
	<service name="IHERetrieveForDisplay">

		<port name="IHERetrieveForDisplayHttpGet" binding="s0:IHERetrieveForDisplayHttpGet">
			<http:address location="http://localhost/" />
		</port>
	</service>
</definitions>

Spring通过注解加载Bean的基本原理浅析(C#版)

这第一篇,同样讲的是spring的IOC功能,是如何实现通过注解来加载Bean文件的。
这是java版本的姐妹篇,C#版本。

文章原创,转载请注明出处www.neohope.com

经过无限精简之后,整体流程为:
1、初始化bean工厂
bean工厂根据配置,加载带有指定attribute的类,并放到了Dictionary中
2、从bean工厂获取一个bean
通过bean的id,实例化一个类,并返回

需要的前置知识为:
1、spring的基本知识
2、反射

然后是源码:
1、TestAttribute.cs
这是个Attribute类,声明了一个新的注解类型,用于表示bean及bean的名字

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace TestAttribute
{
    [AttributeUsage(AttributeTargets.Class)]
    class TestAttribute : System.Attribute
    {
        public String Ntype { get; set; }
        public String Nname { get; set; }
        public String Nauthor { get; set; }
        public String Nversion { get; set; }
        public String Nmsg { get; set; }
    }
}

2、TestBean.cs
这是个Bean,使用了Attribute作为标识,是用于具体加载的类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace TestAttribute
{
    [TestAttribute(Nname = "testbean", Nauthor = "neohope", Ntype = "BEAN", Nmsg = "this is just a message", Nversion = "1.0")]
    class TestBean
    {
        public String name;
        public int age;
        public String sex;
    }
}

3、ClassPathScanner.cs
通过指定assembly名,扫描assembly下所有的类型

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;

namespace TestAttribute
{
    /// <summary>
    /// The class path scanner
    /// </summary>
    class ClassPathScanner
    {
        /// <summary>
        /// Get all assemblies in current domain <see cref="System.Reflection.Assembly"/>.
        /// </summary>
        /// <returns>string set of assembly name</returns>
        public static String[] FindAllAssembliesInCurrentDomain()
        {
            List<String> result = new List<String>();
            foreach (System.Reflection.Assembly assembly in System.AppDomain.CurrentDomain.GetAssemblies())
            {
                result.Add(assembly.GetName().Name);
            }

            return result.ToArray();
        }

        /// <summary>
        /// Get all module in current assembly
        /// </summary>
        /// <returns>string set of module name</returns>
        public static String[] FindAllModuleInThisAssembly()
        {
            List<String> result = new List<String>();
            //Assembly thisAssembly = this.GetType().Assembly;
            Assembly thisAssembly = System.Reflection.Assembly.GetExecutingAssembly();
            foreach (Module item in thisAssembly.GetModules())
            {
                result.Add(item.Name);
            }

            return result.ToArray();
        }


        /// <summary>
        /// Get all type in current assembly
        /// </summary>
        /// <returns>string set of type name</returns>
        public static String[] FindAllTypeInThisAssembly()
        {
            List<String> result = new List<String>();
            //Assembly thisAssembly = this.GetType().Assembly;
            Assembly thisAssembly = System.Reflection.Assembly.GetExecutingAssembly();
            foreach (Type item in thisAssembly.GetTypes())
            {
                result.Add(item.Name); 
            }

            return result.ToArray();
        }

        /// <summary>
        /// Get all type in the assembly
        /// </summary>
        /// <param name="assemblyName">the name of the assembly</param>
        /// <returns>Type set in the assembly</returns>
        public static Type[] FindAllTypeInAssemblyByName(String assemblyName)
        {
            Assembly theAssembly = null;
            foreach (System.Reflection.Assembly assembly in System.AppDomain.CurrentDomain.GetAssemblies())
            {
                if (assembly.GetName().Name.Equals(assemblyName))
                {
                    theAssembly = assembly;
                    break;
                }
            }
            if (theAssembly == null) return new Type[] { };

            List<Type> result = new List<Type>();
            foreach (Type item in theAssembly.GetTypes())
            {
                result.Add(item);
            }

            return result.ToArray();
        }
    }
}

4、ClassAttributeScanner.cs
工厂类,初始化时,通过attribute过滤bean,并将bean的名称及type放到dictionary中
获取实例时,通过bean名称,获取type,并实例化,返回

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;

namespace TestAttribute
{
    internal class ClassAttributeScanner
    {
        /// <summary>
        /// Dictionary of bean name and bean class
        /// </summary>
        private static Dictionary<String, Type> beanDict = new Dictionary<string, Type>();

        /// <summary>
        ///  Load all bean class with attribute from package
        /// </summary>
        /// <param name="assemblyName">the name of the assembly</param>
        /// <returns></returns>
        protected static void loadBeanTypes(String assemblyName)
        {
            Type[] allTypes = ClassPathScanner.FindAllTypeInAssemblyByName(assemblyName);
            foreach (Type aType in allTypes)
            {
                Attribute attribute  = (TestAttribute)Attribute.GetCustomAttribute(aType, typeof(TestAttribute));
                if (attribute == null) continue;

                TestAttribute ta = (TestAttribute)attribute;
                String beanName = ta.Nname;
                beanDict[beanName] = aType;
            }
        }

        /// <summary>
        /// init the bean factory
        /// </summary>
        /// <param name="assemblyName">the name of the assembly</param>
        /// <returns></returns>
        public static void InitBeanFactory(String assemblyName)
        {
            loadBeanTypes(assemblyName);
        }

        public static Object GetBean(String beanName)
        {
            Type theType = beanDict[beanName];
            if (theType != null)
            {
                //return theType.Assembly.CreateInstance(theType.FullName); 
                return Activator.CreateInstance(theType);
            }
            else
            {
                return null;
            }
        }
    }
}

5、Program.cs
程序入口

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace TestAttribute
{
    class Program
    {
        private static void Main(string[] args)
        {
            //String[] ret = ClassPathScanner.FindAllAssembliesInCurrentDomain();
            //String[] ret = ClassPathScanner.FindAllModuleInThisAssembly();
            //String[] ret = ClassPathScanner.FindAllTypeInThisAssembly();
            //foreach (string s in ret) Console.WriteLine(s);

            ClassAttributeScanner.InitBeanFactory("TestAttribute");
            TestBean bean = (TestBean)ClassAttributeScanner.GetBean("testbean");
            bean.name = "neohope";
        }
    }
}

文章原创,转载请注明出处www.neohope.com