CXF 与 spring 的整合: Java EE 应用可以使用其他项目暴露的 Web Service 接口, Java EE 应用实现多平台、多语言、多功能的编写的程序;
* 在传统Spring项目基础上增加 Web Service 的步骤(SSH ):
1 . 让 Controller 依赖远程 Web Service 的接口;
2 . 复制 CXF 的 jar 包(最核心的6个), jar 包地址 http://pan.baidu.com/s/1jHJ56BW 注:请选择性复制 (Apache官网上也可以下载);
asm-3.3.jar commons-logging-1.1.1.jar cxf-2.4.1.jar neethi-3.0.0.jar wsdl4j-1.6.2.jar xmlschema-core-2.0.jar
客户端的 Web 项目,我的这次配置要用到Struts2的 jar 包(jar 包地址 http://pan.baidu.com/s/1gfDNXBH)
3 . 在 Spring 配置文件中导入 CXF 提供 Schema、XML(cxf.jar 包里提供)
* Schema 文件
<beans xmlns:jaxws="http://cxf.apache.org/jaxws"
xsi:schemaLocation="
http://cxf.apache.org/jaxws //命名空间
http://cxf.apache.org/schemas/jaxws.xsd">//物理路径
* XML 的配置文件
<import resource="classpath:META-INF/cxf/cxf.xml"/>
<import resource="classpath:META-INF/cxf/cxf-extension-soap.xml"/>
<import resource="classpath:META-INF/cxf/cxf-servlet.xml"/>
4 . 在 Spring 配置文件中使用 jaxws:client 元素类暴露 Web Service;
5 . 添加拦截器,在 jaxws:endpoint 元素里添加 inInterceptors、outInterceptors 子元素;
* 代码有时比语言更有说服力,新建一个 Web Project 项目代码如下:
①FoodsManageController.java
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.cxf.endpoint.Client;
import org.apache.cxf.frontend.ClientProxy;
import org.apache.cxf.interceptor.LoggingInInterceptor;
import org.apache.cxf.interceptor.LoggingOutInterceptor;
import org.apache.cxf.jaxws.endpoint.dynamic.JaxWsDynamicClientFactory;
import org.fjava.cxf.ws.Entry;
import org.fjava.cxf.ws.Food;
import org.fjava.cxf.ws.HelloWorld;
import org.fjava.cxf.ws.StringFood;
import org.fjava.cxf.ws.auth.AddHeaderInterceptor;
import org.fjava.cxf.ws.impl.HelloWorldWs;
import org.springframework.stereotype.Controller;
import com.opensymphony.xwork2.ActionSupport;
@Controller
public class FoodsManageController extends ActionSupport{
//要用到CXF的jar包,要用到Spring的jar包,可以将服务端的jar包根据情况复制过来
//是一个Web项目,要用到Struts2的jar包
//此时的Controller依赖的是远程Web Service的代理对象
private HelloWorld factory;
public void setFactory(HelloWorld factory) {
this.factory = factory;
}
private Map<String , Food> foods;
public Map<String, Food> getFoods() {
return foods;
}
public void setFoods(Map<String, Food> foods) {
this.foods = foods;
}
public String execute(){
//Controller调用的是远程Web Service代理的方法
Map<String, Food> foods = new HashMap<String, Food>();
StringFood allFoods = factory.getAllFoods();
for (Entry entry : allFoods.getEntries()) {
foods.put(entry.getKey() , entry.getValue());
}
setFoods(foods);
return SUCCESS;
}
}
②AddHeaderInterceptor.java
import java.util.List;
import javax.xml.namespace.QName;
import org.apache.cxf.binding.soap.SoapMessage;
import org.apache.cxf.headers.Header;
import org.apache.cxf.helpers.DOMUtils;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.phase.AbstractPhaseInterceptor;
import org.apache.cxf.phase.Phase;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
public class AddHeaderInterceptor extends AbstractPhaseInterceptor<SoapMessage> {
private String userId;
private String password;
public AddHeaderInterceptor(String userId, String password) {
super(Phase.PREPARE_SEND);//在准备发送Soap消息时启用该拦截器
this.userId = userId;
this.password = password;
}
@Override
public void handleMessage(SoapMessage msg) throws Fault {
List<Header> headers = msg.getHeaders();
//创建Document对象
Document document = DOMUtils.createDocument();
Element eleAuthHeader = document.createElement("authHeader");
//此处创建的元素应该与服务器的拦截元素相同
Element eleUserId = document.createElement("userId");
eleUserId.setTextContent(userId);
Element elePassword = document.createElement("password");
elePassword.setTextContent(password);
eleAuthHeader.appendChild(eleUserId);
eleAuthHeader.appendChild(elePassword);
/*
* 上面代码生成了一个如下XML文档片段:
* <authHeader>
* <userId></userId>
* <password></password>
*</authHeader>
*/
//把ele元素包装成Header,并添加到SOAP消息的Header列表中。
headers.add(new Header(new QName("fjava"),eleAuthHeader));
}
}
③struts.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
<constant name="struts.enable.DynamicMethodInvocation" value="false" />
<constant name="struts.devMode" value="true" />
<package name="default" namespace="/" extends="struts-default">
<action name="listFoods" class = "org.fjava.cxf.controller.FoodsManageController">
<result>/WEB-INF/listFoods.jsp</result>
</action>
<action name="*" class = "org.fjava.cxf.controller.FoodsManageController">
<result>/WEB-INF/index.jsp</result>
</action>
</package>
</struts>
④applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:jaxws="http://cxf.apache.org/jaxws"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://cxf.apache.org/jaxws
http://cxf.apache.org/schemas/jaxws.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- Web应用的类加载路径有两类
1.WEB-INF/classes目录
2.WEB-INF/lib目录下
-->
<import resource="classpath:META-INF/cxf/cxf.xml"/>
<import resource="classpath:META-INF/cxf/cxf-extension-soap.xml"/>
<import resource="classpath:META-INF/cxf/cxf-servlet.xml"/>
<!-- Controller依赖的是远程Web Service的代理
为了保证该Web Service代理对象可以自动装配给Controller
应该保证该id属性值与Controller方法中的setter方法的方法名有对应关系
-->
<jaxws:client id="factory"
serviceClass="org.fjava.cxf.ws.HelloWorld"
address="http://192.168.0.159:6786/sayHello">
<!-- 添加了两个Out拦截器 -->
<jaxws:outInterceptors>
<bean class="org.apache.cxf.interceptor.LoggingOutInterceptor"/><!-- 嵌套Bean,创建一个Bean -->
<bean class="org.fjava.cxf.ws.auth.AddHeaderInterceptor">
<constructor-arg value="admin"/>
<constructor-arg value="admin"/>
</bean>
</jaxws:outInterceptors>
</jaxws:client>
</beans>
⑤listFoods.jsp
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>蟹老板的辉煌食物派对!</title>
</head>
<body>
<ul>
<s:iterator value="foods" var="entry">
<li>${entry.key } --> ${entry.value.describe }</li>
</s:iterator>
</ul>
</body>
</html>
⑥web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
<display-name></display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
<!-- 该Listener会保证在Web应用启动时加载Spring容器 -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- 配置struts2的核心控制器 -->
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
服务端必须是开启状态,开启客户端,打开页面访问地址 http://192.168.0.159:8080/CXF_Spring_Client/listFoods
访问结果:
做一个权限控制,有用户名和密码的时候才允许调用 Web Service 该功能完成!
希望对你有帮助,祝你有一个好心情,加油!
若有错误、不全、可优化的点,欢迎纠正与补充;转载请注明出处!