风人园

弱水三千,只取一瓢,便能解渴;佛法无边,奉行一法,便能得益。
随笔 - 99, 文章 - 181, 评论 - 56, 引用 - 0
数据加载中……

2006年12月29日

Spring boot+Spring Security 4配置整合实例

http://blog.csdn.net/code__code/article/details/53885510

1. 使用Spring Security管理用户身份认证、登录退出

2. 用户密码加密及验证

3. 采用数据库的方式实现Spring Securityremember-me功能

4. 获取登录用户信息。

5.使用Spring Security管理url和权限

posted @ 2018-03-19 21:02 风人园 阅读(301) | 评论 (0)编辑 收藏

spring security 参数配置

     摘要:         // 自定义登录页面          http.csrf().disable().formLogin().loginPage("/login")  //指定登录页的路径&n...  阅读全文

posted @ 2018-03-19 20:33 风人园 阅读(421) | 评论 (0)编辑 收藏

spring quartz 串行配置

<bean id="jobDetail7"class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">

                   <propertyname="targetObject" ref="billingBillTask"></property>

                   <propertyname="targetMethod" value="executeInternal" />

                   <propertyname="concurrent" value="false" />

         </bean>

         <beanid="billingBillTask"class="com.dangdang.tms.job.schedule.bms.BillingBillTask"/>

         <beanid="cronTriggerBean7" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">

                   <propertyname="jobDetail" ref="jobDetail7"></property>

                   <propertyname="cronExpression" value="0/5 * * * * ?"></property>

         </bean>

参考 http://blog.csdn.net/lkforce/article/details/51841890

posted @ 2018-03-12 19:58 风人园 阅读(373) | 评论 (0)编辑 收藏

spring 3.0 async 异步方法 设置

为了解决一些比较费时且不是很紧要的任务,将此任务转为异步任务处理,提高前端操作体验。 spring 中 自带注解 @Async. 配置如下 applicationContext.xml 中 增加 task的引用 如上配置之后,只需要在 需要进行异步调用的方法前面增加 注解就可以了。 @Async public void updateOrderBillItemPQty(String deptId, String orderNo, Integer orderItemSid, Double pQty) { 注:需要注意,同一个对象里面方法调用,不会作为异步方法执行。

posted @ 2017-05-24 14:27 风人园 阅读(248) | 评论 (0)编辑 收藏

android ResourceNotFoundException


在对 TextView 或者 EditText 进行赋值时,调用setText()方法,一定要注意,使用String类型,不要使用int 或者long,否则 会出现找不到资源的异常。系统自动会将int作为一个资源ID,然后去R 里面找,结果找不到。

posted @ 2016-12-21 20:48 风人园 阅读(125) | 评论 (0)编辑 收藏

android 系统提示对话框(AlertDialog)的使用(zt)

     摘要: http://blog.csdn.net/meng425841867/article/details/8523730 在按键单击事件中添加创建对话框并设置相关属性。        [java] view plain copy dialogButton=(Button)findViewBy...  阅读全文

posted @ 2016-12-02 12:54 风人园 阅读(464) | 评论 (0)编辑 收藏

Android 自定义ListView adapter(zt)

     摘要: http://daoshud1.iteye.com/blog/1874241 本文讲实现一个自定义列表的Android程序,程序将实现一个使用自定义的适配器(Adapter)绑定 数据,通过contextView.setTag绑定数据有按钮的ListView。 系统显示列表(ListView)时,首先会实例化一个适配器,本文将实例化一个自定义的适配器。实现 自定义适...  阅读全文

posted @ 2016-12-01 13:13 风人园 阅读(156) | 评论 (0)编辑 收藏

Android之SimpleAdapter简单实例和SimpleAdapter参数说明(zt)

     摘要: http://blog.csdn.net/x605940745/article/details/11981049 SimpleAdapter的参数说明 第一个参数 表示访问整个android应用程序接口,基本上所有的组件都需要 第二个参数表示生成一个Map(String ,Object)列表选项 第三个参数表示界面布局的id  表示该文件作为列表项的组件&...  阅读全文

posted @ 2016-12-01 13:12 风人园 阅读(171) | 评论 (0)编辑 收藏

android开发教程之listview使用方法

首先是布局文件,这里需要两个布局文件,一个是放置列表控件的Activity对应的布局文件 main.xml,另一个是ListView中每一行信息显示所对应的布局 list_item.xml 这一步需要注意的问题是ListView 控件的id要使用Android系统内置的 android:id="@android:id/list"

main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width
="match_parent"
    android:layout_height
="match_parent"
    android:orientation
="vertical" >
        
<ListView 
        
android:id="@android:id/list"
        android:layout_width
="match_parent"
        android:layout_height
="match_parent"
        android:padding
="20dip"/>
</LinearLayout>

list_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width
="match_parent"
android:layout_height
="match_parent"
android:orientation
="horizontal" >

<TextView
android:id="@+id/user_name"
android:layout_width
="match_parent"
android:layout_height
="match_parent"
android:layout_weight
="1"/>
<TextView
android:id="@+id/user_id"
android:layout_width
="match_parent"
android:layout_height
="match_parent"
android:layout_weight
="1"/>
</LinearLayout>


然后就设置MainActivity中的代码了:基本思想就是先将数据添加到ArrayList中,然后在设置SimpleAdapter适配器完成设置,入下:

package com.example.android_newlistview;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import android.os.Bundle;
import android.app.Activity;
import android.app.ListActivity;
import android.view.Menu;
import android.widget.SimpleAdapter;

public class MainActivity extends ListActivity {


String[] from
={"name","id"}; //这里是ListView显示内容每一列的列名
int[] to={R.id.user_name,R.id.user_id}; //这里是ListView显示每一列对应的list_item中控件的id

String[] userName
={"zhangsan","lisi","wangwu","zhaoliu"}; //这里第一列所要显示的人名
String[] userId={"1001","1002","1003","1004"}; //这里是人名对应的ID

ArrayList
<HashMap<String,String>> list=null;
HashMap
<String,String> map=null;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//为MainActivity设置主布局
//创建ArrayList对象;
list=new ArrayList<HashMap<String,String>>();
//将数据存放进ArrayList对象中,数据安排的结构是,ListView的一行数据对应一个HashMap对象,
//HashMap对象,以列名作为键,以该列的值作为Value,将各列信息添加进map中,然后再把每一列对应
//的map对象添加到ArrayList中

for(int i=0; i<4; i++){
map
=new HashMap<String,String>(); //为避免产生空指针异常,有几列就创建几个map对象
map.put("id", userId[i]);
map.put(
"name", userName[i]);
list.add(map);
}


//创建一个SimpleAdapter对象
SimpleAdapter adapter=new SimpleAdapter(this,list,R.layout.list_item,from,to);
//调用ListActivity的setListAdapter方法,为ListView设置适配器
setListAdapter(adapter);
}

}


另外对点击某一行作出响应的方法是覆写onListItemClick方法,根据返回的position(从0开始):
@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
// TODO Auto-generated method stub
super.onListItemClick(l, v, position, id);
}


posted @ 2016-12-01 13:08 风人园 阅读(143) | 评论 (0)编辑 收藏

android json 数据解析



单数据{'singer':{'id':01,'name':'tom','gender':'男'}} 
多个数据{"singers":[ 
        {'id':02,'name':'tom','gender':'男'}, 
         {'id':03,'name':'jerry,'gender':'男'}, 
{'id':04,'name':'jim,'gender':'男'}, 
{'id':05,'name':'lily,'gender':'女'}]}          
// 普通Json数据解析 
    private void parseJson(String strResult) 
        
try 
            JSONObject jsonObj 
= new JSONObject(strResult).getJSONObject("singer"); 
            
int id = jsonObj.getInt("id"); 
            String name 
= jsonObj.getString("name"); 
            String gender 
= jsonObj.getString("gender"); 
            tvJson.setText(
"ID号"+id + ", 姓名:" + name + ",性别:" + gender); 
        }
 catch (JSONException e) 
            System.out.println(
"Json parse error"); 
            e.printStackTrace(); 
        }
 
    }
 
    
//解析多个数据的Json
   private void parseJsonMulti(String strResult) 
       
try 
            JSONArray jsonObjs 
= new JSONObject(strResult).getJSONArray("singers"); 
            String s 
= ""
            
for(int i = 0; i < jsonObjs.length() ; i++)
                JSONObject jsonObj 
= ((JSONObject)jsonObjs.opt(i)).getJSONObject("singer"); 
                
int id = jsonObj.getInt("id"); 
                String name 
= jsonObj.getString("name"); 
                String gender 
= jsonObj.getString("gender"); 
                s 
+=  "ID号"+id + ", 姓名:" + name + ",性别:" + gender+ "\n" ; 
            }
 
            tvJson.setText(s); 
        }
 catch (JSONException e) 
            System.out.println(
"Jsons parse error !"); 
            e.printStackTrace(); 
        }
 
    }
 

posted @ 2016-11-29 15:09 风人园 阅读(150) | 评论 (0)编辑 收藏

button onClick 事件的几种调用方式



  1. //第一种方式    
  2.         Button Btn1 = (Button)findViewById(R.id.button1);//获取按钮资源    
  3.         Btn1.setOnClickListener(new Button.OnClickListener(){//创建监听    
  4.             public void onClick(View v) {    
  5.                 String strTmp = "点击Button01";    
  6.                 Ev1.setText(strTmp);    
  7.             }    
  8.   
  9.         });   

  1.     //第二种方式(Android1.6版本及以后的版本中提供了,直接在layout中设置)    
  2.     public void Btn3OnClick(View view){    
  3.         String strTmp="点击Button03";  
  4.         Ev1.setText(strTmp);  
  5.   
  6.     }  

  1.  <Button  
  2.         android:id="@+id/button3"  
  3.         android:layout_width="wrap_content"  
  4.         android:layout_height="wrap_content"  
  5.         android:text="Button3"   
  6.         android:onClick="Btn3OnClick"/>  


第三种方式 activity 实现 单击监听接口

public class TestButtonActivity extends Activity implements OnClickListener {
Button btn1, btn2;
Toast tst;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test_button);
btn1 = (Button) findViewById(R.id.button1);
btn2 = (Button) findViewById(R.id.button2);
btn1.setOnClickListener(this);
btn2.setOnClickListener(this);
}
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
switch (v.getId()) {
case R.id.button1:
tst = Toast.makeText(this, "111111111", Toast.LENGTH_SHORT);
tst.show();
break;
case R.id.button2:
tst = Toast.makeText(this, "222222222", Toast.LENGTH_SHORT);
tst.show();
break;
default:
break;
}
}
}




 

posted @ 2016-11-29 13:31 风人园 阅读(894) | 评论 (0)编辑 收藏

打开activity的几种方式


一、直接打开,不传递参数
Intent intent = new Intent(this, Activity.class);
startActivity(intent);


二、传递参数
public void OpenNew(View v) {
    
//新建一个显式意图,第一个参数为当前Activity类对象,第二个参数为你要打开的Activity类
    Intent intent =new Intent(MainActivity.this,MainActivity2.class);
    
    
//用Bundle携带数据
    Bundle bundle=new Bundle();
    
//传递name参数为tinyphp
    bundle.putString("name""tinyphp");
    intent.putExtras(bundle);
    
    startActivity(intent);       
 //1.要关闭的页面  
    protected void onCreate(Bundle savedInstanceState) {  
        
super.onCreate(savedInstanceState);  
        setContentView(R.layout.otheractivity);  
        Intent intent 
= this.getIntent();  
        intent.putExtra(
"tel"12345);  
        
//设置requestCode和带有数据的intent对象  
        OtherActivity.this.setResult(3, intent);  
        
//马上关闭Activity  
        this.finish();  
    }
  
      
    
//2.上面的页面关闭时,此页面进行数据的接收  
    class ButtonListener implements android.view.View.OnClickListener{  
        @Override  
        
public void onClick(View arg0) {  
            Intent intent 
= new Intent();  
            intent.setClass(MainActivity.
this, OtherActivity.class);  
            
//与普通的start方法不同,需要设置requestCode  
            startActivityForResult(intent, 1);  
        }
  
    }
  
      
    
//如果要进行此操作,需要在数据接收页面中复写activity的onActivityResul()方法  
    @Override  
    
protected void onActivityResult(int requestCode, int resultCode, Intent data) {  
        
super.onActivityResult(requestCode, resultCode, data);  
        
int tel = 0;  
        
//根据返回码resultCode来判断下一步进行的业务代码  
        if(resultCode==3){  
            tel 
= data.getIntExtra("tel"0);  
        }
  
        Log.i(TAG, 
"tel--------->"+String.valueOf(tel));  
    }
  
 
    }



三、回传参数


posted @ 2016-11-29 13:24 风人园 阅读(433) | 评论 (0)编辑 收藏

spring mvc @ExceptionHandler 异常处理

spring mvc 统一的异常处理,有两种方式。
一、exceptionResolver
二、ExceptionHandler

两者不能同时配置。如果配置了第一种,则第二种无效。就因为这个原因,找了一天的问题。

ExceptionHandler 通过注解的方式,进行配置,只需要在某个controller 中设置了这个注解,则这个controller中的所有异常都会通过这个方法进行处理。

比如rest controller,增加一个
    @ExceptionHandler
    
public String exp(HttpServletRequest request, Exception ex) {  
        
        Map map 
= new HashMap();
        
        logger.error(
"error," + UUID.randomUUID().toString(), ex);
        request.setAttribute(
"ex", ex);  
        
        String msg 
= ex.getMessage();
        
        map.put(
"success""0"); 
        map.put(
"msg", msg);
        
        String rtnjson 
= JSONUtil.objectToJson(map);
        
        request.setAttribute(
"json", rtnjson);
        
        
return "json";
    }
 

这样,这个controler中的异常,都会由这个异常处理方法,进行统一处理,生成异常json。避免在各个方法中通过try catch 的方法,进行异常处理。

posted @ 2016-11-08 08:32 风人园 阅读(382) | 评论 (0)编辑 收藏

有关使用 ActionBarSherlock 自定义样式的问题

1、不同android 版本,需要设置不同的 sytle 文件。
    默认 通常我们会设置values下面的style 文件
    但是如果是4.0以上,则还需要设置values-v14下面的style文件。
    
否则不能生效

posted @ 2014-03-30 09:00 风人园 阅读(458) | 评论 (0)编辑 收藏

解决IIS 启动响应超时 或者 World Wide Web Publishing服务无法启动提示:错误127 找不到指定程序/路径

找了很多方案,都说是那个KB939373 这个补丁搞的,但是在添加删除里就是找不到这个东东,重装也没有用,后来找到了这篇文章
http://www.cnblogs.com/skylaugh/archive/2011/07/21/2112860.html

根据这篇文章,我把 infocomm.dll 给替换一下,然后就好了,简直就是坑爹啊。

这里讲讲需要注意的事项。
1、替换的文件通过iis安装文件生成,请看参考文章
2、文件直接黏贴覆盖,不要使用参考里面bat处理。
3、然后启动这个服务,启动iis,搞定

posted @ 2013-06-18 15:49 风人园 阅读(223) | 评论 (0)编辑 收藏

解决Tomcat Error listenerStart 问题

昨天部署web应用到Tomcat之后,无法成功启动,并且控制台没有详细的错误信息,
顶多就两行提示信息,例如:
严重: Error listenerStart
严重: Context [/] startup failed due to previous errors

或者

严重: Error filterStart
org.apache.catalina.core.StandardContext start
严重: Context startup failed due to previous errors

查找logs目录下的信息,除了这两句话,也没别的辅助内容.
给查错带来了困难,在这种情况下,是因为Tomcat自身的默认日志没有将一些错误信息输出到控制台或文件,
这个时候则需要配置Tomcat自身的log,启用详细的调试日志.

3.log4j配置文件:
log4j.properties
配置内容为:

log4j.rootLogger=ERROR,R

log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=[%p]%t-%c-%m%n

log4j.appender.R=org.apache.log4j.RollingFileAppender
log4j.appender.R.File=${catalina.home}/logs/tomcat.log
log4j.appender.R.MaxFileSize=10MB
log4j.appender.R.MaxBackupIndex=10
log4j.appender.R.layout=org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern=[%p]%t-%c-%m%n

log4j.logger.org.apache.catalina=INFO,R,CONSOLE

#日志级别不能太低,如果配置为debug的话,输出的日志信息太多,导致tomcat启动非常的慢.

4.Tomcat 6.0所需的juli替换文件:
http://www.apache.org/dist/--escaped_anchor:079305423cce36d6691457475e081123--/tomcat-6/v6.0.18/bin/extras/tomcat-juli-adapters.jar
http://www.apache.org/dist/--escaped_anchor:079305423cce36d6691457475e081123--/tomcat-6/v6.0.18/bin/extras/tomcat-juli.jar
以上两个链接基本没用,大家可以搜索一下,csdn上面有人提供jar包下载,这里附件也不能加,没有办法。

在Tomcat6.0中,

将tomcat-juli-adapters.jar,log4j-1.2.15.jar,log4j.properties复制到D:\Java\ApacheTomcat6.0.14\lib下面.

将tomcat-juli.jar复制到D:\Java\apache-tomcat-6.0.14\bin\下面.

然后启动tomcat,就可以在D:\Java\apache-tomcat-6.0.14\logs下看到tomcat.log了.

在这个时候,再通过日志文件来分析,则会发现出现这种错误的情况可能有:
(以下是我遇到的出错情况,大多是些低级错误)
1.webapps要用到的classe文件根本没有复制到WEB-INF/classes目录下面
(java.lang.NoClassDefFoundError,而这个信息可能默认没输出到控制台,尤其是用了spring的,昨天就是这个粗心的低级错误)
2.要用到lib文件没有复制完,缺少lib
3.lib下的同一个库的jar文件存在多个不同版本,引起版本冲突.
4.lib下的jar与tomcat版本不相对应(我遇到的问题是web应用在Tomcat5.5上运行正常,换到Tomcat6.0上就出错,
例如一个用了struts的webapp在Tomcat 6上报下面的错误
“Parse Fatal Error at line 17 column 6: The processing instruction
target matching “[xX][mM][lL]” is not allowed” )

愿意看英文的可以参考官方网站说明:
http://tomcat.apache.org/tomcat-6.0-doc/logging.html


标记一下:) 

posted @ 2012-04-20 15:39 风人园 阅读(2867) | 评论 (0)编辑 收藏

javax.servlet 和 javax.servlet.jsp导致系统错误的问题

提示无法载入 c.tld等信息

只要删除 WEB-INF/lib 下的上述两个文件即可

因为此文件与 tomcat中的文件版本冲突

posted @ 2012-04-20 14:16 风人园 阅读(233) | 评论 (0)编辑 收藏

[转]浅谈Hibernate的flush机制

浅谈Hibernate的flush机制

随着Hibernate在Java开发中的广泛应用,我们在使用Hibernate进行对象持久化操作中也遇到了各种各样的问题。这些问题往往都是我们对Hibernate缺乏了解所致,这里我讲个我从前遇到的问题及一些想法,希望能给大家一点借鉴。

      这是在一次事务提交时遇到的异常。
      an assertion failure occured (this may indicate a bug in Hibernate, but is more likely due to unsafe use of the session)
net.sf.hibernate.AssertionFailure: possible nonthreadsafe access to session
注:非possible non-threadsafe access to the session (那是另外的错误,类似但不一样)
      这个异常应该很多的朋友都遇到过,原因可能各不相同。但所有的异常都应该是在flush或者事务提交的过程中发生的。这一般由我们在事务开始至事务提交的 过程中进行了不正确的操作导致,也会在多线程同时操作一个Session时发生,这里我们仅仅讨论单线程的情况,多线程除了线程同步外基本与此相同。
      至于具体是什么样的错误操作那?我给大家看一个例子(假设Hibernate配置正确,为保持代码简洁,不引入包及处理任何异常)
SessionFactory sf = new Configuration().configure().buildSessionFactory() ;
Session s = sf.openSession();
Cat cat = new Cat();
Transaction tran = s.beginTransaction(); (1)
s.save(cat); (2)(此处同样可以为update delete)
s.evict(cat); (3)
tran.commit(); (4)
s.close();(5)
      这就是引起此异常的典型错误。我当时就遇到了这个异常,检查代码时根本没感觉到这段代码出了问题,想当然的认为在Session上开始一个事务,通过 Session将对象存入数据库,再将这个对象从Session上拆离,提交事务,这是一个很正常的流程。如果这里正常的话,那问题一定在别处。
        问题恰恰就在这里,我的想法也许没有错,但是一个错误的论据所引出的观点永远都不可能是正确的。因为我一直以为直接在对数据库进行操作,忘记了在我与数据 库之间隔了一个Hibernate,Hibernate在为我们提供持久化服务的同时,也改变了我们对数据库的操作方式,这种方式与我们直接的数据库操作 有着很多的不同,正因为我们对这种方式没有一个大致的了解造成了我们的应用并未得到预先设想的结果。
那Hibernate的持久化机制到底有什么不同那?简单的说,Hibernate在数据库层之上实现了一个缓存区,当应用save或者update一个 对象时,Hibernate并未将这个对象实际的写入数据库中,而仅仅是在缓存中根据应用的行为做了登记,在真正需要将缓存中的数据flush入数据库时 才执行先前登记的所有行为。
在实际执行的过程中,每个Session是通过几个映射和集合来维护所有与该Session建立了关联的对象以及应用对这些对象所进行的操作的,与我们这 次讨论有关的有entityEntries(与Session相关联的对象的映射)、insertions(所有的插入操作集合)、 deletions(删除操作集合)、updates(更新操作集合)。下面我就开始解释在最开始的例子中,Hibernate到底是怎样运作的。
(1)生成一个事务的对象,并标记当前的Session处于事务状态(注:此时并未启动数据库级事务)。
(2)应用使用s.save保存cat对象,这个时候Session将cat这个对象放入entityEntries,用来标记cat已经和当前的会话建 立了关联,由于应用对cat做了保存的操作,Session还要在insertions中登记应用的这个插入行为(行为包括:对象引用、对象id、 Session、持久化处理类)。
(3)s.evict(cat)将cat对象从s会话中拆离,这时s会从entityEntries中将cat这个对象移出。
(4)事务提交,需要将所有缓存flush入数据库,Session启动一个事务,并按照insert,update,……,delete的顺序提交所有 之前登记的操作(注意:所有insert执行完毕后才会执行update,这里的特殊处理也可能会将你的程序搞得一团糟,如需要控制操作的执行顺序,要善 于使用flush),现在cat不在entityEntries中,但在执行insert的行为时只需要访问insertions就足够了,所以此时不会 有任何的异常。异常出现在插入后通知Session该对象已经插入完毕这个步骤上,这个步骤中需要将entityEntries中cat的 existsInDatabase标志置为true,由于cat并不存在于entityEntries中,此时Hibernate就认为 insertions和entityEntries可能因为线程安全的问题产生了不同步(也不知道Hibernate的开发者是否考虑到例子中的处理方 式,如果没有的话,这也许算是一个bug吧),于是一个net.sf.hibernate.AssertionFailure就被抛出,程序终止。

我想现在大家应该明白例子中的程序到底哪里有问题了吧,我们的错误的认为s.save会立即的执行,而将cat对象过早的与Session拆离,造成了 Session的insertions和entityEntries中内容的不同步。所以我们在做此类操作时一定要清楚Hibernate什么时候会将数 据flush入数据库,在未flush之前不要将已进行操作的对象从Session上拆离。

对于这个错误的解决方法是,我们可以在(2)和(3)之间插入一个s.flush()强制Session将缓存中的数据flush入数据库(此时 Hibernate会提前启动事务,将(2)中的save登记的insert语句登记在数据库事务中,并将所有操作集合清空),这样在(4)事务提交时 insertions集合就已经是空的了,即使我们拆离了cat也不会有任何的异常了。
前面简单的介绍了一下Hibernate的flush机制和对我们程序可能带来的影响以及相应的解决方法,Hibernate的缓存机制还会在其他的方面给我们的程序带来一些意想不到的影响。看下面的例子:
(name为cat表的主键)
Cat cat = new Cat();
cat.setName(“tom”);
s.save(cat);
cat.setName(“mary”);
s.update(cat);(6)
Cat littleCat = new Cat();
littleCat.setName(“tom”);
s.save(littleCat);
s.flush();
这个例子看起来有什么问题?估计不了解Hibernate缓存机制的人多半会说没有问题,但它也一样不能按照我们的思路正常运行,在flush过程中会产 生主键冲突,可能你想问:“在save(littleCat)之前不是已经更改cat.name并已经更新了么?为什么还会发生主键冲突那?”这里的原因 就是我在解释第一个例子时所提到的缓存flush顺序的问题,Hibernate按照insert,update,……,delete的顺序提交所有登记 的操作,所以你的s.update(cat)虽然在程序中出现在s.save(littleCat)之前,但是在flush的过程中,所有的save都将 在update之前执行,这就造成了主键冲突的发生。
这个例子中的更改方法一样是在(6)之后加入s.flush()强制Session在保存littleCat之前更新cat的name。这样在第二次 flush时就只会执行s.save(littleCat)这次登记的动作,这样就不会出现主键冲突的状况。再看一个例子(很奇怪的例子,但是能够说明问 题)
Cat cat = new Cat();
cat.setName(“tom”);
s.save(cat); (7)
s.delete(cat);(8)
cat.id=null;(9)
s.save(cat);(10)
s.flush();
这个例子在运行时会产生异常net.sf.hibernate.HibernateException: identifier of an instance of Cat altered from 8b818e920a86f038010a86f03a9d0001 to null这里例子也是有关于缓存的问题,但是原因稍有不同:(7)和(2)的处理相同。(8)Session会在deletions中登记这个删除动作,同时更新entityEntries中该对象的登记状态为DELETED。(9)Cat类的标识符字段为id,将其置为null便于重新分配id并保存进数据库。
(10)此时Session会首先在entityEntries查找cat对象是否曾经与Session做过关联,因为cat只改变了属性值,引用并未改 变,所以会取得状态为DELETED的那个登记对象。由于第二次保存的对象已经在当前Session中删除,save会强制Session将缓存 flush才会继续,flush的过程中首先要执行最开始的save动作,在这个save中检查了cat这个对象的id是否与原来执行动作时的id相同。 不幸的是,此时cat的id被赋为null,异常被抛出,程序终止(此处要注意,我们在以后的开发过程尽量不要在flush之前改变已经进行了操作的对象 的id)。
这个例子中的错误也是由于缓存的延时更新造成的(当然,与不正规的使用Hibernate也有关系),处理方法有两种:
1、在(8)之后flush,这样就可以保证(10)处save将cat作为一个全新的对象进行保存。
2、删除(9),这样第二次save所引起的强制flush可以正常的执行,在数据库中插入cat对象后将其删除,然后继续第二次save重新插入cat对象,此时cat的id仍与从前一致。
这两种方法可以根据不同的需要来使用,呵呵,总觉得好像是很不正规的方式来解决问题,但是问题本身也不够正规,只希望能够在应用开发中给大家一些帮助,不对的地方也希望各位给与指正。
  总的来说,由于Hibernate的flush处理机制,我们在一些复杂的对象更新和保存的过程中就要考虑数据库操作顺序的改变以及延时flush是 否对程序的结果有影响。如果确实存在着影响,那就可以在需要保持这种操作顺序的位置加入flush强制Hibernate将缓存中记录的操作flush入 数据库,这样看起来也许不太美观,但很有效。

http://hi.baidu.com/lkdlhw_2000/blog/item/a35b9cca82945342f31fe769.html

posted @ 2012-02-22 13:11 风人园| 编辑 收藏

ActiveMq 的安装及整合spring 使用


1、下载 安装
在windows xp 上,直接解压就可以使用
在2003 上,还需要配置一下,缺一个文件,否则无法启动

2、mq 配置
默认使用 文件持久化的方式,无需进行配置,只需要通过代码,标记消息为持久化即可

//设置 消息为 ‘持久化’ 消息,队列服务器重启后,会重新载入
message.setJMSDeliveryMode(DeliveryMode.PERSISTENT);
message.setString("context", context);

2、整合spring
mq的spring 配置文件, 此处三个bean
 mq 服务器配置,sender ,监听器
完成系统的消息发送和接收

<bean id="connectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
        
<property name="brokerURL" value="tcp://10.10.1.31:61616" />
    
</bean>
    
    
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
        
<property name="connectionFactory" ref="connectionFactory" />
    
</bean>
     
    
<!--  ============================  消息发送 ============================== -->
    
    
<!-- ecp.sd.log -->
    
<bean id="logDestination" class="org.apache.activemq.command.ActiveMQQueue">
        
<constructor-arg value="km.wlog"/>
    
</bean>
    
    
<bean id="logMessageSender" class="com.chint.mq.sender.LogMessageSender">
        
<property name="destination" ref="logDestination" />
        
<property name="jmsTemplate" ref="jmsTemplate" />
    
</bean>
    
    
<!--=============================  队列监听器  ==========================  -->
    
    
<!-- 日志 队列监听器 
    
<bean id="logContextListener" class="com.chint.mq.listener.LogContextListener">
    
</bean>
    
    
<bean class="org.springframework.jms.listener.SimpleMessageListenerContainer">
        
<property name="connectionFactory" ref="connectionFactory"/>
        
<property name="destinationName" value="km.wlog"/>
        
<property name="messageListener" ref="logContextListener"/>
    
</bean>
    
-->

消息发送者
@Service
public class LogMessageSender extends BaseMessageSender{
    
    
public void sendMessage(final String context) {
        jmsTemplate.send(destination, 
new MessageCreator(){

            @Override
            
public Message createMessage(Session session) throws JMSException {
                MapMessage message 
= session.createMapMessage();
                
                
//设置 消息为 ‘持久化’ 消息,队列服务器重启后,会重新载入
                message.setJMSDeliveryMode(DeliveryMode.PERSISTENT);
                message.setString(
"context", context);
                
                logger.info(
"KM INFO [LogMessageSender] send message context ({})", context);
                
                
return message;
            }

            
        }
);
    }


}

消息接受者
/**
 * 
@author wxf
 *
 
*/

public class LogContextListener extends BaseContextListener implements MessageListener{

    @Autowired
    
private WorkLogManager workLogManager;
    
    @Override
    
public void onMessage(Message arg) {
        
if(arg instanceof MapMessage) {
            MapMessage message 
= (MapMessage)arg;
            
            
try {
                String context 
= message.getString("context");
                logger.info(
"KM INFO [LogContextListener] get message context ({})", context);   
            }
 catch (JMSException e) {
                
throw JmsUtils.convertJmsAccessException(e);
            }

        }
 else {
            System.out.println(arg.toString());
        }

    }


}


以上就完成了 MQ的使用,比较简单。

通过spring使用mq从代码来讲还是很简单的,但是mq的性能可能需要额外的调整一下才能达到最佳的状态,特别是大数量的情况下。

仅作记录

posted @ 2011-11-09 09:25 风人园 阅读(624) | 评论 (0)编辑 收藏

同一台电脑登陆多个账号的问题

这个问题一直比较奇怪,今天搜了一下,原来是浏览器的问题,这让我想起来了网页版的网游,不能多登的问题。原来session是相同的。

打开的是两个浏览器还是两个页签,
比如 IE7这种支持多页签的,也就是在一个浏览器里面同时打开多个页签的这种,是共用一个Session的,
但是比如IE6这种一次只能打开一个浏览器的,就没有问题,

因为打开的是多个浏览器我说了,这个和浏览器相关,每当你打开一个浏览器,这个浏览器就会有专门的session.


也算是解决了一个问题吧:)

这里标记一下

posted @ 2011-09-09 16:43 风人园 阅读(408) | 评论 (0)编辑 收藏

遍历所有数据文件的大小

 

1、新建一个临时数据库,用于存放查询结果
CREATE TABLE DatabaseFileLog
(
 date DATETIME,
 dbname VARCHAR(20),
 FILENAME VARCHAR(100),
 fileSIZE FLOAT
 
)


2、通过游标遍历所有数据库
declare @dbName varchar(50)
declare @command varchar(1024)
declare dbName_cursor CURSOR FOR
    select [name]
    from master.dbo.sysdatabases
    where [name] not in ('master','tempdb','msdb','model')
open dbName_cursor
FETCH NEXT FROM dbName_cursor INTO @dbName
WHILE @@FETCH_STATUS = 0
begin
    set @command = '
        insert into DatabaseFileLog
        select
        getdate(),
        '''+
        @dbName
        +''',

        filename,
        convert(float,size) * (8192.0/1024.0)/1024.0 as ''MB''

        from '+@dbName +'.dbo.sysfiles ';
    exec ( @command );
    FETCH NEXT FROM dbName_cursor INTO @dbName ;
end
CLOSE dbName_cursor;
DEALLOCATE dbName_cursor;

3、查询结果
SELECT * FROM DatabaseFileLog

posted @ 2011-09-06 10:46 风人园 阅读(207) | 评论 (0)编辑 收藏

eclipse 注释模版 设置


设置注释模板的入口: Window->Preference->Java->Code Style->Code Template 然后展开Comments节点就是所有需设置注释的元素啦。

常用的,一般两个

文件(Files)注释标签:

/**  
* @Title: ${file_name}
* @Package ${package_name}
* @Description: ${todo}(用一句话描述该文件做什么)
* @author A18ccms A18ccms_gmail_com  
* @date ${date} ${time}
* @version V1.0  
*/


类型(Types)注释标签(类的注释):

/**
* @Description: ${todo}(这里用一句话描述这个类的作用)
* @author ${user}
* @date ${date} ${time}
*
* ${tags}
*/

posted @ 2011-08-18 16:30 风人园 阅读(344) | 评论 (0)编辑 收藏

Spring MVC 使用中的注意事项

    ModelAndView中保存了要传递给视图的对象和具体要使用的视图文件,自2.0起, Spring MVC提供了Convention over Configuration的机制,大大简化了代码与配置。简单地说,名字以Controller结尾的控制器类都会被映射为相应的地址,ListArticleController对应/listarticle*,如果是MultiActionController则会被映射为一个目录;向ModelAndView添加对象时可以不用指定键(key),单一对象的键取决于类名,比如x.y.User的键是user,而某一类对象的 Set、List或数组则稍有些复杂,取第一个对象的类名加上“List”作为它的键,比如这里的articles是一个存放Article对象的 List,它的键就是articleList;
也可以通过执行key,来指定变量名称

posted @ 2010-12-30 15:51 风人园 阅读(369) | 评论 (0)编辑 收藏

spring 事务的回滚问题

    spring的事物配置,默认状态下,只针对 RuntimeException 进行回滚。
而像SQLException并不是RuntimeException,所以这里需要特别注意。

这里困扰了我很久,一直没有想明白为什么在一个事务里面,部分成功,部分失败。可能就是这个原因导致的。
也就是说,一些系统级别的异常,前期都需要转化成 RuntimeException 。这样就可以进行回滚了。

但是这样的只需要修改底层,另外一个偷懒的方法,在每个service类上直接指定rollback = Exception.class。这样所有的异常都会回滚。但是这样有没有副作用,但是不清楚。

异常一直是我没有搞定的一块内容之一,称这个机会研究一下。
为什么需要分check 和unckeck,两者有什么不动点。
如果都是用uncheck,会不会有什么问题?
待续。。。

posted @ 2010-12-14 14:01 风人园 阅读(859) | 评论 (1)编辑 收藏

hibernate 关联查询错误(Path expected for join)

    以前没怎么用,现在真用起来的时候还是会有很多白痴问题,哈。
    今天想做一个left join , 关联关系应该是已经配好了,但是调用hql就是报错,也不知道怎么回事。继续研究ing。

posted @ 2009-12-10 14:00 风人园 阅读(4899) | 评论 (1)编辑 收藏

Hibernate主从数据的操作

struts2+spring2.5+hibernate 3.3

在hibernate的操作中,特别是主从数据的操作。

一般有这么几个地方需要注意,以前也一直没有拿hibernate好好用过,现在真正用起来,问题还是挺多了。这几天一直在调试解释这种问题。

主数据中的一对一关联,这里的关联数据从页面提交的时候是否可以直接映射到主数据对象中?暂时不清楚,可以测试一下。

然后是明细数据的操作,现在动态产生的行数据,然后手动解析,生成明细对象。整个过程个人感觉比较麻烦,暂时也想不出有什么好的解决方案。

这里在级联保存数据的时候,首先要清除掉原来的明细数据,然后再把页面提交过来的数据加上。
不知道一般是不是这样弄的。否则没法清楚原来的数据。


posted @ 2009-11-17 19:30 风人园 阅读(351) | 评论 (0)编辑 收藏

通过MyEclipse生成annotation方式的entity类

    通过搜索和阅读myEclipse的帮助文件,发现这是可以实现的。不过前提是,你使用的hibernate是3.2版本。这样就可以支持以注解的方式生成实体类了。跟hbm配制文件方式基本是一样的。

    昨天特地好好的看了一下MyEclipse的帮助,里面关于ajax web开发的工具感觉还是挺好用的,以前一直也没有了解一下里面的功能,以后要好好用一下,还是可以有不少帮助的。
    今天先起个头,明天写一个详细的操作说明,这样也方便自己,免得忘了。

posted @ 2009-11-15 19:02 风人园 阅读(494) | 评论 (0)编辑 收藏

Jxls 导出excel

 1     public static void exportExcel(String templateFileName, Map beans, 
 2             HttpServletRequest request,HttpServletResponse response){
 3         try {
 4             response.setContentType("application/vnd.ms-excel");
 5             response.setHeader("Content-Disposition""attachment; filename=excel.xls");
 6             XLSTransformer transformer = new XLSTransformer();
 7 
 8             
 9             InputStream is = new BufferedInputStream(
10                     new FileInputStream(RequestUtil.getRealPath(request, templateFileName)));
11             
12             HSSFWorkbook workbook = transformer.transformXLS(is, beans);
13             OutputStream os = response.getOutputStream();
14             workbook.write(os);
15             is.close();
16             os.flush();
17             os.close();
18         } catch (Exception e) {
19             e.printStackTrace();
20         }
21     }
通过服务器端获取模版文件的绝对路径,然后通过response来输出到页面,就可以实现导出,这个比poi等等都简单很多,用起来比较舒服。
服务器路径的获取:request.getSession().getServletContext().getRealPath(name);
这样就可以获得web目录下某个文件的服务器端路劲。

今天在使用的时候发现一个问题,就是在使用表达式的时候有一个地方需要注意
${item.itemQty}
像上面的这个表达式就会出错,这里也没有看源代码,具体不是很清楚,但是看了一下日志,发现,后面的这个item也被替换了,所以觉得这个可能是jxls的bug或者是作者偷懒搞的。

以后只需要注意字段名不能跟bean的名字一样,否则就出错。

仅此记录

posted @ 2009-09-21 16:21 风人园 阅读(2726) | 评论 (1)编辑 收藏

IronTrackSQL配置

主要讲一下在配置的过程中出现的问题,基本的配置方式网上有很多。
这里讲spring的集成问题。
可能会出现两个问题
1、spring配置:
    

 <bean id="datasourceTarget" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
  <!-- Connection Info -->

 </bean>

    <bean id="dataSource" class="com.p6spy.engine.spy.P6DataSource">
        <constructor-arg>
            <ref local="datasourceTarget"/>
        </constructor-arg>
    </bean>

    这样就不会出现说找不到合适的驱动 这个异常。
2、是p6spy的版本问题,导致spring配置文件失败
    如果使用上面这个配置,需要1.3版本的p6spy.jar,我用老的,就出现说不能创建dataSource,没有合适的一个参数的构造函数。

这是今天配置IronTrackSQL出现的两个问题,让我折腾了一个下午,所以记下来。
还有一个问题就是
Warning: Could not instantiate IronTrack server: java.net.BindException: Address already in use: JVM_Bind
地址占用的问题,好像有两个server启动了。我重启一下就会出现这个问题,第一次启动就没有问题,暂时不知道什么原因。
找到了为什么重复启动的问题,项目启动了两次,导致后一次启动端口被暂用。
总的来说还是不错的,但是还搞不清楚怎么正确使用。
继续努力中

posted @ 2009-09-17 15:46 风人园 阅读(471) | 评论 (0)编辑 收藏

代码质量随想

        干了这么多年的代码工,对于代码质量的理解,个人认为就是一个,可维护性,除非你开发的东东是一锤子买卖,否则后期的投入会多的可怕,而且对于错误就没有办法控制了

        下面引用别人的一段话来说明一下什么是高质量的代码:
                高质量的代码,除了符合产品的功能设计需求外,还应该便于维护、执行效率高、经过充分测试并且拥有较好的稳定性。

        但是从我个人来讲,可维护性是第一位的,其他都是必须的,冲突的话就应该适当取舍。便于维护必然会影响到一点点的效率,但是这个肯定是可以接受的。是可以通过其他方式来弥补的。
        不能为了追求所谓的高效,而破坏了系统的维护性,这样导致后期维护会有很大的问题,从而可能导致低效。

        这里介绍几个工具,来提高代码质量。findbugs就是其中的一个,可以对代码提出很好的修改建议。

purifyplus 一个运行时检测系统,可惜不免费。


备注: rational team concert 协作开发系统,集成版本控制、工作项和构建

posted @ 2009-09-02 12:19 风人园 阅读(199) | 评论 (0)编辑 收藏

ECP--之信息提示

        一般,系统中把提示信息保存在request中传递会页面,但是有些情况是redirect的,这样就导致了request失效。在ROR中,有一个scope是夸两个request的,不知道那个是怎么实现的。
        现在用session来代替这个东西,只是显示完成之后,就立刻清除这个数据。感觉比较挫,只能凑合着用了。
        每次新开发一个系统,如果不用现成的东西来做,都要搞很多很多东西,什么东西好像都要自己来,特别是页面上的东西,感觉挺烦的。写写js,改改css,调调table/div。感觉挺无聊的。
        总而言之,这样子都是因为这家公司的it部门太弱了,几乎没有一点技术积累,这么多年了,什么东西都没有留下,就留下了一堆垃圾,让我改的挺郁闷的。现在正在用自己的东西重新。有些东西又没法改,一些现成的组件也不一定能用,不能用的只能自己重新写一遍,来实现这个功能。

        作为一个技术部门,结果什么技术都没有,感觉挺悲哀的,特别是一个技术部门的老大,结果是个门外汉,被手下人看不起,这个也挺惨的,作老大做成这样,连死的心都有了,悲剧啊。

        作为一个技术部门的主管,可以不做技术,但是不能不懂技术。这样才能服众。

posted @ 2009-08-31 14:37 风人园 阅读(147) | 评论 (0)编辑 收藏

ECP--之弹出窗口解决方案(json传递)

        在应用中,弹出式窗口选择数据,这种解决方案是很普遍的。
        弹出窗口,有两种方式,一种是:showModalDialog,使用模式窗口,这种方式的好处有两个地方,一、可以直接返回数据,二、在最前面显示,避免用户误操作,窗口被遮蔽。
        但是这种方式个人感觉比较致命的地方就是因为这个是一个对话框,在form提交的时候只能新开一个页面(可能我没有发现其他的方式)。但是也有其他的方式,如加iframe,但是这样感觉页面太烦了,需要两个页面才能实现,比较麻烦。

        第二种:window.open,这种方式也有一个问题,就是会被当做广告拦截掉,还算不是很致命。
我的方案就是这个,下面上代码。
传递格式通过json,这样我可以自己定义需要回填那些域,返回值这边就是竟可能的完整。


/*
弹出窗口
endtarget: string 目标窗口
无返回
*/

function fopenWindow(endtarget){
    window.open( endtarget, 
"""left=0, top=0, width=800px, height=600px, scrollbars=1, resizable=1, menubar=0, location=0, status=0, toolbar=0, " );
}


/*
window.open的回调函数
根据传入的json格式,赋值相应的域值

cmp:string 域id
retval :json 所选行的数据
无返回
*/

function fopenCallback(cmp, retval){
    
    
//alert("call back start." + cmp);
    var obj = eval('(' + cmp + ')');
    
    
for(var e in obj ){
        
//alert(obj[e]);
        document.getElementById(obj[e]).value = retval[obj[e]]
    }

}


window.openCallback 
= fopenCallback;

/* 
获取url上的参数
返回:key value 对
*/

function GetUrlParms()    
{
    
var args=new Object();   
    
var query=location.search.substring(1);//获取查询串   
    var pairs=query.split("&");//在逗号处断开   
    for(var i=0;i<pairs.length;i++)   
    
{   
        
var pos=pairs[i].indexOf('=');//查找name=value   
        if(pos==-1)   continue;//如果没有找到就跳过   
        var argname=pairs[i].substring(0,pos);//提取name   
        var value=pairs[i].substring(pos+1);//提取value   
        args[argname]=unescape(value);//存为属性   
    }

    
return args;
}
            

/*
行双击方法,用户选择行数据。
通过回调函数,完成赋值,最后关闭窗口
rtnval: string 行数据
*/

function Dialog_onDblClick(rtnval)
{
    
//var rtnval = {prodId: prodId, prodName: prodName};
     
    
var args = new Object();
    args 
= GetUrlParms();
    
var cmp = args['cmp']
    
    window.opener.openCallback(cmp, rtnval); 
    window.close();
}


主页面 域id通过json字符串跟url传递后弹出页面
function popProductDialog(){
    var endtarget = "<%=path%>/bas/product.do?method=dialog";
    var cmp = "{a: 'prodId', b: 'prodName'}";
       //fshowModalDialog(endtarget, cmp);
      
       fopenWindow(endtarget+ "&cmp=" + cmp);
      
   }

弹出框
function Document_onDblClick(value1,value2)
            
{
                
var rtnval = {clientId:value1, clientName:value2};    
                    Dialog_onDblClick(rtnval);

            }
弹出页面解析获得域id,并通过循环域id从返回值中获取数据,并进行赋值。

这里唯一需要变的就是,弹出页面的返回值,可能因为需求的增加,需要返回更多的数据,或者就一次性将所有数据都作为json数据返回。

这样客户在调用的时候,只要域id不超出返回字段的范围,就可以正确使用了。

posted @ 2009-08-31 10:39 风人园 阅读(568) | 评论 (0)编辑 收藏

ibatis3中感觉比2不方便的地方


1、动态sql里面 原来的dynamic,现在没有了,只能用is代替。但是if里面的判断 没有isEmpty这种方便的标签,需要判断需要同时判断 null 和 ""。这个比较麻烦,希望能在正式版本中加上。

2、annotion方式的评价,个人感觉没有什么意义。从我来讲,用iBATIS的主要原因是因为要处理比较复杂的sql,所以通常sql都会很长,就是因为不想通过字符串的方式写在代码里,要是写在代码里,直接用hibernate的原生sql就好了,何必还要用iBATIS呢。sql写在xml里的好处是显而易见的,可以直接将调试好的sql从sql的编辑器中复制过来,这样可以省掉很多麻烦的事情,放在sql里面很长,又没有办法将格式弄好,要是换行什么的就更麻烦。

一个比较有用好的改进就是namespace了,这个功能以前在2.X想用一直没有用成。有了这个,很多通用的地方可以省略。

posted @ 2009-08-26 16:30 风人园 阅读(392) | 评论 (0)编辑 收藏

ibatis3及代码生成工具试用

        ibatis3现在还是beta版,但是已经可以很好的使用了。
        主要增强的方面有namespace这个东西,以前2的时候一直以为可以用的,结果没有效果,害我还郁闷了半天,这样以后就不会再有命名冲突了。
        然后就是annotion的支持,这样就可以不适用xml文件来保存sql了,但是感觉还是写在xml里面比较舒服,特别是比较长的sql,个人感觉。
        第三个就是动态sql的增强,增加很多有用的标签。可以让动态sql使用更加方便。
        在看完之后暂时感觉有那么几个比较好的改变,等正式版出来之后可能还有更多改进。

        接着讲下abator这个代码生成工具,感觉还可以,生成的sqlmap配置文件还可以用下,其他的就算了,还是自己手写吧。

        最后提到一下ibatis-3-migrations,这个东西暂时还没有看明白,好像是数据库schema的一个管理工具。正在啃guide,看看到底有什么好处,上次看有个人的文章说,就是因为没有这个东西才没有用ibatis,所以这个东东应该很强大,我要看下。

posted @ 2009-08-21 10:36 风人园 阅读(837) | 评论 (1)编辑 收藏

ECP--旧系统维护之感慨

        这几天再改老的EC系统,天啊,都快受不了了。我自认为我写的已经算丑的了,没想到有写的丑到这个程度的也是一绝啊,而且这个还是一家国内还有点名气的软件公司的产品(中科软sinosoft)。爷爷,当初是谁写的,帮我问候一下他家先人。害我现在这么惨,看那个代码,看了就想吐。
        只要我还在这家公司做着,一定把这个系统给换了,什么玩意啊。软件公司就知道赚钱,做出来的什么狗屁玩意。
        在这里发发牢骚,实在是有点受不了了,改这些破东西,累啊。shit

posted @ 2009-08-20 15:01 风人园 阅读(160) | 评论 (0)编辑 收藏

SpringSecurity见解

        对于入门来说,这个东西还是挺简单的,但是入门之后,这个事情还是挺复杂的。这里主要是看这个教程自己研究的http://www.family168.com/oa/springsecurity/html/index.html 
        对于那个helloworld,确实是挺好的,让人有了一个初步的认识。之后就是怎么把xml中的东西搬到数据库中的问题。这个过程中还是有很多小问题的,经常出现不能访问,访问错误,配置不生效等等问题。毕业也是第一次弄这个东西。也是在springside中看到这个东西,而权限控制模块也没有什么应用,所以就决定用这个试一下。
        试了一下例子,感觉确实不错 ,有很多功能都可以迎刃而解,剩下的问题就是怎么把那些小问题都搞清楚。
       现在一个比较麻烦的问题 就是资源的动态管理。新增配置只能在系统启动的时候才生效。网上说要把数据refresh()一下,但是不知道在哪里refresh(),不知道到底要刷新那个数据。还得研究一下。
        问题二、一个路径,如果没有加到资源的话,是不是应该叫匿名资源,这个资源是不是匿名用户也可以访问?

posted @ 2009-08-18 10:53 风人园 阅读(237) | 评论 (0)编辑 收藏

ECP--安全控制

        基础数据的操作暂告一个段落,基本上差不多,后面可能还有一些小问题,要修修补补,暂时不弄了,呵呵,典型的喜新厌旧型,弄多了就有点烦,下面开始玩权限。
        权限管理使用spring security 来进行,以前稍微看过,只是感觉挺复杂的,也没有怎么仔细研究,这次一定要用,就好好研究下。这样系统安全性才能有保障。
        毕竟是第一次使用,使用的过程中还是有很多的问题的。下面就是一些小问题,需要注意一下的。
 

1、 登录action/spring_security_login

2、 登出actionj_spring_security_logout (这两个actionspringSecurity自带的,直接用就可以了)

3、 Filter的配置,在项目中,跟struts2一起使用,filter的前后顺序有关系。Spring secutiry要放在struts2的前面,否则系统找不到securityaction

4、 怎么获取用户信息:可以参考springside中的实现org.springside.modules.security.springsecurity.SpringSecurityUtils。具体信息都在Authentication这个类中。

posted @ 2009-08-13 14:18 风人园 阅读(217) | 评论 (0)编辑 收藏

Ext.data.jsonReader的格式

在Grid和Form进行异步载入的时候,一般都是用json来进行返回,这个时候就需要注意格式的问题。jsonReader的格式是固定的,都是一样的
{"data":[{"spec":"aa","id":1,"name":"aa","helpCode":null,"code":"aaa"}],"success":true}
注意:data的数据是一个数组,不管是grid显示还是form显示,都是数组,只是grid有多条,而form就只需要一条而已,这个问题我也找了好一会儿。

从代码上看,grid和form调用的jsonReader是一样,怎么格式有点不一样,原来是这么个回事,两者确实都是一样的。

经过这次之后,对jsonReader有了更深的了解,只要是异步,用jsonReader就好了,一般的问题都能搞定。

特别是form的自己载入,这样可以省掉很多事情。

posted @ 2009-08-11 09:45 风人园 阅读(2271) | 评论 (0)编辑 收藏

ECP--Ext grid

周末的时候给项目从新想了一个名字,ECP,(电子商务平台),呵呵,自己陶醉用的。

今天的成果就是异步的grid实现,效果是不错。现在剩下按钮操作与grid的结合的问题。明天继续努力。

工作越来越烦了,该死的破老大,一点不懂,就瞎指挥,要不是回家没有地方去,早不干了。哎,继续努力吧。早日完成这个项目,走人:)

posted @ 2009-08-10 17:00 风人园 阅读(171) | 评论 (0)编辑 收藏

ECApp--产品主数据操作界面

        又经过了半天多的努力,总算页面基本操作都能实现了,下面就是完善操作及异常处理。
        在window&form的操作上有些小问题。
        还有就是grid的异步数据载入,暂时用array,下面考虑用json来异步实现。

继续看效果图


用ext做这种界面确实很爽,用户体验会很好,呵呵,我很喜欢这种淡淡的蓝,看着养眼,舒服。

posted @ 2009-08-07 15:01 风人园 阅读(196) | 评论 (0)编辑 收藏

ECApp -- 之系统初始化

在java web项目中,最常用的就是使用listener来实现初始化了。

下面是实现代码
 1 public class StartupListener extends ContextLoaderListener implements
 2         ServletContextListener {
 3 
 4     private Logger logger = LoggerFactory.getLogger(getClass());
 5     
 6     /**
 7      * web容器启动时调用
 8      */
 9     public void contextInitialized(ServletContextEvent event) {
10         logger.info("application servlet initialized");
11 
12         ServletContext context = event.getServletContext();
13         
14         //从spring中获得bean,由这个bean进行相应操作,结果存到context中
15         ApplicationContext ctx = WebApplicationContextUtils.getRequiredWebApplicationContext(context);
16         ProductClassManager productClassManager = (ProductClassManager)ctx.getBean("productClassManager");
17         
18         String prodClassTreeJson = productClassManager.generateProdClassTree();
19         
20         context.setAttribute(Constants.PRODUCT_CLASS_JSON_STRING, prodClassTreeJson);
21     }
22     
23     
24     /**
25      * web容器销毁时调用
26      */
27     public void contextDestroyed(ServletContextEvent event){
28         logger.info("application servlet destroyed");
29     }
30 
31 }
        这里面还调用 了spring的bean,所以listener要配置在spring的那个listener下面,否则可能出错。

这样我们就可以在系统启动的时候将一些常用的数据及配置信息都放到内存(即serlvetContext里面),在struts2中,我们可以通过这种方式获得
ServletContext context = ServletActionContext.getServletContext();
然后就可以使用存放在context里面的数据了。
就这么简单。

posted @ 2009-08-06 15:40 风人园 阅读(226) | 评论 (0)编辑 收藏

ECApp--ext应用之我见

        以前做项目的时候也使用过一段时间的ext,但是总体来说,在使用的过程中有蛮多不习惯的地方,后来除了几个布局界面使用ext之外,其他的全部又替换为html了。
        这次项目,再次使用ext又有了新的感觉,总的来说,ext还是非常的好(这个是废话)。css风格是我比较喜欢的那种,非常的耐看,不会看厌。各种组件丰富,只要你能用的起来,还是非常好的,一个应用下来,整体操作非常的爽。
        有一个不爽的地方就是在编写的时候 ,多一个少一个逗号就玩完,这个比较郁闷,但是注意一下就好了。
        下面暂时show一下程序的主体页面,只能说基本完成,还没有完全弄好。
        今天把页面及tree给弄好,明天把中间的grid及相关的几个编辑form弄完,在完善一下相应的按钮操作,就完工了,哈哈。拿出去给人看都是眼前一亮。good,继续努力ing

posted @ 2009-08-06 15:02 风人园 阅读(169) | 评论 (0)编辑 收藏

ECApp--产品主数据管理界面及产品选择方案构思



1、管理界面
        对于一个ERP系统来讲,产品数据是最重要的,而且也是操作比较频繁的。所以界面一定要要友好。
在c/s中,一般是这样处理的,左边树形结构显示分类,右边产品数据,提供查询定位功能。
所以在这个系统里,我也想使用类似的界面,这样直观且方便。

        在这个界面上,提供对产品类别 & 产品数据的操作。
        在树形结构上操作产品类别,操作有:新增类型,新增子类型。
        产品数据:新增(需要先选择类别)、删除、修改、查找、定位等。

2、产品选择
        在整个系统中,产品选择使用是最为广泛和频繁的,所以一定要提供多种选择操作,满足用户的操作需要,方便用户产品需要的产品。
    1)、弹出式选择对话框
    2)、下拉式(自动匹配建议)
    3)、多选输入(减少操作次数,这个很重要)

上面这些看能否用ext实现。
本来想使用jquery.treeview来做,但是好像有点问题。看来只能用ext的东东来做tree了。
那个自动匹配的下拉菜单,估计要自己来手工打造了,已经找到了类似的源代码,自己做吧。
哦:)

posted @ 2009-08-05 15:22 风人园 阅读(270) | 评论 (0)编辑 收藏

java中文注释在eclipse中显示乱码的问题

这个问题困扰已久,一直没有空查,今天终于查了一下,呵呵,总算看见那个久违的汉字了,高兴啊。

原文请看这个论坛帖子 : http://www.javaeye.com/topic/100391

解决方案:
Preferences General > Workspace 修改Text file encoding
为UTF-8后才行。这个问题一直琢磨了好久,今天下了决心想看看,最后还是查了eclipse的帮助才解决。

当当修改project 为UTF-8是不行的。


就这么回事,我一直改项目的那个,怪不得。

posted @ 2009-08-05 15:07 风人园 阅读(2420) | 评论 (0)编辑 收藏

ECApp 项目说明

在此记录开过过程及问题处理,便于浏览查询。
ECApp是一个web版的进销存系统
模块有系统模块,基础模块,采购管理,销售管理,仓库管理,应收应付等。

在web版的基础上,计划再开发一个RCP版本的。web的主要用于查询分析。RCP用于数据操作。

这样B/S,C/S的特点都能发挥出来。


在公司工作也不是很累,有很多时间做开发,给自己点事情做作,免得人都荒废了。这样人累点,但是充实,给人的精神感觉也好。让人有个希望,有个目标。

现在在完成基础模块的东西,整体架构

Struts2 + spring + hibernate + ibatis

数据库任意,现为sql server 2005

争取以后改为ERP,有机会的话,可以拿出去卖卖,哈哈

给自己一个目标,年底前完成,加油吧,兄弟。

posted @ 2009-08-04 16:39 风人园 阅读(237) | 评论 (0)编辑 收藏

struts2 表单属性映射的问题

最近使用的过程中,有点搞不懂,表单域跟属性到底是怎么个关系,因为有时候可以,有时候又不行。有点小郁闷。

使用新东西的时候或多或少会出现这样那样的问题,这导致很多人不愿意更换原来的框架,一换又要学一个大堆东西,处理一大堆异常。但是我们这些做开发的,不学习使用新的 东西,就会被淘汰。这个行业的悲哀啊,当初也不知道怎么选择了这个行业。

以上是题外话。

表单映射,在2里面有两种方式,一个事modelDriver,直接映射到model里面。
另一种方式就是通过属性来影射,通过getter和setter方法来获取和设置值。

现在出现问题的在第二种情况,设值后,传到页面,页面没有得到值,这个不知道什么缘故,感觉有可能是页面转发的问题。这个还要好好看看资料研究一下。

:)

//==========================================================================
2009-11-17
好久以前的问题了,今天终于有了答案,原来都是ValueStack惹的。其实也怪自己,一直没有空把struts2的原理好好的看看,还以为跟以前的东西一样呢。

问题是这样的,在action里定义了属性之后,数据都是存在ValueStack里面的。如果你直接使用tag取的话就没有问题。但是你想通过java代码,用request取的话,这样是取不出来的。

今天终于发现了这个问题的原因。
这些属性可以通过request取,但是首先要去的ValueStack,然后从ValueStack里面把这个值取出来。
如:
ValueStack vs = request.getAttribute(struts.valueStack);
然后根据属性名称,从vs中获取这个对象值。
vs.find("value");

这样就可以把数据取出来通过java代码来操作了。否则只能使用struts2自带的tag来运行。

这个是今天的一大收获。

posted @ 2009-08-04 15:52 风人园 阅读(1088) | 评论 (0)编辑 收藏

jquery.treeview

今天用到tree,试了下jqeury的这个插件,结果发现一个问题。
效果是出来了,可是没有单击事件,这让我们怎么用啊。真是纳闷死了,看文档也没有这个说明,看demo里面也没有这个例子。

好像其他的官方插件也或多或少有这样那样的问题,看来官方的插件还需要努力更新啊。

难道我要自己动手完成这个东东了?

js一直是我的软肋,郁闷死。

现在碰到复杂一点的js,根本没辙。特别是现在oo版本的js,基本上属于看不懂,看来我需要研究一下了。

posted @ 2009-08-04 13:47 风人园 阅读(687) | 评论 (0)编辑 收藏

hibernate annotion 注解放在属性上或者方法上

两种方式都是可以,但是看人家的代码,习惯将注解放于方法上,不知道有没有什么好的地方?

现在唯一发现的区别就是,@Transient非持久化域的不同。
放在方法上,只需要标记那个getter方法即可,可以没有对应属性。

如果放在属性上,需要生成getter 和setter方法


在实体对象中,可能存在很多非持久化方法,这种情况下
注解置于属性上,功能性get方法,可以没有对应属性。
注解至于方法上,直接使用@Transient。

两者基本上都一样。
只是在使用的时候不能混合使用

posted @ 2009-08-04 09:54 风人园 阅读(1511) | 评论 (0)编辑 收藏

Hibernate annotion配置

在这里,记录一下annotion在实际使用过程中一些常用的配置。

1、一对多
2、一对一

常见异常及处理
1、Could not determine type for: java.util.Set
说不能找到这个类型,无法创建列
原因:annotion不能同时放在属性和方法上,要么都放在属性上,或者都放在方法上

posted @ 2009-08-04 08:52 风人园 阅读(420) | 评论 (0)编辑 收藏

OperaMasks学习系列(三) 数据验证(原创)

1、简单验证
   
  • @Required. 声明一个域或Bean属性必须具有输入值。

  • @ValidateDoubleRange. 检验一个浮点数取值是否在指定范围中。

  • @ValidateLongRange. 检验一个整型数取值是否在指定范围中。

  • @ValidateLength. 检验一个字符串的长度是否在指定范围中。

  • @ValidateRegexp. 检验一个字符串是否可以匹配指定的正则表达式。(OperaMasks提供了一个工具类org.operamasks.faces.validator.CommonRegexpPatterns,列出了一些常用的校验正则表达式)

2、服务器端验证

3、自定义验证错误信息

4、客户端验证   
    设置form 的属性:clientValidate="true"
    通过此标签自定义客户端验证
    <ajax:clientValidator message="用户名不能为w">
        嵌入javascript代码
    </ajax:clientValidator>

posted @ 2009-06-17 13:32 风人园 阅读(320) | 评论 (1)编辑 收藏

OperaMasks应用中常见异常

1、异常说明
    找不到指定的LiteBean
@ManagedProperty("#{sys.userEditBean}")org.operamasks.el.eval.EvaluationException: 找不到类型org.operamasks.el.eval.SystemScope的'userEditBean'属性。
    解决方法:
sys前缀的问题改用其他的名字就可以了。aom好像自己有一些保留字,以后需要注意这个问题

2、按钮没有绑定后台方法
   
解决方法:通常情况下都是没有把按钮包含在form标签中所导致的。

持续更新ing

初次使用,导致出现的很多异常信息看不懂,不知道从何处理。几下问题,便于以后查找。

posted @ 2009-06-17 09:30 风人园 阅读(346) | 评论 (0)编辑 收藏

OperaMasks学习系列(二) AdvanceCRUD (原创)

        今天抽空实验了一下aom下实现CRUD的过程,整个过程虽然有点小问题,但是整体还是比较清楚的,而且关键是最后的页面操作,可以说非常的好,特别M-D表格的操作非常好,只是感觉Detail表格部分好像有点点速度问题,但是还能接受。
        第一次做,各个类之间的调用关系有点不是很清楚,还需要好好研究一下。从页面的效果来讲,确实非常的帅,本身就是从extjs扩展过来的。样式就没得说了。
    看一下最终的页面

       
        这两天看来还需要好好研习一下程序代码,搞清楚每个类之间的关系及调用。

有一个比较严重的问题,就是IE无故异常,然后关闭,不知道是本机系统问题,还是程序问题。写java web系统这么久,还没有发生过这种问题,或者说这么频繁的发生,确实有点问题。要是真是这样,这个架构就没有什么意义了。希望不要是aom封装js是的问题。 

        遗留问题:TextField 关联数据的引用。
                            DataGrid数据格式化、GridCell的下拉菜单,及数据关联引用。
        DataGrid/EditDataGrid 永远都是问题最多的,因为用到最多,能用好这两个Grid,系统也就能很完美了。

posted @ 2009-06-15 15:39 风人园 阅读(228) | 评论 (0)编辑 收藏

OperaMasks学习系列(一) HelloDuke(原创)

        很久以前,就有注意过这个项目。当再次见到这个项目的时候,都已经到2.x了,而且还有了studio。看上去比以前好多了,所以我想试一下,到底在开发上能有多大的提高。
        这两天搞helloDuke搞了半天,IovC确实是一个不错的想法,只是在页面编写上需要点点注意。就是在放空间的地方,记得一定要放上form,否则是没有办法关联的。这个问题折腾了我几个小时,才把简单的hello搞出来。
          从IoVC来讲,操作控制上确实不错,需要更深入的了解研究。做到页面与控制的真正分离。
        代码很简单,这里就不做说明了,可以去看OperaMasks社区的指导文章,里面有很详细的说明。

        如果OperaMasks真有宣传的那样,想CS那样操作简单,想Ruby那样开发方便,这确实是web开发的一个飞跃,我也来添砖加瓦吧。

        下一节 CRUD,让我们来一步步了解AOM的魅力。。。

posted @ 2009-06-12 13:01 风人园 阅读(208) | 评论 (0)编辑 收藏

如何快速发布java桌面应用

使用java,最大的一个问题就是运行环境,特别是像java桌面运行环境。安装复杂的话,这么多客户端,会把人累死的。所以要寻找一个方便的设置运行环境、启动jar文件的方法。
    1、设置运行环境
                运行环境就是怎么设置环境变量的问题了,通过delphi也可以实现动态设置。只要将jre跟jar一同发布即可。可以方便客户端的安装。

    2、启动程序,也就是怎么运行jar文件
                 在网上找到一个delphi写的,用来启动jar的程序,这样只要把java程序打包成jar文件后,通过这个程序就可以把jar启动起来,不然的话就需要将其重新打包成exe文件来运行了。
  
   3、创建桌面快捷方式
                方便用户启动程序。

未测试

posted @ 2009-04-15 15:33 风人园 阅读(237) | 评论 (0)编辑 收藏

Asp.net 中各种ajax的实现

首先当然是微软的Atlas了,怎么是说也是官方出品,具体看下面的系列文章
ASP.NET AJAX入门系列

posted @ 2008-10-17 16:28 风人园 阅读(152) | 评论 (0)编辑 收藏

hibernate 延迟加载的错误 failed to lazily initialize a collection of role

这个问题一般出现在一对多的情况下,解决的方法有两种
1、设置lazy=false
如果是用annotation,则配置如下
@OneToMany(
   targetEntity = CourseAuthorizationItem.class,
   cascade = {CascadeType.PERSIST, CascadeType.MERGE},
   mappedBy = "course", fetch=FetchType.EAGER
  )
将fetch类型设置成直接获取

2、就是使用filter,过滤所有的链接
如果在使用filter的时候,要配置事务处理,否则会导致session处于只读状态而不能做修改、删除的动作

<web-app>

<filter>
<filter-name>hibernateFilter</filter-name>
<filter-class>
org.springframework.orm.hibernate.support.OpenSessionInViewFilter
</filter-class>
</filter>

<filter-mapping>
<filter-name>hibernateFilter</filter-name>
<url-pattern>*.do</url-pattern>
</filter-mapping>

</web-app>

posted @ 2008-07-05 09:54 风人园 阅读(4798) | 评论 (1)编辑 收藏

spring mvc的常见问题

1,使用new ModelAndView来返回页面,变量需要跟在这个类中直接返回,使用modelMap.addAttribute("message", message);在页面上使用EL表达式无法获得变量。感觉使用new ModelAndView回到页面不能同ModelMap同时使用。

2,form 的映射,spring mvc中,使用默认映射就可以,如果需要映射到一个对象中,直接在方法中指定这个对象声明就可以,这样form提交时会将属性绑定到同名的属性中。比原版的配置映射要简单很多,而且不需要继承FormBean类,比struts也简单,好用很多。

posted @ 2008-03-24 10:23 风人园 阅读(422) | 评论 (0)编辑 收藏

tomcat vm环境变量设置


1、JAVA_HOME
2、PATH
3、CLASSPATH
4、CATALINA_HOME
5、JAVA_OPTS :-Xms512m -Xmx1024m -XX:MaxPermSize=256m -XX:PermSize=128M -verbose:gc

  查看设置的结果:  
  在浏览器上输入http://主机名称:8080,在有个小猫的页面上点击左上角的status,输入用户名:admin,密码为空。在进入的页面上,查看jvm的选项,看是不是已经设置好了256m的内存。   

如果用户名无法登陆,请修改$CATALINA_HOME/conf/tomcat-users.xml.
添加
    <role rolename="manager"/>
    <user username="admin" password="" roles="manager"/>
就可以登陆管理页面

  备注:  
          在设置环境变量java_opts后,要用tomcat/bin/startup.bat启动系统,使得环境变量生效,而用start   tomcat启动系统不会使环境变量生效。  

posted @ 2008-03-12 10:10 风人园 阅读(2195) | 评论 (0)编辑 收藏

eclipse中启动tomcat的时配置jvm参数



如图,设置一下vm的参数就可以,这样
登陆tomcat的管理界面,就能看到当前tomcat所使用的jvm的内存是多大。

-Xms512m -Xmx1024m -XX:MaxPermSize=256m -XX:PermSize=128M

posted @ 2008-03-12 10:05 风人园 阅读(6258) | 评论 (0)编辑 收藏

springmodule整合spring jbpm配置

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN"
              "http://www.springframework.org/dtd/spring-beans-2.0.dtd"
>

<beans>
    
<!-- Hibernate SessionFactory -->
    
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
        
<property name="configLocation">
            
<value>classpath:hibernate.cfg.xml</value>
        
</property>
    
</bean>
    
    
<!-- Transaction manager for a single Hibernate SessionFactory (alternative to JTA) -->
    
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        
<property name="sessionFactory">
            
<ref local="sessionFactory" />
        
</property>
    
</bean>

    
    
<!-- jBPM configuration-->
    
<!--bean id="hibernateConfiguration" factory-bean="sessionFactory" factory-method="getConfiguration"/-->
    
<bean id="jbpmConfiguration" class="org.springmodules.workflow.jbpm31.LocalJbpmConfigurationFactoryBean">
        
<property name="sessionFactory" ref="sessionFactory" />
        
<property name="configuration">
            
<value>classpath:jbpm.cfg.xml</value>
        
</property>
    
</bean>
    
    
<!-- jBPM template -->
    
<bean id="jbpmTemplate" class="org.springmodules.workflow.jbpm31.JbpmTemplate">
        
<constructor-arg index="0" ref="jbpmConfiguration" />
    
</bean>

    
<bean id="testSetUp" class="com.ivo.jpbm.test.TestSetUp">
        
<property name="jbpmTemplate" ref="jbpmTemplate" />
    
</bean>
    
</beans>


这个是spring的配置,hibernate的配置可以直接使用原来的那个。

然后这里可能会出现一个错误,说找不到default.jbpm.context,需要修改jbpm.cfg.xml

这里最简单的方法就是完全复制org/jbpm/default.jbpm.cfg.xml 内容,然后把hibernate部分的东西注释掉就可以了。



然后编写一个test类,用于测试。

整合的步骤如上,下面就是在jbpmTemplate的基础上,将常用的方法重新封装一下。

posted @ 2008-03-10 16:22 风人园 阅读(2623) | 评论 (16)编辑 收藏

springmodule jbpm 3.1

Chapter 9. jBPM 3.1.x

[Note] Note

The following documentation can be used as reference documentation for Spring Modules jBPM 3.0.x support as well.

9.1. Introduction

jBPM module offers integration between the Spring and jBPM allowing for reuse of Spring's Hibernate support along with the IoC container. The module allows jBPM's underlying Hibernate sessionFactory to be configured through Spring and jBPM actions to access Spring's context.

9.2. Configuration

Users familiar with Spring will see that the jBPM module structure resembles with the orm package from the main Spring distribution. The module offers a central template class for working with jBPM, a callback to access the native JbpmContext and a local factory bean for configuration and creating a jBPM instance.

<beans>
<!-- DataSource definition -->
<bean id="dataSource" class="...">
...
</bean>
<!-- Hibernate SessionFactory definition -->
<bean id="hibernateSessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
...
</bean>
<!-- helper for reading jBPM process definitions -->
<bean id="simpleWorkflow"
class="org.springmodules.workflow.jbpm31.definition.ProcessDefinitionFactoryBean">
<property name="definitionLocation"
value="classpath:org/springmodules/workflow/jbpm31/simpleWorkflow.xml"/>
</bean>
<!-- jBPM configuration -->
<bean id="jbpmConfiguration"
class="org.springmodules.workflow.jbpm31.LocalJbpmConfigurationFactoryBean">
<property name="sessionFactory" ref="hibernateSessionFactory"/>
<property name="configuration" value="classpath:jbpm.cfg.xml"/>
<property name="processDefinitions">
<list>
<ref local="simpleWorkflow"/>
</list>
</property>
<property name="createSchema" value="true"/>
<property name="processDefinitionsResources">
<list>
<value>classpath:/org/springmodules/workflow/jbpm31/someOtherWorkflow.xml</value>
</list>
</property>
</bean>
<!-- jBPM template -->
<bean id="jbpmTemplate" class="org.springmodules.workflow.jbpm31.JbpmTemplate">
<constructor-arg index="0" ref="jbpmConfiguration"/>
<constructor-arg index="1" ref="simpleWorkflow"/>
</bean>
set
</beans>

The example above shows how (existing) Spring-managed Hibernate SessionFactories and transaction management can be reused with jBPM.

9.2.1. LocalJbpmConfigurationFactoryBean

The main element is LocalJbpmConfigurationFactoryBean which should be familiar to users acustomed to Spring. Based on the jbpm configuration file and the given SessionFactory, it will create a jBPM configuration which can be used for working with the given process definitions. It is possible to replace jBPM xml configuration with jBPM 3.1.x newly added ObjectFactory - note that if both are present the xml configuration is preffered. LocalJbpmConfigurationFactoryBean allows the creation of the underlying schema based on the process definitions loaded automatically at startup.

Note that the sessionFactory property is not mandatory - Hibernate SessionFactory can be reused with jBPM or jBPM can work by itself without any integration with the existing infrastructure. However, in most scenarios, using LocalJbpmConfigurationFactoryBean allows one to take advantage of Spring transaction management infrastructure so it's possible without any code change to use jBPM, Hibernate and jdbc-based code inside the same transactional context, be it managed locally or globally (JTA). Moreover, it is possible to use thread-bound session or OpenSessionInView patterns with jBPM.

LocalJbpmConfigurationFactoryBean is also aware of the enclosing applicationContext lifecycle - jBPM will be initialized once the context is started (usually application startup) and will be closed properly when the context is destroyed (application is shutdown).

Note that LocalJbpmConfigurationFactoryBean can be configured programatically and can be used standalone only to build an jBPM context which can be used independently of Spring Modules jBPM support.

9.2.2. Inversion of Control: JbpmTemplate and JbpmCallback

Another important feature of Spring Modules jBPM support is JbpmTemplate. The template offers very convient ways of working directly with process definitions as well as jBPM API taking care of handling exceptions (be it jBPM or Hibernate based) in respect to the ongoing transaction (if it's present), the underlying Hibernate session (if pesistent services are used) and the jBPM context. jBPM exceptions (and the underlying Hibernate information) are translated into Spring's DAO exception hierarchy. Everything happens in a transparent and consistent manner.This is possible, as with every Spring-style template,even when direct access to the native JbpmContext is desired, through the JbpmCallback:

public ProcessInstance findProcessInstance(final Long processInstanceId) {
return (ProcessInstance) execute(new JbpmCallback() {
public Object doInJbpm(JbpmContext context) {
// do something
...
return context.getGraphSession().loadProcessInstance(processInstanceId.longValue());
}
});
}

As well, as LocalJbpmConfigurationFactoryBean, the JbpmTemplate can be configured programatically and can be used standalone on a pre-existing jbpmContext (configured through LocalJbpmConfigurationFactoryBean or not) and can be used independently of Spring Modules jBPM support.

9.2.3. ProcessDefinitionFactoryBean

ProcessDefinitionFactoryBean is a simple reader that loads jBPM process definition using Spring's ResourceLoaders. Thus, the xml files can be load using the classpath, relative or absolute file path or even from the Servlet Context. See the official documentation for more information.

[Note] Note

As reported on the forums, using ProcessDefinitionFactoryBean jBPM 3.1.1will trigger a new process definition to be persisted(through deployProcessDefinition) at each startup. While this is useful in development when the database is created on application startup and destroyed on closing, for cases where the definition doesn't change, the process should not be declared inside Spring XML files.

[Note] Note

As reported here, due to the static nature of jBPM, process definitions which include sub processes are not loaded properly if a JbpmContext does not exist at the time of the loading (no exception is thrown whatsoever). As a workaround consider using the LocalJbpmConfigurationFactoryBean's processDefinitionsResources property.

9.2.4. Outside Spring container

It is important to note that while our example showed LocalJbpmConfigurationFactoryBean and JbpmTemplate template inside a Spring xml, these classes do not depend on each other or on Spring application context. They can be just as well configured programatically and can

9.3. Accessing Spring beans from jBPM actions

Another important feature of Spring Modules jBPM integration is allowing Spring configured beans to be reused inside jBPM actions. This allows one to leverage Spring container capabilities (bean lifecycles, scoping, injection, proxying just to name a few) in a transparent way with jBPM. Consider the following Spring application context:

<beans>
<!-- Spring bean visible inside jBPM processed -->
<bean id="jbpmAction" class="org.MyJbpmActionHandler" singleton="true">
<property name="someProp" ref="anotherBean"/>
...
</bean>
..
</beans>

and jBPM process definition:

<?xml version="1.0" encoding="UTF-8"?>
<process-definition name="simpleWorkflow">
<start-state>
<transition to="myState">
</transition>
</start-state>
<state name="myState">
<transition to="end">
<action name="myAction" config-type="bean"
class="org.springmodules.workflow.jbpm31.JbpmHandlerProxy">
<targetBean>jbpmAction</targetBean>
<factoryKey>jbpmConfiguration</factoryKey>
</action>
</transition>
</state>
<end-state name="end"/>
</process-definition>

JbpmHandlerProxy transparently locates Spring applicationContext and searches the bean identified by the targetBean parameter (in this case jbpmAction) and delegate all calls to the jBPM action. This way, one is not limited only to the injection offered by jBPM container and can integrate and communicate in a very easy manner with other Spring managed beans. Moreover, your action lifecycle can be sigleton (one shared instance) or prototype (every call gets a new instance) or in Spring 2.0 scoped to a certain application component (like one instance per http session).

The optional factoryKey parameter specified in this example should be used when one is dealing with more then one jBPM configuration inside the same classloader (not common in practice). The factoryKey should be the same as the bean name of the LocalJbpmConfigurationFactoryBean to be used (in our case jbpmConfiguration).

posted @ 2008-03-10 16:16 风人园 阅读(935) | 评论 (0)编辑 收藏

jbpm--springmoudle

在使用了一段时间的jbpm之后,现在因新项目,想把原来没有整合的地方,现在整合一下,这样对于事务能更好的处理。

framewor : springmvc + spring + hibernate + jbpm

目的: HR的签核流程(加班、请假、教育训练等)

posted @ 2008-02-29 09:12 风人园 阅读(394) | 评论 (0)编辑 收藏

Ext应用六 -- Form

对于Ext form只能说看上去很美,对于一个复杂的页面,写惯了html之后,突然让你写一大堆的js,对我来讲确实有点很为难。一时间实在是接受不了。而且对于页面来说不是很直观,比较难控制。

个人意见,对于复杂的页面还是不要用ext了,实在有点繁。

但是对于象登录页面这种,绝对是可以用ext的,简单,而且用户体验又好。

下面的任务就是做一个跟后台交互的登录页面。
一是自己学习,二是网上完整的代码很少。

以便大家交流参考。:)

期待ing

posted @ 2008-01-10 16:02 风人园 阅读(612) | 评论 (0)编辑 收藏

Ext应用三 -- tab(3)


在使用ajax tab的时候,可能有些资料需要返回给当前的页面,这个时候怎么把那个tab的中的页面的资料传到当前页面呢?不懂

tab中嵌入iframe的简单方法
// second tabs built from JS
    var tabs2 = new Ext.TabPanel({
        renderTo: document.body,
        activeTab: 0,
        width:600,
        height:250,
        plain:true,
        defaults:{autoScroll: true},
        items:[{
                title: 'Disabled Tab',
                disabled:true,
                html: "<iframe src='xxx.jsp' ></iframe>"
            }
        ]
    });

这样就可以轻松实现一个嵌入页面。

ajax方式和iframe方式各有特点。
如果只是显示一些内容的话,用ajax方式方便。
如果有操作,那就用iframe,否则页面路径都需要重新设置,而且提交的时候还有些不方便,js好像也有问题。

posted @ 2008-01-10 14:08 风人园 阅读(857) | 评论 (0)编辑 收藏

Spring MVC Annotation

spring mvc 使用annotation进行controller配置
注:两种urlmapping的模式不能同时使用,如果使用annotation就不能再配置springapp-servlet.xml的urlmapping。

1、xml配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-2.5.xsd">

    <context:component-scan base-package="com.ivo.web.action.spring" />
 
    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="viewClass"><value>org.springframework.web.servlet.view.JstlView</value></property>
        <property name="prefix"><value>/pages/</value></property>
        <property name="suffix"><value>.jsp</value></property>
    </bean>
   
</beans>

    <context:component-scan base-package="com.ivo.web.action.spring" />用于指明系统从哪个路径下寻找controller,然后提前初始化这些对象。

2、web.xml
    跟一般的mvc配置没有区别。

3、controller配置
    具体可以看spring的参考文件,有好几种配置。

    3.1 在方法上配置mapping路径
        

@Controller
public class HelloController {

 @RequestMapping("/hello.do")
 public ModelAndView processImageUpload() throws IOException {
  System.out.println("hello");
  return new ModelAndView("org", "jsonString", "test");
 }

}

    3.2 在class上配置mapping路径,通过参数指定调用的方法

@Controller
@RequestMapping("/hello.do")
public class HelloController {

@RequestMapping(params = "action=save")
 public ModelAndView save() throws IOException {
  System.out.println("hello");
  return new ModelAndView("org", "jsonString", "test");
 }

}

方法的返回值可以是null,string 或者ModelAndView,都支持。

以上是系统暂时用到的,其他的以后再研究。

posted @ 2008-01-10 13:35 风人园 阅读(1809) | 评论 (0)编辑 收藏

Ext应用五 -- 基础方法


1、Ext.get  获得dom对象,类似于document.getElementById

        Ext.get("hideit").on('click', function() {
           var w = Ext.getCmp('west-panel');
           w.collapsed ? w.expand() : w.collapse(); 
        });

2、Ext.getCmp 获得Ext组件对象,然后就可以直接进行组件操作,首先组件要有ID。

posted @ 2008-01-10 09:37 风人园 阅读(625) | 评论 (0)编辑 收藏

Ext应用三 -- Tab(2)

前面在使用了简单的tab之后,在后来的应用中,又用到了高级tab。

需要用户点击一个链接之后,在panel中新增tab。这里有很多地方有疑问。

1、在var viewport = new Ext.Viewport()中定义tab是这样子的。
new Ext.TabPanel({
                id:tabs,
                region:'center',
                enableTabScroll:
true,
                defaults: 
{autoScroll:true},
                deferredRender:
false,
                activeTab:
0,
                items:[
{
                    contentEl:'center2',
                    title: 'Start',
                    autoScroll:
true
                }
]
            }
)
但是这样子导致这个TabPanel没有变量名,不能直接操作。
然后我试了通过viewport.add进行添加的方式,可能是方法使用错误,导致没有出来。
如果效果出来了。
后面还有问题,我怎么通过这个tab来显示一个页面呢。通过ajax tab来显示。在basic tab这个例子里有看到过,知识还没有研究。

下面是动态添加tab的方法
    function addTab(){
        tabs.add(
{
            title: 'New Tab ' 
+ (++index),
            iconCls: 'tabs',
            html: 'Tab Body ' 
+ (index) + '<br/><br/>'
                    
+ Ext.example.bogusMarkup,
            closable:
true
        }
).show();
    }
就通过TabPanel这个对象的变量来直接add。在add时候再动态载入页面内容。

var viewport = new Ext.Viewport({
layout: 'border',
items: [{
region: 'north',
html: 'menu'
}, {
id: 'center_panel',
region: 'center',
layout: 'card',
items: [
{id: 'first_center', html: 'first center'}
]

}]
});


var center = Ext.getCmp('center_panel');
center.remove('first_center');
center.add({
id: 'second_center',
html: 'second center'
});
center.getLayout().setActiveItem('second_center');
center.doLayout();

通过指定TabPanel id,然后通过Ext.getCmp('center_panel'),就可以获得这个panel的句柄,就可以对这个组件进行操作。layout在add/remove之后需要调用center.doLayout()方法,才能使后来新建的tab的生效。

3、ajax tab
function addFormTab(strScreen_ID, strScreenName){
  var tabs = Ext.getCmp('tabs');
  tabs.add({
   id: strScreen_ID,
   title: strScreenName,
   //html: 'second center',
   autoLoad: {url: './pages/web/business_frame.jsp', params: 'screen_ID=WEB.BU&screen_FK=' + strScreen_ID},
   closable:true
  });
  tabs.getLayout().setActiveItem(strScreen_ID);
  tabs.doLayout();
 }

 autoLoad: {url: './pages/web/business_frame.jsp', params: 'screen_ID=WEB.BU&screen_FK=' + strScreen_ID}

指定这个autoload,就可以从相应的指定页面载入。

以上已经测试成功。嘿嘿:)

posted @ 2008-01-09 10:15 风人园 阅读(4844) | 评论 (5)编辑 收藏

Ext应用四 -- Toolbar & Menu

 

Ext.onReady(function(){
 Ext.QuickTips.init();
    
    
var tb = new Ext.Toolbar();
    tb.render('toolbar');
    
    
var menu = new Ext.menu.Menu({
        id: 'mainMenu',
        items: [
            
{
                text: 'Logout',
                handler: Document_onLogout
            }

        ]
    }
);
    
    tb.add(
{
            text:'Main Menu',
            iconCls: 'blist',  
// <-- icon
            menu: menu  // assign menu by instance
        }

    )
}
以上是一个简单的toolbar 及一个下拉按钮。

1、声明一个toolbar
2、定义一个菜单及按钮
3、把菜单添加到toolbar上面。

注: handler: Document_onLogout  是点击这个菜单项时调用这个js函数。

posted @ 2008-01-08 14:03 风人园 阅读(935) | 评论 (0)编辑 收藏

Ext应用三 -- Tab


简单tab的应用,参考例子
    var tabs = new Ext.TabPanel({
        renderTo: 'tabs1',
        width:
450,
        activeTab: 
0,
        frame:
true,
        defaults:
{autoHeight: true},
        items:[
            
{contentEl:'script', title: 'Short Text'},
            
{contentEl:'markup', title: 'Long Text'}
        ]
    }
);

tab的激活事件
在item的配置中增加
    listeners: {activate: handleActivate}
handleActivate是一个方法,也就是当激活某一个tab的时候,就会调用这个方法。

    // second tabs built from JS
    var tabs2 = new Ext.TabPanel({
        renderTo: document.body,
        activeTab: 
0,
        width:
600,
        height:
250,
        plain:
true,
        defaults:
{autoScroll: true},
        items:[
{
                title: 'Normal Tab',
                html: 
"My content was added during construction."
            }
,{
                title: 'Ajax Tab 
1',
                autoLoad:'ajax1.htm'
            }
,{
                title: 'Ajax Tab 
2',
                autoLoad: 
{url: 'ajax2.htm', params: 'foo=bar&wtf=1'}
            }
,{
                title: 'Event Tab',
                listeners: 
{activate: handleActivate},
                html: 
"I am tab 4's content. I also have an event listener attached."
            }
,{
                title: 'Disabled Tab',
                disabled:
true,
                html: 
"Can't see me cause I'm disabled"
            }

        ]

    }
);
autoLoad:异步载入的页面。

posted @ 2007-12-28 14:53 风人园 阅读(1074) | 评论 (0)编辑 收藏

Ext应用二 -- 事件


事件的自定义
 treeDept.on('click', function(node){
    if(node.leaf==true){
       addSelected(node.id, node.text);
    }
 });
如何自定义事件。上面针对tree的单击事件,设置的单击时所要做 的动作。

其他的事件设置可以参考这个。从API上查到相应的事件名称,然后就可以设定了。

posted @ 2007-12-28 14:50 风人园 阅读(650) | 评论 (0)编辑 收藏

Ext应用一 -- TreeView

在导入需要文件之后,以下代码就能生成一个tree了,非常的简单。
ajax去后台action拿组织架构的json字符串。搞定。还有页面上要定义一个div来显示这个tree。
<div id="tree" style="height:330px;width:300px;"></div>

<script type="text/javascript">
Ext.BLANK_IMAGE_URL 
= '<%=request.getContextPath()%>/ext/resources/images/default/s.gif';
 
Ext.onReady(
function(){
    
//alert("start");
    var tree = new Ext.tree.TreePanel( {
        el:'tree',        
        autoScroll:
true,
        loader: 
new Ext.tree.TreeLoader({dataUrl: '<%=request.getContextPath()%>/org.do?department_ID=10000112'})
    }
);

    
var root = new Ext.tree.AsyncTreeNode( {    
            text : 'IVO',
            draggable : 
false,
            id : '
10000000'
            
    }
);
    
    tree.setRootNode(root);

    tree.on('click', 
function(node)
        
//alert(node.id + ", " + node.text);
        if(node.leaf==true){
            addSelected(node.id, node.text);
        }

    }
); 
                
    tree.render();       
}
);
</script>

posted @ 2007-12-28 13:01 风人园 阅读(1337) | 评论 (0)编辑 收藏

struts2 -- Action Configuration (翻译)

Action Mappings
   Action映射可以指定一组result类型,一组异常处理,一个拦截器堆。但是只有name属性是必须的。其他的属性都可以通过package范围提供。
一个登录action
<action name="Logon" class="tutorial.Logon">
  
<result type="redirect-action">Menu</result>
  
<result name="input">/tutorial/Logon.jsp</result>
</action>
Action Names
       在web应用中,name属性是用以匹配浏览器请求路径的一部分(或其他HTTP客户端)。framework会丢掉主机名、应用名和扩展名,并匹配中间部分。所以,一个http://www.planetstruts.org/struts2-mailreader/Welcome.do 会map到 Welcome action。

在应用中,这个到action的链接一般是由struts tag来自动产生的。这个tag通过名字来指定action,并且这个framework会加上默认扩展名和其他一些必须 的东西。

<s:form action="Hello">
    
<s:textfield label="Please enter your name" name="name"/>
    
<s:submit/>
</s:form>
Wildcard Method
      多数情况,一组action mapping会有一个共享模式。比如,你所有的 edit actions都一个“edit”打头, 并调用这个action 类的edit方法。delete actions也是这个模式,但是调用的是delete方法。

这种情况,你就可以通过通配符的方式来定义一次action mapping,远胜于定义每一个action mapping.

<action name="*Crud" class="example.Crud" method="{1}">

这里,一个"editCrud"的action会调用Crud Action类实例的edit方法。同样,一个"deleteCrud"的action会调用delete方法。
另一种常用的方法就是后缀方法名,通过设置"!", "_", 或者其他一些特殊字符。

  • "action=Crud_input"
  • "action=Crud_delete"

To use a postfix wildcard, just move the asterisk and add an underscore.

<action name="Crud_*" class="example.Crud" method="{1}">

posted @ 2007-07-06 09:51 风人园 阅读(642) | 评论 (0)编辑 收藏

SqlMapClient.insert()返回主键

<insert id="saveInfoReq" parameterClass="informationRequisition" >
     INSERT INTO IT_M_InformationRequisition(TrackingNumber, SAPCODE,PLANT_FK) 
     values (#trackingNumber#, #sapCode#,#plant_FK#)
  <selectKey resultClass="int" keyProperty="id" > 
      SELECT @@IDENTITY AS ID
  </selectKey>
 </insert>
在insert的sql声明中,需要嵌套selectKey,然后去运行相应产生主键的语句。在sql server中,是通过@@IDENTITY来产生主键的,这里相当于两个语句,第一个语句insert,完成之后再调用select,这样就能获得这个记录的主键了。

在其他的数据库中也会有相应其他的主键生产方式,按照他们方式就可以返回相应的主键了。

posted @ 2007-07-06 08:18 风人园 阅读(1610) | 评论 (1)编辑 收藏

struts2--Result Configuration

 

当Action类方法完成,会返回一个字符串,这个字符串值用来选择result元素。一个action可以映射到一组不同描述的结果。标准的result是在ActionSupport 这个基类中定义的。

String SUCCESS = "success";
String NONE    
= "none";
String ERROR   
= "error";
String INPUT   
= "input";
String LOGIN   
= "login";

当然,ap可以自定义其他的result标记来match特定的情况。

Result Elements
result有默认值设定,如果不指定属性,则使用success和dispatch来执行这个result

<action name="Hello">
  
<result>/hello/Result.jsp</result>
  
<result name="error">/hello/Error.jsp</result>
  
<result name="input">/hello/Input.jsp</result>
</action>


如上显示,默认情况下,如果返回值是success,则执行第一个result,其他的情况执行下面的匹配的result

Global Results

大部分时候,results都是嵌套在antion元素中。但是很多results会应用到不同的action。在一个安全的应用中,一个client试图访问一个没有认证的页面,那么很多action可能都需要去访问 logon result。
如果action需要共享result, 一组global result可以为每一个package定义。框架首先查询嵌套在action中的本地result,如果本地result没有符合的,则在global result中查询。

<global-results>
  
<result name="error">/Error.jsp</result>
  
<result name="invalid.token">/Error.jsp</result>
  
<result name="login" type="redirect-action">Logon!input</result>
</global-results>

 

Dynamic Results
A result may not be known until execution time. Consider the implementation of a state-machine-based execution flow; the next state might depend on any combination of form input elements, session attributes, user roles, moon phase, etc. In other words, determining the next action, input page, etc. may not be known at configuration time.

Result values may be retrieved from its corresponding Action implementation by using EL expressions that access the Action's properties, just like the Struts 2 tag libraries. So given the following Action fragment:
一个action有时候不可能在执行前就知道它的action,这种情况就需要通过动态result来实现。

 首先定义一个属性,来存放这个值,然后在流程定义中通过EL表达式来取得这个属性值。这样就可以通过程序动态指定需要转发的值。

private String nextAction;

   public String getNextAction() {
       
return nextAction;
   }

you might define a result like this:
<action name="fragment" class="FragmentAction">
        
<result name="next" type="redirect-action">${nextAction}</result>
</action>
If a FragmentAction method returns "next" the actual value of that result will be whatever is in FragmentAction's nextAction property. So nextAction may be computed based on whatever state information necessary then passed at runtime to "next"'s redirect-action.

总结,struts2对于result提供了很多很灵活的设置方法,用户可以使用相应的方法处理特定的逻辑。对于各种情况,总能找出相应的方法来出来。

posted @ 2007-06-27 11:29 风人园 阅读(2854) | 评论 (0)编辑 收藏

FleaPHP入门


1、项目建立
         复制FleaPHP到apache的www目录,我使用的是wamp,在wamp/www下。
         然后在flea/Example/下创建了FleaTest项目目录
         注意: 在引用flea.php这个文件时要注意目录结果,如果路径错误,会提示找不到此文件。
         
      run()方法是mvc程序的入口,默认会调用actionIndex()方法。
  请注意这里我们没有调用 run() 函数。因此我们需要调用 __FLEA_PREPARE() 函数来初始化 FleaPHP 运行环境。并且 __FLEA_PREPARE() 函数应该在用 register_app_inf() 或 set_app_inf() 修改应用程序设置后调用。

2、基础应用示例
      详细参考FleaPHP的官方开发指南
3、应用程序设置
      3.1、自定义配置文件
            在项目目录下,创建Config文件夹,在里面创建MY_APP_INF.php,把需要自定义的一些参数进行设定。程序应该是首先调用默认配置文件,然后再调用自定义配置文件。一般会设置dbDNS
<?php
require('FLEA/FLEA.php');
register_app_inf(
'Config/MY_APP_INF.php');
run();
?>
相对目录查询。

      3.2、单个配置项
         对于少量的设置,可以在入口文件中直接使用set_app_inf()函数制定,例如:
<?php
require('FLEA/FLEA.php');
set_app_inf(
'defaultController', 'UserCenter');
run();
?>

4、错误注意事项
   4.1、缓存设置: 默认配置文件中,缓存目录为null,在使用fleaphp的数据库操作时,会使用到缓存,所以要设置这个目录,默认配置文件为FLEA/Cconfig/DEBUG_MODE_CONFIG.php的'internalCacheDir' => 'Cache',一般用Cache作为目录名。
   4.2、传值部分:在fleaphp新版中,使用引用传值,减少内存使用量,所以在出现如下错误时Fatal error: Cannot pass parameter 1 by reference ???
      就是参数引用的问题,处理方式如下
      _tableClass->create(array('字段'=>'字段值',.....))
      必须改为
      $row = array('字段'=>'字段值',.....);
      _tableClass->create($row);
       因为 create() 等方法现在使用引用传递参数,这样可以提高性能,减少不必要的内存复制操作。

posted @ 2007-05-18 10:34 风人园 阅读(1303) | 评论 (0)编辑 收藏

在线ASC码查询

目前计算机中用得最广泛的字符集及其编码,是由美国国家标准局(ANSI)制定的ASCII码(American Standard Code for Information Interchange,美国标准信息交换码),它已被国际标准化组织(ISO)定为国际标准,称为ISO 646标准。适用于所有拉丁文字字母,ASCII码有7位码和8位码两种形式。
    因为1位二进制数可以表示(21=)2种状态:0、1;而2位二进制数可以表示(22)=4种状态:00、01、10、11;依次类推,7位二进制数可以表示(27=)128种状态,每种状态都唯一地编为一个7位的二进制码,对应一个字符(或控制码),这些码可以排列成一个十进制序号0~127。所以,7位ASCII码是用七位二进制数进行编码的,可以表示128个字符。
    第0~32号及第127号(共34个)是控制字符或通讯专用字符,如控制符:LF(换行)、CR(回车)、FF(换页)、DEL(删除)、BEL(振铃)等;通讯专用字符:SOH(文头)、EOT(文尾)、ACK(确认)等;
    第33~126号(共94个)是字符,其中第48~57号为0~9十个阿拉伯数字;65~90号为26个大写英文字母,97~122号为26个小写英文字母,其余为一些标点符号、运算符号等。
    注意:在计算机的存储单元中,一个ASCII码值占一个字节(8个二进制位),其最高位(b7)用作奇偶校验位。所谓奇偶校验,是指在代码传送过程中用来检验是否出现错误的一种方法,一般分奇校验和偶校验两种。奇校验规定:正确的代码一个字节中1的个数必须是奇数,若非奇数,则在最高位b7添1;偶校验规定:正确的代码一个字节中1的个数必须是偶数,若非偶数,则在最高位b7添1。
    为了便于查询,以下列出ASCII码表:
    第128~255号为扩展字符(不常用)

ASCII码 键盘 ASCII 码 键盘 ASCII 码 键盘 ASCII 码 键盘
27 ESC 32 SPACE 33 ! 34 "
35 # 36 $ 37 % 38 &
39 ' 40 ( 41 ) 42 *
43 + 44 ' 45 - 46 .
47 / 48 0 49 1 50 2
51 3 52 4 53 5 54 6
55 7 56 8 57 9 58 :
59 ; 60 < 61 = 62 >
63 ? 64 @ 65 A 66 B
67 C 68 D 69 E 70 F
71 G 72 H 73 I 74 J
75 K 76 L 77 M 78 N
79 O 80 P 81 Q 82 R
83 S 84 T 85 U 86 V
87 W 88 X 89 Y 90 Z
91 [ 92 \ 93 ] 94 ^
95 _ 96 ` 97 a 98 b
99 c 100 d 101 e 102 f
103 g 104 h 105 i 106 j
107 k 108 l 109 m 110 n
111 o 112 p 113 q 114 r
115 s 116 t 117 u 118 v
119 w 120 x 121 y 122 z
123 { 124 | 125 } 126 ~

posted @ 2007-05-14 10:27 风人园| 编辑 收藏

应用rails进行敏捷web开发--学习笔记二

Depot应用的开发
1、此应用使用增量开发模式,进行的敏捷开发。
ROR可以很好的体现敏捷的特性,具有高效直观的效果,开发的结果可以即可显示,而且不用重新启动服务器。在java中开发的我,已经被不同重启tomcat折磨的不行了。感觉ROR这点很爽。
在完成了第一个hello程序之后更让人心情愉快,这样的开发,简直让人太舒服了,什么配置文件也不用,写完就可以看到结果。比起java web 来,有太多太多好处。不过大家关注的地方不一样,各有优缺点吧。在网站部分,ROR可能继续成长,企业级开发,还是java的天下。

2、user case、pageflow、Data

3、

posted @ 2007-05-13 11:08 风人园 阅读(324) | 评论 (0)编辑 收藏

应用rails进行敏捷web开发--学习笔记一

开发环境
radrails 0.71, radrails就是一个基于eclipse的IDE工具,不过没有提供代码助手功能,这个让我javaer有点不习惯,可能都是被IDE给宠坏了,不喜欢记那么多的名字吧。

下面来做我们的第一个hello world程序。

1、创建项目

输入项目名称

最后点击Finish
radrails会自动运行 rails Hello命令,创建所有需要的目录及文件。
目录机构如图


在servers窗口中会自动创建相应的server,用来启动服务(ruby script/server)

2、创建controller
在Generators窗口中,下拉框选择controller,后一个输入要创建的controller的名字,然后点击go,过几秒钟,系统就会创建controller所需要的文件,最后会在console窗口显示创建的文件,这个时候就说明controller已经创建完成。你可以在app/controller中发现多了一个say_controller.rb的文件

如果要删除都个已经创建好的controller,在第二个下拉框中选择要删除的名字,然后选择Destroy,点击go即可。



3、增加Action
say_controller.rb的默认代码:

class SayController < ApplicationController
end
简单来说action 就是controller中的方法。
添加一个hello的方法
def hello
end
启动服务器,可以测试了。不过因为没有建view页面,所以会出错,出现的错误类似
Missing template ./script/../config/..//app/view/hello.rhtml

4、view页面
在app/views/say/目录下增减hello.rhtml文件,然后输入
<html>

<body>
    <h1>
        Hello from rails!
    </h1>
</body>
</html>
测试页面代码,在刷新,即可出现你想要的页面。
只是到现在为止,所有的都是静态的数据。下面将对action,及view进行重写,添加动态数据。

4、action修改
看如何从action中传数据到view。

  def hello
    @time = Time.now
  end

页面
<p> It is now <%= @time %></p>
在action中定义了一个 @time, 在页面中就可以引用这个实例变量进行显示。

问题:这个没有对这个实例变量进行任何的访问控制,按照ruby的语法,实例变量在对象外面是不能访问的。

posted @ 2007-05-13 09:38 风人园 阅读(577) | 评论 (0)编辑 收藏

Ruby 基础语法

Ruby的注释

Ruby的注释是指从#开始到该行结束。

Ruby的表达式

Ruby的表达式包括下列内容(主要的)。

字符串
字符串是指被单引号(')或双引号(")括起来的部分。在用双引号括起来的字符串中,可以使用反斜杠(\)来指定转义字符,这同C语言是一样的。同时,以#{}括起来的表达式的结果也被置入其中。
数值
整数,浮点数。
数组/散列表
用[]括起来的一串表达式是数组,而以{}括起来的一串表达式是散列表。
散列表是一种可以把任意类型的对象都当成索引的数组。散列表有时也叫做哈希表或辞典。
变量/常数
Ruby中有常数和3种变量。变量和常数的区别在于第一个字符有所不同。
局部变量
变量名以小写英文字母开始。使用时,需要以赋值的方式进行初始化。
全局变量
以$开始。未初始化的值为nil。
实例变量
以@开始。未初始化的值为nil。
类变量
以@@开始。未初始化的值为nil。
类常数
以大写英文字母开始。未初始化的值为nil。
赋值
变量赋值方法如下。
变量=表达式
调用方法(函数)
执行对象固有操作(方法)的方法如下
表达式.方法名
表达式.方法名(表达式..)
在不引起混淆的情况下,可以省略参数的括号。
调用某方法执行主体self的方法时,可以省略最开始的表达式。
方法名
方法名(表达式..)
区分无参数的方法调用和局部变量的方法是看看有没有赋值过程。
操作符表达式
普通的算式可以用(基本上与C语言一样的)操作符来表示。但内部是把操作符当作方法调用(以操作符作为方法名)来处理的。

Ruby的语句

Ruby使用分号(;)或换行来分隔表达式,表达式串起来构成语句。语句的值取决于最后执行的表达式的值。

Ruby的流程控制结构

Ruby中可以使用下列流程控制结构。

  • if表达式 then代码块 [elsif表达式 then代码块]..[else代码块]end
  • case表达式when表达式..;代码块...[else代码块]end
  • while表达式;代码块end
  • for变量..in表达式;代码块end

if和while的意思与通常的语言基本相同。可以使用分号或换行来代替if代码块中的then。请注意Ruby使用elsif代替C语言中的else if。

case是把若干个比较归为一体的控制结构。

for可以使用循环把数组等的元素分别赋值给变量。

循环内可以使用下列语句。

break
中断循环(相当于C语言的break)。
next
开始下一次循环(相当于C语言的continue)。
redo
重新执行块的第一行。

常用的语句

介绍几个Ruby程序中常用的语句。这些语句是对象类的方法,可以在任何类中使用,就如同使用函数一样。

exit([status])
结束程序的运行。若为status指定了一个整数的话,该整数就成为结束status。默认的status值为0。
gets
从命令行参数指定的文件(群)中读取一行,然后把该行的内容作为字符串返回。若没有制定命令行参数的话,则从标准输入中读取。读取的字符串可以被赋值给变量$_。遇到文件结束返回nil(伪)。
while gets
...
end
上面就是典型的用法。
open(文件名[,mode])
打开文件。mode是字符串,就和C的fopen一样。省略时以读取模式打开。
print
输出函数。按顺序将参数输出到标准输出上。省略参数时则输出变量$_的值。

posted @ 2007-05-12 09:00 风人园| 编辑 收藏

ROR 入门

  安装和运行ruby

  Ruby支持多个操作系统平台,目前支持windows、linux和OS X,可以从ruby的官方网站下载ruby的安装程序和源代码:http://www.ruby-lang.org/en/downloads/。

  在windows下为了方便安装,建议下载ruby的安装版本。在安装完后,在ruby的安装目录中的bin目录中有两个可执行文件:ruby.exe和rubyw.exe。第一个将启动一个控制台运行ruby程序,而第二个不启动控制台运行ruby程序。让我们先编写一个简单的ruby程序吧!

  建一个文本文件:first_ruby.rb

  输入一条ruby语句:

puts Time.now.strftime("%Y-%m-%d %H:%M:%S")

  执行ruby first_ruby.rb

  如果输出类似"2006-10-07 19:20:20"的字符串,则说明ruby已经安装成功。

  注:ruby有一个eclipse插件非常不错,如果对其感性趣,可以使用eclipse的help->Software Updates->Find and Install功能通过http://updatesite.rubypeople.org/release进行安装。

  安装和运行rails

  Rails在windows下安装是非常容易的,只需要执行如下命令:

gem install rails --include-dependencies即可。

  注:gem命令在ruby安装目前的bin目录中,运行时要设置path路径。还有在执行这条命令时本机一定要连接internet。因为这条命令是通过internet来下载rails并安装的。

  在安装完rails后。执行下列命令

rails first_rails
cd first_rails
ruby script/server

  如果出现如图1的提示,则说明这些命令执行成功。

进入RubyonRails世界
图1 ruby script/server的提示信息

  然后在IE中输入http://localhost:3000。如果出现如图2的欢迎界面,则说明rails安装成功。


进入RubyonRails世界
图2 rails的欢迎界面

  Rails支持很多数据库,它默认支持的数据库是MySQL。由于使用MySQL数据库不需要安装驱动。因此,本文将使用MySQL数据库来讨论rails如何对数据库进行操作。

posted @ 2007-05-12 08:17 风人园 阅读(1151) | 评论 (1)编辑 收藏

ruby 入门

1、安装及配置
2、HelloWorld

posted @ 2007-05-11 17:14 风人园 阅读(214) | 评论 (0)编辑 收藏

Struts2 flow 配置


1、默认配置
2、别名
3、返回结果

posted @ 2007-05-10 13:12 风人园 阅读(316) | 评论 (0)编辑 收藏

PHP框架

FleaPHP   http://www.fleaphp.org/

posted @ 2007-05-09 20:17 风人园 阅读(271) | 评论 (0)编辑 收藏

RadRails使用参考

利用Radrails开发Ruby on Rails程序入门指南
http://blog.csdn.net/futurelight/archive/2006/09/27/1297526.aspx

详解用radrails调试rails应用程序
http://www.javaeye.com/topic/40548

使用 RadRails 和 Eclipse 可以轻松进行 Ruby on Rails 开发
http://www.ibm.com/developerworks/cn/opensource/os-ecl-radrails/

以上为几个使用参考

posted @ 2007-05-09 20:03 风人园 阅读(987) | 评论 (0)编辑 收藏

Struts2--form设计


1、form的 theme属性

你可以在<s:form>加上theme="simple"属性,然后自已布局form的输出。如:
<s:form action="Login" method="POST" theme="simple">
<table>
<tr>
<td>
User name: <s:textfield name="name" label="User name"/>
</td>
<td>
Password: <s:password name="password" label="Password"/>
</td>
</tr>
</table>
</s:form>

posted @ 2007-05-09 11:13 风人园 阅读(1143) | 评论 (0)编辑 收藏

JSF--ajax4jsf入门示例(repeater)

一、下载
http://labs.jboss.com/jbossajax4jsf/downloads,现在的版本为1.1

·            复制 ajax4jsf.jar and oscache-2.2.jar 到程序的 WEB-INF/lib 文件夹下.
修改web.xml,增加a4j的filter配置

<filter>
          
<display-name>Ajax4jsf Filter</display-name>
          
<filter-name>ajax4jsf</filter-name>
          
<filter-class>org.ajax4jsf.Filter</filter-class>
          
</filter>
          
<filter-mapping>
          
<filter-name>ajax4jsf</filter-name>
          
<servlet-name>Faces Servlet</servlet-name>
          
<dispatcher>REQUEST</dispatcher>
          
<dispatcher>FORWARD</dispatcher>
          
<dispatcher>INCLUDE</dispatcher>
          
</filter-mapping>
</filter>

二、JSP

<%@ taglib uri="https://ajax4jsf.dev.java.net/ajax" prefix="a4j"%>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h"%>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%>
<html>
    
<head>
        
<title>repeater</title>
    
</head>
    
<body>
        
<f:view>
            
<h:form>
                
<h:panelGrid columns="2">

                        
<h:outputText value="Type the Text:" />
                        
<h:inputText value="#{bean.text}">
                                
<a4j:support event="onkeyup" reRender="repeater" />
                        
</h:inputText>

                        
<h:outputText value="Text in the AJAX Response:" />
                        
<h:outputText id="repeater" value="#{bean.text}" />

                
</h:panelGrid>
        
</h:form>

        
</f:view>
    
</body>
</html>
<a4j:support event="onkeyup" reRender="repeater"/>

在这里我们在父标签(<h:inputText>)中添加了一个AJAX 支持. 该支持绑定了JavaScript事件“onkeyup” .因此, 每一次该事件发布给父标签时,我们的程序将发送一个AJAX请求到Server.这意味着我们的受管理的bean将包含该“text” 域中我们输入的最新数据.

<a4j:support> 标签的“reRender” 属性(attribute)定义我们的页面的哪一部分被更新. 在这里,该页面唯一被更新的部位是 <h:outputText> 标签,因为他的ID值和“reRender” 的属性值向匹配. 在一个页面中更新多个元素(elements)也是很简单的:仅仅把他们的IDs放在 “reRender” 属性中就可以了.

三、Bean & faces-config.xml
package com.ivo.a4j.bean;

public class Bean {

    
private String text;

    
public Bean() {
        
//text = "11";
        
//System.out.println("Create");
    }


    
public String getText() {
        
return text;
    }


    
public void setText(String text) {
        
this.text = text;
    }


}

faces-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE faces-config PUBLIC "-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.1//EN" "http://java.sun.com/dtd/web-facesconfig_1_1.dtd">
<faces-config>

    
<managed-bean>
        
<managed-bean-name>bean</managed-bean-name>
        
<managed-bean-class>com.ivo.a4j.bean.Bean</managed-bean-class>
        
<managed-bean-scope>request</managed-bean-scope>
    
</managed-bean>

</faces-config>

posted @ 2007-04-27 08:54 风人园 阅读(2148) | 评论 (1)编辑 收藏

JSF--整合spring

使用JSF-Spring整合
一、下载
进官方网站http://jsf-spring.sourceforge.net,下载lib

二、参考quickstart配置相应文件
http://jsf-spring.sourceforge.net/quickstart.shtml
最终配置结果如下
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
    xmlns:xsi
="http://www.w3.org/2001/XMLSchema-instance" version="2.4"
    xsi:schemaLocation
="http://java.sun.com/xml/ns/j2ee   http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
    
<context-param>
        
<param-name>javax.faces.CONFIG_FILES</param-name>
        
<param-value>
            /WEB-INF/classes/faces/faces-config.xml, 
            /WEB-INF/classes/faces/faces-config-beans.xml
        
</param-value>
    
</context-param>
    
<context-param>
        
<param-name>contextConfigLocation</param-name>
        
<param-value>
            classpath*:spring/applicationContext-*.xml
        
</param-value>
    
</context-param>

    
<servlet>
        
<servlet-name>Faces Servlet</servlet-name>
        
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
        
<load-on-startup>0</load-on-startup>
    
</servlet>
    
<servlet-mapping>
        
<servlet-name>Faces Servlet</servlet-name>
        
<url-pattern>*.faces</url-pattern>
    
</servlet-mapping>
    
<listener>
        
<listener-class>
            org.springframework.web.context.request.RequestContextListener
        
</listener-class>
    
</listener>
    
<listener>
        
<listener-class>
            org.springframework.web.context.ContextLoaderListener
        
</listener-class>
    
</listener>
    
<listener>
        
<listener-class>de.mindmatters.faces.spring.context.ContextLoaderListener</listener-class>
    
</listener>
        
</web-app>

请注意以上listener的顺序,如果位置不同可能出现找不到在spring中定义的bean。请按以上顺序配置即可。

根据quitstart配置完之后可能还有如下异常:
org.apache.jasper.JasperException: javax.servlet.ServletException: javax.servlet.jsp.JspException: javax.faces.el.EvaluationException: de.mindmatters.faces.spring.factory.BeansEvaluationException: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'uiBean': Scope 'request' is not active; nested exception is java.lang.IllegalStateException: No thread-bound request: use RequestContextFilter
org.apache.jasper.servlet.JspServletWrapper.handleJspException(JspServletWrapper.java:532)
org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:408)
org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:320)
org.apache.jasper.servlet.JspServlet.service(JspServlet.java:266)
javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
com.sun.faces.context.ExternalContextImpl.dispatch(ExternalContextImpl.java:322)
com.sun.faces.application.ViewHandlerImpl.renderView(ViewHandlerImpl.java:147)
de.mindmatters.faces.lifecycle.RenderResponsePhase.executePhase(RenderResponsePhase.java:45)
de.mindmatters.faces.lifecycle.AbstractPhase.execute(AbstractPhase.java:37)
de.mindmatters.faces.lifecycle.LifecycleImpl.executePhase(LifecycleImpl.java:166)
de.mindmatters.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:226)
javax.faces.webapp.FacesServlet.service(FacesServlet.java:198)
然后再把这个listener加上
<listener>
  <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
 </listener>

就ok了。

可选
如果还有问题,在faces-config.xml中添加
<application>
     <variable-resolver>
      org.springframework.web.jsf.DelegatingVariableResolver
     </variable-resolver>
  <view-handler>com.sun.facelets.FaceletViewHandler</view-handler>
 </application>

posted @ 2007-04-26 16:18 风人园 阅读(6082) | 评论 (3)编辑 收藏

JSF--Navigate

JSF中最重要的导航设置
一、静态导航
<h:commandButton label="Login" action="login"/>
通过action返回的字符串,然后比较   from-outcome标签值,如果相同,就返回到   to-view-id  制定的页面
注: view ID strings must start with a /.
二、动态导航
<h:commandButton label="Login" action="#{loginController.verifyUser}"/>
根据action中调用的bean方法返回值来确定显示页面
loginController的验证方法
String verifyUser() {

   if (...)

      return "success";

   else

      return "failure";

}


三、高级导航
Redirection
如果你在to-view-id 后 加redirect元素,则JSP容器即中断当前request请求,并发送一个HTTP redirect 请求到client. 
<navigation-case>
   <from-outcome>success</from-outcome>
   <to-view-id>/success.jsp</to-view-id>
   <redirect/>
</navigation-case>

Wildcards(通配符)
<navigation-rule>
   <from-view-id>/secure/*</from-view-id>
   <navigation-case>
      . . .
   </navigation-case>
</navigation-rule>
只要是在/secure/这个目录下的页面都使用这个导航规则。

所有
<from-view-id>/*</from-view-id>

or
<from-view-id>*</from-view-id>

Using from-action
<navigation-case>
  <from-action>#{quiz.answerAction}</from-action>
  <from-outcome>again</from-outcome>
  <to-view-id>/again.jsp</to-view-id>
</navigation-case>
<navigation-case>
  <from-action>#{quiz.startOverAction}</from-action>
  <from-outcome>again</from-outcome>
  <to-view-id>/index.jsp</to-view-id>
</navigation-case>
根据不同的action使用不同的导航规则。

导航算法

The algorithm has three inputs(算法有三个输入):

  • The outcome, that is, the value of an action attribute or the string resulting from the invocation of a method reference. action属性的值或者引用方法的返回结果(字符串类型)

  • The view ID of the current view。当前视图

  • The action, that is, the literal value of the action attribute in the component that triggered the navigation.用以触发导航的组件属性。

The first of two phases is to find the matching navigation-rule, following these steps(第二阶段的第一步就是寻找符合的导航规则).

  • If the outcome is null, return immediately and redisplay the current page.(如果outcome是空,则立刻返回重新显示当前页面)
  • Merge all navigation rules with the same from-view-id value.(合并相同from-view-id的导航规则)
  • Try to find a navigation rule whose from-view-id value matches the view ID exactly. If such a rule exists, take it.
  • Consider all navigation rules whose from-view-id values end with a wildcard suffix, such as secure. For each such rule, check whether the prefix (after removing the *) is identical to the corresponding prefix of the view ID. If there are matching rules, take the one with the longest matching prefix.
  • If there is a rule without a from-view-id, take it.(如果有没有from-view-id的规则,使用)
  • If there is no match at all, redisplay the current page.(如果都没有符合,重新显示当前页面)

The second of two phases is to consider all navigation-case elements in the matching navigation rule (which may consist of several merged navigation-rule elements with matching from-view-id.values).

Follow these steps to find the matching case.

  • If a case has both matching from-outcome and from-action, take it.
  • Otherwise, if a case has matching from-outcome and no from-action, take it.
  • Otherwise, if a case has matching from-action and no from-outcome, take it.
  • Otherwise, if there is a case with neither from-outcome or from-action, take it.
  • If there is no match at all, redisplay the current page.
    Naturally, we recommend that you do not create tricky navigation rules in your own programs. As long as you stay away from wildcards and from-action elements, you won't need to know about the gory details of the navigation algorithm.


 

posted @ 2007-04-26 15:23 风人园 阅读(574) | 评论 (0)编辑 收藏

JSF--Managed Beans

一、beans在 faces-config.xml中的定义
格式如下:

<managed-bean>
   
<managed-bean-name>user</managed-bean-name>
   
<managed-bean-class>com.corejsf.UserBean</managed-bean-class>
   
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>
意思:在session中创建了一个user名字的UserBean对象。
在bean定义之后,就可以通过JSF组件来访问Bean的属性。
 如    <h:inputSecret value="#{user.password}"/>,访问userbean的password属性。

二、Message Bundle
自定义资源文件com/corejsf/messages.properties,通过f:loadBundle访问
<f:loadBundle basename="com.corejsf.messages" var="msgs"/>
basename : properties文件的路径
var: 文件定义的message key

com/corejsf/messages_de.properties.
国际化,在默认资源文件的基础上,增加后缀,标识语言类别。

语言默认显示设置
  • You can add a locale attribute to the f:view element, for example   <f:view locale="de">

  • You can set the default and supported locales in WEB-INF/faces-config.xml (or another application configuration resource):

    <faces-config>
    <application>
    <locale-config>
    <default-locale>en</default-locale>
    <supported-locale>de</supported-locale>
    </locale-config>
    </application>
    </faces-config>
    
    三、Backing Beans
    四、Bean Scope
  • Request

    Session
    Application

    五、Configure Bean 
    设置属性值
      <managed-bean>
       <managed-bean-name>user</managed-bean-name>
       <managed-bean-class>com.corejsf.UserBean</managed-bean-class>
       <managed-bean-scope>session</managed-bean-scope>
       <managed-property>
          <property-name>name</property-name>
          <value>me</value>
       </managed-property>
       <managed-property>
          <property-name>password</property-name>
          <value>secret</value>
       </managed-property>
    </managed-bean>
    设置null值
    <managed-property>
       <property-name>password</property-name>
       <null-value/>
    </managed-property>

    posted @ 2007-04-26 14:00 风人园 阅读(549) | 评论 (0)编辑 收藏

    JSF-- 入门 First Example

    一、JSF开发环境
       使用myeclipse的功能,添加相关lib到classpath。 或者从sun的官方网站下载相关lib。
    http://java.sun.com/javaee/javaserverfaces/download.html
    二、JSP页面
          index.jsp

    <html>
        
    <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%>
        
    <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h"%>

        
    <f:view>
            
    <head>
                
    <title>A Simple JavaServer Faces Application</title>
            
    </head>
            
    <body>
                
    <h:form>
                    
    <h3>Please enter your name and password.</h3>
                    
    <table>
                        
    <tr>
                            
    <td>Name:</td>
                            
    <td><h:inputText value="#{user.name}" /></td>
                        
    </tr>
                        
    <tr>
                            
    <td>Password:</td>
                            
    <td><h:inputSecret value="#{user.password}" /></td>
                        
    </tr>
                    
    </table>
                    
    <p><h:commandButton value="Login" action="login" /></p>
                
    </h:form>
            
    </body>
        
    </f:view>
    </html>


          welcome.jsp

    <html>
        
    <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%>
        
    <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h"%>

        
    <f:view>
            
    <head>
                
    <title>A Simple JavaServer Faces Application</title>
            
    </head>
            
    <body>
                
    <h3> Welcome to JavaServer Faces,
                    
    <h:outputText value="#{user.name}" /> !
                
    </h3>
            
    </body>
        
    </f:view>
    </html>


    三、Bean
          UserBean .java
       package com.test.jsf.bean;

    public class UserBean {

     private String name;

     private String password;

     // PROPERTY: name
     public String getName() {
      return name;
     }

     public void setName(String newValue) {
      name = newValue;
     }

     // PROPERTY: password
     public String getPassword() {
      return password;
     }

     public void setPassword(String newValue) {
      password = newValue;
     }
     
     public String check() {
      name = "wxf";
      return "success";
      //return SUCCESS;
     }
    }

    四、faces-config
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE faces-config PUBLIC "-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.1//EN" "http://java.sun.com/dtd/web-facesconfig_1_1.dtd">
    <faces-config >
     <navigation-rule>
     
        <from-view-id>/login/index.jsp</from-view-id>
        <navigation-case>
           <from-outcome>login</from-outcome>
           <to-view-id>/login/welcome.jsp</to-view-id>
        </navigation-case>
     </navigation-rule>
     
     <managed-bean>
        <managed-bean-name>user</managed-bean-name>
        <managed-bean-class>
           com.test.jsf.bean.UserBean
        </managed-bean-class>
        <managed-bean-scope>session</managed-bean-scope>
     </managed-bean>

    </faces-config>
    五、web.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns="http://java.sun.com/xml/ns/j2ee"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.4"
     xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee   http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
     <context-param>
      <param-name>javax.faces.CONFIG_FILES</param-name>
      <param-value>/WEB-INF/faces-config.xml</param-value>
     </context-param>

     <servlet>
      <servlet-name>Faces Servlet</servlet-name>
      <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
      <load-on-startup>0</load-on-startup>
     </servlet>
     <servlet-mapping>
      <servlet-name>Faces Servlet</servlet-name>
      <url-pattern>*.faces</url-pattern>
     </servlet-mapping>
    </web-app>


    六、测试

       http://localhost:8080/jsf/login/index.faces
    注意,调用jsp页面时一定要使用faces,结尾,否则jsf的标签将无法识别

    posted @ 2007-04-26 12:56 风人园 阅读(597) | 评论 (0)编辑 收藏

    jBPM--Node Type

    Nodetype task-node

    A task node represents one or more tasks that are to be performed by humans. So when execution arrives in a task node, task instances will be created in the task lists of the workflow participants. After that, the node will behave as a wait state. So when the users perform their task, the task completion will trigger the resuming of the execution. In other words, that leads to a new signal being called on the token.
    任务节点:一个或多个可以人为执行的任务。所以当执行到任务节点,任务实例将由工作流参与者的任务列表创建。之后,这个节点会表现为等待状态。当用户执行他们的任务,任务完成将会触发执行继续。还句话说,在token上会调用一个新的signal

    Nodetype state

    A state is a bare-bones wait state. The difference with a task node is that no task instances will be created in any task list. This can be usefull if the process should wait for an external system. E.g. upon entry of the node (via an action on the node-enter event), a message could be sent to the external system. After that, the process will go into a wait state. When the external system send a response message, this can lead to a token.signal(), which triggers resuming of the process execution.

    Nodetype decision

    Actually there are 2 ways to model a decision. The distinction between the two is based on *who* is making the decision. Should the decision made by the process (read: specified in the process definition). Or should an external entity provide the result of the decision.

    When the decision is to be taken by the process, a decision node should be used. There are basically 2 ways to specify the decision criteria. Simplest is by adding condition elements on the transitions. Conditions are beanshell script expressions that return a boolean. At runtime the decision node will loop over its leaving transitions (in the order as specified in the xml), and evaluate each condition. The first transition for which the conditions resolves to 'true' will be taken. Alternatively, an implementation of the DecisionHandler can be specified. Then the decision is calculated in a java class and the selected leaving transition is returned by the decide-method of the DecisionHandler implementation.

    When the decision is taken by an external party (meaning: not part of the process definition), you should use multiple transitions leaving a state or wait state node. Then the leaving transition can be provided in the external trigger that resumes execution after the wait state is finished. E.g. Token.signal(String transitionName) and TaskInstance.end(String transitionName).

    Nodetype fork

    A fork splits one path of execution into multiple concurrent paths of execution. The default fork behaviour is to create a child token for each transition that leaves the fork, creating a parent-child relation between the token that arrives in the fork.

    Nodetype join

    The default join assumes that all tokens that arrive in the join are children of the same parent. This situation is created when using the fork as mentioned above and when all tokens created by a fork arrive in the same join. A join will end every token that enters the join. Then the join will examine the parent-child relation of the token that enters the join. When all sibling tokens have arrived in the join, the parent token will be propagated over the (unique!) leaving transition. When there are still sibling tokens active, the join will behave as a wait state.

    Nodetype node

    The type node serves the situation where you want to write your own code in a node. The nodetype node expects one subelement action. The action is executed when the execution arrives in the node. The code you write in the actionhandler can do anything you want but it is also responsible for propagating the execution.

    This node can be used if you want to use a JavaAPI to implement some functional logic that is important for the business analyst. By using a node, the node is visible in the graphical representation of the process. For comparison, actions --covered next-- will allow you to add code that is invisible in the graphical representation of the process, in case that logic is not important for the business analyst.

    posted @ 2007-01-25 09:32 风人园 阅读(713) | 评论 (0)编辑 收藏

    jBPM之名词解释

    JbpmConfiguration:configuration of one jBPM instance.
    JbpmContext:is used to surround persistent operations to processes.
    ProcessDefinition
    ProcessInstance:is one execution of a ProcessDefinition. To create a new process execution of a process definition, just use the ProcessInstance(ProcessDefinition).
    ContextInstance:maintains all the key-variable pairs for a process instance
    TaskMgmtSession:
                                     
    findTaskInstances(java.lang.String actorId) 
                                      get the tasllist for a given actor.(根据角色得到此角色的任务列表)
                                     loadTaskInstance(long taskInstanceId) 
                                      get the task instance for a given task instance-id.(根据实例ID获得任务实例)
    TaskInstance:   
                                     
    end() marks this task as done.
                                     end(java.lang.String transitionName) 
                                      marks this task as done and specifies the name of a transition leaving the task-node for the case that the completion of this task instances triggers a signal on the token.

    posted @ 2007-01-19 12:47 风人园 阅读(582) | 评论 (1)编辑 收藏

    jBPM之Custom node behaviour

    在流程中会涉及到很多的分支结构,下面就用代码说明
    public class AmountUpdate implements ActionHandler {
      
    public void execute(ExecutionContext ctx) throws Exception {
        
    // business logic
        Float erpAmount = get amount from erp-system;
        Float processAmount 
    = (Float) ctx.getContextInstance().getVariable("amount");
        
    float result = erpAmount.floatValue() + processAmount.floatValue();
        update erp
    -system with the result;
        
        
    // graph execution propagation
        if (result > 5000{
          ctx.leaveNode(ctx, 
    "big amounts");
        }
     else {
          ctx.leaveNode(ctx, 
    "small amounts");
        }

      }

    }
    leaveNode(java.lang.String transitionName)
              leave this node over the given transition.
    通过ctx的 leaveNode方法,来确定下一个node,这样就可以通过代码动态控制流程。

    posted @ 2007-01-18 14:18 风人园 阅读(513) | 评论 (0)编辑 收藏

    jBPM之swimlane

     

    swimlane一般是为了task准备的,任务总是要分配到某个人头上的。如果在流程定义文件中任务没有指定对应的泳道如:,那么就需要在程序代码中分配相关的处理人taskInstance.setActorId("jeffen")。如果程序都是这样来搞那其实是很麻烦的,而且分配代码分散到各个地方,很容易出错。于是引进了泳道,我们可以在流程定义文件中统一指定swimlane和处理人的关系、task和swimlane的关系,只需要维护这一个文件就好了,(有点像struts的配置文件)如下:

    < swimlane name = " banker " >
            
    < assignment expression = " user(jeffen) " />
    </ swimlane >
    ......

    < task name = " bank "   swimlane = " banker " >

    这样就将任务实例和处理人松耦合了,对于多任务对应相同的处理人,这种方式的好处显而易见。

    当然还可以在程序中动态指定处理人,如上taskInstance.setActorId("jeffen"),也可以通过泳道实例swimlaneInstance.setActorId("jeffen")指定。

    posted @ 2007-01-18 11:56 风人园 阅读(2391) | 评论 (2)编辑 收藏

    jBPM之JbpmContext

    The three most common persistence operations are:

    • Deploying a process
    • Starting a new execution of a process
    • Continuing an execution

    First deploying a process definition. Typically, this will be done directly from the graphical process designer or from the deployprocess ant task. But here you can see how this is done programmatically:

    JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
    try {
      ProcessDefinition processDefinition = ...;
      jbpmContext.deployProcessDefinition(processDefinition);
    } finally {
      jbpmContext.close();
    }

    For the creation of a new process execution, we need to specify of which process definition this execution will be an instance. The most common way to specify this is to refer to the name of the process and let jBPM find the latest version of that process in the database:

    JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
    try {
      String processName = ...;
      ProcessInstance processInstance = 
          jbpmContext.newProcessInstance(processName);
    } finally {
      jbpmContext.close();
    }

    For continuing a process execution, we need to fetch the process instance, the token or the taskInstance from the database, invoke some methods on the POJO jBPM objects and afterwards save the updates made to the processInstance into the database again.

    JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
    try {
      long processInstanceId = ...;
      ProcessInstance processInstance = 
          jbpmContext.loadProcessInstance(processInstanceId);
      processInstance.signal();
      jbpmContext.save(processInstance);
    } finally {
      jbpmContext.close();
    }

    Note that if you use the xxxForUpdate methods in the JbpmContext, an explicit invocation of the jbpmContext.save is not necessary any more because it will then occur automatically during the close of the jbpmContext. E.g. suppose we want to inform jBPM about a taskInstance that has been completed. Note that task instance completion can trigger execution to continue so the processInstance related to the taskInstance must be saved. The most convenient way to do this is to use the loadTaskInstanceForUpdate method:

    JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
    try {
      long taskInstanceId = ...;
      TaskInstance taskInstance = 
          jbpmContext.loadTaskInstanceForUpdate(taskInstanceId);
      taskInstance.end();
    } finally {
      jbpmContext.close();
    }

    posted @ 2007-01-18 11:39 风人园 阅读(1811) | 评论 (0)编辑 收藏

    jBPM之hello world

    参考
    http://www.blogjava.net/chengang/archive/2006/07/13/57986.html

    下面是根据官方开发向导及自己的经验写的

    开发向导上提供的helloworld例子,这个流程是单向的,没有任何的分支,且没有自定义actionHandler,使用的是默认的handler
    public void testHelloWorldProcess() {
      // This method shows a process definition and one execution// of the process definition.  The process definition has // 3 nodes: an unnamed start-state, a state 's' and an // end-state named 'end'.// The next line parses a piece of xml text into a// ProcessDefinition.  A ProcessDefinition is the formal // description of a process represented as a java object.
      ProcessDefinition processDefinition = ProcessDefinition.parseXmlString(
        "<process-definition>" +
        "  <start-state>" +
        "    <transition to='s' />" +
        "  </start-state>" +
        "  <state name='s'>" +
        "    <transition to='end' />" +
        "  </state>" +
        "  <end-state name='end' />" +
        "</process-definition>"
      );
      
      // The next line creates one execution of the process definition.// After construction, the process execution has one main path// of execution (=the root token) that is positioned in the// start-state.
      ProcessInstance processInstance = 
          new ProcessInstance(processDefinition);
      
      // After construction, the process execution has one main path// of execution (=the root token).
      Token token = processInstance.getRootToken();
      
      // Also after construction, the main path of execution is positioned// in the start-state of the process definition.
      assertSame(processDefinition.getStartState(), token.getNode());
      
      // Let's start the process execution, leaving the start-state // over its default transition.
      token.signal();
      // The signal method will block until the process execution // enters a wait state.// The process execution will have entered the first wait state// in state 's'. So the main path of execution is now // positioned in state 's'
      assertSame(processDefinition.getNode("s"), token.getNode());
    
      // Let's send another signal.  This will resume execution by // leaving the state 's' over its default transition.
      token.signal();
      // Now the signal method returned because the process instance // has arrived in the end-state.
      
      assertSame(processDefinition.getNode("end"), token.getNode());
    }

    更详细的例子可以看参考,里面有很详细的操作说明。




    下面是根据参考例子测试时出现的一些问题及说明。
    一、关于数据库,首先要修改数据库连接,然后创建数据库,里面的表格jBPM提供相应的API去创建。
    public void testDeployProcessDefinition() throws FileNotFoundException 
            
    // 从 jbpm.cfg.xml 取得 jbpm 的配置 
            JbpmConfiguration config = JbpmConfiguration.getInstance();
            config.dropSchema();//删除数据表结构
            config.createSchema();//创建数据表结构
            
    // 创建一个 jbpm 容器 
            JbpmContext jbpmContext = config.createJbpmContext(); 
            
    // 由 processdefinition.xml 生成相对应的流程定义类 ProcessDefinition 
            InputStream is = new FileInputStream("processes/simple/processdefinition.xml"); 
            ProcessDefinition processDefinition 
    = ProcessDefinition.parseXmlInputStream(is); 
            
            
    // 利用容器的方法将流程定义数据部署到数据库上 
            jbpmContext.deployProcessDefinition(processDefinition); 
            
    // 关闭 jbpmContext 
            jbpmContext.close(); 
        }

    这个是根据流程配置文件最后生成的数据库信息的测试方法,刚开始我还有一个疑问,数据库和数据表是系统自动创建还
    是要手动创建,数据库是要手动创建的,数据表可以自动创建的



    posted @ 2007-01-18 10:55 风人园 阅读(1001) | 评论 (0)编辑 收藏

    Struts 2.0 起步

    参考 http://www.blogjava.net/max/category/16130.html

    1、添加struts2的jar包,struts2-core-2.x.x.jar, struts2-api-2.x.x.jar (struts2-all-2.x.x.jar即可,其他的struts2的插件包已经包含在里面)。
       如添加其他的插件包,可能会出现文件重复,具体可以看异常信息。
       或者不要加all包,而使用插件包,可以减小包的大小。
    2、修改web.xml

     1 <? xml version="1.0" encoding="UTF-8" ?>
     2 < web-app  version ="2.4"  
     3  xmlns ="http://java.sun.com/xml/ns/j2ee"  
     4  xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance"  
     5  xsi:schemaLocation ="http://java.sun.com/xml/ns/j2ee 
     6  http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" >
     7   < display-name > Struts2 Hello World! </ display-name >   
     8
     9     < filter >
    10          < filter-name > Struts2 </ filter-name >
    11          < filter-class >
    12             org.apache.struts2.dispatcher.FilterDispatcher
    13          </ filter-class >
    14      </ filter >
    15      < filter-mapping >   
    16          < filter-name > Struts2 </ filter-name >   
    17          < url-pattern > /* </ url-pattern >   
    18      </ filter-mapping >   
    19 </ web-app >
    20


    3、在classpath下添加struts.properties文件,内容如下
    struts.devMode = true
    struts.enable.DynamicMethodInvocation = false

    4、在classpath下添加struts.xml,这个是对应struts1.x里面的struts-config.xml

     1 <! DOCTYPE struts PUBLIC
     2         "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
     3         "http://struts.apache.org/dtds/struts-2.0.dtd" >
     4 < struts >
     5      < package  name ="example"  extends ="struts-default" >
     6          < action  name ="hello"  class ="com.ivo.struts2.HelloWorld"  method ="aliasAction" >
     7              < result > /hello.jsp </ result >
     8          </ action >
     9          < action  name ="Login"  class ="com.ivo.struts2.Login" >
    10        < result > /hello.jsp </ result >
    11    </ action >
    12    < action  name ="LoginX"  class ="com.ivo.struts2.LoginX" >
    13        < result > /hello.jsp </ result >
    14    </ action >
    15      </ package >
    16 </ struts >


    注意,struts2的两个相关文件需要放在classpath下

    posted @ 2006-12-29 10:09 风人园 阅读(523) | 评论 (0)编辑 收藏