传送阵:写在最后

一、创建一个能跑的起来的Web API项目

1、建一个空的 ASP.NET Web应用

(为什么不直接添加一个Web API项目呢,那样会有些多余的内容(如js、css、Areas等),项目首先就需要清理一次。这样一步步来也更易于理解API项目)

2、用NuGet引入Web API

这时我的packages

<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.AspNet.Cors" version="5.2.3" targetFramework="net45" />
<package id="Microsoft.AspNet.WebApi" version="5.2.3" targetFramework="net45" />
<package id="Microsoft.AspNet.WebApi.Client" version="5.2.3" targetFramework="net45" />
<package id="Microsoft.AspNet.WebApi.Core" version="5.2.3" targetFramework="net45" />
<package id="Microsoft.AspNet.WebApi.Cors" version="5.2.3" targetFramework="net45" />
<package id="Microsoft.AspNet.WebApi.WebHost" version="5.2.3" targetFramework="net45" />
<package id="Newtonsoft.Json" version="6.0.8" targetFramework="net45" />
</packages>

3、App_Start下创建一个WebApiConfig.cs类,作为api启动配置类

  代码如下

using System.Web.Http;
using System.Web.Http.Cors; namespace Frozen.API
{
public class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
//启用跨域
var cors = new EnableCorsAttribute("*", "*", "*");
config.EnableCors(cors); // Web API routes
config.MapHttpAttributeRoutes(); config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
}

4、添加“全局应用程序类” Global.asax

  Application_Start方法如下

        protected void Application_Start(object sender, EventArgs e)
{
GlobalConfiguration.Configure(WebApiConfig.Register);
}

5、添加一个Web API控制器类,比如”StudentController“

  初始代码如下(常用的还有个Patch方法)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http; namespace Frozen.API.Controllers
{
public class StudentController : ApiController
{
// GET api/<controller>
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
} // GET api/<controller>/5
public string Get(int id)
{
return "value";
} // POST api/<controller>
public void Post([FromBody]string value)
{
} // PUT api/<controller>/5
public void Put(int id, [FromBody]string value)
{
} // DELETE api/<controller>/5
public void Delete(int id)
{
}
}
}

6、绑定下测试域名

  还得在hosts做下指向

  

7、感觉可以跑起来了。启动程序,直接报了500,错误提示是”由于权限不足而无法读取配置文件“

  权限问题,解决方案文件夹,右键属性,安全选项卡,添加‘Everyone’,将‘修改’权限打开,解决问题

8、提前在‘public string Get(int id)’处加好断点,在浏览器输入‘http://api.frozen.com/api/student/1’

  命中断点,说明这已经是一个可以跑起来的API项目了

二、搭建框架

1、按ABP,被我搭建成了这样。这张图后续会根据项目实际情况,或个人现阶段的理论误区,持续更新

  (其实还应该有张架构图,但由于线条交错,看起来效果不怎么样,所以没贴出来)

  

2、注册Autofac

从NuGet安装Autofac,关键代码如下:

        public static void SetAutofacContainer()
{
var builder = new ContainerBuilder();
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
builder.RegisterType<InMemoryCache>().As<ICache>().InstancePerLifetimeScope();
builder.RegisterAssemblyTypes(typeof(StuEducationRepo).Assembly)
.Where(t => t.Name.EndsWith("Repo"))
.AsImplementedInterfaces().InstancePerLifetimeScope();
builder.RegisterAssemblyTypes(typeof(StudentRegisterDmnService).Assembly)
.Where(t => t.Name.EndsWith("DmnService"))
.AsImplementedInterfaces().InstancePerLifetimeScope();
builder.RegisterAssemblyTypes(typeof(StuEducationAppService).Assembly)
.Where(t => t.Name.EndsWith("AppService"))
.AsImplementedInterfaces().InstancePerLifetimeScope(); builder.RegisterWebApiFilterProvider(GlobalConfiguration.Configuration);
IContainer container = builder.Build();
var resolver = new AutofacWebApiDependencyResolver(container); // Configure Web API with the dependency resolver.
GlobalConfiguration.Configuration.DependencyResolver = resolver;
}

3、注册AutoMapper

从NuGet安装AutoMapper,关键代码如下:

     Mapper.Initialize(x =>
{
x.AddProfile<DomainToDtoProfile>();
x.AddProfile<DtoToDomainProfile>();
});
    public class DomainToDtoProfile : Profile
{
public override string ProfileName
{
get { return "DomainToDtoMappings"; }
} protected override void Configure()
{
Mapper.CreateMap<TB_Stu_Education, StuEducationDto>()
.ForMember(dest => dest.DegreeName, opt => opt.ResolveUsing<DegreeNameResolver>().FromMember(s => s.DegreeId))
; } }

4、注册log4net

从NuGet安装log4net,关键代码如下,添加配置文件“\Config\log4net.config”

            log4net.Config.XmlConfigurator.Configure(
new System.IO.FileInfo(AppDomain.CurrentDomain.BaseDirectory + "\\Config\\log4net.config")
);
    public class Log4NetLogger : ILogger
{
private static readonly ILog loginfo;
private static readonly ILog logerror;
private static readonly ILog logmonitor; static Log4NetLogger()
{
//不同类型的日志 存放在 不同 的 目录中
loginfo = LogManager.GetLogger("loginfo");
logerror = LogManager.GetLogger("logerror");
logmonitor = LogManager.GetLogger("logmonitor");
} public void Info(string message)
{
if (loginfo.IsInfoEnabled)
loginfo.Info(message);
} public void InfoFormat(string format, params object[] args)
{
if (loginfo.IsInfoEnabled)
loginfo.InfoFormat(format, args);
} public void Warn(string message)
{
if (loginfo.IsWarnEnabled)
loginfo.Warn(message);
} public void Error(string message, Exception ex = null)
{
if (logerror.IsErrorEnabled)
{
if (ex != null)
{
logerror.Error(message, ex);
}
else
{
logerror.Error(message);
}
}
} public void Monitor(string message)
{
if (logmonitor.IsInfoEnabled)
logmonitor.Info(message);
}
}

三、调试API接口(Fiddler)

1、GET 获取

http://api.frozen.com/api/StuEducation/1

返回:{"DegreeName":"本科","Id":1,"StuId":1,"DegreeId":2,"SchoolName":"安大","MajorName":"计算机科学与技术","StartDate":"2008-09-01 00:00:00","EndDate":"2012-06-01 00:00:00","CreateTime":"2015-01-01 00:00:00","LastModifyTime":null}

代码:

        public StuEducationDto Get(int id)
{
var dto = _stuEducationAppService.GetDTOById(id);
return dto;
}

2、POST 新增

返回

HTTP/1.1 201 Created

代码:

        public HttpResponseMessage Post([FromBody]StuEducationDto dto)
{
int result = _stuEducationAppService.CreateByDTO(dto);
return result > ? Request.CreateResponse(HttpStatusCode.Created) : Request.CreateResponse(HttpStatusCode.InternalServerError);
}

3、PUT 新增/修改

代码:

        public HttpResponseMessage Put(int id, [FromBody]StuEducationDto dto)
{
var result = _stuEducationAppService.CreateOrUpdateByDTO(id, dto);
return result > ? Request.CreateResponse(HttpStatusCode.OK) : Request.CreateResponse(HttpStatusCode.InternalServerError);
}

4、Patch 局部更新

代码(使用了dynamic参数):

        public HttpResponseMessage Patch(int id, dynamic dtoUpdate)
{
var dto = _stuEducationAppService.GetDTOById(id);
if (dto == null)
{
return Request.CreateResponse(HttpStatusCode.PaymentRequired);
}
foreach (JProperty prop in dtoUpdate)
{
switch (prop.Name.ToLower())
{
case "degreeid":
dto.DegreeId = prop.Value.ToObject<int>();
break;
case "schoolname":
dto.SchoolName = prop.Value.ToObject<string>();
break;
case "majormame":
dto.SchoolName = prop.Value.ToObject<string>();
break;
case "startdate":
dto.StartDate = prop.Value.ToObject<DateTime>();
break;
case "enddate":
dto.EndDate = prop.Value.ToObject<DateTime>();
break;
default:
break;
}
}
var result = _stuEducationAppService.UpdateByDTO(id, dto);
return result > ? Request.CreateResponse(HttpStatusCode.OK) : Request.CreateResponse(HttpStatusCode.NotFound);
}

5、Delete 删

代码:

        public HttpResponseMessage Delete(int id)
{
var result = _stuEducationAppService.DeleteById(id);
return result > ? Request.CreateResponse(HttpStatusCode.OK) : Request.CreateResponse(HttpStatusCode.NotFound);
}

四、数据仓储

  由于不打算使用EF,但数据仓储又是DDD一个不可绕开的话题,所以单独写了一个DDD EF Repository的Demo

  http://www.cnblogs.com/frozenzhang/p/5390551.html

五、MongoDB数据仓储

  已单独开篇,

  http://www.cnblogs.com/frozenzhang/p/5442314.html

六、领域事件DomainEvents

感谢仓储大叔的分享,这里只贴出大叔没给出的源码:ActionDelegatedEventHandler<TEvent>类

    public class ActionDelegatedEventHandler<TEvent> : IEventHandler<TEvent>
where TEvent : IEvent
{
private Action<TEvent> func;
public ActionDelegatedEventHandler(Action<TEvent> func)
{
this.func = func;
} public void Handle(TEvent evt)
{
func(evt);
} }

调用示例:

        static void Main(string[] args)
{
EventBus.Instance.Subscribe(new DeleteStudentHandler_SendEmailToStudent());
EventBus.Instance.Subscribe(new DeleteStudentHandler_SendEmailToStudent());
EventBus.Instance.Subscribe(new ActionDelegatedEventHandler<DeleteStudentEvent>(o => { Thread.Sleep(); Console.WriteLine("学生Id为{0}", o.StuId); }));
EventBus.Instance.Subscribe(new ActionDelegatedEventHandler<DeleteStudentEvent>(o => { Thread.Sleep(); Console.WriteLine("学生Id为{0}", o.StuId); }));
var entity = new DeleteStudentEvent { StuId = };
Console.WriteLine("事件:删除一个学生,学生Id为{0}", entity.StuId);
EventBus.Instance.Publish(entity); Console.WriteLine("over"); Console.ReadKey();
}

结果:

七、领域Command

关于Event和Command的解释,http://www.zhihu.com/question/29129068

完整代码请移步

注册

            builder.RegisterType<DefaultCommandBus>().As<ICommandBus>().InstancePerLifetimeScope();

            var domainCommands = Assembly.Load("Frozen.DomainCommands");
builder.RegisterAssemblyTypes(domainCommands)
.AsClosedTypesOf(typeof(ICommandHandler<>)).InstancePerLifetimeScope();
builder.RegisterAssemblyTypes(domainCommands)
.AsClosedTypesOf(typeof(IValidationHandler<>)).InstancePerLifetimeScope();

Command

    /// <summary>
/// Command 删除学生
/// </summary>
public class DeleteStudentCommand : ICommand
{
/// <summary>
/// 学生Id
/// </summary>
public int StuId { get; set; } }

Handler

    public class DeleteStudentHandler : ICommandHandler<DeleteStudentCommand>
{
private readonly IStuEducationRepo _iStuEducationRepo; public DeleteStudentHandler(IStuEducationRepo iStuEducationRepo)
{
this._iStuEducationRepo = iStuEducationRepo;
} public ICommandResult Execute(DeleteStudentCommand command)
{ return new CommandResult(true);
} }

调用

    var command = new DeleteStudentCommand()
{
      StuId =
};
var result = _commandBus.Submit(command);

结果:

八、Solr搜索引擎

 1、搭建Solr环境(Windows),见另一篇分享http://www.cnblogs.com/frozenzhang/p/5333746.html

 2、在browser的Solr管理后台添加Core “Student”

  <!-- general -->
<field name="StuId" type="int" indexed="true" stored="true" multiValued="false" required="true"/>
<field name="Name" type="string" indexed="true" stored="true"/>
<field name="DegreeIdArr" type="int" indexed="true" stored="true" multiValued="true" />
<field name="SchoolNameArr" type="string" indexed="true" stored="true" multiValued="true" />
<field name="MajorCodeArr" type="string" indexed="true" stored="true" multiValued="true" /> <uniqueKey>StuId</uniqueKey>

3、从NuGet安装SolrNet

4、项目中新建索引类‘StudentSolrIndex’

    public class StudentSolrIndex
{
[SolrUniqueKey("StuId")]
public int StuId { get; set; } [SolrField("Name")]
public string Name { get; set; } [SolrField("DegreeId")]
public int DegreeId { get; set; } public string SchoolNamesStr { get; set; } [SolrField("SchoolNameArr")]
public ICollection<string> SchoolNameArr
{
get
{
if (string.IsNullOrEmpty(SchoolNamesStr)) { return new string[] { }; }
return SchoolNamesStr.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Distinct().ToList();
}
} public string MajorCodesStr { get; set; } [SolrField("MajorCodeArr")]
public ICollection<string> MajorCodeArr
{
get
{
if (string.IsNullOrEmpty(MajorCodesStr)) { return new string[] { }; }
return MajorCodesStr.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Distinct().ToList();
}
} }

5、.config配置

  <appSettings>
<add key="StudentSolrServiceUrl" value="http://localhost:8080/solr/Student" />
</appSettings>

6、同步数据

            SolrNet.Startup.Init<StudentSolrIndex>(ConfigurationManager.AppSettings.Get("StudentSolrServiceUrl"));

            var solrOper = ServiceLocator.Current.GetInstance<ISolrOperations<StudentSolrIndex>>();

            solrOper.Add(new StudentSolrIndex()
{
StuId = ,
Name = "张冬林",
DegreeId = ,
SchoolNamesStr = "安大,上大",
MajorCodesStr = "080901,080902"
}); solrOper.Commit();

7、这时在solr的admin界面,查询,看见数据,说明数据同步成功了

8、查询数据

            SolrNet.Startup.Init<StudentSolrResult>(ConfigurationManager.AppSettings.Get("StudentSolrServiceUrl"));

            var solrQuery = ServiceLocator.Current.GetInstance<ISolrOperations<StudentSolrResult>>();

            ISolrQuery mainQuery = SolrQuery.All;

            QueryOptions options = new QueryOptions()
{
FilterQueries = new List<ISolrQuery>().ToArray(),
OrderBy = new SortOrder[] {
SortOrder.Parse("score desc")
},
Start = ,
Rows = ,
};
var results = solrQuery.Query(mainQuery, options);

结果截图:

九、Redis

1、Windows下Redis的环境安装,感谢园子里一位博友的分享

2、配置主从服务器(从服务器作为只读)

  Redis的默认服务端口是6379,

  所以这里只修改从服务器的redis.config里的配置

  port 6380

  bind 127.0.0.1

  slaveof 127.0.0.1 6379

  6379是主服务器,6380作为从服务器

3、Redis作为缓存服务器

  已单独开了一篇,http://www.cnblogs.com/frozenzhang/p/5439940.html

十、SignalR(+Redis)

1、SignalR在线聊天室

  已单独开了一篇,http://www.cnblogs.com/frozenzhang/p/5406773.html

十一、Memcached

   <configSections>
<sectionGroup name="enyim.com">
<section name="memcached" type="Enyim.Caching.Configuration.MemcachedClientSection, Enyim.Caching" />
</sectionGroup>
</configSections>
<enyim.com>
<memcached>
<servers>
<!-- put your own server(s) here-->
<add address="127.0.0.1" port="11211" />
</servers>
<socketPool minPoolSize="10" maxPoolSize="100" connectionTimeout="00:00:10" deadTimeout="00:02:00" />
</memcached>
</enyim.com>
 using Enyim.Caching;
using Enyim.Caching.Memcached;
using Frozen.Framework.Cache;
using System;
using System.Collections.Generic; namespace Froen.Memcached.Cached
{
public class MemcachedCache : ICache
{
private const string REGION_NAME = "$#MemcachedCache#$";
private const int _DefaultCacheTime = ;
private readonly static object s_lock = new object(); private static readonly MemcachedClient client = new MemcachedClient(); public IEnumerable<KeyValuePair<string, object>> Entries
{
get { throw new NotImplementedException(); }
} public T Get<T>(string key, Func<T> baseMethod)
{
return Get(key, baseMethod, _DefaultCacheTime);
} public T Get<T>(string key, Func<T> baseMethod, int cacheTime)
{
key = BuildKey(key); if (client.Get(key) != null)
{
return client.Get<T>(key);
}
else
{
lock (s_lock)
{
if (client.Get(key) == null)
{
var value = baseMethod();
if (value != null) //请区别null与String.Empty
{
client.Store(StoreMode.Set, key, value, TimeSpan.FromMinutes(cacheTime));
}
return value;
}
return client.Get<T>(key);
}
}
} public bool Contains(string key)
{
return client.Get(BuildKey(key)) != null;
} public void Remove(string key)
{
client.Remove(BuildKey(key));
} private string BuildKey(string key)
{
return string.IsNullOrEmpty(key) ? null : REGION_NAME + key;
} }
}

十二、为API自动生成帮助文档

1、安装Microsoft.AspNet.WebApi.HelpPage

2、修改Areas/HelpPag/App_Start/HelpPageConfig的Register方法

配置xml文件路径:"~/App_Data"

             // Uncomment the following to use the documentation from XML documentation file.
config.SetDocumentationProvider(new XmlDocumentationProvider(HttpContext.Current.Server.MapPath("~/App_Data")));

这时访问/Help应该会报异常

3、修改Areas/HelpPag/XmlDocumentationProvider的构造函数

         public XmlDocumentationProvider(string documentPath)
{
//if (documentPath == null)
//{
// throw new ArgumentNullException("documentPath");
//}
//XPathDocument xpath = new XPathDocument(documentPath);
//_documentNavigator = xpath.CreateNavigator(); XDocument finalDoc = null;
foreach (string file in Directory.GetFiles(documentPath, "Frozen.*.xml"))
{
using (var fileStream = File.OpenRead(file))
{
if (finalDoc == null)
{
finalDoc = XDocument.Load(fileStream);
}
else
{
XDocument xdocAdditional = XDocument.Load(fileStream); finalDoc.Root.XPathSelectElement("/doc/members")
.Add(xdocAdditional.Root.XPathSelectElement("/doc/members").Elements());
}
}
} // Supply the navigator that rest of the XmlDocumentationProvider code looks for
_documentNavigator = finalDoc.CreateNavigator();
}

4、通过Web页查看接口

强烈推荐阅读园友的分享如何使 WebAPI 自动生成漂亮又实用在线API文档-Swashbuckle。界面不仅颜值高,还可以代替Fiddler来调试api接口

写在最后

  此篇随笔,如果你粗阅了一下,会发现没有任何理论阐述,这主要是因为博主对相关知识点的理解尚不深刻,至今也没有阅读过源码,不想误导大家。错误的地方也欢迎指正。内容基本是从当前的项目中整理出来的,或来自园子里。博主虽有四年工作经验,会的技能不多也不少,但平时缺乏总结,缺乏review,整理这篇随笔的主要原因一方面是想梳理下自己掌握的技能,另一方面也希望能明确自己在专业技能方面的不足之处

  两年前我刚来魔都,其实那时候(对于当时的我来说,理想的)工作挺难找的,房总招了我,给的待遇对于那时候的我来说,已经非常满足了。无奈项目后来转java了,dotNET团队解散。不管怎么说,房哥对我有着一份知遇之恩,所以以后如果有机会,希望能再次拜入房哥门下

  接着就是面试,基本都会被问的一个问题‘在315che做的都是维护工作么’,好吧,现在才知道人家其实是在问‘你是不是团队里最菜的那个’。面试了几家,有人要就入职了,平级跳,平级跳,没错,就是平级跳

  近期要换雇主了,已拿到一个比较满意的offer,所以没有什么如临大敌的感觉。但一切又好像太平静了

  这篇文章发的其实有点仓促,因为临时打算花时间做个面试准备(这段话写于2016/05/10凌晨)

  一年半前,面试了沪江和携程,都被刷了,比较难回答的问题:‘性能’‘设计模式’‘算法’
  携程被刷是因为当时资历的确没达到
  沪江当时面试后感觉还好,但无奈还是没过。现在想想,当时可能因为是,没有MVC项目的工作经验,‘性能’意识不强,还有就是自己面试时的应变能力、语言组织能力有点差

  这半个月其实我也做了下思想斗争,该不该再投一次沪江和携程呢。现在还是决定再投一次,说实话 面试时,这些理论方面的描述,我其实并不擅长。所以打算一个星期左右的时间做下面试准备,准备差不多后再投

  最后也说下为什么选择离开现在的东家。其实只有一句话:情非得已 实属无奈,我已经兑现了当初面试时我说的一句话,‘我不会轻易跳槽’,在我这样Programmer(至少我)的眼里,我已经算是坚持到最后的那个人了

  本篇也算结束了,虽然还有几个知识点我想整理的,后面有时间再补上吧

  晚安,上海

  晚安,所有在大城市打拼的人

  附:源码下载

搭建一个Web API项目(DDD)的更多相关文章

  1. 如何搭建一个WEB服务器项目(二)—— 对数据库表进行基本的增删改查操作

    使用HibernateTemplate进行增删改查操作 观前提示:本系列文章有关服务器以及后端程序这些概念,我写的全是自己的理解,并不一定正确,希望不要误人子弟.欢迎各位大佬来评论区提出问题或者是指出 ...

  2. 使用模板创建第一个Web API项目

    软件环境 vs 2015 update3 本节将通过例子讲述创建Web API 项目的方法 第一步,打开vs ,依次通过[文件]菜单,[新建][项目]命令,大致步骤如下图 :   第2步,在弹出对话框 ...

  3. 如何搭建一个WEB服务器项目(六)—— 上传图片至服务器

    上传图片(用户头像)至服务器 观前提示:本系列文章有关服务器以及后端程序这些概念,我写的全是自己的理解,并不一定正确,希望不要误人子弟.欢迎各位大佬来评论区提出问题或者是指出错误,分享宝贵经验.先谢谢 ...

  4. 如何搭建一个WEB服务器项目(四)—— 实现安卓端图片加载

    使用Glide安卓图片加载库 观前提示:本系列文章有关服务器以及后端程序这些概念,我写的全是自己的理解,并不一定正确,希望不要误人子弟.欢迎各位大佬来评论区提出问题或者是指出错误,分享宝贵经验.先谢谢 ...

  5. 如何搭建一个WEB服务器项目(三)—— 实现安卓端联网登录

    安卓端调用服务器登录函数进行验证登录 观前提示:本系列文章有关服务器以及后端程序这些概念,我写的全是自己的理解,并不一定正确,希望不要误人子弟.欢迎各位大佬来评论区提出问题或者是指出错误,分享宝贵经验 ...

  6. 如何搭建一个WEB服务器项目(一)—— 开篇 ,搭建SSH整合框架

    使用Intellij IDEA2019创建SSH(Spring+SpringMVC+Hibernate+Maven整合)项目 观前提示:本系列文章有关服务器以及后端程序这些概念,我写的全是自己的理解, ...

  7. 如何搭建一个WEB服务器项目(五)—— Controller返回JSON字符串

    从服务器获取所需数据(JSON格式) 观前提示:本系列文章有关服务器以及后端程序这些概念,我写的全是自己的理解,并不一定正确,希望不要误人子弟.欢迎各位大佬来评论区提出问题或者是指出错误,分享宝贵经验 ...

  8. .Net Core 3.1浏览器后端服务(一) Web API项目搭建

    一.前言 基于CefSharp开发的浏览器项目已有一段时间,考虑到后期数据维护需要Server端来管理,故开启新篇章搭建浏览器后端服务.该项目前期以梳理服务端知识为主,后期将配合CefSharp浏览器 ...

  9. 对一个前端使用AngularJS后端使用ASP.NET Web API项目的理解(4)

    chsakell分享了一个前端使用AngularJS,后端使用ASP.NET Web API的项目. 源码: https://github.com/chsakell/spa-webapi-angula ...

随机推荐

  1. BZOJ2152 聪聪可可 【点分治】

    BZOJ2152 聪聪可可 Description 聪聪和可可是兄弟俩,他们俩经常为了一些琐事打起来,例如家中只剩下最后一根冰棍而两人都想吃.两个人都想玩儿电脑(可是他们家只有一台电脑)--遇到这种问 ...

  2. LeetCode 755. Pour Water

    原题链接在这里:https://leetcode.com/problems/pour-water/description/ 题目: We are given an elevation map, hei ...

  3. 【Netty】netty学习之nio网络编程的模型

    [一]NIO服务器编程结构 [二]Netty3.x服务端线程模型

  4. pycharm中import动态链接库pyd有错误

    有红色波浪线提示unsolved reference云云 去setting里面设置interpreters,  在path里面添加对应的路径, 是包含对应头文件的路径, 不要忘记右边的小按钮去Relo ...

  5. dockerize 容器工具集基本使用

    基本功能:   *  在启动的时候根据环境变量或者模版生成配置文锦啊 *   多日志文件重定向到标准输入输出 *   等待其他服务(tcp,http unix)起来之后在启动主进程   1. 安装 直 ...

  6. getpwuid()

    getpwuid函数是通过用户的uid查找用户的passwd数据.如果出错时,它们都返回一个空指针并设置errno的值,用户可以根据perror函数查看出错的信息. 外文名 getpwuid() 头文 ...

  7. hadoop之 解析HDFS的写文件流程

    文件是如何写入HDFS的 ? 下面我们来先看看下面的“写”流程图:  假如我们有一个文件test.txt,想要把它放到Hadoop上,执行如下命令: 引用         # hadoop fs  - ...

  8. Spring Boot 入门之 Web 篇(二)

    原文地址:Spring Boot 入门之 Web 篇(二) 博客地址:http://www.extlight.com 一.前言 上一篇<Spring Boot 入门之基础篇(一)>介绍了 ...

  9. sql的一些事件处理

    select getdate() select Convert(varchar(10),getdate(),120) yyyy-mm-ddselect Convert(varchar(20),getd ...

  10. c#QQ邮件编程学习(收发邮件)

    本次c#实现邮件管理编程的目的是实现第三方邮件管理,邮箱基于QQ邮箱,发送邮件直接采用.NET自带的System.Net.Mail类,接收邮件采用第三方组件Lumisoft.Net.现将基本实现的接收 ...