開門見山CXF 一個webService框架,一般互聯網基本使用Http+Json 來交互數據,但是國家項目例如稅局、電網、銀行使用CXF 還有很多。原因估計是因爲他們需要給不同開發語言提供服務。這樣CXF 價值體現出來。那麼我們今天剛好需要調用別人的CXF服務。目前我們使用的是SpringBoot 所以從導入cxf jar 開始。
- 配置pom.xml 一個是基本jar 一個安全認證jar
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-spring-boot-starter-jaxws</artifactId>
<version>3.2.4</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-ws-security</artifactId>
<version>3.2.4</version>
</dependency>
- 工具類 這個方法主要通過加載配置文件獲取文件的值。
public class CXFUtils {
private static final Logger log = LoggerFactory.getLogger(CXFUtils.class);
private static Properties keyStoreProperties = null;
private static final String keyStoreConfigFilePath = "you.properties";
public static Properties getKeyStoreConfigFile() {
if (keyStoreProperties == null) {
keyStoreProperties = new Properties();
InputStream in = WebServiceCXFTest.class.getClassLoader().getResourceAsStream(keyStoreConfigFilePath);
try {
keyStoreProperties.load(in);
} catch (IOException e) {
log.error("keyStore配置文件加載失敗.");
}
}
return keyStoreProperties;
}
}
- 實現CallbackHandler 回調接口 主要認證通過設置密碼passwd is the password associated to the identifier, 在創建動態客戶端 中會使用。
public class WSAuthHandler implements CallbackHandler {
@Override
public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
Properties keyStoreConfigFile = CXFUtils .getKeyStoreConfigFile();
for (int i = 0; i < callbacks.length; i++) {
WSPasswordCallback pc = (WSPasswordCallback) callbacks[i];
// 這裏必須設置密碼,否則會拋出:java.lang.IllegalArgumentException: pwd == null
// but a password is needed
pc.setPassword(keyStoreConfigFile.getProperty("org.apache.ws.security.crypto.merlin.alias.password"));
}
}
}
- 創建動態客戶端 這個核心就是需要訪問兼容Https 請求。
public static Client getClient() {
JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance();
Properties keyStoreConfigFile = getKeyStoreConfigFile();
Client client = dcf.createClient(keyStoreConfigFile.getProperty("bjtax.wss.wsdlUrl"));
HTTPConduit conduit = (HTTPConduit) client.getConduit();
HTTPClientPolicy httpClientPolicy = new HTTPClientPolicy();
httpClientPolicy.setAutoRedirect(true);//不設置 將報錯重定向
conduit.setClient(httpClientPolicy);
Map<String, Object> outProps = new HashMap<String, Object>();
outProps.put(ConfigurationConstants.ACTION, ConfigurationConstants.USERNAME_TOKEN + " "
+ ConfigurationConstants.SIGNATURE + " " + ConfigurationConstants.TIMESTAMP);//這個和第三方配置一致就可以
outProps.put(ConfigurationConstants.USER, keyStoreConfigFile.getProperty("bjtax.wss.username"));//第三方分配的用戶
outProps.put(ConfigurationConstants.SIGNATURE_USER, keyStoreConfigFile.getProperty("bjtax.wss.signature.user"));//簽名用戶
outProps.put(ConfigurationConstants.SIG_KEY_ID,
keyStoreConfigFile.getProperty("bjtax.wss.signatureKeyIdentifier"));
outProps.put(ConfigurationConstants.PASSWORD_TYPE, keyStoreConfigFile.getProperty("bjtax.wss.passwordType"));
outProps.put(ConfigurationConstants.PW_CALLBACK_CLASS,
keyStoreConfigFile.getProperty("bjtax.wss.passwordCallbackClass"));//回調方法
outProps.put(ConfigurationConstants.SIG_PROP_FILE, keyStoreConfigFilePath);//jsk 認證文件
WSS4JOutInterceptor wss4jOut = new WSS4JOutInterceptor(outProps);
client.getOutInterceptors().add(wss4jOut);
return client;
}
- 解析xml 和實體轉化
public class XStreamConvertor<T extends Mto> {
private static Map<String,XStreamMarshaller> xstreamCache = new ConcurrentHashMap<String,XStreamMarshaller>();
private static final String XML_TAG = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<tiripPackage xsi:type=\"tiripPackage\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema\" xmlns=\"http://www.chinatax.gov.cn/dataspec/\">";
private static final String GBK = "UTF-8";
public String toXml(T pojo) throws BusinessException {
String clzName = pojo.getClass().getName();
XStreamMarshaller xstreamMarshaller = xstreamCache.get(clzName);
if(xstreamMarshaller == null) {
xstreamMarshaller = new XStreamMarshaller();
xstreamMarshaller.setEncoding(GBK);
xstreamMarshaller.setStreamDriver(new XppDriver(new XmlFriendlyNameCoder("_-", "_")));
xstreamCache.put(clzName, xstreamMarshaller);
}
XStream xStream = xstreamMarshaller.getXStream();
xStream.processAnnotations(pojo.getClass());
return XML_TAG + xStream.toXML(pojo).replaceAll("<tiripPackage>", "").replaceAll(""", "\"");
}
@SuppressWarnings("unchecked")
public T fromXml(Class<T> clz,String xml) {
String clzName = clz.getName();
XStreamMarshaller xstreamMarshaller = xstreamCache.get(clzName);
if(xstreamMarshaller == null) {
xstreamMarshaller = new XStreamMarshaller();
xstreamMarshaller.setEncoding(GBK);
xstreamMarshaller.setStreamDriver(new XppDriver(new XmlFriendlyNameCoder("_-", "_")));
xstreamCache.put(clzName, xstreamMarshaller);
}
XStream xStream = xstreamMarshaller.getXStream();
xStream.setClassLoader(clz.getClassLoader());
xStream.processAnnotations(clz);
return (T) xStream.fromXML(xml);
}
}