移动设备开发中WebService的详解

本文详细介绍了如何使用MyEclipse开发Web和Android工程,包括使用Hibernate和Spring框架、创建Web服务接口、实现Android客户端调用Web服务的方法、以及配置和测试流程。重点在于通过实际例子演示了实体类、数据库映射、Pojo类封装、WebService接口及其实现、Dao层实现、Spring配置、以及如何在Android端调用Web服务。
要建一个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:[mw_shl_code=java,true]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
        }[/mw_shl_code]
Hibernate:
[mw_shl_code=java,true]<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>[/mw_shl_code]
2、PoJo包 
这里面是服务器端返回使用的类,webservice传递数据时,可能只会传递一部分数据,这样的话,就要把要传递的数据封装成一个pojo类,再转成一个json对象,这样的话无论是从代码的整洁、逻辑还是高效,都会是非常完美的写法。在web端和client端的类要完全一样,这样的话更为简单。
[mw_shl_code=java,true]/**
* 登陆状态
*/
public class DataOperateResult {
        private String status;
        public String getStatus() {
                return status;
        }
        public void setStatus(String status) {
                this.status = status;
        }
}[/mw_shl_code]
3、WebService接口 
    这里面是封装的webservice接口,手机端就是直接通过这些接口进行数据的传送与接收,最重要的是在接口上一定要加上"@WebService"这个注解,这样才能把此类里面的方法封装成一个webservice接口,关键代码如下:
[mw_shl_code=java,true]//手机客户端服务类(专门负责与手机客户端进行交互)
@WebService
public interface MobileClientService {
        /**
         * 登陆
         * @param opPhone
         * @param loginPwd
         */
        public String userLogin(@WebParam(name = "opPhone") String opPhone, @WebParam(name = "loginPwd") String loginPwd);
}[/mw_shl_code]
     要注意的是方法里的参数前一定要加上@WebParam(name = "***(随便取的名字)"),这是因为这个opPhone参数通过webservice发布出去之后是以opPhone这个名称存在的,在手机端那边的方法直接获取opPhone就可以了。 
4、WebService接口实现类 
ws里面接口的实现类,在这个类的开始,一定要加上"@WebService(endpointInterface = "com.silent.cn.ws.MobileClientService")"这个注解,它表示是继承自com.silent.cn.ws.MobileClientService的类,没有这一步,webservice接口是不会实现其功能的。下面是代码:
[mw_shl_code=java,true]@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();
                }
        }
}[/mw_shl_code] 
5、Dao和Dao实现类
[mw_shl_code=java,true]/**
* 用户登录DAO
*/
public interface UserLoginDao {
        /**
         * 根据用户名和用户密码登陆
         * @param userPhone 用户手机号码
         * @param passWord 用户密码
         * @return
         */
        public SysUser userLogin(String userPhone, String passWord);
}[/mw_shl_code]

[mw_shl_code=java,true]/**
* 用户登录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);
        }
}[/mw_shl_code]
6、Spring配置 
    这里spring的配置为了整洁与不臃肿,分成了三部分,分别实现了不同功能: 
applicationContext.xml:所有的spring配置信息,包括连接数据库、配置事务管理器、配置事务传播特性 、dao模板等等
Java代码  
[mw_shl_code=java,true]        <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>[/mw_shl_code]
Dao配置(applicationContext-dao.xml):
[mw_shl_code=java,true]<bean id="userLoginDao" class="com.silent.cn.dao.impl.UserLoginDaoImpl"
                parent="daoTemplate" />
[/mw_shl_code]
7、WebService接口配置(applicationContext-webservice.xml) 
这里设定的address就是该webservice的实际地址了:
[mw_shl_code=java,true]<!--
配置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>[/mw_shl_code]


8、配置web.xml 
在web里添加下面的语句:
[mw_shl_code=java,true]<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>[/mw_shl_code]
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上获取数据,代码如下:
[mw_shl_code=java,true]//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";[/mw_shl_code]
2、 然后,我们要写一个通用的WebService接口请求方法,此方法是通用的,只要是通过ksoap与web端交互的都可以使用该方法,代码如下:
[mw_shl_code=java,true]        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.toString(), map.get(key));
                        }
                }
                // 生成调用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;
        }
}[/mw_shl_code]
3、 接着,就是写各种webservice数据交互的方法了,基本上都是封装成一个json对象再以字符串形式传递,这里是用户登录方法:
[mw_shl_code=java,true]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;
                }
        }[/mw_shl_code]
注:hashmap里的key就是web端webservice接口里的@WebParam(name = "opPhone"),此字符串一定要匹配。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值