全文檢索可視化動態管理(二)--solr二次開發和solrj擴展

  要完成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()。 java

進入getMultiCoreHandler()方法,能夠得知是org.apache.solr.handler.admin.CoreAdminHandler。此類則是solr管理界面的Core Admin的接口處理類。所以,能夠繼承CoreAdminHandler,重載handleRequestBody方法來給solr增長所需的處理接口。web

    進一步查看源碼,能夠發現solr.xml裏能夠用adminHandler標籤替換CoreAdminHandler。solr.xml:apache

<?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:ide

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源碼裏的請求方式。post

EdenCoreAdminParams:this

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):spa

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:code

/**
 *  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:server

/**
 * 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();
		}
	}
	
}
相關文章
相關標籤/搜索