??xml version="1.0" encoding="utf-8" standalone="yes"?> 分钟Q?~59Q?/font> 时Q?~23Q?/font> 天(月)Q?~31Q但是你需要考虑你月的天敎ͼ 月(0~11Q?/font> 天(星期Q(1~7 1=SUN ?SUNQMONQTUEQW(xu)EDQTHUQFRIQSATQ?/font> 7.q䆾Q?970Q?099Q?br />
0 0 10,14,16 * * ? 每天上午10点,下午2点,4?br />
0 0/30 9-17 * * ??? 朝九(ji)晚五工作旉内每半小?br />
0 0 12 ? * WED 表示每个星期三中?2?/font> 有些子表辑ּ能包含一些范围或列表 例如Q子表达式(天(星期Q?/strong>Q可以ؓ “MON-FRI”Q?#8220;MONQW(xu)EDQFRI”Q?#8220;MON-WED,SAT” “*”字符代表所有可能的?/font> 因此Q?#8220;*”在子表达式(?/strong>Q里表示每个月的含义Q?#8220;*”在子表达式(天(星期Q?/strong>Q表C星期的每一?/font> ? “/”字符用来指定数值的增量 例如Q在子表辑ּQ分钟)里的“0/15”表示从第0分钟开始,?5分钟 ?????? ? 在子表达式(分钟Q里?#8220;3/20”表示从第3分钟开始,?0分钟Q它?#8220;3Q?3Q?3”Q的含义一?/font> ?个子表达式其中之一被指定了g后,Z避免冲突Q需要将另一个子表达式的D?#8220;Q?#8221; ? “L” 字符仅被用于天(月)和天Q星期)两个子表辑ּQ它是单?#8220;last”的羃?/font> 但是它在两个子表辑ּ里的含义是不同的?/font> 在天Q月Q子表达式中Q?#8220;L”表示一个月的最后一?/font> 在天Q星期)自表辑ּ中,“L”表示一个星期的最后一天,也就是SAT 如果?#8220;L”前有具体的内容,它就h其他的含义了 例如Q?#8220;6L”表示q个月的倒数W6天,“QRQL”表示q个月的最一个星期五 注意Q在使用“L”参数Ӟ不要指定列表或范_因ؓq会D问题 它有两种配置方式OpenSessionInViewInterceptor?span style="font-size: 10pt; color: #4b4b4b; font-family: Verdana">OpenSessionInViewFilter(具体参看SpringSide)按顺序依ơؓ
U(0~59Q?/font>
其中每个元素可以是一个??),一个连l区?9-12),一个间隔时?8-18/4)(/表示每隔4时),一个列?1,3,5),通配W。由?月䆾中的日期"?星期中的日期"q两个元素互斥的,必须要对其中一个设|?.
“Q?#8221;字符仅被用于天(月)和天Q星期)两个子表辑ּQ表CZ指定?/font>
]]>
]]>
Open Session In View?/span>request?/span>sessionl定到当?/span>thread期间一直保?/span>hibernate session?/span>open状态,?/span>session?/span>request的整个期间都可以使用Q如?/span>View层里PO也可?/span>lazy loading数据Q如 ${ company.employees }。当View 层逻辑完成后,才会通过Filter?/span>doFilterҎ(gu)?/span>Interceptor?/span>postHandleҎ(gu)自动关闭session?/span>
OpenSessionInViewInterceptor配置
OpenSessionInViewFilter配置
很多人在使用OpenSessionInViewq程中提及一个错误:
看看OpenSessionInViewFilter里的opensessionҎ(gu)
可以看到OpenSessionInViewFilter在getSession的时?会把获取回来的session的flush mode 设ؓFlushMode.NEVER。然后把该sessionFactoryl定到TransactionSynchronizationManagerQrequest的整个过E都使用同一个sessionQ在hq后再接除该sessionFactory的绑定,最?span class="me1">closeSessionIfNecessaryҎ(gu)该session是否已和transactionl定来决定是否关闭session。在q个q程中,若HibernateTemplate 发现自当前session有不是readOnly的transactionQ就会获取到FlushMode.AUTO SessionQҎ(gu)拥有写权限?/p>
也即是,如果有不是readOnly的transaction可以由Flush.NEVER转ؓFlush.AUTO,拥有insert,update,delete操作权限Q如果没有transactionQƈ且没有另外h为地设flush model的话Q则doFilter的整个过E都是Flush.NEVER。所以受transaction保护的方法有写权限,没受保护的则没有?/p>
采用spring的事务声?使方法受transaction控制
对于上例Q则以save,add,update,remove开头的Ҏ(gu)拥有可写的事务,如果当前有某个方法,如命名ؓimportExcel()Q则因没有transaction而没有写权限Q这时若Ҏ(gu)内有insert,update,delete操作的话Q则需要手动设|flush model为Flush.AUTO,?/p>
管Open Session In View看v来还不错Q其实副作用不少。看回上面OpenSessionInViewFilter的doFilterInternalҎ(gu)代码Q这个方法实际上是被父类的doFilter调用的,因此Q我们可以大U了解的OpenSessionInViewFilter调用程: request(h)->open sessionq开始transaction->controller->View(Jsp)->l束transactionqclose session.
一切看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>
hibernate open session in view 抛出异常解决Ҏ(gu)
在用open-session-in-view的时候,如果使用不当Q有可能抛出两种异常
1QNonUniqueObjectException
2Q在配合spring使用的时候会可能会抛出org.springframework.dao.InvalidDataAccessApiUsageException
先说1Q这个异常的抛出原因和解军_法见q里Q?br />
javaeye上有了很好的事例:http://www.javaeye.com/topic/11581
解决办法可以用mergeQ也可以别的办法?br />
出现的原因,可以参考一下我前边的文章中merge和update的区别的内容?br />
http://www.aygfsteel.com/dreamstone/archive/2007/07/29/133071.html
2的解军_法:在这?br />
springside的一文章做了详l说?br />
http://calvin.blog.javascud.org/post/46.htm
好了Q现在问题解决了Q但关于open-session-in-view的用还有一些探讨,是否应该使用Q用的好处与坏处?br />
见这两篇jdon上的文章:
http://www.jdon.com/jivejdon/thread/22374.html
http://www.jdon.com/jivejdon/thread/28955.html
举例Q假设有在一个应用系l中Q有一个共享的数据必须被ƈ发同时访问,首先Q将q个数据装在数据对象中Q称为Data ClassQ同Ӟ有多个讉Kc,专门用于在同一时刻讉Kq同一个数据对象?br />
Z完成上述q发讉K同一资源的功能,需要引入锁Lock的概念,也就是说Q某个时刻,当有一个访问类讉Kq个数据对象Ӟq个数据对象必须上锁LockedQ用完后q卌锁unLockedQ再供其它访问类讉K?br />
使用传统的编E习(fn)惯,我们会创Z个抽象类Q所有的讉Kcȝ承这个抽象父c,如下Q?br />
abstract class Worker{
abstract void locked();
abstract void accessDataObject();
abstract void unlocked();
}
~点Q?/font>
* accessDataObject()Ҏ(gu)需要有“?#8221;状态之cȝ相关代码?br /> * Java只提供了单承,因此具体讉Kcd能承这个父c,如果具体讉Kc还要承其它父c,比如另外一个如Worker的父c,无法方便实现?br /> * 重用被打折扣Q具体访问类因ؓ也包?#8220;?#8221;状态之cȝ相关代码Q只能被重用在相x“?#8221;的场合,重用范围很窄?/font>
仔细研究q个应用?#8220;?#8221;Q它其实有下列特性:
* “?#8221;功能不是具体讉Kcȝ首要或主要功能,讉KcM要功能是讉K数据对象Q例如读取数据或更改动作?nbsp;
“?#8221;行ؓ其实是和具体讉Kcȝ主要功能可以独立、区分开来的
“?#8221;功能其实是这个系l的一个纵向切面,涉及许多cR许多类的方法?nbsp;
因此Q一个新的程序结构应该是xpȝ的纵向切面,例如q个应用?#8220;?#8221;功能Q这个新的程序结构就是aspectQ方面)
在这个应用中Q?#8220;?#8221;斚wQaspectQ应该有以下职责Q?br />
提供一些必备的功能Q对被访问对象实现加锁或解锁功能。以保证所有在修改数据对象的操作之前能够调用lock()加锁Q在它用完成后Q调用unlock()解锁?br />
AOP应用范围
很明显,AOP非常适合开发J2EE容器服务器,目前JBoss 4.0正是使用AOP框架q行开发?br />
具体功能如下Q?br />
Authentication 权限
Caching ~存
Context passing 内容传?br />
Error handling 错误处理
Lazy loading 懒加?br />
Debugging 调试
logging, tracing, profiling and monitoring 记录跟踪 优化 校准
Performance optimization 性能优化
Persistence 持久?br />
Resource pooling 资源?br />
Synchronization 同步
Transactions 事务
AOP有必要吗Q?br />
当然Q上q应用范例在没有使用AOP情况下,也得C解决Q例如JBoss 3.XXX也提供了上述应用功能Q但是没有用AOP?br />
但是Q用AOP可以让我们从一个更高的抽象概念来理解Y件系l,AOP也许提供一U有价值的工具。可以这么说Q因Z用AOPl构Q现在JBoss 4.0的源码要比JBoss 3.XҎ(gu)理解多了Q这对于一个大型复杂系l来说是非常重要的?br />
从另外一个方面说Q好像不是所有的人都需要关心AOPQ它可能是一U架构设计的选择Q如果选择J2EEpȝQAOPx的上q通用斚w都已l被J2EE容器实现了,J2EE应用pȝ开发者可能需要更多地x行业应用斚waspect?/font>
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource">
<ref bean="dataSource"/>
</property>
<property name="mappingResources">
<list>
<value>org/appfteaching/model/TArticleclass.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
<prop key="hibernate.jdbc.fetch_size">${hibernate.jdbc.fetch_size}</prop>
<prop key="hibernate.jdbc.batch_size">${hibernate.jdbc.batch_size}</prop>
<prop key="hibernate.cache.use_query_cache">true</prop>
<prop key="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</prop>
</props>
</property>
</bean>
2.其次,在src目录下的ehcache.xml中配|如下信?如果是默认ehcache.xml则会?lt;cache name="sampleCache1">?lt;cache name="sampleCache2>",L)
<cache name="org.hibernate.cache.StandardQueryCache"
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="300"
timeToLiveSeconds="4200"
overflowToDisk="true"
/>
<!-- Sample cache named sampleCache2
This cache contains 1000 elements. Elements will always be held in memory.
They are not expired. -->
<cache name="org.hibernate.cache.UpdateTimestampsCache"
maxElementsInMemory="5000"
eternal="true"
timeToIdleSeconds="0"
timeToLiveSeconds="0"
overflowToDisk="false"
/>
3.你要缓存的model加进ehcache.xml?/p>
<cache name="org.appfteaching.model.TArticleclass"
maxElementsInMemory="1000"
eternal="false"
timeToIdleSeconds="100"
timeToLiveSeconds="4200"
overflowToDisk="true"
/>
4.最后一?在TArticleclass.hbm.xml里加?/p>
<cache usage="read-write"/>
启动Tomcat,如发现如下错?/p>
Could not find configuration [org.hibernate.cache.UpdateTimestampsCache]; using defaults.
Could not find configuration [org.hibernate.cache.StandardQueryCache]; using defaults.
则是W二步没有做,加上卛_.配置完毕
配置非常单,在web.xml中增加: <listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> </listener> 或: <servlet> <servlet-name>context</servlet-name> <servlet-class> org.springframework.web.context.ContextLoaderServlet </servlet-class> <load-on-startup>1</load-on-startup> </servlet> |
通过以上配置QW(xu)eb容器会自动加?WEB-INF/applicationContext.xml初始?
ApplicationContext实例Q如果需要指定配|文件位|,可通过context-param加以指定Q?
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/myApplicationContext.xml</param-value>
</context-param>
配置完成之后Q即可通过
WebApplicationContextUtils.getWebApplicationContextҎ(gu)在Web应用中获取ApplicationContext引用?
如:ApplicationContext ctx=WebApplicationContextUtils.getWebApplicationContext();
LoginAction action=(LoginAction)ctx.getBean("action");
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessagePreparator;
public class SpringMail {
public static void main(String[] args) throws Exception {
ApplicationContext ctx = new FileSystemXmlApplicationContext(
"applicationContext.xml");
JavaMailSender sender = (JavaMailSender) ctx.getBean("mailSender");
SpringMail springMail = new SpringMail();
//试发送只有文本信息的单测?br> springMail.sendTextMail(sender);
//试发送带附g的邮?br> springMail.sendMimeMessage(sender);
}
/** *//**
* 试发送只有文本信息的单测?br> * @param sender 邮g发送器
* @throws Exception
*/
private void sendTextMail(JavaMailSender sender) throws Exception {
SimpleMailMessage mail = new SimpleMailMessage();
mail.setTo("superman_wshm@126.com");
mail.setFrom("superman_wshm@126.com");
mail.setSubject("test by amigo");
mail.setText("spring Mail的简单测?);
sender.send(mail);
System.out.println("成功发送文本文Ӟ");
}
/** *//**
* 发送带附g的邮?br> * @param sender 邮g发送器
* @throws Exception
*/
private void sendMimeMessage(final JavaMailSender sender) throws Exception {
//附g文g集合
final List files = new ArrayList();
MimeMessagePreparator mimeMail = new MimeMessagePreparator() {
public void prepare(MimeMessage mimeMessage) throws MessagingException {
mimeMessage.setRecipient(Message.RecipientType.TO,
new InternetAddress("superman_wshm@126.com"));
mimeMessage.setFrom(new InternetAddress("superman_wshm@126.com"));
mimeMessage.setSubject("Spring发送带附g的邮?, "gb2312");
Multipart mp = new MimeMultipart();
//向Multipartd正文
MimeBodyPart content = new MimeBodyPart();
content.setText("内含spring邮g发送的例子Q请查收!");
//向MimeMessagedQMultipart代表正文Q?br> mp.addBodyPart(content);
files.add("com/action/SpringMail.java");
files.add("applicationContext.xml");
//向Multipartd附g
Iterator it = files.iterator();
while(it.hasNext()) {
MimeBodyPart attachFile = new MimeBodyPart();
String filename = it.next().toString();
FileDataSource fds = new FileDataSource(filename);
attachFile.setDataHandler(new DataHandler(fds));
attachFile.setFileName(fds.getName());
mp.addBodyPart(attachFile);
}
files.clear();
//向MultipartdMimeMessage
mimeMessage.setContent(mp);
mimeMessage.setSentDate(new Date());
}
};
//发送带附g的邮?br> sender.send(mimeMail);
System.out.println("成功发送带附g邮g!");
}
}
<beans>
Spring配置文gapplicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "
<bean id="mailSender"
class="org.springframework.mail.javamail.JavaMailSenderImpl">
<property name="host">
<value>smtp.126.com</value>
</property>
<property name="javaMailProperties">
<props>
<prop key="mail.smtp.auth">true</prop>
<prop key="mail.smtp.timeout">25000</prop>
</props>
</property>
<property name="username">
<value>superman_wshm</value>
</property>
<property name="password">
<value>******</value>
</property>
</bean>
</beans>
刚才发现一bugQ当附g名ؓ中文Ӟ会出C文ؕ码问题,对sendMimeMessageҎ(gu)q行了部分修改,如下Q?br> sun.misc.BASE64Encoder enc = new sun.misc.BASE64Encoder();
files.add("src/SpringMail.java");
files.add("src/applicationContext.xml");
files.add("src/谢星?xml");
//向Multipartd附g
Iterator it = files.iterator();
while (it.hasNext())
{
MimeBodyPart attachFile = new MimeBodyPart();
String filename = it.next().toString();
FileDataSource fds = new FileDataSource(filename);
attachFile.setDataHandler(new DataHandler(fds));
attachFile.setFileName("=?GBK?B?"+enc.encode(fds.getName().getBytes())+"?=");
mp.addBodyPart(attachFile);
}
]]>
MVC框架如Struts、WebworkQ都在Servlet的基上创Z一个自ql对I间Q在自己的空间里定义MVC世界和规则。无个世界定义得是否漂亮Q程序员都有一个学?fn)世界的q程?/p>
而Spring MVC则完全保留着Servlet概念中的requestQresponse和sessionQƈ没有强制建立一个自q概念模型Q当Ӟ他也有很烂的SimpleFormControllerQ但你完全可以把它踢在一旁不)Q也不强刉要FormBean和一堆XML定义?/p>
同时Q它透明完成了与Spring的集成,Multi-action的派发,提供了绑定request数据用的binder{基本API?/p>
所以,如果想简单,使用Spring MVC的原始Ş态是一个很好的Q类gRoR中ActionPack的方案?/p>
推荐使用一个Controller响应一l相兛_作的MultiActionController。同Ӟ虽然一点不喜欢FormController定义的概忉|型,但还是不影响发挥拿来MQ在共性比较明昑台管理模块,定义MultiActionFormControllerQ自动完成某些共同的Form程?/p>
你还是很喜欢WebWork?好在我们也提供了sampleQ见2.4 WebWork ?/p>
也许Q所有程序员都先放下自己框架里的概念模型Q还原回一个JSP/ServletE序员的角度Q思考一个JSP/Servlet框架需要的功能?/p>
0. 配置文g
Spring的配|文仉认ؓWEB-INF/xxxx-servelet.xml?/p>
其中xxx为web.xml中org.springframework.web.servlet.DispatcherServlet的servlet-name?/p>
1. 与Spring集成及IOC
天然兮,由DispatcherServlet完成?/p>
2. Action及Multi-Action 分发
Spring按照配|文件定义的URLQMapping到具体Controllerc,再根据URL里的action= xxx或其他参敎ͼ利用反射调用Controller里对应的ActionҎ(gu)?/p>
3. 输入数据l定
Spring提供Binder 通过名字的一一对应反射l定PojoQ也可以直接从request.getParameter()取数据?/p>
如果没有另外加入框架装Q需要手工调用Binder.
4. 输入数据验证
Sping 提供?a >Validator接口Q而Spring Moduleq整合了Commons-Validaor ?/p>
5. l果数据攑֛View
有个ModelAndView的概念,代表了返回的View名及数据(ModelQ一个Map)。可以用modelAndView.addObject()攑օ数据。当Ӟ也可以直接request.setAttribute()?/p>
6. Interceptor
AOP概念Q其实Servlet里面早有Filter概念Q不qInteceptor可以更灵zȝMappingQ另提供postHandle的插入点
preHandle() handler开工之前?br /> postHandle() hander开工之后,但DispatchServletq没有渲染页面?br /> afterCompletion() 一切完工之后?br />
7. RedirectQForward面及Token防止重复提交?/strong>
Spring提供 "redirect:index.jsp", "forward:index.jsp"q样的简写?/p>
Spring Simple Form提供了防止重复提交的机制?/p>
8. 如果想直接编写Responseq回字符? 而不是返回一个View
函数的q回cd设ؓvoidQ用ss装?rendText(response,String text)函数?/p>
<bean id="methodNameResolver" class="org.springframework.web.servlet.mvc.multiaction.ParameterMethodNameResolver">
<property name="paramName">
<value>method</value>
</property>
<property name="defaultMethodName">
<value>index</value> </property> </bean>
以上配置按xxx.do?method= list 调用controller的list()Ҏ(gu)
不过q要争取早日改ؓWeb2.0式的写法./book/list.htm 要优?book.do?action= list?/p>
其余配置和其他Spring MVC配置差不多,L(fng)bookstore-servlet.xmlQ留意下面几个关键节?br /><bean id="exceptionResolver">
<bean id="methodNameResolver">
<bean id="viewResolver">
<bean id="urlMapping">(留意最新的urlMapping写语?)
l承于Spring的MultiActionController, 对其作了量扩展--主要是对数据l定的扩展,q加了一个SaveMessage函数?/p>
1.Ҏ(gu)据绑定的扩展Q?/strong>
a.InitBinder() 初始化BinderQ注册日期类q允许数字类为空?/p>
b.对Bind and Validate函数的再包装
本来Spring已有bind函数完成bind and validate, 但这个函C来没有用BindException作返回D是抛出一个ServletException只好自己另外实现一个bindObject()函数?/p>
c.另外E稍扩展了一些函C其更好用?/p>
2.SaveMessage():
如果是redirect的关p,message信息攑֜request.attribute()׃丢失QSaveMessage()其攑֜session?br /> 配合messageFilterQ在渲染面前,把它从session又移回request?
Spring MVC中的SimpleFormController中的交互机制有值得参考的部分Q但其只有一个onSubmit函数不能很好的表达CRUD的语义,所以将两者结合成Multi-ActionFormController是比较好的方法。通过U定命名Q在基类实现l(f)ist()Qcreate(){函数和默认程Q而在子类实现onList(),onCreate()函数?/p>
目前只是初步l合两者,q有很大的改q空间?/p>
参考了RoR中的命名。BaseManageControllerx照此命名定义基类?/p>