转:[WebServices]介绍

2024-02-09 00:08
文章标签 介绍 webservices

本文主要是介绍转:[WebServices]介绍,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1. 有关生存期的补充
正常情况下,每次调用 WebMethod,服务器都会创建一个新的 WebService 对象,即便客户端使用同一个代理对象多次调用 WebMethod。
而我们一旦调用了有缓存标记的 WebMethod,只要未超出缓存期,WebService 对象都不会被重新创建。在缓存期内调用没有缓存标记的 WebMethod,也会继续使用该 WebService 对象。有太多因素让这个缓存机制变得不那么可靠,因此我们不能奢望用缓存标记来维持特定的对象状态,况且缓存机制的设计初衷也只是为了快速输出那些比较稳定非常大的数据。
基于多用户并发调用这个环境,WebService 本身最好设计成无状态对象,我们可以使用 Session 和 Application 来保持特定的状态信息。
2. 异步调用
网上很多人在写有关 .net 2.0 的文章时,都喜欢用“优雅”这个词。的确,在 2.0 中编译器和代码生成器为我们封装了很多罗嗦的东西,诸如匿名方法、委托推断等等,当然还有这 WebService 的异步调用。我们不用再写那些个 BeginXXX、EndXXX 了,基于事件驱动的异步机制会自动为每个 WebMethod 生成一个 XXXAsync 的异步方法和 XXXCompleted 事件,我们只需调用该方法,并处理该事件即可完成异步操作,当真是优雅了不少。不要小看 2.0 的这些封装,我们编写的代码越少意味着出错的几率越小。
下面的示例中,我们使用了匿名方法来处理事件,看上去更简洁了些。
WebServices.cs

[WebService(Namespace = "http://www.rainsts.net/", Description="我的Web服务")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class WebService : System.Web.Services.WebService
{
   [WebMethod]
   public string HelloWorld()
   {
     return "Hello World!";
   }
}

Client.cs

WebService ws = new WebService();
ws.HelloWorldCompleted += delegate(object sender, HelloWorldCompletedEventArgs e)
{
   Console.WriteLine(e.Result);
};
ws.HelloWorldAsync("xxx");

3. 缓存
WebMethodAttribute.CacheDuration 为 WebService 提供了缓存申明机制。通过添加该标记,我们可以缓存输出结果。不过缓存机制会影响 WebService 的生存期(见上)。
WebServices.cs

[WebService(Namespace = "http://www.rainsts.net/", Description="我的Web服务")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class WebService : System.Web.Services.WebService
{
   [WebMethod(CacheDuration=10)]
   public DateTime TestCache()
   {
     return DateTime.Now;
   }
}

Client.cs

WebService ws = new WebService();
for (int i = 0; i < 20; i++)
{
   Console.WriteLine("{0}:{1}", i + 1, ws.TestCache());
   Thread.Sleep(1000);
}

4. 保持状态
.NET WebService 是建立在 ASP.NET 基础上,在 WebService 中我们同样可以访问 Session、User、Application 等上下文对象,不过在某些使用细节上可能有所不同。
由于 WebService 客户端代理对象可能应用于 ConsoleApplication、WinForm 或 WebForm 等环境,而 Session 又必须通过 Cookie 来保存唯一的 SessionID,因此我们必须使用 CookieContainer 创建 Cookie 容器来保存 WebService 返回的 Session 信息,否则每次调用的 SessionID 都不同,自然无法使用 Session 来保存状态了。
创建容器对象后,必须将其引用赋值给代理对象的 CookieContainer 属性。在第一次调用 SessionEnabled WebMethod 后,该容器将持有 Session Cookie 信息。如果需要在多个代理对象中调用 SessionEnabled WebMethod,那么它们必须持有同一个 Cookie 容器对象。
WebServices.cs

[WebService(Namespace = "http://www.rainsts.net/", Description="我的Web服务")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class WebService : System.Web.Services.WebService
{
   [WebMethod(EnableSession = true)]
   public string TestSession()
   {
     string s = "TestSession";
     object o = Session[s];
     int i = o != null ? (int)o : 0;
     ++i;
     Session[s] = i;
     return Session.SessionID.ToString() + ":" + i;
   }
}

Client.cs

WebService ws = new WebService();
// 创建Cookie容器,保持SessionID。否则每次调用的 SessionID 都不同。
CookieContainer cookies = new CookieContainer();
ws.CookieContainer = cookies;
for (int i = 0; i < 10; i++)
{
   Console.WriteLine("{0}:{1}", i + 1, ws.TestSession());
}

至于 Application 的使用和 WebForm 中基本没有什么区别。
WebServices.cs

[WebService(Namespace = "http://www.rainsts.net/", Description="我的Web服务")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class WebService : System.Web.Services.WebService
{
   [WebMethod]
   public DateTime TestApplicationState()
   {
     object o = Application["TestApplicationState"];
     if (o == null)
     {
       o = DateTime.Now;
       Application["TestApplicationState"] = o;
     }
     return (DateTime)o;
   }
}

Client.cs

for (int i = 0; i < 10; i++)
{
   WebService ws = new WebService();
   Console.WriteLine("{0}:{1}", i + 1, ws.TestApplicationState());
   Thread.Sleep(1000);
}

5. SoapHeader
SoapHeader 多数情况下用来传递用户身份验证信息,当然它的作用远不止如此,有待于在实际应用中发掘。
SoapHeader 缺省情况下由客户端代理对象发送给 WebService,当然我们可以通过 WebMethodAttribute.Direction 来改变传送方向。
SoapHeader 使用步骤:
(1) 创建继承自 System.Web.WebServices.SoapHeader 的自定义 SoapHeader 类型。
(2) 在 WebService 中创建拥有 public 访问权限的自定义 SoapHeader 字段。
(3) 在需要使用 SoapHeader 的 WebMethod 上添加 SoapHeaderAttribute 访问特性。SoapHeaderAttribute 构造必须指定 memberName 参数,就是我们在第二步中申明的字段名称。
(4) 生成器会自动为客户端生成同名的自定义 SoapHeader 类型,只不过比起我们在 WebService 端创建的要复杂一些。同时还会为代理类型添加一个 soapheaderValue 属性。
在下面的演示代码,客户端将传递一个自定义 MyHeader 到 WebService。请注意,我们尽管在 WebService 中申明了 MyHeader 字段,但并没有创建对象实例,这是因为客户端传递过来的 XML 中包含了 SoapHeader 信息,基础结构会自动解析并创建对象实例,然后赋值给 my 字段。至于客户端,自然需要创建一个 MyHeader 对象实例,并赋值给 WebService.MyHeaderValue 属性。SoapHeaderAttribute.Direction 缺省就是 In,下面例子中的 "Direction = SoapHeaderDirection.In" 可以省略。
WebServices.cs

public class MyHeader : SoapHeader
{
   public string Username;
   public string Password;
}
[WebService(Namespace = "http://www.rainsts.net/", Description="我的Web服务")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class WebService : System.Web.Services.WebService
{
   public MyHeader my;
   [WebMethod]
   [SoapHeader("my", Direction = SoapHeaderDirection.In)]
   public void TestSoapHeadIn()
   {
     System.Diagnostics.Debug.Write(my.Username);
     System.Diagnostics.Debug.Write(my.Password);
   }
}

Client.cs

WebService ws = new WebService();
MyHeader head = new MyHeader();
head.Username = "u2";
head.Password = "p2";
ws.MyHeadValue = head;
ws.TestSoapHeadIn();

我们改写一下,将传递方向改为从 WebService 到客户端。自然我们需要调整 "Direction = SoapHeaderDirection.Out",在 WebMethod 中我们还必须创建 MyHeader 实例,因为这次我们不会接受到客户端传递的 SoapHeader 了。客户端代理对象调用 WebMethod 后就可以使用 MyHeaderValue 属性访问其内容了。
WebServices.cs

public class MyHeader : SoapHeader
{
   public string Username;
   public string Password;
}
[WebService(Namespace = "http://www.rainsts.net/", Description="我的Web服务")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class WebService : System.Web.Services.WebService
{
   public MyHeader my;
   [WebMethod]
   [SoapHeader("my", Direction = SoapHeaderDirection.Out)]
   public void TestSoapHeadOut()
   {
     my = new MyHeader();
     my.Username = "u1";
     my.Password = "p1";
   }
}

Client.cs

WebService ws = new WebService();
ws.TestSoapHeadOut();
Console.WriteLine(ws.MyHeaderValue.Username);
Console.WriteLine(ws.MyHeaderValue.Password);

6. 异常
ASP.NET WebService 通过 Fault XML 元素来传递异常信息,客户端代理对象会生成一个 SoapException 的异常,并使用 Fault XML 信息填充其相关属性,诸如 Message 等。另外我们可以对 WebService 进行异常包装,除了传递 Exception Message 外,还可以传递一些错误状态代码,以便客户端用户做进一步处理。
WebServices.cs

[WebService(Namespace = "http://www.rainsts.net/", Description="我的Web服务")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class WebService : System.Web.Services.WebService
{
   [WebMethod]
   public void TestException()
   {
     try
     {
       throw new Exception("aaa...");
     }
     catch (Exception e)
     {
       throw new SoapException(e.Message, new System.Xml.XmlQualifiedName("ErrorCode01"), e);
     }
   }
}

Client.cs

WebService ws = new WebService();
try
{
   ws.TestException();
}
catch (System.Web.Services.Protocols.SoapException e)
{
   Console.WriteLine(e.Message);
   Console.WriteLine(e.Code.Name);
}

 


ASP.NET WebService 支持绝大多数的基元类型及其数组,另外还支持自定义的结构(Struct)、类型(Class)、枚举(Enum)、DataSet、XmlElement、XmlNode、集合(IEnumerable/ICollection)等。
ASP.NET WebService 使用 XmlSerializer 进行序列化操作,对于自定义类型要注意以下几点:
1. 只能序列化可读写公共属性和字段。只读属性(get;)、只读字段(readonly)、常量(const)以及所有的非 public 数据成员都不会被序列化。
2. 自定义类型必须具有不接受任何参数的默认构造函数。
3. 不能序列化方法。客户端生成的代理对象不包含任何自定义类型方法(不是WebMethod)。
基于以上几点,因此我们最好只定义纯粹用来传输复合数据的数据类型(Data Object)。
以下是一些演示代码。
基元类型

[WebService(Namespace = "http://www.rainsts.net/", Description="我的Web服务")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class WebService : System.Web.Services.WebService {
public WebService () {
}
   [WebMethod]
   public DateTime GetNowTime()
   {
     return DateTime.Now;
   }
   [WebMethod]
   public string[] GetStringArray()
   {
     return new string[] { "a", "b", "c"};
   }
   [WebMethod]
   public float[] GetFloatArray()
   {
     return new float[]{1F, 2F, 3F};
   }
   [WebMethod]
   public byte[] GetBytes()
   {
     return System.IO.File.ReadAllBytes(@"c:\windows\notepad.exe");
   }
}

枚举 Enum

public enum Sex
{
   Female,
   Male
}
[WebService(Namespace = "http://www.rainsts.net/", Description="我的Web服务")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class WebService : System.Web.Services.WebService {
public WebService () {
}
   [WebMethod]
   public Sex GetSex()
   {
     return Sex.Female;
   }
   [WebMethod]
   public Sex[] GetAllSex()
   {
     return Enum.GetValues(typeof(Sex)) as Sex[];
   }
}

结构 Struct
结构体默认就会创建无参数构造方法,且不允许自定义。

public struct MyStruct
{
   public int X;
   public int Y;
   public MyStruct(int x, int y)
   {
     this.X = x;
     this.Y = y;
   }
}
[WebService(Namespace = "http://www.rainsts.net/", Description="我的Web服务")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class WebService : System.Web.Services.WebService {
public WebService () {
}
   [WebMethod]
   public MyStruct GetMyStruct()
   {
     MyStruct st = new MyStruct(15, 16);
     return st;
   }
   [WebMethod]
   public MyStruct[] GetMyStructs()
   {
     return new MyStruct[] { new MyStruct(1, 2), new MyStruct(3, 4) }; ;
   }
}

类型 Class

public struct MyStruct
{
   public int X;
   public int Y;
   public MyStruct(int x, int y)
   {
     this.X = x;
     this.Y = y;
   }
}
public class MyClass
{
   public MyClass()
   {
     myStruct = new MyStruct();
   }
   public MyClass(int x, int y, string name) : this()
   {
     myStruct.X = x;
     myStruct.Y = y;
     this.name = name;
   }
   private string name;
   public string Name
   {
     get { return name; }
     set { name = value; }
   }
   private MyStruct myStruct;
   public MyStruct MyStruct
   {
     get { return myStruct; }
     set { myStruct = value; }
   }
   public void Test() // 客户端代理不会生成该方法。
   {
     Console.WriteLine(name);
   }
}
[WebService(Namespace = "http://www.rainsts.net/", Description="我的Web服务")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class WebService : System.Web.Services.WebService {
public WebService () {
}
   [WebMethod]
   public MyClass GetMyClass()
   {
     return new MyClass(1, 2, "name1");
   }
   [WebMethod]
   public MyClass[] GetMyClassArray()
   {
     return new MyClass[] { new MyClass(1, 2, "name1"), new MyClass(2, 3, "name2") }; ;
   }
}

有关数据类型的更详细信息,请查看 MSDN 文档。
ms-help://MS.MSDNQTR.v80.chs/MS.MSDN.v80/MS.VisualStudio.v80.chs/dv_fxwebservices/html/70567d9f-6e53-42a8-bbd5-aee42b25dd28.htm


多数时候我们通过 "添加 Web 引用..." 创建客户端代理类的方式调用WebService,但在某些情况下我们可能需要在程序运行期间动态调用一个未知的服务。在 .NET Framework 的 System.Web.Services.Description 命名空间中有我们需要的东西。
具体步骤:
1. 从目标 URL 下载 WSDL 数据。
2. 使用 ServiceDescription 创建和格式化 WSDL 文档文件。
3. 使用 ServiceDescriptionImporter 创建客户端代理类。
4. 使用 CodeDom 动态创建客户端代理类程序集。
5. 利用反射调用相关 WebService 方法。
OK,看看具体的例子。
我们要调用的目标 WebService,其 URL 是 http://localhost:60436/Learn.WEB/WebService.asmx
HelloWorld.asmx

[WebService(Namespace = "http://www.rainsts.net/", Description="我的Web服务")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class WebService : System.Web.Services.WebService {
public WebService () {
}
   [WebMethod]
   public string HelloWorld()
   {
     return "Hello Wolrd!";
   }
}

1. 动态调用 WebService
客户端动态调用代码

using System.IO;
using System.Net;
using System.Reflection;
using System.CodeDom;
using System.CodeDom.Compiler;
using System.Web.Services;
using System.Web.Services.Description;
using System.Web.Services.Protocols;
using System.Xml.Serialization;
// 1. 使用 WebClient 下载 WSDL 信息。
WebClient web = new WebClient();
Stream stream = web.OpenRead("http://localhost:60436/Learn.WEB/WebService.asmx?WSDL");
// 2. 创建和格式化 WSDL 文档。
ServiceDescription description = ServiceDescription.Read(stream);
// 3. 创建客户端代理代理类。
ServiceDescriptionImporter importer = new ServiceDescriptionImporter();
importer.ProtocolName = "Soap"; // 指定访问协议。
importer.Style = ServiceDescriptionImportStyle.Client; // 生成客户端代理。
importer.CodeGenerationOptions = CodeGenerationOptions.GenerateProperties | CodeGenerationOptions.GenerateNewAsync;
importer.AddServiceDescription(description, null, null); // 添加 WSDL 文档。
// 4. 使用 CodeDom 编译客户端代理类。
CodeNamespace nmspace = new CodeNamespace(); // 为代理类添加命名空间,缺省为全局空间。
CodeCompileUnit unit = new CodeCompileUnit();
unit.Namespaces.Add(nmspace);
ServiceDescriptionImportWarnings warning = importer.Import(nmspace, unit);
CodeDomProvider provider = CodeDomProvider.CreateProvider("CSharp");
CompilerParameters parameter = new CompilerParameters();
parameter.GenerateExecutable = false;
parameter.GenerateInMemory = true;
parameter.ReferencedAssemblies.Add("System.dll");
parameter.ReferencedAssemblies.Add("System.XML.dll");
parameter.ReferencedAssemblies.Add("System.Web.Services.dll");
parameter.ReferencedAssemblies.Add("System.Data.dll");
CompilerResults result = provider.CompileAssemblyFromDom(parameter, unit);
// 5. 使用 Reflection 调用 WebService。
if (!result.Errors.HasErrors)
{
   Assembly asm = result.CompiledAssembly;
   Type t = asm.GetType("WebService"); // 如果在前面为代理类添加了命名空间,此处需要将命名空间添加到类型前面。
   object o = Activator.CreateInstance(t);
   MethodInfo method = t.GetMethod("HelloWorld");
   Console.WriteLine(method.Invoke(o, null));
}

2. 生成客户端代理程序集文件
上面的代码通过在内存中创建动态程序集的方式完成了动态调用过程。如果我们希望将客户端代理类生成程序集文件保存到硬盘,则可以进行如下修改。生成程序集文件后,我们可以通过 Assembly.LoadFrom() 载入并进行反射调用。对于需要多次调用的系统,要比每次生成动态程序集效率高出很多。

using System.IO;
using System.Net;
using System.CodeDom;
using System.CodeDom.Compiler;
using System.Web.Services;
using System.Web.Services.Description;
using System.Web.Services.Protocols;
using System.Xml.Serialization;
// 1. 使用 WebClient 下载 WSDL 信息。
WebClient web = new WebClient();
Stream stream = web.OpenRead("http://localhost:60436/Learn.WEB/WebService.asmx?WSDL");
// 2. 创建和格式化 WSDL 文档。
ServiceDescription description = ServiceDescription.Read(stream);
// 3. 创建客户端代理代理类。
ServiceDescriptionImporter importer = new ServiceDescriptionImporter();
importer.ProtocolName = "Soap"; // 指定访问协议。
importer.Style = ServiceDescriptionImportStyle.Client; // 生成客户端代理。
importer.CodeGenerationOptions = CodeGenerationOptions.GenerateProperties | CodeGenerationOptions.GenerateNewAsync;
importer.AddServiceDescription(description, null, null); // 添加 WSDL 文档。
// 4. 使用 CodeDom 编译客户端代理类。
CodeNamespace nmspace = new CodeNamespace(); // 为代理类添加命名空间,缺省为全局空间。
CodeCompileUnit unit = new CodeCompileUnit();
unit.Namespaces.Add(nmspace);
ServiceDescriptionImportWarnings warning = importer.Import(nmspace, unit);
CodeDomProvider provider = CodeDomProvider.CreateProvider("CSharp");
CompilerParameters parameter = new CompilerParameters();
parameter.GenerateExecutable = false;
parameter.OutputAssembly = "test.dll"; // 可以指定你所需的任何文件名。
parameter.ReferencedAssemblies.Add("System.dll");
parameter.ReferencedAssemblies.Add("System.XML.dll");
parameter.ReferencedAssemblies.Add("System.Web.Services.dll");
parameter.ReferencedAssemblies.Add("System.Data.dll");
CompilerResults result = provider.CompileAssemblyFromDom(parameter, unit);
if (result.Errors.HasErrors)
{
   // 显示编译错误信息
}

调用程序集文件演示

Assembly asm = Assembly.LoadFrom("test.dll");
Type t = asm.GetType("WebService");
object o = Activator.CreateInstance(t);
MethodInfo method = t.GetMethod("HelloWorld");
Console.WriteLine(method.Invoke(o, null));

3. 获取客户端代理类源代码
还有一种情形,就是我们需要获得客户端代理类的 C# 源代码。

using System.IO;
using System.Net;
using System.CodeDom;
using System.CodeDom.Compiler;
using System.Web.Services;
using System.Web.Services.Description;
using System.Web.Services.Protocols;
using System.Xml.Serialization;
// 1. 使用 WebClient 下载 WSDL 信息。
WebClient web = new WebClient();
Stream stream = web.OpenRead("http://localhost:60436/Learn.WEB/WebService.asmx?WSDL");
// 2. 创建和格式化 WSDL 文档。
ServiceDescription description = ServiceDescription.Read(stream);
// 3. 创建客户端代理代理类。
ServiceDescriptionImporter importer = new ServiceDescriptionImporter();
importer.ProtocolName = "Soap"; // 指定访问协议。
importer.Style = ServiceDescriptionImportStyle.Client; // 生成客户端代理。
importer.CodeGenerationOptions = CodeGenerationOptions.GenerateProperties | CodeGenerationOptions.GenerateNewAsync;
importer.AddServiceDescription(description, null, null); // 添加 WSDL 文档。
// 4. 使用 CodeDom 编译客户端代理类。
CodeNamespace nmspace = new CodeNamespace(); // 为代理类添加命名空间,缺省为全局空间。
CodeCompileUnit unit = new CodeCompileUnit();
unit.Namespaces.Add(nmspace);
ServiceDescriptionImportWarnings warning = importer.Import(nmspace, unit);
CodeDomProvider provider = CodeDomProvider.CreateProvider("CSharp");
// 5. 保存源代码到文件。当然,你也可以直接保存到内存字符串中。
TextWriter writer = File.CreateText("test.cs"); // 指定你所需的源代码文件名。
provider.GenerateCodeFromCompileUnit(unit, writer, null);
writer.Flush();
writer.Close();

如果你调用时触发 "WebException: 请求因 HTTP 状态 415 失败: Unsupported Media Type。" 这样的异常,那么恭喜你和我一样郁闷 [cry],赶紧把服务器端的 WSE 关掉吧。在必须使用 WSE 的情况下,需要对客户端进行调整,至于代码需要你自己去写了。呵呵~~~~

这篇关于转:[WebServices]介绍的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/692604

相关文章

MySQL常用字符串函数示例和场景介绍

《MySQL常用字符串函数示例和场景介绍》MySQL提供了丰富的字符串函数帮助我们高效地对字符串进行处理、转换和分析,本文我将全面且深入地介绍MySQL常用的字符串函数,并结合具体示例和场景,帮你熟练... 目录一、字符串函数概述1.1 字符串函数的作用1.2 字符串函数分类二、字符串长度与统计函数2.1

zookeeper端口说明及介绍

《zookeeper端口说明及介绍》:本文主要介绍zookeeper端口说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、zookeeper有三个端口(可以修改)aVNMqvZ二、3个端口的作用三、部署时注意总China编程结一、zookeeper有三个端口(可以

Python中win32包的安装及常见用途介绍

《Python中win32包的安装及常见用途介绍》在Windows环境下,PythonWin32模块通常随Python安装包一起安装,:本文主要介绍Python中win32包的安装及常见用途的相关... 目录前言主要组件安装方法常见用途1. 操作Windows注册表2. 操作Windows服务3. 窗口操作

c++中的set容器介绍及操作大全

《c++中的set容器介绍及操作大全》:本文主要介绍c++中的set容器介绍及操作大全,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录​​一、核心特性​​️ ​​二、基本操作​​​​1. 初始化与赋值​​​​2. 增删查操作​​​​3. 遍历方

HTML img标签和超链接标签详细介绍

《HTMLimg标签和超链接标签详细介绍》:本文主要介绍了HTML中img标签的使用,包括src属性(指定图片路径)、相对/绝对路径区别、alt替代文本、title提示、宽高控制及边框设置等,详细内容请阅读本文,希望能对你有所帮助... 目录img 标签src 属性alt 属性title 属性width/h

MybatisPlus service接口功能介绍

《MybatisPlusservice接口功能介绍》:本文主要介绍MybatisPlusservice接口功能介绍,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友... 目录Service接口基本用法进阶用法总结:Lambda方法Service接口基本用法MyBATisP

MySQL复杂SQL之多表联查/子查询详细介绍(最新整理)

《MySQL复杂SQL之多表联查/子查询详细介绍(最新整理)》掌握多表联查(INNERJOIN,LEFTJOIN,RIGHTJOIN,FULLJOIN)和子查询(标量、列、行、表子查询、相关/非相关、... 目录第一部分:多表联查 (JOIN Operations)1. 连接的类型 (JOIN Types)

java中BigDecimal里面的subtract函数介绍及实现方法

《java中BigDecimal里面的subtract函数介绍及实现方法》在Java中实现减法操作需要根据数据类型选择不同方法,主要分为数值型减法和字符串减法两种场景,本文给大家介绍java中BigD... 目录Java中BigDecimal里面的subtract函数的意思?一、数值型减法(高精度计算)1.

Pytorch介绍与安装过程

《Pytorch介绍与安装过程》PyTorch因其直观的设计、卓越的灵活性以及强大的动态计算图功能,迅速在学术界和工业界获得了广泛认可,成为当前深度学习研究和开发的主流工具之一,本文给大家介绍Pyto... 目录1、Pytorch介绍1.1、核心理念1.2、核心组件与功能1.3、适用场景与优势总结1.4、优

Java实现本地缓存的常用方案介绍

《Java实现本地缓存的常用方案介绍》本地缓存的代表技术主要有HashMap,GuavaCache,Caffeine和Encahche,这篇文章主要来和大家聊聊java利用这些技术分别实现本地缓存的方... 目录本地缓存实现方式HashMapConcurrentHashMapGuava CacheCaffe