近期有个需求,针对所有的webservice请求将其请求与结果全部保存到数据库。
采用的是通过SOAPHandler来实现。
参考了 这个 里的
public class CxfLoggingHandler implements SOAPHandler<SOAPMessageContext> {
private LogService logService;
private Log logger = LogFactory.getLog(CxfLoggingHandler.class);
public void setLogService(LogService logService) {
this.logService = logService;
}
public Set<QName> getHeaders() {
return Collections.EMPTY_SET;
}
public boolean handleMessage(SOAPMessageContext context) {
Boolean outgoingMessage = (Boolean) context.get (MessageContext.MESSAGE_OUTBOUND_PROPERTY);
HttpServletRequest req = (HttpServletRequest) context.get (MessageContext.SERVLET_REQUEST);
ServiceLog log = new ServiceLog();
//id
log.setId(com.construct.util.StringUtils.newGUID());
//ip
log.setIp(getIpAddr(req));
if (outgoingMessage) {
// it is outgoing message. let's work
String soapActionURI = ((QName)context.get(MessageContext.WSDL_OPERATION)).getLocalPart();
//请求方法
log.setMethod(soapActionURI);
SOAPPart requestSoap = (SOAPPart)context.get("SOAP_REQUEST_MSG_KEY");
try {
SOAPEnvelope reqEnvelope = requestSoap.getEnvelope();
SOAPBody reqBody = reqEnvelope.getBody();
Node reqNode = reqBody.getFirstChild();
String reqContent = getString(reqNode);
if (reqContent == null) {
reqContent = convertDomToString(requestSoap);
}
//请求
log.setRequest(reqContent);
SOAPPart responseSoap = context.getMessage().getSOAPPart();
SOAPEnvelope resEnvelope = responseSoap.getEnvelope();
SOAPBody resBody = resEnvelope.getBody();
Node resNode = resBody.getFirstChild();
String resContent = getString(resNode);
if (resContent == null) {
resContent = convertDomToString(responseSoap);
}
//响应
log.setResponse(resContent);
logService.saveLog(log);
} catch (SOAPException e) {
logger.error("错误:::" + e);
}
} else {
// it is incoming message, saving it for future
context.put("SOAP_REQUEST_MSG_KEY", context.getMessage().getSOAPPart());
}
return true;
}
public boolean handleFault(SOAPMessageContext context) {
return handleMessage(context);
}
@Override
public void close(MessageContext context) {
}
private String convertDomToString(SOAPPart soap){
final StringWriter sw = new StringWriter();
try {
TransformerFactory.newInstance().newTransformer().transform(
new DOMSource(soap),
new StreamResult(sw));
} catch (TransformerException e) {
// do something
}
return sw.toString();
}
private String convertNodeToString(Node soap){
final StringWriter sw = new StringWriter();
try {
TransformerFactory.newInstance().newTransformer().transform(
new DOMSource(soap),
new StreamResult(sw));
} catch (TransformerException e) {
// do something
}
return sw.toString();
}
private String getIpAddr(HttpServletRequest request) {
if (request == null) {
return null;
}
String ip = request.getHeader("x-forwarded-for");
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
return ip;
}
}
具体spring中配置
<jaxws:endpoint implementor="#**" address="/**">
<jaxws:handlers>
<bean class="**.CxfLoggingHandler">
<property name="logService" ref="logService" />
</bean>
</jaxws:handlers>
<!-- 输入拦截器 -->
<jaxws:inInterceptors>
<!-- 日志打印 -->
<bean class="org.apache.cxf.interceptor.LoggingInInterceptor" />
</jaxws:inInterceptors>
<!-- 正常输出拦截器 -->
<jaxws:outInterceptors>
<bean class="org.apache.cxf.interceptor.LoggingOutInterceptor"/>
</jaxws:outInterceptors>
</jaxws:endpoint>