php solr 全文检索,全文检索可视化动态管理(二)--solr二次开发和solrj扩展

本文介绍如何通过二次开发实现Solr的动态配置管理,包括添加、删除Core以及修改schema.xml等操作,提供了详细的代码实现。

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

29a2f4dc3bcb614fbdcee9e2e509b2a2.png

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

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

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 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> getSolrCoresInfo(HttpSolrServer rootServer) throws SolrServerException, IOException

{

EdenCoreAdminRequest req = new EdenCoreAdminRequest();

req.setEdenAction( EdenCoreAdminAction.CORESINFO );

CoreAdminResponse list = req.process( rootServer );

NamedList> coresInfoList=list.getCoreStatus();

return coresInfoList;

}

/**

* 获取某一core信息

* @param coreName

* @param rootServer

* @return

* @throws SolrServerException

* @throws IOException

*/

public static NamedList getSolrOneCoreInfo(String coreName,HttpSolrServer rootServer) throws SolrServerException, IOException

{

NamedList 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 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 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();

}

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值