json-lib反序列化精度丢失问题

最近在工作中,遇到一个问题,项目中某处使用了json-lib的2.4-jdk15版本.问题最终简化为 double amount = 6264583.33; String jsonString = "{\"pi\":" + amount + "}"; JSONObject jsonObject = JSONObject.fromObject(jsonString); System.out.println("转换前:" + jsonString); System.out.println("转换后:" + jsonObject); 这个值输出的将会是6264583.5 这个值.这个问题.先google一下,很快赵到了 http://sourceforge.net/p/json-lib/bugs/116/ 于是,大概问题知道了.是json-lib的一个bug,但是这个bug怎么来的呢.结合这个bug下面的评论和debug代码,先以pi这个例子,很快走到了. 可以看到json-lib走到了apache common-lang(2.5这个版本) 的NumberUtils.createNumber处,此时String的还是对的. 继续单步,来到这个方法里面 可以看到这里小数部分,整数部分也都还是对的.继续向下走.我擦.画风不太对.居然采用了先尝试float,发现没问题.然后就继续尝试double,我擦.直接数据就丢失了呀.. 好吧..那么现在问题就便成了更简单的一个问题. 使用NumberUtils.createNumber 的bug.在bug issue里,有人提到.这个bug,apache官方已知.好的. https://issues.apache.org/jira/browse/LANG-693 然后在这里有官方的一次修复,修复记录在这里.3.2版本已经修复. http://svn.apache.org/viewvc?view=revision&revision=1484263 可以看到是对小数部分的长度进行了判断.如果小于7位,就用float转换,如果大于7,小于16,就用double,如果还大,就用BigDecimal. n = org.apache.commons.lang3.math.NumberUtils.createNumber("3.14159265358"); System.out.println("lang3_createNumber_3.14159265358---->" + n + "->精度正常"); 于是我继续debug,看common-lang3的修复情况,好像确实是修复了.但是对于我出现的问题1.6264583.33 这个数字,还是出现了精度丢失,因为这里小数部分小于7位,所以尝试使用float转换,直接丢失精度 修复不完善.. 于是提个bug :https://issues.apache.org/jira/browse/LANG-1187 等回复. 继续.公司内部一般使用fastjson,那么如果我使用fastjson,有问题吗? 发现没有问题. Object o = com.alibaba.fastjson.JSONObject.parse("3.14159265358"); System.out.println("fastjson_createNumber_3.14159265358---->" + o + "->精度正常"); o = com.alibaba.fastjson.JSONObject.parse("6264583.33"); System.out.println("fastjson_createNumber_6264583.33---->" + o + "->精度正常"); 可以看到,这里做转换的时候传递了一个是否是bigdecimal的标识. [Read More]

zookeeper伪集群部署

zookeeper是用来管理分布式环境的系统主要用来服务发现,配置管理,同步.大致原理是zookeeper 自身集群的每个节点都维护这一个目录树,内容相同,每个节点的数据一致性由zookeeper自身的算法来解决.下篇尝试.zookeeper本篇主要说明如果部署zookeeper的分布式环境. 下载 zookeeper由apache在管理,下载地址:http://www.apache.org/dyn/closer.cgi/zookeeper/.下载完成后,随便放个目录好了.. 配置 本次创建3个节点. 1 . 存储目录准备 首先给每个伪节点创建一个目录.用来存储每个节点保存的目录信息.真实的分布式环境将对应在不同的机器上. 这里我在D:\zookeeper,创建三个目录,分别是zk1,zk2,zk3. 然后为每个集群编写一个myid文件,标识集群id 2 . 启动配置文件 下载完成后,在conf目录会看到由一个zoo_sample.cfg实例配置文件,我们可以以这个为模板.来为分布式环境的每个zookeeper节点配置一个节点的数据目录,端口.其他节点的信息等. 我们在conf目录例创建三个配置文件,分别为zk1.cfg,zk2.cfg,zk3.cfg; 里面的值 zk1.cfg tickTime=2000 initLimit=10 syncLimit=5 dataDir=D:/zookeeper/zk1 clientPort=2181 server.1=127.0.0.1:2888:3888 server.2=127.0.0.1:2889:3889 server.3=127.0.0.1:2890:3890 zk2.cfg tickTime=2000 initLimit=10 syncLimit=5 dataDir=D:/zookeeper/zk2 clientPort=2182 server.1=127.0.0.1:2888:3888 server.2=127.0.0.1:2889:3889 server.3=127.0.0.1:2890:3890 zk1.cfg tickTime=2000 initLimit=10 syncLimit=5 dataDir=D:/zookeeper/zk3 clientPort=2183 server.1=127.0.0.1:2888:3888 server.2=127.0.0.1:2889:3889 server.3=127.0.0.1:2890:3890 这里的server.1.2.3这就是每个机器对应的myid的值. server.1=127.0.0.1:2888:3888解释一下这条配置.前面的2888是各个节点用来互相交流.选取leader的端口.后面这个端口,3888是各个节点用来和leader沟通的节点.而clientPort 是开放出去,等待客户端连接的端口. 启动 分别启动三个实例,在zookeeper的安装目录下.进如bin目录,复制三个zkServer.cmd 文件,要是linux就不用这么麻烦了.. 分别加上一行 set ZOOCFG=../conf/zk1.cfg 最终这个文件像这样 setlocal call "%~dp0zkEnv.cmd" set ZOOMAIN=org.apache.zookeeper.server.quorum.QuorumPeerMain set ZOOCFG=../conf/zk1.cfg echo on java "-Dzookeeper.log.dir=%ZOO_LOG_DIR%" "-Dzookeeper.root.logger=%ZOO_LOG4J_PROP%" -cp "%CLASSPATH%" %ZOOMAIN% "%ZOOCFG%" %* endlocal 然后直接双击启动zkServer1. [Read More]

Java可重入锁学习笔记

前几天被前辈问到这个可重入锁,结果忘掉了.于是抽空整个了解一下 目录 什么是可重入锁 为什么要可重入 如何实现可重入锁 有不可重入锁吗 demo代码展示 参考文章 1 . 什么是可重入锁 锁的概念就不用多解释了,当某个线程A已经持有了一个锁,当线程B尝试进入被这个锁保护的代码段的时候.就会被阻塞.而锁的操作粒度是”线程”,而不是调用(至于为什么要这样,下面解释).同一个线程再次进入同步代码的时候.可以使用自己已经获取到的锁,这就是可重入锁 java里面内置锁(synchronize)和Lock(ReentrantLock)都是可重入的 2 . 为什么要可重入 如果线程A继续再次获得这个锁呢?比如一个方法是synchronized,递归调用自己,那么第一次已经获得了锁,第二次调用的时候还能进入吗? 直观上当然需要能进入.这就要求必须是可重入的.可重入锁又叫做递归锁,再举个例子. public class Widget { public synchronized void doSomething() { ... } } public class LoggingWidget extends Widget { public synchronized void doSomething() { System.out.println(toString() + ": calling doSomething"); super.doSomething();//若内置锁是不可重入的,则发生死锁 } } 这个例子是java并发编程实战中的例 子.synchronized 是父类Widget的内置锁,当执行子 类的方法的时候,先获取了一次Widget的锁,然后在执行super的时候,就要获取一次,如果不可重入,那么就跪了. 3 . 如何实现可重入锁 为每个锁关联一个获取计数器和一个所有者线程,当计数值为0的时候,这个所就没有被任何线程只有.当线程请求一个未被持有的锁时,JVM将记下锁的持有者,并且将获取计数值置为1,如果同一个线程再次获取这个锁,技术值将递增,退出一次同步代码块,计算值递减,当计数值为0时,这个锁就被释放. ReentrantLock里面有实现 4 . 有不可重入锁吗 这个还真有.Linux下的pthread_mutex_t锁是默认是非递归的。可以通过设置PTHREAD_MUTEX_RECURSIVE属性,将pthread_mutex_t锁设置为递归锁。如果要自己实现不可重入锁,同可重入锁,这个计数器只能为1.或者0,再次进入的时候,发现已经是1了,就进行阻塞.jdk里面没有默认的实现类. 5 . demo代码展示 5.1 内置锁的可重入 [Read More]

jenkins相关资料

jenkins相关资料

jenkins的前身是hudson,是为了做持续集成测试而诞生的框架.

简单说就是把代码流配置上去,然后该框架就能根据设定的时间或其他方式不间断的执行测试用例.并给出报告.这样就可以随时掌控代码质量.支持执行shell命令.支持短信通知等等.

jenkins,首先从http://jenkins-ci.org/官方下载war包,然后有两种方式可以本地部署,一种直接执行 java -jar hudson.war,然后在本地的8080端口访问就可以了.另一种是我们希望部署在容器上,那么可以部署到tomcat,jetty等等.直接拷贝war包到对应的目录即可.

部署成功后,可以新建job,然后配置svn流,配置build时间,配置一下build之前的动作,配置一下各种命令,执行完成后通知等等就可以了.

最近因为有个功能感觉通过开发jenkins插件的方式会更加方便,周末大量读了一些文档,能找到的都是helloworl.摸索了一下,已经写出一个小的demo了,后面改进一下,.就ok了.先简单把这个过程中收集的资料整理一下.基本都看过觉得还不错的,官方文档不给力.下周希望可以写完,然后分享出来.

  1. jenkins入门文档
  2. The hudson book
  3. Writing-first-hudson-plugin
  4. Hudson插件开发简介
  5. Hudson插件开发入门体验
  6. 插件界面设计设计的各种tag介绍
  7. 官方插件开发
  8. UI开发jelly介绍
  9. jenkins入门(itech)

Spring揭秘-23章,Spring MVC初体验

 鸟瞰Spring MVC

与其他请求驱动的Web框架思路类似。org.springframework.web.servlet.DispatcherServlet就是Spring mvC中的Front Controller。负责处理请求,但是不针对具体的处理逻辑。而是委派给下一级的控制器,也就是org.springframework.web.servlet.mvc.Controller去执行。
DispatcherServlet的处理流程如下:
1.HandlerMapping
DispathcherServlet是FrontController,所以他服务于一组Web请求,需要在web.xml中配置。
DispathcherServlet需要自己处理请求和处理之前的对应关系,比如根据参数对应到不同的Controller上。为了更加方便的处理映射的匹配,引入HandlerMapping用来获取需要处理请求的对应的Controller类。
2.Controller
对应于DispathcherServlet的次级控制器,本身实现了对应某个具体Web请求的处理逻辑,当HandlerMapping查到了Controller之后,DispathcherServlet获得了HandlerMapping的返回结果。然后调用Controller处理请求,处理完成后,返回一个ModelAndView实例,里面包含两部分内容
视图的逻辑名称,DispathcherServlet根据名称决定显示哪个视图
模型数据,渲染过程中需要将这些模型数据并入视图的显示中
ViewResolver和View
我们已经来到了最后一步,要转成最终的JSP视图文件。由于模板引擎很多,Spring提供了一套基于ViewResolver和View的抽象层。

[来自为知笔记(Wiz)](http://www.wiz.cn/i/e0140d75 "来自为知笔记(Wiz)")
java  spring 

Spring揭秘-22章,迈向Spring MVC的旅程

Spring揭秘-22章,迈向Spring MVC的旅程

Servlet导致数据访问逻辑和业务处理逻辑和对应的视图渲染逻辑相互混杂。之后,JSP出现,通过将输出渲染以模板的形式抽取到jsp后缀的模板文件中,jsp开始繁盛,同时要注意,Servlet处理web请求的时候,要在web.xml中,注册相应的请求url和具体的Serlet的映射关系。于是,jsp有开始混合着写代码
于是,我们引入了JavaBean,来封装相关业务逻辑,经过一次升级后,
这个模型就比较清楚了。但是和MVC还是有点差别
一个典型的mvc模式应该是这样的
控制器处理请求,模型封装逻辑和状态,视图给用户,
Structs以请求/响应框架为基础。
Spring MVC属于请求渠道的WEb框架。框架引入Front Controller做分发之后,就更加好管理了。

[来自为知笔记(Wiz)](http://www.wiz.cn/i/e0140d75 "来自为知笔记(Wiz)")
java  spring 

Spring揭秘-第13章 统一的数据访问异常层次体系

Spring揭秘-第13章 统一的数据访问异常层次体系 DAO可以分离数据哭的访问和存储,屏蔽各种数据访问方式的差异性,下面以访问顾客信息为例,使用DAO模式 首先定义一个数据访问对象接口,如下 public interrface ICustomerDao{ Customer findCustomerByPK(String customerId); void updateCustomerStatus(Customer customer);   之后,所有的数据访问都通过该接口进行,不论底层存储机制如何改变,DAO的实现因此会扩展,但客户端代码不需要调整 客户端要用的时候这样使用即可。 publicclassCustomerService { privateICustomerDao customerDao; publicvoid disableCustomerCampain(String customerId) { Customer customer=getCustomerDao().findCustomerByPK(customerId); customer.setCampainStatus(CampainStatus.DISABLE); getCustomerDao().updateCustomerStatus(customer); } publicICustomerDao getCustomerDao() { return customerDao; } publicvoid setCustomerDao(ICustomerDao customerDao) { this.customerDao=customerDao; }   我们只要针对不同的数据存储方式实现不同的Dao类即可。 我们开始实现具体的访问数据了。 publicCustomer findCustomerByPK(String customerId) { Connection con=null; try{ con=getDataSource().getConnection(); Customer cust=..; return cust; } catch(SQLException e){ //这里咋办,直接抛出还是直接处理? } finally{ releaseConnection(con); } } privatevoid releaseConnection(Connection con){ }   [Read More]
java  spring 

Spring揭秘-第四章BeanFactory笔记

之前说了,IoC容器就是一个IoC Service Provider,但是容器是个啥意思?![](/images/d4d1615a6c1a06895088631c37e3fca7692f0b8a.png) 可以看到IoC容器提供了更多的内容, Spring的IoC容器又分成两种, 1.BeanFactory 。基础类型IoC容器,提供完整的IoC服务支持。如果没有特殊指定,默认采用延 迟初始化策略(lazy-load)。只有当客户端对象需要访问容器中的某个受管对象的时候,才对 该受管对象进行初始化以及依赖注入操作。所以,相对来说,容器启动初期速度较快,所需 要的资源有限。对于资源有限,并且功能要求不是很严格的场景,BeanFactory是比较合适的 IoC容器选择。 2.ApplicationContext。ApplicationContext在BeanFactory的基础上构建,是相对比较高 级的容器实现,除了拥有BeanFactory的所有支持,ApplicationContext还提供了其他高级特性,比如事件发布、国际化信息支持等,这些会在后面详述。ApplicationContext所管理 的对象,在该类型容器启动之后,默认全部初始化并绑定完成。所以,相对于BeanFactory来 说,ApplicationContext要求更多的系统资源,同时,因为在启动时就完成所有初始化,容 器启动时间较之BeanFactory也会长一些。在那些系统资源充足,并且要求更多功能的场景中, ApplicationContext类型的容器是比较合适的选择。   通过 图4-2,我们可以对BeanFactory和ApplicationContext之间的关系有一个更清晰的认识。 ![](/images/f531ea3e11bb391453eb5f763283398c938634b2.png) Bean工长,就是生成Bean的嘛,每个业务对象被看成Javabean,我们与工厂打交道就简单得多,我们只要告诉他我要什么对象,至于怎么组装,那是他的事情。 工厂提供了一些对外的接口,比如获取Bean,渠道Bean的状态等等。 以xml为例 <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <bean id="djNewsProvider" class="..FXNewsProvider"> <constructor-arg index="0"> <ref bean="djNewsListener"/> </constructor-arg> <constructor-arg index="1"> <ref bean="djNewsPersister"/> </constructor-arg> </bean> <bean id="djNewsListener" class="..impl.DowJonesNewsListener"> </bean> <bean id=" [Read More]
java  spring 

Spring揭秘-第三章IoC Service Provider读书笔记

我们虽然已经通过IoC声明了相应的依赖,但是最终总要有个啥东西将这些依赖对象绑定在一起,这里而IoC Service Provider, 来啦,表示一种绑定的实现方式,可以使一段代码,也可以是一组相关的泪,甚至是框架或容器。 比如前一篇提到的 IFXNewsListener newsListener = new DowJonesNewsListener(); IFXNewsPersister newsPersister = new DowJonesNewsPersister(); FXNewsProvider newsProvider = new FXNewsProvider(newsListener,newsPersister); newsProvider.getAndPersistNews();   就是一个容器,只不过太简单了,不适用于更多的场景, IoC容器就是Spring提供依赖注入服务的Provider IoC Service Provider 是干嘛? 1.业务对象的构建管理,剥离客户端对象的构建的依赖逻辑,比如A引用B,那么A是B的客户端对象,容器需要理清这种关系。 2.业务对象之间的依赖绑定,通过1的实现, 识别各个对象的依赖关系,然后将这些对象依赖的对象注入绑定,用的时候就有了。 那你要问了,这怎么管理对象间的依赖关系呢 IoC Service Provider怎么就能完全领会代码的意图呢?他怎么记住这么多的依赖关系等等,他要这么做 1.元数据方式 2.通过描述性较强的xml来记录对应信息 3.通过编写代码的方式注册这些信息 3.直接编码方式, 明确了依赖关系 IoContainer container = …; container.register(FXNewsProvider.class,new FXNewsProvider()); container.register(IFXNewsListener.class,new DowJonesNewsListener()); … FXNewsProvider newsProvider = (FXNewsProvider)container.get(FXNewsProvider.class); newProvider.getAndPersistNews();   2.配置文件方式 最常见的还是xml方式, <bean id=“newsProvider” class=“. [Read More]
java  spring 

《Spring揭秘》读书笔记-第二章IoC的基本概念

理念就是让别人为你服务,中文名控制反转,也叫依赖注入DI public class FXNewsProvider { private IFXNewsListener newsListener; private IFXNewsPersister newPersistener; public void getAndPersistNews() { String[] newsIds = newsListener.getAvailableNewsIds(); if(ArrayUtils.isEmpty(newsIds)) { return; } for(String newsId : newsIds) { FXNewsBean newsBean = newsListener.getNewsByPK(newsId); newPersistener.persistNews(newsBean); newsListener.postProcessIfNecessary(newsId); } } }  假设这个类用来处理新闻, IFXNewsListener 用来获取新闻, IFXNewsPersister  用来把获取的新闻持久化 当我们需要获取不同的新闻源,比如道琼斯的新闻时,我们会写一个 DowJonesNewsListener 类和 DowJonesNewsPersister 类,然后实例化 public FXNewsProvider() { newsListener = new DowJonesNewsListener(); newPersistener = new DowJonesNewsPersister(); }   如果我们依赖于某个类或服务,最简单而有效的方式就是直接 在类的构造函数中新建相应的依赖类。 注意看, ,我们都是自己主动地去获 取依赖的对象! 可是回头想想,我们自己每次用到什么依赖对象都要主动地去获取,这是否真的必要?我们最终 所要做的,其实就是直接调用依赖对象所提供的某项服务而已 能不能我们用的时候自动送过来呢? [Read More]