想要实现:客户端访问服务端时不带命名空间。
在百度上搜索,是给服务添加一个拦截器。代码如下:
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.message.Message;
import org.apache.cxf.phase.AbstractPhaseInterceptor;
import org.apache.cxf.phase.Phase;
import org.apache.cxf.service.model.ServiceInfo;
import java.io.*;
public class ServerNameSpaceInterceptor extends AbstractPhaseInterceptor<Message> {
public ServerNameSpaceInterceptor()
{
super(Phase.RECEIVE);
}
@Override
public void handleMessage(Message message) throws Fault {
for (ServiceInfo si : message.getExchange().getService().getServiceInfos()) {
si.setProperty("soap.force.doclit.bare",true); //这个就是忽略客户端不带命名空间的关键
}
}
}
程序访问报错:org.apache.cxf.interceptor.Fault: UnmarshallingError: 意外的元素 (uri:"", local:"arg0")
个人解决方案:在上述代码中的handleMessage方法中添加获取请求流,将请求流转成字符串,处理字符串中命名空间、参数、方法名相关信息,参考代码如下:
@Override
public void handleMessage(Message message) throws Fault {
for (ServiceInfo si : message.getExchange().getService().getServiceInfos()) {
si.setProperty("soap.force.doclit.bare",true); //这个就是忽略客户端不带命名空间的关键
}
// 获取参数
InputStream is = message.getContent(InputStream.class);
BufferedReader in = new BufferedReader(new InputStreamReader(is));
StringBuffer reqParamsBuf = new StringBuffer();
String line = "";
while (true) {
try {
if (!((line = in.readLine()) != null)) break;
} catch (IOException e) {
e.printStackTrace();
}
//post参数,json格式
reqParamsBuf.append(line);
}
String str = reqParamsBuf.toString();
if(str.indexOf("xmlns:ns1") < 0){//特殊处理,请求中没有命名空间,处理请求流
//根据提供服务的方法修改请求流
//处理方法的命名空间
str = str.replace("><arg0"," xmlns:ns1=\"service.mvc.web.w.a.com\"><arg0");
//处理方法的参数个数
str = str.replace("arg0", "ns1:arg0");
str = str.replace("arg1", "ns1:arg1");
//处理方法名
str = str.replace("execute", "ns1:execute");
}
message.setContent(InputStream.class, new ByteArrayInputStream(str.getBytes()));
}
所有代码:
pom依赖:
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-spring-boot-starter-jaxws</artifactId>
<version>3.4.4</version>
</dependency>
代码结构:(package-info.java和接口同级目录)
webService的配置:webServiceConfig.java
package com.a.walk.web.mvc.config;
import com.a.walk.web.mvc.service.ServerNameSpaceInterceptor;
import com.a.walk.web.mvc.service.TestWebService;
import org.apache.cxf.Bus;
import org.apache.cxf.bus.spring.SpringBus;
import org.apache.cxf.jaxws.EndpointImpl;
import org.apache.cxf.transport.servlet.CXFServlet;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.xml.ws.Endpoint;
@Configuration
public class WebServiceConfig {
/**
* 注入servlet bean name不能dispatcherServlet 否则会覆盖dispatcherServlet
*
* @return
*/
@Bean
public ServletRegistrationBean cxfServlet() {
return new ServletRegistrationBean(new CXFServlet(), "/webservice/*");//第二个参数:设置CXFServlet注册地址
}
@Bean(name = Bus.DEFAULT_BUS_ID)
public SpringBus springBus() {
return new SpringBus();
}
/**
* 注册WebService接口到webservice服务
*
* @return
*/
@Bean(name = "webServiceEndpoint")
public Endpoint sweptPayEndpoint(TestWebService webService) {
EndpointImpl endpoint = new EndpointImpl(springBus(), webService);
endpoint.publish("/test");//设置接口注册地址
endpoint.getInInterceptors().add(new ServerNameSpaceInterceptor());
return endpoint;
}
}
接口TestWebService.java:
package com.a.w.web.mvc.service;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
@WebService(targetNamespace = "service.mvc.web.walk.ao.com",name = "testWebService")
public interface TestWebService {
@WebResult(name = "execute", targetNamespace = "service.mvc.web.walk.a.com")
@WebMethod
String execute(String funcName,String value);
}
实现类TestWebServiceImpl.java:
package com.a.w.web.mvc.service.impl;
import com.a.w.web.mvc.service.TestWebService;
import org.springframework.stereotype.Service;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
@Service
@WebService(targetNamespace = "service.mvc.web.w.a.com", serviceName = "Services",endpointInterface = "com.a.w.web.mvc.service.TestWebService")
public class TestWebServiceImpl implements TestWebService {
@WebResult(name = "execute", targetNamespace = "service.mvc.web.w.as.com")
@WebMethod
public String execute(String funcName, String value) {
return funcName;
}
}
package-info.java:
@javax.xml.bind.annotation.XmlSchema(//namespace = "http://com.mypro.service",
attributeFormDefault = XmlNsForm.QUALIFIED,
elementFormDefault= XmlNsForm.QUALIFIED)
package com.a.w.web.mvc.service;
import javax.xml.bind.annotation.XmlNsForm;
拦截器ServerNameSpaceInterceptor.java:
package com.a.w.web.mvc.service;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.message.Message;
import org.apache.cxf.phase.AbstractPhaseInterceptor;
import org.apache.cxf.phase.Phase;
import org.apache.cxf.service.model.ServiceInfo;
import java.io.*;
public class ServerNameSpaceInterceptor extends AbstractPhaseInterceptor<Message> {
public ServerNameSpaceInterceptor()
{
super(Phase.RECEIVE);
}
@Override
public void handleMessage(Message message) throws Fault {
for (ServiceInfo si : message.getExchange().getService().getServiceInfos()) {
si.setProperty("soap.force.doclit.bare",true); //这个就是忽略客户端不带命名空间的关键
}
// 获取参数
InputStream is = message.getContent(InputStream.class);
BufferedReader in = new BufferedReader(new InputStreamReader(is));
StringBuffer reqParamsBuf = new StringBuffer();
String line = "";
while (true) {
try {
if (!((line = in.readLine()) != null)) break;
} catch (IOException e) {
e.printStackTrace();
}
//post参数,json格式
reqParamsBuf.append(line);
}
String str = reqParamsBuf.toString();
if(str.indexOf("xmlns:ns1") < 0){//特殊处理,请求中没有命名空间,处理请求流
//根据提供服务的方法修改请求流
//处理方法的命名空间
str = str.replace("><arg0"," xmlns:ns1=\"service.mvc.w.w.a.com\"><arg0");
//处理方法的参数个数
str = str.replace("arg0", "ns1:arg0");
str = str.replace("arg1", "ns1:arg1");
//处理方法名
str = str.replace("execute", "ns1:execute");
}
message.setContent(InputStream.class, new ByteArrayInputStream(str.getBytes()));
}
}