Solr初始化源码分析-Solr初始化与启动

 用solr做项目已经有一年有余,但都是使用层面,只是利用solr现有机制,修改参数,然后监控调优,从没有对solr进行源码级别的研究。但是,最近手头的一个项目,让我感觉必须把solrn内部原理和扩展机制弄熟,才能把这个项目做好。今天分享的就是:Solr是如何启动并且初始化的。大家知道,部署solr时,分两部分:一、solr的配置文件。二、solr相关的程序、插件、依赖lucene相关的jar包、日志方面的jar。因此,在研究solr也可以顺着这个思路:加载配置文件、初始化各个core、初始化各个core中的requesthandler...

  研究solr的启动,首先从solr war程序的web.xml分析开始,下面是solr的web.xml片段:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
<web-app xmlns= "http://java.sun.com/xml/ns/javaee"
          xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation= "http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
          version= "2.5"
          metadata-complete= "true"
>
 
 
   <!-- Uncomment if you are trying to use a Resin version before 3.0 . 19 .
     Their XML implementation isn't entirely compatible with Xerces.
     Below are the implementations to use with Sun's JVM.
   <system-property javax.xml.xpath.XPathFactory=
              "com.sun.org.apache.xpath.internal.jaxp.XPathFactoryImpl" />
   <system-property javax.xml.parsers.DocumentBuilderFactory=
              "com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl" />
   <system-property javax.xml.parsers.SAXParserFactory=
              "com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl" />
    -->
 
   <!-- People who want to hardcode their "Solr Home" directly into the
        WAR File can set the JNDI property here...
    -->
     <!--  Solr配置文件的参数,用于Solr初始化使用  -->
     <env-entry>
        <env-entry-name>solr/home</env-entry-name>
        <env-entry-value>R:/solrhome1/solr</env-entry-value>
        <env-entry-type>java.lang.String</env-entry-type>
     </env-entry>
 
    
   
   <!-- org.apache.solr.servlet.SolrDispatchFilter  Solr启动最重要的东东,所以针对solr源码分析,要对这个Filter开始,它主要的作用:加载solr配置文件、初始化各个core、初始化各个requestHandler和component -->
   <filter>
     <filter-name>SolrRequestFilter</filter-name>
     <filter- class >org.apache.solr.servlet.SolrDispatchFilter</filter- class >
     <!-- If you are wiring Solr into a larger web application which controls
          the web context root, you will probably want to mount Solr under
          a path prefix (app.war with /app/solr mounted into it, for example).
          You will need to put this prefix in front of the SolrDispatchFilter
          url-pattern mapping too (/solr/*), and also on any paths for
          legacy Solr servlet mappings you may be using.
          For the Admin UI to work properly in a path-prefixed configuration,
          the admin folder containing the resources needs to be under the app context root
          named to match the path-prefix.  For example:
 
             .war
                xxx
                  js
                    main.js
     -->
     <!--
     <init-param>
       <param-name>path-prefix</param-name>
       <param-value>/xxx</param-value>
     </init-param>
     -->
   </filter>

  SolrDispatchFilter 是继承BaseSolrFilter的一个Filter(Filter的作用是啥,大家应该清楚吧,一般web框架级别的产品源码分析都是从filter或者servlet开始)。在介绍SolrDispatchFilter之前,先介绍一下BaseSolrFilter(也许程序员都有刨根问底的习惯)。BaseSolrFilter,是一个实现Filter接口的抽象类,功能很简单,就是判断当前程序是否已经加载日志方面的jar。代码片段如下:

  

?
1
2
3
4
5
6
7
8
9
10
11
12
13
/**
  * All Solr filters available to the user's webapp should
  * extend this class and not just implement {@link Filter}.
  * This class ensures that the logging configuration is correct
  * before any Solr specific code is executed.
  */
abstract class BaseSolrFilter implements Filter {
   
   static { //
     CheckLoggingConfiguration.check();
   }
   
}

  着于篇幅,我就不介绍CheckLoggingConfiguration.check() 这里面的东东了。OK,我们回到SolrDispatchFilter上。由于BaseSolrFilter是一个抽象类,所有作为非抽象类的SolrDispatchFilter必须要实现Filter接口。Filter接口如下:

  

?
1
2
3
4
5
6
7
8
9
10
11
12
13
public interface Filter {
 
     //进行初始化
     public void init(FilterConfig filterConfig) throws ServletException;
     
    //拦截所有的http请求
     public void doFilter(ServletRequest request, ServletResponse response,
                          FilterChain chain)
             throws IOException, ServletException;
 
    //进行注销的动作
     public void destroy();
}

  根据上面的注释,我们知道在init方法中是进行初始化的。因此,今天咱们研究SolrDispatchFilter是如何初始化,是离不开这个方法的。接下来,咱们看看SolrDispatchFilter的init方法吧:

  

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@Override
public void init(FilterConfig config) throws ServletException
{
   log.info( "SolrDispatchFilter.init()" );
 
   try {
     // web.xml configuration
     this .pathPrefix = config.getInitParameter( "path-prefix" );
     //各位看客,乾坤尽在此方法中
     this .cores = createCoreContainer();
     log.info( "user.dir=" + System.getProperty( "user.dir" ));
   }
   catch ( Throwable t ) {
     // catch this so our filter still works
     log.error( "Could not start Solr. Check solr/home property and the logs" );
     SolrCore.log( t );
     if (t instanceof Error) {
       throw (Error) t;
     }
   }
 
   log.info( "SolrDispatchFilter.init() done" );
}

  咱们顺藤摸瓜,来看看createCoreContainer这个方法到底干了些什么。

  

?
1
2
3
4
5
6
7
protected CoreContainer createCoreContainer() {<br>   //看好了SolrResourceLoader 是用来加载solr home中的配置文件文件的
   SolrResourceLoader loader = new SolrResourceLoader(SolrResourceLoader.locateSolrHome());
   //加载配置文件<br>    ConfigSolr config = loadConfigSolr(loader);
   CoreContainer cores = new CoreContainer(loader, config);<br>   //初始化Core
   cores.load();
   return cores;
}

  createCoreContainer这个方法是决定咱们今天能否弄懂Solr初始化和启动的关键。我们顺便简单分析一下这个方法中用到的几个类和方法:

  SolrResourceLoader  类如其名,是solr资源加载器。

     ConfigSolr 是通过SolrResourceLoader来读取solr配置文件的中信息的。

    loadConfigSolr,加载配置信息的方法:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
private ConfigSolr loadConfigSolr(SolrResourceLoader loader) {
   //优先读取solr.solrxml.location配置的信息,往往是通过读取zookeeper中的配置信息进行初始化的,如果没有配置,就会读取solrhome配置项配置的信息(记得web.xml第一个配置项否,就是它)
   String solrxmlLocation = System.getProperty( "solr.solrxml.location" , "solrhome" );
   
   if (solrxmlLocation == null || "solrhome" .equalsIgnoreCase(solrxmlLocation))
     return ConfigSolr.fromSolrHome(loader, loader.getInstanceDir());
    //ok 从zookeeper中读取配置信息吧,这是在solrcloud集群下用来solr初始化的
   if ( "zookeeper" .equalsIgnoreCase(solrxmlLocation)) {
     String zkHost = System.getProperty( "zkHost" );
     log.info( "Trying to read solr.xml from " + zkHost);
     if (StringUtils.isEmpty(zkHost))
       throw new SolrException(ErrorCode.SERVER_ERROR,
           "Could not load solr.xml from zookeeper: zkHost system property not set" );
     SolrZkClient zkClient = new SolrZkClient(zkHost, 30000 );
     try {
       if (!zkClient.exists( "/solr.xml" , true )) //solr.xml里有描述的zookeeper相关的配置信息
         throw new SolrException(ErrorCode.SERVER_ERROR, "Could not load solr.xml from zookeeper: node not found" );
       byte [] data = zkClient.getData( "/solr.xml" , null , null , true );<br>         //加载配置信息
       return ConfigSolr.fromInputStream(loader, new ByteArrayInputStream(data));
     } catch (Exception e) {
       throw new SolrException(ErrorCode.SERVER_ERROR, "Could not load solr.xml from zookeeper" , e);
     } finally {
       zkClient.close(); //关闭zookeeper连接
     }
   }
 
   throw new SolrException(ErrorCode.SERVER_ERROR,
       "Bad solr.solrxml.location set: " + solrxmlLocation + " - should be 'solrhome' or 'zookeeper'" );
}

  CoreContainer  就是进行Core初始化工作的。我们主要看看load方法吧,这段方法有点长,代码如下:

  

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
public void load()  {
 
     log.info( "Loading cores into CoreContainer [instanceDir={}]" , loader.getInstanceDir());
      //加载solr共享jar包库
     // add the sharedLib to the shared resource loader before initializing cfg based plugins
     String libDir = cfg.getSharedLibDirectory();
     if (libDir != null ) {
       File f = FileUtils.resolvePath( new File(solrHome), libDir);
       log.info( "loading shared library: " + f.getAbsolutePath());<br>      //对classloader不熟的,可以进去看看
       loader.addToClassLoader(libDir, null , false );
       loader.reloadLuceneSPI();
     }
 
     //分片相关的handler加载以及初始化
     shardHandlerFactory = ShardHandlerFactory.newInstance(cfg.getShardHandlerFactoryPluginInfo(), loader);
     
     updateShardHandler = new UpdateShardHandler(cfg);
 
     solrCores.allocateLazyCores(cfg.getTransientCacheSize(), loader);
 
     logging = LogWatcher.newRegisteredLogWatcher(cfg.getLogWatcherConfig(), loader);
 
     hostName = cfg.getHost();
     log.info( "Host Name: " + hostName);
 
     zkSys.initZooKeeper( this , solrHome, cfg);
 
     collectionsHandler = createHandler(cfg.getCollectionsHandlerClass(), CollectionsHandler. class );
     infoHandler        = createHandler(cfg.getInfoHandlerClass(), InfoHandler. class );
     coreAdminHandler   = createHandler(cfg.getCoreAdminHandlerClass(), CoreAdminHandler. class );
     //zookeeper 配置信息初始化solr core
     coreConfigService = cfg.createCoreConfigService(loader, zkSys.getZkController());
 
     containerProperties = cfg.getSolrProperties( "solr" );
 
     // setup executor to load cores in parallel
     // do not limit the size of the executor in zk mode since cores may try and wait for each other.<br>    //多线程初始化core  不熟悉多线的可以驻足研究一会
     ExecutorService coreLoadExecutor = Executors.newFixedThreadPool(
         ( zkSys.getZkController() == null ? cfg.getCoreLoadThreadCount() : Integer.MAX_VALUE ),
         new DefaultSolrThreadFactory( "coreLoadExecutor" ) );
 
     try {
       CompletionService<SolrCore> completionService = new ExecutorCompletionService<>(
           coreLoadExecutor);
 
       Set<Future<SolrCore>> pending = new HashSet<>();
 
       List<CoreDescriptor> cds = coresLocator.discover( this );
       checkForDuplicateCoreNames(cds);
 
       for ( final CoreDescriptor cd : cds) {
 
         final String name = cd.getName();
         try {
 
           if (cd.isTransient() || ! cd.isLoadOnStartup()) {
             // Store it away for later use. includes non-transient but not
             // loaded at startup cores.
             solrCores.putDynamicDescriptor(name, cd);
           }
           if (cd.isLoadOnStartup()) { // The normal case
 
             Callable<SolrCore> task = new Callable<SolrCore>() {
               @Override
               public SolrCore call() {
                 SolrCore c = null ;
                 try {
                   if (zkSys.getZkController() != null ) { //zookeeper模式
                     preRegisterInZk(cd);
                   }
                   c = create(cd); //普通创建模式
                   registerCore(cd.isTransient(), name, c, false , false );
                 } catch (Exception e) {
                   SolrException.log(log, null , e);
                   try {
               /*    if (isZooKeeperAware()) {
                     try {
                       zkSys.zkController.unregister(name, cd);
                     } catch (InterruptedException e2) {
                       Thread.currentThread().interrupt();
                       SolrException.log(log, null, e2);
                     } catch (KeeperException e3) {
                       SolrException.log(log, null, e3);
                     }
                   }*/
                   } finally {
                     if (c != null ) {
                       c.close();
                     }
                   }           
                 }
                 return c;
               }
             };
             pending.add(completionService.submit(task));
 
           }
         } catch (Exception e) {
           SolrException.log(log, null , e);
         }
       }
 
       while (pending != null && pending.size() > 0 ) {
         try {
           //获取创建完成的core
           Future<SolrCore> future = completionService.take();
           if (future == null ) return ;
           pending.remove(future);
 
           try {
             SolrCore c = future.get();
             // track original names
             if (c != null ) {
               solrCores.putCoreToOrigName(c, c.getName());
             }
           } catch (ExecutionException e) {
             SolrException.log(SolrCore.log, "Error loading core" , e);
           }
 
         } catch (InterruptedException e) {
           throw new SolrException(SolrException.ErrorCode.SERVICE_UNAVAILABLE,
               "interrupted while loading core" , e);
         }
       }
<br>      //solr core的守护线程,在容器关闭或者启动失败的时候,进行资源注销
       // Start the background thread
       backgroundCloser = new CloserThread( this , solrCores, cfg);
       backgroundCloser.start();
 
     } finally {
       if (coreLoadExecutor != null ) {<br>        //初始化完成,关闭线程池
         ExecutorUtil.shutdownNowAndAwaitTermination(coreLoadExecutor);
       }
     }
     
     if (isZooKeeperAware()) { //如果zookeeper可用 也就是solrcloud模式
       // register in zk in background threads
       Collection<SolrCore> cores = getCores();
       if (cores != null ) {
         for (SolrCore core : cores) {
           try {<br>            //讲core的状态信息注册到zookeeper中
             zkSys.registerInZk(core, true );
           } catch (Throwable t) {
             SolrException.log(log, "Error registering SolrCore" , t);
           }
         }
       }<br>      //
       zkSys.getZkController().checkOverseerDesignate();
     }
   }

  在这段代码,关键部分我都做了注释。当你需要优化你的solr启动速度时,你还会来研究这段代码。下面,我们将研究solr的请求过滤处理的部分,我们需要关注doFilter那个方法了(关键部分我作以注释,就不细讲了):

     

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
if ( abortErrorMessage != null ) { //500错误处理
      ((HttpServletResponse)response).sendError( 500 , abortErrorMessage );
      return ;
    }
    
    if ( this .cores == null ) { //solr core初始化失败或者已经关闭
      ((HttpServletResponse)response).sendError( 503 , "Server is shutting down or failed to initialize" );
      return ;
    }
    CoreContainer cores = this .cores;
    SolrCore core = null ;
    SolrQueryRequest solrReq = null ;
    Aliases aliases = null ;
    
    if ( request instanceof HttpServletRequest) { //如果是http请求
      HttpServletRequest req = (HttpServletRequest)request;
      HttpServletResponse resp = (HttpServletResponse)response;
      SolrRequestHandler handler = null ;
      String corename = "" ;
      String origCorename = null ;
      try {
        // put the core container in request attribute
        req.setAttribute( "org.apache.solr.CoreContainer" , cores);
        String path = req.getServletPath();
        if ( req.getPathInfo() != null ) {
          // this lets you handle /update/commit when /update is a servlet
          path += req.getPathInfo();
        }
        if ( pathPrefix != null && path.startsWith( pathPrefix ) ) {
          path = path.substring( pathPrefix.length() );
        }
        // check for management path
        String alternate = cores.getManagementPath();
        if (alternate != null && path.startsWith(alternate)) {
          path = path.substring( 0 , alternate.length());
        }
        // unused feature ?
        int idx = path.indexOf( ':' );
        if ( idx > 0 ) {
          // save the portion after the ':' for a 'handler' path parameter
          path = path.substring( 0 , idx );
        }
 
        // Check for the core admin page
        if ( path.equals( cores.getAdminPath() ) ) { //solr admin 管理页面请求
          handler = cores.getMultiCoreHandler();
          solrReq =  SolrRequestParsers.DEFAULT.parse( null ,path, req);
          handleAdminRequest(req, response, handler, solrReq);
          return ;
        }
        boolean usingAliases = false ;
        List<String> collectionsList = null ;
        // Check for the core admin collections url
        if ( path.equals( "/admin/collections" ) ) { //管理collections
          handler = cores.getCollectionsHandler();
          solrReq =  SolrRequestParsers.DEFAULT.parse( null ,path, req);
          handleAdminRequest(req, response, handler, solrReq);
          return ;
        }
        // Check for the core admin info url
        if ( path.startsWith( "/admin/info" ) ) { //查看admin info
          handler = cores.getInfoHandler();
          solrReq =  SolrRequestParsers.DEFAULT.parse( null ,path, req);
          handleAdminRequest(req, response, handler, solrReq);
          return ;
        }
        else {
          //otherwise, we should find a core from the path
          idx = path.indexOf( "/" , 1 );
          if ( idx > 1 ) {
            // try to get the corename as a request parameter first
            corename = path.substring( 1 , idx );
            
            // look at aliases
            if (cores.isZooKeeperAware()) { //solr cloud状态
              origCorename = corename;
              ZkStateReader reader = cores.getZkController().getZkStateReader();
              aliases = reader.getAliases();
              if (aliases != null && aliases.collectionAliasSize() > 0 ) {
                usingAliases = true ;
                String alias = aliases.getCollectionAlias(corename);
                if (alias != null ) {
                  collectionsList = StrUtils.splitSmart(alias, "," , true );
                  corename = collectionsList.get( 0 );
                }
              }
            }
            
            core = cores.getCore(corename);
 
            if (core != null ) {
              path = path.substring( idx );
            }
          }
          if (core == null ) {
            if (!cores.isZooKeeperAware() ) {
              core = cores.getCore( "" );
            }
          }
        }
        
        if (core == null && cores.isZooKeeperAware()) {
          // we couldn't find the core - lets make sure a collection was not specified instead
          core = getCoreByCollection(cores, corename, path);
          
          if (core != null ) {
            // we found a core, update the path
            path = path.substring( idx );
          }
          
          // if we couldn't find it locally, look on other nodes
          if (core == null && idx > 0 ) {
            String coreUrl = getRemotCoreUrl(cores, corename, origCorename);
            // don't proxy for internal update requests
            SolrParams queryParams = SolrRequestParsers.parseQueryString(req.getQueryString());
            if (coreUrl != null
                && queryParams
                    .get(DistributingUpdateProcessorFactory.DISTRIB_UPDATE_PARAM) == null ) {
              path = path.substring(idx);
              remoteQuery(coreUrl + path, req, solrReq, resp);
              return ;
            } else {
              if (!retry) {
                // we couldn't find a core to work with, try reloading aliases
                // TODO: it would be nice if admin ui elements skipped this...
                ZkStateReader reader = cores.getZkController()
                    .getZkStateReader();
                reader.updateAliases();
                doFilter(request, response, chain, true );
                return ;
              }
            }
          }
          
          // try the default core
          if (core == null ) {
            core = cores.getCore( "" );
          }
        }
 
        // With a valid core...
        if ( core != null ) { //验证core
          final SolrConfig config = core.getSolrConfig();
          // get or create/cache the parser for the core
          SolrRequestParsers parser = config.getRequestParsers();
 
          // Handle /schema/* and /config/* paths via Restlet
          if ( path.equals( "/schema" ) || path.startsWith( "/schema/" )
              || path.equals( "/config" ) || path.startsWith( "/config/" )) { //solr rest api 入口 
            solrReq = parser.parse(core, path, req);
            SolrRequestInfo.setRequestInfo( new SolrRequestInfo(solrReq, new SolrQueryResponse()));
            if ( path.equals(req.getServletPath()) ) {
              // avoid endless loop - pass through to Restlet via webapp
              chain.doFilter(request, response);
            } else {
              // forward rewritten URI (without path prefix and core/collection name) to Restlet
              req.getRequestDispatcher(path).forward(request, response);
            }
            return ;
          }
 
          // Determine the handler from the url path if not set
          // (we might already have selected the cores handler)
          if ( handler == null && path.length() > 1 ) { // don't match "" or "/" as valid path
            handler = core.getRequestHandler( path );
            // no handler yet but allowed to handle select; let's check
            if ( handler == null && parser.isHandleSelect() ) {
              if ( "/select" .equals( path ) || "/select/" .equals( path ) ) { //solr 各种查询过滤入口
                solrReq = parser.parse( core, path, req );
                String qt = solrReq.getParams().get( CommonParams.QT );
                handler = core.getRequestHandler( qt );
                if ( handler == null ) {
                  throw new SolrException( SolrException.ErrorCode.BAD_REQUEST, "unknown handler: " +qt);
                }
                if ( qt != null && qt.startsWith( "/" ) && (handler instanceof ContentStreamHandlerBase)) {
                  //For security reasons it's a bad idea to allow a leading '/', ex: /select?qt=/update see SOLR-3161
                  //There was no restriction from Solr 1.4 thru 3.5 and it's not supported for update handlers.
                  throw new SolrException( SolrException.ErrorCode.BAD_REQUEST, "Invalid Request Handler ('qt').  Do not use /select to access: " +qt);
                }
              }
            }
          }
 
          // With a valid handler and a valid core...
          if ( handler != null ) {
            // if not a /select, create the request
            if ( solrReq == null ) {
              solrReq = parser.parse( core, path, req );
            }
 
            if (usingAliases) {
              processAliases(solrReq, aliases, collectionsList);
            }
            
            final Method reqMethod = Method.getMethod(req.getMethod());
            HttpCacheHeaderUtil.setCacheControlHeader(config, resp, reqMethod);
            // unless we have been explicitly told not to, do cache validation
            // if we fail cache validation, execute the query
            if (config.getHttpCachingConfig().isNever304() ||
                !HttpCacheHeaderUtil.doCacheHeaderValidation(solrReq, req, reqMethod, resp)) { //solr http 缓存 在header控制失效时间的方式
                SolrQueryResponse solrRsp = new SolrQueryResponse();
                /* even for HEAD requests, we need to execute the handler to
                 * ensure we don't get an error (and to make sure the correct
                 * QueryResponseWriter is selected and we get the correct
                 * Content-Type)
                 */
                SolrRequestInfo.setRequestInfo( new SolrRequestInfo(solrReq, solrRsp));
                this .execute( req, handler, solrReq, solrRsp );
                HttpCacheHeaderUtil.checkHttpCachingVeto(solrRsp, resp, reqMethod);
              // add info to http headers
              //TODO: See SOLR-232 and SOLR-267. 
                /*try {
                  NamedList solrRspHeader = solrRsp.getResponseHeader();
                 for (int i=0; i<solrRspHeader.size(); i++) {
                   ((javax.servlet.http.HttpServletResponse) response).addHeader(("Solr-" + solrRspHeader.getName(i)), String.valueOf(solrRspHeader.getVal(i)));
                 }
                } catch (ClassCastException cce) {
                  log.log(Level.WARNING, "exception adding response header log information", cce);
                }*/
               QueryResponseWriter responseWriter = core.getQueryResponseWriter(solrReq);
               writeResponse(solrRsp, response, responseWriter, solrReq, reqMethod);
            }
            return ; // we are done with a valid handler
          }
        }
        log.debug( "no handler or core retrieved for " + path + ", follow through..." );
      }
      catch (Throwable ex) {
        sendError( core, solrReq, request, (HttpServletResponse)response, ex );
        if (ex instanceof Error) {
          throw (Error) ex;
        }
        return ;
      } finally {
        try {
          if (solrReq != null ) {
            log.debug( "Closing out SolrRequest: {}" , solrReq);
            solrReq.close();
          }
        } finally {
          try {
            if (core != null ) {
              core.close();
            }
          } finally {
            SolrRequestInfo.clearRequestInfo();
          }
        }
      }
    }
 
    // Otherwise let the webapp handle the request
    chain.doFilter(request, response);
  }

  

 

 

 

文章转载请注明出处:http://www.cnblogs.com/likehua/p/4353608.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值