zoukankan      html  css  js  c++  java
  • solr解决访问安全

    Tomcat7,solr3.6,mmseg1.8

    1:环境的搭建

    1:解压tomcat,solr,mmseg4j

    2:复制dist文件夹下apache-solr.war到tomcat的webapp文件夹下,修改文件名为solr(不该也行,这里修改文件名方便一会地址栏的输入)

    3:创建solr-tomcat文件夹作为solr的根目录

    4:tomcat/conf/Catalina/localhost文件夹(不存在手动创建)下创建solr.xml,文件内容如下,根据情况,修改相应的路径

    <Context docBase="E:/tomcat7/apache-tomcat-7.0.19/webapps/solr" reloadable="true" >

    <Environment name="solr/home" type="java.lang.String" value="E:/solr-tomcat" override="true" />

    </Context>

    5:复制solr解压后,example文件夹下的solr文件夹到solr-tomcat文件夹下

    6:访问http://localhost:8080/solr/,验证是否配置成功(访问后,solr-tomcat/solr文件夹下会多一个data文件夹)

    2:配置文件的说明

    1:apache-tomcat-7.0.19confCatalinalocalhostsolr.xml文件,用来配置solr的根目录,目前只用到一次

    2:E:solr-tomcatsolrsolr.xml文件,目前只看到在配置多核时用到,后面讲

    3:E:solr-tomcatsolrconfschema.xml文件(非常重要)

    <fieldType name="string" class="solr.StrField" sortMissingLast="true" />配置域的类型

    <field name="name" type="text_general" indexed="true" stored="true"/>配置域,在doc文档中的用到的field和solrj中用到的域名必须在这里配置。Index表示是否需要索引,stored是否需要存储,multiValued表示是否有多个值

    <dynamicField name="*_s" type="string" indexed="true" stored="true"/>就是动态匹配

    <copyField source="name" dest="text"/>在搜索时可以直接通过“zhang san”来搜索那么,不需要在通过“name:zhang san”来搜索

    4:E:solr-tomcatsolrconfsolrconfig.xml文件:缓存,请求的配置,索引的配置

    3:浏览器客户端的说明

    Solr->analyze:分词

    Query String:根据索引搜索时用。eg:name:zhang san可以通过name来搜索姓名是zhang san的人。如果配置了copyField也可以直接通过zhang san来搜索

    4:中文分词的配置

    1:解压mmseg4j,拷贝mmseg4j-all-1.8.5.jar到tomcatwebappsolr的lib目录下

    2:solr-tomcatsolr下创建dic文件夹,存放词库;拷贝mmseg4j下的words.dic到该目录下

    3:修改schema.xml文件,添加如下代码(注意修改路径)

    <!--mmseg4j field types-->

    <fieldType name="textComplex" class="solr.TextField" positionIncrementGap="100" >

    <analyzer>

    <tokenizer class="com.chenlb.mmseg4j.solr.MMSegTokenizerFactory" mode="complex" dicPath="E:/solr-tomcat/solr/dic"/>

    <filter class="solr.LowerCaseFilterFactory"/>

    </analyzer>

    </fieldType>

    <fieldType name="textMaxWord" class="solr.TextField" positionIncrementGap="100" >

    <analyzer>

    <tokenizer class="com.chenlb.mmseg4j.solr.MMSegTokenizerFactory" mode="max-word" dicPath="E:/solr-tomcat/solr/dic"/>

    <filter class="solr.LowerCaseFilterFactory"/>

    </analyzer>

    </fieldType>

    <fieldType name="textSimple" class="solr.TextField" positionIncrementGap="100" >

    <analyzer>

    <tokenizer class="com.chenlb.mmseg4j.solr.MMSegTokenizerFactory" mode="simple" dicPath="E:/solr-tomcat/solr/dic"/>

    <filter class="solr.LowerCaseFilterFactory"/>

    </analyzer>

    </fieldType>

    <field name="simple" type="textSimple" indexed="true" stored="true" multiValued="true"/>

    <field name="complex" type="textComplex" indexed="true" stored="true" multiValued="true"/>

    <field name="text" type="textMaxWord" indexed="true" stored="true" multiValued="true"/>

    <copyField source="simple" dest="text"/>

    <copyField source="complex" dest="text"/>

    4:测试中文分词是否起作用

    复制一段中文到Field value中;Field选择name输入complex,测试分词

    name在使用name(没有配置中文分词,使用默认的)再次进行测试

    5:多核的配置

    1:拷贝examplemulticore文件夹下的core0,core1,solr.xml到solr-tomcatsolr文件夹下

    2:方位http://localhost:8080/solr/

    使用浏览器客户端创建索引,搜索

    4:创建索引(xml,json,cvs格式的文件cookbook)

    1:复制solr解压后的,example文件夹下的exampledocs目录到solr-tomcat下(里面包含了一些测试索引用到的文件)

    2:命令行创建索引:E:solr-tomcatexampledocs>java -Durl=http://localhost:8080/solr/update -Dcommit=yes -jar post.jar m*.xml,对该文件夹下所有以m开头的xml文件创建索引,此时solr-tomcatsolrdata文件夹下多了一些文件,有段文件,域文件,索引文件等

    3:通过浏览器进行搜索,必须通过一个完整的分词(一个完整的单词,不能用a,m,z等搜索,同时this,that等也不能用于搜索)

    5:更新索引

    更新索引一般都是通过删除索引,然后再创建

    6:删除索引

    Solrj的使用

    http://wiki.apache.org/solr/Solrj

    private static final String DEFAULT_URL = "http://localhost:8080/solr/";

    1:创建索引(如何对一个指定格式的xml创建索引还不清楚)

    对文件进行索引

    public void index() throws SolrServerException, IOException {

    SolrServer solrServer = new HttpSolrServer(DEFAULT_URL);

    SolrInputDocument document = new SolrInputDocument();

    document.addField("id", "1"); //id必须有

    document.addField("name", "test");

    document.addField("path", "测试"); //path需要在schema.xml中定义

    solrServer.add(document);

    solrServer.commit();

    }

    对Bean进行索引

    public class SolrItem {

    /**

    * id,对应Solr中记录的Id

    */

    @Field("id")

    public String id;

    /**

    * 员工姓名

    */

    @Field("title")

    public String empName;

    /**

    * 员工邮箱

    */

    @Field("subject")

    public String email;

    ...

    }

    public void index() throws SolrServerException, IOException {

    SolrItem item = new SolrItem();

    item.setId("1");

    item.setEmpName("张三");

    item.setEmail("test@ppstream.com");

    solrServer.addBean(item);

    solrServer.commit();

    }

    2:搜索

    public void query(String query) {

    SolrParams params = new SolrQuery(query);

    try {

    QueryResponse response = solrServer.query(params);

    SolrDocumentList list = response.getResults();

    for (int i = 0; i < list.size(); i++) {

    fail(list.get(i));

    }

    catch (SolrServerException e) {

    e.printStackTrace();

    }

    }

    3:删除索引

    public void delete(String params) throws SolrServerException, IOException {

    solrServer.deleteByQuery(params);

    //solrServer.deleteById(params);

    }

    4:高亮显示

    public SolrDocumentList query(String str) {

    SolrQuery query = new SolrQuery(str);

    //设置高亮,以下两种方式都行(相当于开启高亮功能)

    //query.setHighlight(true);

    query.setParam("hl", "true"); //highlighting

    //设置高亮显示的请求,高亮显示的内容由该参数决定,但是返回结果还是由SolrQuery决定

    //query.setParam("hl.q", "email:zhang@ppstream.com");

    /*

    * 那些字段高亮显示,可以用空格或者逗号分隔(有一个域的时候正常,两个及以上没测试通过)

    * 老版本使用query.addHighlightField("name");query.addHighlightField("description");给多个字段开启高亮功能

    */

    query.setParam("hl.fl", "name");

    //高亮显示字段前后添加html代码

    query.setHighlightSimplePre("<font color="red">");

    query.setHighlightSimplePost("</font>");

    SolrDocumentList list = new SolrDocumentList();

    SolrDocument document = null;

    QueryResponse response=new QueryResponse();

    try {

    SolrDocumentList documents = response.getResults();

    //第一个Map的键是文档的ID,第二个Map的键是高亮显示的字段名

    Map<String, Map<String, List<String>>> map = response.getHighlighting();

    for(int i=0;i<documents.size();i++) {

    document = documents.get(i);

    document.setField("name", map.get(document.getFieldValue("id")).get("name"));

    /*document.setField("email", map.get(document.getFieldValue("id")).get("email"));*/

    list.add(document);

    }

    catch (Exception e) {

    }

    return list;

    }

    Solr的其他应用

    1:对一篇文章的前100个分词字创建索引

    有时可能需要对某个字段(文章的内容content)的前1000个字符创建索引并存储,可以在solrconfig.xml中添加<maxFieldLength>1000</maxFieldLength>实现(默认是1万)。这里是分词数量,不是汉字或字母的个数。

     

    2:配置中文分词后,如果查询“java编程思想”,会自动拆分成java,编程,思想3个分词依次进行查找

     

    3:多条件查询

    可以通过“编程 AND empName:XXX”进行查询,或者“编程 OR empName:XXX”等

     

    4:字段当做一个整体,不进行分词

    如果某个字段不需要使用分词,eg:java编程思想,只有在输入完成的书名:java编程思想才会搜索出来,可以在书名字段上的type使用不带分词的类型(schema.xml中配置)

     

    5:检索索引中的部分字段

    有时索引中可能存放很多信息,eg:书名,作者,出版时间,ISBN…….;在某次查询中,我们只需要搜索结果书名和作者即可。可以通过如下方式实现

    SolrQuery query = new SolrQuery(param);

       //返回的结果

       String[] str = {"title", "author"};

    query.setFields(str);

    6:Solr的分页

             SolrQuery query = new SolrQuery("*:* AND (empName:XXX OR empName:XX)");

        query.setHighlight(true);

        query.setStart(0);

        query.setRows(2);

        QueryResponse response = solrServer.query(query);

        long totalCount = response.getResults().getNumFound();

     totalCount返回的是满足条件的总记录条数,并不一定是0或2

     

    7:solrj高亮显示时,只显示字段部分内容

    SolrDocumentList list = response.getResults();

       Map<String, Map<String, List<String>>> map = response.getHighlighting();

       //对应的高亮字段(假设是content)。在list中显示正确,map中显示的只是content中的一部分。

       query.setHighlightFragsize(100000); //可以通过这种方法改变,设置一个比list中,对应content内容大的数字

    query.setHighlightSnippets(0);//或者设置高亮片段为0,这样关键字也就不会在高亮显示

     

    8:搜索条件的部分关键字高亮显示

    有时我们查询根据条件“java OR (empId:1000 AND empId:1001)”搜索时,结果如果高亮显示,可能出现1000,1001数字也会高亮,但是我们只希望java关键字高亮,这个时候可以用下面的方法

       query.setParam("hl.q", "lucene solr");只对lucene和solr关键字进行高亮显示(solr不作为搜索条件也可以)

    9:显示第一个匹配关键字附近的部分内容

       有时我们需要显示检索出内容的一部分(在列表页,只需要显示一个概要信息),这时候可以通过设置query.setHighlightFragsize(100000);的大小来控制

    10:schema文件,copyField配置

    <!-- 感觉使用copyField的作用是。

                    1:不需要在输入title:XXX,只需简单XXX即可查询

                    2:将title,content中输入的内容全部放到text一个字段上进行,可以简化查询不需要过多的判断

                    3:需要注意的是:source对应域的类型要和dest域对应的类型相兼容

        -->

        <copyField source="title" dest="complex"/>

        <copyField source="content" dest="complex"/>

    11:自动补全

    搜索时在title和content上进行搜索,所以自动补全时要在title和content上同时进行。但是自动补全只能在一个字段上进行(目前我知道这样),所以就创建一个新字段searchField=title+”,”+content用来进行自动补全的提示,该字段仅用来索引不需要存储。

    SolrQuery query = new SolrQuery(q); 

    query.addTermsField(searchField);

    query.setTerms(true); 

    query.setTermsLimit(limit); 

    query.setTermsLower(pre); 

    query.setTermsPrefix(pre);

    query.setQueryType("/terms");

    QueryResponse qr = solrServer.query(query);

           TermsResponse resp = qr.getTermsResponse();

     List<Term> list = resp.getTerms(searchField);

    这种搜索存在的问题:

    1: q:empName:XXX AND projecteId:19    pre:lucen   在搜索时,返回的TermsResponse结果只应用了pre一个条件

    2: title,content无法配置copyField字段使用complex(原因及解决办法没找到)

    解决方法:改用Facet替换Term

    SolrQuery query = new SolrQuery(q);

            query.setFacet(true);

            query.addFacetField(searchField);

            query.setFacetLimit(limit);

            query.setFacetPrefix(pre);

            QueryResponse qr = solrServer.query(query);

            List<FacetField> fss = qr.getFacetFields();

            FacetField ff = fss.get(0);

      return ff.getValues();

      返回的fss结果仍然是根据pre一个条件返回的结果集,但是不满足条件query的结果集中,对应的count为0,即出现了0次

    12:solr删除索引后,索引文件还存在,但是搜索结果已经不存在

    13:添加tomcat验证,防止用户直接通过地址栏访问solr,进行修改删除索引

       1:修改tomcat-user.xml文件

    <role rolename="tomcat"/>

      <role rolename="role1"/>

      <role rolename="manager"/>

      <role rolename="admin"/>

      <role rolename="manager-gui"/>

      <user username="tomcat" password="tomcat" roles="tomcat"/>

      <user username="both" password="tomcat" roles="tomcat,role1"/>

      <user username="role1" password="tomcat" roles="role1"/>

      <user username="zhchx" password="zhchx" roles="admin,manager,manager-gui"/>

    2:修改solr的web.xml文件,添加如下代码,对所有的请求,都需要tomcat用户及密码的验证

    <security-constraint>

           <web-resource-collection>

               <web-resource-name>solr</web-resource-name>

               <url-pattern>/*</url-pattern>

               <http-method>GET</http-method>

               <http-method>POST</http-method>

           </web-resource-collection>

           <auth-constraint>

               <description>This applies only to the "tomcat" security role</description>

               <role-name>admin</role-name>

           </auth-constraint>

       </security-constraint>

       <login-config>

           <auth-method>BASIC</auth-method>

       </login-config>

       <security-role>

           <role-name>admin</role-name>

       </security-role>

    3:使用该方法后,通过solrj也不能直接访问,修改如下

    String url = PropertiesSon.getText("solr.serverUrl");

                String username = PropertiesSon.getText("solr.username");

                String password = PropertiesSon.getText("solr.password");

                String host = PropertiesSon.getText("solr.host");

                int port = Integer.parseInt(PropertiesSon.getText("solr.port"));

               

                DefaultHttpClient httpclient = new DefaultHttpClient();

                httpclient.getCredentialsProvider().setCredentials(

                        new AuthScope(host, port),

                        new UsernamePasswordCredentials(username, password));

                solrServer = new HttpSolrServer(url, httpclient);

    4:使用该方法创建时,删除添加索引报错“Cannot retry request with a non-repeatable request entity.”

    修改方法:url用http://username:password@10.1.11.165:8081/solr取代http://10.1.20.57:8081/solr(httpclient使用 4.2是时正常,使用4.1时,在删除新增索引仍然会报上面的错误)

  • 相关阅读:
    PHP书写规范 PHP Coding Standard
    PHP开发编码规范.
    javascript hasOwnProperty 函数
    PHP::转义与反转义函数 (POST/GET/COOKIE)
    PHP 单一入口程序
    SET_INCLUDE_PATH详细解释
    PHP类命名规范
    管理软件本质论
    数据驱动
    脚本适用场合
  • 原文地址:https://www.cnblogs.com/cuihongyu3503319/p/9101819.html
Copyright © 2011-2022 走看看