• 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏吧

cxf+webservice基本配置及java.lang.ClassCastException: 服务端实体类 cannot be cast to 客户端实体类错误解决

error 来源:hao_6067 78次浏览

**

cxf+webservice基本配置及java.lang.ClassCastException: 服务端实体类 cannot be cast to 客户端实体类错误解决**

例如:java.lang.ClassCastException: com.xima.webservice.service.User cannot be cast to com.xima.breast.vo.User

其中User为wenservice传输的bean,两端bean中的属性相同

此处使用springboot,所用pom如下

         <dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		<!-- http -->
		<dependency>
			<groupId>org.apache.httpcomponents</groupId>
			<artifactId>httpclient</artifactId>
		</dependency>
		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>fastjson</artifactId>
			<version>1.1.41</version>
		</dependency>
		<!-- 热部署模块 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
			<optional>true</optional>  <!--这个需要为 true 热部署才有效 -->
		</dependency>

		<!-- CXF webservice -->
		<dependency>
			<groupId>org.apache.cxf</groupId>
			<artifactId>cxf-spring-boot-starter-jaxws</artifactId>
			<version>3.1.11</version>
		</dependency>

先将基本代码附上:

webservice接口:

@WebService(targetNamespace="http://service.webservice.modular.anyu.com")
public interface TestUserService {

    @WebMethod//标注该方法为webservice暴露的方法,用于向外公布,它修饰的方法是webservice方法,去掉也没影响的,类似一个注释信息。
    
    @WebMethod
    List<User> getUserByAll();
}

webservice接口实现类:

@WebService(serviceName="TestUserService",//对外发布的服务名
            targetNamespace="http://service.webservice.modular.anyu.com",//指定你想要的名称空间,通常使用使用包名反转
            endpointInterface="com.anyu.modular.webservice.service.TestUserService")//服务接口全路径, 指定做SEI(Service EndPoint Interface)服务端点接口
@Component
public class TestUserServiceImpl implements TestUserService{
	
	@Autowired
	BreastCureNodeDao breastCureNodeDao;//dao层,数据库查询
	
	public List<User> getUserByAll(){
		return breastCureNodeDao.selectUserByAll();
	}

}

BreastCureNode 类 (bean):

@XmlRootElement(name="User")
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(propOrder= {""})
public class User implements Serializable {

    private static final long serialVersionUID = 1L;
	private Integer id;
   
	private String userName;
	
	private Integer age;
	
	private String six;
    
	private String school;
  
	private Date brithday;

	//.......get   ....set  ....toString省略

}

webservice配置config

@Configuration
public class CxfConfig {
	@Autowired
	private Bus bus;

	@Autowired
	TestUserService testUserService;

	/**
	 * 此方法作用是改变项目中服务名的前缀名,此处127.0.0.1或者localhost不能访问时,请使用ipconfig查看本机ip来访问
	 * wsdl访问地址为:http://127.0.0.1:8080/soap/user?wsdl
	 * 不用此方法,则访问 : http://127.0.0.1:8080/services/user?wsdl
	 */
//	@SuppressWarnings("all")
//	@Bean
//	public ServletRegistrationBean dispatcherServlet() {
//		return new ServletRegistrationBean(new CXFServlet(), "/soap/*");
//	}

	/**
	 * 方法一
	 */

	// @Bean(name = Bus.DEFAULT_BUS_ID)
	// public SpringBus springBus() {
	// return new SpringBus();
	// }
	//
	// @Bean
	// public TestUserService testUserService() {
	// return new TestUserServiceImpl();
	// }
	//
	// @Bean
	// public Endpoint endpoint() {
	// EndpointImpl endpoint = new EndpointImpl(springBus(), testUserService());
	// endpoint.publish("/user");
	// return endpoint;
	// }

	/** 
	 * 方法二
	 * 若有多个webservice,将下面方法复制,修改service和publish即可 
	 **/
	@Bean
	public Endpoint endpoint() {
		EndpointImpl endpoint = new EndpointImpl(bus, testUserService);
		endpoint.publish("/user/breast");
		endpoint.getInInterceptors().add(new AuthInterceptor());//添加用户密码验证,去掉则客户端不需要用户密码验证
		return endpoint;
	}

}

AuthInterceptor 用户名密码验证:

public class AuthInterceptor extends AbstractPhaseInterceptor<SoapMessage>{

	
	private static final Logger logger = LoggerFactory.getLogger(AuthInterceptor.class);
	private SAAJInInterceptor saa = new SAAJInInterceptor();
 
    private static final String USER_NAME = "admin";
	private static final String USER_PASSWORD = "admin";
 
	
    public AuthInterceptor() {
		super(Phase.PRE_PROTOCOL);
		getAfter().add(SAAJInInterceptor.class.getName());
	}
 
	@Override
	public void handleMessage(SoapMessage message) throws Fault {
		SOAPMessage mess = message.getContent(SOAPMessage.class);
        if (mess == null) {
            saa.handleMessage(message);
            mess = message.getContent(SOAPMessage.class);
        }
        SOAPHeader head = null;
        try {
            head = mess.getSOAPHeader();
        } catch (Exception e) {
            logger.error("getSOAPHeader error: {}",e.getMessage(),e);
        }
        if (head == null) {
            throw new Fault(new IllegalArgumentException("找不到Header,无法验证用户信息"));
        }
 
        NodeList users = head.getElementsByTagName("username");
        NodeList passwords = head.getElementsByTagName("password");
        if (users.getLength() < 1) {
            throw new Fault(new IllegalArgumentException("找不到用户信息"));
        }
        if (passwords.getLength() < 1) {
            throw new Fault(new IllegalArgumentException("找不到密码信息"));
        }
 
        String userName = users.item(0).getTextContent().trim();
        String password = passwords.item(0).getTextContent().trim();
        
        //可以从数据库获取用户名密码验证,也可以使用固定的用户名,密码
        //根据项目需要选择
        
        //固定的用户名和密码   此处为admin admin
        if(USER_NAME.equals(userName) && USER_PASSWORD.equals(password)){
            logger.debug("admin auth success");
        } else {
            SOAPException soapExc = new SOAPException("认证错误");
            logger.debug("admin auth failed");
            throw new Fault(soapExc);
        }
    }
}

客户端代码:

public class CxfClient {


    public static void main(String[] args) {
        CxfClient.main1();
        CxfClient.main2();

        
    }

    /**
     * 1.代理类工厂的方式,需要拿到对方的接口地址
     */
    public static void main1() {
        try {
            // 接口地址
            String address = "http://192.168.0.100:8081/services/user/breast?wsdl";
            // 代理工厂
            JaxWsProxyFactoryBean jaxWsProxyFactoryBean = new JaxWsProxyFactoryBean();
            // 设置代理地址
            jaxWsProxyFactoryBean.setAddress(address);
            // 设置接口类型
            jaxWsProxyFactoryBean.setServiceClass(TestUserService.class);
            // 创建一个代理接口实现
            TestUserService us = (TestUserService) jaxWsProxyFactoryBean.create();
            // 数据准备
            
            // 调用代理接口的方法调用并返回结果
            String result = us.getUserByAll();
           
            System.err.println("返回结果:" + result);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 2:动态调用
     */
    public static void main2() {
        // 创建动态客户端
        JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance();
        Client client = dcf.createClient("http://192.168.0.100:8081/services/user/breast?wsdl");
        
        // 需要密码的情况需要加上用户名和密码
         client.getOutInterceptors().add(new ClientLoginInterceptor("admin", "admin"));
        Object[] objects = new Object[0];
        try {
            // invoke("方法名",参数1,参数2,参数3....);
        	objects = client.invoke("getUserByAll");
        	List<User> users = (List<User>)objects[0];
        	for (User user : users) {
				System.out.println(user.toString());
			}
            System.err.println("main2 : 动态调用  : 返回数据:" + objects[0]);
        } catch (java.lang.Exception e) {
            e.printStackTrace();
        }
    }
}

客户端User类:

public class User implements Serializable {

    private static final long serialVersionUID = 1L;
	private Integer id;
   
	private String userName;
	
	private Integer age;
	
	private String six;
    
	private String school;
  
	private Date brithday;

	//.......get   ....set  ....toString省略

}

ClientLoginInterceptor 验证用户名,密码的类:

public class ClientLoginInterceptor extends AbstractPhaseInterceptor<SoapMessage>
{

    public ClientLoginInterceptor(String username, String password) 
    {
        super(Phase.PREPARE_SEND);  
        this.username = username;
        this.password = password;
    }


    private String username;  
    private String password;
    
    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }


    public void handleMessage(SoapMessage soap) throws Fault 
    {
        List<Header> headers = soap.getHeaders();
        Document doc = DOMUtils.createDocument();
        Element auth = doc.createElement("authrity");
        Element username = doc.createElement("username");
        Element password = doc.createElement("password");
        username.setTextContent(this.username);
        password.setTextContent(this.password);
        
        auth.appendChild(username);
        auth.appendChild(password);
        
        headers.add(0, new Header(new QName("tiamaes"),auth));
    }

}

此时基本代码书写完成,启动服务端,输入:http://localhost:8081/services/user/breast?wsdl则可以出现如下页面:

启动客户端: 则会报以下错误:

java.lang.ClassCastException: com.xima.webservice.service.User cannot be cast to com.xima.breast.vo.User
	at com.example.demo.CxfClient.main2(CxfClient.java:79)
	at com.example.demo.CxfClient.main(CxfClient.java:26)

错误原因:

两个bean类的路径不同,导致映射失败;

将客户端User的路径改为com.xima.webservice.service.User即成功在客户端输出User数据

重点说明:bean类所在路径必须是wenservice的路径


版权声明:本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系管理员进行删除。
喜欢 (0)