Introduction  众所周知,web请求(HTTP请求)是根据请求/响应机制工作的。通过这种方式,作为客户机的浏览器使用GET或POST向服务器发送请求,服务器根据客户机对它的请求准备适当的响应,然后关闭它们之间的连接。因此,这个过程是一种单向通信,客户端是初学者,因此服务器只是一个响应,它不能发送一个请求给客户端,并通知他们自己的状态。对于开发人员来说,这种请求/响应机制似乎是一个麻烦的限制。为什么我们被强制发送一个请求来告知当前的服务器状态?我们如何摆脱这个响应/请求问题?这个问题促使开发人员尝试许多方法、技巧和技术来克服这个限制。其中的一些方法是: 刷新页面在一个周期时间:这个方法是最糟糕的,因为它刷新所有元素的指定页面没有必要性refreshmentRefreshing页面在一个周期的一部分时间使用Iframe 彗星Programming  TechniquesWeb Socket : HTML5和IIS7 在本文中,我们主要讨论Web套接字、Comet技术和SignalR,它是一个很好的工具,可以帮助在ASP中使用Comet技术。网络开发者。 彗星Programming  Techniques  我引用以下维基百科的描述: Comet是一种web应用程序模型,在该模型中,一个长期存在的HTTP 请求允许web服务器将数据推送到浏览器,而不需要浏览器明确地请求它。所有这些方法都依赖于浏览器默认包含的特性,比如JavaScript,而不是非默认插件。Comet方法不同于web的原始模型,在原始模型中,浏览器一次请求一个完整的web页面 Comet技术在web开发中的使用早于Comet一词作为集体技术的新词的使用。Comet还有其他几个名字,包括Ajax Push,[4][5] Reverse Ajax,[6]双向web,[7] HTTP流,[7]和HTTP服务器Push[8]等等。 Comet有一些用于实现的技术,它们是两大类的子集:流和长轮询 流媒体包括以下: 依次向服务器(传统的AJAX)隐藏框架发送AJAX请求 长轮询的AJAX:“以上所有流传输都不能在所有现代浏览器上正常工作而不产生负面的副作用。这迫使Comet开发人员实现几个复杂的流传输,并根据浏览器在它们之间切换。因此,许多Comet应用程序使用长轮询,这更容易在浏览器端实现,并且至少可以在支持XHR的每个浏览器中工作。顾名思义,长轮询要求客户机向服务器轮询一个事件(或一组事件)。浏览器向服务器发出ajax风格的请求,该请求一直保持打开状态,直到服务器有新数据要发送给浏览器,该数据将以完整的响应发送给浏览器。浏览器启动一个新的长轮询请求,以获取后续事件。完成长轮询的具体技术包括: XMLHttpRequest长轮询脚本标记长轮询 SignalR 使用comet技术进行编程是很复杂的,如果您想这样做的话,它将是一项困难而耗时的工作。SignalR是一个用于ASP的库。NET在web应用程序中添加实时功能。使用SignalR并不困难,但更重要的是,它根据浏览器的功能使用一组comet技术。如果你的浏览器不支持HTML5和web套接字技术,SignalR将回到以前的框架或长池作为comet优先级(例如:IE8)。使用SignalR需要有丰富的背景对客户端和服务器之间的通信,但是这个库是一个简单的方法使用彗星,这可能就像一把双刃剑肤浅的程序员(程序员所使用客户端框架的豪言壮语jQuery和JavaScript编程没有经验,因为他们大多没有深度了解客户端编程),这可能会导致缺乏很多不适。此外,你应该了解。net 4中的动态类型。除此之外,SignalR是一个很棒的库,它提供了许多用于创建实时web应用程序的高级功能。 如何安装信号 进入Nuget: PM>安装包Microsoft.AspNet.SignalR 和 PM>安装包SignalR版本0.6.1 为了得到它的例子,在Nuget上键入这一行: PM>安装包Microsoft.AspNet.SignalR.Sample安装后,一些dll将添加到bin目录中,一些JavaScript文件将添加到Scripts文件夹中。 对于IE8,你应该安装JSON2.js如下: PM>安装包json2 如果这个文件没有安装到你的脚本文件夹,你会遇到这个错误: 隐藏,复制Code

No JSON parser found. Please ensure json2.js is referenced before the SignalR.js file

如何使用信号 有两种使用SignalR的框架,包括Hub和persistence connection。Hub提供了一个比持久连接更高级的框架。PersistentConnection给了你很多控制权。如果您想让SignalR为您做所有繁重的工作,并将困难的工作分配给SignalR来自动完成,您可以使用Hub框架。在本文中,我们使用Hub。 首先将以下代码写入全局变量。在ApplicationStart()方法中的asax: 隐藏,复制Code

RouteTable.Routes.MapHubs();  

与低级的持久连接不同,不需要为hub指定路由,因为它们可以通过一个特殊的URL自动访问。 创建一个从Hub类继承的类。 隐藏,复制Code

public class CommentHub : Hub {......}

客户机调用服务器 要展示一个可从所有客户端调用的方法,只需声明一个公共方法: 隐藏,复制Code

public class MyHub : Hub
{
public string Send(string data)
{
return data;
}
}

此方法可从客户端访问。客户端使用指定的数据作为参数调用此方法,然后此方法可以对输入数据执行任何操作,然后将其作为输出返回。 隐藏,复制Code

public string get(string data)
{
return data;
}

服务器调用客户端 从服务器调用客户端方法使用客户端属性: 隐藏,复制Code

public string get(string data)
{
return Clients.All.broadcastMessage(data);
}

现在我们扩展我们的描述,关注细节并仔细阅读项目代码。 在这个项目中,主要文件有: CommentHub。cs:根据注释成功或失败的过程,将添加的注释的XML文档(已在客户机中生成)转换为适当的html。发表评论。注释的实体及其属性注释。xslt Comments.aspx CommentHub类 隐藏,收缩,复制Code

public class CommentHub : Hub
{
public void Send(string name, string message, int status, Guid hubId,
string thisCommentId,string contentId,string currentUserID)
{
XmlDocument XmlMessage = new XmlDocument();
XmlMessage.LoadXml(message);
string CommentId=XmlMessage.SelectSingleNode("comment").Attributes["id"].Value;
string messageBody = XmlMessage.SelectSingleNode("comment/message").InnerText;
XSLTransformer XSL = new XSLTransformer();
XsltArgumentList argsList = new XsltArgumentList();
try
{
if (messageBody != string.Empty && messageBody != null)
{
if (message.Contains("fail"))
{
argsList.AddParam("ResultSet", "", 0);
Clients.All.broadcastMessage(name, XSL.TransformToHtml(XmlMessage,
"Comments.xslt", argsList), 0, hubId, CommentId);
} //Adding parameters to XSLT
//If ResultSet set to 1,it means success
else
{
argsList.AddParam("ResultSet", "", 1);
argsList.AddParam("CommentingDate", "", DateTime.Now);
Clients.All.broadcastMessage(name, XSL.TransformToHtml(XmlMessage,
"Comments.xslt", argsList).Replace(
"<?xml version=\"1.0\" encoding=\"utf-16\"?>",
""), 1, hubId, CommentId);
}
}
}
catch (Exception exp)
{
//Adding parameters to XSLT
//If ResultSet set to 0,it means fail
argsList.AddParam("ResultSet", "", 0);
switch (exp.GetType().ToString())
{
case "SqlException":
Clients.All.broadcastMessage(name, XSL.TransformToHtml(XmlMessage,
"Comments.xslt", argsList), -2, hubId,CommentId);
break;
default:
Clients.All.broadcastMessage(name, XSL.TransformToHtml(XmlMessage,
"Comments.xslt", argsList), 0, hubId, CommentId);
break;
}
}
}
}

从客户端调用Send()方法,客户端将所需的参数传递给该方法。其中一个参数是message。实际上message是由客户机生成的XML,它包含当前评论的一些属性和属性,如:用户名、CommentID和message。这个参数被加载到一个XmlDocument中,然后XSLTransformer将这个XML文档转换为将广播给用户的适当的HTML文档。在这个项目中,没有数据库中的存储注释或其他功能的代码,但您可以做任何您想做的事情。例如,假设我们的代码将注释存储到数据库中,通过插入过程,代码遇到了异常,比如连接失败等等。在这种情况下,我们想通知用户他的评论没有被发送,并给他再一次机会重新发送评论。为了实现此操作,我们将ResultSet参数添加到XSLT Transformer的参数列表中,以便对html输出进行决策。如果结果集被设置为“0”,则表示失败,而“1”表示成功。正如我写的,客户,所有人。broadcastMessage意味着我们在客户端有一个名为“broadcastMessage”的函数,服务器可以调用它。 下面的代码模拟了失败状态。如果你写了一个包含“fail”的句子,你会看到失败状态的结果。 隐藏,复制Code

//Lines 38 to 42 simulate failed status
if (message.Contains("fail"))
{
argsList.AddParam("ResultSet", "", 0);
Clients.All.broadcastMessage(name, XSL.TransformToHtml(XmlMessage,
"Comments.xslt", argsList), 0, hubId, CommentId);
}

SignalR JS客户端hub: 在你的页面上包括以下脚本: 隐藏,复制Code

<script src="http://www.codeproject.com/Scripts/json2.js"></script>
<script src="http://www.codeproject.com/Scripts/jquery-1.7.1.min.js"></script>
<script src="http://www.codeproject.com/Scripts/jquery.signalR-1.0.0-rc2.js"></script>
<script src="http://www.codeproject.com/signalr/hubs"></script>

编程模型 .connection.hub美元 所有集线器的连接(URL指向/signalr)。 返回a 连接 .connection.hub.id美元 hub连接的客户端id。 .connection.hub.logging美元 设置为true则启用日志记录。默认的是假的 $ .connection.hub.start () 启动所有集线器的连接。 查看其他重载,开始()返回jQuery延迟 .connection美元。{hubname}, 从生成的代理访问客户端中心。 返回一个中心。服务器上集线器的名称。注意:集线器的名称是驼峰式大小写(例如,如果服务器集线器是MyHub,连接上的属性将是MyHub) stateChanged是一个函数,每次连接状态改变时执行。 隐藏,复制Code

$.connection.hub.error(function (error) {
$.connection.hub.stop();
}); $.connection.hub.stateChanged(function (change) {
if (change.newState === $.signalR.connectionState.reconnecting) {
//console.log('Re-connecting');
}
else if (change.newState === $.signalR.connectionState.connected) {
//console.log('The server is online');
}
});

首先,我们声明一个变量如下: 隐藏,复制Code

var commentList = $.connection.commentHub; 

根据以上描述,其功能如下: 隐藏,收缩,复制Code

//-------functions------
$(function () {
commentList.client.broadcastMessage = function (name, message, status, hubId, thisCommentId) {
var messageResonse = message;
var oo = thisCommentId.toString();
var GUID = null;
if (writerHubId == hubId) {
GUID = comments.generateGuid();
messageResonse = message + "<tr><td align='left' id='delete_" + GUID
+ "' width='200px' align='left' style='color:red;'>" +
"<a href='javascript:void(0)' " +
"onclick='javascript:comments.deleteComment(\""
+ oo + "\");return false;'><img title='delete' " +
"style='width:20px;height:20px;border:0px;cursor:pointer' " +
"src='Images/trash_green.png' /></a></td></tr>;
}
messageResonse = "<table width='100%' id='PT_" + thisCommentId
+ "' style='background-color:#F1F1F1;" +
"border:1px;border-style:solid;border-color:#C4C4C4'>"
+ comments.setRealBreakLine(messageResonse)
+ "</table><table id='HDT_" + thisCommentId +
"' width='100%'><tr><td " +
"height='15px'></td></tr></table>";
if (status == 1)
$('#Comments').append(messageResonse);
else if ((writerHubId == hubId)
&&
(status == 0 || status == -2))
$('#Comments').append(comments.setRealBreakLineForInnerTextOnTextArea(message));
}; $('#message').focus();
$.connection.hub.start({ waitForPageLoad: false }, function () {
}).done(function () {
$('#sendmessage').click(function () {
sendOverHub();
});
}); $.connection.hub.error(function (error) {
$.connection.hub.stop();
}); $.connection.hub.stateChanged(function (change) {
if (change.newState === $.signalR.connectionState.reconnecting) {
//console.log('Re-connecting');
}
else if (change.newState === $.signalR.connectionState.connected) {
//console.log('The server is online');
}
});
});

broadcastMessage函数由服务器调用,并为客户端显示最后的注释。为了检查用户对自己的评论进行删除评论等行为的可访问性,我们需要检查当前用户的hubId是否等于当前评论已发送的hubId。 隐藏,复制Code

var GUID = null;
if (writerHubId == hubId) {
GUID = comments.generateGuid();
messageResonse = message + "<tr><td align='left' id='delete_" + GUID
+ "' width='200px' align='left' style='color:red;'><a "
+ "href='javascript:void(0)' onclick='javascript:comments.deleteComment(\""
+ oo + "\");return false;'><img title='delete' "
+ "style='width:20px;height:20px;border:0px;cursor:pointer' " +
"src='Images/trash_green.png' /></a></td></tr>";
}

函数通过CommentHub类的Send方法发送注释。在本文中,我没有为用户使用不同的名称,而是设置了相同的nam因为代码简单,所以被称为“测试用户”。 隐藏,复制Code

function send() {
writerHubId = $.connection.hub.id;
commentList.server.send(
$('test').val()
,comments.ToXml(comments.setFakeBreakline("message"),
"Test User",comments.generateGuid())
, -1
, $.connection.hub.id
, null
, ""
, $('').val());
$('#message').val('').focus();
}

如果评论出现错误,你之前的评论会再次出现,并且会显示错误信息,在再次尝试之前还会给你一次编辑评论的机会。当你点击Try again链接时,tryToSendMessageAgain 被调用: 隐藏,复制Code

tryToSendMessageAgain: function (Id) {
var messageBody = comments.getLastFailedCommentText(Id);
$("#div_" + comments.getPureId(Id)).animate({ height: 'hide', opacity: 'hide' }, 500);
window.setTimeout(function () { $("#div_" + comments.getPureId(Id)).remove() },600);
writerHubId = $.connection.hub.id;
commentList.server.send(
"Test User"
, comments.ToXml
(
comments._setFakeBreaklineForInnerText(messageBody)
, "Test User"
, comments.generateGuid()
)
, -1
, writerHubId
, ""
, ""
, "");
$('#message').val('').focus();
}

thetrytosendmessageagain和send 函数可以在一个集成的函数,但我没有花更多的时间来实现这个。 ToXML()函数将注释转换为XML格式,以便通过XSLT进行转换,而generateGuid函数为每个注释生成一个惟一的ID。 隐藏,复制Code

ToXml: function (message, user, previousID) {
return (previousID == null) ? "<comment id='"
+ this.generateGuid() + "'><message>"
+ message + "</message><username>"
+ user + "</username></comment>" : "<comment id='"
+ previousID + "'><message>"
+ message + "</message><username>"
+ user + "</username></comment>";
}

隐藏,复制Code

generateGuid: function () {
var result, i, j;
result = '';
for (j = 0; j < 32; j++) {
if (j == 8 || j == 12 || j == 16 || j == 20)
result = result + '-';
i = Math.floor(Math.random() * 16).toString(16).toUpperCase();
result = result + i;
}
return result;
},

XSLTransformer类 这个类根据传递给它的参数将每个注释的xmldocument转换为HTML文档。它包含两个重载方法。如果您想要将一些参数发送到指定的XSLT,那么应该使用第二个参数,它接受参数并将它们传递给XSLT。 隐藏,复制Code

public string TransformToHtml(XmlDocument xmlDocument,
string XmlTransformer,XsltArgumentList Argument)
{
try
{
XslCompiledTransform transform = new XslCompiledTransform();
transform.Load(HttpContext.Current.Server.MapPath(
"~/XSLT/" + XmlTransformer + ""));
StringBuilder htmlStrb = new StringBuilder();
StringReader stringReader = new StringReader(xmlDocument.InnerXml);
StringWriter stringWriter = new StringWriter(htmlStrb);
transform.Transform(new XPathDocument(stringReader), Argument, stringWriter);
return htmlStrb.ToString();
}
catch (Exception exp)
{
throw new Exception(exp.InnerException.Message);
}
}

XSLT XSLT (可扩展样式表语言转换)是一个语言转换XML 文档转换为其他XML文档,[1],或其他对象(as  HTML  for 网页,,纯text 或into  XSL格式化Objects 然后可以用转换PDF, PostScript 以及PNG。[2] 通常,输入文档是XML文件,但是可以使用处理器可以从中构建XQuery和XPath数据模型的任何文件,例如关系数据库表或地理信息系统 原始文件未发生变化;相反,新文档是基于现有文档的内容创建的 XSLT是一种图尔-完整的语言,这意味着它可以执行现代计算机程序所能执行的任何计算。 我发现XSLT是一种非常有用的语言,可以处理各种情况,例如:错误处理、基于服务器或客户端生成的XML导出适当的HTML以及基于用户请求处理各种外观。它有一些巨大的好处,如: 干净,简洁的模板一种简单的方法处理XML数据到HTML合理的快速一种伟大的方法有干净的代码在UI层 在本文中,我使用XSLT处理评论的用户界面和处理诸如连接错误之类的错误。XSLT中有两个模板。第一个调用在服务器端作业完成且没有任何错误时调用,第二个调用在发生错误时调用。 showNewComment:当服务器端作业完成且没有任何错误时调用第一个。 隐藏,复制Code

<xsl:templatematch="/">
<xsl:iftest="$ResultSet='1'">
<xsl:call-templatename="showNewComment"></xsl:call-template>
</xsl:if>
<xsl:iftest="$ResultSet='0'">
<xsl:call-templatename="showFailedComment"></xsl:call-template>
</xsl:if>
</xsl:template>

对于基于成功/失败调用正确的调用,我们使用xsl:call-template。 如果在服务器端,ResultSet参数被初始化为1,那么showNewComment 模板被调用;如果它被初始化为0,那么showFailedComment 被调用。 在这个XSLT中,我不关心HTML设计,它看起来可能设计得很糟糕,但这并不重要。这只是一个样本。 根据以上描述,XSLT结构如下: 隐藏,收缩,复制Code

<xsl:stylesheetversion="1.0"xmlns:xsl="http://www.w3.org/1999/XSL/Transform"xmlns:msxsl="urn:schemas-microsoft-com:xslt"exclude-result-prefixes="msxsl">
<xsl:outputmethod="xml"indent="yes"/>
<xsl:paramname="ResultSet"></xsl:param>
<xsl:paramname="CurrentUser"></xsl:param>
<xsl:paramname="CommentingDate"></xsl:param>
<xsl:templatematch="/">
<xsl:iftest="$ResultSet='1'">
<xsl:call-templatename="showNewComment"></xsl:call-template>
</xsl:if>
<xsl:iftest="$ResultSet='0'">
<xsl:call-templatename="showFailedComment"></xsl:call-template>
</xsl:if>
</xsl:template>
<xsl:templatename="showNewComment">
<xsl:for-eachselect="comment">
<xsl:variablename="elementID"select="@id"/>
<xsl:variablename="userName"select="username"></xsl:variable>
.......
</xsl:for-each>
</xsl:template> <xsl:templatename="showFailedComment">
.......... </xsl:for-each>
</xsl:template>
</xsl:stylesheet>

的兴趣点 这一点,对我来说是很有趣的和有趣的是这一现实,一个杰出的程序员没有丰富的背景是客户机/服务器的概念和缺乏当他们想要程序出现在comet技术之一,显然有些JavaScript 框架类似jQuery,加强这种短缺的程序员没有优秀的背景与JavaScript编程和使用它来处理AJAX请求。这组程序员在理解SignalR是如何工作的时候会混淆。所以我建议他们更深入地学习JavaScript和客户端/服务器的概念。 References  Comet编程: http://en.wikipedia.org/wiki/Comet_(编程)SignalR wiki: https://github.com/SignalR/SignalR/wiki  History  2013年3月1日(星期五):1.0版本。 本文转载于:http://www.diyabc.com/frontweb/news18852.html

使用SignalR和XSLT进行实时注释的更多相关文章

  1. 使用SignalR+Asp.net创建实时聊天应用程序

    一.概述: 使用 ASP.NET 那么 SignalR 2 创建一个实时聊天应用程序.将 SignalR 添加 MVC 5 应用程序中,并创建聊天视图发送并显示消息. 在Demo中,将学习Signal ...

  2. WPF+SignalR实现用户列表实时刷新

    原文:WPF+SignalR实现用户列表实时刷新 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/lordwish/article/details/5 ...

  3. 使用SignalR实现比特币价格实时刷新

    ASP.NET SignalR是微软支持的一个运行在 Dot NET 平台上的 HTML Websocket 框架.它出现的主要目的是实现服务器主动推送(Push)消息到客户端页面,这样客户端就不必重 ...

  4. Vue 结合 SignalR 实现前后端实时消息同步

    最近业务中需要实现服务器端与客户端的实时通信功能,对Signalr做了一点总结和整理. SignalR 作为  ASP.NET 的一个库,能够简单方便地为应用提供实时的服务器端与客户端双向通信功能. ...

  5. Signalr Vue Echarts绘制实时CPU使用率

    后端基于Asp.net webapi,前端Vue,前后端分离,该demo仅做演示,实现的细节可以自己优化 Echarts:4.2.1  可参考 官网 Jquery:3.4.1 Signalr:2.4. ...

  6. XAMARIN.ANDROID SIGNALR 实时消息接收发送示例

    SignalR 是一个开发实时 Web 应用的 .NET 类库,使用 SignalR 可以很容易的构建基于 ASP.NET 的实时 Web 应用.SignalR 支持多种服务器和客户端,可以 Host ...

  7. 常见的Web实时消息交互方式和SignalR

    标签: WebSocket SignalR 前言 1. Web消息交互技术 1.1 常见技术 1.2 WebSocket介绍 1.3 WebSocket示例 2. Signal 2.1 SignalR ...

  8. 【转】常见的Web实时消息交互方式和SignalR

    https://www.cnblogs.com/Wddpct/p/5650015.html 前言 1. Web消息交互技术1.1 常见技术1.2 WebSocket介绍1.3 WebSocket示例 ...

  9. SignalR 2.0入门

    下载已完成的项目 本教程展示如何使用那么 SignalR 创建一个实时聊天应用程序.你会那么 SignalR 添加一个空的 ASP.NET web 应用程序,创建一个 HTML 页面发送并显示消息. ...

随机推荐

  1. adb 打开手机端口进行无线模式调试

    打开手机端口 让手机在指定的端口可以接收到TCP/IP连接. 确保手机开启了usb调试 用usb线把手机和电脑连接起来 执行命令:adb tcpip 5555 执行成功后就可以把usb线拔掉了,端口可 ...

  2. 开源基于lua gc管理c++对象的cocos2dx lua绑定方案

    cocos2dx目前lua对应的c++对象的生命周期管理,是基于c++析构函数的,也就是生命周期可能存在不一致,比如c++对象已经释放,而lua对象还存在,如果这时候再使用,会有宕机的风险,为此我开发 ...

  3. 分数运算(gcd)

    时间限制 1000 ms 内存限制 32768 KB 代码长度限制 100 KB 判断程序 Standard (来自 小小) 题目描述 计算机中采用浮点数表示所有实数,但这意味着精度丢失.例如无法精确 ...

  4. [易霖博YCTF]Web WriteUp

    中午队里师傅发到群里的比赛,借来队里师傅账号和队里其他师傅一起做了一下,ak了web,师傅们tql.学到挺多东西,总结一下. rce_nopar 进入题目给出源码: <?php if(isset ...

  5. MySQL索引凭什么能让查询效率提高这么多?

    点赞再看,养成习惯,微信搜一搜[三太子敖丙]关注这个喜欢写情怀的程序员. 本文 GitHub https://github.com/JavaFamily 已收录,有一线大厂面试完整考点.资料以及我的系 ...

  6. rank,dense_rank和row_number函数区别

    我对技术一般抱有够用就好的态度,一般在网上或者书上找了贴合的解决方案,放到实际中发现好用就行了,不再深究,等出了问题再说. 因此,我对Oracle中中形成有效序列的方法集中在rownum,row_nu ...

  7. Effective Objective-C 的读书笔记

    本文主要是摘录了 <Effective Objective-C 2.0>一书中提到的编写高质量iOS 代码的几个方法. 1 熟悉Objective -C 1.1 OC 起源 OC 为C语言 ...

  8. pycharm写的代码提交到git上,提示需要merge失败时解决办法

    当遇到pycharm代码提交需要合并报错时 原因:pycharm目录和git中目录冲突了 解决办法:1.先在git仓库中创建一个文件夹,比如day1 2.然后在pycharm中update一下,可以看 ...

  9. Druid连接池配置全攻略

    Druid是阿里开源出来的数据库连接池,性能非常好,还自带日志监控. 它的DataSource类为:com.alibaba.druid.pool.DruidDataSource. 由于使用的yaml格 ...

  10. day52:django:ORM单表/多表操作

    目录 1.ORM 2.ORM单表增删改查 13个必知必会的查询接口 filter基于双下划线的模糊查询 3.ORM多表增删改查 ORM 什么是ORM? ORM(object relational ma ...