spring 整合webService後需要在spring-cxf中配置需要發佈的接口,配置如下:
<bean id="DemoServiceBean"
class="com.app.ahnyapp.cxf.impl.DemoServiceImpl">
</bean>
<!-- #DemoService是和你的實現類上聲明的serviceName一致
id 同上面你聲明的bean id
address 是web.xml上面配置的cxf匹配路徑之後的路徑,隨便起命,但是訪問時要一致 -->
<jaxws:endpoint id="DemoService" implementor="#DemoServiceBean"
address="DemoService" />
現在問題是,我需要提供的接口很多,而且每個接口都在不同的接口類中,那麼我的每個接口都需要配置一個bean 和endpoint,就比較麻煩,所以對這一塊進行了相應的修改,自動掃描需要發佈的接口實現類。
實現過程:掃描固定包下的以Impl結尾的實現類,把這些類在項目啓動的時候加載到webservice中的endpoint中去,把這些實現層的Impl去掉做爲接口名稱
/**
*
* 此類描述的是:webservice 注入到spring容器中,掃描classPath 下面的包含impl的實現類,加載到webservice中
*
* @author: yangzhen
* @version: 2019年12月17日 下午3:14:44
* @ClassName: CxfConfig
* @項目: ahny
* @包:com.app.ahnyapp.cxf.config
*/
// 註冊到spring啓動中
@Configuration
public class CxfConfig {
private final static String classPath = "com.app.ahnyapp.cxf";
private final static String cutString = "impl";
@Bean(name = Bus.DEFAULT_BUS_ID)
public SpringBus springBus() {
return new SpringBus();
}
@Bean
public Endpoint endpoint() {
List list = new ArrayList();
list = getImplClassPath();
EndpointImpl endpoint = null;
for (int i = 0; i < list.size(); i++) {
// 根據給定的類名初始化類
Class catClass;
try {
catClass = Class.forName((String) list.get(i));
// 實例化這個類
Object obj = catClass.newInstance();
endpoint = new EndpointImpl(springBus(), obj);// 綁定要發佈的服務實現類
// 截取class名稱去掉最後的impl作爲服務的名稱
String serviceName = (String) list.get(i);
serviceName = serviceName.substring(serviceName
.lastIndexOf(".") + 1);
serviceName = serviceName
.substring(0, serviceName.length() - 4);
endpoint.publish("/" + serviceName); // 接口訪問地址
} catch (Exception e) {
e.printStackTrace();
}
}
return endpoint;
}
/**
*
* 此方法描述的是:獲取com.app.ahnyapp.cxf 以impl爲結尾的類的路徑
*
* @Title: getImplClassPath
* @author: yangzhen
* @return
* @return List 返回類型
* @version: 2019年12月17日 下午3:05:22
*/
private static List getImplClassPath() {
List list = new ArrayList();
Set classNames = ClassUtil.getClassSet(classPath);
if (classNames != null) {
for (Iterator iterator = classNames.iterator(); iterator.hasNext();) {
String classPath = iterator.next().toString();
String lowerCase = classPath.toLowerCase();
if (lowerCase.contains(cutString)) {
classPath = classPath.substring(6, classPath.length());
list.add(classPath);
}
}
}
return list;
}
}
ClassUtil代碼如下
package com.haozi.core.util;
import java.io.File;
import java.io.FileFilter;
import java.net.JarURLConnection;
import java.net.URL;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
/**
*
* 此類描述的是:類操作工具類
*
* @author: yangzhen
* @version: 2019年12月17日 上午11:21:33
* @ClassName: ClassUtil
* @項目: ahny
* @包:com.haozi.core.util
*/
public final class ClassUtil {
private static Logger LOGGER = Logger.getLogger(ClassUtil.class);
/**
* 獲取類加載器
*/
public static ClassLoader getClassLoader() {
return Thread.currentThread().getContextClassLoader();
}
/**
* 加載類
*/
public static Class<?> loadClass(String className, boolean isInitialized) {
Class<?> cls;
try {
cls = Class.forName(className, isInitialized, getClassLoader());
} catch (ClassNotFoundException e) {
LOGGER.error("load class failure", e);
throw new RuntimeException(e);
}
return cls;
}
/**
* 加載類(默認將初始化類)
*/
public static Class<?> loadClass(String className) {
return loadClass(className, true);
}
/**
* 獲取指定包名下的所有類
*/
public static Set<Class<?>> getClassSet(String packageName) {
Set<Class<?>> classSet = new HashSet<Class<?>>();
try {
Enumeration<URL> urls = getClassLoader().getResources(
packageName.replace(".", "/"));
while (urls.hasMoreElements()) {
URL url = urls.nextElement();
if (url != null) {
String protocol = url.getProtocol();
if (protocol.equals("file")) {
String packagePath = url.getPath().replaceAll("%20",
" ");
addClass(classSet, packagePath, packageName);
} else if (protocol.equals("jar")) {
JarURLConnection jarURLConnection = (JarURLConnection) url
.openConnection();
if (jarURLConnection != null) {
JarFile jarFile = jarURLConnection.getJarFile();
if (jarFile != null) {
Enumeration<JarEntry> jarEntries = jarFile
.entries();
while (jarEntries.hasMoreElements()) {
JarEntry jarEntry = jarEntries
.nextElement();
String jarEntryName = jarEntry.getName();
if (jarEntryName.endsWith(".class")) {
String className = jarEntryName
.substring(
0,
jarEntryName
.lastIndexOf("."))
.replaceAll("/", ".");
doAddClass(classSet, className);
}
}
}
}
}
}
}
} catch (Exception e) {
LOGGER.error("get class set failure", e);
throw new RuntimeException(e);
}
return classSet;
}
private static void addClass(Set<Class<?>> classSet, String packagePath,
String packageName) {
File[] files = new File(packagePath).listFiles(new FileFilter() {
public boolean accept(File file) {
return (file.isFile() && file.getName().endsWith(".class"))
|| file.isDirectory();
}
});
for (File file : files) {
String fileName = file.getName();
if (file.isFile()) {
String className = fileName.substring(0,
fileName.lastIndexOf("."));
if (StringUtils.isNotEmpty(packageName)) {
className = packageName + "." + className;
}
doAddClass(classSet, className);
} else {
String subPackagePath = fileName;
if (StringUtils.isNotEmpty(packagePath)) {
subPackagePath = packagePath + "/" + subPackagePath;
}
String subPackageName = fileName;
if (StringUtils.isNotEmpty(packageName)) {
subPackageName = packageName + "." + subPackageName;
}
addClass(classSet, subPackagePath, subPackageName);
}
}
}
private static void doAddClass(Set<Class<?>> classSet, String className) {
Class<?> cls = loadClass(className, false);
classSet.add(cls);
}
}
這樣spring整合的cxf基本上就不需要在cxf.xml中添加配置了,最後在webService實現層裏發現@Autowired註解注入不了其他的service,爲null,這裏改成了@Resource就能注入了成功了
最後這裏提供下spring4.2.0+cxf的3.1.18的jar 包 cxf3.1.18