.NET开发过程中的全文索引使用技巧之Solr

    前言:相信许多人都听说过.net开发过程中基于Lucene.net实现的全文索引,而Solr是一个高性能,基于Lucene的全文搜索服务器。同时对其进行了扩展,提供了比Lucene更为丰富的查询语言,同时实现了可配置、可扩展并对查询性能进行了优化,并且提供了一个完善的功能管理界面,是一款非常优秀的全文搜索引引擎,这里我就绕过Lucene,直接说Solr的应用了,总之,Solr比Lucene更加方便简洁好用,而且上手快,开发效率高。

   Solr应用场景:涉及到大数据的全文搜索。尤其是电子商务平台还有现在流行的云计算,物联网等都是需要强大的数据量作为支撑的,使用Solr来进行数据检索最合适不过了,而且Solr是免费开源的,门槛低、投资少见效快。关于Solr的一些优点我这里就不在累赘陈述了,园子里也有很多大神也写了很多关于Solr的技术博文,我这里也只是抛砖引玉,见笑了。

   好了,这里就开始Solr的奇幻之旅吧

 

基于.NET平台下的Solr开发步骤

一、搭建Solr服务器,具体步骤如下:

   1.安装JDK,因为是.NET平台,不需要安装JRE、JAVA虚拟机,只安装JDK即可,而且安装JDK不需要手动去配置环境变量,它会自动帮我们配置好环境变量,很方便,这里我安装的是jdk1.7,官网地址:http://www.oracle.com/technetwork/java/javase/downloads/index.html

   2.安装Tomcat8.0,官网地址:http://tomcat.apache.org/download-80.cgi,安装完成后启动Monitor Tomcat,浏览器地址栏输入http://localhost:8080/,能进入说明安装成功

   3.下载Solr,这里我用的是Solr4.4版本,下载后进行下列配置

  (1)解压Solr4.4,创建Solr目录,比如D:/SorlServer/one,将解压后的Solr4.4中的example目录下的Solr文件夹中的所有文件拷贝到创建的目录中

  (2)创建Solr Web应用,具体步骤,将解压后的Solr4.4中的dist目录下的Solr-4.4.0.war文件拷贝到Tomcat下,比如C:\Program Files\Apache Software Foundation\Tomcat 7.0\webapps下,重命名为one.war,启动Tomcat后该文件会自动解压,进入到D:\SorlServer\one\collection1\conf下,打开solrconfig.xml文件,找到 <dataDir>节点改为<dataDir>${solr.data.dir:c:/SorlServer/one/data}</dataDir>

注意:这一步很重要:打开C:\Program Files\Apache Software Foundation\Tomcat 7.0\webapps\One\WEB-INF下的web.xml文件,找到<env-entry>节点开启

env-entry-value值改为D:/SorlServer/one,如下:

<env-entry>       

      <env-entry-name>solr/home</env-entry-name>

      <env-entry-value>D:/SorlServer/one</env-entry-value>

      <env-entry-type>java.lang.String</env-entry-type>

 </env-entry>

   (3)将解压后的Solr4.4下的/dist/solrj-lib目录中的所有jar包拷贝到C:\Program Files\Apache Software Foundation\Tomcat 7.0\lib

  (4)停止Tomcat,然后再启动,访问http://localhost:8080/one,即可打开

注意:如果是开发英文网站,我们就不需要使用第三方的分词配置,Solr本身就内置支持英文分词,如果是其他语种比如小语种(日语、意大利、法语等等),大家可以去网上找相关的分词包,这里我们以中文分词为例,毕竟国内大部分网站都是中文为主的。

   4.配置中文分词,国内常用的分词器(庖丁解牛、mmseg4j、IKAnalyzer),这里我用的是IKAnalyzer,这个分词器比较活跃而且更新也快,挺好用的,具体步骤如下:

   (1)IKAnalyzerjar包以及IKAnalyzer.cfg.xml都复制到C:\Program Files\Apache Software Foundation\Tomcat 7.0\webapps\one\WEB-INF\lib

   (2)配置D:\SorlServer\one\collection1\conf下的schema.xml,添加如下配置:

      <!-- 分词配置 -->

 <fieldType name="text_IKFENCHI" class="solr.TextField"> 

     <analyzer class="org.wltea.analyzer.lucene.IKAnalyzer"/>

 </fieldType>

    (3)停止Tomcat,然后再启动,访问http://localhost:8080/one/#/collection1/analysis,即可进行测试

    以上是Solr服务器端的相关配置工作

二、开始基于.NET平台的Solr开发:

   1.下载Solr客户端组件,我用的是园子里的Terry大哥的EasyNet.Solr,地址在微软开源站:http://easynet.codeplex.com/,

Terry大哥已经把solr客户端封装的很完善了,里面封装了很多现成的方法和参数配置,我们直接可以拿过来用,利用Easynet.solr创建索引,然后再查询索引,具体使用方法如下:

  (1)下载EasyNet.Solr源码直接放到项目中,也可以将源码生成Dll组件后添加到项目引用进行使用,把源码放到项目中最好不过了,我们也可以对其进行调整来满足自己的需要

  (2)创建索引实体类,就是我们要保存的索引数据,比如创建一个产品实体类   

using System;
using System.Collections.Generic;namespace Seek.SearchIndex
{public partial class IndexProductModel{public IndexProductModel(){}#region  Propertiespublic int ID { get; set; }public int ProductID { get; set; }public string ClassPath { get; set; }public int ClassID1 { get; set; }public int ClassID2 { get; set; }public int ClassID3 { get; set; }public string Title { get; set; }public string Model { get; set; }public string PriceRange { get; set; }public string AttributeValues { get; set; }public string ProductImages { get; set; }public int MemberID { get; set; }public System.DateTime CreateDate { get; set; }public System.DateTime LastEditDate { get; set; }public string FileName { get; set; }public string ProductType { get; set; }public string Summary { get; set; }public string Details { get; set; }public string RelatedKeywords { get; set; }public int MemberGrade { get; set; }#endregion}
}
View Code

  (3)配置Solr服务器端的xml,就是将咱们的这个索引实体类配置到Solr服务器上,进入D:\SorlServer\one\collection1\conf,打开schema.xml文件,配置如下

 <field name="ID" type="string" indexed="true" stored="true" required="true" multiValued="false" /> <field name="ProductID" type="int" indexed="true" stored="true"/><!-- 快速高亮配置 termVectors="true" termPositions="true"  termOffsets="true" --><field name="Title" type="text_en_splitting" indexed="true" stored="true" termVectors="true" termPositions="true"  termOffsets="true"/><field name="Model" type="text_en_splitting" indexed="true" stored="true" termVectors="true" termPositions="true"  termOffsets="true"/><field name="ClassPath" type="string" indexed="true" stored="true"/><field name="ClassID1" type="int" indexed="true" stored="true"/><field name="ClassID2" type="int" indexed="true" stored="true"/><field name="ClassID3" type="int" indexed="true" stored="true"/><field name="PriceRange" type="string" indexed="true" stored="true"/><field name="AttributeValues" type="string" indexed="true" stored="true"/><field name="ProductImages" type="string" indexed="true" stored="true"/><field name="MemberID" type="int" indexed="true" stored="true"/><field name="CreateDate" type="date" indexed="true" stored="true"/><field name="LastEditDate" type="date" indexed="true" stored="true"/><field name="FileName" type="string" indexed="true" stored="true"/><field name="ProductType" type="string" indexed="true" stored="true"/><field name="Summary" type="string" indexed="true" stored="false"/><field name="Details" type="string" indexed="true" stored="false"/><field name="RelatedKeywords" type="string" indexed="true" stored="true"/><field name="MemberType" type="string" indexed="true" stored="true"/><field name="MemberGrade" type="int" indexed="true" stored="true"/>
View Code

  (4)开始创建索引,最好能写一个生成索引的客户端程序,我这里提供一下自己的索引器关键代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Seek.SearchIndex;
using System.Data;
using System.Threading;
using System.Configuration;
using System.Reflection;
using EasyNet.Solr;
using EasyNet.Solr.Impl;
using EasyNet.Solr.Commons;
using System.Xml.Linq;
using EasyNet.Solr.Commons.Params;
using System.Threading.Tasks;namespace Seek.SearchIndex
{/// <summary>/// 索引器/// </summary>public class Indexer{private readonly static OptimizeOptions optimizeOptions = new OptimizeOptions();private readonly static CommitOptions commitOptions = new CommitOptions() { SoftCommit = true };private readonly static ISolrResponseParser<NamedList, EasyNet.Solr.ResponseHeader> binaryResponseHeaderParser = new BinaryResponseHeaderParser();private readonly static IUpdateParametersConvert<NamedList> updateParametersConvert = new BinaryUpdateParametersConvert();private readonly static ISolrQueryConnection<NamedList> connection = new SolrQueryConnection<NamedList>() { ServerUrl = ConfigurationManager.AppSettings["SolrServer"] };private readonly static ISolrUpdateConnection<NamedList, NamedList> solrUpdateConnection = new SolrUpdateConnection<NamedList, NamedList>() { ServerUrl = ConfigurationManager.AppSettings["SolrServer"], ContentType = "application/javabin" };private readonly static ISolrUpdateOperations<NamedList> solr = new SolrUpdateOperations<NamedList, NamedList>(solrUpdateConnection, updateParametersConvert) { ResponseWriter = "javabin" };private readonly static ISolrQueryOperations<NamedList> solrQuery = new SolrQueryOperations<NamedList>(connection) { ResponseWriter = "javabin" };public enum State{/// <summary>/// 运行中/// </summary>
            Runing,/// <summary>/// 停止/// </summary>
            Stop,/// <summary>/// 中断/// </summary>
            Break}/// <summary>/// 窗口/// </summary>private Main form;/// <summary>/// 线程/// </summary>public Thread t;/// <summary>/// 消息状态/// </summary>public State state = State.Stop;/// <summary>/// 当前索引/// </summary>private long currentIndex = 0;public long CurrentIndex{get { return currentIndex; }set { currentIndex = value; }}private int _startId = AppCongfig.StartId;public int StartId{get { return _startId; }set { _startId = value; }}/// <summary>/// 产品总数/// </summary>private int productsCount = 0;/// <summary>/// 起始时间/// </summary>private DateTime startTime = DateTime.Now;/// <summary>/// 结束时间/// </summary>private DateTime endTime = DateTime.MinValue;private static object syncLock = new object();#region 单利模式private static Indexer instance = null;private Indexer(Main _form){form = _form;productsCount = DataAccess.GetCount(0);       //产品数统计form.fullerTsslMaxNum.Text = productsCount.ToString();form.fullerProgressBar.Minimum = 0;form.fullerProgressBar.Maximum = productsCount;}public static Indexer GetInstance(Main form){if (instance == null){lock (syncLock){if (instance == null){instance = new Indexer(form);}}}return instance;}#endregion/// <summary>/// 启动/// </summary>public void Start(){ThreadStart ts = new ThreadStart(FullerRun);t = new Thread(ts);t.Start();}/// <summary>/// 停止/// </summary>public void Stop(){state = State.Stop;}/// <summary>/// 中断/// </summary>public void Break(){state = State.Break;}/// <summary>/// 创建索引/// </summary>public void InitIndex(object data){var docs = new List<SolrInputDocument>();DataTable list = data as DataTable;foreach (DataRow pro in list.Rows){var model = new SolrInputDocument();PropertyInfo[] properites = typeof(IndexProductModel).GetProperties();//得到实体类属性的集合string[] dateFields = { "CreateDate", "LastEditDate" };string field = string.Empty;//存储fieldnameforeach (PropertyInfo propertyInfo in properites)//遍历数组
                {object val = pro[propertyInfo.Name];if (val != DBNull.Value){model.Add(propertyInfo.Name, new SolrInputField(propertyInfo.Name, val));}}docs.Add(model);StartId = Convert.ToInt32(pro["ID"]);}GetStartId();lock (syncLock){if (currentIndex <= productsCount){form.fullerProgressBar.Value = (int)currentIndex;}form.fullerTsslCurrentNum.Text = currentIndex.ToString();}var result = solr.Update("/update", new UpdateOptions() {  Docs = docs });}/// <summary>/// 创建索引/// </summary>public void CreateIndexer(DataTable dt){GetStartId();Parallel.ForEach<DataRow>(dt.AsEnumerable(), (row) =>{//从数据库查询商品详细属性if (row != null){var docs = new List<SolrInputDocument>();var model = new SolrInputDocument();PropertyInfo[] properites = typeof(IndexProductModel).GetProperties();//得到实体类属性的集合string[] dateFields = { "CreateDate", "LastEditDate" };string field = string.Empty;//存储fieldnameforeach (PropertyInfo propertyInfo in properites)//遍历数组
                    {object val = row[propertyInfo.Name];if (val != DBNull.Value){model.Add(propertyInfo.Name, new SolrInputField(propertyInfo.Name, val));}}docs.Add(model);StartId = Convert.ToInt32(row["ID"]);var result = solr.Update("/update", new UpdateOptions() { Docs = docs });}});//GetStartId();lock (syncLock){if (currentIndex <= productsCount){form.fullerProgressBar.Value = (int)currentIndex;}form.fullerTsslCurrentNum.Text = currentIndex.ToString();}}/// <summary>/// 全部索引运行/// </summary>public void FullerRun(){//GetStartId();//form.fullerTsslCurrentNum.Text = currentIndex.ToString();DataTable dt = DataAccess.GetNextProductsInfo(StartId);StartId = AppCongfig.StartId;if (state == State.Break){this.SendMesasge("完全索引已继续,起始ID[" + StartId + "]...");}else{startTime = DateTime.Now;this.SendMesasge("完全索引已启动,起始ID[" + StartId + "]...");}state = State.Runing;form.btnInitIndex.Enabled = false;form.btnSuspend.Enabled = true;form.btnStop.Enabled = true;while (dt != null && dt.Rows.Count > 0 && state == State.Runing){try{InitIndex(dt);//单线程// CreateIndexer(dt);//多线程
                }catch (Exception ex){state = State.Stop;form.btnInitIndex.Enabled = true;form.btnSuspend.Enabled = false;form.btnStop.Enabled = false;GetStartId();this.SendMesasge(ex.Message.ToString());}form.fullerTsslTimeSpan.Text = "已运行 :" + GetTimeSpanShow(DateTime.Now - startTime) + ",预计还需:" + GetTimeSpanForecast();try{dt = DataAccess.GetNextProductsInfo(StartId);//获取下一组产品
                }catch (Exception err){this.SendMesasge("获取下一组产品出错,起始ID[" + StartId + "]:" + err.Message);}}if (state == State.Runing){state = State.Stop;form.btnInitIndex.Enabled = true;form.btnSuspend.Enabled = false;form.btnStop.Enabled = false;AppCongfig.SetValue("StartId", StartId.ToString());this.SendMesasge("完全索引已完成,总计索引数[" + currentIndex + "]结束的产品Id" + StartId);}else if (state == State.Break){GetStartId();state = State.Break;form.btnInitIndex.Enabled = true;form.btnSuspend.Enabled = false;form.btnStop.Enabled = false;AppCongfig.SetValue("StartId", StartId.ToString());this.SendMesasge("完全索引已暂停,当前索引位置[" + currentIndex + "]结束的产品Id" + StartId);}else if (state == State.Stop){GetStartId();state = State.Stop;this.SendMesasge("完全索引已停止,已索引数[" + currentIndex + "]结束的产品Id" + StartId);form.btnInitIndex.Enabled = true;form.btnSuspend.Enabled = false;form.btnStop.Enabled = false;AppCongfig.SetValue("StartId", StartId.ToString());productsCount = DataAccess.GetCount(StartId);       //产品数统计form.fullerTsslMaxNum.Text = productsCount.ToString();form.fullerProgressBar.Minimum = 0;form.fullerProgressBar.Maximum = productsCount;}endTime = DateTime.Now;}/// <summary>/// 多线程构建索引数据方法/// </summary>/// <param name="threadDataParam"></param>public void MultiThreadCreateIndex(object threadDataParam){InitIndex(threadDataParam);}/// <summary>/// 获取最大的索引id/// </summary>private void GetStartId(){IDictionary<string, ICollection<string>> options = new Dictionary<string, ICollection<string>>();options[CommonParams.SORT] = new string[] { "ProductID DESC" };options[CommonParams.START] = new string[] { "0" };options[CommonParams.ROWS] = new string[] { "1" };options[HighlightParams.FIELDS] = new string[] { "ProductID" };options[CommonParams.Q] = new string[] { "*:*" };var result = solrQuery.Query("/select", null, options);var solrDocumentList = (SolrDocumentList)result.Get("response");currentIndex = solrDocumentList.NumFound;if (solrDocumentList != null && solrDocumentList.Count() > 0){StartId = (int)solrDocumentList[0]["ProductID"];//AppCongfig.SetValue("StartId", solrDocumentList[0]["ProductID"].ToString());
            }else{StartId = 0;// AppCongfig.SetValue("StartId", "0");
            }}/// <summary>/// 优化索引/// </summary>public void Optimize(){this.SendMesasge("开始优化索引,请耐心等待...");var result = solr.Update("/update", new UpdateOptions() { OptimizeOptions = optimizeOptions });var header = binaryResponseHeaderParser.Parse(result);this.SendMesasge("优化索引耗时:" + header.QTime + "毫秒");}/// <summary>/// 发送消息到界面/// </summary>/// <param name="message">发送消息到界面</param>protected void SendMesasge(string message){form.fullerDgvMessage.Rows.Add(form.fullerDgvMessage.Rows.Count + 1, message, DateTime.Now.ToString());}/// <summary>/// 获取时间间隔显示/// </summary>/// <param name="ts">时间间隔</param>/// <returns></returns>protected string GetTimeSpanShow(TimeSpan ts){string text = "";if (ts.Days > 0){text += ts.Days + "";}if (ts.Hours > 0){text += ts.Hours + "";}if (ts.Minutes > 0){text += ts.Minutes + "";}if (ts.Seconds > 0){text += ts.Seconds + "";}return text;}/// <summary>/// 获取预测时间/// </summary>/// <returns></returns>protected string GetTimeSpanForecast(){if (currentIndex != 0){TimeSpan tsed = DateTime.Now - startTime;double d = ((tsed.TotalMilliseconds / currentIndex) * productsCount) - tsed.TotalMilliseconds;return GetTimeSpanShow(TimeSpan.FromMilliseconds(d));}return "";}}
}
View Code

  (5)运行索引器,创建索引,这里是我的索引器界面,如图

   可以随时跟踪索引生成的情况

  (6)索引创建完毕后,可以进入Solr服务器界面http://localhost:8080/one/#/collection1/query进行测试

 

以上就是Solr的前期工作,主要是Solr服务器搭建和客户端调用生成索引,后期再对客户端的查询进行详细的说明,下期预告

1.全文搜索,分词配置,以及类似于谷歌和百度那种输入关键字自动完成功能

2.Facet查询

 

 

     

 

 

 

转载于:https://www.cnblogs.com/johnwood/p/3447242.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/259116.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

auto.js停止所有线程_Java线程与并发编程实践:深入理解volatile和final变量

同步有两种属性&#xff1a;互斥性和可见性。synchronized关键字与两者都有关系。Java同时也提供了一种更弱的、仅仅包含可见性的同步形式&#xff0c;并且只以volatile关键字关联。假设你自己设计了一个停止线程的机制(因为无法使用Thread不安全的stop()方法))。清单1中Thread…

项目实例改编:利用structs2的action 实时显示图片、pdf和其他内容的框架抽取。(转)...

转自&#xff1a;http://www.verydemo.com/demo_c167_i1382.html 针对&#xff1a;预览文件&#xff08;图片&#xff0c;PDF&#xff09;文件来源为action中的inputStream 重点&#xff1a; structs2的action的配置 action的写法和结果类型 resulttype的写法 网页上实…

开始Go开发之旅-Golang架构师之路系列实战

2019独角兽企业重金招聘Python工程师标准>>> 作者: gomaster.me(冯琪超) 系列:Golang架构师之路 巧妇难做无米之炊&#xff0c;golang sdk就是gopher的大米 下载golang 点击 官网下载golang sdk 根据不同系统&#xff0c;官网下载链接会选择相应的平台进行链接跳转&…

安卓9.0官方系统升级包_华为、荣耀公布可升级安卓10.0机型,你的手机在名单之内吗?...

在近两个月以前&#xff0c;美方将华为关进了小黑屋&#xff0c;随后谷歌也将华为旗下的机型移出了安卓10.0升级名单&#xff0c;这一波操作之后&#xff0c;引起了不小的“恐慌”&#xff0c;许多华为用户也在担心是否还能正常使用安卓系统服务&#xff0c;不过&#xff0c;让…

2. Mysql数据库的入门知识

2. Mysql数据库的入门知识 &#xff08;1&#xff09;打开Windows系统提供的服务查看相应的服务。 &#xff08;2&#xff09;在Windows任务管理器的进程中查看 &#xff08;3&#xff09;使用命令行管理windows的Mysql数据库服务。 Net start 服务名 Net stop 服务名 mysql -h…

nginx php-fpm 输出php错误日志(转)

nginx是一个web服务器&#xff0c;因此nginx的access日志只有对访问页面的记录&#xff0c;不会有php 的 error log信息。 nginx把对php的请求发给php-fpm fastcgi进程来处理&#xff0c;默认的php-fpm只会输出php-fpm的错误信息&#xff0c;在php-fpm的errors log里也看不到ph…

win7优化设置_win7蓝牙怎么打开?

当电脑需要连接蓝牙设备的时候&#xff0c;就需要打开蓝牙设置才行。鉴于一些win7的用户还不知道蓝牙功能在哪&#xff0c;win7蓝牙怎么打开&#xff0c;故系统圣地分享本篇教程。1、win7蓝牙怎么打开?首先要你的电脑支持蓝牙功能。如果你的电脑有蓝牙功能的话那么在电脑的右下…

Doxygen从零学起———安装和配置

Doxygen可以为多种语言生成说明文档&#xff08;从程序的源代码中提取其中按照约定格式写的注释中提取信息&#xff09; 例如C, Objective-C, C#, C, PHP, Python, IDL (Corba, Microsoft, and UNO/OpenOffice flavors), Fortran, VHDL, Tcl, D ,从这期开始&#xff0c;我将系…

Java中的ClassLoader

Java中类的加载过程&#xff08;如Dog类&#xff09;&#xff1a; 通过类型信息定位Dog.class文件。载入Dog.class文件&#xff0c;创建相应的Class对象。执行父类的静态字段定义时初始化语句和父类的静态初始化块。执行子类的静态字段定义时初始化语句和子类的静态初始化块。当…

excel删除无尽空白行_excel如何批量删除空白行 巧用 ctrl+G 只需1秒 最常用的技巧...

工作中我们使用excel通常都会遇到这种情况&#xff0c;就是表格中有很多多余的空行。我们需要把多余的空行删除。 如果空行只有一两行的话&#xff0c;可以把鼠标放在空白行上&#xff0c;然后点击鼠标右键&#xff0c;在弹出的菜单中选择删除菜单。 在弹出的删除确定窗口中&am…

DevOps的前世今生

2019独角兽企业重金招聘Python工程师标准>>> 目前在国外&#xff0c;互联网巨头如Google、Facebook、Amazon、LinkedIn、Netflix、Airbnb&#xff0c;传统软件公司如Adobe、IBM、Microsoft、SAP等&#xff0c;亦或是网络业务非核心企业如苹果、沃尔玛、索尼影视娱乐…

【转】最牛B的编码套路

最近&#xff0c;我大量阅读了Steve Yegge的文章。其中有一篇叫“Practicing Programming”&#xff08;练习编程&#xff09;&#xff0c;写成于2005年&#xff0c;读后令我惊讶不已&#xff1a; 与你所相信的恰恰相反&#xff0c;单纯地每天埋头于工作并不能算是真正意义上的…

ecshop 广告设置

最近公司准备做个商城&#xff0c;让我从JAVA转过去&#xff0c;好吧&#xff0c;先看下吧&#xff0c;反正也得做。接到手里的是一套已经成型的模板&#xff0c;但是二次开发必须得了解下机制、文件、响应、设置什么的&#xff0c;也是个新手&#xff0c;写点东西给后面更新的…

linux 信号_Linux信号机制

信号就是一条消息&#xff0c;通知进程系统中发生了什么事&#xff0c;每种信号都对应着某种系统事件。一般的底层硬件异常是由内核的异常处理程序处理的&#xff0c;它对用户进程来说是透明的。而信号机制&#xff0c;提供了一种方法通知用户进程发生了这些异常。例如&#xf…

DOxygen for C++使用说明——添加数学公式

公式 Doxygen允许你把 公式显示在最终的输出中&#xff08;这个功能仅限于HTML和输出&#xff09;.为了可以在HTML documentation显示公式&#xff08;转化为图片&#xff09;&#xff0c;你必须安装以下软件&#xff1a; latex: 编译器, 被用来解析公式, 首先提取公式写到一…

Tomcat 的 DefaultServlet

问题描述&#xff1a; 群里有人测试 Spring MVC&#xff0c;没有配置任何Controller&#xff0c;只配置了一个view resolver&#xff0c;指定了前缀后缀。 然后&#xff0c;他问的是 当访问 localhost:8080/test 的时候&#xff0c;为什么会被重定向到 localhost:8080/test/ &a…

spss练习数据_SPSS篇——如何在成千上百万个数据中标识重复个案

本文就带大家来学习一个小技巧&#xff0c;如何运用SPSS标识重复个案。我们都知道在Excel中&#xff0c;通常会用到“筛选”功能来选出指定条件相同的单元格。那么在SPSS中&#xff0c;如何在成千上百万个数据中筛选出重复的个案呢&#xff1f; 小编就是要告诉你&#xff0c;几…

DOxygen for C++使用说明——Markdown支持

自Doxygen 版本1.8.0&#xff0c;Markdown被引进。 接下来&#xff0c;我们将先简单介绍标准的Markdown语法&#xff0c;读者可以进入Markdown官网查询更详细的细节。然后讨论一下Doxygen支持的Markdown扩展&#xff0c;最后讨论一下Doxygen对Markdown标准的实现细节。 Stand…

方程式漏洞之复现window2008/win7 远程命令执行漏洞

前几天就想写的&#xff0c;因为一些缘故就没写。此次是在外网环境下进行的。大家在内网中也一个样。 方法&#xff1a; 使用Eternalblue模块&#xff0c;剑测是否有漏洞然后msf生成一个dll直接反弹shell. PS&#xff1a;win版本的不知道缘何生成出来的dll是0kb 我就在自己本地…

客服会话 小程序 如何发起_小程序、公众号、App三者如何融合布局?这里有一份避坑指南...

对产品经理来说&#xff0c;小程序无疑是2020年最火爆的词之一了。我们能看到&#xff0c;就在今年疫情期间&#xff0c;小程序DAU达到4.5亿&#xff0c;而超市、生鲜果蔬、社区购物等都同比增长100个点左右&#xff0c;小程序的商业价值很明显地在快速释放。小程序如此火爆&am…