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