全文检索可视化动态管理(二)--solr二次开发和solrj扩展
博客专区 > hxt168 的博客 > 博客详情
全文检索可视化动态管理(二)--solr二次开发和solrj扩展
hxt168 发表于2年前
全文检索可视化动态管理(二)--solr二次开发和solrj扩展
  • 发表于 2年前
  • 阅读 225
  • 收藏 8
  • 点赞 0
  • 评论 0

标题:腾讯云 新注册用户域名抢购1元起>>>   

摘要: 要完成solr的索引动态配置,需要solr提供动态新建、修改配置等的接口。solr虽提供core的载入,但不提供schema.xml修改新建接口,并且如果添加一个新core,也要将另一个core的conf配置文件复制一份到新的core文件夹下,然后管理页载入新的core。从而需要二次开发。

  要完成solr的索引动态配置,需要solr提供动态新建、修改配置等的接口。solr虽提供core的添加删除,但不提供schema.xml修改新建接口,并且如果添加一个新core,也要将另一个core的conf配置文件复制一份到新的core文件夹下,然后管理页载入新的core。因此需要二次开发。
   查看solr的web.xml,可以发现请求链接都进入org.apache.solr.servlet.SolrDispatchFilter。查看SolrDispatchFilter源码,可以在doFilter方式里看到,如果是adminPath的链接,则SolrRequestHandler的实现是cores.getMultiCoreHandler()。 

进入getMultiCoreHandler()方法,可以得知是org.apache.solr.handler.admin.CoreAdminHandler。此类则是solr管理界面的Core Admin的接口处理类。因此,可以继承CoreAdminHandler,重载handleRequestBody方法来给solr增加所需的处理接口。

    进一步查看源码,可以发现solr.xml里可以用adminHandler标签替换CoreAdminHandler。solr.xml:

<?xml version="1.0" encoding="UTF-8" ?>
<solr persistent="true">
  <cores defaultCoreName="default" adminHandler="org.apache.solr.handler.admin.EdenCoreAdminHandler" adminPath="/admin/cores" zkClientTimeout="${zkClientTimeout:15000}" hostPort="8080" hostContext="solr">
    <core instanceDir="core0\" name="core0"/>
    <core instanceDir="default\" name="default"/>
    <core instanceDir="periodical\" name="periodical"/>

  </cores>
</solr>

EdenCoreAdminHandler:

public class EdenCoreAdminHandler  extends CoreAdminHandler {

	  public EdenCoreAdminHandler()
	  {
		  
		 
	  }
	  
	 public EdenCoreAdminHandler(final CoreContainer coreContainer) {
		    super(coreContainer);
	}
	 
	  public CoreContainer getCoreContainer() {
		    return this.coreContainer;
		  }
	 
	
	@Override
	public void handleRequestBody(SolrQueryRequest req, SolrQueryResponse rsp)
			throws Exception {
		  CoreContainer cores = getCoreContainer();
		    if (cores == null) {
		      throw new SolrException(SolrException.ErrorCode.BAD_REQUEST,
		              "Core container instance missing");
		    }
		    String action = req.getParams().get(CoreAdminParams.ACTION);
			//String newCoreName=req.getParams().get("newCoreName");
			if (action!=null&&action.equals("ADDNEWCORE")) {
				doAddCore( req,  rsp);
			}else if (action!=null&&action.equals("CHANGESCHEMA")) {
				changeSchemaXml(req, rsp);
			}else if (action!=null&&action.equals("DELCORE")) {
				delCore(req, rsp);
			}else{
				super.handleRequestBody( req, rsp);
			}
        
	}
	
	
	/**
	 * 添加core
     *将默认core下conf里的solrconfig.xml和schema.xml拷贝到新core的conf下。这步是必须的
     *因为新建的core solr会去其conf文件夹下找这两个文件,如果没有就会报错,新core则不会创建成功
	 * @param req
	 * @param rsp
	 * @throws Exception
	 */
	public void doAddCore(SolrQueryRequest req, SolrQueryResponse rsp)	throws Exception 
	{
		  CoreContainer cores = getCoreContainer();
		 
		String defaultCoreName=  cores.getDefaultCoreName();
		SolrCore core=cores.getCore(defaultCoreName);
		
		final SolrResourceLoader loader = core.getResourceLoader();
		File srcCoredir = new File(loader.getInstanceDir());

	
		if (!srcCoredir.exists()) {
			throw new SolrException(ErrorCode.FORBIDDEN,
					"当前core不存在!");
		}

		String newCoreName=req.getParams().get(CoreAdminParams.NAME);
		if (newCoreName==null||newCoreName.equals("")) {
			 
			 throw new SolrException(ErrorCode.FORBIDDEN,
						"name不能为空!");
		 }
		 if (coreContainer.getCore(newCoreName) != null) {
			 
			 throw new SolrException(ErrorCode.FORBIDDEN,
						"已经创建了"+newCoreName+"的core!");
		 }
			
		String solrHome=srcCoredir.getParent();
		String srcConfPath= solrHome+File.separator+"default"+ File.separator+"conf";  //复制default文件夹
		String fromCoreName=req.getParams().get(CoreAdminParams.OTHER);
		if(fromCoreName!=null&&!fromCoreName.equals(""))  //如果有参数,则用这个的配置
		{
			SolrCore fromcore=cores.getCore(fromCoreName);
			SolrResourceLoader fromcoreLoader = fromcore.getResourceLoader();
			srcConfPath=fromcoreLoader.getConfigDir();
			
		}
	
		  // 建立新core所在文件夹
       File newCorePath = new File(solrHome + File.separator + newCoreName);
       if (!newCorePath.exists()) {
    	   newCorePath.mkdir();
       }
       // 建立新core下的conf文件夹
       File newConfPath = new File(newCorePath.getAbsolutePath() + File.separator
               + "conf/");
       if (!newConfPath.exists()) {
    	   newConfPath.mkdir();
       }
  
       boolean doPersist=this.handleCreateAction(req, rsp);
       
       if (doPersist) {
           cores.persist();
           rsp.add("saved", cores.getConfigFile().getAbsolutePath());
         }
         rsp.setHttpCaching(false);
		
	}
	
	.......

	@Override
	public String getDescription() {
		return "add new core";
	}

	@Override
	public String getSource() {
		return null;
	}

}

 

同时solrj也要扩展新接口的请求方法。按照solrj源码里的请求方式。

EdenCoreAdminParams:

public class EdenCoreAdminParams implements CoreAdminParams{
	  public enum EdenCoreAdminAction {
	    CORESINFO,
	    ADDNEWCORE,
	    CHANGESCHEMA,
	    DELCORE;
	    public static CoreAdminAction get( String p )
	    {
	      if( p != null ) {
	        try {
	          return CoreAdminAction.valueOf( p.toUpperCase(Locale.ROOT) );
	        }
	        catch( Exception ex ) {}
	      }
	      return null; 
	    }
	  }
	
}

EdenSchemaUpdateRequest(动态修改schema.xml):

public class EdenSchemaUpdateRequest extends AbstractUpdateRequest{

	private String xmlContent=null;
	
	public EdenSchemaUpdateRequest( String path) {
		super(METHOD.POST, path);
	}

	@Override
	public Collection<ContentStream> getContentStreams() throws IOException {
		 return ClientUtils.toContentStreams(getXmlContent(), ClientUtils.TEXT_XML);
	}

	public String getXmlContent() {
		return xmlContent;
	}

	public void setXmlContent(String xmlContent) {
		this.xmlContent = xmlContent;
	}

	
}

EdenCoreAdminRequest:

/**
 *  solrj CoreAdminRequest扩展
 * @author hanxuetong
 * 
 */
@SuppressWarnings("serial")
public class EdenCoreAdminRequest extends CoreAdminRequest{

	protected  ModifiableSolrParams params;
    protected EdenCoreAdminAction edenAction; 
	
	
    @Override
    public SolrParams getParams() {
    	
        if(params==null)
        {
        	params = new ModifiableSolrParams(); 
        }
        if( edenAction == null&&params==null ) { //使用原来的
	        return super.getParams();
	    }
        if(edenAction==null||edenAction.equals(EdenCoreAdminAction.CORESINFO)  ) //直接查询所有信息
        {
        	 return params;
        }
        
        params.set( EdenCoreAdminParams.ACTION, edenAction.toString() );
        params.set( EdenCoreAdminParams.NAME, core );
    	if(other!=null)
    	{
    		params.set( EdenCoreAdminParams.OTHER, other );
    	}

      return params;
    }
	public void setParams(ModifiableSolrParams params) {
		this.params = params;
	}

	public void setEdenAction(EdenCoreAdminAction edenAction) {
		this.edenAction = edenAction;
	}
	 public static class DelCore extends EdenCoreAdminRequest {
		    protected String deleteDir;

		    public DelCore(String deleteDir) {
		      edenAction=EdenCoreAdminAction.DELCORE;
		      this.deleteDir = deleteDir;
		    }

		    public String isDeleteDir() {
		      return deleteDir;
		    }

		    public void setDeleteDir(String deleteDir) {
		      this.deleteDir = deleteDir;
		    }

		    @Override
		    public SolrParams getParams() {
		      ModifiableSolrParams params = new ModifiableSolrParams();
		      params.set( EdenCoreAdminParams.ACTION, edenAction.toString());
		      params.set( EdenCoreAdminParams.CORE, core );
		      if(deleteDir!=null)
		      {
		    	  params.set("deleteDir", deleteDir);
		      }
		     
		      return params;
		    }
	 }
	  public static CoreAdminResponse delCore( String name, String deleteDir, SolrServer server ) throws SolrServerException, IOException
	  {
		  DelCore req = new DelCore(deleteDir);
		  req.setCoreName( name );
		  return req.process( server );
	  }	 
}

EdenSolrCoresRequest:

/**
 * solr控制台管理交互类
 * @author hanxuetong
 * 
 */
public class EdenSolrCoresRequest {

	/**
	 * 获得所有core信息
	 * @return
	 * @throws IOException 
	 * @throws SolrServerException 
	 */
	public static NamedList<NamedList<Object>>  getSolrCoresInfo(HttpSolrServer rootServer) throws SolrServerException, IOException
	{
		EdenCoreAdminRequest req = new EdenCoreAdminRequest();
	    req.setEdenAction( EdenCoreAdminAction.CORESINFO );
		CoreAdminResponse list = req.process( rootServer );
		
		NamedList<NamedList<Object>>  coresInfoList=list.getCoreStatus();

		return coresInfoList;
			
	}
	
	/**
	 * 获取某一core信息
	 * @param coreName
	 * @param rootServer
	 * @return
	 * @throws SolrServerException
	 * @throws IOException
	 */
	public static NamedList<Object>  getSolrOneCoreInfo(String coreName,HttpSolrServer rootServer) throws SolrServerException, IOException
	{
		
		NamedList<Object> list = EdenCoreAdminRequest
				       .getStatus(coreName, rootServer)
				       .getCoreStatus()
				       .get(coreName);

		return list;
	}
	
	/**
	 * 添加core,默认
	 * @param newCoreName
	 * @param rootServer
	 * @throws SolrServerException
	 * @throws IOException
	 */
	public static void addCore(String newCoreName,HttpSolrServer rootServer) throws SolrServerException, IOException
	{
		
		
		EdenCoreAdminRequest req = new EdenCoreAdminRequest();
		req.setCoreName(newCoreName);
		req.setEdenAction(EdenCoreAdminAction.ADDNEWCORE);
	
		CoreAdminResponse list = req.process(rootServer);
		int state = list.getStatus();
		if (state != 0) {
			throw new SolrServerException("添加core失败!");
		}

		
	}
	
	
	/**
	 * 添加core
	 * @param newCoreName
	 * @param from 复制的core配置
	 * @throws SolrServerException
	 * @throws IOException
	 */
	public static void addCore(String newCoreName,String from,HttpSolrServer rootServer) throws SolrServerException, IOException
	{
		
		
		EdenCoreAdminRequest req = new EdenCoreAdminRequest();
		req.setCoreName(newCoreName);
		req.setEdenAction(EdenCoreAdminAction.ADDNEWCORE);
		req.setOtherCoreName(from);
		CoreAdminResponse list = req.process(rootServer);
		int state = list.getStatus();
		if (state != 0) {
			throw new SolrServerException("添加core失败!");
		}

		
	}
	
	/**
	 * 获取schema.xml内容
	 * @param coreName
	 * @param rootServer
	 * @return
	 * @throws SolrServerException
	 * @throws IOException
	 */
	public static String getSchemaXmlContent(String coreName,HttpSolrServer rootServer) throws SolrServerException, IOException
	{
		ModifiableSolrParams params = new ModifiableSolrParams();
		params.set("file", "schema.xml");
		params.set("contentType", "text/xml;charset=utf-8");
		EdenCoreAdminRequest req = new EdenCoreAdminRequest();
		req.setPath("/" + coreName + "/admin/file");
		req.setParams(params);
		NamedList<Object> ob = rootServer.request(req, null);
		InputStream respBody = (InputStream) ob.get("stream");
		String con=StringStreamUtil.convertStreamToString(respBody);
				
		return con;
	}
	
	/**
	 * 远程修改schema.xml的内容
	 * @param coreName
	 * @param xmlContent
	 * @param rootServer
	 * @throws SolrServerException
	 * @throws IOException
	 */
	public static void postSchemaXmlContent(String coreName,String xmlContent,HttpSolrServer rootServer) throws SolrServerException, IOException
	{
	
		EdenSchemaUpdateRequest edenSchemaUpdateRequest=new EdenSchemaUpdateRequest("/admin/cores");
	    edenSchemaUpdateRequest.setParam("name", coreName);
	    edenSchemaUpdateRequest.setParam("action", "CHANGESCHEMA");
	    edenSchemaUpdateRequest.setXmlContent(xmlContent);	  
	    UpdateResponse rep=edenSchemaUpdateRequest.process(rootServer);
	    int state =  rep.getStatus();
		if (state != 0) {
			throw new SolrServerException("postSchemaXml失败!");
		}
		
	}
	
	/**
	 * 重新加载core
	 * @param coreName
	 * @param rootServer
	 * @throws SolrServerException
	 * @throws IOException
	 */
	public static void reloadCore(String coreName,HttpSolrServer rootServer) throws SolrServerException, IOException
	{
		CoreAdminRequest req = new CoreAdminRequest();
		req.setAction(CoreAdminAction.RELOAD);
		req.setCoreName(coreName);
		CoreAdminResponse list = req.process(rootServer);
		int state = list.getStatus();
		if (state != 0) {
			throw new SolrServerException("reload失败!");
		}
		
		
	}
	
	/***
	 * 加载core
	 * @param coreName
	 * @param rootServer
	 * @throws SolrServerException
	 * @throws IOException
	 */
	public static void loadCore(String coreName,HttpSolrServer rootServer) throws SolrServerException, IOException
	{
		CoreAdminRequest req = new CoreAdminRequest();
		req.setAction(CoreAdminAction.LOAD);
		req.setCoreName(coreName);
		CoreAdminResponse list = req.process(rootServer);
		int state = list.getStatus();
		if (state != 0) {
			throw new SolrServerException("load失败!");
		}
		
		
	}
	
	/**
	 * 删除core
	 * @param coreName
	 * @param isDeleteDir 是否删除文件夹
	 * @param rootServer
	 * @throws SolrServerException
	 * @throws IOException
	 */
	public static void delCore(String coreName,boolean isDeleteDir,HttpSolrServer rootServer) throws SolrServerException, IOException
	{
		String instanceDir=null;
		if(isDeleteDir)
		{
			NamedList<Object> list = EdenCoreAdminRequest
				       .getStatus(coreName, rootServer)
				       .getCoreStatus()
				       .get(coreName);
			instanceDir=(String) list.get("instanceDir");
		}
		
	
		int state= EdenCoreAdminRequest
			       .delCore(coreName, instanceDir, rootServer)
			       .getStatus();
		if (state != 0) {
			throw new SolrServerException("delCore失败!");
		}
		
		
	}
	
	/**
	 * 两个core交换
	 * @param coreName
	 * @param otherCore
	 * @param rootServer
	 * @throws SolrServerException
	 * @throws IOException
	 */
	public static void swap(String coreName,String otherCore,HttpSolrServer rootServer) throws SolrServerException, IOException
	{
		CoreAdminRequest req = new CoreAdminRequest();
		req.setAction(CoreAdminAction.SWAP);
		req.setCoreName(coreName);
		req.setOtherCoreName(otherCore);
		CoreAdminResponse list = req.process(rootServer);
		int state = list.getStatus();
		if (state != 0) {
			throw new SolrServerException("swap失败!");
		}
		
		
	}
	
	
	public static void main(String[] args) {
		
		HttpSolrServer server = new HttpSolrServer("http://localhost:8082/solr");
		/*try {
			swap("newsss","dddsdd",server);
		} catch (SolrServerException e) {
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		*/
		try {
			delCore( "oa_car5", false, server);
		} catch (SolrServerException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
}

 

 

共有 人打赏支持
hxt168
粉丝 8
博文 14
码字总数 13288
作品 3
×
hxt168
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: