C#调用js库的方法

前言

用.net6开发一个Winform程序,处理Excel文件,并把结果导出Excel文件。
要用到两个算法,一是turf.js库的booleanPointInPolygon方法,判断经纬度坐标是否在区域内;二是经纬度纠偏算法,因为对方给的区域坐标集合有偏移,需要纠偏。
这两个算法,网上找C#的实现,一是不好找;二是找来的不信任,我还要测试以确保没有问题。我之前做电子地图使用过turf.js库和js版本的纠偏算法,比较信任,确定没有问题。
所以我就打算通过C#调用js库的方法,来实现数据处理。

安装ClearScript

ClearScript是微软开源的js引擎,支持windows、linux、mac。
NuGet搜索安装:
Microsoft.ClearScript.Core
Microsoft.ClearScript.V8
Microsoft.ClearScript.V8.Native.win-x64

引入js文件


把leaflet.mapCorrection.js、turf.v6.5.0.min.js和自己写的calc.js放入工程中,右击属性设置复制到输出目录:如果较新则复制。
calc.js通过调用leaflet.mapCorrection.js和turf.v6.5.0.min.js中的方法实现功能,文件内容如下:

function calc(lng, lat, polygonStr) {
    var point = turf.point([lng, lat]);
    var polygonPoints = JSON.parse(polygonStr);
    var polygon = turf.polygon(polygonPoints);

    var bl = turf.booleanPointInPolygon(point, polygon);
    return bl;
}

function correct(lng, lat) {
    var newPoint = new CoordConvertor().gcj02_To_gps84(lng, lat);
    return newPoint;
}

创建V8ScriptEngine对象

private V8ScriptEngine _engine = new V8ScriptEngine();

通过js引擎加载js文件

在Form1_Load方法中添加如下代码:

_engine.AddHostType("Console", typeof(Console));
string fileName = AppDomain.CurrentDomain.BaseDirectory + "turf.v6.5.0.min.js";
string js;
using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read))
{
    byte[] bArr = new byte[fs.Length];
    await fs.ReadAsync(bArr, 0, bArr.Length);
    js = ASCIIEncoding.UTF8.GetString(bArr);
}
_engine.Execute(js);
fileName = AppDomain.CurrentDomain.BaseDirectory + "calc.js";
using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read))
{
    byte[] bArr = new byte[fs.Length];
    await fs.ReadAsync(bArr, 0, bArr.Length);
    js = ASCIIEncoding.UTF8.GetString(bArr);
}
_engine.Execute(js);
fileName = AppDomain.CurrentDomain.BaseDirectory + "leaflet.mapCorrection.js";
using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read))
{
    byte[] bArr = new byte[fs.Length];
    await fs.ReadAsync(bArr, 0, bArr.Length);
    js = ASCIIEncoding.UTF8.GetString(bArr);
}
_engine.Execute(js);

C#调用js方法实现经纬度坐标纠偏

double lng = Convert.ToDouble(lnglat[0]);
double lat = Convert.ToDouble(lnglat[1]);

//坐标纠偏
dynamic newPoint = _engine.Invoke("correct", new object[] { lng, lat });
lng = newPoint.lng;
lat = newPoint.lat;

C#调用js方法判断经纬度点位是否在多边形内

//_selectedRegionPoints是多边形坐标点位集合json字符串
bool bl = (bool)_engine.Invoke("calc", new object[] { lng, lat, _selectedRegionPoints });

程序开发完成后发布


发布后文件夹拷贝到用户的win10系统中可以直接使用,不需要安装.net6环境。我自己的很老的win7 sp1虚拟机上跑不起来,ClearScriptV8.win-x64.dll无法加载成功,暂不知道为什么。

Form1.cs完整代码如下:

当时程序写的急,当然,程序还可以优化,不过没必要,要处理的数据量不大,功能没问题就行。

using Models;
using Newtonsoft.Json;
using System.Drawing;
using System.Text;
using System.Text.RegularExpressions;
using Microsoft.ClearScript.JavaScript;
using Microsoft.ClearScript.V8;
using NPOI.HSSF.UserModel;
using NPOI.XSSF.UserModel;
using NPOI.SS.UserModel;
using System.Reflection;
using System.Windows.Forms;
using NPOI.Util;

namespace 点位
{
    public partial class Form1 : Form
    {
        private Regions _regions;
        private List<CameraInfo> _cameraList = new List<CameraInfo>();
        private V8ScriptEngine _engine = new V8ScriptEngine();
        private string _selectedRegionPoints;

        public Form1()
        {
            InitializeComponent();
        }

        private async void Form1_Load(object sender, EventArgs e)
        {
            //通过js引擎加载js文件
            _engine.AddHostType("Console", typeof(Console));
            string fileName = AppDomain.CurrentDomain.BaseDirectory + "turf.v6.5.0.min.js";
            string js;
            using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read))
            {
                byte[] bArr = new byte[fs.Length];
                await fs.ReadAsync(bArr, 0, bArr.Length);
                js = ASCIIEncoding.UTF8.GetString(bArr);
            }
            _engine.Execute(js);
            fileName = AppDomain.CurrentDomain.BaseDirectory + "calc.js";
            using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read))
            {
                byte[] bArr = new byte[fs.Length];
                await fs.ReadAsync(bArr, 0, bArr.Length);
                js = ASCIIEncoding.UTF8.GetString(bArr);
            }
            _engine.Execute(js);
            fileName = AppDomain.CurrentDomain.BaseDirectory + "leaflet.mapCorrection.js";
            using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read))
            {
                byte[] bArr = new byte[fs.Length];
                await fs.ReadAsync(bArr, 0, bArr.Length);
                js = ASCIIEncoding.UTF8.GetString(bArr);
            }
            _engine.Execute(js);

            //行政区划下拉列表初始化
            fileName = AppDomain.CurrentDomain.BaseDirectory + "安徽.json";
            using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read))
            {
                byte[] bArr = new byte[fs.Length];
                await fs.ReadAsync(bArr, 0, bArr.Length);
                string json = ASCIIEncoding.UTF8.GetString(bArr);
                _regions = JsonConvert.DeserializeObject<Regions>(json);
            }

            List<Records> citys = _regions.RECORDS.ToList().FindAll(a => a.civilcode.Length == 4);
            cbxCity.DataSource = citys;
            cbxCity.DisplayMember = "civilname";
            cbxCity.ValueMember = "civilcode";
        }

        private void button1_Click(object sender, EventArgs e)
        {
            openFileDialog1.Title = "选择要处理的Excel文件";
            openFileDialog1.Filter = "Excel文件(*.xlsx)|*.xlsx";
            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                using (FileStream fs = new FileStream(openFileDialog1.FileName, FileMode.Open, FileAccess.Read, FileShare.Read))
                {

                }
            }
        }


        private void cbxCity_SelectedIndexChanged(object sender, EventArgs e)
        {
            Records record = cbxCity.SelectedItem as Records;
            List<Records> citys = _regions.RECORDS.ToList().FindAll(a => a.civilcode.Length > 4 && a.civilcode.Substring(0, 4) == record.civilcode);
            citys.Insert(0, new Records() { civilcode = null, civilname = "==请选择==" });
            cbxCounty.DataSource = citys;
            cbxCounty.DisplayMember = "civilname";
            cbxCounty.ValueMember = "civilcode";
        }

        private void cbxCounty_SelectedIndexChanged(object sender, EventArgs e)
        {
            Records record = cbxCounty.SelectedItem as Records;
            if (record.civilcode == null)
            {
                record = cbxCity.SelectedItem as Records;
            }
            Regex regex = new Regex(@"^POLYGON\((\(.*\),?)*\)$");
            var mc = regex.Matches(record.polygongeo);
            StringBuilder sb = new StringBuilder();
            foreach (Match m in mc)
            {
                string value = m.Groups[1].Value.TrimStart('(').TrimEnd(')');
                string[] lnglatArr = value.Split(',');
                bool first = true;
                if (sb.Length > 0)
                {
                    sb.Append(",");
                }
                sb.Append("[[");
                foreach (string lnglatStr in lnglatArr)
                {
                    string[] lnglat = lnglatStr.Trim().Split(' ');
                    double lng = Convert.ToDouble(lnglat[0]);
                    double lat = Convert.ToDouble(lnglat[1]);

                    //坐标纠偏
                    dynamic newPoint = _engine.Invoke("correct", new object[] { lng, lat });
                    lng = newPoint.lng;
                    lat = newPoint.lat;

                    if (first)
                    {
                        first = false;
                        sb.AppendFormat($"[{lng}, {lat}]");
                    }
                    else
                    {
                        sb.AppendFormat($",[{lng}, {lat}]");
                    }
                }
                sb.Append("]]");
            }
            _selectedRegionPoints = sb.ToString();
        }

        private async void openFileDialog1_FileOk(object sender, System.ComponentModel.CancelEventArgs e)
        {
            await Task.Delay(10);

            //读取Excel
            _cameraList = new List<CameraInfo>();
            using (FileStream fs = new FileStream(openFileDialog1.FileName, FileMode.Open, FileAccess.Read, FileShare.Read))
            {
                XSSFWorkbook workbook = new XSSFWorkbook(fs);
                ISheet sheet = workbook.GetSheetAt(0);
                for (int i = 1; i <= sheet.LastRowNum; i++)
                {
                    IRow row = sheet.GetRow(i);
                    CameraInfo cameraInfo = new CameraInfo();
                    cameraInfo.CameraNo = row.GetCell(1).StringCellValue.Trim();
                    cameraInfo.City = row.GetCell(2).StringCellValue.Trim();
                    cameraInfo.County = row.GetCell(3).StringCellValue.Trim();
                    cameraInfo.CameraName = row.GetCell(4).StringCellValue.Trim();
                    cameraInfo.Lng = row.GetCell(5).StringCellValue.Trim();
                    cameraInfo.Lat = row.GetCell(6).StringCellValue.Trim();
                    cameraInfo.CameraFunType = row.GetCell(7).StringCellValue.Trim();
                    cameraInfo.Region = row.GetCell(8).StringCellValue.Trim();
                    cameraInfo.Type = row.GetCell(9).StringCellValue.Trim();
                    cameraInfo.Status = row.GetCell(10).StringCellValue.Trim();
                    cameraInfo.Mac = row.GetCell(11).StringCellValue.Trim();
                    cameraInfo.Ip = row.GetCell(12).StringCellValue.Trim();
                    _cameraList.Add(cameraInfo);
                }
            }

            //过滤数据
            _cameraList = _cameraList.FindAll(cameraInfo =>
            {
                if (!string.IsNullOrWhiteSpace(cameraInfo.Lng) && !string.IsNullOrWhiteSpace(cameraInfo.Lat))
                {
                    double lng = Convert.ToDouble(cameraInfo.Lng);
                    double lat = Convert.ToDouble(cameraInfo.Lat);
                    bool bl = (bool)_engine.Invoke("calc", new object[] { lng, lat, _selectedRegionPoints });
                    if (bl) //区域内
                    {
                        return false;
                    }
                    else //区域外
                    {
                        return true;
                    }
                }
                else
                {
                    return false;
                }
            });

            saveFileDialog1.Title = "选择处理结果要保存的位置及文件名";
            saveFileDialog1.Filter = "Excel文件(*.xlsx)|*.xlsx";
            if (saveFileDialog1.ShowDialog() == DialogResult.OK)
            {
                if (File.Exists(saveFileDialog1.FileName))
                {
                    File.Delete(saveFileDialog1.FileName);
                }
                string template = AppDomain.CurrentDomain.BaseDirectory + "点位模板.xlsx";
                XSSFWorkbook workbook;
                using (FileStream fs = new FileStream(template, FileMode.Open, FileAccess.Read, FileShare.Read))
                {
                    workbook = new XSSFWorkbook(fs);

                    using (FileStream fs2 = new FileStream(saveFileDialog1.FileName, FileMode.OpenOrCreate, FileAccess.ReadWrite))
                    {
                        ISheet sheet = workbook.GetSheetAt(0);
                        sheet.RemoveRow(sheet.GetRow(1));
                        sheet.RemoveRow(sheet.GetRow(2));
                        Dictionary<int, ICellStyle> cellStyles = GetCellStyles(sheet);
                        int i = 1;
                        foreach (CameraInfo cameraInfo in _cameraList)
                        {
                            IRow row = sheet.CreateRow(i);
                            ICell cell1 = row.CreateCell(1, CellType.String);
                            ICell cell2 = row.CreateCell(2, CellType.String);
                            ICell cell3 = row.CreateCell(3, CellType.String);
                            ICell cell4 = row.CreateCell(4, CellType.String);
                            ICell cell5 = row.CreateCell(5, CellType.String);
                            ICell cell6 = row.CreateCell(6, CellType.String);
                            ICell cell7 = row.CreateCell(7, CellType.String);
                            ICell cell8 = row.CreateCell(8, CellType.String);
                            ICell cell9 = row.CreateCell(9, CellType.String);
                            ICell cell10 = row.CreateCell(10, CellType.String);
                            ICell cell11 = row.CreateCell(11, CellType.String);
                            ICell cell12 = row.CreateCell(12, CellType.String);
                            SetCellStyles(row, cellStyles);
                            cell1.SetCellValue(cameraInfo.CameraNo);
                            cell2.SetCellValue(cameraInfo.City);
                            cell3.SetCellValue(cameraInfo.County);
                            cell4.SetCellValue(cameraInfo.CameraName);
                            cell5.SetCellValue(cameraInfo.Lng);
                            cell6.SetCellValue(cameraInfo.Lat);
                            cell7.SetCellValue(cameraInfo.CameraFunType);
                            cell8.SetCellValue(cameraInfo.Region);
                            cell9.SetCellValue(cameraInfo.Type);
                            cell10.SetCellValue(cameraInfo.Status);
                            cell11.SetCellValue(cameraInfo.Mac);
                            cell12.SetCellValue(cameraInfo.Ip);
                            i++;
                        }
                        workbook.Write(fs2);
                    }
                    MessageBox.Show("完成");
                }
            }
        }

        private Dictionary<int, ICellStyle> GetCellStyles(ISheet sheet)
        {
            var styleRow = sheet.GetRow(5);
            Dictionary<int, ICellStyle> result = new Dictionary<int, ICellStyle>();
            for (int i = 1; i <= 12; i++)
            {
                result.Add(i, styleRow.GetCell(i).CellStyle);
            }
            return result;
        }

        private void SetCellStyles(IRow row, Dictionary<int, ICellStyle> styles)
        {
            for (int i = 1; i <= 12; i++)
            {
                row.GetCell(i).CellStyle = styles[i];
            }
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            _engine.Dispose();
        }

        private void button2_Click(object sender, EventArgs e)
        {
            folderBrowserDialog1.Description = "选择模板文件保存位置";
            if (folderBrowserDialog1.ShowDialog() == DialogResult.OK)
            {
                string template = AppDomain.CurrentDomain.BaseDirectory + "点位模板.xlsx";
                string filePath = Path.Combine(folderBrowserDialog1.SelectedPath, "点位模板.xlsx");
                if (File.Exists(filePath))
                {
                    if (MessageBox.Show("模板文件已存在,是否覆盖?", "提示", MessageBoxButtons.OKCancel) == DialogResult.OK)
                    {
                        File.Copy(template, filePath, true);
                        MessageBox.Show("下载完成");
                    }
                }
                else
                {
                    File.Copy(template, filePath, true);
                    MessageBox.Show("下载完成");
                }
            }
        }
    }
}
本文转载于网络 如有侵权请联系删除

相关文章

  • STM32F103C8T6最小系统

    大家好,又见面了,我是你们的朋友全栈君。单片机最小系统一般有晶振电路、电源电路、复位电路以及调试电路组成1.电源电路主要有两部分组成:供电电路可以使用普通的USB接口电路,5V电源输出 降压电路 USB的5V输入,然后输出为3.3V 这里使用两种不同的电容。输入滤波电容的作用: 输入电压,当接入电源,其幅值是从零起始的,波动非常大,加入足够容量的电容进行滤波后,因电容的充放电效应,该脉动直流变成纹波不大的直流电,这是输入滤波的作用。输出滤波电容的作用: 稳压电路的工作过程需要从输出采样,然后根据其反馈值调节输出以达稳压的目的。如果此时没有输出滤波电容,只要因负载变化带来的电压波动频率恰好与稳压电路的调节速率差不多就会产生振荡效应,导致输出失控,所以稳压输出也必须加滤波电容,而且增加滤波电容也可以进一步增加稳压输出的稳定性。大电容和小电容并联的作用: 至于与大容量电解电容并联的小电容,其作用在于旁路频率较高的波动电压,因为铝电解电容的制造工艺导致其具有较大的ESL(等效电感),无法滤除高频成份,故需加个小电容。2.晶振电路晶振电路用来给芯片提供时钟信号,原理图如下: 需要注意的是:画

  • C++ seekg()函数「建议收藏」

    大家好,又见面了,我是你们的朋友全栈君。seekg()是对输入流的操作g是get缩写 seekp()是对输出流的操作p是put缩写seekg() Movesthereadpositioninastream.//移动在流中读的位置 ------------------------------------------------------------------------ basic_istream<Elem,Tr>&seekg(//一个参数 pos_typepos ); basic_istream<Elem,Tr>&seekg( off_typeoff,//两个参数 ios_base::seekdirway ); ------------------------------------------------------------------------ 参数 pos Theabsolutepositioninwhichtomovethereadpointer. //移动读取指针的绝对位置 off//偏移量 Anoffsettomoveth

  • Kafka 与 RabbitMQ 如何选择使用哪个?

    文章目录:前言如何选择?开发语言延迟队列消息顺序性优先级队列消息留存消息过滤可伸缩行小结推荐阅读前言我们在工作中经常会用到异步消息,主要使用两种消息模式:消息队列发布/订阅消息队列:多个生产者可以向同一个消息队列发送消息,但是一个消息只能被一个消费者消费。发布/订阅:一个消息可以被多个订阅者并发的获取和处理。Kafka和RabbitMQ都能满足如上的特性,那么我们应该如何选择使用哪一个?这两个MQ有什么差异性?在什么样的场景下适合使用Kafka,什么场景下适合使用RabbitMQ?你是否有这样的疑惑?希望这篇文章能够帮助到你。如何选择?开发语言Kafka:Scala,支持自定义的协议。RabbitMQ:Erlang,支持AMQP、MQTT、STOMP等协议。延迟队列如果你有以下这样的需求场景:生成订单60秒后,给用户发短信。用户7天未登录给用户做召回推送。下单15分钟后,未进行付款就关闭订单。请选择RabbitMQ,官方已提供延迟队列插件(x-delayed-message),开箱即用。消息顺序性如果你的需求场景是需要保证消息是有序的,例如:传递的消息是MySQLbinlog,这种消息

  • Kubernetes 原生 CI/CD 构建框架 Argo 详解!

    流水线(Pipeline)是把一个重复的过程分解为若干个子过程,使每个子过程与其他子过程并行进行的技术。本文主要介绍了诞生于云原生时代的流水线框架Argo。K8sMeetup什么是流水线?在计算机中,流水线是把一个重复的过程分解为若干个子过程,使每个子过程与其他子过程并行进行的技术,也叫Pipeline。由于这种s工作方式与工厂中的生产流水线十分相似,因此也被称为流水线技术。从本质上讲,流水线技术是一种时间并行技术。以“构建镜像”过程为例:在每一次构建镜像中,我们都需要拉下代码仓库中的代码,进行代码编译,构建镜像,最后推往镜像仓库。在每一次代码更改过后,这一过程都是不变的。使用流水线工具可以极大的提升这一过程的效率,只需要进行简单的配置便可以轻松的完成重复性的工作。这样的过程也被称之为CI。上图流程中使用的是Jenkins。Jenkins作为老牌流水线框架被大家所熟知。在云原生时代,Jenkins推出了JenkinsX作为基于Kubernetes的新一代流水线,另外云原生时代还诞生了两大流水线框架——Argo和Tekton。本文就详细介绍了Argo的相关内容。《Kubernetes原生

  • Android NavigationView头部设置监听事件

    NavigationView头部设置监听事件的方法,供大家参考,具体内容如下1、将XML里的静态引入删除:<android.support.design.widget.NavigationView android:id="@+id/nav_view" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravity="start"/ <!--删除下面两行-- <!--app:headerLayout="@layout/nav_header"-- <!--app:menu="@menu/nav_menu"--复制2、在代码里findViewById找到NavigationView,然后引入Header和Menu,再获取头部布局,最后设置监听事件://findviewbyid navigationView=(Navigati

  • ccnp第3讲之笔记 (eigrp)

    一、eigrp是高级的距离矢量协议。eigrp传送的是路由条目,但是接受到了路由条目的路由器并不会马上将条目加入路由表,而是根据接受到的所有路由条目构建一个全网拓扑,然后在计算出最佳路由,再将这个最佳路由放入路由表。eigrp只支持增量更新。路由只传一次,之后稳定了下来,只传增量更新。eigrp是唯一的支持非等价负载均衡的协议。二、eigrp的三张表A、邻居表B、拓扑表C、路由表三、EIGRP的度量值带宽、延迟、可靠性、负载。带宽:所有网段的最小值延迟:所有网段的汇总可靠性:所有网段的最小值负载:所有网段的最大值四、EIGRP常用命令no autosummaryeigrp router-id最大环回口地址show ip protocolsshow ip eigrp interfaceshow ip eigrp neighbors五、实验:EIGRP的等价负载均衡实现R1有到R5的2条等价路由。1、基本配置完成后,查看R1路由 1.0.0.0/24issubnetted,1subnets C   1.1.1.0isdirectlyconnected,Loopback0 5.0.0.0/2

  • Galera Cluster for MySQL 详解(四)——性能测试

    版权声明:本文为博主原创文章,遵循CC4.0BY-SA版权协议,转载请附上原文出处链接和本声明。本文链接:https://blog.csdn.net/wzy0623/article/details/102840342本篇使用tpcc-mysql压测工具对实验环境的三节点Galera集群进行一系列性能测试。一、测试目标验证Galera的同步复制,检查是否存在复制延迟。对比Galera与MySQL组复制的每秒事务数(TPS)。验证多线程复制对Galera性能的影响。验证流控对Galera性能的影响。二、测试规划这里采用与MySQL组复制性能测试相同的环境和方法,但组复制与Galera使用的MySQL版本不同。组复制测试用的是MySQL8.0.16版本,而Galera测试用的是GaleraClusterforMySQL5.7。之所以版本不同,是因为我在测试时使用的都是当时的最新版本。节点1:172.16.1.125 节点2:172.16.1.126 节点3:172.16.1.127具体思路与环境参见https://cloud.tencent.com/developer/article/148

  • 这简历一看就是包装过的

    作者:Coody来源:my.oschina.net/hooker/blog/3014656前言上到职场干将下到职场萌新,都会接触到包装简历这个词语。当你简历投到心仪的公司,公司内负责求职的工作人员是如何甄别简历的包装程度的?Coody老师根据自己的经验写下了这篇文章,谁都不是天才,包装无可厚非,切勿对号入座!正文在互联网极速膨胀的社会背景下,各行各业涌入互联网的IT民工日益增大。早在2016年,我司发布了Java、Ios工程师的招聘信息,就Java工程师单个岗位而言,日收简历近200份,Ios日收简历近一千份。没错,这就是当年培训机构对Ios工程师这个岗位发起的市场讨伐。而随着近几年的发展,市场供大于求现象日益严重。人员摸底成为用人单位对人才考核的重大难题。笔者初次与求职者以面试的形式进行沟通是2015年6月。由于当时笔者从业时间短,经验不够丰富,错过了一些优秀的求职者。三年后的,今天,笔者再次因公司规模扩大而深入与求职者进行沟通。1.初选如何鉴别劣质简历培训机构除了提供技术培训,往往还提供简历编写指导、面试指导。很多潜移默化的东西,我们很难甄别。但培训机构包装的简历,存在千遍一律的特

  • 基于容器技术的平台化SaaS软件设计与实践

    关键词:Docker传统软件SaaS禅道 Docker——近几年最火的技术之一!在IaaS、PaaS等云服务提供商那里受到了很高的关注度,它的众多特性仿佛都在CI/CD、系统和运维层面,但实际上它为传统软件、SaaS软件行业带来的技术思想更有价值。本次分享的内容主要针对传统软件和SaaS软件如何借助容器技术来设计灵活、可定制、专属的SaaS服务,不但有设计思路还有解决方案,更有经验分享。

  • 考研英语-1-导学

    试卷结构1、完形填空:10分,20题,四选一,每题0.5分。2、阅读理解:A节:阅读理解,40分,20题,四选一,每题2分。B节:新题型,10分。C节:英译汉,英语一10分/英语二15分。3、写作:英语一30分,英语二25分。A节:小作文,10分,应用文,书信、告示、备忘录、报告。B节:大作文,20/15分,议论文,图画/图表作文。4、考试属性:3小时,100分,180分钟。英一、二的区别1、词汇2、语法3、阅读A节(英二的特征)a.用词比较简单。b.句子结构简单,没有那么多长难句,语法简单。c.选项设置简单。4、阅读B节,新题型。英一:三种题型选择一个。英二:两种题型选择一个。5、阅读C节,翻译英一:是5个长难句,比较难。英二:全文翻译,相对比较简单点儿。6、大作文英一:重点考图画作文,漫画照片。英二:重点考图表作文,表格数据。另外的两种题型差别不大,完型和小作文几乎一样。英二图表作文要重视。总体而言,英语一会比英语二难点。不过就写作而言,英语二会比英语一有难度,毕竟图表作文并不好写。王江涛背单词法读单词,3-5遍就行,记不得的话,就再来一轮。三大背词步骤:a.快速突破b.了解用法c

  • dubbo源码——服务提供者的服务暴露过程(一)

    一、前言最近在学习dubbo源码,故写下学习dubbo时的一些心得。。dubbo源码版本:2.6.1二、自定义标签<dubbo:xxx/>标签是Spring的自定义标签,可以查看dubbo.jar包下的META-INF->spring.handlers//file:spring.handlers http\://code.alibabatech.com/schema/dubbo=com.alibaba.dubbo.config.spring.schema.DubboNamespaceHandler复制它是通过DubboNamespaceHandler继承Spring提供的NamespaceHandlerSupport来对标签进行解析的//DubboNamespaceHandler.java publicclassDubboNamespaceHandlerextendsNamespaceHandlerSupport{ static{ Version.checkDuplicate(DubboNamespaceHandler.class); } publicvoidin

  • 面试分享系列:从现在开始,准备加入BAT!

    豌豆贴心提醒,本文阅读时间5分钟程序员是一项技术工种,个人的技术水平决定薪资。 程序员需要在面试的过程中展示自己的技术水平,通过有说服力的表现拿到自己理想的薪资。面试中,面试题是招聘方对应聘方技术水平考核的重要方式。 为了帮助大家熟悉面试题,获取面试优势,我们将会精选国内一线互联网公司的面试题目,在这个系列里进行定时分享。第一题Linux如何进行Linux分区优化?第二题Python 如何用Python来进行查询和替换一个文本字符串?答案就在下面,记得先思考再看哦!第一题答案1.将访问率比较高的几个分区放置于硬盘的边缘位置,比如/boot,/home/,/var,/tmp/,/usr和SWAP等等 2.还可以对访问率比较高的分区单独建立文件系统 3.如果硬盘空间比较大,富裕空间比较多,可以保留一些硬盘空间作为备用空间 4.如果你的系统有多快硬盘,可以是用SWAP来提高交换分区性能。 另外还有其他的优化方式,如选择合适的文件系统等等第二题答案使用sub()方法来进行查询和替换。sub方法的格式为:sub(replacement,string[,count=0]) replacement是

  • “音”你而来,“视”而可见 腾讯腾讯云开发者社区音视频技术开发实战沙龙圆满结束

    近年来,得益于移动互联网的普及和智能终端设备的广泛应用,短视频、直播、在线教学等音视频通信模式风靡大众,音视频功能为用户带来沟通便捷的同时,也启发了应用平台基于音视频功能开拓业务模式的创新思路。然而,音视频技术虽然使用便捷,但在技术开发方面却有“重重难关”要过。为破解音视频技术研发中的高门槛、重投入的痛点,4月21日,腾讯腾讯云开发者社区在京举办“‘音’你而来,‘视’而可见——音视频技术开发实战沙龙”,活动现场座无虚席,有200余名开发者参加了本次沙龙。本次活动内容由视频云行业未来趋势展开,不仅涵盖腾讯视频云产品全景,腾讯云H5语音通信QoE优化,在线音视频素材创作合法化实际应用,讲述如何结合新的行业技术,从内容的产生到内容的消费,进行闭环。还针对时下的热门:微信小程序,推出小程序音视频典型应用场景剖析,小程序音视频技术实现以及在相关行业的实际应用等课程,详细介绍小程序音视频的应用前景和技术解析。活动现场视频行业的发展,从黑白到彩色电视,从线上点播视频到直播千播大战,从连麦互动到实时音视频沟通,视频一直在解决用户信息获取的痛点。在未来娱乐的同时能否结合社交,或者满足用户认同感,获得自我

  • 区块链是什么?读懂这些就够了!

    没有区块链,比特币便虚有其名。我们来看看它的运作原理吧。区块链技术通常与比特币和其他加密货币息息相关,但这只是其功能的冰山一角。有人认为,区块链最终可以改变从医疗保健到政治的许多重要领域。无论你只是想投资比特币以太币,还是想弄清区块链到底是什么,都来对了地方。区块链不仅仅应用于比特币虽然深究其本质,区块链技术并不简单,但它的基本理念简单易懂。它实际上是一个由一个更大的组织而不是某个中心权威机构认证的数据库。区块链是一组被多人认证的记录集合,而不依赖于某个实体,比如银行或政府,它们一般在某个特定的服务器上存储数据。每个“块”呈现多条交易记录,而“链”元素将这些“块”用一个散列函数联系起来。随着记录的创建,它们被一个分布式的计算机网络加固,并与链中前一个条目配对,这样,一个区块的链就创建好了,这就是区块链。整条区块链被存储在一个庞大的计算机网络上,这意味着没有任何一个人能够管控它的历史记录。这很重要,因为它保存了链前端发生的所有事件,任何人都不能后退或改变事件,这使区块链成为一个不能轻易被篡改的公共账目,有一张内置的保护网,这是标准集中的信息数据库不可能提供的。虽然一直以来,我们都要求核心

  • 机器学习技术的重要性:达观数据亲身实践

    大数据时代里,互联网用户每天都会直接或间接使用到大数据技术的成果,直接面向用户的比如搜索引擎的排序结果,间接影响用户的比如网络游戏的流失用户预测、支付平台的欺诈交易监测等等。达观数据技术团队长期以来一直致力于钻研和积累各种大数据技术,曾获得cikm2014数据挖掘竞赛冠军,也开发过智能文本内容审核系统、作弊监测系统、用户建模系统等多个基于大数据技术的应用系统。机器学习是大数据挖掘的一大基础,本文以机器学习为切入点,将达观在大数据技术实践时的一些经验与大家分享(达观数据联合创始人纪传俊)CIKM数据挖掘竞赛获得冠军后领奖 机器学习——海量数据挖掘解决方案 互联网的海量数据不可能靠人工一个个处理,只能依靠计算机批量处理。最初的做法是人为设定好一些规则,由机器来执行。比如明确指定计算机给男性、30岁的用户推送汽车广告。很明显如此粗略的规则不会有好效果,因为对人群的定位不够精确。要提高精度必须增加对用户的特征描述。但特征一多规则就很难制定,即使定下了规则也没法根据实际情况灵活变化。机器学习可以很好的解决以上问题,从一定程度上赋予了计算机以“学习”的能力,使得千人千面成为可能。 图1面对大量的特

  • 社交平台上的桃色陷阱:僵尸网络SIREN侵袭Twitter

    近年来,越来越多的恶意攻击者盯上了各大社交媒体。这些社交平台由于使用便捷、可扩展性强、自动化程度高,受众面广泛等特性,为攻击者发起僵尸网络攻击提供了得天独厚的条件。这里的僵尸网络指的是由中央控制台控制的社交平台账户集合。这些账户均由机器控制,而非真实人类所有。这些机器账户能够形成僵尸网络,发送恶意链接,例如钓鱼广告、恶意软件、勒索软件、欺诈调查、垃圾邮件、对受害者账户进行劫持控制的恶意应用程序以及点击即收费的垃圾邮件网站等等。自今年2月起,ZeroFOX威胁研究团队调查了一个Twitter上名为SIREN的大型垃圾邮件色情僵尸网络。该僵尸网络名为SIREN(起源于希腊神话中用美妙歌声让水手迷失方向的海妖塞壬),约包含9万多个伪造的推特账号,共计发布了850万条含有恶意链接的推文,在数周内诱使网友进行了3000万次恶意点击。本文将ZeroFOX威胁研究团队发现的SIREN僵尸网络与BrianKrebs最近在KrebsOnSecurity披露的大型垃圾邮件僵尸网络联系在一起。两者使用的策略相似,即将受害者引诱到同一网络下的色情网站。SIREN僵尸网络是社交平台历史上规模最大的恶意活动之一。

  • React-diff原理及应用

    抛砖引玉React通过引入VirtualDOM的概念,极大地避免无效的Dom操作,已使我们的页面的构建效率提到了极大的提升。但是如何高效地通过对比新旧VirtualDOM来找出真正的Dom变化之处同样也决定着页面的性能,React用其特殊的diff算法解决这个问题。VirtualDOM+Reactdiff的组合极大地保障了React的性能,使其在业界有着不错的性能口碑。diff算法并非React首创,React只是对diff算法做了一个优化,但却是因为这个优化,给React带来了极大的性能提升,不禁让人感叹React创造者们的智慧!接下来我们就探究一下React的diff算法。传统diff算法在文章开头我们提到React的diff算法给React带来了极大的性能提升,而之前的Reactdiff算法是在传统diff算法上的优化。下面我们先看一下传统的diff算法是什么样子的。传统diff算法通过循环递归对节点进行依次对比,效率低下,算法复杂度达到O(n^3),其中n是树中节点的总数。O(n^3)到底有多可怕呢?这意味着如果要展示1000个节点,就要依次执行上十亿次的比较,这种指数型的性能

  • 第九章 JQUI

    一、什么是插件 ①是遵循一定接口规范编写的程序 ②是原有系统平台功能的扩展和补充 ③只能运行在规定的系统平台下,而不能单独运行 注:由于jQuery插件是基于jQuery脚本库的扩展,所以所有jQuery插件都必须依赖于jQuery基础脚本库,在加入插件时需要先引入jQuery基础脚本库,再引入插件库,一定要注意引入的先后顺序。 jQuery插件的参数一般采用的是JSON格式 二、常用插件 dialog插件:常用的对话框展现形式分为普通对话框和form对话框 常用参数:   引入jQuery-ui库:    ViewCode 实现效果:   tabs插件:  可实现丰富的选项卡效果。常用的展现形式有鼠标单击触发tab切换、鼠标移动触发tab切换 常用属性: 常用方法: 常用事件:    ViewCode 实现效果:   menu插件:  常用属性:    ViewCode 实现效果:   autocomplete插件:远程数据源实现自动完成 &nbs

  • 容斥原理(转载)

    转自:https://blog.csdn.net/m0_37286282/article/details/78869512     对容斥原理的描述 容斥原理是一种重要的组合数学方法,可以让你求解任意大小的集合,或者计算复合事件的概率。 描述        容斥原理可以描述如下:          要计算几个集合并集的大小,我们要先将所有单个集合的大小计算出来,然后减去所有两个集合相交的部分,再加回所有三个集合相交的部分,再减去所有四个集合相交的部分,依此类推,一直计算到所有集合相交的部分。 关于集合的原理公式       上述描述的公式形式可以表示如下:                  它可以写得更简洁

  • win7下虚拟机安装mac 转载自 http://itbbs.pconline.com.cn/50602805.html

    最近,不断有人问起,如何在vmware下安装MAC系统。起因是以前曾发过一篇贴,在vmware8下安装MAC的方法。于是,重新下载了最新版苹果系统10.8.5,终于成功安装。现将注意事项及过程与各位朋友共享。一、准备工作:(1)虚拟机系统:vmware workstation 10,(或vmware player),请自行在网上下载。(2)vmware的MAC补丁包。如果你使用的是vmware10,请下载补丁包V1.20,如果是vmware8或9,请下载补丁包V1.10。补丁包120是卡饭论坛中的网友hpmlo提供的。(3)苹果最新版操作系统OS X Mountain Lion,下载地址:http://kuai.xunlei.com/d/dBhJEAIdmABxhjZS8e7二、安装软件(这一部分是关键,过了这一关,后边安装就很简单了)由于此前大家常用的mac补丁unlock 110,在vmware 10下无法使用,故此需要使用unlock 120来打补丁。所以,在使用补丁前,请注意查看自己使用的

  • Oracle 19c自启动

    Oracle19c自启动1、root用户修改/etc/oratab,将上面的N改为Yvi/etc/oratabora19c:/u01/app/oracle/product/19.3.0/db_1:Y 2、root用户修改chmod777/etc/rc.d/rc.localvi/etc/rc.d/rc.local 添加#fororaclesu-oracle-lc'lsnrctlstart'su-oracle-lc'dbstart' 2、oracle用户修改su-oracle记录下面路径cd$ORACLE_HOME/binpwd vidbstart\$1会使后面的字母格式变乱,可以在\$前面加一个斜杠\就不会出现字母格式混乱了修改#ORACLE_HOME_LISTNER=\$1为ORACLE_HOME_LISTNER=$ORACLE_HOME vidbshut修改#ORACLE_HOME_LISTNER=\$1为ORACLE_HOME_LISTNER=$ORACLE_HOME 4.重启,测试成功reboot或init6 注意:su-oracle-lc'lsnrctlstart' -l表示同

相关推荐

推荐阅读