• day53_BOS项目_05


    • 今天内容安排:
      • 1、添加定区
      • 2、定区分页查询
      • 3、hessian入门 --> 远程调用技术
      • 4、基于hessian实现定区关联客户

    1、添加定区

    定区可以将取派员、分区、客户信息关联到一起。
    页面:WEB-INF/pages/base/decidedzone.jsp


    第一步:使用下拉框展示取派员数据,需要修改combobox的URL地址,发送请求
        <tr>
            <td>选择取派员</td>
            <td>
                <input class="easyui-combobox" name="staff.id"  
                    data-options="valueField:'id',textField:'name',
                        url:'${pageContext.request.contextPath}/staffAction_listajax.action'"
     />
      
            </td>
        </tr>

    浏览器效果截图:


    第二步:在StaffAction中提供listajax()方法,查询没有作废的取派员,并返回json数据
        /**
         * 查询没有作废的取派员,并返回json数据
         * @return
         * @throws IOException 
         */

        public String listajax() throws IOException {
            List<Staff> list = staffService.findListNoDelete();
            String[] excludes = new String[] {"decidedzones"}; // 我们只需要Staff的id和name即可,其余的都不需要,本例中我们只排除关联的分区对象
            this.writeList2Json(list, excludes);
            return "none";
        }

    第三步:在StaffService中提供方法查询没有作废的取派员

        /**
         * 查询没有作废的取派员,即查询条件:deltag值为“0”
         */

        public List<Staff> findListNoDelete() {
            // 创建离线条件查询对象
            DetachedCriteria detachedCriteria = DetachedCriteria.forClass(Staff.class);
            // 向离线条件查询对象中封装条件
            detachedCriteria.add(Restrictions.eq("deltag""0"));
            return staffDao.findByCriteria(detachedCriteria);
        }

    第四步:在IBaseDao中提供通用的条件查询方法
    IBaseDao.java

        // 条件查询(不带分页)
        public List<T> findByCriteria(DetachedCriteria detachedCriteria);

    BaseDaoImpl.java

        /**
         * 通用条件查询(不带分页)
         */

        public List<T> findByCriteria(DetachedCriteria detachedCriteria{
            return this.getHibernateTemplate().findByCriteria(detachedCriteria);
        }

    浏览器效果截图:


    第五步:使用数据表格datagrid展示未关联到定区的分区数据
    decidedzone.jsp
        <td valign="top">关联分区</td>
        <td>
            <table id="subareaGrid"  class="easyui-datagrid" border="false" style="300px;height:300px" 
                    data-options="url:'${pageContext.request.contextPath}/subareaAction_listajax.action',
                    fitColumns:true,singleSelect:false"
    >

                <thead>  
                    <tr>  
                        <th data-options="field:'id',30,checkbox:true">编号</th>  
                        <th data-options="field:'addresskey',150">关键字</th>  
                        <th data-options="field:'position',200,align:'right'">位置</th>  
                    </tr>  
                </thead> 
            </table>
        </td>

    浏览器效果截图:


    第六步:在SubareaAction中提供listajax()方法,查询未关联到定区的分区数据,并返回json数据
        /**
         * 查询未关联到定区的分区数据,并返回json数据
         * @return
         * @throws IOException 
         */

        public String listajax() throws IOException {
            List<Subarea> list = subareaService.findListNotAssociation();
            String[] excludes = new String[] {"region""decidedzone"}; // 本例中我们只排除关联的区域对象和定区对象
            this.writeList2Json(list, excludes);
            return "none";
        }

    Service层代码:

        /**
         * 查询未关联到定区的分区数据,即查询条件:decidedzone值为“null”
         */

        public List<Subarea> findListNotAssociation() {
            // 创建离线条件查询对象
            DetachedCriteria detachedCriteria = DetachedCriteria.forClass(Subarea.class);
            // 向离线条件查询对象中封装条件
            // detachedCriteria.add(Restrictions.eq("decidedzone", "null")); // 基本类型的属性使用eq()和ne()
            detachedCriteria.add(Restrictions.isNull("decidedzone")); // 引用类型的属性使用isNull()和isNotNull()
            return subareaDao.findByCriteria(detachedCriteria);
        }

    浏览器效果截图:


    第七步:为添加/修改定区窗口中的保存按钮绑定事件
        <!-- 添加/修改分区 -->
        <div style="height:31px;overflow:hidden;" split="false" border="false" >
            <div class="datagrid-toolbar">
                <a id="save" icon="icon-save" href="#" class="easyui-linkbutton" plain="true" >保存</a>
                <script type="text/javascript">
                    $(function() {
                        $("#save").click(function() {
                            var v = $("#addDecidedzoneForm").form("validate");
                            if (v) {
                                $("#addDecidedzoneForm").submit(); // 页面会刷新
                                // $("#addDecidedzoneForm").form("submit"); // 页面不会刷新
                            }
                        });
                    });
                
    </script>
            </div>
        </div>

    第八步:提交上面的添加定区的表单,发现id名称冲突
    浏览器截图:


    代码截图:

    即:关联分区中的复选框的field的名称叫id,定区编码的name名称也叫id,造成冲突,服务器不能够区分开他们哪个id是定区,还是哪个id是分区,如何解决呢?
    答:我们应该类比于选择取派员的name的名称staff.id这样,如上图绿色框框中的那样,即我们可以把关联分区中的复选框的field的名称改为subareaid。
    即:我们要在Subarea类中提供getSubareaid()方法,就相当于给Subarea类中的字段id重新起个名字,这样返回的json数据中就含有subareaid字段了。

    Subarea.java

    改过之后,浏览器截图:

    第十步:创建定区管理的Action,提供add()方法保存定区,提供subareaid数组属性接收多个分区的subareaid
    package com.itheima.bos.web.action;

    import org.springframework.context.annotation.Scope;
    import org.springframework.stereotype.Controller;

    import com.itheima.bos.domain.Decidedzone;
    import com.itheima.bos.web.action.base.BaseAction;

    /**
     * 定区设置
     * @author Bruce
     *
     */

    @Controller
    @Scope("prototype")
    public class DecidedzoneAction extends BaseAction<Decidedzone{

        // 采用属性驱动的方式,接收页面提交过来的参数subareaid(多个,需要用到数组进行接收)
        private String[] subareaid;
        public void setSubareaid(String[] subareaid) {
            this.subareaid = subareaid;
        }

        /**
         * 添加定区
         * @return
         */

        public String add() {
            decidedzoneService.save(model, subareaid);
            return "list";
        }
    }

    Service层代码:

    package com.itheima.bos.service.impl;

    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Transactional;

    import com.itheima.bos.dao.IDecidedzoneDao;
    import com.itheima.bos.dao.ISubareaDao;
    import com.itheima.bos.domain.Decidedzone;
    import com.itheima.bos.domain.Subarea;
    import com.itheima.bos.service.IDecidedzoneService;

    @Service
    @Transactional
    public class DecidedzoneServiceImpl implements IDecidedzoneService {

        // 注入定区dao
        @Autowired
        private IDecidedzoneDao decidedzoneDao;
        // 注入分区dao
        @Autowired
        private ISubareaDao subareaDao;
        /**
         * 添加定区,并修改分区的外键
         */

        public void save(Decidedzone model, String[] subareaid) {
            // 先保存定区表(一个定区含有多个分区)
            decidedzoneDao.save(model);

            // 再修改分区表的外键,java代码如何体现呢?答:让这两个对象关联下即可。谁关联谁都行。
            // 但是在关联之前,我们应该有意识去检查下通过反转引擎自动生成出来的Hibernate配置文件中,谁放弃了维护外键的能力。
            // 一般而言:是“一”的一方放弃。所以需要由“多”的一方来维护外键关系。

            for (String sid : subareaid) {
                // 根据分区id把分区对象查询出来,再让分区对象去关联定区对象model
                Subarea subarea = subareaDao.findById(sid); // 持久化对象
                // 分区对象 关联 定区对象 --> 多方关联一方
                subarea.setDecidedzone(model); // 关联完之后,会自动更新数据库,根据快照去对比,看看我们取出来的持久化对象是否跟快照长得不一样,若不一样,就刷新缓存。

                // 从效率的角度讲:我们应该拼接一个HQL语句去更新Subarea,而不是去使用Hibernate框架通过关联的方式更新
                // HQL:update Subarea set decidedzone=? where id=? -->
                // SQL:update bc_subarea set decidedzone_id=? where id=?
            }
        }
    }

    第十一步:配置struts.xml

        <!-- 定区管理:配置decidedzoneAction-->
        <action name="decidedzoneAction_*" class="decidedzoneAction" method="{1}">
            <result name="list">/WEB-INF/pages/base/decidedzone.jsp</result>
        </action>

    2、定区分页查询

    第一步:decidedzone.jsp页面修改datagrid的URL

        // 定区标准数据表格
        $('#grid').datagrid( {
            iconCls : 'icon-forward',
            fit : true,
            border : true,
            rownumbers : true,
            striped : true,
            pageList: [30,50,100],
            pagination : true,
            toolbar : toolbar,
            url : "${pageContext.request.contextPath}/decidedzoneAction_pageQuery.action",
            idField : 'id',
            columns : columns,
            onDblClickRow : doDblClickRow
        });

    第二步:在DecidedzoneAction中提供分页查询方法

        /**
         * 定区的分页查询
         * @return
         * @throws IOException 
         */

        public String pageQuery() throws IOException {
            decidedzoneService.pageQuery(pageBean);
            String[] excludes = new String[] {"currentPage""pageSize""detachedCriteria""subareas""decidedzones"};
            this.writePageBean2Json(pageBean, excludes);
            return "none";
        }

    第三步:修改Decidedzone.hbm.xml文件,取消懒加载

    3、hessian入门 --> 远程调用技术

    • Hessian是一个轻量级的 remoting on http 工具,使用简单的方法提供了RMI(Remote Method Invocation 远程方法调用)的功能。相比WebService,Hessian更简单、快捷。采用的是二进制RPC协议(Remote Procedure Call Protocol 远程过程调用协议),因为采用的是二进制协议,所以它很适合于发送二进制数据

    • 常见的远程调用的技术:

      • 1、webservice(CXF框架、axis框架),偏传统,基于soap(简单对象访问协议)协议,传输的是xml格式的数据,数据冗余比较大,传输效率低。现在也支持json。
      • 2、httpclient --> 电商项目:淘淘商城,大量使用
      • 3、hessian --> http协议、传输的是二进制数据,冗余较少,传输效率较高。
      • 4、dubbo --> 阿里巴巴
    • Dubbo是阿里巴巴SOA服务化治理方案的核心框架,每天为2,000+个服务提供3,000,000,000+次访问量支持,并被广泛应用于阿里巴巴集团的各成员站点。自开源后,已有不少非阿里系公司在使用Dubbo。

    • Tengine是由淘宝网发起的Web服务器项目。它在Nginx的基础上,针对大访问量网站的需求,添加了很多高级功能和特性。Tengine的性能和稳定性已经在大型的网站如淘宝网,天猫商城等得到了很好的检验。它的最终目标是打造一个高效、稳定、安全、易用的Web平台。

    • hessian有两种发布服务的方式:

      • 1、使用hessian框架自己提供的HessianServlet发布:com.caucho.hessian.server.HessianServlet
      • 2、和spring整合发布服务:org.springframework.web.servlet.DispatcherServlet
    • hessian入门案例

    服务端开发:
    第一步:创建一个java web项目,并导入hessian的jar包
    第二步:创建一个接口

        public interface HelloService {
            public String sayHello(String name);
            public List<User> findAllUser();
        }

    第三步:提供上面接口的实现类

        public class HelloServiceImpl implements HelloService {
            public String sayHello(String name) {
                System.out.println("sayHello方法被调用了");
                return "hello " + name;
            }

            public List<User> findAllUser() {
                List<User> list = new ArrayList<User>();
                list.add(new User(1"小艺"));
                list.add(new User(2"小军"));
                return list;
            }
        }

    第四步:在web.xml中配置服务

        <servlet>
            <servlet-name>hessian</servlet-name>
            <servlet-class>com.caucho.hessian.server.HessianServlet</servlet-class>
            <init-param>
                <param-name>home-class</param-name>
                <param-value>com.itheima.HelloServiceImpl</param-value>
            </init-param>
            <init-param>
                <param-name>home-api</param-name>
                <param-value>com.itheima.HelloService</param-value>
            </init-param>
        </servlet>
        <servlet-mapping>
            <servlet-name>hessian</servlet-name>
            <url-pattern>/hessian</url-pattern>
        </servlet-mapping>

    客户端开发:
    第一步:创建一个客户端项目(普通java项目即可),并导入hessian的jar包
    第二步:创建一个接口(和服务端接口对应)

        public interface HelloService {
            public String sayHello(String name);
            public List<User> findAllUser();
        }

    第三步:使用hessian提供的方式创建远程代理对象调用服务

    public class Test {

        public static void main(String[] args) throws MalformedURLException {
            // 通过hessian提供的工厂类创建一个代理对象,通过这个代理对象可以远程调用服务
            HessianProxyFactory factory = new HessianProxyFactory();
            HelloService remoteProxy= (HelloService) factory.create(HelloService.class"http://localhost:8080/hessian_server/hessian");

            String ret = remoteProxy.sayHello("test");
            System.out.println(ret);

            List<User> list = remoteProxy.findAllUser();
            for (User user : list) {
                System.out.println(user.getId() + "---" + user.getName());
            }
        }
    }

    4、基于hessian实现定区关联客户

    4.1、发布crm服务并测试访问

    第一步:创建动态的web项目crm,导入hessian的jar
    第二步:创建一个crm数据库和t_customer表


    第三步:在web.xml中配置spring的DispatcherServlet
        <!-- hessian发布服务的方式:和spring整合发布服务:org.springframework.web.servlet.DispatcherServlet -->
        <servlet>
            <servlet-name>remoting</servlet-name>
            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
            <load-on-startup>1</load-on-startup>
        </servlet>
        <servlet-mapping>
            <servlet-name>remoting</servlet-name>
            <url-pattern>/remoting/*</url-pattern>
        </servlet-mapping>

    第四步:提供接口CustomerService和Customer类、Customer.hbm.xml映射文件
    CustomerService.java

    package cn.itcast.crm.service;

    import java.util.List;

    import cn.itcast.crm.domain.Customer;

    // 客户服务接口 
    public interface CustomerService {
        // 查询未关联定区客户
        public List<Customer> findnoassociationCustomers();

        // 查询已经关联指定定区的客户
        public List<Customer> findhasassociationCustomers(String decidedZoneId);

        // 将未关联定区客户关联到定区上
        public void assignCustomersToDecidedZone(Integer[] customerIds, String decidedZoneId);
    }

    第五步:为上面的CustomerService接口提供实现类

    package cn.itcast.crm.service.impl;

    import java.util.List;

    import org.hibernate.Session;

    import cn.itcast.crm.domain.Customer;
    import cn.itcast.crm.service.CustomerService;
    import cn.itcast.crm.utils.HibernateUtils;

    public class CustomerServiceImpl implements CustomerService {

        public List<Customer> findnoassociationCustomers() {
            Session session = HibernateUtils.openSession();
            session.beginTransaction();

            String hql = "from Customer where decidedzone_id is null";
            List<Customer> customers = session.createQuery(hql).list();

            session.getTransaction().commit();
            session.close();

            return customers;
        }

        public List<Customer> findhasassociationCustomers(String decidedZoneId) {
            Session session = HibernateUtils.openSession();
            session.beginTransaction();

            String hql = "from Customer where decidedzone_id=?";
            List<Customer> customers = session.createQuery(hql).setParameter(0, decidedZoneId).list();

            session.getTransaction().commit();
            session.close();

            return customers;
        }

        public void assignCustomersToDecidedZone(Integer[] customerIds, String decidedZoneId) {
            Session session = HibernateUtils.openSession();
            session.beginTransaction();

            // 取消定区所有关联客户
            String hql2 = "update Customer set decidedzone_id=null where decidedzone_id=?";
            session.createQuery(hql2).setParameter(0, decidedZoneId).executeUpdate();

            // 进行关联
            String hql = "update Customer set decidedzone_id=? where id=?";
            if (customerIds != null) {
                for (Integer id : customerIds) {
                    session.createQuery(hql).setParameter(0, decidedZoneId).setParameter(1, id).executeUpdate();
                }
            }
            session.getTransaction().commit();
            session.close();
        }
    }

    第六步:在WEB-INF目录提供spring的配置文件remoting-servlet.xml

        <!-- 通过配置的方式对外发布服务 -->
        <!-- 业务接口实现类  -->
        <bean id="customerService" class="cn.itcast.crm.service.impl.CustomerServiceImpl" />

        <!-- 注册hessian服务 -->
        <bean id="/customer" class="org.springframework.remoting.caucho.HessianServiceExporter">
            <!-- 业务接口实现类 -->
            <property name="service" ref="customerService" />
            <!-- 业务接口 -->
            <property name="serviceInterface" value="cn.itcast.crm.service.CustomerService" />
        </bean>

    第七步:发布crm服务
    第八步:在hessian_client客户端调用crm服务获得客户数据
    注意:拷贝接口CustomerService代码文件放到客户端中,同时必须在hessian_client客户端新建和crm服务端一样的实体Bean目录,如下图所示:


    hessian_client客户端调用代码如下:
    package com.itheima;

    import java.net.MalformedURLException;
    import java.util.List;

    import org.junit.Test;

    import com.caucho.hessian.client.HessianProxyFactory;

    import cn.itcast.crm.domain.Customer;

    public class TestService {
        @Test
        public void test1() throws MalformedURLException {
            // 通过hessian提供的工厂类创建一个代理对象,通过这个代理对象可以远程调用服务
            HessianProxyFactory factory = new HessianProxyFactory();
            CustomerService remoteProxy= (CustomerService) factory.create(CustomerService.class, "http://localhost:8080/crm/remoting/customer");
            List<Customer> list = remoteProxy.findnoassociationCustomers();
            for (Customer customer : list) {
                System.out.println(customer);
            }

            // 上面的演示方式:我们手动创建一个代理对象,通过代理对象去调用,然后获取服务端发布的客户数据。
            // 实际的开发方式:我们只需要在applicationContext.xml中配置一下,由spring工厂帮我们去创建代理对象,再将该代理对象注入给action、service,他们再去使用该代理对象即可。
            // 如何配置呢?配置相关代码如下:
            /*
            <!-- 配置远程服务的代理对象 -->
            <bean id="customerService" class="org.springframework.remoting.caucho.HessianProxyFactoryBean">
                <property name="serviceInterface" value="cn.itcast.bos.service.ICustomerService"/>
                <property name="serviceUrl" value="http://localhost:8080/crm/remoting/customer"/>
            </bean>
            */

        }
    }

    客户端控制台输出:

    cn.itcast.crm.domain.Customer@59b746f
    cn.itcast.crm.domain.Customer@20f92649
    cn.itcast.crm.domain.Customer@45409388
    cn.itcast.crm.domain.Customer@1295e93d
    cn.itcast.crm.domain.Customer@3003ad53
    cn.itcast.crm.domain.Customer@41683cc5
    cn.itcast.crm.domain.Customer@226dcb0f
    cn.itcast.crm.domain.Customer@562e5771

    服务端控制台输出:

    Hibernate: 
        select
            customer0_.id as id0_,
            customer0_.name as name0_,
            customer0_.station as station0_,
            customer0_.telephone as telephone0_,
            customer0_.address as address0_,
            customer0_.decidedzone_id as decidedz6_0_ 
        from
            t_customer customer0_ 
        where
            customer0_.decidedzone_id is null

    4.2、在bos项目中调用crm服务获得客户数据

    第一步:在bos项目中导入hessian的jar包
    第二步:从crm项目中复制CustomerService接口和Customer类到bos项目中
    第三步:在spring配置文件中配置一个远程服务代理对象,调用crm服务

        <!-- 配置远程服务的代理对象 -->
        <bean id="customerService" class="org.springframework.remoting.caucho.HessianProxyFactoryBean">
            <property name="serviceInterface" value="com.itheima.bos.crm.CustomerService"/>
            <property name="serviceUrl" value="http://localhost:8080/crm/remoting/customer"/>
        </bean>

    第四步:将上面的代理对象通过注解方式注入到BaseAction中

        @Autowired 
        protected CustomerService remoteProxy;

    第五步:为定区列表页面中的“关联客户”按钮绑定事件,发送2次ajax请求访问DecidedzoneAction,在DecidedzoneAction中调用hessian代理对象,通过代理对象可以远程访问crm获取客户数据,获取数据后进行解析后,填充至左右下拉框中去

        // 设置全局变量:存储选中一个定区时的 定区id
        var decidedzoneid;
        // 关联客户窗口
        function doAssociations(){
            // 在打开关联客户窗口之前判断是否选中了一个定区,即获得选中的行
            var rows = $("#grid").datagrid("getSelections");
            if (rows.length == 1) {
                // 打开窗口
                $("#customerWindow").window('open');
                // 清空窗口中的下拉框内容
                $("#noassociationSelect").empty();
                $("#associationSelect").empty();

                // 发送ajax请求获取未关联到定区的客户(左侧下拉框)
                var url1 = "${pageContext.request.contextPath}/decidedzoneAction_findnoassociationCustomers.action";
                $.post(url1, {}, function(data{
                    // alert(data); // json数据
                    // 解析json数据,填充至左侧下拉框中去
                    for (var i = 0; i < data.length; i++) {
                        var id = data[i].id;
                        var name = data[i].name;
                        $("#noassociationSelect").append("<option value='" + id + "'>" + name + "</option>");
                    }
                }, 'json');

                decidedzoneid = rows[0].id;
                // 发送ajax请求获取关联到当前选中定区的客户(右侧下拉框)
                var url2 = "${pageContext.request.contextPath}/decidedzoneAction_findhasassociationCustomers.action";
                $.post(url2, {"id":decidedzoneid}, function(data{
                    // alert(data); // json数据
                    // 解析json数据,填充至右侧下拉框中去
                    for (var i = 0; i < data.length; i++) {
                        var id = data[i].id;
                        var name = data[i].name;
                        $("#associationSelect").append("<option value='" + id + "'>" + name + "</option>");
                    }
                }, 'json');
            } else {
                // 没有选中或选中多个,提示信息
                $.messager.alert("提示信息","请选择一条定区记录进行操作","warning");
            }
        }

    第六步:为“左右移动按钮”绑定事件

        <td>
            <input type="button" value="》》" id="toRight"><br/>
            <input type="button" value="《《" id="toLeft">
            <script type="text/javascript">
                $(function() {
                    // 为右移动按钮绑定事件
                    $("#toRight").click(function() {
                        $("#associationSelect").append($("#noassociationSelect option:selected"));
                        $("#associationSelect>option").removeAttr("selected"); // 移除它们默认的选中状态
                    });
                    // 为右移动按钮绑定事件
                    $("#toLeft").click(function() {
                        $("#noassociationSelect").append($("#associationSelect option:selected"));
                        $("#noassociationSelect>option").removeAttr("selected"); // 移除它们默认的选中状态
                    });
                });
            
    </script>
        </td>

    第七步:为关联客户窗口中的“关联客户”按钮绑定事件

    <script type="text/javascript">
        $(function() {
            // 为关联客户按钮绑定事件
            $("#associationBtn").click(function() {
                // 在提交表单之前,选中右侧下拉框中所有的选项
                $("#associationSelect option").attr("selected""selected"); // attr(key, val) 给一个指定属性名设置值
                // 在提交表单之前设置隐藏域的值(定区id)
                $("input[name=id]").val(decidedzoneid);
                // 提交表单
                $("#customerForm").submit();
            });
        });
    </script>

    第八步:在定区Action中接收提交的参数,调用crm服务实现定区关联客户的业务功能

        /**
         * 调用代理对象,查询未关联到定区的客户
         * @return
         * @throws IOException 
         */

        public String findnoassociationCustomers() throws IOException {
            List<Customer> list = remoteProxy.findnoassociationCustomers();
            String[] excludes = new String[] {"station""address"};
            this.writeList2Json(list, excludes);
            return "none";
        }

        /**
         * 调用代理对象,查询已经关联到指定定区的客户
         * @return
         * @throws IOException 
         */

        public String findhasassociationCustomers() throws IOException {
            List<Customer> list = remoteProxy.findhasassociationCustomers(model.getId());
            String[] excludes = new String[] {"station""address"};
            this.writeList2Json(list, excludes);
            return "none";
        }

        // 采用属性驱动的方式,接收页面提交过来的参数customerIds(多个,需要用到数组进行接收)
        private Integer[] customerIds;
        public void setCustomerIds(Integer[] customerIds) {
            this.customerIds = customerIds;
        }

        /**
         * 调用代理对象,将未关联定区的客户关联到定区上
         * @return
         */

        public String assignCustomersToDecidedZone() {
            remoteProxy.assignCustomersToDecidedZone(customerIds, model.getId());
            return "list";
        }
  • 相关阅读:
    odoo 的各种domain
    odoo search之时间搜索,时间段查询
    git 修改远程仓库地址
    Windows 挂起进程
    结构体 偏移量 (size_t)&(((s *)0)->m) , list相关
    Data Flow Diagram with Examples
    Windows环境,获取当前线程的ID,GetCurrentThreadId
    获取 保存 系统信息 [Windows]
    notepad正则删除关键词所在行
    文件或文件夹改变后,发信号让系统刷新
  • 原文地址:https://www.cnblogs.com/chenmingjun/p/9754441.html
Copyright © 2020-2023  润新知