??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲熟妇无码AV,亚洲伊人久久综合影院,国产亚洲精品AA片在线观看不加载 http://m.tkk7.com/junky/category/11393.htmlzh-cnThu, 23 Aug 2007 11:50:47 GMTThu, 23 Aug 2007 11:50:47 GMT60一步一步开发Spring Framework MVC应用E序(?http://m.tkk7.com/junky/archive/2007/08/22/138543.htmljunkyjunkyWed, 22 Aug 2007 02:50:00 GMThttp://m.tkk7.com/junky/archive/2007/08/22/138543.htmlhttp://m.tkk7.com/junky/comments/138543.htmlhttp://m.tkk7.com/junky/archive/2007/08/22/138543.html#Feedback0http://m.tkk7.com/junky/comments/commentRss/138543.htmlhttp://m.tkk7.com/junky/services/trackbacks/138543.html阅读全文

junky 2007-08-22 10:50 发表评论
]]>
Spring interceptorhttp://m.tkk7.com/junky/archive/2007/06/28/126716.htmljunkyjunkyThu, 28 Jun 2007 01:36:00 GMThttp://m.tkk7.com/junky/archive/2007/06/28/126716.htmlhttp://m.tkk7.com/junky/comments/126716.htmlhttp://m.tkk7.com/junky/archive/2007/06/28/126716.html#Feedback0http://m.tkk7.com/junky/comments/commentRss/126716.htmlhttp://m.tkk7.com/junky/services/trackbacks/126716.html1 Spring的通知cd

现在让我们看?span>Spring AOP是如何处理通知的?/span>

1.1. 通知的生命周?/span>

Spring的通知可以跨越多个被通知对象׃nQ或者每个被通知对象有自q通知。这分别对应 per-class?em>per-instance 通知?/span>

Per-class通知使用最为广泛。它适合于通用的通知Q如事务adisor。它们不依赖被代?的对象的状态,也不d新的状态。它们仅仅作用于Ҏ(gu)和方法的参数?/span>

Per-instance通知适合于导入,来支持؜入(mixinQ。在q种情况下,通知d状态到 被代理的对象?/span>

可以在同一?span>AOP代理中؜合用共享和per-instance通知?/span>

1.2. Spring中通知cd

Spring提供几种现成的通知cdq可扩展提供L的通知cd。让我们看看基本概念和标准的通知cd?/span>

1.2.1. Interception around advice

Spring中最基本的通知cd?em>interception around advice .

Spring使用Ҏ(gu)拦截器的around通知是和AOP联盟接口兼容的。实?span>around通知?c需要实现接?span>MethodInterceptorQ?/span>

public interface MethodInterceptor extends Interceptor {

 

    Object invoke(MethodInvocation invocation) throws Throwable;

}

invoke()Ҏ(gu)?em>MethodInvocation 参数暴露被调用的方法、目标连接点?span>AOP代理和传递给被调用方法的参数?invoke()Ҏ(gu)应该q回调用的结果:(x)q接点的q回倹{?/span>

一个简单的MethodInterceptor实现看v来如?span>:

public class DebugInterceptor implements MethodInterceptor {

 

    public Object invoke(MethodInvocation invocation) throws Throwable {

        System.out.println("Before: invocation=[" + invocation + "]");

        Object rval = invocation.proceed();

        System.out.println("Invocation returned");

        return rval;

    }

}

注意MethodInvocation?em>proceed()Ҏ(gu)的调用。这个调用会(x)应用到目标连接点的拦截器链中的每一个拦截器。大部分拦截器会(x)调用q个Ҏ(gu)Qƈq回它的q回倹{但是, 一?span>MethodInterceptorQ和Maround通知一P可以q回不同的值或者抛Z个异常,?不调?span>proceedҎ(gu)。但是,没有好的原因你要q么做?/span>

MethodInterceptor提供?jin)和其?span>AOP联盟的兼容实现的交互能力。这一节下?要讨论的其他的通知cd实现?span>AOP公共的概念,但是?span>Spring特定的方式。虽然用特?通知cd有很多优点,但如果你可能需要在其他?span>AOP框架中用,请坚持?span>MethodInterceptor around通知cd。注意目前切入点不能和其它框架交互操作,q且AOP联盟目前也没有定义切?Ҏ(gu)口?/span>

1.2.2. Before通知

Before通知是一U简单的通知cd?q个通知不需要一?span>MethodInvocation对象Q因为它只在q入一个方法前被调用?/span>

Before通知的主要优Ҏ(gu)它不需要调?span>proceed() Ҏ(gu)Q?因此没有无意中忘掉l执行拦截器铄可能性?/span>

MethodBeforeAdvice接口如下所C?span> (Spring?span>API设计允许成员变量?span>before通知Q虽然一般的对象都可以应用成员变量拦截,?span>Spring 有可能永q不?x)实现它Q?/span>

public interface MethodBeforeAdvice extends BeforeAdvice {

 

    void before(Method m, Object[] args, Object target) throws Throwable;

}

注意q回cd?span>void?span> Before通知可以在连接点执行之前 插入自定义的行ؓ(f)Q但是不能改变返回倹{如果一?span>before通知抛出一个异常,q将中断拦截?铄q一步执行。这个异常将沿着拦截器链后退着向上传播。如果这个异常是unchecked的,或?出现在被调用的方法的{֐中,它将?x)被直接传递给客户代码Q否则,它将?span>AOP代理包装C?span>unchecked 的异帔R?/span>

下面?span>Spring中一?span>before通知的例子,q个例子计数所有正常返回的Ҏ(gu)Q?/span>

public class CountingBeforeAdvice implements MethodBeforeAdvice {

    private int count;

    public void before(Method m, Object[] args, Object target) throws Throwable {

        ++count;

    }

 

    public int getCount() {

        return count;

    }

}

Before通知可以被用于Q何类型的切入炏V?/span>

1.2.3. Throws通知

如果q接Ҏ(gu)出异常,Throws通知 在连接点q回后被调用?span>Spring提供强类型的throws通知。注意这意味着 org.springframework.aop.ThrowsAdvice接口不包含Q何方法:(x) 它是一个标记接口,标识l定的对象实C(jin)一个或多个强类型的throws通知Ҏ(gu)。这些方法Ş?如下Q?/span>

afterThrowing([Method], [args], [target], subclassOfThrowable)

只有最后一个参数是必需的。这样从一个参数到四个参数Q依赖于通知是否Ҏ(gu)法和Ҏ(gu) 的参数感兴趣。下面是throws通知的例子?/span>

如果抛出RemoteException异常Q包括子c)(j), q个通知?x)被调?/span>

public class RemoteThrowsAdvice implements ThrowsAdvice {

 

    public void afterThrowing(RemoteException ex) throws Throwable {

        // Do something with remote exception

    }

}

如果抛出ServletException异常Q?下面的通知?x)被调用。和上面的通知不一P它声明了(jin)四个参数Q所以它可以讉K被调用的Ҏ(gu)Q方法的参数和目标对?span>:

public static class ServletThrowsAdviceWithArguments implements ThrowsAdvice {

 

    public void afterThrowing(Method m, Object[] args, Object target, ServletException ex) {

        // Do something will all arguments

    }

}

最后一个例子演CZ(jin)如何在一个类中用两个方法来同时处理 RemoteException?span>ServletException 异常。Q意个数的throwsҎ(gu)可以被组合在一个类中?/span>

public static class CombinedThrowsAdvice implements ThrowsAdvice {

 

    public void afterThrowing(RemoteException ex) throws Throwable {

        // Do something with remote exception

    }

 

    public void afterThrowing(Method m, Object[] args, Object target, ServletException ex) {

        // Do something will all arguments

    }

}

Throws通知可被用于Mcd的切入点?/span>

1.2.4. After Returning通知

Spring中的after returning通知必须实现 org.springframework.aop.AfterReturningAdvice 接口Q如下所C:(x)

public interface AfterReturningAdvice extends Advice {

 

    void afterReturning(Object returnValue, Method m, Object[] args, Object target)

            throws Throwable;

}

After returning通知可以讉Kq回|不能改变Q、被调用的方法、方法的参数和目标对象?/span>

下面?span>after returning通知l计所有成功的没有抛出异常的方法调用:(x)

public class CountingAfterReturningAdvice implements AfterReturningAdvice {

    private int count;

 

    public void afterReturning(Object returnValue, Method m, Object[] args, Object target) throws Throwable {

        ++count;

    }

 

    public int getCount() {

        return count;

    }

}

q方法不改变执行路径。如果它抛出一个异常,q个异常而不是返回值将被沿着拦截器链向上抛出?/span>

After returning通知可被用于Mcd的切入点?/span>

1.2.5. Introduction通知

Spring?span>introduction通知看作一U特D类型的拦截通知?/span>

Introduction需要实?span>IntroductionAdvisor, ?span>IntroductionInterceptor接口Q?/span>

public interface IntroductionInterceptor extends MethodInterceptor {

 

    boolean implementsInterface(Class intf);

}

l承?span>AOP联盟MethodInterceptor接口?span> invoke()Ҏ(gu)必须实现导入Q也是_(d)如果被调用的Ҏ(gu)是在 导入的接口中Q导入拦截器负责处理q个Ҏ(gu)调用Q它不能调用proceed() Ҏ(gu)?/span>

Introduction通知不能被用于Q何切入点Q因为它只能作用于类层次上,而不是方法。你可以只用InterceptionIntroductionAdvisor来实现导入通知Q它有下面的Ҏ(gu)Q?/span>

public interface InterceptionIntroductionAdvisor extends InterceptionAdvisor {

 

    ClassFilter getClassFilter();

 

    IntroductionInterceptor getIntroductionInterceptor();

 

    Class[] getInterfaces();

}

q里没有MethodMatcherQ因此也没有和导入通知兌?切入炏V只有类qo(h)是合乎逻辑的?/span>

getInterfaces()Ҏ(gu)q回advisor导入的接口?/span>

让我们看看一个来?span>Spring试套g中的单例子。我们假设想要导入下面的接口C?或者多个对象中:

public interface Lockable {

    void lock();

    void unlock();

    boolean locked();

}

q个例子演示?jin)一?span>mixin。我们想要能?被通知对象cd转换?span>LockableQ不它们的cdQƈ且调?span>lock?span>unlockҎ(gu)。如果我们调?span> lock()Ҏ(gu)Q我们希望所?span>setterҎ(gu)抛出LockedException异常。这h们能d一个方面的对象不可变Q而它们不需要知道这一点:(x)q是一个很好的AOP?子?/span>

首先Q我们需要一个做大量转化?span>IntroductionInterceptor?在这里,我们l承 org.springframework.aop.support.DelegatingIntroductionInterceptor 实用cR我们可以直接实?span>IntroductionInterceptor接口Q但是大多数情况?span> DelegatingIntroductionInterceptor是最合适的?/span>

DelegatingIntroductionInterceptor的设计是导?委托到真正实现导入接口的接口Q隐藏完成这些工作的拦截器。委托可以用构造方法参?讄CQ何对象中Q默认的委托是自己Q当无参数的构造方法被使用Ӟ(j)。这样在下面的例子里Q委托是DelegatingIntroductionInterceptor的子c?span> LockMixin。给定一个委托(默认是自w)(j)?span> DelegatingIntroductionInterceptor实例L被这个委托(而不 ?span>IntroductionInterceptorQ实现的所有接口,q支持它们中M一个导入。子cd LockMixin也可能调?span>suppressInterflace(Class intf) Ҏ(gu)隐藏不应暴露的接口。然而,不管IntroductionInterceptor 准备支持多少接口Q?span>IntroductionAdvisor控制哪个接口将被实?暴露。一个导入的接口隐藏目标的同一个接口的所有实现?/span>

q样Q?span>LockMixinl承DelegatingIntroductionInterceptor q自己实?span>Lockable。父c自动选择支持导入?span>LockableQ所以我们不需要指定它。用q种Ҏ(gu)我们可以导入L数量的接口?/span>

注意locked实例变量的用。这有效地添加额外的状态到目标 对象?/span>

public class LockMixin extends DelegatingIntroductionInterceptor

    implements Lockable {

 

    private boolean locked;

 

    public void lock() {

        this.locked = true;

    }

 

    public void unlock() {

        this.locked = false;

    }

 

    public boolean locked() {

        return this.locked;

    }

 

    public Object invoke(MethodInvocation invocation) throws Throwable {

        if (locked() && invocation.getMethod().getName().indexOf("set") == 0)

            throw new LockedException();

        return super.invoke(invocation);

    }

 

}

通常不要需要改?span>invoke()Ҏ(gu)Q实?span> DelegatingIntroductionInterceptorp够了(jin)Q如果是导入的方法, DelegatingIntroductionInterceptor实现?x)调用委托方法?否则l箋(hu)沿着q接点处理。在现在的情况下Q我们需要添加一个检查:(x)在上锁状态下不能调用setterҎ(gu)?/span>

所需的导?span>advisor是很单的。只有保存(sh)个独立的 LockMixin实例Qƈ指定导入的接口,在这里就?span> Lockable。一个稍微复杂一点例子可能需要一个导入拦截器Q可?定义?span>prototypeQ的引用Q在q种情况下,LockMixin没有相关配置Q所以我们简单地 使用new来创建它?/span>

public class LockMixinAdvisor extends DefaultIntroductionAdvisor {

 

    public LockMixinAdvisor() {

        super(new LockMixin(), Lockable.class);

    }

}

我们可以非常单地使用q个advisorQ它不需要Q何配|。(但是Q有一??/em>必要的:(x)是不可能在没有IntroductionAdvisor 的情况下使用IntroductionInterceptor。)(j) 和导入一P通常 advisor必须是针Ҏ(gu)个实例的Qƈ且是有状态的。我们会(x)有不同的?span>LockMixinAdvisor 每个被通知对象Q会(x)有不同的LockMixin?span> advisorl成?jin)被通知对象的状态的一部分?/span>

和其?span>advisor一P我们可以使用 Advised.addAdvisor() Ҏ(gu)以编E地方式使用q种advisorQ或者在XML中配|(推荐q种方式Q?下面讨论所有代理创建,包括自动代理创徏?span>”Q选择代理创徏以正地处理导入和有状态的混入?/span>

 

 

参考资料:(x)

1Q?/font> http://www.javaresearch.org/article/showarticle.jsp?column=23&thread=41315

2Q?/font> http://tech.ccidnet.com/art/1112/20051114/371959_5.html

3Q?/font> http://www.7dspace.com/doc/21/0603/20063305365394884.htm

4Q?/font> http://barton131420.cnblogs.com/articles/280664.html

5Q?/font> http://www.opentown.info/bbs/viewtopic.php?t=7

 



junky 2007-06-28 09:36 发表评论
]]>
Spring ~程入门十大问题解答http://m.tkk7.com/junky/archive/2007/06/07/122540.htmljunkyjunkyThu, 07 Jun 2007 03:10:00 GMThttp://m.tkk7.com/junky/archive/2007/06/07/122540.htmlhttp://m.tkk7.com/junky/comments/122540.htmlhttp://m.tkk7.com/junky/archive/2007/06/07/122540.html#Feedback0http://m.tkk7.com/junky/comments/commentRss/122540.htmlhttp://m.tkk7.com/junky/services/trackbacks/122540.html
  你可以通过下列途径学习(fn)springQ?br>
  (1) spring下蝲包中doc目录下的MVC-step-by-step和sample目录下的例子都是比较好的spring开发的例子?

  (2) AppFuse集成?jin)目前最行的几个开源轻量框架或者工?Ant,XDoclet,Spring,Hibernate(iBATIS),JUnit,Cactus,StrutsTestCase,Canoo's WebTest,Struts Menu,Display Tag Library,OSCache,JSTL,Struts ?br>
  你可以通过AppFuse源代码来学习(fn)spring?br>
AppFuse|站Qhttp://raibledesigns.com/wiki/Wiki.jsp?page=AppFuse

  (3)Spring 开发指?夏昕)Qhttp://www.xiaxin.net/Spring_Dev_Guide.rarQ?br>
  一本spring的入门书c?里面介绍?jin)反转控制和依赖注射的概念,以?qing)spring的bean理Qspring的MVCQspring和hibernteQiBatis的结合?br>
  (4) spring学习(fn)的中文论?br>
  SpringFramework中文论坛(http://spring.jactiongroup.net)

  Java视线论坛(http://forum.javaeye.com)的spring栏目

  2、利用Spring框架~程Qconsole打印出log4j:WARN Please initialize the log4j system properlyQ?br>
  说明你的log4j.properties没有配置。请把log4j.properties攑ֈ工程的classpath中,eclipse的classpath为bin目录Q由于编译后src目录下的文g?x)拷贝到bin目录下,所以你可以把log4j.properties攑ֈsrc目录下?br>
  q里l出一个log4j.properties的例子:(x)

log4j.rootLogger=DEBUG,stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %5p (%F:%L) - %m%n

  3、出?java.lang.NoClassDefFoundError?

  一般情况下是由于你没有把必要的jar包放到l(f)ib中?br>
  比如你要采用spring和hibernateQ带事务支持的话Q,你除?jin)spring.jar外还需要hibernat.jar、aopalliance.jar、cglig.jar、jakarta-commons下的几个jar包?br>
http://www.springframework.org/download.html下蝲spring开发包Q提供两Uzip?br>spring-framework-1.1.3-with-dependencies.zip和spring-framework-1.1.3.zipQ我你下载spring-framework-1.1.3-with-dependencies.zip。这个zip解压~后比后者多一个lib目录Q其中有hibernate、j2ee、dom4j、aopalliance、jakarta-commons{常用包?br>
  4、java.io.FileNotFoundException: Could not open class path resource [....hbm.xml],提示找不到xml文gQ?br>
  原因一般有两个Q?br>
  (1)该xml文g没有在classpath中?

  (2)applicationContext-hibernate.xml中的xml名字没有带包名。比如:(x)

Qbean id="sessionFactory" class="org.springframework.orm.hibernate.LocalSessionFactoryBean"Q?br>Qproperty name="dataSource"Q<ref bean="dataSource"/Q</propertyQ?br>Qproperty name="mappingResources"Q?br> QlistQ?br>  QvalueQUser.hbm.xmlQ?valueQ?br>  错,改ؓ(f)Q?
  QvalueQcom/yz/spring/domain/User.hbm.xmlQ?valueQ?br> Q?listQ?br>Q?propertyQ?br>Qproperty name="hibernateProperties"Q?br>QpropsQ?
 Qprop key="hibernate.dialect"Q?net.sf.hibernate.dialect.MySQLDialect Q?propQ?
 Qprop key="hibernate.show_sql"QtrueQ?propQ?
Q?propsQ?
Q?propertyQ?br>Q?beanQ?/td>

  5、org.springframework.beans.NotWritablePropertyException: Invalid property 'postDao' of bean classQ?br>
  出现异常的原因是在application-xxx.xml中property name的错误?br>
  Qproperty name="...."Q?中name的名字是与bean的setҎ(gu)相关的,而且要注意大写?br>
  比如

public class PostManageImpl extends BaseManage implements PostManage {
 private PostDAO dao = null;
 public void setPostDAO(PostDAO postDAO){
  this.dao = postDAO;
 }
}

  那么xml的定义应该是Q?br>
Qbean id="postManage" parent="txProxyTemplate"Q?br>Qproperty name="target"Q?br> Qbean class="com.yz.spring.service.implement.PostManageImpl"Q?br>  Qproperty name="postDAO"Q<ref bean="postDAO"/Q</propertyQ??br>  Qproperty name="dao"Q<ref bean="postDAO"/Q</propertyQ??br> Q?beanQ?br>Q?propertyQ?br>Q?beanQ?/td>

  6、Spring中如何实C务管理?

  首先Q如果用mysqlQ确定mysql为InnoDBcd?br>
  事务理的控制应该放到商业逻辑层。你可以写个处理商业逻辑的JavaBeanQ在该JavaBean中调用DAOQ然后把该Bean的方法纳入spring的事务管理?br>
  比如Qxml文g定义如下Q?br>
Qbean id="txProxyTemplate" abstract="true"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"Q?br>Qproperty name="transactionManager"Q<ref bean="transactionManager"/Q</propertyQ?br>Qproperty name="transactionAttributes"Q?br>QpropsQ?br>Qprop key="save*"QPROPAGATION_REQUIREDQ?propQ?br>Qprop key="remove*"QPROPAGATION_REQUIREDQ?propQ?br>Qprop key="*"QPROPAGATION_REQUIREDQ?propQ?br>Q?propsQ?br>Q?propertyQ?br>Q?beanQ?br>
Qbean id="userManage" parent="txProxyTemplate"Q?br> Qproperty name="target"Q?br>  Qbean class="com.yz.spring.service.implement.UserManageImpl"Q?br>   Qproperty name="userDAO"Q<ref bean="userDAO"/Q</propertyQ?br>  Q?beanQ?br> Q?propertyQ?br>Q?beanQ?/td>

  com.yz.spring.service.implement.UserManageImpl是我们的实现商业逻辑的JavaBean。我们通过parent元素声明其事务支持?br>
  7、如何管理Spring框架下更多的JavaBeanQ?br>
  JavaBean多Qspring配置文gp大,q样不易l护。ؓ(f)?jin)配置清晰Q我们可以将JavaBean分类理Q放在不同的配置文g中?应用启动时将所有的xml同时加蝲?br>
  比如Q?br>
  DAO层的JavaBean攑ֈapplicationContext-hibernate.xml中,商业逻辑层的JavaBean攑ֈapplicationContext-service.xml中。然后启动类中调用以下代码蝲入所有的ApplicationContext?br>
String[] paths = {"com/yz/spring/dao/hibernate/applicationContext-hibernate.xml",
"com/yz/spring/service/applicationContext-service.xml"};
ctx = new ClassPathXmlApplicationContext(paths);

  8、web应用中如何加载ApplicationContextQ?br>
  可以通过定义web.xmlQ由web容器自动加蝲?br>
QservletQ?br>Qservlet-nameQcontextQ?servlet-nameQ?br>Qservlet-classQorg.springframework.web.context.ContextLoaderServletQ?servlet-classQ?br>Qload-on-startupQ?Q?load-on-startupQ?br>Q?servletQ?br>
Qcontext-paramQ?br>Qparam-nameQcontextConfigLocationQ?param-nameQ?br>Qparam-valueQ?WEB-INF/applicationContext-hibernate.xmlQ?param-valueQ?br>Qparam-valueQ?WEB-INF/applicationContext-service.xmlQ?param-valueQ?br>Q?context-paramQ?/td>

  9、在spring中如何配|的log4j?

  在web.xml中加入以下代码即可?br>
Qcontext-paramQ?br>Qparam-nameQlog4jConfigLocationQ?param-nameQ?br>Qparam-valueQ?WEB-INF/log4j.propertiesQ?param-valueQ?br>Q?context-paramQ?/td>

  10、Spring框架入门的编E问题解决了(jin)Q我该如何更深地领会(x)Spring框架呢?

  q两本书你该ȝ看。这两本书是由Spring的作者Rod Johnson~写的?br>
Expert One on one J2EE Design and Development
Expert One on one J2EE Development Without EJB

  你也该看看martinfowler的Inversion of Control Containers and the Dependency Injection pattern?br>
http://www.martinfowler.com/articles/injection.html
 
  再好好研M下spring的文档?br>
http://www.jactiongroup.net/reference/html/index.htmlQ中文版Q未全部译Q?/td>

  q有是多实践吧?

junky 2007-06-07 11:10 发表评论
]]>
Open Session In View探讨(?http://m.tkk7.com/junky/archive/2007/03/06/102142.htmljunkyjunkyTue, 06 Mar 2007 06:01:00 GMThttp://m.tkk7.com/junky/archive/2007/03/06/102142.htmlhttp://m.tkk7.com/junky/comments/102142.htmlhttp://m.tkk7.com/junky/archive/2007/03/06/102142.html#Feedback0http://m.tkk7.com/junky/comments/commentRss/102142.htmlhttp://m.tkk7.com/junky/services/trackbacks/102142.html Spring Open Session In View service(or Dao) session lazy loading true company.getEmployees() Hibernate session already closed Exception;  (tng) (tng) (tng) Open Session In View lazy loading .

 (tng) (tng) (tng) 它有两种配置方式OpenSessionInViewInterceptor OpenSessionInViewFilter(具体参看SpringSide) web.xml application.xml  (tng) (tng) (tng) Open Session In View request session thread hibernate session open session request View PO lazy loading ${ company.employees } View Filter doFilter Interceptor postHandle session


										
OpenSessionInViewInterceptor配置
  1. <beans>
  2. <bean name="openSessionInViewInterceptor"
  3. class="org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor">
  4. <property name="sessionFactory">
  5. <ref bean="sessionFactory"/>
  6. </property>
  7. </bean>
  8. <bean id="urlMapping"
  9. class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
  10. <property name="interceptors">
  11. <list>
  12. <ref bean="openSessionInViewInterceptor"/>
  13. </list>
  14. </property>
  15. <property name="mappings">
  16. ...
  17. </property>
  18. </bean>
  19. ...
  20. </beans>
										
OpenSessionInViewFilter配置
  1. <web-app>
  2. ...
  3. <filter>
  4. <filter-name>hibernateFilter</filter-name>
  5. <filter-class>
  6. org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
  7. </filter-class>
  8. <!-- singleSession默认为true,若设为false则等于没?span class="me1">OpenSessionInView -->
  9. <init-param>
  10. <param-name>singleSession</param-name>
  11. <param-value>true</param-value>
  12. </init-param>
  13. </filter>
  14. ...
  15. <filter-mapping>
  16. <filter-name>hibernateFilter</filter-name>
  17. <url-pattern>*.do</url-pattern>
  18. </filter-mapping>
  19. ...
  20. </web-app>

很多人在使用OpenSessionInViewq程中提?qing)一个错误:(x)

										
  1. org.springframework.dao.InvalidDataAccessApiUsageException: Write operations
  2. are not allowed in read-only mode (FlushMode.NEVER) - turn your Session into
  3. FlushMode.AUTO or remove 'readOnly' marker from transaction definition

看看OpenSessionInViewFilter里的几个Ҏ(gu)

										
  1. protected void doFilterInternal(HttpServletRequest request,
    HttpServletResponse response,FilterChain filterChain)
    throws ServletException, IOException{
     SessionFactory sessionFactory = lookupSessionFactory();
     logger.debug("Opening Hibernate Session in OpenSessionInViewFilter");
     Session session = getSession(sessionFactory);
     TransactionSynchronizationManager.bindResource(
      sessionFactory, new SessionHolder(session));
     try{
      filterChain.doFilter(request, response);
     }
     finally{
     TransactionSynchronizationManager.unbindResource(sessionFactory);
     logger.debug("Closing Hibernate Session in OpenSessionInViewFilter");
     closeSession(session, sessionFactory);
     }
    }




     (tng)
  2. protected Session getSession(SessionFactory sessionFactory)
    throws DataAccessResourceFailureException {
     Session session = SessionFactoryUtils.getSession(sessionFactory, true);
     session.setFlushMode(FlushMode.NEVER);
     return session;
    }

  3. protected
    void closeSession(Session session, SessionFactory sessionFactory)
    throws CleanupFailureDataAccessException {
     SessionFactoryUtils.closeSessionIfNecessary(session, sessionFactory);
    }

 (tng) (tng) (tng) (tng) 可以看到OpenSessionInViewFilter在getSession的时??x)把获取回来的session的flush mode 设ؓ(f)FlushMode.NEVER。然后把该sessionFactoryl定到TransactionSynchronizationManagerQrequest的整个过E都使用同一个sessionQ在hq后再接除该sessionFactory的绑定,最?span class="me1">closeSessionIfNecessaryҎ(gu)该session是否已和transactionl定来决定是否关闭session。在q个q程中,若HibernateTemplate 发现自当前session有不是readOnly的transactionQ就?x)获取到FlushMode.AUTO SessionQҎ(gu)拥有写权限?/p>

										
  1. public static void closeSessionIfNecessary(Session session, SessionFactory sessionFactory)
  2. throws CleanupFailureDataAccessException {
  3. if (session == null ||
    TransactionSynchronizationManager.hasResource(sessionFactory)){
  4. return;
  5. }
  6. logger.debug("Closing Hibernate session");
  7. try {
  8. session.close();
  9. }
  10. catch (JDBCException ex){
  11. // SQLException underneath
  12. throw new CleanupFailureDataAccessException("Could not close Hibernate session", ex.getSQLException());
  13. }
  14. catch (HibernateException ex){
  15. throw new CleanupFailureDataAccessException("Could not close Hibernate session", ex);
  16. }
  17. }

 (tng) (tng) (tng) 也即是,如果有不是readOnly的transaction可以由Flush.NEVER转ؓ(f)Flush.AUTO,拥有insert,update,delete操作权限Q如果没有transactionQƈ且没有另外h为地设flush model的话Q则doFilter的整个过E都是Flush.NEVER。所以受transaction保护的方法有写权限,没受保护的则没有?/p>

										
采用spring的事务声?使方法受transaction控制
  1.  (tng) <bean id="baseTransaction"
    class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"
     (tng)  (tng)  (tng)  (tng)  (tng) abstract="true">
     (tng)  (tng)  (tng)  (tng) <property name="transactionManager" ref="transactionManager"/>
     (tng)  (tng)  (tng)  (tng) <property name="proxyTargetClass" value="true"/>
     (tng)  (tng)  (tng)  (tng) <property name="transactionAttributes">
     (tng)  (tng)  (tng)  (tng)  (tng)  (tng) <props>
     (tng)  (tng)  (tng)  (tng)  (tng)  (tng)  (tng)  (tng) <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
     (tng)  (tng)  (tng)  (tng)  (tng)  (tng)  (tng)  (tng) <prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
     (tng)  (tng)  (tng)  (tng)  (tng)  (tng)  (tng)  (tng) <prop key="load*">PROPAGATION_REQUIRED,readOnly</prop>
     (tng)  (tng)  (tng)  (tng)  (tng)  (tng)  (tng)  (tng) <prop key="save*">PROPAGATION_REQUIRED</prop>
     (tng)  (tng)  (tng)  (tng)  (tng)  (tng)  (tng)  (tng) <prop key="add*">PROPAGATION_REQUIRED</prop>
     (tng)  (tng)  (tng)  (tng)  (tng)  (tng)  (tng)  (tng) <prop key="update*">PROPAGATION_REQUIRED</prop>
     (tng)  (tng)  (tng)  (tng)  (tng)  (tng)  (tng)  (tng) <prop key="remove*">PROPAGATION_REQUIRED</prop>
     (tng)  (tng)  (tng)  (tng)  (tng)  (tng) </props>
     (tng)  (tng)  (tng)  (tng) </property>
     (tng)  (tng) </bean>

  2.  (tng)  (tng) <bean id="userService" parent="baseTransaction">
     (tng)  (tng)  (tng)  (tng) <property name="target">
     (tng)  (tng)  (tng)  (tng)  (tng)  (tng) <bean class="com.phopesoft.security.service.impl.UserServiceImpl"/>
     (tng)  (tng)  (tng)  (tng) </property>
     (tng)  (tng) </bean>

对于上例Q则以save,add,update,remove开头的Ҏ(gu)拥有可写的事务,如果当前有某个方法,如命名ؓ(f)importExcel()Q则因没有transaction而没有写权限Q这时若Ҏ(gu)内有insert,update,delete操作的话Q则需要手动设|flush model为Flush.AUTO,?/p>

								
  1. session.setFlushMode(FlushMode.AUTO);
  2. session.save(user);
  3. session.flush();

 (tng) (tng) (tng) (tng) (tng)管Open Session In View看v来还?sh)错Q其实副作用不少。看回上面OpenSessionInViewFilter的doFilterInternalҎ(gu)代码Q这个方法实际上是被父类的doFilter调用的,因此Q我们可以大U了(jin)解的OpenSessionInViewFilter调用程: request(h)->open sessionq开始transaction->controller->View(Jsp)->l束transactionqclose session.

 (tng) (tng) (tng) (tng) 一切看h很正,其是在本地开发测试的时候没出现问题Q但试想下如果流E中的某一步被d的话Q那在这期间connection׃直被占用而不释放。最有可能被d的就是在写Jspq步Q一斚w可能是页面内容大Qresponse.write的时间长Q另一斚w可能是网速慢Q服务器与用户间传输旉久。当大量q样的情况出现时Q就有连接池q接不Q造成面假死现象?/p>

Open Session In View是个双刃剑,攑֜公网上内容多量大的|站h用?/p>

junky 2007-03-06 14:01 发表评论
]]>
Spring + Quartz L搞定webd定时调度(?http://m.tkk7.com/junky/archive/2007/02/25/100617.htmljunkyjunkySun, 25 Feb 2007 09:46:00 GMThttp://m.tkk7.com/junky/archive/2007/02/25/100617.htmlhttp://m.tkk7.com/junky/comments/100617.htmlhttp://m.tkk7.com/junky/archive/2007/02/25/100617.html#Feedback0http://m.tkk7.com/junky/comments/commentRss/100617.htmlhttp://m.tkk7.com/junky/services/trackbacks/100617.htmlwebd定时调度具体的实现方法很?

q里只分n自己的唯一l验? spring + quartz.

其实spring对quartz装的完无?哈哈

试牛刀开始了(jin)...

java代码呢就是区区几?


import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.scheduling.quartz.QuartzJobBean;
import org.apache.log4j.*;

public class ContentArbitrateServiceJob extends QuartzJobBean {
 (tng)public static Logger log = Logger.getLogger(ContentArbitrateServiceJob.class);
 (tng)private int timeout;
 (tng)public void setTimeout(int timeout){
 (tng) (tng)this.timeout = timeout;
 (tng)}
 (tng)protected void executeInternal(JobExecutionContext arg0)
 (tng) (tng) (tng)throws JobExecutionException {
 (tng) (tng)// TODO Auto-generated method stub
 (tng) (tng)try{
 (tng) (tng) (tng)log.info("pȝ监督仲裁处理d开?gt;........");
 (tng) (tng) (tng)//业务逻辑代码调用
 (tng) (tng) (tng)log.info("pȝ监督仲裁处理dl束!");
 (tng) (tng)}catch(Exception e){
 (tng) (tng) (tng)log.error("pȝ监督仲裁处理d出现异常",e);
 (tng) (tng)}
 (tng)}

} (tng)

 (tng)

下面是看配|文仉面的道道?其实也不?

<bean name="contentarbitrateservicejob" (tng) class="org.springframework.scheduling.quartz.JobDetailBean">
 (tng) (tng)  (tng)<property name="jobClass">
 (tng) (tng)  (tng) (tng)<value>com.xuedu.ContentArbitrateServiceJob</value>
 (tng) (tng)  (tng)</property>
 (tng) (tng)  (tng)<property name="jobDataAsMap">
 (tng) (tng)  (tng) (tng)<map>
 (tng) (tng)  (tng) (tng) (tng)<entry key="timeout">
 (tng) (tng)  (tng) (tng) (tng) (tng)<value>5</value>
 (tng) (tng)  (tng) (tng) (tng)</entry>
 (tng) (tng)  (tng) (tng)</map>
 (tng) (tng)  (tng)</property>
 (tng) (tng) </bean>
 (tng)
 (tng) <!-- 配置触发?-->
 (tng) (tng) (tng) (tng) (tng) (tng) <bean id="cronTriggerCA" class="org.springframework.scheduling.quartz.CronTriggerBean">

 (tng) (tng)<property name="jobDetail">
 (tng) (tng) (tng)<ref bean="contentarbitrateservicejob"/>
 (tng) (tng)</property>
 (tng) (tng)<!-- 每天?点到21??0分钟触发Q具体说明见附录 -->
 (tng) (tng)<property name="cronExpression">
 (tng) (tng) (tng)<value>0 50 08-21 * * ?</value>
 (tng) (tng)</property>

 (tng) (tng) (tng) </bean>
 (tng) (tng) (tng)
 (tng) (tng) (tng) <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">

 (tng) (tng)<!-- d触发?-->
 (tng) (tng) <property name="triggers">
 (tng) (tng) (tng) <list>
 (tng) (tng) (tng)<ref local="cronTriggerCA"/>
 (tng) (tng) (tng) </list>
 (tng) (tng) </property>
 (tng) (tng) (tng) </bean>

也很单吧.

至于cronExpresession的设定格式呢,弟附下:

字段 允许?允许的特D字W?
U?0-59 , - * /
?0-59 , - * /
时 0-23 , - * /
日期 1-31 , - * ? / L W C
月䆾 1-12 或?JAN-DEC , - * /
星期 1-7 或?SUN-SAT , - * ? / L C #
q_(d)可选)(j) 留空, 1970-2099 , - * /


表达?意义
"0 0 12 * * ?" 每天中午12点触?
"0 15 10 ? * *" 每天上午10:15触发
"0 15 10 * * ?" 每天上午10:15触发
"0 15 10 * * ? *" 每天上午10:15触发
"0 15 10 * * ? 2005" 2005q的每天上午10:15触发
"0 * 14 * * ?" 在每天下?点到下午2:59期间的每1分钟触发
"0 0/5 14 * * ?" 在每天下?点到下午2:55期间的每5分钟触发
"0 0/5 14,18 * * ?" 在每天下?点到2:55期间和下?点到6:55期间的每5分钟触发
"0 0-5 14 * * ?" 在每天下?点到下午2:05期间的每1分钟触发
"0 10,44 14 ? 3 WED" 每年三月的星期三的下?:10?:44触发
"0 15 10 ? * MON-FRI" 周一臛_五的上午10:15触发
"0 15 10 15 * ?" 每月15日上?0:15触发
"0 15 10 L * ?" 每月最后一日的上午10:15触发
"0 15 10 ? * 6L" 每月的最后一个星期五上午10:15触发
"0 15 10 ? * 6L 2002-2005" 2002q至2005q的每月的最后一个星期五上午10:15触发
"0 15 10 ? * 6#3" 每月的第三个星期五上?0:15触发

至于每个W号 看看例子好?很简单了(jin).



junky 2007-02-25 17:46 发表评论
]]>
Acegi安全pȝ的配|??http://m.tkk7.com/junky/archive/2007/01/30/96724.htmljunkyjunkyTue, 30 Jan 2007 06:14:00 GMThttp://m.tkk7.com/junky/archive/2007/01/30/96724.htmlhttp://m.tkk7.com/junky/comments/96724.htmlhttp://m.tkk7.com/junky/archive/2007/01/30/96724.html#Feedback0http://m.tkk7.com/junky/comments/commentRss/96724.htmlhttp://m.tkk7.com/junky/services/trackbacks/96724.html

Acegi (tng)的配|看h非常复杂,但事实上在实际项目的安全应用中我们ƈ不需要那么多功能,清楚的了(jin)解Acegi配置中各的功能Q有助于我们灉|的运用Acegi于实践中。?/font>

 (tng)

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)Acegi (tng)的配|看h非常复杂,但事实上在实际项目的安全应用中我们ƈ不需要那么多功能,清楚的了(jin)解Acegi配置中各的功能Q有助于我们灉|的运用Acegi于实践中?/font>

2.1 (tng)在Web.xml中的配置

1) (tng) (tng)FilterToBeanProxy
  Acegi通过实现?jin)Filter接口的FilterToBeanProxy提供一U特D的使用Servlet (tng)Filter的方式,它委托Spring中的Bean (tng)-- (tng)FilterChainProxy来完成过滤功能,q好处是化了(jin)web.xml的配|,q且充分利用?jin)Spring (tng)I(yng)OC的优ѝFilterChainProxy包含?jin)处理认证过E的filter列表Q每个filter都有各自的功能?/font>

						 (tng) (tng) (tng) (tng)<filter>
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)<filter-name>Acegi (tng)Filter (tng)Chain (tng)Proxy</filter-name>
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)<filter-class>org.acegisecurity.util.FilterToBeanProxy</filter-class>
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)<init-param>
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)<param-name>targetClass</param-name>
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)<param-value>org.acegisecurity.util.FilterChainProxy</param-value>
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)</init-param>
 (tng) (tng) (tng) (tng)</filter>

2) (tng)filter-mapping
  <filter-mapping>限定?jin)FilterToBeanProxy的URL匚w模式,只有*.do?.jsp?j_acegi_security_check (tng)的请求才?x)受到权限控Ӟ对javascript,css{不限制?/font>

						 (tng) (tng) (tng)<filter-mapping>
 (tng) (tng) (tng) (tng) (tng) (tng)<filter-name>Acegi (tng)Filter (tng)Chain (tng)Proxy</filter-name>
 (tng) (tng) (tng) (tng) (tng) (tng)<url-pattern>*.do</url-pattern>
 (tng) (tng) (tng) (tng)</filter-mapping>
 (tng) (tng) (tng) (tng)
 (tng) (tng) (tng) (tng)<filter-mapping>
 (tng) (tng) (tng) (tng) (tng) (tng)<filter-name>Acegi (tng)Filter (tng)Chain (tng)Proxy</filter-name>
 (tng) (tng) (tng) (tng) (tng) (tng)<url-pattern>*.jsp</url-pattern>
 (tng) (tng) (tng) (tng)</filter-mapping>
 (tng) (tng) (tng) (tng)
 (tng) (tng) (tng) (tng)<filter-mapping>
 (tng) (tng) (tng) (tng) (tng) (tng)<filter-name>Acegi (tng)Filter (tng)Chain (tng)Proxy</filter-name>
 (tng) (tng) (tng) (tng) (tng) (tng)<url-pattern>/j_acegi_security_check</url-pattern>
 (tng) (tng) (tng) (tng)</filter-mapping>

3) (tng)HttpSessionEventPublisher
  <listener>的HttpSessionEventPublisher用于发布HttpSessionApplicationEvents和HttpSessionDestroyedEvent事glspring的applicationcontext?/font>

						 (tng) (tng) (tng) (tng)<listener>
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)<listener-class>org.acegisecurity.ui.session.HttpSessionEventPublisher</listener-class>
 (tng) (tng) (tng) (tng)</listener>


2.2 (tng)在applicationContext-acegi-security.xml?/font>

2.2.1 (tng)FILTER (tng)CHAIN

  FilterChainProxy?x)按序来调用这些filter,使这些filter能n用Spring (tng)ioc的功? (tng)CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON定义?jin)url比较前先转ؓ(f)写Q?tng)PATTERN_TYPE_APACHE_ANT定义?jin)用Apache (tng)ant的匹配模式?/font>

						 (tng) (tng) (tng) (tng)<bean (tng)id="filterChainProxy" (tng)class="org.acegisecurity.util.FilterChainProxy">
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)<property (tng)name="filterInvocationDefinitionSource">
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)<value>
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)PATTERN_TYPE_APACHE_ANT
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)/**=httpSessionContextIntegrationFilter,authenticationProcessingFilter,
basicProcessingFilter,rememberMeProcessingFilter,anonymousProcessingFilter,
 (tng)exceptionTranslationFilter,filterInvocationInterceptor
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)</value>
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)</property>
 (tng) (tng) (tng) (tng)</bean>

2.2.2 (tng)基础认证

1) (tng)authenticationManager
  起到认证理的作用,它将验证的功能委托给多个ProviderQƈ通过遍历Providers, (tng)以保证获取不同来源的w䆾认证Q若某个Provider能成功确认当前用L(fng)w䆾Qauthenticate()Ҏ(gu)?x)返回一个完整的包含用户授权信息的Authentication对象Q否则会(x)抛出一个AuthenticationException?br />Acegi提供?jin)不同的AuthenticationProvider的实?如:(x)
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)DaoAuthenticationProvider (tng)从数据库中读取用户信息验证n?br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)AnonymousAuthenticationProvider (tng)匿名用户w䆾认证
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)RememberMeAuthenticationProvider (tng)已存cookie中的用户信息w䆾认证
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)AuthByAdapterProvider (tng)使用容器的适配器验证n?br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)CasAuthenticationProvider (tng)Ҏ(gu)Yale中心(j)认证服务验证?li)w䆾, (tng)用于实现单点登陆
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)JaasAuthenticationProvider (tng)从JASS登陆配置中获取用户信息验证n?br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)RemoteAuthenticationProvider (tng)Ҏ(gu)q程服务验证用户w䆾
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)RunAsImplAuthenticationProvider (tng)对n份已被管理器替换的用戯行验?br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)X509AuthenticationProvider (tng)从X509认证中获取用户信息验证n?br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)TestingAuthenticationProvider (tng)单元试时?/font>

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)每个认证者会(x)对自己指定的证明信息q行认证Q如DaoAuthenticationProvider仅对UsernamePasswordAuthenticationTokenq个证明信息q行认证?/font>

						<bean (tng)id="authenticationManager" (tng)class="org.acegisecurity.providers.ProviderManager">
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)<property (tng)name="providers">
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)<list>
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)<ref (tng)local="daoAuthenticationProvider"/>
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)<ref (tng)local="anonymousAuthenticationProvider"/>
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)<ref (tng)local="rememberMeAuthenticationProvider"/>
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)</list>
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)</property>
</bean>


2) (tng)daoAuthenticationProvider
  q行单的Z数据库的w䆾验证。DaoAuthenticationProvider获取数据库中的̎号密码ƈq行匚wQ若成功则在通过用户w䆾的同时返回一个包含授权信息的Authentication对象Q否则n份验证失败,抛出一个AuthenticatiionException?/font>

						 (tng) (tng) (tng) (tng)<bean (tng)id="daoAuthenticationProvider" (tng)class="org.acegisecurity.providers.dao.DaoAuthenticationProvider">
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)<property (tng)name="userDetailsService" (tng)ref="jdbcDaoImpl"/>
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)<property (tng)name="userCache" (tng)ref="userCache"/>
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)<property (tng)name="passwordEncoder" (tng)ref="passwordEncoder"/>
 (tng) (tng) (tng)</bean>


3) (tng)passwordEncoder (tng)
  使用加密器对用户输入的明文进行加密。Acegi提供?jin)三U加密器:
PlaintextPasswordEncoder—默认,不加密,q回明文.
ShaPasswordEncoder—哈希算?SHA)加密
Md5PasswordEncoder—消息摘?MD5)加密

						<bean (tng)id="passwordEncoder" (tng)class="org.acegisecurity.providers.encoding.Md5PasswordEncoder"/>
				


4) (tng)jdbcDaoImpl (tng)
  用于在数据中获取用户信息。?tng)acegi提供?jin)用户?qing)授权的表l构Q但是?zhn)也可以自己来实现。通过usersByUsernameQueryq个SQL得到你的(用户ID,密码,状态信?;通过authoritiesByUsernameQueryq个SQL得到你的(用户ID,授权信息)

						 (tng)
<bean (tng)id="jdbcDaoImpl" (tng)
class="org.acegisecurity.userdetails.jdbc.JdbcDaoImpl">
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) <property (tng)name="dataSource" (tng) ref="dataSource"/>
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)<property (tng) name="usersByUsernameQuery">
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) <value>select (tng)loginid,passwd,1 (tng)from (tng)users (tng)where (tng)loginid (tng)= (tng) ?</value>
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) </property>
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)<property (tng) name="authoritiesByUsernameQuery">
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) <value>select (tng)u.loginid,p.name (tng)from (tng)users (tng)u,roles (tng)r,permissions (tng) p,user_role (tng)ur,role_permis (tng)rp (tng)where (tng)u.id=ur.user_id (tng)and (tng)r.id=ur.role_id (tng)and (tng) p.id=rp.permis_id (tng) and
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) r.id=rp.role_id (tng)and (tng)p.status='1' (tng)and (tng) u.loginid=?</value>
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) </property>
</bean>

5) (tng)userCache & (tng) (tng)resourceCache (tng)
  ~存用户和资源相对应的权限信息。每当请求一个受保护资源ӞdaoAuthenticationProvider׃(x)被调用以获取用户授权信息。如果每ơ都从数据库获取的话Q那代h(hun)很高Q对于不常改变的用户和资源信息来_(d)最好是把相x(chng)权信息缓存v来?详见 (tng)
2.6.3 (tng)资源权限定义扩展  (tng))
userCache提供?jin)两U实? (tng)NullUserCache和EhCacheBasedUserCache, (tng)NullUserCache实际上就是不q行M~存QEhCacheBasedUserCache是用Ehcache来实现缓功能?/font>

						<bean (tng)id="userCacheBackend" (tng)class="org.springframework.cache.ehcache.EhCacheFactoryBean">
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) <property (tng)name="cacheManager" (tng)ref="cacheManager"/>
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) <property (tng)name="cacheName" (tng)value="userCache"/>
 (tng) (tng) (tng) (tng)</bean>
 (tng) (tng) (tng) (tng)<bean (tng)id="userCache" (tng)class="org.acegisecurity.providers.dao.cache.EhCacheBasedUserCache" (tng)autowire="byName">
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)<property (tng)name="cache" (tng)ref="userCacheBackend"/> (tng) (tng) (tng) (tng) (tng) (tng)  (tng) (tng) (tng) (tng)</bean>
 (tng) (tng) (tng) (tng)<bean (tng)id="resourceCacheBackend" (tng)class="org.springframework.cache.ehcache.EhCacheFactoryBean"> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) <property (tng)name="cacheManager" (tng)ref="cacheManager"/> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)  (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)<property (tng)name="cacheName" (tng)value="resourceCache"/>
 (tng) (tng) (tng) (tng)</bean>
 (tng) (tng) (tng) (tng)<bean (tng)id="resourceCache" (tng)class="org.springside.modules.security.service.acegi.cache.ResourceCache" (tng)autowire="byName">
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)<property (tng)name="cache" (tng)ref="resourceCacheBackend"/>
 (tng) (tng) (tng) (tng)</bean>


6) (tng)basicProcessingFilter (tng)
  用于处理HTTP头的认证信息Q如从Springq程协议(如Hessian和Burlap)或普通的览器如IE,Navigator的HTTP头中获取用户信息Q将他们转交l通过authenticationManager属性装配的认证理器。如果认证成功,?x)将一个Authentication对象攑ֈ?x)话中,否则Q如果认证失败,?x)将控制转交l认证入口点(通过authenticationEntryPoint属性装?

						 (tng) (tng) (tng) (tng)<bean (tng)id="basicProcessingFilter" (tng)class="org.acegisecurity.ui.basicauth.BasicProcessingFilter">
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)<property (tng)name="authenticationManager" (tng)ref="authenticationManager"/>
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)<property (tng)name="authenticationEntryPoint" (tng)ref="basicProcessingFilterEntryPoint"/>
 (tng) (tng) (tng) (tng)</bean>

7) (tng)basicProcessingFilterEntryPoint (tng)
  通过向浏览器发送一个HTTP401(未授?消息Q提C用L(fng)录?br />处理ZHTTP的授权过E, (tng)在当验证q程出现异常后的"d"Q通常实现转向、在response里加入error信息{功能?/font>

						<bean (tng)id="basicProcessingFilterEntryPoint" (tng)class="org.acegisecurity.ui.basicauth.BasicProcessingFilterEntryPoint"> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)
 <property (tng)name="realmName" (tng)value="SpringSide (tng)Realm"/>
</bean>

8) (tng)authenticationProcessingFilterEntryPoint (tng)
  当抛出AccessDeniedExceptionӞ用户重定向到登录界面。属性loginFormUrl配置?jin)一个登录表单的URL,当需要用L(fng)录时QauthenticationProcessingFilterEntryPoint?x)将用户重定向到该URL

						 (tng)
<bean (tng)id="authenticationProcessingFilterEntryPoint" (tng)class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint">
<property (tng)name="loginFormUrl">
<value>/security/login.jsp</value>
</property>
<property (tng)name="forceHttps" (tng)value="false"/>
</bean>

2.2.3 (tng)HTTP安全h

1) (tng)httpSessionContextIntegrationFilter
  每次request前?tng)HttpSessionContextIntegrationFilter从Session中获取Authentication对象Q在request完后, (tng)又把Authentication对象保存到Session中供下次request使用,此filter必须其他Acegi (tng)filter前用,使之能跨多个请求?/font>

						<bean (tng)id="httpSessionContextIntegrationFilter" (tng)class="org.acegisecurity.context.HttpSessionContextIntegrationFilter"></bean>
 (tng) (tng) (tng) (tng)<bean (tng)id="httpRequestAccessDecisionManager" (tng)class="org.acegisecurity.vote.AffirmativeBased">
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)<property (tng)name="allowIfAllAbstainDecisions" (tng)value="false"/>
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)<property (tng)name="decisionVoters">
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)<list>
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)<ref (tng)bean="roleVoter"/>
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)</list>
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)</property>
</bean>


2) (tng)httpRequestAccessDecisionManager
  l过投票机制来决定是否可以访问某一资源(URL或方?。allowIfAllAbstainDecisions为false时如果有一个或以上的decisionVoters投票通过,则授权通过。可选的决策机制有ConsensusBased和UnanimousBased

						 (tng) (tng) (tng) (tng)<bean (tng)id="httpRequestAccessDecisionManager" (tng)class="org.acegisecurity.vote.AffirmativeBased">
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)<property (tng)name="allowIfAllAbstainDecisions" (tng)value="false"/>
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)<property (tng)name="decisionVoters">
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)<list>
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)<ref (tng)bean="roleVoter"/>
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)</list>
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)</property>
 (tng) (tng) (tng) (tng)</bean>


3) (tng)roleVoter
 (tng)  必须是以rolePrefix讑֮的value开头的权限才能q行投票,如AUTH_ (tng), (tng)ROLE_

						 (tng) (tng) (tng) (tng)<bean (tng)id="roleVoter" (tng)class="org.acegisecurity.vote.RoleVoter">
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)<property (tng)name="rolePrefix" (tng)value="AUTH_"/>
 (tng) (tng) (tng)</bean>

4Q?strong>exceptionTranslationFilter
  异常转换qo(h)器,主要是处理AccessDeniedException和AuthenticationExceptionQ将l每个异常找到合适的"d" (tng)

						 (tng) (tng) (tng)<bean (tng)id="exceptionTranslationFilter" (tng)class="org.acegisecurity.ui.ExceptionTranslationFilter">
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)<property (tng)name="authenticationEntryPoint" (tng)ref="authenticationProcessingFilterEntryPoint"/>
 (tng) (tng) (tng) (tng)</bean>

5) (tng)authenticationProcessingFilter
  和servlet (tng)spec差不?处理登陆h.当n份验证成功时QAuthenticationProcessingFilter?x)在会(x)话中放|一个Authentication对象Qƈ且重定向到登录成功页?br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)authenticationFailureUrl定义登陆p|时{向的面
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)defaultTargetUrl定义登陆成功时{向的面
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)filterProcessesUrl定义登陆h的页?br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)rememberMeServices用于在验证成功后dcookie信息

						 (tng) (tng) (tng) (tng)<bean (tng)id="authenticationProcessingFilter" (tng)class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilter">
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)<property (tng)name="authenticationManager" (tng)ref="authenticationManager"/>
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)<property (tng)name="authenticationFailureUrl">
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)<value>/security/login.jsp?login_error=1</value>
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)</property>
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)<property (tng)name="defaultTargetUrl">
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)<value>/admin/index.jsp</value>
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)</property>
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)<property (tng)name="filterProcessesUrl">
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)<value>/j_acegi_security_check</value>
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)</property>
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)<property (tng)name="rememberMeServices" (tng)ref="rememberMeServices"/>
 (tng) (tng) (tng) (tng)</bean>

6) (tng)filterInvocationInterceptor
  在执行{向url前检查objectDefinitionSource中设定的用户权限信息。首先,objectDefinitionSource中定义了(jin)讉KURL需要的属性信?q里的属性信息仅仅是标志Q告诉accessDecisionManager要用哪些voter来投?。然后,authenticationManager掉用自己的provider来对用户的认证信息进行校验。最后,有投者根据用h有认证和讉Kurl需要的属性,调用自己的voter来投,军_是否允许讉K?/font>

						 (tng) (tng) (tng) (tng)<bean (tng)id="filterInvocationInterceptor" (tng)class="org.acegisecurity.intercept.web.FilterSecurityInterceptor">
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)<property (tng)name="authenticationManager" (tng)ref="authenticationManager"/>
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)<property (tng)name="accessDecisionManager" (tng)ref="httpRequestAccessDecisionManager"/>
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)<property (tng)name="objectDefinitionSource" (tng)ref="filterDefinitionSource"/>
 (tng) (tng) (tng) (tng)</bean>


7) (tng)filterDefinitionSource (tng)(详见 (tng) 2.6.3 (tng)资源权限定义扩展 )
  自定义DBFilterInvocationDefinitionSource从数据库和cache中读取保护资源及(qing)光要的讉K权限信息 (tng)

						<bean (tng)id="filterDefinitionSource" (tng)class="org.springside.modules.security.service.acegi.DBFilterInvocationDefinitionSource">
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)<property (tng)name="convertUrlToLowercaseBeforeComparison" (tng)value="true"/>
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)<property (tng)name="useAntPath" (tng)value="true"/>
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)<property (tng)name="acegiCacheManager" (tng)ref="acegiCacheManager"/>
</bean>

2.2.4 (tng)Ҏ(gu)调用安全控制

(详见 (tng) 2.6.3 (tng)资源权限定义扩展 )

1) (tng)methodSecurityInterceptor
  在执行方法前q行拦截Q检查用h限信?br />2) (tng)methodDefinitionSource
  自定义MethodDefinitionSource从cache中读取权?/font>

						 (tng) (tng) (tng)<bean (tng)id="methodSecurityInterceptor" (tng)class="org.acegisecurity.intercept.method.aopalliance.MethodSecurityInterceptor">
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)<property (tng)name="authenticationManager" (tng)ref="authenticationManager"/>
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)<property (tng)name="accessDecisionManager" (tng)ref="httpRequestAccessDecisionManager"/>
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)<property (tng)name="objectDefinitionSource" (tng)ref="methodDefinitionSource"/>
 (tng) (tng) (tng) (tng)</bean>
 (tng) (tng) (tng) (tng)<bean (tng)id="methodDefinitionSource" (tng)class="org.springside.modules.security.service.acegi.DBMethodDefinitionSource">
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)<property (tng)name="acegiCacheManager" (tng)ref="acegiCacheManager"/>
 (tng) (tng) (tng) (tng)</bean>

2.3 (tng)Jcaptcha验证?/font>

采用 (tng) http://jcaptcha.sourceforge.net  (tng)作ؓ(f)通用的验证码Ҏ(gu)Q请参考SpringSide中的例子Q或|上的:(x)
http://www.coachthrasher.com/page/blog?entry=jcaptcha_with_appfuse ?/font>

差沙在此q程中又发现acegi (tng)logout (tng)filter的错误,q行?jin)修正?/font>



junky 2007-01-30 14:14 发表评论
]]>
Spring的Acegi security的配|,和JDK1.5的一些问??http://m.tkk7.com/junky/archive/2006/12/22/89560.htmljunkyjunkyFri, 22 Dec 2006 08:36:00 GMThttp://m.tkk7.com/junky/archive/2006/12/22/89560.htmlhttp://m.tkk7.com/junky/comments/89560.htmlhttp://m.tkk7.com/junky/archive/2006/12/22/89560.html#Feedback0http://m.tkk7.com/junky/comments/commentRss/89560.htmlhttp://m.tkk7.com/junky/services/trackbacks/89560.html阅读全文

junky 2006-12-22 16:36 发表评论
]]>
Spring AOP with Hibernatehttp://m.tkk7.com/junky/archive/2006/10/17/75602.htmljunkyjunkyTue, 17 Oct 2006 06:08:00 GMThttp://m.tkk7.com/junky/archive/2006/10/17/75602.htmlhttp://m.tkk7.com/junky/comments/75602.htmlhttp://m.tkk7.com/junky/archive/2006/10/17/75602.html#Feedback0http://m.tkk7.com/junky/comments/commentRss/75602.htmlhttp://m.tkk7.com/junky/services/trackbacks/75602.html

One of the sweetiest things the Spring framework gives is Hibernate support is built-in by the time it's born.

Following is a quick guide to configure Hibernate's SessionFactory in Spring. For a detailed version about Spring's Hibernate support, read http://www.springframework.org/docs/data_access.html .



With Spring, Hibernate's SessionFactory no longer needs to bind itself to JNDI; nor use Hibernate's own hibernate.cfg.xml method, which is a little bit tricky to code in Hibernate 2.x (as Hibernate2 doesn't use the once-and-only-once configure() anymore).

Instead, we use org.springframework.orm.hibernate.LocalSessionFactoryBean .

<bean (tng)id= "MySessionFactory" (tng) class = "org.springframework.orm.hibernate.LocalSessionFactoryBean" >

 (tng) (tng) (tng) <property (tng)name= "mappingResources" >

 (tng) (tng) (tng) (tng) (tng) (tng) <list>

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) <value>mappings/Book.hbm.xml</value>

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) <value>mappings/Patron.hbm.xml</value>

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) <value>mappings/BorrowRecord.hbm.xml</value>

 (tng) (tng) (tng) (tng) (tng) (tng) </list>

 (tng) (tng) (tng) </property>

 (tng) (tng) (tng) <property (tng)name= "hibernateProperties" >

 (tng) (tng) (tng) (tng) (tng) (tng) <props>

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) <prop (tng)key= "hibernate.dialect" >net.sf.hibernate.dialect.MySQLDialect</prop>

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) <prop (tng)key= "hibernate.query.substitutions" > true = 1 (tng) false = 0 </prop>

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) <prop (tng)key= "hibernate.show_sql" > false </prop>

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) <prop (tng)key= "hibernate.use_outer_join" > false </prop>

 (tng) (tng) (tng) (tng) (tng) (tng) </props>

 (tng) (tng) (tng) </property>

 (tng) (tng) (tng) <property (tng)name= "dataSource" ><ref (tng)bean= "MyDataSource" /></property>

</bean>

The above parameters are simple and verbose:

However, we don't need to configure a transaction manager inside the SessionFactory, as we will see below.

After configuring this, we need to provide a setter method in our business objects that need to use Hibernate's SessionFactory:

import (tng) net.sf.hibernate.SessionFactory;

....

public (tng)class (tng) MyBusinessObjectImpl (tng) implements (tng) MyBusinessObject

{

 (tng) (tng) (tng) private (tng) SessionFactory (tng)sessionFactory;

 (tng) (tng)

 (tng)

public (tng) void (tng) setSessionFactory(SessionFactory (tng)sessionFactory)

 (tng) (tng) (tng) {

 (tng) (tng) (tng) (tng) (tng) (tng) this .sessionFactory (tng)= (tng)sessionFactory;

 (tng) (tng) (tng) }

 (tng) (tng) (tng) public (tng) SessionFactory (tng)getSessionFactory()

 (tng) (tng) (tng) {

 (tng) (tng) (tng) (tng) (tng) (tng) return (tng)this .sessionFactory;

 (tng) (tng) (tng) }

....

and hook it up to Spring.

<bean (tng)id= "MyBusinessObject" (tng) class = "library.MyBusinessObjectImpl" >

 (tng) (tng) (tng) <property (tng)name= "sessionFactory" >

 (tng) (tng) (tng) (tng) (tng) (tng) <ref (tng)bean= "MySessionFactory" />

 (tng) (tng) (tng) </property>

</bean>

 (tng)

How about transactions support? And how do I get Hibernate's Session inside my business objects?

That's Spring framework's another power - HibernateInterceptor and TransactionInterceptor. With them, together with configurations made in Spring, methods inside business objects don't need to write a single line of code for that; instead, a Session will be bound to the business object's current thread, opened and closed automatically; and a transaction will also begin and end automatically.

The sequence is like this:

  1. Transaction begins
  2. Hibernate session opened and bound to the current thread
  3. Actual method execution
  4. Hibernate session bound to the current thread closed
  5. Transaction ended

This is done with the help of Spring's AOP capability.

However, we need to configure a transaction manager first.

<bean (tng)id= "MyTransactionManager" (tng) class = "org.springframework.transaction.jta.JtaTransactionManager" />

The above configures a transaction manager that will access an UserTransaction inside the environment, usually in a J2EE container, or a servlet container with transaction support.

Alternately you may want to have a look at org.springframework.orm.hibernate.HibernateTransactionManager .

Next, we need to define the transaction attribute for our business methods. This is done in org.springframework.transaction.interceptor.TransactionInterceptor ? .

<bean (tng)id= "MyTransactionInterceptor" (tng)

class = "org.springframework.transaction.interceptor.TransactionInterceptor" >

 (tng) (tng) (tng) <property (tng)name= "transactionManager" ><ref (tng)bean= "MyTransactionManager" /></property>

 (tng) (tng) (tng) <property (tng)name= "transactionAttributeSource" >

 (tng) (tng) <value>

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) library.MyBusinessImpl.borrowBook=PROPAGATION_REQUIRED

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) library.MyBusinessImpl.returnBook=PROPAGATION_REQUIRED

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) library.BookSearchImpl.*=PROPAGATION_SUPPORTS

 (tng) (tng) </value>

 (tng) (tng) (tng) </property>

</bean>

You can use a wildcard to tell every method in that business object uses the same transaction attribute. However it is not recommended, as the private methods used inside the business object will have transactions too, which you may not need to.

By the way, the TransactionInterceptor's default behaviour is to commit an transaction anyway, and rollback whenever a RuntimeException is caught - much the same as EJB's behaviour. If you want to control TransactionInterceptor's behaviour when exception is caught, you may tell it with a plus (+) or minus (-) sign, followed by the name of the exception, to commit or rollback a transaction even if an exception mentioned is caught.

An example:

library.MyBusinessImpl.addBook=PROPAGATION_REQUIRED,-SeriesNotFoundException,+CategoryNotFoundException

This means that when SeriesNotFoundException is thrown inside the addBook() method, the transaction will roll back; on the other hand when CategoryNotFoundException is thrown the transaction will be commited anyway.

In most cases you don't need to specify the exception's name with the package it belongs; you just need to specify simply the exception's name.

Then our business objects will need to define as an AOP "target". This is just a change in a name; make sure your code will not call these business objects directly. So change the above business object declaration to

<bean (tng)id= "MyBusinessObjectTarget" (tng) class = "library.MyBusinessObjectImpl" >

 (tng) (tng) (tng) <property (tng)name= "sessionFactory" >

 (tng) (tng) (tng) (tng) (tng) (tng) <ref (tng)bean= "MySessionFactory" />

 (tng) (tng) (tng) </property>

</bean>

Final step is to expose the business object on Spring's ApplicationContext, but not the business object itself; instead we use a ProxyFactoryBean, provided by Spring.

<bean (tng)id= "MyBusinessObject" (tng) class = "org.springframework.aop.framework.ProxyFactoryBean" >

 (tng) (tng) (tng) <property (tng)name= "proxyInterfaces" >

 (tng) (tng) (tng) (tng) (tng) (tng) <value>library.MyBusinessObject</value>

 (tng) (tng) (tng) </property>

 (tng) (tng) (tng) <property (tng)name= "interceptorNames" >

 (tng) (tng) (tng) (tng) (tng) (tng) <list>

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) <value>MyTransactionInterceptor</value>

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) <value>MyHibernateInterceptor</value>

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) <value>MyBusinessObjectTarget</value>

 (tng) (tng) (tng) (tng) (tng) (tng) </list>

 (tng) (tng) (tng) </property>

</bean>

  • proxyInterfaces: the interface implemented by your business object.
  • interceptorNames: the interceptors to be applied when methods on the business interface is called. Be careful, they have to be placed in order.

Then in our business method we just need to obtain the Session instance, and ignore everything else - everything is done behind the scene.

import (tng) net.sf.hibernate.*;

import (tng) org.springframework.orm.hibernate.SessionFactoryUtils;

....

public (tng) Book (tng)findBook( int (tng) bookID) (tng) throws (tng) BookNotFoundException, (tng)DataAccessException

{

 (tng) (tng) (tng) //get (tng)the (tng)Session (tng)instance (tng)already (tng)bound (tng)to (tng)current (tng)thread (tng)and (tng)opened

 (tng) (tng) (tng) Session (tng)session (tng)= (tng)SessionFactoryUtils.getSession(getSessionFactory(), (tng) false );

 (tng) (tng) (tng) try

 (tng) (tng) (tng) {

 (tng) (tng) (tng) (tng) (tng) (tng) Book (tng)book (tng)= (tng)(Book)session.load(Book.class, (tng)bookID);

 (tng) (tng) (tng) (tng) (tng) (tng) return (tng) book;

 (tng) (tng) (tng) }

 (tng) (tng) (tng) catch (ObjectNotFoundException (tng)e)

 (tng) (tng) (tng) {

 (tng) (tng) (tng) (tng) (tng) (tng) throw (tng)new (tng) BookNotFoundException();

 (tng) (tng) (tng) }

 (tng) (tng) (tng) catch (HibernateException (tng)e)

 (tng) (tng) (tng) {

 (tng) (tng) (tng) (tng) (tng) (tng) throw (tng) SessionFactoryUtils.convertHibernateAccessException(e);

 (tng) (tng) (tng) }

}

 (tng)

Alternately you may also use HibernateTemplate and TransactionTemplate, though the above method is simpler. Read http://www.hibernate.org/110.html for details (this page seems more updated than the one in Spring?).



junky 2006-10-17 14:08 发表评论
]]>
Spring的几个常用的Bean声明http://m.tkk7.com/junky/archive/2006/10/17/75600.htmljunkyjunkyTue, 17 Oct 2006 06:06:00 GMThttp://m.tkk7.com/junky/archive/2006/10/17/75600.htmlhttp://m.tkk7.com/junky/comments/75600.htmlhttp://m.tkk7.com/junky/archive/2006/10/17/75600.html#Feedback0http://m.tkk7.com/junky/comments/commentRss/75600.htmlhttp://m.tkk7.com/junky/services/trackbacks/75600.html Spring Bean hibernate SessionFactory Bean 1 Message source

<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">

<property name="basename"><value>messages</value></property>

</bean>

2 Bean

<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">

<property name="locations">

<list>

<value>WEB-INF/mail.properties</value>

<value>WEB-INF/jdbc.properties</value>

</list>

</property>

</bean>

3 Custom Editor

<bean id="customEditorConfigurer" class="org.springframework.beans.factory.config.CustomEditorConfigurer">

<property name="customEditors">

<map>

<entry key="java.util.Date">

<bean class="org.springframework.beans.propertyeditors.CustomDateEditor">

<constructor-arg index="0">

<bean class="java.text.SimpleDateFormat">

<constructor-arg><value>yyyy-MM-dd</value></constructor-arg>

</bean>

</constructor-arg>

<constructor-arg index="1"><value>false</value></constructor-arg>

</bean>

</entry>

</map>

</property>

</bean>

4

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">

<property name="driverClassName"><value>${jdbc.driverClassName}</value></property>

<property name="url"><value>${jdbc.url}</value></property>

<property name="username"><value>${jdbc.username}</value></property>

<property name="password"><value>${jdbc.password}</value></property>

</bean>

5 hibernate

<bean id="sessionFactory" class="org.springframework.orm.hibernate.LocalSessionFactoryBean">

<property name="dataSource"><ref local="dataSource"/></property>

<property name="mappingResources">

<value>mapping.xml</value>

</property>

<property name="hibernateProperties">

<props>

<prop key="hibernate.dialect">${hibernate.dialect}</prop>

</props>

</property>

</bean>

6 Jotm

<bean id="jotm" class="org.springframework.transaction.jta.JotmFactoryBean"/>

<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">

<property name="userTransaction"><ref local="jotm"/></property>

</bean>

7 Hibernate

<bean id="hibernateTransactionManager" class="org.springframework.orm.hibernate.HibernateTransactionManager">

<property name="sessionFactory"><ref local="sessionFactory"/></property>

</bean>

8 Bean

<bean id="clinic" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">

<property name="transactionManager"><ref local="hibernateTransactionManager"/></property>

<property name="target"><ref local="clinicTarget"/></property>

<property name="transactionAttributes">

<props>

<prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>

<prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>

<prop key="load*">PROPAGATION_REQUIRED,readOnly</prop>

<prop key="store*">PROPAGATION_REQUIRED</prop>

</props>

</property>

</bean>

9 Email

<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">

<property name="host"><value>${mail.host}</value></property>

</bean>

10 Url Mapping

<bean id="DemoController" class="cn.edu.bit82.DemoController"/>

<bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">

<property name="mappings">

<props>

<prop key="/hello.html">DemoController</prop>

<prop key="*">SecondController</prop>

</props>

</property>

</bean>

Bean IntelliJ Live Template Bean



junky 2006-10-17 14:06 发表评论
]]>
ServiceLocator的实?/title><link>http://m.tkk7.com/junky/archive/2006/10/17/75601.html</link><dc:creator>junky</dc:creator><author>junky</author><pubDate>Tue, 17 Oct 2006 06:06:00 GMT</pubDate><guid>http://m.tkk7.com/junky/archive/2006/10/17/75601.html</guid><wfw:comment>http://m.tkk7.com/junky/comments/75601.html</wfw:comment><comments>http://m.tkk7.com/junky/archive/2006/10/17/75601.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/junky/comments/commentRss/75601.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/junky/services/trackbacks/75601.html</trackback:ping><description><![CDATA[ServiceLocator的实?br /><p style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: tahoma">/*</p><p style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: tahoma">* Created on 2004-8-25 by simba.</p><p style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: tahoma">*</p><p style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: tahoma">*/</p><p style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: tahoma">package com.simba.blog.util;</p><p style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: tahoma"> (tng)</p><p style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: tahoma"> (tng)</p><p style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: tahoma">import javax.servlet.ServletContext;</p><p style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: tahoma"> (tng)</p><p style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: tahoma">import org.apache.commons.logging.Log;</p><p style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: tahoma">import org.apache.commons.logging.LogFactory;</p><p style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: tahoma">import org.springframework.context.ApplicationContext;</p><p style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: tahoma">import org.springframework.web.context.support.WebApplicationContextUtils;</p><p style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: tahoma"> (tng)</p><p style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: tahoma">import com.opensymphony.webwork.ServletActionContext;</p><p style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: tahoma">import com.simba.blog.service.BlogService;</p><p style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: tahoma"> (tng)</p><p style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: tahoma">/**</p><p style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: tahoma">* @author simba</p><p style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: tahoma">* </p><p style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: tahoma">* email: simbasun@msn.com</p><p style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: tahoma">*/</p><p style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: tahoma">public class ServiceLocator</p><p style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: tahoma">{</p><p style="FONT-SIZE: 10pt; MARGIN: 0in 0in 0in 0.5in; FONT-FAMILY: tahoma">//the catalog service bean name</p><p style="FONT-SIZE: 10pt; MARGIN: 0in 0in 0in 0.5in; FONT-FAMILY: tahoma">private static final String BLOG_SERVICE_BEAN_NAME = "blogService";</p><p style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: tahoma"> (tng)</p><p style="FONT-SIZE: 10pt; MARGIN: 0in 0in 0in 0.5in; FONT-FAMILY: tahoma">//the user service bean name</p><p style="FONT-SIZE: 10pt; MARGIN: 0in 0in 0in 0.5in; FONT-FAMILY: tahoma">private static final String USER_SERVICE_BEAN_NAME = "userService";</p><p style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: tahoma"> (tng)</p><p style="FONT-SIZE: 10pt; MARGIN: 0in 0in 0in 0.5in; FONT-FAMILY: tahoma">//the logger for this class</p><p style="FONT-SIZE: 10pt; MARGIN: 0in 0in 0in 0.5in; FONT-FAMILY: tahoma">private Log logger = LogFactory.getLog(this.getClass());</p><p style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: tahoma"> (tng)</p><p style="FONT-SIZE: 10pt; MARGIN: 0in 0in 0in 0.5in; FONT-FAMILY: tahoma">//the Spring application context</p><p style="FONT-SIZE: 10pt; MARGIN: 0in 0in 0in 0.5in; FONT-FAMILY: tahoma">private ApplicationContext appContext;</p><p style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: tahoma"> (tng)</p><p style="FONT-SIZE: 10pt; MARGIN: 0in 0in 0in 0.5in; FONT-FAMILY: tahoma">//the cached catalog service</p><p style="FONT-SIZE: 10pt; MARGIN: 0in 0in 0in 0.5in; FONT-FAMILY: tahoma">private BlogService blogService;</p><p style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: tahoma"> (tng)</p><p style="FONT-SIZE: 10pt; MARGIN: 0in 0in 0in 0.5in; FONT-FAMILY: tahoma">//the cached user service</p><p style="FONT-SIZE: 10pt; MARGIN: 0in 0in 0in 0.5in; FONT-FAMILY: tahoma">//private UserService userService;</p><p style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: tahoma"> (tng)</p><p style="FONT-SIZE: 10pt; MARGIN: 0in 0in 0in 0.5in; FONT-FAMILY: tahoma">/**</p><p style="FONT-SIZE: 10pt; MARGIN: 0in 0in 0in 0.5in; FONT-FAMILY: tahoma">* Constructor.</p><p style="FONT-SIZE: 10pt; MARGIN: 0in 0in 0in 0.5in; FONT-FAMILY: tahoma">* <p></p><p style="FONT-SIZE: 10pt; MARGIN: 0in 0in 0in 0.5in; FONT-FAMILY: tahoma">* The following steps being done:</p><p style="FONT-SIZE: 10pt; MARGIN: 0in 0in 0in 0.5in; FONT-FAMILY: tahoma">* <ul></p><p style="FONT-SIZE: 10pt; MARGIN: 0in 0in 0in 0.5in; FONT-FAMILY: tahoma">* <li>retrieve Spring application context from servlet context.</p><p style="FONT-SIZE: 10pt; MARGIN: 0in 0in 0in 0.5in; FONT-FAMILY: tahoma">* <li>look up <code>CatalogService</code> from Spring application</p><p style="FONT-SIZE: 10pt; MARGIN: 0in 0in 0in 0.5in; FONT-FAMILY: tahoma">* context.</p><p style="FONT-SIZE: 10pt; MARGIN: 0in 0in 0in 0.5in; FONT-FAMILY: tahoma">* <li>look up <code>UserService</code> from Spring applicatino context.</p><p style="FONT-SIZE: 10pt; MARGIN: 0in 0in 0in 0.5in; FONT-FAMILY: tahoma">* </ul></p><p style="FONT-SIZE: 10pt; MARGIN: 0in 0in 0in 0.5in; FONT-FAMILY: tahoma">*/</p><p style="FONT-SIZE: 10pt; MARGIN: 0in 0in 0in 0.5in; FONT-FAMILY: tahoma">public ServiceLocator()</p><p style="FONT-SIZE: 10pt; MARGIN: 0in 0in 0in 0.5in; FONT-FAMILY: tahoma">{</p><p style="FONT-SIZE: 10pt; MARGIN: 0in 0in 0in 1in; FONT-FAMILY: tahoma">/*InputStream is = getClass().getResourceAsStream("springapp-servlet.xml"); </p><p style="FONT-SIZE: 10pt; MARGIN: 0in 0in 0in 1in; FONT-FAMILY: tahoma">XmlBeanFactory bf = new XmlBeanFactory(is); </p><p style="FONT-SIZE: 10pt; MARGIN: 0in 0in 0in 1in; FONT-FAMILY: tahoma">blogService = (BlogService) bf.getBean("blogService");*/</p><p style="FONT-SIZE: 10pt; MARGIN: 0in 0in 0in 1in; FONT-FAMILY: tahoma"> (tng)</p><p style="FONT-WEIGHT: bold; FONT-SIZE: 10pt; MARGIN: 0in 0in 0in 1in; FONT-FAMILY: tahoma">ServletContext context = ServletActionContext.getServletContext();</p><p style="FONT-WEIGHT: bold; FONT-SIZE: 10pt; MARGIN: 0in 0in 0in 1in; FONT-FAMILY: tahoma">this.appContext = WebApplicationContextUtils.getRequiredWebApplicationContext(context);</p><p style="FONT-WEIGHT: bold; FONT-SIZE: 10pt; MARGIN: 0in 0in 0in 1in; FONT-FAMILY: tahoma">this.blogService = (BlogService)this.lookupService(BLOG_SERVICE_BEAN_NAME);</p><p style="FONT-SIZE: 10pt; MARGIN: 0in 0in 0in 1in; FONT-FAMILY: tahoma"> (tng)</p><p style="FONT-SIZE: 10pt; MARGIN: 0in 0in 0in 1in; FONT-FAMILY: tahoma">/*</p><p style="FONT-SIZE: 10pt; MARGIN: 0in 0in 0in 1in; FONT-FAMILY: tahoma">* this.userService = (UserService)this.lookupService(USER_SERVICE_BEAN_NAME);</p><p style="FONT-SIZE: 10pt; MARGIN: 0in 0in 0in 1in; FONT-FAMILY: tahoma">*/</p><p style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: tahoma"> (tng)</p><p style="FONT-SIZE: 10pt; MARGIN: 0in 0in 0in 0.5in; FONT-FAMILY: tahoma">this.logger.info("Service locator bean is initialized");</p><p style="FONT-SIZE: 10pt; MARGIN: 0in 0in 0in 0.5in; FONT-FAMILY: tahoma">}</p><p style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: tahoma"> (tng)</p><p style="FONT-SIZE: 10pt; MARGIN: 0in 0in 0in 0.5in; FONT-FAMILY: tahoma"> (tng)</p><p style="FONT-SIZE: 10pt; MARGIN: 0in 0in 0in 0.5in; FONT-FAMILY: tahoma">/**</p><p style="FONT-SIZE: 10pt; MARGIN: 0in 0in 0in 0.5in; FONT-FAMILY: tahoma">* Lookup service based on service bean name.</p><p style="FONT-SIZE: 10pt; MARGIN: 0in 0in 0in 0.5in; FONT-FAMILY: tahoma">* </p><p style="FONT-SIZE: 10pt; MARGIN: 0in 0in 0in 0.5in; FONT-FAMILY: tahoma">* @param serviceBeanName the service bean name</p><p style="FONT-SIZE: 10pt; MARGIN: 0in 0in 0in 0.5in; FONT-FAMILY: tahoma">* @return the service bean</p><p style="FONT-SIZE: 10pt; MARGIN: 0in 0in 0in 0.5in; FONT-FAMILY: tahoma">*/</p><p style="FONT-SIZE: 10pt; MARGIN: 0in 0in 0in 0.5in; FONT-FAMILY: tahoma">public Object lookupService(String serviceBeanName)</p><p style="FONT-SIZE: 10pt; MARGIN: 0in 0in 0in 0.5in; FONT-FAMILY: tahoma">{</p><p style="FONT-SIZE: 10pt; MARGIN: 0in 0in 0in 1in; FONT-FAMILY: tahoma">return appContext.getBean(serviceBeanName);</p><p style="FONT-SIZE: 10pt; MARGIN: 0in 0in 0in 0.5in; FONT-FAMILY: tahoma">}</p><p style="FONT-SIZE: 10pt; MARGIN: 0in 0in 0in 0.5in; FONT-FAMILY: tahoma"> (tng)</p><p style="FONT-SIZE: 10pt; MARGIN: 0in 0in 0in 0.5in; FONT-FAMILY: tahoma">/**</p><p style="FONT-SIZE: 10pt; MARGIN: 0in 0in 0in 0.5in; FONT-FAMILY: tahoma">* @return Returns the blogService.</p><p style="FONT-SIZE: 10pt; MARGIN: 0in 0in 0in 0.5in; FONT-FAMILY: tahoma">*/</p><p style="FONT-SIZE: 10pt; MARGIN: 0in 0in 0in 0.5in; FONT-FAMILY: tahoma">public BlogService getBlogService()</p><p style="FONT-SIZE: 10pt; MARGIN: 0in 0in 0in 0.5in; FONT-FAMILY: tahoma">{</p><p style="FONT-SIZE: 10pt; MARGIN: 0in 0in 0in 1in; FONT-FAMILY: tahoma">return blogService;</p><p style="FONT-SIZE: 10pt; MARGIN: 0in 0in 0in 0.5in; FONT-FAMILY: tahoma">}</p><p style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: tahoma">}</p><p style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: tahoma"> (tng)</p><p style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: tahoma"> (tng)</p><p style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: tahoma"> (tng)</p><p style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: tahoma">[in web.xml]</p><p style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: tahoma"> (tng)</p><p style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: tahoma"><context-param></p><p style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: tahoma"><param-name>contextConfigLocation</param-name></p><p style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: tahoma"><param-value>/WEB-INF/daoContext.xml /WEB-INF/applicationContext.xml</param-value></p><p style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: tahoma"></context-param></p><p style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: tahoma"><listener></p><p style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: tahoma"><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></p><p style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: tahoma"></listener></p><p style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: tahoma"><!-- OR USE THE CONTEXTLOADERSERVLET INSTEAD OF THE LISTENER</p><p style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: tahoma"><servlet></p><p style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: tahoma"><servlet-name>context</servlet-name></p><p style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: tahoma"><servlet-class>org.springframework.web.context.ContextLoaderServlet</servlet-class></p><p style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: tahoma"><load-on-startup>1</load-on-startup></p><p style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: tahoma"></servlet></p><p style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: tahoma">--></p><img src ="http://m.tkk7.com/junky/aggbug/75601.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/junky/" target="_blank">junky</a> 2006-10-17 14:06 <a href="http://m.tkk7.com/junky/archive/2006/10/17/75601.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Ajax资源 or Ajax Resourceshttp://m.tkk7.com/junky/archive/2006/06/04/50368.htmljunkyjunkySun, 04 Jun 2006 15:23:00 GMThttp://m.tkk7.com/junky/archive/2006/06/04/50368.htmlhttp://m.tkk7.com/junky/comments/50368.htmlhttp://m.tkk7.com/junky/archive/2006/06/04/50368.html#Feedback0http://m.tkk7.com/junky/comments/commentRss/50368.htmlhttp://m.tkk7.com/junky/services/trackbacks/50368.html
资源Q-Q-中文
1 Ajax中国
 (tng) (tng)  (tng)http://www.okajax.com/
2 Java 开源大?br /> (tng) (tng)  (tng)http://www.open-open.com/

3 安全矩阵QSecurity MatrixQ官方网?br /> (tng) (tng)  (tng)http://www.smatrix.org/
4 TechTarget IT专家|-QAjax_IT专家|_Web服务
 (tng) (tng)  (tng)http://searchwebservices.techtarget.com.cn/wsdev/ajax/
5 |易学院
 (tng) (tng)  (tng)http://tech.163.com/special/c/0009159F/codeother.html
6 Java 视线论坛
 (tng) (tng)  (tng)http://forum.javaeye.com/


ResourcesQ-Q-English

1 AJAX开发h员的~译模式:
 (tng) (tng)  (tng)http://www.ajaxpatterns.org
2 (tng) XMLHttpRequest教程Q“动态网|口?
 (tng) (tng)  (tng)http://www.xml.com/pub/a/2005/02/09/xml-http-request.html
3 JavaScript性能基准:
 (tng) (tng)  (tng)http://blogs.ebusiness-apps.com/dave/?p=14
4 AJAX资源:
 (tng) (tng)  (tng)http://www.ajaxmatters.com
5 JavaScript规范:
 (tng) (tng)  (tng)http://www.ecma-international.org/publications/standards/Ecma-262.htm
6 介绍JavaScript对象标识:
 (tng) (tng)  (tng)http://www.crockford.com/JSON/index.html
7 (tng) Mozilla 的Venkman JavaScript调试?
 (tng) (tng)  (tng)http://www.mozilla.org/projects/venkman/
8 (tng) XML DOM参?
 (tng) (tng) (tng) (tng) (tng) http://msdn.microsoft.com/library/default.asp?url=/library/en-us/xmlsdk/html/e9da2722-7879-4e48-869c-7f16714e2824.asp
9 Microsoft Dynamic HTML reference:
 (tng) (tng)  (tng)http://msdn.microsoft.com/library/default.asp?url=/workshop/author/dhtml/reference/dhtml_reference_entry.asp
10 Gecko DOM Reference:
 (tng) (tng) (tng) (tng) (tng) http://www.mozilla.org/docs/dom/domref/
11 "“移植IE应用到Mozilla?br /> (tng) (tng)  (tng)http://www-128.ibm.com/developerworks/web/library/wa-ie2mozgd/
12 Mozilla XUL reference:
 (tng) (tng)  (tng)http://www.xulplanet.com/
13 Microsoft XAML reference:
 (tng) (tng)  (tng)http://windowssdk.msdn.microsoft.com/library/default.asp?url=/library/en-us/wcp_conceptual/html/0ff5f36e-dd84-44d1-aa3e- (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)  (tng)

5bb4f147b169.asp?frame=true
14 James Jesses Garret introduced the term AJAX in his article "AJAX: A New Approach to Web Applications," (Adaptive Path, February 2005):

“AJAXQ新的网应用开发方式?br /> (tng) (tng)  (tng)http://www.adaptivepath.com/publications/essays/archives/000385.php
15 JetBrains IntelliJ IDEA:
 (tng) (tng)  (tng)http://www.jetbrains.com/
16 Microsoft Visual Studio:
 (tng) (tng)  (tng)http://msdn.microsoft.com/vstudio/
17 JSEditor:
 (tng) (tng)  (tng)http://jseditor.sourceforge.net/
18 JSEclipse:
 (tng) (tng)  (tng)http://www.interaktonline.com/Products/Eclipse/JSEclipse/Overview/
19 ActiveState Komodo:
 (tng) (tng)  (tng)http://www.activestate.com/Products/Komodo/
20 XHTML:
 (tng) (tng)  (tng)http://www.w3.org/TR/xhtml1/
21 Document Object Model:
 (tng) (tng)  (tng)http://www.w3.org/DOM/
22 Cascading Style Sheets:
 (tng) (tng)  (tng)http://www.w3.org/Style/CSS/
23 Extensible Stylesheet Language:
 (tng) (tng)  (tng)http://www.w3.org/Style/XSL/
24 XForms:
 (tng) (tng)  (tng)http://www.w3.org/MarkUp/Forms/
25 Scaling Vector Graphics:
 (tng) (tng)  (tng)http://www.w3.org/Graphics/SVG/
26 XPath:
 (tng) (tng)  (tng)http://www.w3.org/TR/xpath
27 AJAX.Net:
 (tng) (tng)  (tng)http://ajax.schwarz-interactive.de/csharpsample/default.aspx
28 Backbase:
 (tng) (tng)  (tng)http://www.backbase.com
29 Bitkraft:
 (tng) (tng)  (tng)http://www.tiggrbitz.com/
30 Django:
 (tng) (tng)  (tng)http://www.djangoproject.com/
31 Dojo:
 (tng) (tng)  (tng)http://www.dojotoolkit.org/
32 DWR (Direct Web Reporting):
 (tng) (tng)  (tng)http://getahead.ltd.uk/dwr/
33 MochiKit:
 (tng) (tng)  (tng)http://mochikit.com/
34 Prototype:
 (tng) (tng)  (tng)http://prototype.conio.net/
35 Rico:
 (tng) (tng)  (tng)http://openrico.org/rico/home.page
36 Sajax:
 (tng) (tng)  (tng)http://www.modernmethod.com/sajax/
37 Sarissa:
 (tng) (tng)  (tng)http://sarissa.sourceforge.net/doc/
38 Script.aculo.us:
 (tng) (tng)  (tng)http://script.aculo.us/
39 Ruby on Rails:
 (tng) (tng)  (tng)http://www.rubyonrails.org/
40 For more on AJAX and DWR, read "AJAX Made Simple with DWR," Cloves Carneiro Jr. (JavaWorld, June 2005): 关于AJAX和DWRQ请阅读“AJAX使用DWR?br />
单?br /> (tng) (tng)  (tng)http://www.javaworld.com/javaworld/jw-06-2005/jw-0620-dwr.html
41 For more articles on Java development tools, browse the Development Tools section of JavaWorld’s Topical Index: 更多Java开发工L(fng)文章Q请

览JavaWorld的开发工具部分烦(ch)引页
 (tng) (tng)  (tng)http://www.javaworld.com/channel_content/jw-tools-index.shtml
42 For more articles on XML, browse the Java and XML section of JavaWorld’s Topical Index: 更多XML的文章,h览JavaWorld的Java和XML部分索引?br /> (tng) (tng)  (tng)http://www.javaworld.com/channel_content/jw-xml-index.shtml
43 For more articles on UI design, browse the User Interface Design section of JavaWorld’s Topical Index: 更多UI设计的文章,h览JavaWorld?br />
UI设计部分索引?br /> (tng) (tng)  (tng)http://www.javaworld.com/channel_content/jw-ui-index.shtml


junky 2006-06-04 23:23 发表评论
]]>
Spring in Action W记V -- 使用Spring来发邮g和执行定时Q?http://m.tkk7.com/junky/archive/2006/05/31/49357.htmljunkyjunkyWed, 31 May 2006 15:04:00 GMThttp://m.tkk7.com/junky/archive/2006/05/31/49357.htmlhttp://m.tkk7.com/junky/comments/49357.htmlhttp://m.tkk7.com/junky/archive/2006/05/31/49357.html#Feedback2http://m.tkk7.com/junky/comments/commentRss/49357.htmlhttp://m.tkk7.com/junky/services/trackbacks/49357.html阅读全文

junky 2006-05-31 23:04 发表评论
]]>
Spring in Action W记(III) -- 在Spring下的Hibernate操作数据?/title><link>http://m.tkk7.com/junky/archive/2006/05/29/48849.html</link><dc:creator>junky</dc:creator><author>junky</author><pubDate>Mon, 29 May 2006 15:20:00 GMT</pubDate><guid>http://m.tkk7.com/junky/archive/2006/05/29/48849.html</guid><wfw:comment>http://m.tkk7.com/junky/comments/48849.html</wfw:comment><comments>http://m.tkk7.com/junky/archive/2006/05/29/48849.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/junky/comments/commentRss/48849.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/junky/services/trackbacks/48849.html</trackback:ping><description><![CDATA[ <p align="center"> <strong>Spring in Action W记(III)</strong> </p> <p>By: icess blog: <a ><font color="#002c99">http://blog.matrix.org.cn/page/icess</font></a></p> <p>q次来看看用Spring的Hibernate模板来操作数? Spring提供?jin)Hibernate的一层包?使Hibernate使用h更加方便,其是结合Hibernate Annotation? 配置文g更少,l护更加? 下面来看看吧.</p> <p>下面是一个测试数据实体类<font color="#000000"><code style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New', Courier">TestData.java 和前一提到的实体cM?只不q用?jin)Annotation注释. (tng)</code></font></p> <p> <code style="FONT-SIZE: 10pt; MARGIN: 0px; FONT-FAMILY: 'Courier New', Courier"> <font color="#7f0055"> <b>package (tng)</b> </font> <font color="#000000">test.orm.hibernate.model;</font> <br /> <br /> <font color="#7f0055"> <b>import (tng)</b> </font> <font color="#000000">javax.persistence.Basic;</font> <br /> <font color="#7f0055"> <b>import (tng)</b> </font> <font color="#000000">javax.persistence.Entity;</font> <br /> <font color="#7f0055"> <b>import (tng)</b> </font> <font color="#000000">javax.persistence.Id;</font> <br /> <font color="#7f0055"> <b>import (tng)</b> </font> <font color="#000000">javax.persistence.Table;</font> <br /> <br /> <br /> <font color="#000000">@Entity</font> <br /> <font color="#000000">@Table(name (tng)= (tng)</font> <font color="#2a00ff">"test"</font> <font color="#000000">,schema (tng)= (tng)</font> <font color="#2a00ff">"APP"</font> <font color="#000000">)</font> <br /> <font color="#7f0055"> <b>public (tng)class (tng)</b> </font> <font color="#000000">TestData (tng){</font> <br /> <font color="#ffffff"> (tng) (tng)</font> <font color="#7f0055"> <b>private (tng)int (tng)</b> </font> <font color="#000000">id;</font> <br /> <font color="#ffffff"> (tng) (tng)</font> <font color="#7f0055"> <b>private (tng)</b> </font> <font color="#000000">String (tng)name;</font> <br /> <font color="#ffffff"> (tng) (tng)</font> <font color="#7f0055"> <b>public (tng)</b> </font> <font color="#000000">TestData(</font> <font color="#7f0055"> <b>int (tng)</b> </font> <font color="#000000">id, (tng)String (tng)name) (tng){</font> <br /> <font color="#ffffff"> (tng) (tng) (tng) (tng)</font> <font color="#7f0055"> <b>this</b> </font> <font color="#000000">.id (tng)= (tng)id;</font> <br /> <font color="#ffffff"> (tng) (tng) (tng) (tng)</font> <font color="#7f0055"> <b>this</b> </font> <font color="#000000">.name (tng)= (tng)name;</font> <br /> <font color="#ffffff"> (tng) (tng)</font> <font color="#000000">}</font> <br /> <font color="#ffffff"> (tng) (tng)</font> <font color="#7f0055"> <b>public (tng)</b> </font> <font color="#000000">TestData() (tng){}</font> <br /> <font color="#ffffff"> (tng) (tng)</font> <br /> <font color="#ffffff"> (tng) (tng)</font> <font color="#000000">@Id</font> <br /> <font color="#ffffff"> (tng) (tng)</font> <font color="#7f0055"> <b>public (tng)int (tng)</b> </font> <font color="#000000">getId() (tng){</font> <br /> <font color="#ffffff"> (tng) (tng) (tng) (tng)</font> <font color="#7f0055"> <b>return (tng)</b> </font> <font color="#000000">id;</font> <br /> <font color="#ffffff"> (tng) (tng)</font> <font color="#000000">}</font> <br /> <font color="#ffffff"> (tng) (tng)</font> <font color="#7f0055"> <b>public (tng)void (tng)</b> </font> <font color="#000000">setId(</font> <font color="#7f0055"> <b>int (tng)</b> </font> <font color="#000000">id) (tng){</font> <br /> <font color="#ffffff"> (tng) (tng) (tng) (tng)</font> <font color="#7f0055"> <b>this</b> </font> <font color="#000000">.id (tng)= (tng)id;</font> <br /> <font color="#ffffff"> (tng) (tng)</font> <font color="#000000">}</font> <br /> <font color="#ffffff"> (tng) (tng)</font> <font color="#000000">@Basic</font> <br /> <font color="#ffffff"> (tng) (tng)</font> <font color="#7f0055"> <b>public (tng)</b> </font> <font color="#000000">String (tng)getName() (tng){</font> <br /> <font color="#ffffff"> (tng) (tng) (tng) (tng)</font> <font color="#7f0055"> <b>return (tng)</b> </font> <font color="#000000">name;</font> <br /> <font color="#ffffff"> (tng) (tng)</font> <font color="#000000">}</font> <br /> <font color="#ffffff"> (tng) (tng)</font> <font color="#7f0055"> <b>public (tng)void (tng)</b> </font> <font color="#000000">setName(String (tng)name) (tng){</font> <br /> <font color="#ffffff"> (tng) (tng) (tng) (tng)</font> <font color="#7f0055"> <b>this</b> </font> <font color="#000000">.name (tng)= (tng)name;</font> <br /> <font color="#ffffff"> (tng) (tng)</font> <font color="#000000">}</font> <br /> <font color="#000000">}</font> </code> </p> <p>下面是测试Hibernate模板的类, <font color="#000000"><code style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New', Courier">TestHibernateTemplate.java</code></font></p> <p> <code style="FONT-SIZE: 10pt; MARGIN: 0px; FONT-FAMILY: 'Courier New', Courier"> <font color="#7f0055"> <b>package (tng)</b> </font> <font color="#000000">test.orm.hibernate;</font> <br /> <br /> <font color="#7f0055"> <b>import (tng)</b> </font> <font color="#000000">java.sql.SQLException;</font> <br /> <br /> <font color="#7f0055"> <b>import (tng)</b> </font> <font color="#000000">org.hibernate.HibernateException;</font> <br /> <font color="#7f0055"> <b>import (tng)</b> </font> <font color="#000000">org.hibernate.Session;</font> <br /> <font color="#7f0055"> <b>import (tng)</b> </font> <font color="#000000">org.springframework.orm.hibernate3.HibernateCallback;</font> <br /> <font color="#7f0055"> <b>import (tng)</b> </font> <font color="#000000">org.springframework.orm.hibernate3.HibernateTemplate;</font> <br /> <br /> <font color="#7f0055"> <b>import (tng)</b> </font> <font color="#000000">test.orm.hibernate.model.TestData;</font> <br /> <br /> <br /> <font color="#7f0055"> <b>public (tng)class (tng)</b> </font> <font color="#000000">TestHibernateTemplate (tng){</font> <br /> <font color="#ffffff"> (tng) (tng)</font> <font color="#7f0055"> <b>private (tng)</b> </font> <font color="#000000">HibernateTemplate (tng)hibernateTemplate;</font> <br /> <font color="#ffffff"> (tng) (tng)</font> <br /> <font color="#ffffff"> (tng) (tng)</font> <font color="#7f0055"> <b>public (tng)</b> </font> <font color="#000000">TestHibernateTemplate() (tng){}</font> <br /> <br /> <font color="#ffffff"> (tng) (tng)</font> <font color="#7f0055"> <b>public (tng)</b> </font> <font color="#000000">HibernateTemplate (tng)getHibernateTemplate() (tng){</font> <br /> <font color="#ffffff"> (tng) (tng) (tng) (tng)</font> <font color="#7f0055"> <b>return (tng)</b> </font> <font color="#000000">hibernateTemplate;</font> <br /> <font color="#ffffff"> (tng) (tng)</font> <font color="#000000">}</font> <br /> <br /> <font color="#ffffff"> (tng) (tng)</font> <font color="#7f0055"> <b>public (tng)void (tng)</b> </font> <font color="#000000">setHibernateTemplate(HibernateTemplate (tng)hibernateTemplate) (tng){</font> <br /> <font color="#ffffff"> (tng) (tng) (tng) (tng)</font> <font color="#7f0055"> <b>this</b> </font> <font color="#000000">.hibernateTemplate (tng)= (tng)hibernateTemplate;</font> <br /> <font color="#ffffff"> (tng) (tng)</font> <font color="#000000">}</font> <br /> <font color="#ffffff"> (tng) (tng)</font> <br /> <font color="#ffffff"> (tng) (tng)</font> <font color="#3f7f5f">//试使用HibernateTemplate来操作数?/font> <br /> <font color="#ffffff"> (tng) (tng)</font> <font color="#7f0055"> <b>public (tng)</b> </font> <font color="#000000">TestData (tng)getTestData(</font> <font color="#7f0055"> <b>final (tng)int (tng)</b> </font> <font color="#000000">id) (tng){</font> <br /> <font color="#ffffff"> (tng) (tng) (tng) (tng)</font> <font color="#7f0055"> <b>return (tng)</b> </font> <font color="#000000">(TestData) (tng)hibernateTemplate.execute(</font> <font color="#7f0055"> <b>new (tng)</b> </font> <font color="#000000">HibernateCallback() (tng){</font> <br /> <br /> <font color="#ffffff"> (tng) (tng) (tng) (tng) (tng) (tng)</font> <font color="#7f0055"> <b>public (tng)</b> </font> <font color="#000000">Object (tng)doInHibernate(Session (tng)s) (tng)</font> <font color="#7f0055"> <b>throws (tng)</b> </font> <font color="#000000">HibernateException, (tng)SQLException (tng){</font> <br /> <font color="#ffffff"> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)</font> <font color="#3f7f5f">// (tng)TODO (tng)Auto-generated (tng)method (tng)stub</font> <br /> <font color="#ffffff"> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)</font> <font color="#7f0055"> <b>return (tng)</b> </font> <font color="#000000">s.get(TestData.class, (tng)id);</font> <br /> <font color="#ffffff"> (tng) (tng) (tng) (tng) (tng) (tng)</font> <font color="#000000">}</font> <br /> <font color="#ffffff"> (tng) (tng) (tng) (tng) (tng) (tng)</font> <br /> <font color="#ffffff"> (tng) (tng) (tng) (tng)</font> <font color="#000000">});</font> <br /> <font color="#ffffff"> (tng) (tng)</font> <font color="#000000">}</font> <br /> <font color="#3f7f5f">// (tng) (tng)上面查询数据的方法?tng)用?jin)HibernateCallBack接口,对于q样单的查询,可以使用下面由HibernateTemplate (tng)提供的更单的Ҏ(gu)</font> <br /> <font color="#ffffff"> (tng) (tng)</font> <font color="#7f0055"> <b>public (tng)</b> </font> <font color="#000000">TestData (tng)getTestData2(</font> <font color="#7f0055"> <b>final (tng)int (tng)</b> </font> <font color="#000000">id) (tng){</font> <br /> <font color="#ffffff"> (tng) (tng) (tng) (tng)</font> <font color="#7f0055"> <b>return (tng)</b> </font> <font color="#000000">(TestData) (tng)hibernateTemplate.get(TestData.class, (tng)id);</font> <br /> <font color="#ffffff"> (tng) (tng)</font> <font color="#000000">}</font> <br /> <font color="#ffffff"> (tng) (tng)</font> <font color="#3f7f5f">/* (tng)如果上面的两处方法用Load (tng)Ҏ(gu)的时, (tng)抛出延迟加蝲属性异? (tng)Spring理Session的问? (tng)应该是Spring用完Session (tng)然后关闭了(jin),</font> <br /> <font color="#ffffff"> (tng) (tng) (tng)</font> <font color="#3f7f5f">* (tng)所以不可以延迟加蝲, (tng)也就不可以用load (tng)Ҏ(gu)?,????? (tng)Z????*/</font> <br /> <font color="#ffffff"> (tng) (tng)</font> <br /> <font color="#ffffff"> (tng) (tng)</font> <font color="#3f7f5f">// (tng)其他操作数据Ҏ(gu) (tng)? (tng)插入,修改.... (tng)和用Hibernate (tng)session (tng)差不? (tng)HibernateTemplate只是Session的包?/font> <br /> <font color="#000000">}</font> </code> </p> <p>可以看到使用Hibernate模板来操作数?是多么简? </p> <p>注意: 上面注释?提到?jin)在使用LoadҎ(gu)时??x)有问? Session in view 时候用load是不?x)出问题? q里Spring提供的方法应该是按照Hibernate的语义写的吧.</p> <p>下面是用来试上面的类是否正常工作的测试类?<font color="#000000"><code style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New', Courier">TestApp.java</code></font></p> <p> <code style="FONT-SIZE: 10pt; MARGIN: 0px; FONT-FAMILY: 'Courier New', Courier"> <font color="#7f0055"> <b>package (tng)</b> </font> <font color="#000000">test.orm.hibernate;</font> <br /> <br /> <font color="#7f0055"> <b>import (tng)</b> </font> <font color="#000000">org.springframework.context.ApplicationContext;</font> <br /> <font color="#7f0055"> <b>import (tng)</b> </font> <font color="#000000">org.springframework.context.support.ClassPathXmlApplicationContext;</font> <br /> <br /> <font color="#7f0055"> <b>import (tng)</b> </font> <font color="#000000">test.jdbc.DatabaseUtils;</font> <br /> <font color="#7f0055"> <b>import (tng)</b> </font> <font color="#000000">test.orm.hibernate.model.TestData;</font> <br /> <br /> <font color="#7f0055"> <b>public (tng)class (tng)</b> </font> <font color="#000000">TestApp (tng){</font> <br /> <br /> <font color="#ffffff"> (tng) (tng)</font> <font color="#3f5fbf">/**</font> <br /> <font color="#ffffff"> (tng) (tng) (tng)</font> <font color="#3f5fbf">* (tng)</font> <font color="#7f9fbf">@param (tng)</font> <font color="#3f5fbf">args</font> <br /> <font color="#ffffff"> (tng) (tng) (tng)</font> <font color="#3f5fbf">*/</font> <br /> <font color="#ffffff"> (tng) (tng)</font> <font color="#7f0055"> <b>public (tng)static (tng)void (tng)</b> </font> <font color="#000000">main(String[] (tng)args) (tng){</font> <br /> <font color="#ffffff"> (tng) (tng) (tng) (tng)</font> <font color="#3f7f5f">// (tng)TODO (tng)Auto-generated (tng)method (tng)stub</font> <br /> <font color="#ffffff"> (tng) (tng) (tng) (tng)</font> <font color="#000000">DatabaseUtils (tng)dataUtils (tng)= (tng)</font> <font color="#7f0055"> <b>new (tng)</b> </font> <font color="#000000">DatabaseUtils();</font> <br /> <font color="#ffffff"> (tng) (tng) (tng) (tng)</font> <font color="#000000">dataUtils.connect();</font> <br /> <font color="#ffffff"> (tng) (tng) (tng) (tng)</font> <font color="#000000">System.out.println(</font> <font color="#2a00ff">"Open (tng)database:!"</font> <font color="#000000">);</font> <br /> <font color="#ffffff"> (tng) (tng) (tng) (tng)</font> <font color="#000000">ApplicationContext (tng)context (tng)= (tng)</font> <font color="#7f0055"> <b>new (tng)</b> </font> <font color="#000000">ClassPathXmlApplicationContext(</font> <font color="#2a00ff">"test/orm/hibernate/spring-hibernate.xml"</font> <font color="#000000">);</font> <br /> <font color="#ffffff"> (tng) (tng) (tng) (tng)</font> <br /> <font color="#ffffff"> (tng) (tng) (tng) (tng)</font> <font color="#000000">TestHibernateTemplate (tng)hibernateTemplate (tng)= (tng)(TestHibernateTemplate) (tng)context.getBean(</font> <font color="#2a00ff">"testDao"</font> <font color="#000000">);</font> <br /> <font color="#ffffff"> (tng) (tng) (tng) (tng)</font> <br /> <font color="#ffffff"> (tng) (tng) (tng) (tng)</font> <font color="#000000">System.out.println(</font> <font color="#2a00ff">"name (tng): (tng)" (tng)</font> <font color="#000000">);</font> <br /> <font color="#ffffff"> (tng) (tng) (tng) (tng)</font> <font color="#000000">TestData (tng)data (tng)= (tng)hibernateTemplate.getTestData(</font> <font color="#990000">9</font> <font color="#000000">);</font> <br /> <font color="#ffffff"> (tng) (tng) (tng) (tng)</font> <font color="#000000">System.out.println(</font> <font color="#2a00ff">"name (tng): (tng)" (tng)</font> <font color="#000000">+ (tng)data.getName());</font> <br /> <font color="#ffffff"> (tng) (tng) (tng) (tng)</font> <font color="#000000">data (tng)= (tng)hibernateTemplate.getTestData2(</font> <font color="#990000">3</font> <font color="#000000">);</font> <br /> <font color="#ffffff"> (tng) (tng) (tng) (tng)</font> <font color="#000000">System.out.println(</font> <font color="#2a00ff">"name (tng)2: (tng)" (tng)</font> <font color="#000000">+ (tng)data.getName());</font> <br /> <font color="#ffffff"> (tng) (tng) (tng) (tng)</font> <br /> <font color="#ffffff"> (tng) (tng) (tng) (tng)</font> <br /> <font color="#ffffff"> (tng) (tng) (tng) (tng)</font> <font color="#000000">dataUtils.disconnect();</font> <br /> <font color="#ffffff"> (tng) (tng) (tng) (tng)</font> <br /> <font color="#ffffff"> (tng) (tng)</font> <font color="#000000">}</font> <br /> <br /> <font color="#000000">}</font> </code> </p> <p> </p> <p>注意: 本测试中用到?jin)上一用到?font color="#000000"><code style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New', Courier">DatabaseUtils.java 工具cL操作Derby数据?</code></font></p> <p> <code> <font size="2"> <span style="FONT-FAMILY: 'Courier New', Courier">?/span> </font> </code> <font color="#000000"> <code style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New', Courier">以上实例可以看出,在Spring中用Hibernate,效率更高?sh)? 你不q样认ؓ(f)?</code> </font> </p> <p> <code> <font size="2"> <span style="FONT-FAMILY: 'Courier New', Courier">同时</span> </font> </code> <font color="#000000"> <code style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New', Courier">Spring也提供了(jin) JDO{其他一些数据操作框架的包装,使用上基本上 (tng)是一L(fng)q里׃在详qC(jin).</code> </font> </p> <p> <code> <font size="2"> <span style="FONT-FAMILY: 'Courier New', Courier">下一ơ我们来看看Spring的I18N处理,和自定义属性编辑器的实?</span> </font> </code> </p> <img src ="http://m.tkk7.com/junky/aggbug/48849.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/junky/" target="_blank">junky</a> 2006-05-29 23:20 <a href="http://m.tkk7.com/junky/archive/2006/05/29/48849.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Spring in Action W记 (IV) -- i18n问题和自定义属性编辑器http://m.tkk7.com/junky/archive/2006/05/29/48846.htmljunkyjunkyMon, 29 May 2006 15:19:00 GMThttp://m.tkk7.com/junky/archive/2006/05/29/48846.htmlhttp://m.tkk7.com/junky/comments/48846.htmlhttp://m.tkk7.com/junky/archive/2006/05/29/48846.html#Feedback0http://m.tkk7.com/junky/comments/commentRss/48846.htmlhttp://m.tkk7.com/junky/services/trackbacks/48846.htmlSpring in Action W记 (tng)(IV) -- i18n问题和自定义属性编辑器

 (tng) BY: icess Blog: http://blog.matrix.org.cn/page/icess (tng)

 (tng) (tng) 在Spring中处理I18N问题和用Java里面的类基本上是一L(fng).使用org.springframework.context.support.ResourceBundleMessageSource

然后注入资源文g(一个名字ؓ(f)basename的属?,然后可以在Context中用资源文件了(jin), 如下Z个配|示? test.xml

<?

xml version = "1.0" encoding = "UTF-8" ?>

<!

DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "spring-beans.dtd" >

<

beans >

< bean id = "messageSource" class = "org.springframework.context.support.ResourceBundleMessageSource" >

< property name = "basename" >

<!-- 注意此处讄 资源 名字 和\?-->

< value > test/i18n/test </ value >

</ property >

</ bean >

</

beans >

下面源文?test.properties

name =

\u51B0\u96E8

sex =

\u5148\u751F

test_zh.properties

name =

\u51B0\u96E8

sex =

\u5148\u751F

test_en_US.properties

name =

ice rain

sex =

male

下面是一个简单的试c?

package

test.i18n;

import

java.util.Locale;

import

org.springframework.context.ApplicationContext;

import

org.springframework.context.support.ClassPathXmlApplicationContext;

public

class TestI18n {

/**

* @param args

*/

 (tng) public static void main(String[] args) {

 (tng) (tng) (tng) // TODO Auto-generated method stub

 (tng) (tng) (tng) ApplicationContext context =

new ClassPathXmlApplicationContext( "test/i18n/test.xml" );

 (tng) (tng) (tng) String text = context.getMessage(

"sex" , new Object[0], Locale. US );

 (tng) (tng) (tng) String textZH = context.getMessage(

"sex" , new Object[0], Locale. CHINA );

 (tng) (tng) (tng) System.

out .println(text + " 中文:" +textZH);

 (tng) }

}

很简?q样可以了(jin).

下面来看看Spring中的属性自定义~辑?q个和Hibernate中的自定义属性差不多 ? 例如下面我们要看C(jin)例子,映射一个电(sh)话号??font size="2">areaCode,prefix?number, 如果不用自定义属性编辑器那么p分别注入上面?个代?ȝ(ch). 如果使用自定义属性编辑器,直接注入一?分开的数字序列就可以??/p>

888-666-9999

.在下面的例子中的Contact.javacL个PhoneNumber属?里面保存?sh)(jin)上面?个代?两个cȝ代码如下:

package (tng) test.propertyEditor;

public (tng)class (tng) Contact (tng){
 (tng) (tng) private (tng) PhoneNumber (tng)phoneNumber;
 (tng) (tng) private (tng) String (tng)name;
 (tng) (tng)
 (tng) (tng) public (tng) Contact() (tng){}
 (tng) (tng)
 (tng) (tng) public (tng) String (tng)getName() (tng){
 (tng) (tng) (tng) (tng) return (tng) name;
 (tng) (tng) }

 (tng) (tng) public (tng)void (tng) setName(String (tng)name) (tng){
 (tng) (tng) (tng) (tng) this .name (tng)= (tng)name;
 (tng) (tng) }

 (tng) (tng) public (tng) PhoneNumber (tng)getPhoneNumber() (tng){
 (tng) (tng) (tng) (tng) return (tng) phoneNumber;
 (tng) (tng) }

 (tng) (tng) public (tng)void (tng) setPhoneNumber(PhoneNumber (tng)phoneNumber) (tng){
 (tng) (tng) (tng) (tng) this .phoneNumber (tng)= (tng)phoneNumber;
 (tng) (tng) }
 (tng) (tng)
}

PhoneNumber.java

package (tng) test.propertyEditor;

public (tng)class (tng) PhoneNumber (tng){
 (tng) (tng) private (tng) String (tng)areaCode;
 (tng) (tng) private (tng) String (tng)prefix;
 (tng) (tng) private (tng) String (tng)number;
 (tng) (tng) public (tng) PhoneNumber() (tng){
 (tng) (tng) (tng) (tng)
 (tng) (tng) }
 (tng) (tng) public (tng) PhoneNumber(String (tng)areaCode,String (tng)prefix,String (tng)number) (tng){
 (tng) (tng) (tng) (tng) this .areaCode (tng)= (tng)areaCode;
 (tng) (tng) (tng) (tng) this .prefix (tng)= (tng)prefix;
 (tng) (tng) (tng) (tng) this .number (tng)= (tng)number;
 (tng) (tng) }
 (tng) (tng) public (tng) String (tng)getAreaCode() (tng){
 (tng) (tng) (tng) (tng) return (tng) areaCode;
 (tng) (tng) }
 (tng) (tng) public (tng)void (tng) setAreaCode(String (tng)areaCode) (tng){
 (tng) (tng) (tng) (tng) this .areaCode (tng)= (tng)areaCode;
 (tng) (tng) }
 (tng) (tng) public (tng) String (tng)getNumber() (tng){
 (tng) (tng) (tng) (tng) return (tng) number;
 (tng) (tng) }
 (tng) (tng) public (tng)void (tng) setNumber(String (tng)number) (tng){
 (tng) (tng) (tng) (tng) this .number (tng)= (tng)number;
 (tng) (tng) }
 (tng) (tng) public (tng) String (tng)getPrefix() (tng){
 (tng) (tng) (tng) (tng) return (tng) prefix;
 (tng) (tng) }
 (tng) (tng) public (tng)void (tng) setPrefix(String (tng)prefix) (tng){
 (tng) (tng) (tng) (tng) this .prefix (tng)= (tng)prefix;
 (tng) (tng) }
}

然后定义一个用来编辑PhoneNumber的编辑器PhoneEditor.java 如下:

package (tng) test.propertyEditor;

import (tng) java.beans.PropertyEditorSupport;

public (tng)class (tng) PhoneEditor (tng) extends (tng) PropertyEditorSupport (tng){
 (tng) (tng) public (tng)void (tng) setAsText(String (tng)textValue) (tng){
 (tng) (tng) (tng) (tng) String (tng)stripped (tng)= (tng)stripNonNumber(textValue);
 (tng) (tng) (tng) (tng)
 (tng) (tng) (tng) (tng) String (tng)areaCode (tng)= (tng)stripped.substring( 0 , 3 );
 (tng) (tng) (tng) (tng) String (tng)prefix (tng)= (tng)stripped.substring( 3 , 6 );
 (tng) (tng) (tng) (tng) String (tng)number (tng)= (tng)stripped.substring( 6 );
 (tng) (tng) (tng) (tng) PhoneNumber (tng)phone (tng)= (tng) new (tng) PhoneNumber(areaCode,prefix,number);
 (tng) (tng) (tng) (tng)
 (tng) (tng) (tng) (tng) setValue(phone);
 (tng) (tng) }
 (tng) (tng)
 (tng) (tng) private (tng) String (tng)stripNonNumber(String (tng)original) (tng){
 (tng) (tng) (tng) (tng) StringBuilder (tng)allNumeric (tng)= (tng) new (tng) StringBuilder();
 (tng) (tng) (tng) (tng)
 (tng) (tng) (tng) (tng) for ( int (tng) i (tng)= (tng) 0 ; (tng)i (tng)< (tng)original.length(); (tng)i (tng)++) (tng){
 (tng) (tng) (tng) (tng) (tng) (tng) char (tng) c (tng)= (tng)original.charAt(i);
 (tng) (tng) (tng) (tng) (tng) (tng) if (Character.isDigit(c)) (tng){
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) allNumeric.append(c);
 (tng) (tng) (tng) (tng) (tng) (tng) }
 (tng) (tng) (tng) (tng) }
 (tng) (tng) (tng) (tng) return (tng) allNumeric.toString();
 (tng) (tng) }
}

l承java里面的属性编辑器,实现里面的一个方法就可以? 下面是在配|文件中注册该编辑器.如下:

testPropertyEditor.xml

<?

xml version = "1.0" encoding = "UTF-8" ?>

<!

DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "spring-beans.dtd" >

<

beans >

< bean id = "customEditorConfigurer" class = "org.springframework.beans.factory.config.CustomEditorConfigurer" >

< property name = "customEditors" >

< map >

< entry key = "test.propertyEditor.PhoneNumber" >

< bean id = "phoneEditor" class = "test.propertyEditor.PhoneEditor" ></ bean >

</ entry >

</ map >

</ property >

</ bean >

<!-- 如果不注册上面自定义Editor的实? 需要注册一个PhoneNumber的bean,讄其属性然后再注册

Contact的PhoneNumber的属?/p>

-->

< bean id = "contact" class = "test.propertyEditor.Contact" >

< property name = "phoneNumber" >

< value > 888-666-9999 </ value >

</ property >

</ bean >

</

beans >

最后来试一下注册的l果是否正确:

package (tng) test.propertyEditor;

import (tng) org.springframework.context.ApplicationContext;
import (tng) org.springframework.context.support.ClassPathXmlApplicationContext;

public (tng)class (tng) TestPropertyEditor (tng){

 (tng) (tng) /**
 (tng) (tng) (tng) * (tng) @param (tng) args
 (tng) (tng) (tng) */
 (tng) (tng) public (tng)static (tng)void (tng) main(String[] (tng)args) (tng){
 (tng) (tng) (tng) (tng) // (tng)TODO (tng)Auto-generated (tng)method (tng)stub
 (tng) (tng) (tng) (tng) ApplicationContext (tng)context (tng)= (tng) new (tng) ClassPathXmlApplicationContext( "test/propertyEditor/testPropertyEditor.xml" );
 (tng) (tng) (tng) (tng) Contact (tng)c (tng)= (tng)(Contact) (tng)context.getBean( "contact" );
 (tng) (tng) (tng) (tng)
 (tng) (tng) (tng) (tng) System.out.println(c.getPhoneNumber().getAreaCode());
 (tng) (tng) (tng) (tng) System.out.println(c.getPhoneNumber().getPrefix());
 (tng) (tng) (tng) (tng) System.out.println(c.getPhoneNumber().getNumber());
 (tng) (tng) }

}

ok, 很简?下一ơ来看看,Spring提供的一下比较有意思的功能.如定?发送Email{?



junky 2006-05-29 23:19 发表评论
]]>
Spring in Action W记(II) part II http://m.tkk7.com/junky/archive/2006/05/25/48175.htmljunkyjunkyThu, 25 May 2006 12:22:00 GMThttp://m.tkk7.com/junky/archive/2006/05/25/48175.htmlhttp://m.tkk7.com/junky/comments/48175.htmlhttp://m.tkk7.com/junky/archive/2006/05/25/48175.html#Feedback0http://m.tkk7.com/junky/comments/commentRss/48175.htmlhttp://m.tkk7.com/junky/services/trackbacks/48175.html阅读全文

junky 2006-05-25 20:22 发表评论
]]>
Spring in Action W记(II) part I http://m.tkk7.com/junky/archive/2006/05/25/48174.htmljunkyjunkyThu, 25 May 2006 12:21:00 GMThttp://m.tkk7.com/junky/archive/2006/05/25/48174.htmlhttp://m.tkk7.com/junky/comments/48174.htmlhttp://m.tkk7.com/junky/archive/2006/05/25/48174.html#Feedback0http://m.tkk7.com/junky/comments/commentRss/48174.htmlhttp://m.tkk7.com/junky/services/trackbacks/48174.html Spring in Action W记 (II)

今天来看看用JDBC来操作数据:(x) 使用的是DerbyQJavaDBQ数据库Q关于JavaDB的介l请点击q里Q?/font> http://blog.matrix.org.cn/page/icess?catname=%2FJavaDB ?下面建立一个DatabaseUtils.java的工L(fng)Q来操作数据?。该cd上面的连接的文章中有讲述?/font>

package (tng) test.jdbc;

import (tng) java.io.File;
import (tng) java.io.IOException;
import (tng) java.io.InputStream;
import (tng) java.sql.Connection;
import (tng) java.sql.DriverManager;
import (tng) java.sql.PreparedStatement;
import (tng) java.sql.ResultSet;
import (tng) java.sql.SQLException;
import (tng) java.sql.Statement;
import (tng) java.util.Properties;
import (tng) java.util.logging.Logger;

public (tng)class (tng) DatabaseUtils (tng){
 (tng) (tng) private (tng)static (tng)final (tng) String (tng)DB_PROPERTIES_FILE (tng)= (tng) "jdbc.properties" ;

 (tng) (tng) private (tng)static (tng)final (tng) String (tng)DB_OPPOSITE_LOCATION (tng)= (tng) "/.test" ;

 (tng) (tng) static (tng) Logger (tng)logger (tng)= (tng)Logger.getLogger(DatabaseUtils. class .getName());

 (tng) (tng) private (tng) Connection (tng)dbConnection;

 (tng) (tng) private (tng) Properties (tng)dbProperties;

 (tng) (tng) private (tng)boolean (tng) isConnected;

 (tng) (tng) // (tng)database (tng)name
 (tng) (tng) private (tng) String (tng)dbName;

 (tng) (tng) private (tng)static (tng)final (tng) String (tng)strCreateTestClobTeble (tng)= (tng) "CREATE (tng)TABLE (tng)APP.test (tng)(id (tng)I(yng)NT, (tng)name (tng)VARCHAR(30),text (tng)CLOB(64 (tng)K))" ;

 (tng) (tng) private (tng)static (tng)final (tng) String (tng)strInsertIntoTestTeble (tng)= (tng) "INSERT (tng)I(yng)NTO (tng)APP.test (tng)(id, (tng)name) (tng) (tng)VALUES (tng)(?, (tng)?)" ;
 (tng) (tng) public (tng)static (tng)final (tng) String (tng)strGetTest (tng)= (tng) "SELECT (tng)* (tng)FROM (tng)APP.test (tng)WHERE (tng)I(yng)D (tng)= (tng)?" ;
 (tng) (tng) private (tng)static (tng)final (tng) String (tng)strCreateCourseTable (tng)= (tng) "create (tng)table (tng)APP.Course (tng)("
 (tng) (tng) (tng) (tng) (tng) (tng) + (tng) " (tng) (tng) (tng) (tng)I(yng)D (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)I(yng)NTEGER (tng)NOT (tng)NULL (tng)PRIMARY (tng)KEY (tng)GENERATED (tng)ALWAYS (tng)AS (tng)I(yng)DENTITY (tng)(START (tng)WITH (tng)1, (tng)I(yng)NCREMENT (tng)BY (tng)1),"
 (tng) (tng) (tng) (tng) (tng) (tng) + (tng) " (tng) (tng) (tng) (tng)name (tng) (tng) (tng) (tng)VARCHAR(30), (tng)"
 (tng) (tng) (tng) (tng) (tng) (tng) + (tng) " (tng) (tng) (tng) (tng)description (tng) (tng)VARCHAR(30), (tng)"
 (tng) (tng) (tng) (tng) (tng) (tng) + (tng) " (tng) (tng) (tng) (tng)startDate (tng) (tng)DATE, (tng)" (tng) + (tng) " (tng) (tng) (tng) (tng)endDate (tng) (tng) (tng) (tng) (tng)DATE (tng)" (tng) + (tng) ")" ;

 (tng) (tng) private (tng)static (tng)final (tng) String (tng)strCreateStudentTable (tng)= (tng) "create (tng)table (tng)APP.ADDRESS (tng)("
 (tng) (tng) (tng) (tng) (tng) (tng) + (tng) " (tng) (tng) (tng) (tng)I(yng)D (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)I(yng)NTEGER (tng)NOT (tng)NULL (tng)PRIMARY (tng)KEY (tng)GENERATED (tng)ALWAYS (tng)AS (tng)I(yng)DENTITY (tng)(START (tng)WITH (tng)1, (tng)I(yng)NCREMENT (tng)BY (tng)1),"
 (tng) (tng) (tng) (tng) (tng) (tng) + (tng) " (tng) (tng) (tng) (tng)LASTNAME (tng) (tng) (tng) (tng)VARCHAR(30), (tng)"
 (tng) (tng) (tng) (tng) (tng) (tng) + (tng) " (tng) (tng) (tng) (tng)FIRSTNAME (tng) (tng) (tng)VARCHAR(30), (tng)"
 (tng) (tng) (tng) (tng) (tng) (tng) + (tng) " (tng) (tng) (tng) (tng)MIDDLENAME (tng) (tng)VARCHAR(30), (tng)"
 (tng) (tng) (tng) (tng) (tng) (tng) + (tng) " (tng) (tng) (tng) (tng)PHONE (tng) (tng) (tng) (tng) (tng) (tng) (tng)VARCHAR(20), (tng)"
 (tng) (tng) (tng) (tng) (tng) (tng) + (tng) " (tng) (tng) (tng) (tng)EMAIL (tng) (tng) (tng) (tng) (tng) (tng) (tng)VARCHAR(30), (tng)"
 (tng) (tng) (tng) (tng) (tng) (tng) + (tng) " (tng) (tng) (tng) (tng)ADDRESS1 (tng) (tng) (tng) (tng)VARCHAR(30), (tng)"
 (tng) (tng) (tng) (tng) (tng) (tng) + (tng) " (tng) (tng) (tng) (tng)ADDRESS2 (tng) (tng) (tng) (tng)VARCHAR(30), (tng)"
 (tng) (tng) (tng) (tng) (tng) (tng) + (tng) " (tng) (tng) (tng) (tng)CITY (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)VARCHAR(30), (tng)"
 (tng) (tng) (tng) (tng) (tng) (tng) + (tng) " (tng) (tng) (tng) (tng)STATE (tng) (tng) (tng) (tng) (tng) (tng) (tng)VARCHAR(30), (tng)" (tng) + (tng) ")" ;

 (tng) (tng) public (tng) DatabaseUtils() (tng){
 (tng) (tng) (tng) (tng) this ( "test" );
 (tng) (tng) }

 (tng) (tng) public (tng) DatabaseUtils(String (tng)dbName) (tng){
 (tng) (tng) (tng) (tng) this .dbName (tng)= (tng)dbName;

 (tng) (tng) (tng) (tng) setDBSystemDir();
 (tng) (tng) (tng) (tng) dbProperties (tng)= (tng)loadDBProperties();
 (tng) (tng) (tng) (tng) String (tng)driverName (tng)= (tng)dbProperties.getProperty( "db.driver" );
 (tng) (tng) (tng) (tng) loadDatabaseDriver(driverName);
 (tng) (tng) (tng) (tng) if (tng) (!dbExists()) (tng){
 (tng) (tng) (tng) (tng) (tng) (tng) createDatabase();
 (tng) (tng) (tng) (tng) }
 (tng) (tng) }

 (tng) (tng) private (tng) Properties (tng)loadDBProperties() (tng){
 (tng) (tng) (tng) (tng) InputStream (tng)dbPropInputStream (tng)= (tng) null ;

 (tng) (tng) (tng) (tng) dbPropInputStream (tng)= (tng)DatabaseUtils. class
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) .getResourceAsStream(DB_PROPERTIES_FILE);
 (tng) (tng) (tng) (tng) dbProperties (tng)= (tng) new (tng) Properties();

 (tng) (tng) (tng) (tng) try (tng) {
 (tng) (tng) (tng) (tng) (tng) (tng) dbProperties.load(dbPropInputStream);
 (tng) (tng) (tng) (tng) } (tng) catch (tng) (IOException (tng)e) (tng){
 (tng) (tng) (tng) (tng) (tng) (tng) e.printStackTrace();
 (tng) (tng) (tng) (tng) }
 (tng) (tng) (tng) (tng) return (tng) dbProperties;
 (tng) (tng) }

 (tng) (tng) private (tng)void (tng) setDBSystemDir() (tng){
 (tng) (tng) (tng) (tng) String (tng)userDir (tng)= (tng)System.getProperty( "user.dir" , (tng) "." );
 (tng) (tng) (tng) (tng) String (tng)systemDir (tng)= (tng)userDir (tng)+ (tng)DB_OPPOSITE_LOCATION;
 (tng) (tng) (tng) (tng) System.setProperty( "derby.system.home" , (tng)systemDir);

 (tng) (tng) (tng) (tng) // (tng)create (tng)the (tng)db (tng)System (tng)dir
 (tng) (tng) (tng) (tng) File (tng)fileSystemDir (tng)= (tng) new (tng) File(systemDir);
 (tng) (tng) (tng) (tng) fileSystemDir.mkdir();
 (tng) (tng) }

 (tng) (tng) private (tng)void (tng) loadDatabaseDriver(String (tng)driverName) (tng){
 (tng) (tng) (tng) (tng) try (tng) {
 (tng) (tng) (tng) (tng) (tng) (tng) Class.forName(driverName);
 (tng) (tng) (tng) (tng) } (tng) catch (tng) (ClassNotFoundException (tng)e) (tng){
 (tng) (tng) (tng) (tng) (tng) (tng) e.printStackTrace();
 (tng) (tng) (tng) (tng) }
 (tng) (tng) }

 (tng) (tng) private (tng)boolean (tng) dbExists() (tng){
 (tng) (tng) (tng) (tng) boolean (tng) bExists (tng)= (tng) false ;
 (tng) (tng) (tng) (tng) String (tng)dbLocation (tng)= (tng)getDatabaseLocation();
 (tng) (tng) (tng) (tng) File (tng)dbFileDir (tng)= (tng) new (tng) File(dbLocation);
 (tng) (tng) (tng) (tng) if (tng) (dbFileDir.exists()) (tng){
 (tng) (tng) (tng) (tng) (tng) (tng) bExists (tng)= (tng) true ;
 (tng) (tng) (tng) (tng) }
 (tng) (tng) (tng) (tng) return (tng) bExists;
 (tng) (tng) }

 (tng) (tng) private (tng)boolean (tng) createDatabase() (tng){
 (tng) (tng) (tng) (tng) boolean (tng) bCreated (tng)= (tng) false ;
 (tng) (tng) (tng) (tng) Connection (tng)dbConnection (tng)= (tng) null ;

 (tng) (tng) (tng) (tng) String (tng)dbUrl (tng)= (tng)getDatabaseUrl();
 (tng) (tng) (tng) (tng) dbProperties.put( "create" , (tng) "true" );

 (tng) (tng) (tng) (tng) try (tng) {
 (tng) (tng) (tng) (tng) (tng) (tng) dbConnection (tng)= (tng)DriverManager.getConnection(dbUrl, (tng)dbProperties);
 (tng) (tng) (tng) (tng) (tng) (tng) bCreated (tng)= (tng)createTables(dbConnection, (tng)strCreateTestClobTeble);
 (tng) (tng) (tng) (tng) } (tng) catch (tng) (SQLException (tng)e) (tng){
 (tng) (tng) (tng) (tng) (tng) (tng) e.printStackTrace();
 (tng) (tng) (tng) (tng) }

 (tng) (tng) (tng) (tng) dbProperties.remove( "create" );
 (tng) (tng) (tng) (tng) return (tng) bCreated;
 (tng) (tng) }

 (tng) (tng) private (tng)boolean (tng) createTables(Connection (tng)dbConnection, (tng)String (tng)creatTableSql) (tng){
 (tng) (tng) (tng) (tng) boolean (tng) bCreatedTables (tng)= (tng) false ;
 (tng) (tng) (tng) (tng) Statement (tng)statement (tng)= (tng) null ;

 (tng) (tng) (tng) (tng) try (tng) {
 (tng) (tng) (tng) (tng) (tng) (tng) statement (tng)= (tng)dbConnection.createStatement();
 (tng) (tng) (tng) (tng) (tng) (tng) statement.execute(creatTableSql);
 (tng) (tng) (tng) (tng) (tng) (tng) bCreatedTables (tng)= (tng) true ;
 (tng) (tng) (tng) (tng) } (tng) catch (tng) (SQLException (tng)e) (tng){
 (tng) (tng) (tng) (tng) (tng) (tng) e.printStackTrace();
 (tng) (tng) (tng) (tng) }
 (tng) (tng) (tng) (tng) return (tng) bCreatedTables;
 (tng) (tng) }

 (tng) (tng) public (tng) String (tng)getDatabaseUrl() (tng){

 (tng) (tng) (tng) (tng) return (tng) dbProperties.getProperty( "db.url" ) (tng)+ (tng)dbName;
 (tng) (tng) }

 (tng) (tng) public (tng) String (tng)getDatabaseLocation() (tng){
 (tng) (tng) (tng) (tng) String (tng)dbLocation (tng)= (tng)System.getProperty( "derby.system.home" ) (tng)+ (tng) "/"
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) + (tng)dbName;
 (tng) (tng) (tng) (tng) return (tng) dbLocation;
 (tng) (tng) }

 (tng) (tng) public (tng)boolean (tng) connect() (tng){
 (tng) (tng) (tng) (tng) String (tng)dbUrl (tng)= (tng)getDatabaseUrl();
 (tng) (tng) (tng) (tng) try (tng) {
 (tng) (tng) (tng) (tng) (tng) (tng) logger.info( "DBUrl: (tng)" (tng) + (tng)dbUrl);
 (tng) (tng) (tng) (tng) (tng) (tng) dbConnection (tng)= (tng)DriverManager.getConnection(dbUrl, (tng)dbProperties);
 (tng) (tng) (tng) (tng) (tng) (tng) isConnected (tng)= (tng)dbConnection (tng)!= (tng) null ;
 (tng) (tng) (tng) (tng) } (tng) catch (tng) (SQLException (tng)e) (tng){
 (tng) (tng) (tng) (tng) (tng) (tng) // (tng)TODO (tng)Auto-generated (tng)catch (tng)block
 (tng) (tng) (tng) (tng) (tng) (tng) e.printStackTrace();
 (tng) (tng) (tng) (tng) (tng) (tng) isConnected (tng)= (tng) false ;
 (tng) (tng) (tng) (tng) (tng) (tng) logger.info( "create (tng)connection (tng)if (tng)failed!" );
 (tng) (tng) (tng) (tng) }
 (tng) (tng) (tng) (tng) return (tng) isConnected;
 (tng) (tng) }

 (tng) (tng) public (tng) Connection (tng)getConnection() (tng){
 (tng) (tng) (tng) (tng) return (tng) dbConnection;
 (tng) (tng) }

 (tng) (tng) public (tng)void (tng) disconnect() (tng){
 (tng) (tng) (tng) (tng) if (tng) (isConnected) (tng){
 (tng) (tng) (tng) (tng) (tng) (tng) String (tng)dbUrl (tng)= (tng)getDatabaseUrl();
 (tng) (tng) (tng) (tng) (tng) (tng) dbProperties.put( "shutdown" , (tng) "true" );
 (tng) (tng) (tng) (tng) (tng) (tng) try (tng) {
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) System.out.println( "断开数据库连????????????????" );
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) DriverManager.getConnection(dbUrl, (tng)dbProperties);
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) System.out.println( "????????????????" );
 (tng) (tng) (tng) (tng) (tng) (tng) } (tng) catch (tng) (SQLException (tng)e) (tng){
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) // (tng)e.printStackTrace();
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) logger.info( "disconnect (tng)the (tng)connection (tng)Successful!" );
 (tng) (tng) (tng) (tng) (tng) (tng) }
 (tng) (tng) (tng) (tng) (tng) (tng) isConnected (tng)= (tng) false ;
 (tng) (tng) (tng) (tng) }
 (tng) (tng) }

 (tng) (tng) /**
 (tng) (tng) (tng) * (tng) @param (tng) args
 (tng) (tng) (tng) */
 (tng) (tng) public (tng)static (tng)void (tng) main(String[] (tng)args) (tng){
 (tng) (tng) (tng) (tng) // (tng)TODO (tng)Auto-generated (tng)method (tng)stub
 (tng) (tng) (tng) (tng) DatabaseUtils (tng)testdb (tng)= (tng) new (tng) DatabaseUtils();
 (tng) (tng) (tng) (tng) logger.info(testdb.getDatabaseLocation());
 (tng) (tng) (tng) (tng) logger.info(testdb.getDatabaseUrl());
 (tng) (tng) (tng) (tng) testdb.connect();
 (tng) (tng) (tng) (tng) Connection (tng)c (tng)= (tng)testdb.getConnection();
 (tng) (tng) (tng) (tng) PreparedStatement (tng)ps (tng)= (tng) null ;
 (tng) (tng) (tng) (tng) try (tng) {
 (tng) (tng) (tng) (tng) (tng) (tng) ps (tng)= (tng)c.prepareStatement(DatabaseUtils.strInsertIntoTestTeble, (tng)Statement.RETURN_GENERATED_KEYS);
 (tng) (tng) (tng) (tng) (tng) (tng) ps.setInt( 1 , (tng) 1 );
 (tng) (tng) (tng) (tng) (tng) (tng) ps.setString( 2 , (tng) "test (tng)I(yng)cerain" );
 (tng) (tng) (tng) (tng) (tng) (tng) int (tng) i (tng)=ps.executeUpdate();
 (tng) (tng) (tng) (tng) (tng) (tng) System.out.println(i);
 (tng) (tng) (tng) (tng) (tng) (tng) ps.close();
 (tng) (tng) (tng) (tng) (tng) (tng)
 (tng) (tng) (tng) (tng) (tng) (tng) ps (tng)= (tng)c.prepareStatement(DatabaseUtils.strGetTest);
 (tng) (tng) (tng) (tng) (tng) (tng) ps.setInt( 1 , (tng) 1 );
 (tng) (tng) (tng) (tng) (tng) (tng) ResultSet (tng)rs (tng)= (tng)ps.executeQuery();
 (tng) (tng) (tng) (tng) (tng) (tng) if (rs.next()) (tng){
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) String (tng)name (tng)= (tng)rs.getString( 2 );
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) System.out.println(name);
 (tng) (tng) (tng) (tng) (tng) (tng) }
 (tng) (tng) (tng) (tng) (tng) (tng) ps.close();
 (tng) (tng) (tng) (tng) } (tng) catch (tng) (SQLException (tng)e) (tng){
 (tng) (tng) (tng) (tng) (tng) (tng) // (tng)TODO (tng)Auto-generated (tng)catch (tng)block
 (tng) (tng) (tng) (tng) (tng) (tng) e.printStackTrace();
 (tng) (tng) (tng) (tng) }
 (tng) (tng) (tng) (tng) testdb.disconnect();
 (tng) (tng) }

}

 

下面是一个插入数据的c?InsertData.java

package (tng) test.jdbc;

import (tng) java.sql.Types;

import (tng) javax.sql.DataSource;

import (tng) org.springframework.jdbc.core.SqlParameter;
import (tng) org.springframework.jdbc.object.SqlUpdate;

public (tng)class (tng) InsertData (tng) extends (tng) SqlUpdate (tng){
 (tng) (tng) // (tng)需要注入一个DataSource...
 (tng) (tng) public (tng) InsertData(DataSource (tng)ds) (tng){
 (tng) (tng) (tng) (tng) setDataSource(ds); (tng) (tng) // (tng)TODO (tng)注意 (tng)讄数据?/font>
 (tng) (tng) (tng) (tng) setSql( "INSERT (tng)I(yng)NTO (tng)APP.test (tng)(id, (tng)name) (tng) (tng)VALUES (tng)(?, (tng)?)" );
 (tng) (tng) (tng) (tng) declareParameter( new (tng) SqlParameter(Types.INTEGER));
 (tng) (tng) (tng) (tng) declareParameter( new (tng) SqlParameter(Types.VARCHAR));
 (tng) (tng) (tng) (tng)
 (tng) (tng) (tng) (tng) compile(); // (tng)TODO (tng)注意 (tng), (tng)要编译以后才可以使用
 (tng) (tng) }
 (tng) (tng)
 (tng) (tng) // (tng)覆盖insertҎ(gu)
 (tng) (tng) public (tng)int (tng) insert(TestData (tng)data) (tng){
 (tng) (tng) (tng) (tng) Object[] (tng)params (tng)= (tng) new (tng) Object[] (tng){data.id,data.name};
 (tng) (tng) (tng) (tng) return (tng) update(params); (tng) (tng) // (tng)执行插入操作....
 (tng) (tng) }

}

很简? q带有详l注?

下面是一个查询的c?QueryDataById.java

package (tng) test.jdbc;

import (tng) java.sql.ResultSet;
import (tng) java.sql.SQLException;
import (tng) java.sql.Types;

import (tng) javax.sql.DataSource;

import (tng) org.springframework.jdbc.core.SqlParameter;
import (tng) org.springframework.jdbc.object.MappingSqlQuery;

public (tng)class (tng) QueryDataById (tng) extends (tng) MappingSqlQuery{
 (tng) (tng) private (tng)static (tng)final (tng) String (tng)sql (tng)= (tng) "SELECT (tng)* (tng)FROM (tng)APP.test (tng)WHERE (tng)I(yng)D (tng)= (tng)?" ;
 (tng) (tng) public (tng) QueryDataById(DataSource (tng)ds) (tng){
 (tng) (tng) (tng) (tng) super (ds,sql);
 (tng) (tng) (tng) (tng) declareParameter( new (tng) SqlParameter( "id" ,Types.INTEGER));
 (tng) (tng) (tng) (tng) compile();
 (tng) (tng) }
 

 (tng) // (tng)覆盖mapRowҎ(gu)
 (tng) (tng) @Override
 (tng) (tng) protected (tng) Object (tng)mapRow(ResultSet (tng)rs, (tng) int (tng) index) (tng) throws (tng) SQLException (tng){
 (tng) (tng) (tng) (tng) // (tng)TODO (tng)Auto-generated (tng)method (tng)stub
 (tng) (tng) (tng) (tng) TestData (tng)tdata (tng)= (tng) new (tng) TestData();
 (tng) (tng) (tng) (tng) tdata.id (tng)= (tng)rs.getInt( 1 );
 (tng) (tng) (tng) (tng) tdata.name (tng)= (tng)rs.getString( 2 );
 (tng) (tng) (tng) (tng)
 (tng) (tng) (tng) (tng) return (tng) tdata;
 (tng) (tng) }
 (tng) (tng)
}

 

也很?

注意:

 (tng)以上两个c都实现?jin)Spring化Jdbc操作的一些接? 关于接口的信息请查考文? q里不在详细讲述.

 

下面是一个很单的试(数据)实体c?TestData.java

package (tng) test.jdbc;

public (tng)class (tng) TestData (tng){
 (tng) (tng) public (tng)int (tng) id;
 (tng) (tng) public (tng) String (tng)name;
 (tng) (tng) public (tng) TestData( int (tng) id, (tng)String (tng)name) (tng){
 (tng) (tng) (tng) (tng) this .id (tng)= (tng)id;
 (tng) (tng) (tng) (tng) this .name (tng)= (tng)name;
 (tng) (tng) }
 (tng) (tng) public (tng) TestData() (tng){}
}

下面是一个测试数据源是否注入正确的类:TestDataSource.java

package (tng) test.jdbc;

import (tng) java.sql.Connection;
import (tng) java.sql.PreparedStatement;
import (tng) java.sql.ResultSet;

import (tng) javax.sql.DataSource;

public (tng)class (tng) TestDataSource (tng){
 (tng) (tng) private (tng) DataSource (tng)dataSource;
 

// 注入数据?/span>
 (tng) (tng) public (tng)void (tng) setDataSource(DataSource (tng)dataSource) (tng){
 (tng) (tng) (tng) (tng) this .dataSource (tng)= (tng)dataSource;
 (tng) (tng) }
 

//试数据?/span>
 (tng) (tng) public (tng)void (tng) testDataSource() (tng){
 (tng) (tng) (tng) (tng) try (tng) {
 (tng) (tng) (tng) (tng) (tng) (tng) System.out.println( "Test (tng)DataSource!!!" );
 (tng) (tng) (tng) (tng) (tng) (tng) Connection (tng)connection (tng)= (tng)dataSource.getConnection();
 (tng) (tng) (tng) (tng) (tng) (tng) if (tng) (connection (tng)!= (tng) null )
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) System.out.println( "test (tng)ok!" );
 (tng) (tng) (tng) (tng) (tng) (tng)
 (tng) (tng) (tng) (tng) (tng) (tng) PreparedStatement (tng)ps (tng)= (tng) null ;
 (tng) (tng) (tng) (tng) (tng) (tng) ps (tng)= (tng)connection.prepareStatement(DatabaseUtils.strGetTest);
 (tng) (tng) (tng) (tng) (tng) (tng) ps.setInt( 1 , (tng) 1 );
 (tng) (tng) (tng) (tng) (tng) (tng) ResultSet (tng)rs (tng)= (tng)ps.executeQuery();
 (tng) (tng) (tng) (tng) (tng) (tng) if (rs.next()) (tng){
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) String (tng)name (tng)= (tng)rs.getString( 2 );
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) System.out.println( "试数据源配|?" (tng) + (tng)name);
 (tng) (tng) (tng) (tng) (tng) (tng) }
 (tng) (tng) (tng) (tng) (tng) (tng) ps.close();
 (tng) (tng) (tng) (tng) } (tng) catch (tng) (Exception (tng)e) (tng){
 (tng) (tng) (tng) (tng) (tng) (tng) e.printStackTrace();
 (tng) (tng) (tng) (tng) }
 (tng) (tng) }

}

下面是测试Spring提高的Jdbc功能的主要测试类, 试?jin)一些用JDBC操作数据的常用功? 其他没有试的请查看其Doc,TestJdbcTemplate.java



junky 2006-05-25 20:21 发表评论
]]>
Spring in Action W记(I) http://m.tkk7.com/junky/archive/2006/05/23/47703.htmljunkyjunkyTue, 23 May 2006 11:37:00 GMThttp://m.tkk7.com/junky/archive/2006/05/23/47703.htmlhttp://m.tkk7.com/junky/comments/47703.htmlhttp://m.tkk7.com/junky/archive/2006/05/23/47703.html#Feedback0http://m.tkk7.com/junky/comments/commentRss/47703.htmlhttp://m.tkk7.com/junky/services/trackbacks/47703.html在考试前匆匆看?jin)一遍Spring in Action 也没有记录什?考试l束?要抓紧时间整理一?要不然就忘(sh)(jin).^_^:

整理一下我目前可能?x)用到的模? 对于那些现在Ҏ(gu)用不到的冬冬q是{有旉再研I吧!

W一个当然是最l典的HelloWorld ?, 呵呵,?但是说明?jin)原?

定义一个服务接?/p>

package (tng) test.helloworld;

public (tng)interface (tng) GreetingService (tng){
 (tng) (tng) public (tng)void (tng) sayGreeting();

}

下面是其实现:

package (tng) test.helloworld;

public (tng)class (tng) GreetingServiceImpl (tng) implements (tng) GreetingService (tng){

 (tng) (tng) private (tng) String (tng)greeting;
 (tng) (tng) public (tng) GreetingServiceImpl() (tng){}
 (tng) (tng) public (tng) GreetingServiceImpl(String (tng)greeting) (tng){
 (tng) (tng) (tng) (tng) this .greeting (tng)= (tng)greeting;
 (tng) (tng) }
 (tng) (tng) public (tng)void (tng) sayGreeting() (tng){
 (tng) (tng) (tng) (tng) // (tng) (tng)Auto-generated (tng)method (tng)stub
 (tng) (tng) (tng) (tng) System.out.println(greeting);
 (tng) (tng) }
 (tng) (tng)
 (tng) (tng) public (tng)void (tng) setGreeting(String (tng)greeting) (tng){
 (tng) (tng) (tng) (tng) this .greeting (tng)= (tng)greeting;
 (tng) (tng) }

}

然后是试 IoC 的测试代?

package (tng) test.helloworld;


import (tng) org.springframework.beans.factory.BeanFactory;
import (tng) org.springframework.beans.factory.xml.XmlBeanFactory;
import (tng) org.springframework.context.ApplicationContext;
import (tng) org.springframework.context.support.ClassPathXmlApplicationContext;
import (tng) org.springframework.core.io.FileSystemResource;

public (tng)class (tng) HelloApp (tng){

 (tng) (tng) /**
 (tng) (tng) (tng) * (tng) @param (tng) args
 (tng) (tng) (tng) */
 (tng) (tng) public (tng)static (tng)void (tng) main(String[] (tng)args) (tng){
 (tng) (tng) (tng) (tng) // (tng)TODO (tng)Auto-generated (tng)method (tng)stub
// (tng) (tng) (tng) (tng)BeanFactory (tng)factory;
// (tng) (tng) (tng) (tng)factory (tng)= (tng)new (tng)XmlBeanFactory(new (tng)FileSystemResource("src/test/helloworld/hello.xml"));
 (tng) (tng) (tng) (tng) // (tng)使用不同的方法得到bean. (tng)(BeanFactory (tng)or (tng)ApplicationContext)
 (tng) (tng) (tng) (tng) ApplicationContext (tng)context (tng)= (tng) new (tng) ClassPathXmlApplicationContext( "test/helloworld/hello.xml" );
 (tng) (tng) (tng) (tng)
 (tng) (tng) (tng) (tng)
 (tng) (tng) (tng) (tng) GreetingService (tng)greetingService (tng)= (tng)(GreetingService) (tng)context.getBean( "greetingService" );
// (tng) (tng) (tng) (tng)GreetingService (tng)greetingService (tng)= (tng)(GreetingService) (tng)factory.getBean("greetingService");
 (tng) (tng) (tng) (tng) greetingService.sayGreeting();
 (tng) (tng) }

}

q有重要的配|文件如?hello.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 = "greetingService"

class = "test.helloworld.GreetingServiceImpl" >

< property name = "greeting" >

< value > ice rain ! </ value >

</ property >

</ bean >

</

beans >

呵呵p么简?实现?greeting 属性的 Ioc.

q是Spring 两大基本支柱其一的工作原? 关于AoP的内?在这里不作讨?因ؓ(f)现在我用AoP的地方不是很?单的应用是很单的?^_^.

下面一我们来看看 在spring包装下的jdbc讉K. 详细情况也可?b>参考这?/a>



junky 2006-05-23 19:37 发表评论
]]>
Spring框架学习(fn)前言---我的开源框架用心(j)得体?http://m.tkk7.com/junky/archive/2006/05/17/46514.htmljunkyjunkyTue, 16 May 2006 16:26:00 GMThttp://m.tkk7.com/junky/archive/2006/05/17/46514.htmlhttp://m.tkk7.com/junky/comments/46514.htmlhttp://m.tkk7.com/junky/archive/2006/05/17/46514.html#Feedback0http://m.tkk7.com/junky/comments/commentRss/46514.htmlhttp://m.tkk7.com/junky/services/trackbacks/46514.html 目的Q?/strong>
在实际项目中ZE_性以?qing)团队开发技能我一直没考虑采用Spring框架Q最q有旉p划学?fn)Spring框架Qؓ(f)以后的项目开发做相关的技术储备?/p>


回顾Q?/strong>
开源框架在以前的项目中用过不少Q?struts,webwork,hibernate,前两者属于web框架Q后者属于ORM框架Q这些框架基本都是侧重于应用的某个层面,不能UC为J2EE全面的框Ӟ往往是需要和其他框架相结合,我开发的目采用q如下组合,有的Ҏ(gu)没有框Ӟ只是自己做了(jin)设计装
a、servlet+jdbc,
b、servlet+jsp+javabean+jdbc,
c、struts+BD+DAO ,
d、webwork+ejb+hibernate

使用体会(x)Q?/strong>

 (tng)a、b׃要说?jin),那时候的代码l构真是天马行空Q我当时初学Q维护公怸个项目代码,1个jsp实现一个模块所有功能,我花?jin)好长时间才?tng)L代码?br /> (tng) 时代L向前发展的,慢慢的系l结构层ơ上是越来越清晰Q开发效率也来高Q维护也来容易(Z一定的培训成本Q?br /> (tng)
 (tng)相对而言Z设计理念来讲Q个人更喜欢webwork+hibernate框架l合?/font> (tng)

 (tng)常有论同{开发层面框架的优缺点,我所属品的另外一个项目团队曾lؓ(f)目后箋(hu)开?应该采用strutsq是webwork争论的不可开交, (tng)其实个h认ؓ(f)struts,webwork都是非常好的web框架Q都有自w的优缺点:(x)
 (tng)struts开创web MVC框架之先治I2003Q?004q开发的目基本都是采用struts框架Q当时招聘(sh)h的时候常问会(x)不会(x)strutsQ会(x)基本招?jin) (tng)?j)Q实际MVC设计理念很早提Z(jin)Q在j2SE中有很多使用之处Q但当时没有一个web框架开发中很好的诏彻该设计理念Q直到struts (tng)出现Q可能有Q只是没有apache更引人注意)(j)?br />
 (tng)struts优点使用用户多,相关技术文比较全面,开发遇到的问题相关案例也比较多、比较容易解冻I框架更加E_(q一炚w帔R要)(j)?br /> (tng)
 (tng)webwork相对于struts来讲Q的有不少优异之处Q(也是情理之中的事Q后发布的框架如果再没有优点别h也不?x)用?j)
 (tng)个h认ؓ(f)在开发上主要有以下几点:(x)

 (tng)1、页面数据封装成值对象功能比struts强大Qwebwork采用ognlcd转化?br /> (tng)struts只能对简单类型的数据对象以及(qing)文g对象装成值对? (tng)而webwork装的值对象基本没有限Ӟ值对象属性还可以是List,Mapq些对象Q这个特性在我们开发一些批量数据、复杂数据处理时非常方便Q,减少很多代码量,代码非常整洁?br /> (tng)
 (tng)2、拦截器功能
 (tng)拦截器是webwork的一个亮点,实际上也是业界比较流行的AOP的一个体玎ͼ在实际开发中你可以配|默认的拦截器, (tng)也可以ؓ(f)单独的模块指定特定的拦截器,q且可自定义拦截器,action执行前后拦截都可以。?br /> (tng)
 (tng)3、单元测试比较方?br /> (tng)最早用struts框架开发测试时Q相关的单元试基本是不好做的,无法qweb环境Q测试都是只做集成测试、系l测试?br /> (tng)使用webwork可以单对action相关属性赋|可以相关的单元测试,当然前提是在对应action中没有引用web环境相关的对象。?br /> (tng)其实webwork框架核心(j)q是xwork框架Q最早框架用在C/Sl构下,webwork只是xwork的一个在web环境的实玎ͼ只是ActionContext (tng)上下文发生了(jin)变化Q所以说action能够做到qweb环境也是情理之中的?/p>


4、配|文?br />webwork配置文g可以采用引用、承其他配|文件方式,在团队开发一般都是分模块开发,q样比较方便Q配|管理更Ҏ(gu)Q不?x)冲H?br />
5、模板技术集?br /> (tng)我在实际应用目中是采用velocity模板做视囑ֱ玎ͼ因ؓ(f)在对应版本的webwork框架中和velociy集成的相当好Q比较方便,
 (tng)比直接写jsp代码更整z、同时利用velocity模板Ҏ(gu)结合每个action的配|文Ӟ可实现比较通用的页面查询、录入等视图的展现?br /> (tng)而struts是没有相x(chng)杉K成,不过struts的tag相对而言比webwork的tag好用Qwebwork如果视图是jspcdQ相关的tag真的比较ȝ(ch)
 (tng)虽然tag 库很丰富Q这也是我ؓ(f)什么用velocity做视囄原因 。?br /> (tng)
6?框架的效验功?br /> (tng)老实_(d)两者框架的效验功能都比较麻?ch),相对而言webwork更加ȝ(ch)点,配置较多Q验证接口实现太ȝ(ch)Q我实际目使用中还?br /> (tng)自定义了(jin)相关后台验证接口Q?要验证的相关action只要实现相关接口卛_Q相x(chng)截器负责拦截验证Q?br /> (tng)大部分的效验Ҏ(gu)配置数据以及(qing)html对象自定义属性通过javascript通用效验Q实际上现在ZXmlHttp的ajax技术应用成熟的?br /> (tng)后台验证接口的用途会(x)逐渐淡化?
 (tng)
 (tng)说明上述比较版本?struts 1.0 /webwork 2.1.6Q后lstruts框架扩展很多功能Q不是很?jin)解Q可能和上诉描述不一定很d?br /> (tng)
 (tng)现在两者已l合qӞ希望能结合两者的优势Q发展出更好web框架?br /> (tng)
7、关于Hibernateq是DAO模式Q个人徏议采用hibernate+DAO盔R合的模式Qhibernate占主导地位?br /> (tng)虽然DAO模式通过自动生成代码效率不会(x)低,但如果需求变更就比较ȝ(ch)Q维护修改代码较多,试工作量也较大Q?tng)但Hibernate不是万能的,在一些必要的应用q是采用DAO模式Q特别是性能相关的部分?
 (tng)
 (tng)
 (tng)废话一大堆Q也把我的工作回顾?jin)一遍,呵呵Q这两天单了(jin)解Spring框架Q个人感觉Spring更像一个全面的J2EE框架解决Ҏ(gu), (tng)希望能够有时间系l的学习(fn)一把,大家有兴的请多多交?我会(x)我的学?fn)?j)得和大家分n?/p>

junky 2006-05-17 00:26 发表评论
]]>
վ֩ģ壺 ÿ޻ɫ| ձva߹ۿ| һƵ| Ӱַ| Ƶһ| aaŮ˴ƬˮƵ| ۺɫ| aëƬ18ϹۿƷ| þþþƷҹѲ| ŮƵ| ľþþƷ| 91۲ݹ߹ۿ| Ƶ| Ļav| þþƷ| žѹۿ嶯4| ձƵѹۿ| Avһ| Ƶ߲| ëƬƵa| ëƬƬѹۿ| Ʒ޸жƪ | ĻþþƷ| Ļ| Ƶ߹ۿѿƬ| ձ˳ww555| ƷƬ߻ | ѴƬ߹ۿcom| Ѷ| һ| ĻƵ| ѧŮëƬƵ| 18ɽƵվ| aëƬѹۿ| ѿվ߿| ŷݵһղsuv| Ļ޾ƷԴ| ˳վɫwww| ޾Ʒպ?V| auƵӰԺ| ŷƵ|