最近项目里面需要将某些服务以webservice的形式向外部应用暴露API,在JAVA领域有很多选择,如:CXF,XFIRE,JAXWS等,考虑到不想引入太多依赖,就选择了使用JDK自带的JAXWS。
直接上代码吧,首先是Spring与JAXWS的集成:
<bean class="org.springframework.remoting.jaxws.SimpleHttpServerJaxWsServiceExporter"> <property name="server" ref="server" /> <property name="basePath" value="/ws/" /> <property name="authenticator" ref="authenticator" /> </bean>
上面代码使用了SimpleHttpServerJaxWsServiceExporter这个spring的类,主要是因为这个类提供了一个authenticator属性,可以达到验证IP的目的,而另外一个SimpleJaxWsServiceExporter则没有。
解释下上面3个属性的含义,server使用jdk自带的httpserver搭建了一个简易的http服务器来暴露web服务,这个server的配置可以通过spring配置如下:
<bean id="server" class="org.springframework.remoting.support.SimpleHttpServerFactoryBean"> <property name="port" value="8890" /> </bean>
authenticator定义验证器,此验证器需要继承com.sun.net.httpserver.Authenticator类,然后实现它的autenticate方法来验证IP地址,具体如下:
public class ApprovalSystemServiceAuthenticator extends Authenticator {
public Result authenticate(HttpExchange httpexchange) {
String ip = httpexchange.getRemoteAddress().getAddress().getHostAddress();
if (!("127.0.0.1".equals(ip))) {
return new Authenticator.Failure(403);
}
return new Authenticator.Success(null);
}
}
这样就完成了整个验证IP地址的过程了。
上面讲到了对客户端IP的验证,但是我们的应用有可能会在SOAP message里面加入一些认证信息,需要对SOAP信息作处理来做一些额外的验证,这时就用到了JAXWS的handler机制了。
见如下代码片段:
@Component
@WebService(serviceName="TestService")
@HandlerChain(file="handler-chain.xml") // 指定SOAP handler
public class TesServiceEndpoint {
@WebMethod
public String test() {
...
}
}
上面的代码中指定了一个handler的配置文件,这是一个责任链模式,在配置文件中包含有我们的handler处理的责任链,代码如下:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <javaee:handler-chains xmlns:javaee="http://java.sun.com/xml/ns/javaee" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <javaee:handler-chain> <javaee:handler> <javaee:handler-class>com.xxx.ws.AuthenticationSoapHandler</javaee:handler-class> </javaee:handler> </javaee:handler-chain> </javaee:handler-chains>
来看一下handler的代码:
public class AuthenticationSoapHandler implements
SOAPHandler<SOAPMessageContext> {
public boolean handleMessage(SOAPMessageContext context) {
Boolean isRequest = (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
if (!isRequest) {
SOAPMessage soapMsg = context.getMessage();
String username = soapMsg.getSOAPHeader().getElementsByTagName("username").item(0).getTextContent();
String password = soapMsg.getSOAPHeader().getElementsByTagName("password").item(0).getTextContent();
if (!(username.equals("admin") && password.equals("admin"))) {
return false;
}
}
}
}
上面的代码在soap消息被接收和发送时执行,依据isRequest为true还是false来判断是发送还是接收,然后再message header里面拿到用户名和密码进行验证,返回true和false表示验证成功和失败。
到此就完成了我们业务所需要的全部的校验过程了。
总的来说,jaxws的使用还是比较简单的,而且无需引入第三方的依赖,可以做为JAVA项目一个非常不错的选择。