net core体系-web应用程序-2项目简单案例
阅读目录
- NO1 留言板(mysql的使用)
- NO2 聊天室(WebSocket的使用)
- NO3 找工作(AngleSharp的使用)
- 部署多个站点
- 一些其它的细节
- 部署阿里云
- mysql的客户端
- 获取ip
- WebSocket在nginx的配置
- WebSocket心跳
- 中文编码
- 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.
靠,英文实在太烂了。
默认情况下,如果代理的服务器在60秒内没有传输任何数据,则连接将被关闭。可以使用proxy_read_timeout指令增加此超时 。或者,代理服务器可以配置为定期发送WebSocket ping帧以重置超时并检查连接是否仍然存在。
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 中抓到的数据是“页面加载中...”。和浏览器访问的结果不一样。
原因未知。如果有大佬解惑,感激不尽!
参考
http://www.runoob.com/html/html5-websocket.html
http://www.cnblogs.com/liguobao/p/6130121.html
http://www.cnblogs.com/linezero/p/5806814.html
演示
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
net core体系-web应用程序-2项目简单案例的更多相关文章
- net core体系-web应用程序-3项目结构、配置文件详解
一.应用程序文件结构 如下图所示,相比于Asp.Net项目,在新建的Asp.Net Core项目中,没有了Global.asax以及Web.config这样的文件,但多了几个其他主要的文件,它们分别为 ...
- net core体系-web应用程序-4asp.net core2.0 项目实战(任务管理系统)-2项目搭建
系统要求 首先建议采用 Windows 10 专业版/企业版/教育版,且必须是64位操作系统,原因是docker装起来比较方便,Win7装起来比较麻烦,且不确定是否有其他问题(自己没有实践过) 其次W ...
- net core体系-web应用程序-4net core2.0大白话带你入门-2asp.net core新建项目
新建asp.net core项目 开发环境:Windows Server R2 2008 开发工具:Microsoft Visual Studio 2017 新建asp.net core项目 创建 ...
- net core体系-web应用程序-4asp.net core2.0 项目实战(CMS)-第二章 入门篇-快速入门ASP.NET Core看这篇就够了
.NET Core实战项目之CMS 第二章 入门篇-快速入门ASP.NET Core看这篇就够了 原文链接:https://www.cnblogs.com/yilezhu/p/9985451.ht ...
- net core体系-web应用程序-1VS2017构建一个简单的web
使用vs2017,添加一个新项目-asp.net core web应用程序. 结构如图, wwwroot放了网站的静态资源如css.js.image文件: appsetting.json是应用程序的配 ...
- net core体系-web应用程序-4asp.net core2.0 项目实战(1)-12基于cookie登录授权认证并实现前台会员、后台管理员同时登录
1.登录的实现 登录功能实现起来有哪些常用的方式,大家首先想到的肯定是cookie或session或cookie+session,当然还有其他模式,今天主要探讨一下在Asp.net core 2.0下 ...
- net core体系-web应用程序-4asp.net core2.0 项目实战(1)-11项目日志解决方案
本文目录1. Net下日志记录2. NLog的使用 2.1 添加nuget引用NLog.Web.AspNetCore 2.2 配置文件设置 2.3 依赖配置及调用 2.4 日志 ...
- net core体系-web应用程序-4asp.net core2.0 项目实战(1)-2项目说明和源码下载
本文目录1. 摘要2. Window下运行 3.linux下运行4. 开发记录5. 总结 1.概要 写<Asp.Net Core 2.0 项目实战>系列断断续续已经很长时间了,期间很多朋友 ...
- net core体系-web应用程序-4net core2.0大白话带你入门-4asp.net core配置项目访问地址
asp.net core配置访问地址 .net core web程序,默认使用kestrel作为web服务器. 配置Kestrel Urls有四种方式,我这里只介绍一种.其它方式可自行百度. 在Pr ...
随机推荐
- mysql的csv数据导入与导出
# 需要station_realtime存在 load data infile 'd:/xxxx/station_realtime2013_01.csv' into table `station_re ...
- Linux Free命令每个数字的含义 和 cache 、buffer的区别
Linux Free命令每个数字的含义 和 cache .buffer的区别 我们按照图中来一细细研读(数字编号和图对应)1,total:物理内存实际总量2,used:这块千万注意,这里可不是实际已经 ...
- [转]Navicat Premium 12试用期的破解方法
link: https://blog.csdn.net/Jason_Julie/article/details/82864187 ref: https://www.jianshu.com/p/42a3 ...
- Java数据结构与算法解析(十二)——散列表
散列表概述 散列表就是一种以 键-值(key-indexed) 存储数据的结构,我们只要输入待查找的值即key,即可查找到其对应的值. 散列表的思路很简单,如果所有的键都是整数,那么就可以使用一个简单 ...
- mysql-约束介绍
一.约束介绍 约束是一种限制,它通过对表的行或列的数据做出限制,来确保数据的完整性.一致性.约束条件与数据类型宽度一样都是可选参数. 常用约束: PRIMARY KEY (PK) 标识该字段为该表的主 ...
- Python装饰器执行顺序详解
探究多个装饰器执行顺序 装饰器是Python用于封装函数或代码的工具,网上可以搜到很多文章可以学习,我在这里要讨论的是多个装饰器执行顺序的一个迷思. 疑问 大部分涉及多个装饰器装饰的函数调用顺序时都会 ...
- liunx 安装jdk1.8
采用解压压缩文件形式安装 第一步:将jdk压缩文件上传至home目录下面 第二步:目录切换至/usr目录下 cd /usr 创建java目录 mkdir java 第三步:将jdk 压缩文 ...
- headless&unittest
为什么要使用 headless 测试? headless broswer 可以给测试带来显著好处: 对于 UI 自动化测试,少了真实浏览器加载 css,js 以及渲染页面的工作.无头测试要比真实浏览器 ...
- swift 实践- 09 -- UIImageVIew
import UIKit class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoa ...
- Confluence 6 管理协同编辑 - 修改你的 Synchrony 配置
你不能通过 Confluence UI 修改 Synchrony 的配置.配置的修改是通过系统属性进行修改的.在绝大部分情况下,你不需要对默认的配置进行修改. 修改 Synchrony 运行的端口. ...