|
2009年8月21日
http://blog.csdn.net/code__code/article/details/53885510
1. 使用Spring Security管理用戶身份認證、登錄退出
2. 用戶密碼加密及驗證
3. 采用數據庫的方式實現Spring Security的remember-me功能
4. 獲取登錄用戶信息。
5.使用Spring Security管理url和權限
摘要: // 自定義登錄頁面 http.csrf().disable().formLogin().loginPage("/login") //指定登錄頁的路徑&n... 閱讀全文
<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
為了解決一些比較費時且不是很緊要的任務,將此任務轉為異步任務處理,提高前端操作體驗。
spring 中 自帶注解 @Async.
配置如下
applicationContext.xml 中 增加 task的引用
如上配置之后,只需要在 需要進行異步調用的方法前面增加 注解就可以了。
@Async
public void updateOrderBillItemPQty(String deptId, String orderNo, Integer orderItemSid, Double pQty) {
注:需要注意,同一個對象里面方法調用,不會作為異步方法執行。
在對 TextView 或者 EditText 進行賦值時,調用setText()方法,一定要注意,使用String類型,不要使用int 或者long,否則 會出現找不到資源的異常。系統自動會將int作為一個資源ID,然后去R 里面找,結果找不到。
摘要: http://blog.csdn.net/meng425841867/article/details/8523730
在按鍵單擊事件中添加創建對話框并設置相關屬性。
[java] view plain copy
dialogButton=(Button)findViewBy... 閱讀全文
摘要: http://daoshud1.iteye.com/blog/1874241
本文講實現一個自定義列表的Android程序,程序將實現一個使用自定義的適配器(Adapter)綁定 數據,通過contextView.setTag綁定數據有按鈕的ListView。 系統顯示列表(ListView)時,首先會實例化一個適配器,本文將實例化一個自定義的適配器。實現 自定義適... 閱讀全文
摘要: http://blog.csdn.net/x605940745/article/details/11981049
SimpleAdapter的參數說明 第一個參數 表示訪問整個android應用程序接口,基本上所有的組件都需要 第二個參數表示生成一個Map(String ,Object)列表選項 第三個參數表示界面布局的id 表示該文件作為列表項的組件&... 閱讀全文
首先是布局文件,這里需要兩個布局文件,一個是放置列表控件的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);
}
單數據{'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();
}
}
-
- Button Btn1 = (Button)findViewById(R.id.button1);
- Btn1.setOnClickListener(new Button.OnClickListener(){
- public void onClick(View v) {
- String strTmp = "點擊Button01";
- Ev1.setText(strTmp);
- }
-
- });
-
- public void Btn3OnClick(View view){
- String strTmp="點擊Button03";
- Ev1.setText(strTmp);
-
- }
- <Button
- android:id="@+id/button3"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="Button3"
- 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) {
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 ;
}
}
}
一、直接打開,不傳遞參數 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));
}
}
三、回傳參數
1、不同android 版本,需要設置不同的 sytle 文件。 默認 通常我們會設置values下面的style 文件 但是如果是4.0以上,則還需要設置values-v14下面的style文件。 否則不能生效
找了很多方案,都說是那個KB939373 這個補丁搞的,但是在添加刪除里就是找不到這個東東,重裝也沒有用,后來找到了這篇文章 http://www.cnblogs.com/skylaugh/archive/2011/07/21/2112860.html根據這篇文章,我把 infocomm.dll 給替換一下,然后就好了,簡直就是坑爹啊。 這里講講需要注意的事項。 1、替換的文件通過iis安裝文件生成,請看參考文章 2、文件直接黏貼覆蓋,不要使用參考里面bat處理。 3、然后啟動這個服務,啟動iis,搞定
昨天部署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
標記一下:)
提示無法載入 c.tld等信息
只要刪除 WEB-INF/lib 下的上述兩個文件即可
因為此文件與 tomcat中的文件版本沖突
淺談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
這個問題一直比較奇怪,今天搜了一下,原來是瀏覽器的問題,這讓我想起來了網頁版的網游,不能多登的問題。原來session是相同的。
打開的是兩個瀏覽器還是兩個頁簽, 比如 IE7這種支持多頁簽的,也就是在一個瀏覽器里面同時打開多個頁簽的這種,是共用一個Session的, 但是比如IE6這種一次只能打開一個瀏覽器的,就沒有問題,
因為打開的是多個瀏覽器我說了,這個和瀏覽器相關,每當你打開一個瀏覽器,這個瀏覽器就會有專門的session.
也算是解決了一個問題吧:)
這里標記一下
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
設置注釋模板的入口: 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} */
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,來指定變量名稱
spring的事物配置,默認狀態下,只針對 RuntimeException 進行回滾。
而像SQLException并不是RuntimeException,所以這里需要特別注意。
這里困擾了我很久,一直沒有想明白為什么在一個事務里面,部分成功,部分失敗??赡芫褪沁@個原因導致的。
也就是說,一些系統級別的異常,前期都需要轉化成 RuntimeException 。這樣就可以進行回滾了。
但是這樣的只需要修改底層,另外一個偷懶的方法,在每個service類上直接指定rollback = Exception.class。這樣所有的異常都會回滾。但是這樣有沒有副作用,但是不清楚。
異常一直是我沒有搞定的一塊內容之一,稱這個機會研究一下。
為什么需要分check 和unckeck,兩者有什么不動點。
如果都是用uncheck,會不會有什么問題?
待續。。。
以前沒怎么用,現在真用起來的時候還是會有很多白癡問題,哈。
今天想做一個left join , 關聯關系應該是已經配好了,但是調用hql就是報錯,也不知道怎么回事。繼續研究ing。
struts2+spring2.5+hibernate 3.3
在hibernate的操作中,特別是主從數據的操作。
一般有這么幾個地方需要注意,以前也一直沒有拿hibernate好好用過,現在真正用起來,問題還是挺多了。這幾天一直在調試解釋這種問題。
主數據中的一對一關聯,這里的關聯數據從頁面提交的時候是否可以直接映射到主數據對象中?暫時不清楚,可以測試一下。
然后是明細數據的操作,現在動態產生的行數據,然后手動解析,生成明細對象。整個過程個人感覺比較麻煩,暫時也想不出有什么好的解決方案。
這里在級聯保存數據的時候,首先要清除掉原來的明細數據,然后再把頁面提交過來的數據加上。
不知道一般是不是這樣弄的。否則沒法清楚原來的數據。
通過搜索和閱讀myEclipse的幫助文件,發現這是可以實現的。不過前提是,你使用的hibernate是3.2版本。這樣就可以支持以注解的方式生成實體類了。跟hbm配制文件方式基本是一樣的。
昨天特地好好的看了一下MyEclipse的幫助,里面關于ajax web開發的工具感覺還是挺好用的,以前一直也沒有了解一下里面的功能,以后要好好用一下,還是可以有不少幫助的。
今天先起個頭,明天寫一個詳細的操作說明,這樣也方便自己,免得忘了。
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等等都簡單很多,用起來比較舒服。
服務器路徑的獲?。簉equest.getSession().getServletContext().getRealPath(name);
這樣就可以獲得web目錄下某個文件的服務器端路勁。
今天在使用的時候發現一個問題,就是在使用表達式的時候有一個地方需要注意
像上面的這個表達式就會出錯,這里也沒有看源代碼,具體不是很清楚,但是看了一下日志,發現,后面的這個item也被替換了,所以覺得這個可能是jxls的bug或者是作者偷懶搞的。
以后只需要注意字段名不能跟bean的名字一樣,否則就出錯。
僅此記錄
主要講一下在配置的過程中出現的問題,基本的配置方式網上有很多。
這里講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啟動了。我重啟一下就會出現這個問題,第一次啟動就沒有問題,暫時不知道什么原因。
找到了為什么重復啟動的問題,項目啟動了兩次,導致后一次啟動端口被暫用。
總的來說還是不錯的,但是還搞不清楚怎么正確使用。
繼續努力中
干了這么多年的代碼工,對于代碼質量的理解,個人認為就是一個,可維護性,除非你開發的東東是一錘子買賣,否則后期的投入會多的可怕,而且對于錯誤就沒有辦法控制了
下面引用別人的一段話來說明一下什么是高質量的代碼:
高質量的代碼,除了符合產品的功能設計需求外,還應該便于維護、執行效率高、經過充分測試并且擁有較好的穩定性。
但是從我個人來講,可維護性是第一位的,其他都是必須的,沖突的話就應該適當取舍。便于維護必然會影響到一點點的效率,但是這個肯定是可以接受的。是可以通過其他方式來彌補的。
不能為了追求所謂的高效,而破壞了系統的維護性,這樣導致后期維護會有很大的問題,從而可能導致低效。
這里介紹幾個工具,來提高代碼質量。findbugs就是其中的一個,可以對代碼提出很好的修改建議。
purifyplus 一個運行時檢測系統,可惜不免費。
備注: rational team concert 協作開發系統,集成版本控制、工作項和構建
一般,系統中把提示信息保存在request中傳遞會頁面,但是有些情況是redirect的,這樣就導致了request失效。在ROR中,有一個scope是夸兩個request的,不知道那個是怎么實現的。
現在用session來代替這個東西,只是顯示完成之后,就立刻清除這個數據。感覺比較挫,只能湊合著用了。
每次新開發一個系統,如果不用現成的東西來做,都要搞很多很多東西,什么東西好像都要自己來,特別是頁面上的東西,感覺挺煩的。寫寫js,改改css,調調table/div。感覺挺無聊的。
總而言之,這樣子都是因為這家公司的it部門太弱了,幾乎沒有一點技術積累,這么多年了,什么東西都沒有留下,就留下了一堆垃圾,讓我改的挺郁悶的?,F在正在用自己的東西重新。有些東西又沒法改,一些現成的組件也不一定能用,不能用的只能自己重新寫一遍,來實現這個功能。
作為一個技術部門,結果什么技術都沒有,感覺挺悲哀的,特別是一個技術部門的老大,結果是個門外漢,被手下人看不起,這個也挺慘的,作老大做成這樣,連死的心都有了,悲劇啊。
作為一個技術部門的主管,可以不做技術,但是不能不懂技術。這樣才能服眾。
在應用中,彈出式窗口選擇數據,這種解決方案是很普遍的。
彈出窗口,有兩種方式,一種是: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不超出返回字段的范圍,就可以正確使用了。
1、動態sql里面 原來的dynamic,現在沒有了,只能用is代替。但是if里面的判斷 沒有isEmpty這種方便的標簽,需要判斷需要同時判斷 null 和 ""。這個比較麻煩,希望能在正式版本中加上。
2、annotion方式的評價,個人感覺沒有什么意義。從我來講,用iBATIS的主要原因是因為要處理比較復雜的sql,所以通常sql都會很長,就是因為不想通過字符串的方式寫在代碼里,要是寫在代碼里,直接用hibernate的原生sql就好了,何必還要用iBATIS呢。sql寫在xml里的好處是顯而易見的,可以直接將調試好的sql從sql的編輯器中復制過來,這樣可以省掉很多麻煩的事情,放在sql里面很長,又沒有辦法將格式弄好,要是換行什么的就更麻煩。
一個比較有用好的改進就是namespace了,這個功能以前在2.X想用一直沒有用成。有了這個,很多通用的地方可以省略。
ibatis3現在還是beta版,但是已經可以很好的使用了。
主要增強的方面有namespace這個東西,以前2的時候一直以為可以用的,結果沒有效果,害我還郁悶了半天,這樣以后就不會再有命名沖突了。
然后就是annotion的支持,這樣就可以不適用xml文件來保存sql了,但是感覺還是寫在xml里面比較舒服,特別是比較長的sql,個人感覺。
第三個就是動態sql的增強,增加很多有用的標簽??梢宰寗討Bsql使用更加方便。
在看完之后暫時感覺有那么幾個比較好的改變,等正式版出來之后可能還有更多改進。
接著講下abator這個代碼生成工具,感覺還可以,生成的sqlmap配置文件還可以用下,其他的就算了,還是自己手寫吧。
最后提到一下ibatis-3-migrations,這個東西暫時還沒有看明白,好像是數據庫schema的一個管理工具。正在啃guide,看看到底有什么好處,上次看有個人的文章說,就是因為沒有這個東西才沒有用ibatis,所以這個東東應該很強大,我要看下。
|