这几天接手一个项目,应用的是CXF和Spring编写webservice,对于第一次编写接口的菜鸟来说,只调用过别人的接口,这是让我有些头疼的,代码很容易就搞定了,毕竟是复制修改,但是关于这个怎么暴露给别人调用,百度了很多,试过直接在main方法中暴露,然后客户端调用,但是调用报空指针,后来找到原因之后,不知道该接口的暴露的url,交接文档中也没有注明,当时我心里一万个草泥马飞奔而过。。。这些请在下文详细看:
一、正确的示范,发布调用成功
1、准备需要的关于cxf的jar包: 2.7.2的版本可以在这里下载https://download.csdn.net/download/luuvyjune/10523675
2、web.xml 配置
<servlet>
<servlet-name>CXFServlet</servlet-name>
<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>CXFServlet</servlet-name>
<url-pattern>/ws/*</url-pattern>
</servlet-mapping>
3、spring-cxf.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:jaxws="http://cxf.apache.org/jaxws" xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://cxf.apache.org/jaxws
http://cxf.apache.org/schemas/jaxws.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<import resource="classpath:/META-INF/cxf/cxf.xml" />
<import resource="classpath:/META-INF/cxf/cxf-servlet.xml" />
<jaxws:endpoint id="patientEventWebservice" implementor="cn.myjob.empi.webservice.PEventLogXmlImpl " address="/PatientEventWebservice" />
</beans>
4、代码(只是关于这个接口的代码):
PatientEventWebservice.java
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;
@WebService
public interface PatientEventWebservice {
@WebMethod(action="getPatientEventLogByMpi")
String getPatientEventLogByMpi(@WebParam(name="text") String inputString);
}
PEventLogXmlImpl.java
@WebService(endpointInterface="cn.myjob.empi.webservice.PatientEventWebservice",serviceName="PEventLogXmlImpl")
public class PEventLogXmlImpl implements PatientEventWebservice {
private Logger log = Logger.getLogger(PEventLogXmlImpl.class);
@Autowired
private QueryPatientEventLogByMpiService queryPatientEventLogByMpiService;
@Override
public String getPatientEventLogByMpi(String inputString) {
log.info("\n[查询事件信息]"+inputString);
XStream xstream = new XStream();
xstream.aliasType("XmlResponse", XmlResponse.class);
xstream.aliasType("PEvent", PEvent.class);
System.out.println(queryPatientEventLogByMpiService);
if(queryPatientEventLogByMpiService == null){
queryPatientEventLogByMpiService = ContextLoaderListener.getCurrentWebApplicationContext().getBean(QueryPatientEventLogByMpiService.class);
}
XmlResponse<PEvent> xml = queryPatientEventLogByMpiService.process(inputString);
return xstream.toXML(xml);
}
}
PEventLogWebService.java
public abstract class PEventLogWebService {
protected Logger log = Logger.getLogger(this.getClass());
public abstract XmlResponse<PEvent> process(String inputString);
}
QueryPatientEventLogByMpiService.java
@Service
public class QueryPatientEventLogByMpiService extends PEventLogWebService{
@Override
public XmlResponse<PEvent> process(String inputString) {
XmlResponse<PEvent> response = null;
Results<XmlRequest> parseResult = null;
try {
parseResult = processString(inputString);
if(parseResult.getSuccess()){
processValidate(parseResult.getData());
response = processBusi(parseResult.getData());
}
} catch (Exception e) {
e.printStackTrace();
log.error(e);
if(response ==null){
response = new XmlResponse<PEvent>();
if(parseResult!=null&&parseResult.getData()!=null){
response.setMSH(parseResult.getData().getMSH());
}
response.setEVN(IdService.getEvn());
}
response.setCODE(SystemCode._EXCEPTION.getKey());
response.setDETAIL(e.getMessage());
response.setSTACK_TRANCE(e.getStackTrace());
}
return response;
}
}
这个类展示为service层,里面的方法会调用持久层并返回结果,此处代码省略。
6、tomcat启动web服务,浏览器输入地址:
http://localhost:8082/emp3/ws/PatientEventWebservice?wsdl
webservice暴露的地址命名:http://ip:端口/项目名/web.xml中cxf配置的匹配值/webservice接口名称?wsdl
结果如下:
发布成功!
7、本地调用:
在工程的src右击,选择web service client
配置接口地址,点击next自动生成并下载代码:
生成的代码结构:
本地客户端编写:
右击运行,打印结果。
二、然而,在这之前是这样的。。
发布接口:
这样的话,在浏览器输入http://localhost:8081/HelloWord?wsdl
也是可以看到信息的,发布成功没有问题。
调用的话,和正确示范的一样,只不过地址改成了http://localhost:8081/HelloWord?wsdl
运行客户端程序,debug调试webservice服务端,发现
原因很明确了,因为没有启动web程序,只是单独运行了一个main程序,@Autowired 自动注入也就失效了,因为这是spring的注解,必须在spring的配置问件中设置自动扫描,并启动web程序,配置文件才会生效,@Autowired才会自动注入bean。
获取bean的方法除了@Autowired 还有其他很多方法,网上可以找到,就不再一一赘述。