清风飒影 Blog

自由、平等、随意、突破!

Jfinal集成dubbo

| 评论

通过我的推荐,公司上个产品使用了淘宝的dubbo框架,应用效果还不错。 后端技术使用的是:springmvc+hibernatejap+dubbo。 最近参与一个新的产品,想使用jfinal做后端,同时集成dubbo框架, 网上没有现成的集成例子,自己动手丰衣足食,其中也遇到了一些坑,为了 避免有同样需求的人出错,这里做个记录。 dubbo文档http://alibaba.github.io/dubbo-doc-static/Home-zh.htm

注意事项:由于阿里关闭了dubbo.xsd的线上路径。需要将dubbo.xsd文件导入到eclipse本地。 window->preferences->xml->xml catalog->add->catalog entity->file system ->dubbo.xsd文件在dubbo-2.5.3.jar中(不限版本,解压到磁盘目录)-> key=http://code.alibabatech.com/schema/dubbo/dubbo.xsd PS:直接导入后,key默认没有后面的/dubbo.xsd 要手动加上,再在项目上右键validate即可消除xml校验错误

步骤
1.  准备jar文件,拷贝jfinal的spring支持jar文件到web-inf/lib目录下

spring依赖

2.  拷贝dubbo依赖到web-inf/lib目录下。一定要拷贝到lib目录下并在eclipse中右键buildpath -> add to buildpath
    运行的时候,项目会验证dubbo.xsd文件。文件在dubbo.2.5.3.jar中。

dubbo依赖

3.  applicationContext.xml、consumer.xml文件放到eclipse项目的src根目录下
    applicationContext.xml内容
<?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns="http://www.springframework.org/schema/beans"  
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
    xmlns:context="http://www.springframework.org/schema/context"  

    xsi:schemaLocation="
          http://www.springframework.org/schema/beans   
          http://www.springframework.org/schema/beans/spring-beans.xsd   
          http://www.springframework.org/schema/context   
          http://www.springframework.org/schema/context/spring-context.xsd   ">

    <import resource="consumer.xml"/>
</beans> 
    consumer.xml内容,注意接口的包路径一定要和提供者的package一致。不然找不到。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
    xsi:schemaLocation="http://www.springframework.org/schema/beans        
    http://www.springframework.org/schema/beans/spring-beans.xsd        
    http://code.alibabatech.com/schema/dubbo        
    http://code.alibabatech.com/schema/dubbo/dubbo.xsd 

    ">

    <!-- 消费方应用名,用于计算依赖关系,不是匹配条件,不要与提供方一样 -->
    <dubbo:application name="xjly3"  />

    <!-- 使用multicast广播注册中心暴露发现服务地址 -->
    <dubbo:registry  protocol="zookeeper"  address="127.0.0.1:2181" />
    <!-- 生成远程服务代理,可以和本地bean一样使用demoService -->
    <dubbo:reference id="demoService" interface="com.supermap.egispservice.base.service.DemoService" version="2.5.3" check="false"/>

</beans>
    provider.xml内容,这个文件是放在提供者项目中的。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://code.alibabatech.com/schema/dubbo
        http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
    <!-- 提供方应用信息,用于计算依赖关系 -->
    <dubbo:application name="provider_menu" />

    <!--使用zookeeper注册中心暴露服务地址 -->
    <dubbo:registry  protocol="zookeeper"  address="127.0.0.1:2181" />
    <dubbo:protocol port="20821"/>
    <dubbo:service interface="com.supermap.egispservice.base.service.DemoService" version="2.5.3" ref="demoService"  timeout="30000" retries="0" async="false" loadbalance="leastactive" actives="200"/>
    <bean id="demoService" class="com.supermap.egispservice.base.service.DemoServiceImpl" />

</beans>
4.  JfinalConfig子类中添加springplugin
log.info("SpringPlugin spring");
me.add(new SpringPlugin("classpath:applicationContext.xml"));
5.  controller调用代码
import java.util.List;

import little.ant.platform.annotation.Controller;
import little.ant.platform.controller.BaseController;
import little.ant.platform.model.User;
import little.ant.platform.tools.ToolContext;
import little.ant.crm.model.Customer;
import little.ant.crm.model.Messenger;
import little.ant.crm.model.MessengerRemark;
import little.ant.crm.service.MessengerService;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;

import com.jfinal.aop.Before;
import com.jfinal.plugin.spring.Inject;
import com.jfinal.plugin.spring.IocInterceptor;
import com.supermap.egispservice.base.service.DemoService;

@Before(IocInterceptor.class)
@Controller(controllerKey = "/jf/crm/messenger")
public class MessengerController extends BaseController {

    @SuppressWarnings("unused")
    private static Logger log = Logger.getLogger(MessengerController.class);

    @Inject.BY_NAME
    private DemoService demoService;

    /**
     * 默认列表
     */
    public void index() {
        log.info("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
        log.info(demoService.sayHello("jfinal!"));
        log.info("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");

        render("/crm/messenger/list.html");
    }
}

Openlayers2加载百度地图

| 评论

可以完成加载百度地图,但使用纠偏后的坐标定位有偏移。将下面连接的代码做了部分修改。 [转]http://www.cnblogs.com/songjiang6940/p/4139258.html

主页

OpenLayers.Layer.Baidu = OpenLayers.Class(OpenLayers.Layer.TileCache, {
    initialize: function (name, url, options) {
        var tempoptions = OpenLayers.Util.extend({
        'format': 'image/png',
        isBaseLayer: true
        }, options);
        OpenLayers.Layer.TileCache.prototype.initialize.apply(this, [name, url, {},
        tempoptions]);
        this.extension = this.format.split('/')[1].toLowerCase();
        this.extension = (this.extension == 'jpg') ? 'jpeg' : this.extension;
        this.transitionEffect = "resize";
        this.buffer = 0;
    },
    /**
    * 按地图引擎切图规则实现的拼接方式
    */
    getURL: function (bounds) {
        var tilez=this.map.zoom-1;
        var res = this.map.getResolution();
        var bbox = this.map.getMaxExtent();
        var size = this.tileSize;
        var bx = Math.round((bounds.left - this.tileOrigin.lon) / (res * size.w));
        var by = Math.round((bounds.bottom - this.tileOrigin.lat) / (res * size.h));
        tilez = tilez + 1; 
        var x = bx.toString().replace("-","M"); 
        var y = by.toString().replace("-","M"); 
        var urlsNum = parseInt((bx + by) % this.url.length); 
        var strURL = ""; 
        strURL = this.url[urlsNum] + '?qt=tile&x='+x+'&y='+y+'&z='+tilez+'&styles=pl&udt=20140807';
        return strURL;
    },
    clone: function (obj) {
        if (obj == null) {
            obj = new OpenLayers.Layer.Baidu(this.name, this.url, this.options);
        }
        obj = OpenLayers.Layer.TileCache.prototype.clone.apply(this, [obj]);
        return obj;
    },
    CLASS_NAME: "OpenLayers.Layer.Baidu"
});

/**
 * 墨卡托投影坐标转换为经纬度坐标
 */
function meterXY2GeoLoc(x, y, precision){
    var earthCircumferenceInMeters = new Number(40075016.685578488);
    var halfEarthCircumferenceInMeters = earthCircumferenceInMeters / 2;

    var geoX = x/halfEarthCircumferenceInMeters*180;
    var geoY = y/halfEarthCircumferenceInMeters*180;
    geoY = Math.atan(Math.exp(geoY * (Math.PI / 180.0)))*360.0/Math.PI - 90;

    geoX = setPrecision(geoX, precision);
    geoY = setPrecision(geoY, precision);

    var obj = new Object();
    obj.lngX = geoX;
    obj.latY = geoY;
    return obj;
}

/**
 * 经纬度坐标转墨卡托投影坐标
 */
function geoLoc2MeterXY(x, y){
    var earthCircumferenceInMeters = new Number(40075016.685578488);
    var halfEarthCircumferenceInMeters = earthCircumferenceInMeters / 2;

    var geoX = new Number(x);
    var geoY = new Number(y);

    var mx = geoX / 180.0 * halfEarthCircumferenceInMeters;
    var my = Math.log(Math.tan((90 + geoY) * Math.PI / 360.0)) / (Math.PI / 180.0);
    my = my / 180.0 * halfEarthCircumferenceInMeters;

    var obj = new Object();
    obj.lngX = mx;
    obj.latY = my;
    return obj;
}
//这个参数在对接中还是稍微有y轴的偏移,考虑因该是百度平面坐标系不是基于web墨卡托投影,而这个用的是web墨卡托投影的方式却对接的。
var tileOrigin = new OpenLayers.LonLat(0,28000);
//var tileOrigin = new OpenLayers.LonLat(-120,22000);
var maxExtent = new OpenLayers.Bounds(-20037508.34,-20037508.34,20037508.34,20037508.34);
var opts = {numZoomLevels:20,maxResolution:262144,maxExtent :maxExtent ,tileOrigin :tileOrigin }

var baidu = new OpenLayers.Layer.Baidu ('baidu',["http://online1.map.bdimg.com/tile/"],opts);
var map = new OpenLayers.Map("map",{projection:"EPSG:900913",displayProjection:"EPSG:4326"});

map.addLayers([baidu]);
//成都-天府广场//baidu:104.072593, 30.663547,GPS:104.0636,30.6599,google:104.066109, 30.657483
//北京-天安门拱桥//baidu:116.40392 ,39.914552,GPS:116.3913,39.9068,google:116.397547, 39.908208
var center=geoLoc2MeterXY(104.072593, 30.663547);
//北京
map.setCenter(new OpenLayers.LonLat(12958399.4681885, 4852082.44060595),10);
//map.setCenter(new OpenLayers.LonLat(center.lngX, center.latY),18);

Crm系统

| 评论

经朋友介绍,帮忙做一个内部管理用的CRM系统。用于规范工作流,方便领导管理。

业务对象
1.  员工(业务员+主管):
用户名,密码,姓名,ids,uuid(自增),创建时间

2.  信息员:
电话号码(1个,必填),qq 1个,姓名1个,公司名称,商圈名称,ids,uuid,录入时间(YYMMDDHHMMSS),是否过期,回访时间(业务员可以调整)
注意:信息员名称‘电话  业务员不能修改,主管可以修改。

3.  客户(添加信息员后,才能针对信息员添加他下面的客户)
ids,uuid,qq,项目类型(办公,餐饮,酒店,卖场,展会),公司名称,甲方负责人姓名和电话(1-3对,必须1个)
甲方负责人职位1个,量房时间,量房地点,主营业务,项目地址,建筑面积,办公地址,工程类型(新装工程,
整体改造,局部改造),房屋类型(租赁房屋,购买房屋),备注信息

4.  回访记录(员工只能添加,不能删除,不能修改)
ids,uuid,内容,添加时间(系统自动生成)

查询条件:姓名,电话,编码,(查询客户时,可以加一个查询条件:信息员姓名)
业务逻辑
业务员
1.  员工录入信息员/客户后,在系统里显示录入时间(自动生成)
2.  其他员工不能重复录入信息员/客户(以电话为判断标准)。重复录入时提示:已录入,在XX业务员下
3.  业务员可以针对某个信息员/客户添加“回访记录”,回访记录时间有系统自动生成
4.  业务员不能删除信息员/客户
5.  业务员查询客户时,单独一个页面显示所有信息员的客户(查询条件,姓名,电话,编码,信息员)。
    查询后可以修改客户信息,但不能修改客户的电话号码。
6.  每个业务员只能看自己的信息业/客户

主管(主管也有员工的录入信息功能)
1.  市场部主管可以看下面业务员录入的信息员/客户信息,但不包括电话号码
2.  市场部主管可以调配信息由/客户到其他业务员下(可以批量调配)
3.  批复:(可以批量操作)
3.1 录入信息后,自动生成回访时间(默认为10天以后).
3.2 业务员可以调整回访时间
3.3 如果10天后仍未回访,就不能再回访(系统显示过期)
3.4 市场部主管可以批复过期的信息,系统将回访时间调整到当前时间10条后
4.  主管可以删除信息员/客户
5.  主管可以删除回访记录

部分竣工截图 主页 登陆 添加信息员 查询所有信息员

博客搬家!!

| 评论

工作到现在,由于工作繁忙,陆陆续续写了些博客内容,几乎都是用的免费空间。 免费空间嘛,你懂的。

  1. 最开始是在javaeye, 那上面有不少大牛,写了几篇文章。后来javaeye被csdn收购了,没落了。
  2. 后来Google的GAE兴起,折腾了几下,没多久就被墙了
  3. 百度看Google搞的风声水起,出了个BAE,就用WordPress搭建了一个PHP博客,本来想就这样了,可是百度收费了。。。
  4. BAE的博客没有备份,最近工作又比较忙,没怎么写博客了,想想,还是需要将一些代码经验记录下来。 看github有静态空间,果断放过来。还能放代码。