2012年5月15日
工作中會帶一些實習生或新人,大多缺乏經驗,項目調試是他們很頭疼的問題,代碼出了問題往往就束手無策了,很影響工作效率。其實代碼調試是有步驟可循的,代碼出了問題要做的第一件事情是定位問題,只有知道問題出在哪才能解決。
一個Java Web項目通常是由前端和后端組成的,請求是由前端發送給后臺代碼處理的,所以我們要做的第一件事情就是確定問題出在前端還是后端,先要保證前端發送給后端的請求參數是對的,有些同學在請求參數不對或者請求根本沒有到達后臺的情況下盲目地去檢查后臺代碼是不對的。
前臺請求通常通過form、超鏈接或ajax等方法提交給后臺,我們必須確定提交的鏈接是對的,然后是參數,提交的參數我們可以通過瀏覽器地址或者一些瀏覽器調試工具(例如火狐的firebug)得到。
如果請求鏈接是對的、參數也是對的,那就是后臺的問題了,后臺問題通常通過eclipse的debug工作調試,但有一種情況,就是開發中會運用一些mvc框架,例如struts2、spring
mvc等,我們在后臺某個地方加斷點根本就沒反應,這時候有個很簡單的方法,把斷點加到control層的代碼入口處,如果還沒反應,那就是框架配置問題了,要檢查配置對不對。
對象,你可以理解成一種具有屬性和行為的實體,它可向外部提供服務。而使用這個對象,可忽略其內部的細節,只需要知道使用這種服務時的“投入”、“產出”即可,因此,“高內聚、低耦合”是面向對象編程的基本思想。
略舉一例,平時我們工作中要刪除某條數據,一般不是真的delete掉,而是用一個status標識,status為-1表示刪除,你寫刪除接口時完全可以這么寫:
Class UserService{
private UserDao userDao;
public void deleteUser(User user){
user.setStatus(-1);
userDao.update(user);
}
}
這個邏輯其實執行的是更新操作,但接口名仍是deleteUser,因為它提供的確實是刪除“服務”,調用接口時我只需要知道我調用這個接口時會刪除對象,至于它怎么實現,我管不著。
Java中到處是指針引用,習慣了使用c語言指針的程序員往往會亂用指針,而破壞了面向對象的思想,比如,我要查詢某個用戶的密碼,有人可能會這么寫:
Class UserService{
private UserDao userDao;
public void queryUserPasswd(int id,User user){
String passwd=userdao.getUserPasswd(id)
User.setPasswd(passwd);
}
}
這種寫法在語法上沒什么問題,也能得到正確的值,但傳個user對象進來就有些不妥了,我要得到密碼,傳個用戶的密碼,只要給個id就可以把密碼返回給調用者了,干嘛要讓人再傳個對象進來?
作為一個項目經理,在工作過程中,確實會遇到令人哭笑不得的接口,就像上面那個刪除接口吧,有人會這么寫:
Class UserService{
public void deleteUser(UserDao userDao ,User user){
user.setStatus(-1);
userDao.update(user);
}
}
這接口寫得,讓人摸不著頭腦了,我刪除一個user對象,還要傳個userDao給你,意思是你為我提供服務,我還要給個工具給你,這說不通吧!
Java是純粹的面向對象語言,寫Java程序時要時刻記住,你在為別人提供服務,為別人提供服務就不應該提出過多的附加要求。這個問題在使用MVC模式分層思想的時候體現得更加嚴重。在使用MVC模式開發的時候,往往將整個項目分成幾層:action層、service層、數據庫處理層(dao層)等等,每一層往往由不同的程序員編寫,這時候要格外提醒自己在為別人提供服務。在一個新項目開始的時候往往會出現一個問題:在增加某條數據時,要對這條數據的字段進行驗證,不能為空或者長度過長等等,如果沒有驗證容易拋錯,在分層編寫接口時,開發人員經常想這個驗證應該在上層或者下層做吧,我這邊得到的數據是正確的,最后導致誰都沒做驗證。只要你記住了提供“服務”的思想,就不應該要求別人給你的數據是正確的,而是應該處理各種非正常問題,保證用戶給你的任何數據你都能給出相應的返回,當然,在實際的項目中項目經理可能規定數據驗證在service層做。
Android Adapter 是將數據綁定到UI 界面上的橋接類。 Adapter負責創建和顯示每個項目的子View和提供對下層數據的訪問。支持Adapter綁定的UI控件必須擴展Adapter View抽象類。創建自己的繼承自AdapterView的控件和創建新的Adapter類來綁定它們是可能的。
Android 系統本身提供了兩種現成的Adapter 供我們使用。
1.ArrayAdapter:它是一個綁定View到一組對象的通用類。默認情況下,ArrayAdapter綁定每個對象的toString值到layout中預先定義的TextView空間上。構造函數允許用戶使用更加復雜的Layout或者通過重寫getView方法來擴展類從而使用TextView的替代物
2.SimpleCursorAdapter:它綁定View到Content Provider 查詢返回的游標上。指定一個XML layout定義,然后將數據集的每一列的值綁定到layout中的一個View
寫自己的Adapter類實現更多復雜的UI界面和數據綁定
public class MyAdapter extends SimpleAdapter {
private LayoutInflater mInflater;
private Context context;
private List<Map<String,Object>> list;
private int resource;
private String[] tags;
private int[] ids;
public MyAdapter(Context context, List<Map<String,Object>> items, int resource,
String[] tags,int[] ids) {
super(context, items, resource, tags, ids);
this.mInflater = LayoutInflater.from(context);
this.context = context;
this.list = items;
this.resource = resource;
this.tags = tags;
this.ids = ids;
}
public int getCount() {
return list.size();
}
public Object getItem(int position) {
return list.get(position);
}
public long getItemId(int position) {
return position;
}
public View getView(final int position, View convertView, ViewGroup parent) {
convertView = super.getView(position, convertView, parent);
if (convertView == null) {
Toast.makeText(context, "this is null", 2000).show();
} else {
}
ImageView more = (ImageView) convertView.findViewById(R.id.iv_more);
more.setOnClickListener(new View.OnClickListener() {
public void onClick(View arg0) {
Intent intent = new Intent(context, VehicleInfoActivity.class);
intent.putExtra("vehicleID", VehicleListActivity.idList.get(position));
intent.putExtra("CameraID", "0");
Toast.makeText(context, "sssssss", 2000).show();
context.startActivity(intent);
}
});
return convertView;
}
}
主要重載getCount 方法,getView方法 getItem方法 getItemId方法; 參數解析:context:傳入的上下文Activity, items 綁定數據的列表, resource layout布局ID, tags 綁定數據的key, ids Item 中對應key的資源ID。 在getView中自定義Item里面的事件監聽,自定義新的重載后的顯示界面返回 convertView。 如果需要使用到父類SimpleAdapter 顯示效果需要調用super.getView方法為 convertView 賦值。
在java中"=="是用來比較兩者儲存值的地址是否相同,比如A==B,就是比較A和B所儲存值的地址是否相同。
再來看看equals()的使用
在java中有這兩種情況存在:
1、使用object類中的equals()方法,這個是java中最初的equals()方法
如果你自定義一個類A,并且沒有去繼承其他的類,這時A中的equals()
的功能就是比較兩者儲存值的地址是否相同。因為所有的類都繼承object
類,而object類中有equals()這樣的方法
object類中的equals()方法的源代碼如下:
public boolean equals(object obj)
{
return this == obj;
}
從這段代碼中,我們可以再次確定,這種情況下的equals()方法的功能是
比較兩者儲存值的地址。
2、自定義一個類B,但B類繼承了c類,而c類中的equals()方法已經被重寫過
了,這種情形就需要具體情況具體分析了,但大部分被重寫的equals()方
法所擁有的功能就是比較兩者儲存值的內容是否相同,而不再是比較地址
了。比如:創建一個String對象 String str1 = new String("1");
String str2 = new String("1");
這時str1.equals(str2)比較的就是str1和str2中儲存值的內容是否相同
了,因為String類中的equals()就被重寫了,但這并不意味著所有被重寫
過的equals()方法都是用來比較內容的(因為目前我所遇到的只有這種情
況,如果大家有興趣可以去多研究研究
總結:"=="就只有一種用法,而equals()有兩種用法,只是所使用的環境不一樣而已。
WARN com.opensymphony.xwork2.ognl.OgnlValueStack:60 - Error setting expression 'ssc.x' with value '[Ljava.lang.String;@28d320d6'
ognl.OgnlException: target is null for setProperty(null, "x", [Ljava.lang.String;@28d320d6)
ognl.OgnlException: target is null for setProperty(null, "y", [Ljava.lang.String;@32a88bc2)
的解決辦法
Struts2
這個異常是在提交表單的時候發生的,乍一看以為是Struts2類型轉換的錯誤,但是程序中又壓根兒沒有用到Struts2的類型轉換,而且前臺頁面
index.jsp中也沒有設置x,y這些參數;且這個錯誤并不會影響程序的正常運行,找了很久,最后發現是提交按鈕的緣故,提交按鈕引用的是一個圖片,
如下:
<input id="submit" type="image" name="ssc" src="asserts/images/5.jpg"/>
由于表單提交中設置了name屬性,所以struts2會進行接收相應的值,查找它的set 和 get方法,而action里面沒有這個name值的,所以才出現了如上錯誤。可以這樣寫:
<input id="submit" type="image" src="asserts/images/5.jpg" />
將name屬性去掉即可。
其實,在struts.xml文件里可以配置"struts.devMode"屬性。
當
struts.devMode = true時,使用struts在默認配置下對任何提交到action的參數強制需要setter方法,html表單數
據中有和action屬性匹配不上的參數名時就會提示這樣的信息。所以,在開發過程中將這個屬性設為true還是很好的,它可以幫我們發現一些可能出現但
又被我們忽視的問題,犯的“錯誤”越多,才能積累很多的經驗。
轉自百度空間:
http://hi.baidu.com/gpsdreamer/item/544050ed0e00e4d0e1a5d4cd
1. 首先看Spring中beans的配置:
1) <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"destroy-method="close">
第一個bean作為配置連接數據庫,設置DriverManager以及用戶名密碼
2) <bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
第二個bean就是選擇SqlMapClient,并且填寫該xml的路徑:
XmlSqlMapClientBuilder xmlBuilder =new XmlSqlMapClientBuilder();
SqlMapClient sqlMap = xmlBuilder.buildSqlMap(reader);
3) <bean id="sqlMapClientTemplate" class="org.springframework.orm.ibatis.SqlMapClientTemplate">
<property name="sqlMapClient">
<ref bean="sqlMapClient" />
</property>
</bean>
第三個bean,SqlMapClientTemplate是SqlMapClient的封裝類.
SqlMapClient中包含著session的管理.
SqlMapClientTemplate用于session的封裝,以及異常的捕捉.
所以按照以上的推斷來說.應該盡量使用SqlMapClientTemplate.
保證session以及Exception的正常以及統一.
2. 然后就是SqlMapClient的配置:
<sqlMap resource="sql/gpsData_sqlmap_mapping.xml"/>
配置gpsData類與數據庫的對應關系
3. 這兩個xml文件配置好以后就可以在自己的DAO類中寫相應的增刪改查方法了。
public class IbatisGpsDataDao extends BaseDao implements GpsDataDao{
…
}
該類集成了BaseDao類,BaseDao提供了SqlMapClientTemplate的對象操作,該對象正是在Spring beans中配置的。通過獲得這個SqlMapClientTemplate,進行增刪改查的操作。
例如下面的insert方法:
public long insertGpsDataDo(GpsDataDo gpsdata) {
if(gpsdata == null){
throw new IllegalArgumentException();
}
return (Long) getSqlMapClientTemplate().insert("GpsData.insertGpsData",gpsdata);
}