MDA/MDD/TDD/DDD/DDDDDDD
posts - 536, comments - 111, trackbacks - 0, articles - 0
  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

我最近在开发一个使用Spring MVC的Web程序时遇到了一个奇怪的问题:自己写的Spring AOP切面对Controller中的方法切点不起作用。

后来我查了一下,Spring对自己的MVC(Controller)有特殊的拦截方法,需要在URLHandlerMapping中配置 Interceptor实现,它可以对请求进行拦截。因此直接用Spring AOP切面拦截Controller中的任何方法都是不起作用的。(具体的实现过程我不是很清楚,但是很多文章和贴子表达的意思是这样的)

后来,我做了一个实验。通过IOC将一个业务对象注入Controller中,然后将AOP配置成作用于该业务对象的方法上,结果还是不起作用。 我几乎试验了所有的Spring AOP和AspectJ的实现和配置方法,都不起作用。后来我用同样的类方法和同样的配置方式,写了一个脱离了Spring MVC的测试程序,一切正常,切面能够起到作用。

如果说Spring AOP对Spring MVC的Controller的方法不起作用,难道对注入到Controller的类方法也不起作用吗???我想得到一个准确的答案,谢谢!!! (bryantd)

我对Spring的MVC并不是很熟,不过刚才仔细看了一下源码,我觉得应该之所以Spring的AOP没有对Controller应用成功的原因 是:Spring MVC在启动的时候会根据处理器策略加载handler映射到一个map中,这个时候因为配置的原因它从容器中取到的对象是原生对象,而不是我们代理的对 象;所以不管我们的Controller做了什么操作都不会经过我们的代理,这样AOP就失去了作用;获取handler的方法应该是 DefaultListableBeanFactory的getBeanNamesForType方法;这是我自己在查看源码后总结出来的,如果有什么不 对的地方大家讨论下  (layer555)

转自http://www.javaeye.com/problems/20363

posted @ 2010-01-27 23:53 leekiang 阅读(3319) | 评论 (1)编辑 收藏

1,List转数组
    List list = new ArrayList();
        list.add("1");
        list.add("2");
        int size = list.size();
        String[] arr = (String[]) list.toArray(new String[size]);
     必须带参数new String[size],否则会报造型异常

2, 数组转List
    String[] arr = new String[] {"1", "2"};
    List list = Arrays.asList(arr);

3,  Arrays.binarySearch(Object[] arr,Object key)
    public static int binarySearch(int[] a,int key)使用二进制搜索算法来搜索指定的 int 型数组,以获得指定的值。必须在进行此调用之前对数组进行排序(通过上面的 sort 方法)。如果没有对数组进行排序,则结果是不明确的。如果数组包含多个带有指定值的元素,则无法保证找到的是哪一个。
    也就是说必须先执行Arrays.sort,再执行Arrays.binarySearch

4, commons-lang的ArrayUtils
   1)ArrayUtils.contains()方法可以判定数组是否存在指完元素.比Arrays.binarySearch好用(见上文)
     当然有两个比较实用的方法ArrayUtils.lastIndexOf()和ArrayUtils.indexOf()
   3)使用ArrayUtils.reverse(arr)方法可以反转一个数组
   4)使用ArrayUtils.toObject(arr)和ArrayUtils.toPrimitive(arr)两个方法,
     即可互相转换基本类型数组和对象数组
   5)ArrayUtils.toString()方法可以输入数组内容,此方法接受任意一个数组
     作为参数并输出其内容,输出时所有元素位于大括号,中间逗号隔开。
     如new String[] { "1","2","3","fd","3g"}会输出为字符串"{1,2,3,fd,3g}"
   6)// 判断数组是否为空(null和length=0的时候都为空)
        ArrayUtils.isEmpty(new int[0]);// true
        ArrayUtils.isEmpty(new Object[] { null });// false
   7)
// 合并两个数组
        ArrayUtils.addAll(new int[] { 135 }, new int[] { 24 });// {1,3,5,2,4}
   8)// 删除数组中某个对象(从正序开始搜索,删除第一个) 注意只删除一个
        ArrayUtils.removeElement(new int[] { 135 }, 3);// {1,5}




posted @ 2010-01-14 18:43 leekiang 阅读(796) | 评论 (0)编辑 收藏

JEP
http://www.singularsys.com/jep/
https://sourceforge.net/projects/jep/
http://rabbit8.bokee.com/3936531.html
http://suneca.com/article.asp?id=28

http://www.javaeye.com/topic/58422里办法多

关于jexl
1,jexl1.1计算分母为0的表达式时,竟然算出来的值为0,被某人说没有逻辑https://issues.apache.org/jira/browse/JEXL-45
2,jexl2解决了这个问题,但jexl2依赖jdk5
https://issues.apache.org/jira/browse/JEXL-58
handles ArithmeticException (divide by zero)
division by zero ignored only if JexlEngine.isSilent()
JexlEngine jexl = new JexlEngine();
jexl.setCache(
512);//有何用
jexl.setLenient(false);//什么意思
jexl.setSilent(false);

String calculate 
= "(G1 + G2)/2";
Expression e 
=jexl.createExpression(calculate);
// populate the context
JexlContext context = new MapContext();
context.set(
"G1""3");
context.set(
"G2""5");
Object res 
= e.evaluate(context);//silent为false时evaluate方法会抛异常,为true不抛异常但res为null

           
另外,利用oracle计算,如果分母为0会报ORA-01476: divisor is equal to zero

posted @ 2010-01-06 00:44 leekiang 阅读(1109) | 评论 (0)编辑 收藏

resultSetType 的可选值有: ResultSet.TYPE_FORWARD_ONLY ResultSet.TYPE_SCROLL_INSENSITIVEResultSet.TYPE_SCROLL_SENSITIVE
1)
TYPE_FORWARD_ONLY是默认值, 仅支持结果集forward ,不支持滚动,也不是 SENSITIVE的
2)
ResultSet.TYPE_SCROLL_INSENSITIVE,
支持结果集backforwardlastfirst 等操作,对其它session对数据库中数据做出的更改是不敏感的
原因:JDBC对数据库进行数据查询executeQuery时,数据库会创建查询结果的cache和cursor,如下面sql:
    select name,id from foo
    用jdbc执行上面的sql语句时,数据库会把foo表所有记录的name和id字段缓存到cache中,之后cache和真正的数据库数据文件没有任何联系了,foo表发生的改变在查询完成后不会自动同步到cache上去,因此TYPE_SCROLL_INSENSITIVE对选择数据做出的更改是不敏 感,不可见。
3)ResultSet.TYPE_SCROLL_SENSITIVE
支持结果集backforwardlastfirst 等操作,对其它session对数据库中数据做出的更改是敏感的,即其他session 修改了数据库中的数据,会反映到本结果集中
上面的select name,id from foo语句用TYPE_SCROLL_SENSITIVE的Statement来执行,会转化成以下的sql语句:
    select rowid from foo
    数据库这时候是把foo表所有记录的rowid缓存到cache中,用户代码在fetch记录时,再继续做以下查询:
    select name,id from foo where rowid=?
    因此这时候发生的查询是实时从真正的数据库数据文件中取,因此对期间发生的数据更改是可见的,敏感的。但是这种可见性仅限于update操作,而 insert和delete同样是不可见的。因为如果查询发生在insert之前,insert生成的rowid并不会反应在cache中的rowid结果集上。在一个记录的rowid已经缓存到cache中,这时候被删除了,但一般数据库的删除是标记删除,也就是说rowid对应那行记录并没有真正从数 据库文件中抹去,一般是可以再次取到记录的。

结论:是否SENSITIVE与fetchsize没有什么关系。是否SENSITIVE是告诉数据库如何作查询的缓存。fetchsize是客户端jdbc的设置。

另外oracle的
fetchsize默认为10
stmt.setFetchSize(0)时stmt.getFetchSize()=1
0
stmt.setFetchSize(1)时stmt.getFetchSize()=1

另外如果查询的sql复杂时,我发现就算设为
ResultSet.TYPE_SCROLL_SENSITIVE也不起作用,如
select t.*  from test t left join testp p on t.pid=p.id where p.title like '%国%',在运行中修改title的值,发现仍然可以取到。是否可以理解为SENSITIVE只对查询的主表起作用。

摘自:
http://www.javaeye.com/topic/128636
http://www.javaeye.com/topic/560109
http://www.javaeye.com/topic/418604

posted @ 2010-01-03 23:57 leekiang 阅读(967) | 评论 (0)编辑 收藏

1,
Hibernate动态模型(dynamic models) 一对多映射的实现
http://scnjl.blogbus.com/logs/35361929.html

2,
hibernate shards

3,
http://www.javaeye.com/topic/142404

4,
http://www.infoq.com/cn/articles/hibernate-custom-fields

posted @ 2010-01-03 17:31 leekiang 阅读(302) | 评论 (0)编辑 收藏

转自http://davidwang.javaeye.com/blog/83952(此文思路相当清晰,值得一看)

http://jakarta.apache.org/turbine/

Turbine是一个提供了完善权限控制的坚实框架(Fulcrum子项目是其基石)。Turbine的个人用户不多,但不少公司用户选择 Turbine作为框架,开发一些严肃的应用(我并没有说,用其它框架开发的应用就不严肃^_^)。Portal开源项目JetSpeed建立在 Turbine上。

Turbine用RunData来传递输入输出数据。如同Maverick的ControllerContext,RunData是整个 Turbine框架的数据交换中心。除了request, response等基本信息,RunData直接包括了User/ACL等权限控制相关的属性和方法,另外还包括Action Name和Target Template Name等定位属性。

Module是Turbine里面除了RunData之外的又一个核心类,是Turbine框架的基本构件,Action是 Module,Screen也是Module。Turbine提供了LoginUser和LogoutUser两个Action作为整个系统的出入口。而 其余流量的权限控制则由类似于Servlet Filter机制的Pipeline控制。

Turbine Pipeline的编程模型和Servlet Filter一模一样:Turbine Pipeline的Valve就相当于Servlet Filter,而ValveContext则相当于Filter Chain。还有更相近的例子,Tomcat源代码里面也有Valve和ValueContext两个类,不仅编程模型一样,而且名字也一样。



权限控制贯穿于Turbine框架的始终。要用好Turbine,首先要通晓子项目Fulcrum 的Security部分的权限实现模型。

Fulcrum Security的权限实体包括四个-- User, Group, Role, Permission。

实体之间包含{Role,Permission}和{ Group, User, Role}两组关系。

{Role,Permission}是多对多的关系,一个Role可以具有各种Permission;{ Group, User, Role}之间是多对多的关系,一个Group可包含多个User,并可以给User分配不同的Role。

权限模型的实现同样采用Peer模式,Entity -> EntityPeer, Entity -> ManagerPeer。

Entity和EntityManger代表抽象的模型概念,而EntityPeer和ManagerPeer代表具体的实现。

用户可以根据模型,提供不同的实现,比如,用内存结构中实现,用数据表结构实现,与Windows NT权限验证机制结合,与OSWorkflow的权限控制模型结合,等等。其中,用数据表结构实现,又可以选择用Torque实现,或者用 Hibernate实现。(Torque是Turbine的O/R Mapping子项目)
例如,Falcrum.property配置文件包含如下Security相关选项:

# -------------------------------------------------------------------

# S E C U R I T Y S E R V I C E

# -------------------------------------------------------------------

services.SecurityService.user.class=org.apache.fulcrum.security.impl.db.entity.TurbineUser

services.SecurityService.user.manager=org.apache.fulcrum.security.impl.db.DBUserManager

services.SecurityService.secure.passwords.algorithm=SHA

# -------------------------------------------------------------------

# D A T A B A S E S E R V I C E

# -------------------------------------------------------------------

services.DatabaseService.database.newapp.driver=org.gjt.mm.mysql.Driver

services.DatabaseService.database.newapp.url=jdbc:mysql://127.0.0.1/newapp

services.DatabaseService.database.newapp.username=turbine

services.DatabaseService.database.newapp.password=turbine



这说明,权限控制实现由数据库提供,需要根据权限模型创建如下数据表:

TURBINE_USER,TURBINE_ROLE,TURBINE_GROUP,

TURBINE_PERMISSION,TURBINE_ROLE_PERMISSION,

TURBINE_USER_GROUP_ROLE

Turbine表单处理中的中文:http://dev.csdn.net/article/70476.shtm

使用turbine的项目:
1)http://www.campware.org的Cream CRM
2)http://scarab.tigris.org/
3)Ohioedge 是采用B/S架构的开源的客户管理系统。基于Jetspeed/Turbine技术
  http://www.ohioedge.com/

参考资料:
http://turbine.apache.org/fulcrum/fulcrum-osworkflow-example
http://www.itpub.net/thread-306279-1-1.html
http://dev.csdn.net/article/19/19994.shtm

posted @ 2009-12-29 04:46 leekiang 阅读(706) | 评论 (0)编辑 收藏

1,关于statement,resultset和connection的问题

statement,resultset属于弱refrence,即如果statement关掉,resultset就会被自动释构,弱 refrence的做法不保险,所以JDBC3.0开始明确规定了如果connection被关,所有statement都应该关,不过这取决于使用的数 据库驱动。
应该DBMS 执行操作后,显式的关闭statement ,因为在connection关闭前,JDBC statement仍旧处于打开状态,当返回resultset后,关闭statement是必要的,尤其在遇到异常的时候。
如果不使用connection pool可以直接关闭connection,不考虑statement的关闭,使用连接池的时候,务必关闭statement,否则你的连接马上被用光,使用statement pooling除外。

http://www.w3china.org/blog/more.asp?name=hongrui&id=10283



2,Software caused connection abort: socket write error

最终找到了原因:sql写错了,写成了where name='?'

有人说原因:
oracle数据库连接与连接池之间冲突导至.
oracle database把空闲一段时间的连接关闭了,而应用服务器连接池却认为该边接还是可用的,再次访问时还是使用该连接,导致出现连接异常。
方法,当然是改数据库配置了.

spring对oracle的clob和StoredProcedure 的处理

经过几天的夜战,终于知道使用spring对oracle的存储过程操作,程序死掉的真正原因,一旦执行存储过程没有任何返回值,因为 “Statement.getUpdateCount() returns 1 instead of -1”,是oracle的驱动的bug,10.1.0.2的驱动就不行,听说10.1.0.3就没有问题,但是10.1.0.3的jdbc驱动不能下载。大家可以使用weblogic8.1SP3带的10.1.0.2或weblogic9beta的10.1.0.2,可以解决这个问题。不知道开发 oracle jdbc的程序员是什末人,没毕业的大学生,还是拖欠了工资的程序员,开发水平远不如开源数据库的jdbc驱动的人呢,再次建议oracle驱动最好是自己命名,把文件名加上版本信息,要不会死人的。

http://72.5.124.102/thread.jspa?messageID=1424984

http://group.gimoo.net/review/44109

http://azi.javaeye.com/blog/182146

http://hi.baidu.com/happyidea/blog/item/c84b313de75add0abba16779.html



3,Random Connection Closed Exceptions

These can occur when one request gets a db connection from the connection pool and closes it twice.

见http://tomcat.apache.org/tomcat-4.1-doc/jndi-datasource-examples-howto.html

posted @ 2009-12-25 02:31 leekiang 阅读(402) | 评论 (0)编辑 收藏

事务直接配到DAO上
<bean id="transactionManager"
        class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource" />
    </bean>

    <bean id="baseTxProxy"
        class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"
        lazy-init="true" abstract="true">
        <property name="transactionManager">
            <ref bean="transactionManager" />
        </property>
        <property name="transactionAttributes">
            <props>
                <prop key="update*">PROPAGATION_REQUIRED</prop>
            </props>
        </property>
    </bean>

    <bean id="studentDaoProxy" parent="baseTxProxy">
        <property name="target">
            <ref bean="studentDao" />
        </property>
    </bean>

    <bean id="studentDao" class="com.dao.StudentDaoImpl">
        <property name="dataSource" ref="dataSource" />
    </bean>
    
    StudentDao st = (StudentDao) context.getBean("studentDaoProxy");
    
    两个bean也可以合并为
    <bean id="studentDao" parent="baseTxProxy">
        <property name="target">
            <bean class="com.dao.StudentDaoImpl">
                <property name="dataSource" ref="dataSource" />
                <property name="kpiDao" ref="kpiDao" />
            </bean>
        </property>
    </bean>
    StudentDao st = (StudentDao) context.getBean("studentDao");
    上述这种方式必须使用接口,为什么。
    
    
    第二种同样必须用接口。配置起来比第一种麻烦
        <bean id="transactionManager"
        class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource" />
    </bean>

    <bean id="transactionInterceptor"
        class="org.springframework.transaction.interceptor.TransactionInterceptor">
        <property name="transactionManager" ref="transactionManager" />
        <property name="transactionAttributes">
            <props>
                <prop key="update*">PROPAGATION_REQUIRED</prop>
            </props>
        </property>
    </bean>
    <bean id="studentDaoProxy"
        class="org.springframework.aop.framework.ProxyFactoryBean">
        <property name="target" ref="studentDao" />
        <property name="interceptorNames">
            <list>
                <value>transactionInterceptor</value>
            </list>
        </property>
    </bean>
    
    <bean id="studentDao" class="com.dao.StudentDaoImpl">
        <property name="dataSource" ref="dataSource" />
    </bean>
    ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
    StudentDao st = (StudentDao) context.getBean("studentDaoProxy");
    
    如果使用的都是接口,那么就不需要用cglib-nodep-2.1_3.jar
    如果service调dao没有用到接口,那么必须用cglib-nodep-2.1_3.jar


事务策略: 了解事务陷阱 http://www.ibm.com/developerworks/cn/java/j-ts1.html 事务策略: 高并发策略 http://www.ibm.com/developerworks/cn/java/j-ts5/index.html 这是一个系列.

http://beet.sourceforge.net
Beet records user behavior and performance data for your Spring-based Java application.  It can thus help you to analyze usage patterns and research production performance issues.

posted @ 2009-12-24 22:04 leekiang 阅读(289) | 评论 (0)编辑 收藏

SQL标准允许基于一个带参数列表的表达式进行查询。一个典型的例子可能像这样:"select * from T_ACTOR where id in (1, 2, 3)"。 不过这种参数列表的方式并不能直接被JDBC标准所支持 - 因为并不存在这种声明一个列表参数作为占位符的方式。 你不得不为此写多个占位符来表示多个参数,或者当你知道占位符的数量时,你可以动态构建SQL字符串。 NamedParameterJdbcTemplate和SimpleJdbcTemplate中所提供的命名参数的特性,采用的是后面一种做法。 当你传入参数时,你需要传入一个java.util.List类型,支持基本类型。而这个list将会在SQL执行时替换占位符并传入参数。
在使用IN语句时,当你传入大批量的值时要小心,JDBC标准并不确保超过100个元素在IN语句中。 有不少数据库可以超出这个值的限制,但是不同的数据库会有不同的数量限制,比如Oracle的限制数量是1000个。
除了基本类型之外,你还可以创建一个java.util.List的对象数组,这可以让你支持在IN表达式中编写多重表达式,例如"select * from T_ACTOR where (id, last_name) in ((1, 'Johnson'), (2, 'Harrop'))". 当然,这样做的前提是数据库底层的语法支持。

http://www.javaeye.com/problems/6124
select count(*) num from lottery_term where term_issuenum in (?) and term_lotteryid = ?
改成getJdbcTemplate().queryForInt(sql,new Object[]{new String[]{"2008326","2008325","2008324"},103});
List list=new ArrayList();
list.add("****");
getJdbcTemplate().queryForInt(sql,new Object[]{list,103});

select count(*) from info_document where category_id in (:category_id_list);
Map<String,Object> parm = new HashMap<String,Object>();
parm.put("category_id_list", idList);


  public List getAllStu() {

       String sql="select s_id as sid,s_name as sname,s_sex as ssex,s_brith as sbrith from stu";

       List list=this.getJdbcTemplate().query(sql,new BeanPropertyRowMapper(Stu.class));

       return list;

    }


关于execute和update方法之间的区别,update方法返回的是受影响的记录数目的 一个计数,并且如果传入参数的话,使用的是java.sql.PreparedStatement,而execute方法总是使用 java.sql.Statement,不接受参数,而且他不返回受影响记录的计数,更适合于创建和丢弃表的语句,而update方法更适合于插入,更新 和删除操作,这也是我们在使用时需要注意的。



Connection conn=DataSourceUtils.getConnection(getJdbcTempldate().getDataSource());

conn=getJdbcTemplate().getNativeJdbcExtractor().getNativeConnection(conn);

OracleConnection oconn=(OracleConnection)conn;

通过DataSourceUtils获取当前线程绑定的数据连接,为了使用线程上下文相关的事务,这样写是正确的写法,如果直接从DataSource获取连接,得到的是和当前线程上下文无关的新的数据库连接实例。

http://www.javaeye.com/topic/49932?page=2

http://www.javaeye.com/problems/15846

http://www.javaeye.com/topic/87034

http://www.javaeye.com/topic/508799

http://ttitfly.javaeye.com/blog/151560


jdbcTemplate的方式里如果带上int[] argTypes显示指定每个占位符所对应的字段数据类型,可以保证类型安全,当参数值为null时,提供了更好的支持。

-----------------------

上面这句话如何理解?


后在http://javazoo.bokee.com/viewdiary.15850865.html找到原因了

今天在调试程序的时候,在后台业务逻辑类中利用JdbcTemplate进行数据同步操作时,发现当
执行jdbcTemplate.update(带?的SQL语句,new Object[]{tmp.getName( ),tmp.getNo( ),tmp.getSpeciality( ),tmp.getMounterofficer( ),tmp.getDesigner( ),tmp.getProductivity( ),tmp.getState( ))
这种操作时,如果后面参数中有值为null时,后台会报异常,细想下也是,如果是null,那就要执行jdbc的setNull(Spring底层还是用JDBC做的)方法了,但是setNull方法要知道具体的数据库字段的类型.如setNull(1,Types.VARCHAR).而在上面的方法没有体现.
终于体会到update方法中第三个参数new int[]的作用了.!
spring还是很伟大的.


如果字段名和属性名是严格对应的,那么就可以不用自己写RowMapper了,使用BeanPropertyRowMapper:

getJdbcTemplate().query(sql, new BeanPropertyRowMapper(User.class));  

类的属性字段名称要数据库中的字段名称一样或者数据库字段名为s_id类的名称为SId,
如果你没有遵守这个规范则可以在select语句后面给数据库字段名取别名


//绑定参数时,日期类型的写法,未经过验证

    public void updStu(Stu stu) {
String sql = "update stu set s_name=?,s_sex=?,s_brith=? where s_id=?";
Object[] obj = new Object[] { stu.getSname(), stu.getSsex(),new java.sql.Date(stu.getSbrith().getTime()), stu.getSid() };
      getJdbcTemplate().update(sql, obj, new int[] { Types.VARCHAR, Types.VARCHAR,Types.DATE, Types.INTEGER });
    }



ConnectionCallback的用法,使用完要手动关闭连接吗?

spring的AbstractRoutingDataSource,可以多态切换数据库?


事务抽象层http://blog.csdn.net/congqian1120/archive/2008/01/16/2046311.aspx




http://www.oracle.com/technology/global/cn/pub/articles/marx_spring.html

posted @ 2009-12-23 17:29 leekiang 阅读(796) | 评论 (0)编辑 收藏

jdk1.4下使用spring2.5时报上述这个错误,把xerces-2.6.2.jar放进去就好了。奇怪的是spring自带的jar包里没有xerces.jar
jfreechart里的gnujaxp.jar
cewolf里的crimson-1.1.3.jar
j2ee自带的xml-apis.jar
xercesImpl.jar
这些jar与Your JAXP provider有何关系

posted @ 2009-12-21 10:41 leekiang 阅读(2805) | 评论 (0)编辑 收藏

仅列出标题
共54页: First 上一页 18 19 20 21 22 23 24 25 26 下一页 Last