ASP.NET MVC API 接口验证的示例代码

项目中有一个留言消息接口,接收其他系统的留言和展示留言,参考了网上的一些API验证方法,发现使用通用权限管理系统提供的验证方法最完美。

下面将实现的完整思路共享

1、WebApiConfig全局处理

/// <summary>
  /// WebApiConfig
  /// 路由基础配置。
  ///
  ///
  /// 修改记录
  ///
  ///    2016.11.01 版本:2.0 宋彪 对日期格式进行统一处理。
  ///    2016.10.30 版本:2.0 宋彪 解决json序列化时的循环引用问题。
  ///    2016.10.28 版本:2.0 宋彪 回传响应格式 $format 支持。
  ///    2016.09.01 版本:1.0 宋彪  创建。
  ///
  /// 版本:1.0
  ///
  /// <author>
  ///    <name>宋彪</name>
  ///    <date>2016.09.01</date>
  /// </author>
  /// </summary>
  public static class WebApiConfig
  {
    /// <summary>
    /// 注册全局配置服务
    /// </summary>
    /// <param name="config"></param>
    public static void Register(HttpConfiguration config)
    {
      // Web API configuration and services

      //强制https访问
      //config.Filters.Add(new ForceHttpsAttribute());
      // 统一回传格式
      config.Filters.Add(new ApiResultAttribute());
      // 发生异常时处理
      config.Filters.Add(new ApiErrorHandleAttribute());
      // ToKen身份验证过滤器 更方便 不需要在这里了 具有改标签的就会自动检查
      //config.Filters.Add(new ApiAuthFilterAttribute());
      // 解决json序列化时的循环引用问题
      config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
      //对日期格式进行统一处理
      config.Formatters.JsonFormatter.SerializerSettings.Converters.Add(
      new IsoDateTimeConverter()
      {
        DateTimeFormat = "yyyy-MM-dd hh:mm:ss"
      }
      );

      // Web API routes 路由
      config.MapHttpAttributeRoutes();

      config.Routes.MapHttpRoute(
        name: "DefaultApi",
        routeTemplate: "api/{controller}/{action}/{id}",
        defaults: new { id = RouteParameter.Optional }
      );

      // 干掉XML序列化器
      //config.Formatters.Remove(config.Formatters.XmlFormatter);
      //在请求的Url加上 ?$format=xml,便可以指定响应格式
      config.Formatters.XmlFormatter.AddQueryStringMapping("$format", "xml", "application/xml");
      config.Formatters.JsonFormatter.AddQueryStringMapping("$format", "json", "application/json");
    }
  }

2、身份验证过滤器

  using DotNet.Business;
  using DotNet.Utilities;
  using DotNet.Tracking.API.Common;

  /// <summary>
  /// ApiAuthFilterAttribute
  /// 身份验证过滤器,具有ApiAuthFilterAttribute标签属性的方法会自动检查
  ///
  ///
  /// 修改纪录
  ///
  /// 2016-10-11 版本:1.0 SongBiao 创建文件。
  ///
  /// <author>
  ///   <name>SongBiao</name>
  ///   <date>2016-10-11</date>
  /// </author>
  /// </summary>
  [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
  public class ApiAuthFilterAttribute : AuthorizationFilterAttribute
  {
    /// <summary>
    /// 未授权时的提示信息
    /// </summary>
    private const string UnauthorizedMessage = "请求未授权,拒绝访问。";

    /// <summary>
    /// 权限进入
    /// </summary>
    /// <param name="actionContext"></param>
    public override void OnAuthorization(HttpActionContext actionContext)
    {
      base.OnAuthorization(actionContext);
      // 允许匿名访问
      if (actionContext.ActionDescriptor.GetCustomAttributes<AllowAnonymousAttribute>().Count > 0)
      {
        return;
      }

      string systemCode = APIOperateContext.Current.SystemCode;
      string permissionCode = APIOperateContext.Current.PermissionCode;
      string appKey = APIOperateContext.Current.AppKey;
      string appSecret = APIOperateContext.Current.AppSecret;
      if (string.IsNullOrWhiteSpace(appKey) || string.IsNullOrWhiteSpace(appSecret))
      {
        //未验证(登录)的用户, 而且是非匿名访问,则转向登录页面
        //actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized);
        //actionContext.Response.Content = new StringContent("<p>Unauthorized</p>", Encoding.UTF8, "text/html");
        var response = actionContext.Response= actionContext.Response?? new HttpResponseMessage();
        response.StatusCode = HttpStatusCode.Unauthorized;
        BaseResult result = new BaseResult
        {
          Status = false,
          StatusMessage = UnauthorizedMessage
        };
        response.Content = new StringContent(result.ToJson(), Encoding.UTF8, "application/json");
      }
      else
      {
        // 检查 AppKey 和 AppSecret
        BaseResult result = BaseServicesLicenseManager.CheckService(appKey, appSecret, false, 0, 0, systemCode, permissionCode);
        if (!result.Status)
        {
          var response = actionContext.Response = actionContext.Response?? new HttpResponseMessage();
          response.Content = new StringContent(result.ToJson(), Encoding.UTF8, "application/json");
        }
      }

    }
  }

3、统一回传格式

  /// <summary>
  /// ApiResultAttribute
  /// 统一回传格式
  ///
  /// 修改纪录
  ///
  /// 2016-10-31 版本:1.0 宋彪 创建文件。
  ///
  /// <author>
  ///   <name>宋彪</name>
  ///   <date>2016-10-31</date>
  /// </author>
  /// </summary>
  public class ApiResultAttribute : ActionFilterAttribute
  {
    /// <summary>
    /// 重写回传的处理
    /// </summary>
    /// <param name="actionExecutedContext"></param>
    public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
    {
      // 快件跟踪接口传的是format,不用走这里
      if (actionExecutedContext.Request.Properties.ContainsKey("format"))
      {
        // 若发生例外则不在这边处理 在异常中处理 ApiErrorHandleAttribute
        if (actionExecutedContext.Exception != null)
          return;
        base.OnActionExecuted(actionExecutedContext);
        var result = new ApiResultModel();
        // 取得由 API 返回的状态码
        result.Status = actionExecutedContext.ActionContext.Response.StatusCode;
        // 取得由 API 返回的资料
        result.Data = actionExecutedContext.ActionContext.Response.Content.ReadAsAsync<object>().Result;
        // 重新封装回传格式
        actionExecutedContext.Response = actionExecutedContext.Request.CreateResponse(result.Status, result);
      }
    }
  }

4、全局异常处理

  using DotNet.Utilities;
  using DotNet.Tracking.API.Common;
  using DotNet.Tracking.API.Controllers;
  using DotNet.Tracking.API.Models;

  /// <summary>
  /// ApiErrorHandleAttribute
  /// 全局异常处理
  ///
  /// 修改纪录
  ///
  /// 2016-10-31 版本:1.0 宋彪 创建文件。
  ///
  /// <author>
  ///   <name>宋彪</name>
  ///   <date>2016-10-31</date>
  /// </author>
  /// </summary>

  public class ApiErrorHandleAttribute : System.Web.Http.Filters.ExceptionFilterAttribute
  {
    /// <summary>
    /// 异常统一处理
    /// </summary>
    /// <param name="actionExecutedContext"></param>
    public override void OnException(System.Web.Http.Filters.HttpActionExecutedContext actionExecutedContext)
    {
      base.OnException(actionExecutedContext);
      // 取得发生例外时的错误讯息
      var errorMessage = actionExecutedContext.Exception.Message;

      // 异常记录
      string parameters = APIOperateContext.GetRequestParameters();
      NLogHelper.Trace(actionExecutedContext.Exception, BaseSystemInfo.SystemCode + " ApiErrorHandleAttribute OnException 完整的请求地址及参数 : " + parameters);
      // 2016-11-01 加入异常邮件提醒
      NLogHelper.InfoMail(actionExecutedContext.Exception, BaseSystemInfo.SystemCode + " ApiErrorHandleAttribute OnException 完整的请求地址及参数 : " + parameters);

      var result = new ApiResultModel()
      {
        Status = HttpStatusCode.BadRequest,
        ErrorMessage = errorMessage
      };
      // 重新打包回传的讯息
      actionExecutedContext.Response = actionExecutedContext.Request.CreateResponse(result.Status, result);
    }
  }

5、接口操作的上下文

  using DotNet.Business;
  using DotNet.Model;
  using DotNet.Utilities;

  /// <summary>
  /// APIOperateContext
  /// 接口操作的上下文
  /// 跟上下文有关的一些通用的东西放在这里处理
  ///
  /// 修改纪录
  ///
  /// 2016-10-31 版本:1.0 宋彪 创建文件。
  ///
  /// <author>
  ///   <name>宋彪</name>
  ///   <date>2016-10-31</date>
  /// </author>
  /// </summary>
  public class APIOperateContext
  {
    /// <summary>
    /// 获取当前 操作上下文 (为每个处理浏览器请求的服务器线程 单独创建 操作上下文)
    /// </summary>
    public static APIOperateContext Current
    {
      get
      {
        APIOperateContext oContext = CallContext.GetData(typeof(APIOperateContext).Name) as APIOperateContext;
        if (oContext == null)
        {
          oContext = new APIOperateContext();
          CallContext.SetData(typeof(APIOperateContext).Name, oContext);
        }
        return oContext;
      }
    }

    #region Http上下文 及 相关属性
    /// <summary>
    /// Http上下文
    /// </summary>
    public HttpContext ContextHttp
    {
      get
      {
        return HttpContext.Current;
      }
    }

    /// <summary>
    /// 输出对象
    /// </summary>
    public HttpResponse Response
    {
      get
      {
        return ContextHttp.Response;
      }
    }

    /// <summary>
    /// 请求对象
    /// </summary>
    public HttpRequest Request
    {
      get
      {
        return ContextHttp.Request;
      }
    }

    /// <summary>
    /// Session对象
    /// </summary>
    System.Web.SessionState.HttpSessionState Session
    {
      get
      {
        return ContextHttp.Session;
      }
    }
    #endregion

    /// <summary>
    /// 获取全部请求参数,get和post的 简化版
    /// </summary>
    public static string GetRequestParameters()
    {
      string query = HttpContext.Current.Request.Url.Query;
      NameValueCollection nvc;
      string baseUrl;
      ParseUrl(query, out baseUrl, out nvc);
      List<string> list = new List<string>() { };
      foreach (var key in nvc.AllKeys)
      {
        list.Add(key + "=" + nvc[key]);
      }

      var form = HttpContext.Current.Request.Form;
      foreach (var key in form.AllKeys)
      {
        list.Add(key + "=" + form[key]);
      }
      string result = HttpContext.Current.Request.Url.AbsoluteUri + "?" + string.Join("&", list);

      return result;
    }

    /// <summary>
    /// 分析 url 字符串中的参数信息
    /// 针对get请求的
    /// </summary>
    /// <param name="url">输入的 URL</param>
    /// <param name="baseUrl">输出 URL 的基础部分</param>
    /// <param name="nvc">输出分析后得到的 (参数名,参数值) 的集合</param>
    public static void ParseUrl(string url, out string baseUrl, out NameValueCollection nvc)
    {
      if (url == null)
      {
        throw new ArgumentNullException("url");
      }
      nvc = new NameValueCollection();
      baseUrl = "";
      if (url == "")
      {
        return;
      }
      int questionMarkIndex = url.IndexOf('?');
      if (questionMarkIndex == -1)
      {
        baseUrl = url;
        return;
      }
      baseUrl = url.Substring(0, questionMarkIndex);
      if (questionMarkIndex == url.Length - 1)
      {
        return;
      }
      string ps = url.Substring(questionMarkIndex + 1);
      // 开始分析参数对
      Regex re = new Regex(@"(^|&)?(\w+)=([^&]+)(&|$)?", RegexOptions.Compiled);
      MatchCollection mc = re.Matches(ps);
      foreach (Match m in mc)
      {
        nvc.Add(m.Result("$2").ToLower(), m.Result("$3"));
      }
    }

    /// <summary>
    /// 系统编号
    /// </summary>
    public string SystemCode
    {
      get
      {
        return Request["systemCode"] ?? "Base";
      }
    }

    /// <summary>
    /// 权限编号
    /// </summary>
    public string PermissionCode
    {
      get
      {
        return Request["permissionCode"];
      }
    }

    /// <summary>
    /// 访问接口的应用传来AppKey
    /// </summary>
    public string AppKey
    {
      get
      {
        return Request["appKey"];
      }
    }

    /// <summary>
    /// 访问接口的应用传来AppSecret
    /// </summary>
    public string AppSecret
    {
      get
      {
        return Request["appSecret"];
      }
    }

    private BaseUserInfo _userInfo = null;
    /// <summary>
    /// 获取当前用户
    /// 通过接口AppKey和AppSecret获取的用户
    /// </summary>
    /// <returns></returns>
    public BaseUserInfo UserInfo
    {
      get
      {
        BaseUserInfo userInfo = null;
        BaseUserEntity userEntity = BaseUserManager.GetObjectByCodeByCache(AppKey);
        if (userEntity != null)
        {
          if (BaseServicesLicenseManager.CheckServiceByCache(userEntity.Id, AppSecret))
          {
            userInfo = new BaseUserInfo();
            userInfo.Id = userEntity.Id;
            userInfo.RealName = userEntity.RealName;
            userInfo.UserName = userEntity.UserName;
            userInfo.IPAddress = Utilities.GetIPAddress(true);
          }
        }
        return userInfo;
      }
    }

    #region 业务库连接
    /// <summary>
    /// 业务库连接
    /// </summary>
    public static IDbHelper BusinessDbHelper
    {
      get
      {
        return DbHelperFactory.GetHelper(BaseSystemInfo.BusinessDbType, BaseSystemInfo.BusinessDbConnection);
      }
    }
    #endregion

    #region 用户中心库连接
    /// <summary>
    /// 用户中心库连接
    /// </summary>
    public static IDbHelper UserCenterDbHelper
    {
      get
      {
        return DbHelperFactory.GetHelper(BaseSystemInfo.UserCenterDbType, BaseSystemInfo.UserCenterDbConnection);
      }
    }
    #endregion

  }

7、统一回传格式实体

  /// <summary>
  /// ApiResultModel
  /// 统一回传格式实体
  ///
  /// 修改纪录
  ///
  /// 2016-10-31 版本:1.0 宋彪 创建文件。
  ///
  /// <author>
  ///   <name>宋彪</name>
  ///   <date>2016-10-31</date>
  /// </author>
  /// </summary>
  public class ApiResultModel
  {
    public HttpStatusCode Status { get; set; }

    //public JsonResult<T> Data { get; set; }
    public object Data { get; set; }
    public string ErrorMessage { get; set; }
  }

8、留言相关接口

  /// <summary>
  /// MessageBookController
  /// 留言相关接口
  ///
  /// 修改纪录
  ///
  /// 2016-10-31 版本:1.0 宋彪 创建文件。
  ///
  /// <author>
  ///   <name>宋彪</name>
  ///   <date>2016-10-31</date>
  /// </author>
  /// </summary>
  [ApiAuthFilter]
  public class CustomerMessageController : ApiController
  {
    /// <summary>
    /// 保存单号留言信息
    /// </summary>
    /// <param name="messageBook"></param>
    /// <returns></returns>
    [HttpPost]
    //[AllowAnonymous] 不需要验证的就加这个标签
    public IHttpActionResult Add([FromBody]MsgbookCusEntity messageBook)
    {
      BaseResult baseResult = new BaseResult();
      if (string.IsNullOrWhiteSpace(messageBook.SystemFrom))
      {
        baseResult.Status = false;
        baseResult.StatusMessage = "SystemFrom参数不可为空";
      }
      else
      {
        try
        {
          MsgbookCusManager manager = new MsgbookCusManager(APIOperateContext.BusinessDbHelper, APIOperateContext.Current.UserInfo);
          MsgbookCusEntity model = new MsgbookCusEntity();
          model.Id = Guid.NewGuid().ToString("N");
          model.Message = messageBook.Message;
          model.SendEmail = messageBook.SendEmail;
          model.SendTelephone = messageBook.SendTelephone;
          model.Message = messageBook.Message;
          model.BillCode = messageBook.BillCode;
          model.SystemFrom = messageBook.SystemFrom;
          model.DeletionStateCode = 0;
          manager.Add(model, false, false);

          baseResult.Status = true;
          baseResult.StatusMessage = "添加成功。";
        }
        catch (Exception ex)
        {
          NLogHelper.Warn(ex, "CustomerMessageController AddBillMessage 异常");
          baseResult.Status = false;
          baseResult.StatusMessage = "异常:" + ex.Message;
        }
      }

      return Ok(baseResult);
    }

    /// <summary>
    /// 获取某个单号的留言
    /// </summary>
    /// <param name="billCode"></param>
    /// <returns></returns>
    [HttpGet]
    public IHttpActionResult GetList(string billCode)
    {
      JsonResult<List<MsgbookCusEntity>> jsonResult = new JsonResult<List<MsgbookCusEntity>>();
      try
      {
        MsgbookCusManager manager = new MsgbookCusManager(APIOperateContext.BusinessDbHelper, APIOperateContext.Current.UserInfo);
        List<MsgbookCusEntity> list = new List<MsgbookCusEntity>();
        list = manager.GetList<MsgbookCusEntity>(new KeyValuePair<string, object>(MsgbookCusEntity.FieldBillCode, billCode)
        , new KeyValuePair<string, object>(MsgbookCusEntity.FieldDeletionStateCode, 0));

        jsonResult.Status = true;
        jsonResult.RecordCount = list.Count;
        jsonResult.Data = list;
        jsonResult.StatusMessage = "获取成功";
      }
      catch (Exception ex)
      {
        NLogHelper.Warn(ex, "CustomerMessageController AddBillMessage 异常");
        jsonResult.Status = false;
        jsonResult.StatusMessage = "异常:" + ex.Message;
      }

      return Ok(jsonResult);
    }
  }

9、接口调用方法

    /// <summary>
    /// 测试留言接口调用
    /// </summary>
    /// <returns></returns>
    public ActionResult AddCustomerMessage()
    {
      string url = "http://192.168.1.88:808/api/CustomerMessage/Add?";
      WebClient webClient = new WebClient();
      NameValueCollection postValues = new NameValueCollection();

      postValues.Add("Message", "填写您的留言内容吧");
      postValues.Add("SendEmail", "youemail@qq.com");
      postValues.Add("SendTelephone", "021-60375335");
      postValues.Add("Code", "661137858");
      postValues.Add("AppKey", "wssavbcn");
      postValues.Add("AppSecret", "350e66b1e6564b0a817163erwwwwe8");
      postValues.Add("SystemFrom", "官网");

      byte[] responseArray = webClient.UploadValues(url, postValues);
      string response = Encoding.UTF8.GetString(responseArray);

      return Content(response);
    }

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • ASP.NET MVC Web API HttpClient简介

    1.HttpClient简单介绍 依稀还记得那个时候用WebClient,HttpWebRequest来发送一个请求,现在ASP.NET MVC4中自带了一个类HttpClient,用于接收HttpResponseMessage和发送HttpRequestMesssage. 问题在于既然WebClient,HttpWebRequest可以完成相应的功能,为什么还要使用HttpClient类,.NET Framework中既然提出了这样一个类肯定是有其特别之处的,这里罗列几个不同之处: (1) 可

  • 在CentOS6.5上使用Jexus安装部署ASP.NET MVC4和WebApi

    Jexus 即 Jexus Web Server,简称JWS,是Linux平台上的一款ASP.NET WEB服务器,是 Linux.Unix.FreeBSD 等非Windows系统架设 ASP.NET WEB 服务器的核心程序,是企业级ASP.NET跨平台部署的一种可选方案.与其它WEB服务器相比,Jexus不但具有跨平台ASP.NET服务器这样的标志性特征,同时还拥有内核级的安全监控.入侵检测.URL重写.无文件路由等一系列重要功能和专有特性. 一.使用Jexus5.8.1独立版 网址http

  • 为ASP.NET MVC及WebApi添加路由优先级

    一.为什么需要路由优先级 大家都知道我们在Asp.Net MVC项目或WebApi项目中注册路由是没有优先级的,当项目比较大.或有多个区域.或多个Web项目.或采用插件式框架开发时,我们的路由注册很可能 不是写在一个文件中的,而是分散在很多不同项目的文件中,这样一来,路由的优先级的问题就突显出来了. 比如: App_Start/RouteConfig.cs中 routes.MapRoute( name: "Default", url: "{controller}/{actio

  • ASP.NET MVC API 接口验证的示例代码

    项目中有一个留言消息接口,接收其他系统的留言和展示留言,参考了网上的一些API验证方法,发现使用通用权限管理系统提供的验证方法最完美. 下面将实现的完整思路共享 1.WebApiConfig全局处理 /// <summary> /// WebApiConfig /// 路由基础配置. /// /// /// 修改记录 /// /// 2016.11.01 版本:2.0 宋彪 对日期格式进行统一处理. /// 2016.10.30 版本:2.0 宋彪 解决json序列化时的循环引用问题. ///

  • Asp.net Mvc表单验证气泡提示效果

    本文实例为大家分享了Asp.net Mvc表单验证的制作代码,供大家参考,具体内容如下 将ASP.NET MVC或ASP.NET Core MVC的表单验证改成气泡提示: //新建一个js文件(如:jquery.validate.Bubble.js),在所有要验证的页面引用 (function ($) { $("form .field-validation-valid,form .field-validation-error") .each(function () { var tip

  • Springboot使用redis实现接口Api限流的示例代码

    前言 该篇介绍的内容如题,就是利用redis实现接口的限流(  某时间范围内 最大的访问次数 ) . 正文 惯例,先看下我们的实战目录结构: 首先是pom.xml 核心依赖: <!--用于redis数据库连接--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId>

  • ASP.NET MVC使用正则表达式验证手机号码

    在ASP.NET MVC中,可以使用RegularExpression特性来验证手机号码. public class Customer { [Required(ErrorMessage = "必填")] [Display(Name = "手机号")] [RegularExpression(@"^1[3458][0-9]{9}$", ErrorMessage = "手机号格式不正确")] public string PhoneN

  • SpringBoot实现阿里云短信接口对接的示例代码

    前言 公司最近项目需要一个手机验证码的功能,任务确定后,倍感亚历山大,以为和第三方对接的都好麻烦,查阿里的API.网上大神写的博客,各种查之后才发现,简单的一塌糊涂,这里想说个问题,不知道其他的攻城狮们是不是和我一样的心里,刚接触个没做过的任务时,会一脸懵里的着急,无从下手的感觉,后来会了,就觉得简单的一*,在这里我说一下自己的体会,遇到任何难点,先理思路.任务拆分.逐个查资料,其实一套下来,就不会那种一脸懵逼的干着急... 所需条件 1.阿里云账户 2.开通云通讯中的短信服务 3.申请短信签名

  • Python实现http接口自动化测试的示例代码

    网上http接口自动化测试Python实现有很多,我也是在慕课网上学习了相关课程,并实际操作了一遍,于是进行一些总结,便于以后回顾温习,有许多不完善的地方,希望大神们多多指教! 接口测试常用的工具有fiddler,postman,jmeter等,使用这些工具测试时,需要了解常用的接口类型和区别,比如我用到的post和get请求,表面上看get用于获取数据post用于修改数据,两者传递参数的方式也有不一样,get是直接在url里通过?来连接参数,而post则是把数据放在HTTP的包体内(reque

  • Vue+Springboot实现接口签名的示例代码

    1.实现思路 接口签名目的是为了,确保请求参数不会被篡改,请求的数据是否已超时,数据是否重复提交等. 接口签名示意图 客户端提交请求时,将以下参数按照约定签名方式进行签名,随后将参数和签名一同提交服务端: 1.请求头部分(header) appid:针对不同的调用方分配不同的appid. noce:请求的流水号,防止重复提交. timestamp:请求时间戳,验证请求是否已超时失效. 2.数据部分 Path:按照path中的参数将所有key=value进行拼接. Query:按照所有key=va

  • SpringBoot结合Redis实现接口幂等性的示例代码

    目录 介绍 实现过程 引入 maven 依赖 spring 配置文件写入 引入 Redis 自定义注解 token 的创建和实现 拦截器的配置 测试用例 介绍 幂等性的概念是,任意多次执行所产生的影响都与一次执行产生的影响相同,按照这个含义,最终的解释是对数据库的影响只能是一次性的,不能重复处理.手段如下 数据库建立唯一索引 token机制 悲观锁或者是乐观锁 先查询后判断 小小主要带你们介绍Redis实现自动幂等性.其原理如下图所示. 实现过程 引入 maven 依赖 <dependency>

  • ASP.NET MVC4异步聊天室的示例代码

    本文介绍了ASP.NET MVC4异步聊天室的示例代码,分享给大家,具体如下: 类图: Domain层 IChatRoom.cs using System; using System.Collections.Generic; namespace MvcAsyncChat.Domain { public interface IChatRoom { void AddMessage(string message); void AddParticipant(string name); void GetM

  • python统计mysql数据量变化并调用接口告警的示例代码

    统计每天的数据量变化,数据量变动超过一定范围时,进行告警.告警通过把对应的参数传递至相应接口. python程序如下 #!/usr/bin/python # coding=utf-8 import pymysql as mdb import os import sys import requests import json tar_conn = mdb.connect(host='192.168.56.128',port=3306,user='xxx',passwd='xxx123',db='b

随机推荐