标签归档:Java

[原] 给paoding-rose添加动态编译实现ParamResolver的功能

通过javassist,添加了动态编译解析参数类的功能。记录一下主要目的和原理:
目的:动态解析传入参数组合成类。
最后达到的效果:

主要是为了能自动获取DataTables传入的参数:

过程:最初修改自wanghaomiao的blog(以下2-6条)。原文是用java的反射机制,我加入了7-9条,实现了动态编译解析器类。

原理:rose的ParamResolver接口提供了supports和resolve方法,在supports判断某个类是否支持解析,resolve里实现解析。我引入了一个WebBean注解,通过是否加注了WebBean来判断。如果加注了,就用ResolverHelper来实现动态编译。

动态编译核心代码:

附动态生成的解析类主要方法(支持嵌套、支持List、暂支持int long boolean)

[原] paoding-rose获取spring的ApplicationContext

刚开始用rose,因为有些服务是在线程里的,需要getBean。
试了好几个办法,都没法得到spring的ApplicationContext,
比如实现 ApplicationContextAware 结果没Aware。
有一个解决办法是所有线程里用到的依赖都在new的时候传递进去(也是rose作者推荐的方案),不过有时候比较麻烦,比如依赖很多很多,参数一大串;或者临时测一下,又要写一堆@Autowired
另外wangqiaowqo(rose作者之一)在blog里写了通过 new RoseAppContext(); 的方法,实际使用发现这种方式相当于把spring又重启了一遍,所有服务都会重新init,有可能导致严重问题。
有没有办法实现类似一个App.getBean()这种方法呢。
我试了一下,是可以得到最初spring启动环境的那个ApplicationContext的,方法如下(有点绕哦,因为@Autowired不能注解static成员,就把app本身从ApplicationContext中getBean):

其实核心是

[原] JarClassLoader在mac下无法加载native library的问题

JarClassLoader配合maven把所有依赖打包在一起,还是很方便的。不过在mac下发现无法加载native library。
通过跟踪JarClassLoader运行,发现主要原因是:System.mapLibraryName returns suffix ‘dylib’ and not ‘jnilib’ using JDK 7/8 on OS X

解决:
1)复制一份.dylib,or
2)判断下把.dylib的后缀改为.jnilib

[原] 利用java8的新特性lambda和stream处理list转为map

一个需求是这样:根据list,转为map。
假设List,map的key为User.getId(),value显而易见为User
java8以前得这样写:

java8利用lambda和stream这样即可,还是挺方便的:

看起来复杂,好处是支持泛型。如

[原] solr 1.3 multicore使用指南

尽管solr 1.3还是dev版,目前还没release,它比1.2多的很多特性(特别是multicore的支持)还是让我选择了1.3(1.2用了一段时间,多个索引要复制多份,非常麻烦)。
使用基本和solr 1.2差不多,几乎没什么难度就切换到1.3了。只是多了multicore的配置:
solr/home比如设为/opt/solrs
在/opt/solrs下新建multicore.xml

继续阅读

[原] spring的事件监听和java反射及IoC注入还是很强大的

这几天做了一个东西:在DAO上往数据库插入一个bean的时候,用java反射机制自动产生SQL语句,同时publishEvent触发bean更新事件,事件监听类根据配置文件处理bean并自动提交到Lucene(Solr)全文检索(主要是bean的属性跟Solr字段的对应)进行准实时的索引更新(当然bean有缓冲);反过来,检索结果有望自动转成bean丢给用户callback。
danny这个巨牛完成的基于spring的再次开发框架除了自动controller Action绑定、ResultSet自动转成bean、自动分页、自动View视图等等快捷开发功能外(Orz),现在支持自动全文检索了,而且整个过程对其他开发人员是无缝过渡的,建立全文索引不需要修改任何一处代码(其实概念上用AOP比事件监听更适合:“可热插拔”的全文检索切面,但是事件监听最大的优势是异步的,全文检索准实时索引更新这种需求用AOP同步包装一层实在是太不实际了):只要在配置文件里指定哪些数据表的bean哪些字段需要全文检索,OK。。。添加或者全记录更新的时候索引都会准实时更新——而且几乎近似热插拔。

[译]volatile关键字有什么用?

最近看LumaQQ的源码发现一个volatile(中文意思是“可变的、不稳定的”),找了篇英文介绍。抽空我翻译了一下,翻错了大家不要见笑。。。

volatile关键字有什么用?
  恐怕比较一下volatile和synchronized的不同是最容易解释清楚的。volatile是变量修饰符,而synchronized则作用于一段代码或方法;看如下三句get代码:

  geti1()得到存储在当前线程中i1的数值。多个线程有多个i1变量拷贝,而且这些i1之间可以互不相同。换句话说,另一个线程可能已经改变了它线程内的i1值,而这个值可以和当前线程中的i1值不相同。事实上,Java有个思想叫“主”内存区域,这里存放了变量目前的“准确值”。每个线程可以有它自己的变量拷贝,而这个变量拷贝值可以和“主”内存区域里存放的不同。因此实际上存在一种可能:“主”内存区域里的i1值是1,线程1里的i1值是2,线程2里的i1值是3——这在线程1和线程2都改变了它们各自的i1值,而且这个改变还没来得及传递给“主”内存区域或其他线程时就会发生。
  而geti2()得到的是“主”内存区域的i2数值。用volatile修饰后的变量不允许有不同于“主”内存区域的变量拷贝。换句话说,一个变量经volatile修饰后在所有线程中必须是同步的;任何线程中改变了它的值,所有其他线程立即获取到了相同的值。理所当然的,volatile修饰的变量存取时比一般变量消耗的资源要多一点,因为线程有它自己的变量拷贝更为高效。
  既然volatile关键字已经实现了线程间数据同步,又要synchronized干什么呢?呵呵,它们之间有两点不同。首先,synchronized获得并释放监视器——如果两个线程使用了同一个对象锁,监视器能强制保证代码块同时只被一个线程所执行——这是众所周知的事实。但是,synchronized也同步内存:事实上,synchronized在“主”内存区域同步整个线程的内存。因此,执行geti3()方法做了如下几步:
1. 线程请求获得监视this对象的对象锁(假设未被锁,否则线程等待直到锁释放)
2. 线程内存的数据被消除,从“主”内存区域中读入(Java虚拟机能优化此步。。。[后面的不知道怎么表达,汗])
3. 代码块被执行
4. 对于变量的任何改变现在可以安全地写到“主”内存区域中(不过geti3()方法不会改变变量值)
5. 线程释放监视this对象的对象锁
  因此volatile只是在线程内存和“主”内存间同步某个变量的值,而synchronized通过锁定和解锁某个监视器同步所有变量的值。显然synchronized要比volatile消耗更多资源。

附英文原文:
What does volatile do?

This is probably best explained by comparing the effects that volatile and synchronized have on a method. volatile is a field modifier, while synchronized modifies code blocks and methods. So we can specify three variations of a simple accessor using those two keywords:

geti1() accesses the value currently stored in i1 in the current thread. Threads can have local copies of variables, and the data does not have to be the same as the data held in other threads. In particular, another thread may have updated i1 in it’s thread, but the value in the current thread could be different from that updated value. In fact Java has the idea of a “main” memory, and this is the memory that holds the current “correct” value for variables. Threads can have their own copy of data for variables, and the thread copy can be different from the “main” memory. So in fact, it is possible for the “main” memory to have a value of 1 for i1, for thread1 to have a value of 2 for i1 and for thread2 to have a value of 3 for i1 if thread1 and thread2 have both updated i1 but those updated value has not yet been propagated to “main” memory or other threads.

On the other hand, geti2() effectively accesses the value of i2 from “main” memory. A volatile variable is not allowed to have a local copy of a variable that is different from the value currently held in “main” memory. Effectively, a variable declared volatile must have it’s data synchronized across all threads, so that whenever you access or update the variable in any thread, all other threads immediately see the same value. Of course, it is likely that volatile variables have a higher access and update overhead than “plain” variables, since the reason threads can have their own copy of data is for better efficiency.

Well if volatile already synchronizes data across threads, what is synchronized for? Well there are two differences. Firstly synchronized obtains and releases locks on monitors which can force only one thread at a time to execute a code block, if both threads use the same monitor (effectively the same object lock). That’s the fairly well known aspect to synchronized. But synchronized also synchronizes memory. In fact synchronized synchronizes the whole of thread memory with “main” memory. So executing geti3() does the following:

1. The thread acquires the lock on the monitor for object this (assuming the monitor is unlocked, otherwise the thread waits until the monitor is unlocked).
2. The thread memory flushes all its variables, i.e. it has all of its variables effectively read from “main” memory (JVMs can use dirty sets to optimize this so that only “dirty” variables are flushed, but conceptually this is the same. See section 17.9 of the Java language specification).
3. The code block is executed (in this case setting the return value to the current value of i3, which may have just been reset from “main” memory).
4. (Any changes to variables would normally now be written out to “main” memory, but for geti3() we have no changes.)
5. The thread releases the lock on the monitor for object this.

So where volatile only synchronizes the value of one variable between thread memory and “main” memory, synchronized synchronizes the value of all variables between thread memory and “main” memory, and locks and releases a monitor to boot. Clearly synchronized is likely to have more overhead than volatile.

[原]Java正则表达式获取匹配结果

有关正则表达式语法,请参考:文档 Document

[原]利用HttpServletResponseWrapper获取jsp输出内容

有时候我们需要得到某个jsp的输出内容。比如说在servlet里处理了Module Controller后,需要不同的jsp页面来展示view;又或者得到不同的模板内容(jsp本身可以作为模板语言)并将其缓冲到内存里。
利用 javax.servlet.http.HttpServletResponseWrapper 可以很好地实现我们所需要的功能。下面是使用方法:

可以看到,使用起来还是挺方便的。getJspOutput(“/view/header.jsp”, request, response) 就完成了对”/view/header.jsp”的输出内容获取,之后可以进行其他操作。
附WrapperResponse类代码: