`

WebService的用法

阅读更多

看到有很多朋友对WebService还不是很了解,在此就详细的讲讲WebService,争取说得明白吧。此文章采用的项目是我毕业设计的webservice部分。
首先要建一个web工程和android工程,在此采用myeclipse开发,个人觉得比较方便,要是eclipse安装了tomcat也行。这的web端采用了框架hibernate和spring,因为我的项目只是client端调用web端的数据,没什么web页面,所以就没用struts了。
讲解前先说说流程:此项目里,在web端里webservice把实体类转换成json的对象通过一个web地址发布出去;(由于WebService 是一种基于SOAP协议的远程调用标准。通过WebService可以将不同操作系统平台,不同语言、不同技术整合到一起,而在Android SDK中并没有提供调用WebService的库,因此需要使用第三方类库(KSOAP2)来调用WebService ),client端就需要通过发布的地址来获取数据了。
以下就一步一步来讲解了,所有的代码和流程就以用用户登录来体现了:
一、Web端
1、Model和Hibernate配置
实体类SysUser:

Java代码 复制代码 收藏代码
  1. public class SysUser implements Serializable {   
  2.     private Long id;   
  3.     private String userPwd;   
  4.     private String userPhone;   
  5.     public SysUser() {   
  6.     }   
  7.     public SysUser(Long id,  String userPwd, String userPhone) {   
  8.         super();   
  9.         this.id = id;   
  10.         this.userPwd = userPwd;   
  11.         this.userPhone = userPhone;   
  12.         }   
  13.     //get和set   
  14.     }  
public class SysUser implements Serializable {
	private Long id;
	private String userPwd;
	private String userPhone;
	public SysUser() {
	}
	public SysUser(Long id,  String userPwd, String userPhone) {
		super();
		this.id = id;
		this.userPwd = userPwd;
		this.userPhone = userPhone;
		}
	//get和set
	}


Hibernate:

Java代码 复制代码 收藏代码
  1. <hibernate-mapping>   
  2.     <class name="com.silent.cn.model.SysUser" table="SYS_USER">   
  3.         <id name="id" type="java.lang.Long">   
  4.             <column name="ID" precision="22" scale="0" />   
  5.             <generator class="native" />   
  6.         </id>   
  7.         <property name="userPwd" type="java.lang.String">   
  8.             <column name="USER_PWD" length="20" />   
  9.         </property>   
  10.         <property name="userPhone" type="java.lang.String">   
  11.             <column name="USER_PHONE" length="11" />   
  12.         </property>   
  13.     </class>   
  14.     </hibernate-mapping>  
<hibernate-mapping>
	<class name="com.silent.cn.model.SysUser" table="SYS_USER">
		<id name="id" type="java.lang.Long">
			<column name="ID" precision="22" scale="0" />
			<generator class="native" />
		</id>
		<property name="userPwd" type="java.lang.String">
			<column name="USER_PWD" length="20" />
		</property>
		<property name="userPhone" type="java.lang.String">
			<column name="USER_PHONE" length="11" />
		</property>
	</class>
	</hibernate-mapping>


2、PoJo包
这里面是服务器端返回使用的类,webservice传递数据时,可能只会传递一部分数据,这样的话,就要把要传递的数据封装成一个pojo类,再转成一个json对象,这样的话无论是从代码的整洁、逻辑还是高效,都会是非常完美的写法。在web端和client端的类要完全一样,这样的话更为简单。

Java代码 复制代码 收藏代码
  1. /**  
  2.  * 登陆状态  
  3.  */  
  4. public class DataOperateResult {   
  5.     private String status;   
  6.     public String getStatus() {   
  7.         return status;   
  8.     }   
  9.     public void setStatus(String status) {   
  10.         this.status = status;   
  11.     }   
  12. }  
/**
 * 登陆状态
 */
public class DataOperateResult {
	private String status;
	public String getStatus() {
		return status;
	}
	public void setStatus(String status) {
		this.status = status;
	}
}


3、WebService接口
    这里面是封装的webservice接口,手机端就是直接通过这些接口进行数据的传送与接收,最重要的是在接口上一定要加上"@WebService"这个注解,这样才能把此类里面的方法封装成一个webservice接口,关键代码如下:

Java代码 复制代码 收藏代码
  1. //手机客户端服务类(专门负责与手机客户端进行交互)   
  2. @WebService  
  3. public interface MobileClientService {   
  4.     /**  
  5.      * 登陆  
  6.      * @param opPhone  
  7.      * @param loginPwd  
  8.      */  
  9.     public String userLogin(@WebParam(name = "opPhone") String opPhone, @WebParam(name = "loginPwd") String loginPwd);   
  10. }  
//手机客户端服务类(专门负责与手机客户端进行交互)
@WebService
public interface MobileClientService {
	/**
	 * 登陆
	 * @param opPhone
	 * @param loginPwd
	 */
	public String userLogin(@WebParam(name = "opPhone") String opPhone, @WebParam(name = "loginPwd") String loginPwd);
}


     要注意的是方法里的参数前一定要加上@WebParam(name = "***(随便取的名字)"),这是因为这个opPhone参数通过webservice发布出去之后是以opPhone这个名称存在的,在手机端那边的方法直接获取opPhone就可以了。
4、WebService接口实现类
ws里面接口的实现类,在这个类的开始,一定要加上"@WebService(endpointInterface = "com.silent.cn.ws.MobileClientService")"这个注解,它表示是继承自com.silent.cn.ws.MobileClientService的类,没有这一步,webservice接口是不会实现其功能的。下面是代码:

Java代码 复制代码 收藏代码
  1. @WebService(endpointInterface = "com.silent.cn.ws.MobileClientService")   
  2. public class MobileClientServiceImpl implements MobileClientService {   
  3.     public String userLogin(String opPhone, String loginPwd) {   
  4.         SysUser sysUser = userLoginDao.userLogin(opPhone, loginPwd);   
  5.         DataOperateResult dataOperateResult = new DataOperateResult();   
  6.         if (sysUser != null) {   
  7.             // 封装登录验证结果   
  8.             dataOperateResult.setStatus(SUCC);   
  9.             System.out.println("登陆成功!");   
  10.             return JSONObject.fromObject(dataOperateResult).toString();   
  11.         } else {   
  12.             System.out.println("不存在或手机号码和密码不正确!");   
  13.             dataOperateResult.setStatus(FAIL);   
  14.             return JSONObject.fromObject(dataOperateResult).toString();   
  15.         }   
  16.     }   
  17. }  
@WebService(endpointInterface = "com.silent.cn.ws.MobileClientService")
public class MobileClientServiceImpl implements MobileClientService {
    public String userLogin(String opPhone, String loginPwd) {
		SysUser sysUser = userLoginDao.userLogin(opPhone, loginPwd);
		DataOperateResult dataOperateResult = new DataOperateResult();
		if (sysUser != null) {
			// 封装登录验证结果
			dataOperateResult.setStatus(SUCC);
			System.out.println("登陆成功!");
			return JSONObject.fromObject(dataOperateResult).toString();
		} else {
			System.out.println("不存在或手机号码和密码不正确!");
			dataOperateResult.setStatus(FAIL);
			return JSONObject.fromObject(dataOperateResult).toString();
		}
	}
}


5、Dao和Dao实现类

Java代码 复制代码 收藏代码
  1. /**  
  2.  * 用户登录DAO  
  3.  */  
  4. public interface UserLoginDao {   
  5.     /**  
  6.      * 根据用户名和用户密码登陆  
  7.      * @param userPhone 用户手机号码  
  8.      * @param passWord 用户密码  
  9.      * @return  
  10.      */  
  11.     public SysUser userLogin(String userPhone, String passWord);   
  12. }  
/**
 * 用户登录DAO
 */
public interface UserLoginDao {
	/**
	 * 根据用户名和用户密码登陆
	 * @param userPhone 用户手机号码
	 * @param passWord 用户密码
	 * @return
	 */
	public SysUser userLogin(String userPhone, String passWord);
}
Java代码 复制代码 收藏代码
  1. /**  
  2.  * 用户登录DAO实现类  
  3.  */  
  4. public class UserLoginDaoImpl extends BaseDao implements UserLoginDao {   
  5.     public SysUser userLogin(String userPhone, String passWord) {   
  6.         String sql = " from SysUser where userPhone=? and userPwd=? ";   
  7.         List<SysUser> list = this.getHibernateTemplate().find(sql, new Object[] { userPhone, passWord });   
  8.         if (list.size() == 0) {   
  9.             return null;   
  10.         }   
  11.         return list.get(0);   
  12.     }   
  13. }  
/**
 * 用户登录DAO实现类
 */
public class UserLoginDaoImpl extends BaseDao implements UserLoginDao {
	public SysUser userLogin(String userPhone, String passWord) {
		String sql = " from SysUser where userPhone=? and userPwd=? ";
		List<SysUser> list = this.getHibernateTemplate().find(sql, new Object[] { userPhone, passWord });
		if (list.size() == 0) {
			return null;
		}
		return list.get(0);
	}
}


6、Spring配置
    这里spring的配置为了整洁与不臃肿,分成了三部分,分别实现了不同功能:
applicationContext.xml:所有的spring配置信息,包括连接数据库、配置事务管理器、配置事务传播特性 、dao模板等等

Java代码 复制代码 收藏代码
  1. <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">   
  2.     <property name="driverClassName" value="com.mysql.jdbc.Driver" />   
  3.     <property name="url" value="jdbc:mysql://localhost:3306/phonesell" />   
  4.     <property name="username" value="root" />   
  5.     <property name="password" value="root" />   
  6. </bean>   
  7. <bean id="sessionFactory"  
  8.     class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">   
  9.     <property name="dataSource">   
  10.         <ref bean="dataSource" />   
  11.     </property>   
  12.     <property name="hibernateProperties">   
  13.         <props>   
  14.             <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>   
  15.             <prop key="hibernate.show_sql">true</prop>   
  16.         </props>   
  17.     </property>   
  18.     <!-- 实体类资源映射 -->   
  19.     <property name="mappingDirectoryLocations">   
  20.         <list>   
  21.             <value>classpath:/com/silent/cn/model/</value>   
  22.         </list>   
  23.     </property>   
  24. </bean>   
  25. <!-- 配置事务管理器 -->   
  26. <bean id="transactionManager"  
  27. class="org.springframework.orm.hibernate3.HibernateTransactionManager">   
  28.     <property name="sessionFactory">   
  29.         <ref bean="sessionFactory" />   
  30.     </property>   
  31. </bean>   
  32. <!-- 配置事务传播特性 -->   
  33. <tx:advice id="txAdvice" transaction-manager="transactionManager">   
  34.     <tx:attributes>   
  35.         <tx:method name="save*" propagation="REQUIRED" />   
  36.         <tx:method name="delete*" propagation="REQUIRED" />   
  37.         <tx:method name="update*" propagation="REQUIRED" />   
  38.         <tx:method name="do*" propagation="REQUIRED" />   
  39.         <tx:method name="*" read-only="false" />   
  40.     </tx:attributes>   
  41. </tx:advice>   
  42. <!-- 哪些类的哪些方法参与事务 -->   
  43. <aop:config>   
  44.     <aop:pointcut id="allManagerMethod"  
  45.         expression="execution(* com.silent.cn.dao.impl.*.*(..))" />   
  46.     <aop:advisor pointcut-ref="allManagerMethod" advice-ref="txAdvice" />   
  47. </aop:config>   
  48. <!-- dao模板(所有dao都将使用此模板) -->   
  49. <bean id="daoTemplate" abstract="true">   
  50.     <property name="sessionFactory" ref="sessionFactory"></property>   
  51. </bean>   
  52. <bean id="jdbcTemplate" abstract="true">   
  53.     <property name="dataSource" ref="dataSource"></property>   
  54. </bean>   
  55. <!--WebService配置-->   
  56. <import resource="applicationContext-webservice.xml" />   
  57. <import resource="applicationContext-dao.xml" />   
  58. </beans>  
	<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
		<property name="driverClassName" value="com.mysql.jdbc.Driver" />
		<property name="url" value="jdbc:mysql://localhost:3306/phonesell" />
		<property name="username" value="root" />
		<property name="password" value="root" />
	</bean>
	<bean id="sessionFactory"
		class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
		<property name="dataSource">
			<ref bean="dataSource" />
		</property>
		<property name="hibernateProperties">
			<props>
				<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
				<prop key="hibernate.show_sql">true</prop>
			</props>
		</property>
		<!-- 实体类资源映射 -->
		<property name="mappingDirectoryLocations">
			<list>
				<value>classpath:/com/silent/cn/model/</value>
			</list>
		</property>
	</bean>
	<!-- 配置事务管理器 -->
	<bean id="transactionManager"
	class="org.springframework.orm.hibernate3.HibernateTransactionManager">
		<property name="sessionFactory">
			<ref bean="sessionFactory" />
		</property>
	</bean>
	<!-- 配置事务传播特性 -->
	<tx:advice id="txAdvice" transaction-manager="transactionManager">
		<tx:attributes>
			<tx:method name="save*" propagation="REQUIRED" />
			<tx:method name="delete*" propagation="REQUIRED" />
			<tx:method name="update*" propagation="REQUIRED" />
			<tx:method name="do*" propagation="REQUIRED" />
			<tx:method name="*" read-only="false" />
		</tx:attributes>
	</tx:advice>
	<!-- 哪些类的哪些方法参与事务 -->
	<aop:config>
		<aop:pointcut id="allManagerMethod"
			expression="execution(* com.silent.cn.dao.impl.*.*(..))" />
		<aop:advisor pointcut-ref="allManagerMethod" advice-ref="txAdvice" />
	</aop:config>
	<!-- dao模板(所有dao都将使用此模板) -->
	<bean id="daoTemplate" abstract="true">
		<property name="sessionFactory" ref="sessionFactory"></property>
	</bean>
	<bean id="jdbcTemplate" abstract="true">
		<property name="dataSource" ref="dataSource"></property>
	</bean>
	<!--WebService配置-->
	<import resource="applicationContext-webservice.xml" />
	<import resource="applicationContext-dao.xml" />
	</beans>


7、WebService接口配置
这里设定的address就是该webservice的实际地址了:

Java代码 复制代码 收藏代码
  1. <!--   
  2. 配置WebService接口 http://localhost:8080/PhoneSell/ws/clientService?wsdl   
  3.     -->   
  4. <jaxws:endpointid="clientServiceEndpoint"address="/clientService" implementorClass="com.silent.cn.ws.MobileClientService">   
  5.         <jaxws:implementor>   
  6.             <bean id="clientService" class="com.silent.cn.ws.impl.MobileClientServiceImpl">   
  7.                 <property name="userLoginDao" ref="userLoginDao" />   
  8.             </bean>   
  9.         </jaxws:implementor>   
  10.     </jaxws:endpoint>  
<!--
配置WebService接口 http://localhost:8080/PhoneSell/ws/clientService?wsdl
	-->
<jaxws:endpointid="clientServiceEndpoint"address="/clientService" implementorClass="com.silent.cn.ws.MobileClientService">
		<jaxws:implementor>
			<bean id="clientService" class="com.silent.cn.ws.impl.MobileClientServiceImpl">
				<property name="userLoginDao" ref="userLoginDao" />
			</bean>
		</jaxws:implementor>
	</jaxws:endpoint>


8、配置web.xml
在web里添加下面的语句:

Java代码 复制代码 收藏代码
  1. <servlet>   
  2.    <servlet-name>CXFServlet</servlet-name>   
  3.    <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>   
  4. </servlet>   
  5. <servlet-mapping>   
  6.     <servlet-name>CXFServlet</servlet-name>   
  7.     <url-pattern>/ws/*</url-pattern>   
  8. </servlet-mapping>  
<servlet>
   <servlet-name>CXFServlet</servlet-name>
   <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>CXFServlet</servlet-name>
	<url-pattern>/ws/*</url-pattern>
</servlet-mapping>


9、WebService接口测试
    最好安装soapUI  pro这个软件,SOAPUI这个工具功能非常强大,是作为测试工具来用的,它既可以模拟客户端,也可以模拟服务端,可以根据描述文件很容易就生成的模拟的服务端和服务端,还可以有测试用例管理,负荷测试等,对通讯的中间过程也可以全程监控。
SOAPUI是一个免费的工具,而SOAPUI PRO是收费的,功能更强大。详细的SOAPUI用法可以参考下面的网址:http://xzhoumin.blog.163.com/blog/static/40881136201231955833137/
Client端
1、
首先,我们要获取Web端在Tomcat发布成功之后的接口地址与方法地址,如果是模拟器的话,其IP地址必须是10.0.2.2;如果是真机,那么电脑和真机都要用wifi连接到同一个网段下,而且IP地址就是电脑的实际IP地址,这样手机才能从Tomcat上获取数据,代码如下:

Java代码 复制代码 收藏代码
  1. //WebService接口地址   
  2. public static String NAME_SPACE_SALE = "http://ws.cn.silent.com/";   
  3. // 网址(如果是模拟器额话,需要把IP地址<192.168.1.***:8080>换成10.0.2.2:8080)   
  4. public static String NAME_SPACE = "http://10.0.2.2:8080/PhoneSell/";   
  5. // 连接地址(WebService的方法地址)   
  6. public static String END_POINT_SALE = NAME_SPACE + "ws/clientService";  
//WebService接口地址
public static String NAME_SPACE_SALE = "http://ws.cn.silent.com/";
// 网址(如果是模拟器额话,需要把IP地址<192.168.1.***:8080>换成10.0.2.2:8080)
public static String NAME_SPACE = "http://10.0.2.2:8080/PhoneSell/";
// 连接地址(WebService的方法地址)
public static String END_POINT_SALE = NAME_SPACE + "ws/clientService";


2、
然后,我们要写一个通用的WebService接口请求方法,此方法是通用的,只要是通过ksoap与web端交互的都可以使用该方法,代码如下:

Java代码 复制代码 收藏代码
  1.     public static SoapObject common(String methodName, HashMap<String, Object> map, String nameSpace, String endPoint) {   
  2.          String soapAction = nameSpace + methodName;   
  3.          // 指定WebService的命名空间和调用的方法名   
  4.         SoapObject rpc = new SoapObject(nameSpace, methodName);   
  5.         // 设置需调用WebService接口需要传入的参数   
  6.         if (null != map && map.size() > 0) {   
  7.             Object[] key = map.keySet().toArray();   
  8.             for (int i = 0; i < key.length; i++) {   
  9.                 rpc.addProperty(key[i].toString(), map.get(key[i]));   
  10.             }   
  11.         }   
  12.         // 生成调用WebService方法的SOAP请求信息,并指定SOAP的版本   
  13.         SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);   
  14.         envelope.bodyOut = rpc;   
  15.         // 设置是否调用的是dotNet开发的WebService   
  16.         envelope.dotNet = false;   
  17.         // 设置连接超时时间为20秒   
  18.     HttpTransportSE transport = new HttpTransportSE(endPoint, timeout);   
  19.         try {   
  20.             // 调用WebService   
  21.             transport.call(soapAction, envelope);   
  22.         } catch (IOException e) {   
  23.             e.printStackTrace();   
  24.         } catch (XmlPullParserException e) {   
  25.             e.printStackTrace();   
  26.         }   
  27.         // 获取返回的数据   
  28.         SoapObject soapObject = (SoapObject) envelope.bodyIn;   
  29.         return soapObject;   
  30.     }   
  31. }  
	public static SoapObject common(String methodName, HashMap<String, Object> map, String nameSpace, String endPoint) {
         String soapAction = nameSpace + methodName;
         // 指定WebService的命名空间和调用的方法名
		SoapObject rpc = new SoapObject(nameSpace, methodName);
		// 设置需调用WebService接口需要传入的参数
		if (null != map && map.size() > 0) {
			Object[] key = map.keySet().toArray();
			for (int i = 0; i < key.length; i++) {
				rpc.addProperty(key[i].toString(), map.get(key[i]));
			}
		}
		// 生成调用WebService方法的SOAP请求信息,并指定SOAP的版本
		SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
		envelope.bodyOut = rpc;
		// 设置是否调用的是dotNet开发的WebService
		envelope.dotNet = false;
		// 设置连接超时时间为20秒
	HttpTransportSE transport = new HttpTransportSE(endPoint, timeout);
		try {
			// 调用WebService
			transport.call(soapAction, envelope);
		} catch (IOException e) {
			e.printStackTrace();
		} catch (XmlPullParserException e) {
			e.printStackTrace();
		}
		// 获取返回的数据
		SoapObject soapObject = (SoapObject) envelope.bodyIn;
		return soapObject;
	}
}


3、
    接着,就是写各种webservice数据交互的方法了,基本上都是封装成一个json对象再以字符串形式传递,这里是用户登录方法:

Java代码 复制代码 收藏代码
  1. public static String verifyUser(Context context, String userPhone, String userPwd)      {   
  2.         // 设置调用接口需要传递的参数名称、值   
  3.         HashMap<String, Object> paramMap = new HashMap<String, Object>();   
  4.         paramMap.put("opPhone", userPhone);   
  5.         paramMap.put("loginPwd", userPwd);   
  6.         try {   
  7.             // 调用接口   
  8.             SoapObject soapObject = common("userLogin", paramMap, NAME_SPACE_SALE, END_POINT_SALE);   
  9.             return soapObject.getProperty(0).toString();   
  10.         } catch (Exception e) {   
  11.             return null;   
  12.         }   
  13.     }  
public static String verifyUser(Context context, String userPhone, String userPwd)      {
		// 设置调用接口需要传递的参数名称、值
		HashMap<String, Object> paramMap = new HashMap<String, Object>();
		paramMap.put("opPhone", userPhone);
		paramMap.put("loginPwd", userPwd);
		try {
			// 调用接口
			SoapObject soapObject = common("userLogin", paramMap, NAME_SPACE_SALE, END_POINT_SALE);
			return soapObject.getProperty(0).toString();
		} catch (Exception e) {
			return null;
		}
	}


注:hashmap里的key就是web端webservice接口里的@WebParam(name = "opPhone"),此字符串一定要匹配。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics