开门见山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);
}
}