asp.net core快速入門之實戰篇
no1 留言板(mysql的使用)
演示:http://haojima.net
這個功能很簡單。就是對數據庫的寫入和展示。如果在windows下,相信大家分分鐘都可以搞定。而初次接觸.net core + mysql可能需要注意些細節。
首先打開vs2017新建一個asp.net core項目(選web應用程序),然后nuget 導入microsoft.entityframeworkcore.tools 1.1.1和mysql.data.entityframeworkcore 8.0.8-dmr。
然后新建一個dbcontext類。
public class datacontext : dbcontext { //【注意】連接字符串一定要加 sslmode=none string str = @"data source=;database=;user id=;password=;pooling=true;charset=utf8;port=3306;sslmode=none"; protected override void onconfiguring(dbcontextoptionsbuilder optionsbuilder) => optionsbuilder.usemysql(str); //下面就可以添加要加入數據庫的實體了 //public dbset<message> messages { get; set; } }
到此為止,我們已經可以利用ef core直接連接mysql進行增刪改查操作了。注意:需要導入命名空間using microsoft.entityframeworkcore; using mysql.data.entityframeworkcore.extensions;
當然。你會說,連接字符串不能硬編碼到代碼里面。我們也可以放配置文件。appsettings.json
{ "logging": { "includescopes": false, "loglevel": { "default": "warning" } }, "connectionstrings": { "sqlserverconnection": "data source=;database=;user id=;password=;pooling=true;charset=utf8;port=3306;sslmode=none" } }
然后把上面的硬編碼注釋掉。在startup.cs文件的configureservices方法添加
var connection = configuration.getconnectionstring("sqlserverconnection"); services.adddbcontext<datacontext>(options => options.usemysql(connection));
【注意】項目名稱和路徑最好不要有中文,不然會出現些亂七八糟的問題。
【完整代碼】:https://github.com/zhaopeiym/blogdemocode/tree/master/messageboard
no2 聊天室(websocket的使用)
演示:http://socket.haojima.net
websocket是html5新增的一個很酷的技術。下面我們簡單講解下這個很酷的技術
var socket = new websocket(url);//創建 websocket 對象
創建了一個websocket對象后會觸發打開連接事件:
socket.onopen = function(){ }
除了onopen事件,還有其他三個事件:
socket.onmessage //客戶端接收服務端數據時觸發 socket.onerror //通信發生錯誤時觸發 socket.onclose //連接關閉時觸發
另外還有兩個方法:
socket.send() //使用連接發送數據 socket.close() //關閉連接
最后還有四個連接狀態屬性:
socket.readystate 0 - 表示連接尚未建立。 1 - 表示連接已建立,可以進行通信。 2 - 表示連接正在進行關閉。 3 - 表示連接已經關閉或者連接不能打開。
整個websocket常用功能知識點就四個事件、兩個方法、四種狀態。簡單吧,下面我們看看asp.net core后臺的配合:
后臺添加一個sockethandler類,并添加一個靜態方法map:
/// <summary> /// 請求 /// </summary> /// <param name="app"></param> public static void map(iapplicationbuilder app) { app.usewebsockets(); //【注意】需要 nuget 導入 microsoft.aspnetcore.websockets.server app.use(acceptor); }
然后新增對應的acceptor方法:
/// <summary> /// 接收請求 /// </summary> /// <param name="httpcontext"></param> /// <param name="n"></param> /// <returns></returns> static async task acceptor(httpcontext httpcontext, func<task> n) {
需要在startup.cs類里面的configure方法里面加入
app.map("/ws", sockethandler.map); //傳入我們剛才新建的靜態方法map
現在為止,基本的類和配置已經完成。
我們主要操作,是在acceptor方法里面接收和發送消息。
//建立連接 var socket = await httpcontext.websockets.acceptwebsocketasync(); //等待接收數據 await socket.receiveasync(new arraysegment<byte>(buffer), cancellationtoken.none); //發送消息 await socket.sendasync(arraysegment, websocketmessagetype.text, true, cancellationtoken.none);
后臺關鍵代碼也就這三句,建立連接、等待接收、發送消息。
不過這里有一點需要理解。建立連接后,可以接收任意多次客戶端消息。所以receiveasync等待接收這里需要死循環接收消息,直到連接斷開。(不用擔心真的死循環,沒有消息發送的時候,代碼會阻塞在那里等待消息)
【完整實現】:https://github.com/zhaopeiym/chatroom
no3 找工作(anglesharp的使用)
演示:http://job.haojima.net
對于爬蟲抓包,我相信大家初次接觸都非常的熱衷于此。我也不例外。
那么在asp.net core下面是否也有這樣的插件呢?答案是肯定的。
http://www.cnblogs.com/linezero/p/5599611.html htmlagilitypack html解析(感謝博主對.net core的貢獻)。不過xpath用起來超級惡心。
之前在.net下面有一款jumony http://www.cnblogs.com/ivony/p/3447536.html(博客園大牛寫的)。支持css選擇和linq查詢。簡直不要太爽??墒遣恢С?net core。(本人試了下遷移.net core,發現很多類在.net core沒有實現)
最后還是到了一款支持.net core的解析組件。并可以媲美jumony,同樣支持css選擇和linq查詢。那就是anglesharp。
新建項目,nuget 安裝 anglesharp。然后以下簡單使用:
using (httpclient http = new httpclient()) { var htmlstring = await http.getstringasync(url); htmlparser htmlparser = new htmlparser(); var jobinfos = htmlparser.parse(htmlstring) .queryselectorall(".newlist_list_content table") .where(t => t.queryselectorall(".zwmc a").firstordefault() != null) .select(t => new jobinfo() { positionname = t.queryselectorall(".zwmc a").firstordefault().textcontent, corporatename = t.queryselectorall(".gsmc a").firstordefault().textcontent, salary = t.queryselectorall(".zwyx").firstordefault().textcontent, workingplace = t.queryselectorall(".gzdd").firstordefault().textcontent, .tolist(); return jobinfos; }
看到沒有,就像jq一樣解析html。如果你說不爽我都不信。
【完整實現】:https://github.com/zhaopeiym/jobwanted
部署多個站點
以上,這些項目都比較簡單。關鍵技術點和難點都進行的分析。我相信大家都可以動起手練習起來了。
不過有個問題,前面我們只說了部署一個應用程序。如果是多個該怎么部署呢?
首先我們把多個程序發布包放到服務器上。
然后修改nginx的配置文件/etc/nginx/conf.d/default.conf
server { listen 80; server_name www.haojima.net; #對應的域名 root /home/projects/messagboard; #程序路徑 location / { proxy_pass http://localhost:5000; #內網端口 proxy_http_version 1.1; proxy_set_header upgrade $http_upgrade; proxy_set_header connection keep-alive; proxy_set_header host $host; proxy_cache_bypass $http_upgrade; proxy_set_header x-real-ip $remote_addr; proxy_set_header upgrade $http_upgrade; } }
有幾個程序就添加幾個server,不過需要修改你解析到的域名、程序路徑和內網對應的端口(看配置里的注釋) 。
然后修改supervisor的配置文件/etc/supervisor/conf.d/supervisord.conf
[program:messageboard] command=dotnet messageboard.dll ; 運行程序的命令 directory= /home/projects/messagboard/ ; 命令執行的目錄 autorestart=true ; 程序意外退出是否自動重啟 stderr_logfile=/var/log/webapplication1.err.log ; 錯誤日志文件 stdout_logfile=/var/log/webapplication1.out.log ; 輸出日志文件 environment=aspnetcore_environment=production ; 進程環境變量 user=root ; 進程執行的用戶身份 stopsignal=int
有幾個程序就往下復制幾份program。需要修改program名稱,只要名稱不重復就可以。然后修改 運行程序的命令 對應的dll和命令執行的目錄(看配置文件的注釋)。
如此就可以部署多個程序了。
開始我還以為是在域名解析的時候,解析ip + 端口。原來是多個域名解析到同一個ip,然后nginx在內部做域名和內網端口分發。
一些其它的細節
部署阿里云
我們在linux的防火墻開放了端口,發現在外面還是訪問不了(可以telnet ip 端口 來測試)。有可能是阿里云攔截了。https://help.aliyun.com/document_detail/25471.html 在安全組添加某端口哪些ip可以訪問。
mysql的客戶端
對于mysql,我們安裝好之后總不能每次命令操作吧。在windows下面有個客戶端navicat可以方便管理mysql。navicat
獲取ip
用了nginx后發現取不到瀏覽器ip了。那是因為我們程序都是瀏覽器訪問nginx,然后nginx轉發內網程序端口。所以取到的ip都是內網本機ip。如果需要取瀏覽器ip需要在nginx配置
server { listen 80; server_name www.haojima.net; root /home/projects/messagboard; location / { proxy_pass http://localhost:5000; proxy_http_version 1.1; proxy_set_header upgrade $http_upgrade; proxy_set_header connection keep-alive; proxy_set_header host $host; proxy_cache_bypass $http_upgrade; proxy_set_header x-real-ip $remote_addr; # 新添加 } }
然后代碼里面取ip:
var ip = httpcontext.request.headers["x-real-ip"].firstordefault();
websocket在nginx的配置
上面我們寫的websocket直接運行發現沒有任何問題,可是部署在nginx去跑不起來了。那是因為需要nginx支持websocket,需要配置。http://nginx.org/en/docs/http/websocket.html
server { listen 80; server_name job.haojima.net; root /home/projects/jobwanted; location / { proxy_pass http://localhost:5002; proxy_http_version 1.1; proxy_set_header upgrade $http_upgrade; proxy_set_header connection keep-alive; proxy_set_header host $host; proxy_cache_bypass $http_upgrade; proxy_set_header x-real-ip $remote_addr; proxy_set_header upgrade $http_upgrade; # 新增 #proxy_set_header connection "upgrade"; # 新增 proxy_set_header connection $http_connection; #ws和post同時使用 https://github.com/aspnet/kestrelhttpserver/issues/1263 } }
websocket心跳
經過上面的配置,我們的websocket在nginx上跑起來了。萬分歡喜的我們,發現一分鐘不發消息就自動掉線了。郁悶至極到頭大。細心的同學通過上面的鏈接資料其實已經有說明:
by default, the connection will be closed if the proxied server does not transmit any data within 60 seconds. this timeout can be increased with the proxy_read_timeout directive. alternatively, the proxied server can be configured to periodically send websocket ping frames to reset the timeout and check if the connection is still alive.
nginx給出了兩種解決方案。第一種,修改proxy_read_timeout (默認60秒)。第二種,瀏覽器客戶端定時發送心跳包(時間要短于proxy_read_timeout)。
我使用的是第二種方式。
第一種雖然簡單粗暴,但是時間再長也是一個值,還是會有超時的可能。再者,誰能保證瀏覽器端不會new 很多個websocket出來搗蛋。
第二種方式,瀏覽器定時發送一條消息,內容和后臺約定下。如發送“心跳”,然后后臺接收消息是,判斷如果是“心跳”則不做任何處理。
中文編碼
在做“找工作”爬前程無憂的數據時,發現他們使用的gbk編碼。而在.net core中默認不支持這種格式,導致取到的數據都是亂碼。我們需要nuget安裝system.text.encoding.codepages。然后在startup.cs的configure里面注冊:
encoding.registerprovider(codepagesencodingprovider.instance);//注冊編碼提供程序
使用:
var htmlbytes = await http.getbytearrayasync(url); var htmlstring = encoding.getencoding("gbk").getstring(htmlbytes);
asp.net core 端口分配
asp.net core 默認端口都是5000。那么我們運行第二個程序的時候就會提示5000端口被占用。這個時候,我們就需要為每個程序分配不同的端口了。
在根目錄新建一個json文件hosting.json
{ "server.urls": "http://*:5002" }
在program.cs文件修改
public static void main(string[] args) { var config = new configurationbuilder() .setbasepath(directory.getcurrentdirectory()) .addjsonfile("hosting.json", optional: true) .build(); var host = new webhostbuilder() .usekestrel() .useconfiguration(config) .usecontentroot(directory.getcurrentdirectory()) .useiisintegration() .usestartup<startup>() .useapplicationinsights() .build(); host.run(); }
爬拉勾數據
在爬拉勾網的時候沒有搞定,不知道是不是因為https的原因。
using (httpclient http = new httpclient()) { var url = "https://www.lagou.com/zhaopin/java/?labelwords=label"; var htmlstring = await http.getstringasync(url); }
在.net core中報錯:an unhandled exception occurred while processing the request.
在.net 4.5 中抓到的數據是“頁面加載中...”。和瀏覽器訪問的結果不一樣。
170819搞定 https://github.com/zhaopeiym/jobwanted/blob/master/jobwanted/controllers/jobscontroller.cs#l211 //拉勾網 后臺檢測了user-agent、x-requested-with、referer還會檢測list_是否有參數 http.defaultrequestheaders.add("referer", "https://www.lagou.com/jobs/list_.net"); http.defaultrequestheaders.add("user-agent", "mozilla/5.0"); http.defaultrequestheaders.add("x-requested-with", "xmlhttprequest");
演示
http://haojima.net
http://socket.haojima.net
http://job.haojima.net
源碼
https://github.com/zhaopeiym/jobwanted
https://github.com/zhaopeiym/chatroom
https://github.com/zhaopeiym/blogdemocode
以上就是asp.net core快速入門之實戰篇的詳細內容,更多關于asp.net core實戰的資料請關注碩編程其它相關文章!