第一組:劉聰 .NET數據庫連接和參數化查詢
.NET中連接MySql數據庫
引用MySql.Data:.NET框架一般連接數據庫為SQL SERVER 數據庫,如果需要連接Mysql數據庫,則需要添加專用的引用。從官網http://dev.mysql.com/downloads/connector/net/下載最新的MySQL connection/Net組件mysql-connector-net-6.10.5.msi并運行后,在本地C:\Program Files (x86)\MySQL\MySQL Connector Net 6.10.5\Assemblies\v4.5.2路徑下得到MySql.Data.dll(如果沒有也可能在C:\Program Files下)。
-
建立數據庫連接
添加引用后可以使用using MySql.Data.MySqlClient;通過下列代碼實現MySql數據庫連接。
-
數據庫操作
這里只進行簡單的查詢操作:
控制臺輸出:
參數化查詢
- SQL注入問題
上面的查詢操作是通過查詢字符串拼接實現的,模擬用戶輸入。這里存在一個SQL注入的問題:
問題在于password = "111' or '1'='1";最后拼成的sql語句為:
select * from usertable where UserName='congliu' AND Password ='111' or '1'='1'
由于1=1恒為真,所以不管其他的輸入為什么都會返回當前表的所有信息。這是一個簡單的sql注入。
- 參數化查詢
為了解決這個問題,比較好的方法是采用參數化查詢:
參數化查詢是訪問數據庫時,在需要填入數值或數據的地方,使用參數 (Parameter) 來給值。
在使用參數化查詢的情況下,數據庫服務器不會將參數的內容視為SQL指令的一部份來處理,而是在數據庫完成SQL指令的編譯后,才套用參數運行,因此就算參數中含有指令,也不會被數據庫運行。Access、SQL Server、MySQL、SQLite等常用數據庫都支持參數化查詢。
第二組:趙彩鳳 改變超鏈接樣式、AppCan--Switch開關組件
- 改變超鏈接樣式
<style type="text/css">
a:link {color: #FF0000} /* 未訪問的鏈接 */
a:visited {color: #00FF00} /* 已訪問的鏈接 */
a:hover {color: #FF00FF} /* 鼠標移動到鏈接上 */
a:active {color: #0000FF} /* 選定的鏈接 */
</style>
- AppCan--Switch開關組件
(1)對象
appcan.switchBtn(selector, css, callback)
Selector 按鈕的選擇器,例如 .btn、div或#id??赏瑫r處理多個按鈕
css Switch 開啟后的背景CSS類名稱。預置 bc-head。可選參數
callback switch 狀態變更后的回調函數
(2)代碼
HTML:
<div class="switch uba bc-border data-checked="true">
<div class="switch-btn sc-bg-active "></div>
</div>
JS:
appcan.switchBtn(switchBtns,function(obj,value) {
console.log(“switch status:”,value);
})
appcan.updateSwitch(obj);//obj:需要操作的dom對象
E.g.
<div class="switch uba bc-border" data-checked="true">
<div class="switch-btn sc-bg-active "></div>
</div>
appcan.updateSwitch($('.switch'))
第三組:蔡永堅 Asp.Net底層解析-頁面生命周期
頁面生命周期總體理解起來其實很容易,說白了就是在客戶端提出了一個頁面請求之后,服務器端將ASPX頁面源代碼轉化為正確的HTML和JS代碼的整個過程。服務端在轉化的過程中當然不是調用一兩個方法就能解決了的,是經歷被設計好的若干個階段,一步一步完成的,且各個階段的功能很明確彼此是承前啟后的關系。這些階段大體上可以分為:初始化、加載、回發事件處理、呈現、卸載等等。關于這些階段的具體細節本文將在后面說明,現在先來看一個簡單的從整體上反映頁面生命周期的實例(頁面周期每達到一個事件時,就往頁面中寫入一些字符串),新建一個空頁面,并在后臺編寫以下代碼:
[csharp] view plain copy
1. protected void Page_PreInit(object sender, EventArgs e)
2. { //這里設置斷點
3. Response.Write("執行Page_PreInit<br/>");
4. }
5. protected void Page_Init(object sender, EventArgs e)
6. { //這里設置斷點
7. Response.Write("執行Page_Init<br/>");
8. }
9. protected void Page_InitComplete(object sender, EventArgs e)
10. { //這里設置斷點
11. Response.Write("執行Page_InitComplete<br/>");
12. }
13. protected void Page_PreLoad(object sender, EventArgs e)
14. { //這里設置斷點
15. Response.Write("執行Page_PreLoad<br/>");
16. }
17. protected void Page_Load(object sender, EventArgs e)
18. { //這里設置斷點
19. Response.Write("執行Page_Load<br/>");
20. }
21. protected void Page_LoadComplete(object sender, EventArgs e)
22. { //這里設置斷點
23. Response.Write("執行Page_LoadComplete<br/>");
24. }
25. protected void Page_PreRender(object sender, EventArgs e)
26. { //這里設置斷點
27. Response.Write("執行Page_PreRender<br/>");
28. }
29. protected void Page_PreRenderComplete(object sender, EventArgs e)
30. { //這里設置斷點
31. Response.Write("執行Page_PreRenderComplete<br/>");
32. }
33. protected void Page_SaveStateComplete(object sender, EventArgs e)
34. { //這里設置斷點
35. Response.Write("執行Page_SaveStateComplete<br/>");
36. }
37. protected void Page_Unload(object sender, EventArgs e)
38. { //這里設置斷點
39. //這里是頁面卸載階段,不能使用Response.Write方法,一般該事件內執行釋放本頁面控制的系統資源
40. }
如果在每個方法的內部都設置了斷點,那么當運行該頁面后會發現,斷點的觸發是從頂部往底部依次執行的,觸發一個事件之后再觸發下一步事件,有條不紊,最終得到頁面效果如下截圖所示:
上面的示例是每次頁面(無論是首次請求還是PostBack)的請求都要觸發的一系列事件,而當請求為PostBack時,會在Page_Load事件與Page_LoadComplete事件之間觸發引起本次PostBack的控件對應的事件,在上面的示例上進行簡單的修改,前臺頁面添加Bot同控件,代碼如下:
[html] view plain copy
1. <form id="form1" runat="server">
2. <asp:Button ID="aspbtn_TestPostBack" runat="server" Text="點擊提交"
3. onclick="aspbtn_TestPostBack_Click" />
4. </form>
后臺代碼與上面的示例一致,只是添加了Button控件的Click事件對應的方法,添加的方法如下:
[csharp] view plain copy
1. //這里是Button的Click事件
2. protected void aspbtn_TestPostBack_Click(object sender, EventArgs e)
3. {
4. Response.Write("執行Button控件的Click事件<br/>");
5. }
首次運行頁面得到結果與上次示例一致,而當點擊按鈕產生PostBack時,發現在Page_Load事件與Page_LoadComplete事件之間執行了按鈕的事件,即aspbtn_TestPostBack_Click方法。
第四組:張元一 iOS獲取系統電量
EFB項目中,需要實現后臺持續監控電量的功能,這可以拆分為三個需求:
- 程序需要保持在后臺可以運行。
- 程序需要獲取ipad精確電量。
- 需要每隔一段時間掃描一次電量,以獲取當前有效的電量。
上次文章實現了需求一,本文先討論需求二的實現:
獲取ios系統電量,有幾種方法:
方法一:
通過蘋果官方文檔里面UIDevice public API來獲取,代碼如下:
[UIDevice currentDevice].batteryMonitoringEnabled = YES;
[[NSNotificationCenter defaultCenter]
addObserverForName:UIDeviceBatteryLevelDidChangeNotification
object:nil queue:[NSOperationQueue mainQueue]
usingBlock:^(NSNotification *notification) {
self.myVC.batteryLevellb.text = [NSString stringWithFormat:@"CurrentBatteryLevel:%.f%%",[UIDevice currentDevice].batteryLevel*100];
}];
方法獲取的電量是1%精度的,可以滿足要求。
方法二:通過runtime 獲取StatusBar上電池電量控件類私有變量的值,此方法可精準獲取iOS6以上電池電量
- (int)getCurrentBatteryLevel
{
UIApplication *app = [UIApplication sharedApplication];
if (app.applicationState == UIApplicationStateActive||app.applicationState==UIApplicationStateInactive) {
Ivar ivar= class_getInstanceVariable([app class],"_statusBar");
id status = object_getIvar(app, ivar);
for (id aview in [status subviews]) {
int batteryLevel = 0;
for (id bview in [aview subviews]) {
if ([NSStringFromClass([bview class]) caseInsensitiveCompare:@"UIStatusBarBatteryItemView"] == NSOrderedSame&&[[[UIDevice currentDevice] systemVersion] floatValue] >=6.0)
{
Ivar ivar= class_getInstanceVariable([bview class],"_capacity");
if(ivar)
{
batteryLevel = ((int (*)(id, Ivar))object_getIvar)(bview, ivar);
//這種方式也可以
/*ptrdiff_t offset = ivar_getOffset(ivar);
unsigned char *stuffBytes = (unsigned char *)(__bridge void *)bview;
batteryLevel = * ((int *)(stuffBytes + offset));*/
NSLog(@"電池電量:%d",batteryLevel);
if (batteryLevel > 0 && batteryLevel <= 100) {
return batteryLevel;
} else {
return 0;
}
}
}
}
}
}
return 0;
}
經測試,此方法獲取電量精度為5%,且在程序退出到后臺后,此方法不能獲取到電量,不能滿足要求。
方法三:
通過IOKit framework來獲取
IOKit framework在IOS中用來跟硬件或內核服務通信,常用于獲取硬件詳細信息。
首先,需要將IOPowerSources.h,IOPSKeys.h,IOKit三個文件導入到工程中。然后即可通過如下代碼獲取1%精確度的電量信息:
-(double) getBatteryLevel{
// returns a blob of power source information in an opaque CFTypeRef
CFTypeRef blob = IOPSCopyPowerSourcesInfo();
// returns a CFArray of power source handles, each of type CFTypeRef
CFArrayRef sources = IOPSCopyPowerSourcesList(blob);
CFDictionaryRef pSource = NULL;
const void *psValue;
// returns the number of values currently in an array
int numOfSources = CFArrayGetCount(sources);
// error in CFArrayGetCount
if (numOfSources == 0) {
NSLog(@"Error in CFArrayGetCount");
return -1.0f;
}
// calculating the remaining energy
for (int i=0; i<numOfSources; i++) {
// returns a CFDictionary with readable information about the specific power source
pSource = IOPSGetPowerSourceDescription(blob, CFArrayGetValueAtIndex(sources, i));
if (!pSource) {
NSLog(@"Error in IOPSGetPowerSourceDescription");
return -1.0f;
}
psValue = (CFStringRef) CFDictionaryGetValue(pSource, CFSTR(kIOPSNameKey));
int curCapacity = 0;
int maxCapacity = 0;
double percentage;
psValue = CFDictionaryGetValue(pSource, CFSTR(kIOPSCurrentCapacityKey));
CFNumberGetValue((CFNumberRef)psValue, kCFNumberSInt32Type, &curCapacity);
psValue = CFDictionaryGetValue(pSource, CFSTR(kIOPSMaxCapacityKey));
CFNumberGetValue((CFNumberRef)psValue, kCFNumberSInt32Type, &maxCapacity);
percentage = ((double) curCapacity / (double) maxCapacity * 100.0f);
NSLog(@"curCapacity : %d / maxCapacity: %d , percentage: %.1f ", curCapacity, maxCapacity, percentage);
return percentage;
}
return -1.0f;
}
相比方法一,此方法麻煩很多,不過現在的EFB使用的是這種方式。
本項目demo的GitHub地址:
https://github.com/Frued/BatteryLevel
第五組:陳孚楠 javascript使用的兩項原則
兩項原則之平穩退化和漸進增強
平穩退化
如果正確地使用了JavaScript腳本,就可以讓訪問者在他們瀏覽器不支持javascript的情況下仍能順利地瀏覽你的網站。
即當客戶禁止javascript功能后,仍能看到網頁的內容。漸進增強
即用一些額外的信息層去包裹原始數據。若按照“漸進增強”原則創建的網頁幾乎都能符合“平穩退化”原則。
例如:先只使用常規的鏈接,然后通過JavaScript去攔截默認動作。同理:先構建常規網站,然后再Hijax它
大概可以說:
“平穩退化”是在瀏覽器沒有JavaScript功能,或沒有開啟JavaScript功能情況下,我們解決這種問題的方式;
“漸進增強”是在瀏覽器開啟JavaScript功能后,如果瀏覽器版本不支持某些JavaScript能力,我們解決這種問題的方式。