2006年10月16日

不知道大家有没有碰到,还是没有这种需求。就是用like来查询,我们没有用Lucene,Compass这种全文索引的方案,我们只是简单的添加%进行like查询。用户搜索的时候就使用*和?来代表任意和一个。所以要对"%"和"_"进行转义,我们使用的是oracle数据库。sql语句看起来可能是这样的。

Select * FROM t_user where nickname like %Goo\_D escape \

这里对_进行转义了。因为用户昵称包含下划线,如果不进行转义就表示一个任意字符。有时候我们可能还需要对%进行转义。同样的方法在%前加\% 但是比起普通的like语句。多了一个声明转义符的语句。所以我们会想到这样的语句

DetachedCriteria criteria = DetachedCriteria.forClass(User.class);
criteria.add(Restrictions.like(
"nickname", user.getNickname()+"‘ escape’\"));

但是这样是不管用的。
接下来可能会想到使用Hibernate3的原生sql查询,其实我们不需要这样做。我们还是使用Criteria条件查询。

criteria.add(Restrictions.sqlRestriction("{alias}.nickname like ? escape’/’", StringUtil.escapeSQLLike(user.getNickname()), Hibernate.STRING));

这样Hibernate产生的语句就是我们想要的语句了。

    /**
     * 转义like语句中的
     * <code>’_'</code><code>’%'</code>
     * 将<code>’?'</code>转成sql的<code>’/_’</code>
     * 将<code>’%'</code>转成sql的<code>’/%’</code>
     * <p>
     *   例如搜索<code>?aa*bb?c_d%f</code>将转化成<br/>
     *   <code>_aa%bb_c/_d/%f</code>
     * </p>
     * 
@param likeStr
     * 
@return
     * 
@author <a href="http://jdkcn.com">somebody</a>
     
*/
    
public static String escapeSQLLike(String likeStr) {
        String str 
= StringUtils.replace(likeStr, "_""/_");
        str 
= StringUtils.replace(str, "%",    "/%");
        str 
= StringUtils.replace(str, "?""_");
        str 
= StringUtils.replace(str, "*""%");
        
return str;
    }

创造共用协议:署名,非商业,保持一致   除经特别注明外,本文章版权归莫多泡泡所有.
署名,非商业用途,保持一致.   somebody(莫多)

不知道大家有没有碰到,还是没有这种需求。就是用like来查询,我们没有用Lucene,Compass这种全文索引的方案,我们只是简单的添加%进行like查询。用户搜索的时候就使用*和?来代表任意和一个。所以要对"%"和"_"进行转义,我们使用的是oracle数据库。sql语句看起来可能是这样的。

SELECT * FROM t_user where nickname like %Goo\_D escape \

这里对_进行转义了。因为用户昵称包含下划线,如果不进行转义就表示一个任意字符。有时候我们可能还需要对%进行转义。同样的方法在%前加\% 但是比起普通的like语句。多了一个声明转义符的语句。所以我们会想到这样的语句

DetachedCriteria criteria = DetachedCriteria.forClass(User.class);
criteria.add(Restrictions.like(
"nickname", user.getNickname()+"‘ escape’\"));

但是这样是不管用的。
接下来可能会想到使用Hibernate3的原生sql查询,其实我们不需要这样做。我们还是使用Criteria条件查询。

criteria.add(Restrictions.sqlRestriction("{alias}.nickname like ? escape’/’", StringUtil.escapeSQLLike(user.getNickname()), Hibernate.STRING));

这样Hibernate产生的语句就是我们想要的语句了。

    /**
     * 转义like语句中的
     * <code>’_'</code><code>’%'</code>
     * 将<code>’?'</code>转成sql的<code>’/_’</code>
     * 将<code>’%'</code>转成sql的<code>’/%’</code>
     * <p>
     *   例如搜索<code>?aa*bb?c_d%f</code>将转化成<br/>
     *   <code>_aa%bb_c/_d/%f</code>
     * </p>
     * 
@param likeStr
     * 
@return
     * 
@author <a href="http://jdkcn.com">somebody</a>
     
*/
    
public static String escapeSQLLike(String likeStr) {
        String str 
= StringUtils.replace(likeStr, "_""/_");
        str 
= StringUtils.replace(str, "%",    "/%");
        str 
= StringUtils.replace(str, "?""_");
        str 
= StringUtils.replace(str, "*""%");
        
return str;
    }

创造共用协议:署名,非商业,保持一致   除经特别注明外,本文章版权归莫多泡泡所有.
署名,非商业用途,保持一致.   somebody(莫多)

不知道大家有没有碰到,还是没有这种需求。就是用like来查询,我们没有用Lucene,Compass这种全文索引的方案,我们只是简单的添加%进行like查询。用户搜索的时候就使用*和?来代表任意和一个。所以要对"%"和"_"进行转义,我们使用的是oracle数据库。sql语句看起来可能是这样的。

SELECT * FROM t_user where nickname like %Goo\_D escape \

这里对_进行转义了。因为用户昵称包含下划线,如果不进行转义就表示一个任意字符。有时候我们可能还需要对%进行转义。同样的方法在%前加\% 但是比起普通的like语句。多了一个声明转义符的语句。所以我们会想到这样的语句

DetachedCriteria criteria = DetachedCriteria.forClass(User.class);
criteria.add(Restrictions.like(
"nickname", user.getNickname()+"‘ escape’\"));

但是这样是不管用的。
接下来可能会想到使用Hibernate3的原生sql查询,其实我们不需要这样做。我们还是使用Criteria条件查询。

criteria.add(Restrictions.sqlRestriction("{alias}.nickname like ? escape’/’", StringUtil.escapeSQLLike(user.getNickname()), Hibernate.STRING));

这样Hibernate产生的语句就是我们想要的语句了。

    /**
     * 转义like语句中的
     * <code>’_'</code><code>’%'</code>
     * 将<code>’?'</code>转成sql的<code>’/_’</code>
     * 将<code>’%'</code>转成sql的<code>’/%’</code>
     * <p>
     *   例如搜索<code>?aa*bb?c_d%f</code>将转化成<br/>
     *   <code>_aa%bb_c/_d/%f</code>
     * </p>
     * 
@param likeStr
     * 
@return
     * 
@author <a href="http://jdkcn.com">somebody</a>
     
*/
    
public static String escapeSQLLike(String likeStr) {
        String str 
= StringUtils.replace(likeStr, "_""/_");
        str 
= StringUtils.replace(str, "%",    "/%");
        str 
= StringUtils.replace(str, "?""_");
        str 
= StringUtils.replace(str, "*""%");
        
return str;
    }

创造共用协议:署名,非商业,保持一致   除经特别注明外,本文章版权归莫多泡泡所有.
署名,非商业用途,保持一致.   somebody(莫多)

不知道大家有没有碰到,还是没有这种需求。就是用like来查询,我们没有用Lucene,Compass这种全文索引的方案,我们只是简单的添加%进行like查询。用户搜索的时候就使用*和?来代表任意和一个。所以要对"%"和"_"进行转义,我们使用的是oracle数据库。sql语句看起来可能是这样的。

SELECT * FROM t_user where nickname like %Goo\_D escape \

这里对_进行转义了。因为用户昵称包含下划线,如果不进行转义就表示一个任意字符。有时候我们可能还需要对%进行转义。同样的方法在%前加\% 但是比起普通的like语句。多了一个声明转义符的语句。所以我们会想到这样的语句

DetachedCriteria criteria = DetachedCriteria.forClass(User.class);
criteria.add(Restrictions.like(
"nickname", user.getNickname()+"‘ escape’\"));

但是这样是不管用的。
接下来可能会想到使用Hibernate3的原生sql查询,其实我们不需要这样做。我们还是使用Criteria条件查询。

criteria.add(Restrictions.sqlRestriction("{alias}.nickname like ? escape’/’", StringUtil.escapeSQLLike(user.getNickname()), Hibernate.STRING));

这样Hibernate产生的语句就是我们想要的语句了。

    /**
     * 转义like语句中的
     * <code>’_'</code><code>’%'</code>
     * 将<code>’?'</code>转成sql的<code>’/_’</code>
     * 将<code>’%'</code>转成sql的<code>’/%’</code>
     * <p>
     *   例如搜索<code>?aa*bb?c_d%f</code>将转化成<br/>
     *   <code>_aa%bb_c/_d/%f</code>
     * </p>
     * 
@param likeStr
     * 
@return
     * 
@author <a href="http://jdkcn.com">somebody</a>
     
*/
    
public static String escapeSQLLike(String likeStr) {
        String str 
= StringUtils.replace(likeStr, "_""/_");
        str 
= StringUtils.replace(str, "%",    "/%");
        str 
= StringUtils.replace(str, "?""_");
        str 
= StringUtils.replace(str, "*""%");
        
return str;
    }

创造共用协议:署名,非商业,保持一致   除经特别注明外,本文章版权归莫多泡泡所有.
署名,非商业用途,保持一致.   somebody(莫多)

2006年08月10日

 jspark 的这篇文章《开发阶段eclipse下面的spring容器的启动优化 》讲到如何加快spring的启动速度。非常感谢jspark. 一下是引用的原文:

  最近在负责一个大项目,项目组成员包括项目经理大概10个人左右。项目技术用struts+spring+hibernate实现。项目的规模相对来说是比较大的,总共有10大模块,每个大模块又分为有十几个、甚至几十个小模块。开发工具用eclipse,由于在开发阶段,项目开发成员需要频繁重启服务器。在启动服务器的时候,每次启动时间总是会超过1分钟。记得以前在做另外一个项目时,启动时间不到5秒钟,相差了10倍,而且项目规模是差不多的。

    从初步分析来说,应该是hibernate解释hbm.xml时花费时间,或者可能是spring容器启动并解释所有的bean配置文件。诊断了一下,发现1分钟消耗的时间主要分布在hibernate解释hbm.xml花费5秒;spring容器从启动到解释bean配置文件竟然花了58秒,真是太嚣张了。当时非常怀疑spring的效率问题。企图从网上搜索相关资料,看看有什么优化措施。

    首先是找到了hibernate的启动优化 http://www.hibernate.org/194.html  里面的主要思想是通过将xml序列花到本地的文件里,每次读取的时候根据情况,从本地文件读取并反序列化,节省了hibernate xml的解析时间。按照这个方式测试了一下,发现hibernate的启动时间从5秒降低到3秒,但是这个优化对于整个启动过程是杯水车薪的,毫无用处。

    没办法,又仔细查看了spring的资料,终于发现spring的容器是提供了lazy-load的,即默认的缺省设置是bean没有lazy- load,该属性处于false状态,这样导致spring在启动过程导致在启动时候,会默认加载整个对象实例图,从初始化ACTION配置、到 service配置到dao配置、乃至到数据库连接、事务等等。这么庞大的规模,难怪spring的启动时间要花将近1分钟。尝试了一下,把beans的 default-lazy-init改为true就,再次启动,速度从原来的55秒,降到8秒钟!!Great!虽然是非常小一个改动,但是影响确实非常大。一个项目组10个人,假若每个人一天平均需要在eclipse下启动测试服务器50次。那么一天项目组需要重启500次,每次节省50秒的话,就是 25000秒,将近几个小时,差不多一个工作日,多么可观的数字!

   不过在运行期间第一次点页面的时候,由于spring做了lazy-load,现在就需要启动一部分需要的beans,所以稍微慢2-3秒钟,但是明显比等几十秒要快很多,值得一鉴。

    以上是针对开发阶段的spring容器启动优化,在部署到实际环境中,倒是没必要设置为lazy-load。毕竟部署到实际环境中不是经常的事,每次启动1分钟倒不是大问题。

我这里要提醒的是不是说有的beans都能设置default-lazy-init成为true.对于scheduler的bean不能用lazy-init

<beans default-lazy-init="true">
    
    
<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
        
<property name="triggers">
            
<list>
                
<ref bean="buildHtmlTrigger"/>
                
<ref bean="askTrigger"/>
                
<ref bean="mailSenderTrigger"/>
                
<ref bean="topicDetailBuildTrigger"/>
                
<ref bean="forumBuildTrigger"/>
                
<ref bean="topicBuildTrigger"/>
            
</list>
        
</property>
    
</bean>
</beans>

这样的话。所有的scheduler就都不管用了。所以请大家要注意。

<beans>
    
    
<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
        
<property name="triggers">
            
<list>
                
<ref bean="buildHtmlTrigger"/>
                
<ref bean="askTrigger"/>
                
<ref bean="mailSenderTrigger"/>
                
<ref bean="topicDetailBuildTrigger"/>
                
<ref bean="forumBuildTrigger"/>
                
<ref bean="topicBuildTrigger"/>
            
</list>
        
</property>
    
</bean>
</beans>

创造共用协议:署名,非商业,保持一致   除经特别注明外,本文章版权归莫多泡泡所有.
署名,非商业用途,保持一致.   somebody(莫多) 

2006年07月22日

只是自己的想法,不对不要扔鸡蛋哦。

今天突发奇想的实现一个小小的cache。把分类categories放入map中,cache起来。

    private void cache() {
        
if(log.isDebugEnabled()){
            log.debug(
"Starting cache the categories");
        }
        cacheCategoryMap 
= new HashMap();
        cacheCategoryMap.put(
"categories",categoryDao.getCategories());
    }

然后我想在interceptor里面把categories写到ognlvaluestack里面这样我在ftl里面就可以<#list categories>….</#list>了。因为这个是在每个页面的header.ftl里面的。我也就不需要再每个 action里面去get一下了。
刚开始我implements Interceptor

        final OgnlValueStack stack = ActionContext.getContext().getValueStack();
        stack.setValue(
"categories" ,categoryManager.getCategories());
        
return invocation.invoke();

可是这样也不可以。后来我想到是不是action执行完毕之后就把stack中的这个值清空了我又用了。AroundInterceptor 我想在after里面去设置不就可以了。

    protected void after(ActionInvocation dispatcher, String result) throws Exception {
        
final OgnlValueStack stack = ActionContext.getContext().getValueStack();
        stack.setValue(
"categories" ,categoryManager.getCategories());
    }

可是这样还是不可以。我晕了。我想是不是要在action里面声明一下categories。

    private List categories;

    public List getCategories() {
        
return categories;
    }

    public void setCategories(List categories) {
        
this.categories = categories;
    }

然后在before里面去get就可以了。

    protected void before(ActionInvocation invocation) throws Exception {
        
final OgnlValueStack stack = ActionContext.getContext().getValueStack();
        stack.setValue(
"categories" ,categoryManager.getCategories());
    }

总算实现了。不过还要在每个action里面声明一下categories,这样还是很不好的。刚才有人建议用filter。我在试试吧.

创造共用协议:署名,非商业,保持一致   除经特别注明外,本文章版权归莫多泡泡所有.
署名,非商业用途,保持一致.   somebody(莫多)  

 

以前一直都没有试过,前几天打算把wordpress换成自己写的程序,就想到了数据的导入和导出,首先想到的是用数据库工具来导。可是觉得有些麻烦,我自己的程序是用spring+hibernate的。后来我就试了一下spring的JdbcTemplate,就和HibernateTemplate 一样的好用。首先增加一个连接到wp数据库的dataSource

    <bean id="dataSource2" class="org.springframework.jdbc.datasource.DriverManagerDataSource" destroy-method="close">
        
<property name="driverClassName"><value>org.hibernate.dialect.MySQLDialect</value></property>
        
<property name="url">
            
<value>jdbc:mysql://192.168.0.240:3306/wordpressωuseUnicode=true&amp;characterEncoding=utf8</value>
            
</property>
        
<property name="username"><value>root</value></property>
        
<property name="password"><value></value></property>
    
</bean>

    然后在转换程序里面get这个dataSource,new 一个JdbcTemplate(dataSource2),这样就ok了。很简单吧。

    public void testCopyData() throws Exception{
        DataSource ds 
= (DataSource)applicationContext.getBean("dataSource2");
        
        CategoryManager cateManager 
= (CategoryManager) applicationContext.getBean("categoryManager");
        
        JdbcTemplate jt 
= new JdbcTemplate(ds);
        System.out.println(
"Total posts:"+jt.queryForInt("select count(*) from wp_posts"));
        assertNotNull(ds);
        
        List cates 
= jt.queryForList("select * from wp_categories");
        
int i= 0;
        
for(Iterator ite = cates.iterator(); ite.hasNext();){
            i
++;
            Map result 
= (Map) ite.next();
            Category cate 
= new Category();
            cate.setName((String)result.get(
"cat_name"));
            cate.setOrder(i);
            
if(i==1)
                cate.setDefaultCategory(
true);
            cateManager.saveCategory(cate);
            System.out.println(
"cat_name:"+result.get("cat_name")+"\n");
        }
    }

创造共用协议:署名,非商业,保持一致   除经特别注明外,本文章版权归莫多泡泡所有.
署名,非商业用途,保持一致.   somebody(莫多)  

Rss,Atom,基本上是Web2.0的基本特征,今天终于有时间决定实现一下。对于动态的Rss,Atom其实就是选取最新的内容,迭迨一下生成一个固定格式的xml文件就可以了。其实也很简单。
       我用webwork2,用freemarker做模版,在网上找了一个标准的Rss2.0格式就生成我的模版文件rss.ftl

<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
<channel>
<title><![CDATA[我的小站]]></title>
<link>http://leaf.jdk.cn/</link>
<description><![CDATA[泡出好心情,泡出好技术]]></description>
<language>zh-cn</language>
<copyright><![CDATA[Copyright 2006 PaoPao v4.0]]></copyright>
<webMaster><![CDATA[rory.cn@gmail.com (Rory Ye)]]></webMaster>
<generator>PaoPao v4.0</generator> 
    
<image>
        
<title>我的小站</title> 
        
<url>http://leaf.jdk.cn/logo.gif</url> 
        
<link>http://leaf.jdk.cn</link> 
        
<description>莫多泡泡2006</description> 
    
</image>
    
<#list blogs as blog>
    
<item>
        
<link>http://leaf.jdk.cn/entry.action?entryId=${blog.id}</link>
        
<title><![CDATA[${blog.title}]]></title>
        
<author>${blog.authorMail}(${blog.author})</author>
        
<category><![CDATA[ ${blog.categories} ]]></category>
        
<pubDate>${blog.pubDate}</pubDate>
        
<guid>http://leaf.jdk.cn/entry.action?id=${blog.id}</guid>    
        
<description><![CDATA[${blog.content}]]></description>
    
</item>
    
</#list>
</channel>
</rss>

我在rss.action里面去取blogs就可以了。

    public String execute() throws Exception {
        PaginationSupport ps 
= blogManager.getBlogsByPage(0);
        blogs 
= new ArrayList();
        
        
for(Iterator ite = ps.getItems().iterator(); ite.hasNext();){
            Blog blog 
= (Blog)ite.next();
            WrapRssBlog wrapBlog 
= new WrapRssBlog();
            wrapBlog.setId(blog.getId());
            wrapBlog.setAuthor(blog.getAuthor().getNickname());
            wrapBlog.setAuthorMail(blog.getAuthor().getMail());
            wrapBlog.setTitle(blog.getTitle());
            wrapBlog.setContent(StringUtil.extractText(blog.getContent()));
            wrapBlog.setPubDate(DateUtil.formatRssDate(blog.getPostTime()));
            StringBuffer sb 
= new StringBuffer();
            
for(Iterator ite2 = blog.getCategories().iterator(); ite2.hasNext();){
                Category cate 
= (Category) ite2.next();
                sb.append(
" ")
                  .append(cate.getName());
            }
            wrapBlog.setCategories(sb.toString());
            blogs.add(wrapBlog);
        }
        
return super.execute();
    }

这里把blog包装了一下,主要是处理了一下日期,内容,还有把分类拼成字符串。关于日期的处理,参考了飞云小侠写的rss日期的研究。实现代码如下。

    public static String formatRssDate(Date date){
        SimpleDateFormat sdf 
= new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss z",Locale.US);
        
//TODO TimeZone
        SimpleTimeZone zone = new SimpleTimeZone(8,"GMT");
        sdf.setTimeZone(zone);
        
return sdf.format(date);
    }

这样就得到了这样的日期
Thu, 6 Apr 2006 16:01:36 GMT
做好了这些,配置一下action

        <action name="rss" class="cn.jdk.leaf.action.RssAction">        
            
<result name="success" type="freemarker">/WEB-INF/pages/rss.ftl</result>
        
</action>

不过像这样配置的话,你访问http://xxx.xxx.com/rss.action看到的不是一个xml
因为返回结果的contentType是text/html.而不是xml,这样是不行的。看了一下webwork源码。原来可以这样简单的解决。改成这样配置就可以了。

        <action name="rss" class="cn.jdk.leaf.action.RssAction">
            
<result name="success" type="freemarker">
                
<param name="location">/WEB-INF/pages/rss.ftl</param>
                
<param name="contentType">application/xml</param>
            
</result>
        
</action>

简单吧。其实你还可以把这个contentType改成其他类型的。比如excle的。这样用户执行就可以得到一个xls文件。哈哈。

 创造共用协议:署名,非商业,保持一致   除经特别注明外,本文章版权归莫多泡泡所有.
署名,非商业用途,保持一致.   somebody(莫多)  

前面一篇文章提到通过webwork的interceptor给webwork的action设置初始值,

如何给webwork的action里的Field设置初始值

jdev说到"为什么要放在这里,而不是放到系统配置文件中,然后在系统设置界面中提供设置",后来我就用spring来注入了。现在就把值放入properties文件中了。

    <bean id="propertyPlaceholderConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
      
<property name="locations">
        
<list>
          
<value>classpath:mail.properties</value>
          
<value>classpath:upload.properties</value>
        
</list>
      
</property>
    
</bean>
    
<!– 收发外部邮箱 author:somebody–>
    
<bean id="outMailManager" class="cn.com.fivefortunes.mail.manager.impl.OutMailManagerImpl">
        
<property name="javaMailSender"><ref bean="javaMailSender"/></property>
        
<property name="attachementDirectory"><value>${mail.attachementDirectory}</value></property>
        
<property name="uploadFileDirectory"><value>${upload.directory}</value></property>
        
<property name="outMailHibernateManager"><ref bean="outMailHibernateManager"/></property>
        
<property name="outMailAccountManager"><ref bean="outMailAccountManager"/></property>
    
</bean>

这样把uploadFileDirectory放入mananger中去了。在properties里面配置一下就ok了。


upload.directory
=D:\\tomcat5\\webapps\\files
mail.attachementDirectory
=D:\\tomcat5\\webapps\\files

上次还有网友这样说到"return ServletActionContext.getServletContext().getRealPath("/");

你这样换了部署环境每次都要改
而且也该是
D://tomcat5//webapps//files"
也许很多人都以为这是最好的方式,可是实际情况不是这样,我们的uploadfile目录已经有3G的文件,而基本上每天我们都要发布新的webapp,如果把uploadfile目录放到webapp的一个子目录,每次部署的时候都要先把uploadfile copy出来然后再部署。所以我们这么做就是把upload目录放到其他目录不影响uploadfile目录里面的文件。关于我们项目的部署见我的下一篇文章。谢谢大家。如果您有什么更好的方法请您指教。

创造共用协议:署名,非商业,保持一致   除经特别注明外,本文章版权归莫多泡泡所有.
署名,非商业用途,保持一致.   somebody(莫多)  

 

我们的项目比较特殊,基本上每天都要发布一次。为了不影响系统的正常使用,我们的做法是在下班之前把打包好的war放到服务器的一个目录下面(eg:d: \bak)。然后用windows的计划任务在晚上12点自动部署系统,也就是net stop tomcat,删除xx.war,删除xx,然后把d:\bak\xx.war拷贝到webapps下面。然后再net start tomcat。这样在第二天来的上班的时候就可以使用升级过的系统了。也不会影响其他人的使用,不需要中断操作。
    关于项目的一个配置我的前几篇文章我也提到过,那个upload的问题就不会发生了。还有就是关于项目开发中的一些问题。比如数据库的连接地址, upload directory的配置等,这些在团队中的每个人都是不一样的,那么在发布的时候都要改成服务器上的正确配置,如果一个月部署一次这到没有什么。但是像我们这样每天部署就不是那么轻松了。而且如果一时不注意很容易造成配置的不正确。所以对于很多配置文件我们都有两份。一份是用户自己开发用的,一份是部署到服务器的配置,这样在开发的时候团队中的每个人都不一样,关于服务器的配置都是一样的,在发布的时候是用的服务器的配置而不是用开发用的配置。eg: web.xml(个人的配置)web-dest.xml 而关键的配置也就是下面这段。
web.xml

    <context-param>
        
<param-name>contextConfigLocation</param-name>
        
<param-value>
            classpath:spring/*_context.xml,
            classpath:spring/global.xml 

        
</param-value>
    
</context-param>

web-dest.xml

    <context-param>
        
<param-name>contextConfigLocation</param-name>
        
<param-value>
            classpath:spring/*_context.xml,
            classpath:spring/global-dest.xml,
            classpath:spring/scheduler.xml
        
</param-value>
    
</context-param>

注意到其中不一样的。dest里少了scheduler.xml这个主要是定时执行的一些任务,一般在开发的时候都不需要,去掉也可以提升速度,也不会出现那么多的log。还有就是发布的web.xml用了global-dest.xml这个是关于spring的总的配置。
global.xml

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        
<property name="driverClassName"><value>net.sourceforge.jtds.jdbc.Driver</value></property>
        
<property name="url">
            
<value>jdbc:jtds:sqlserver://192.168.0.240:1433/fivefortunes;SelectMethod=cursor</value>
            
</property>
        
<property name="username"><value>sa</value></property>
        
<property name="password"><value></value></property>
    
</bean>
    
    
<bean id="dataSource2" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        
<property name="driverClassName"><value>net.sourceforge.jtds.jdbc.Driver</value></property>
        
<property name="url">
            
<value>jdbc:jtds:sqlserver://192.168.0.240:1433/outmail;SelectMethod=cursor</value>
            
</property>
        
<property name="username"><value>sa</value></property>
        
<property name="password"><value></value></property>
    
</bean>
    
    
<bean id="customDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        
<property name="driverClassName"><value>net.sourceforge.jtds.jdbc.Driver</value></property>
        
<property name="url">
            
<value>jdbc:jtds:sqlserver://192.168.0.240:1433/custom;SelectMethod=cursor</value>
            
</property>
        
<property name="username"><value>sa</value></property>
        
<property name="password"><value></value></property>
    
</bean>

global-dest.xml

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        
<property name="driverClassName"><value>net.sourceforge.jtds.jdbc.Driver</value></property>
        
<property name="url">
            
<value>jdbc:jtds:sqlserver://192.168.0.5:1433/fivefortunes;SelectMethod=cursor</value>
            
</property>
        
<property name="username"><value>sa</value></property>
        
<property name="password"><value></value></property>
    
</bean>
    
    
<bean id="dataSource2" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        
<property name="driverClassName"><value>net.sourceforge.jtds.jdbc.Driver</value></property>
        
<property name="url">
            
<value>jdbc:jtds:sqlserver://192.168.0.5:1433/outmail;SelectMethod=cursor</value>
            
</property>
        
<property name="username"><value>sa</value></property>
        
<property name="password"><value></value></property>
    
</bean>
    
    
<bean id="customDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        
<property name="driverClassName"><value>net.sourceforge.jtds.jdbc.Driver</value></property>
        
<property name="url">
            
<value>jdbc:jtds:sqlserver://192.168.0.5:1433/custom;SelectMethod=cursor</value>
            
</property>
        
<property name="username"><value>sa</value></property>
        
<property name="password"><value></value></property>
    
</bean>

还有关于一些properties文件我们采用了用ant部署的时候改名字来达到目的。
build.xml

        <move file="${dist.dir}/mail.properties" tofile="${dist.dir}/mail-dev.properties" />
        
<copy file="${dist.dir}/mail-dest.properties" tofile="${dist.dir}/mail.properties" />
        
<move file="${dist.dir}/upload.properties" tofile="${dist.dir}/upload-dev.properties" />
        
<copy file="${dist.dir}/upload-dest.properties" tofile="${dist.dir}/upload.properties" />

这个是在war之前做的,大家眼看也就明白吧,就是把xx-dest.properties,改名成xx.propeties。在打完包之后

        <move file="${dist.dir}/mail-dev.properties" tofile="${dist.dir}/mail.properties" />
        
<move file="${dist.dir}/upload-dev.properties" tofile="${dist.dir}/upload.properties" />

这样就达到了我们无忧的目的了。只要每天部署的时候保证程序能正常运行,ant war一下就安心部署吧。
以上就是全部内容,如果有什么不正确欢迎砸板砖。

创造共用协议:署名,非商业,保持一致   除经特别注明外,本文章版权归莫多泡泡所有.
署名,非商业用途,保持一致.   somebody(莫多)