一、描述:最近在做的一个招聘网站的项目中,有一个期望职位类别的选择。其中有一个选项是:C/C++。在后台做搜索的时候,需要从lucene中搜索。

二、问题1:例如C/C++,系统运维/Linux系统这样带 “/”的字符串,在做lucene的时候,会报错。报错信息如下:

        org.apache.lucene.queryparser.classic.ParseException: Cannot parse 'C/C++': Lexical error at line 1, column 6.  Encountered: after : "/C++"

at org.apache.lucene.queryparser.classic.QueryParserBase.parse(QueryParserBase.java:130)

at org.apache.lucene.queryparser.classic.MultiFieldQueryParser.parse(MultiFieldQueryParser.java:358)

at com.tarena.hr.dao.ResumeLuceneImpl.complexQuery(ResumeLuceneImpl.java:245)

at com.tarena.hr.service.impl.ResumeServiceImpl.complexQuery(ResumeServiceImpl.java:97)

at com.tarena.hr.controller.ResumeController.complexQuery(ResumeController.java:79)

at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)

at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)

at java.lang.reflect.Method.invoke(Method.java:597)

at org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:213)

at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:126)

at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:96)

at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:617)

at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:578)

at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80)

at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:923)

at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:852)

at org.springframework.web.servlet.FrameworkServlet.proce***equest(FrameworkServlet.java:882)

at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:789)

at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)

at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)

at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)

at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)

at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88)

at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)

at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)

at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)

at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)

at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)

at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)

at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)

at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)

at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)

at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:857)

at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)

at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)

at java.lang.Thread.run(Thread.java:619)

Caused by: org.apache.lucene.queryparser.classic.TokenMgrError: Lexical error at line 1, column 6.  Encountered: after : "/C++"

at org.apache.lucene.queryparser.classic.QueryParserTokenManager.getNextToken(QueryParserTokenManager.java:1133)

at org.apache.lucene.queryparser.classic.QueryParser.jj_scan_token(QueryParser.java:599)

at org.apache.lucene.queryparser.classic.QueryParser.jj_3R_2(QueryParser.java:482)

at org.apache.lucene.queryparser.classic.QueryParser.jj_3_1(QueryParser.java:489)

at org.apache.lucene.queryparser.classic.QueryParser.jj_2_1(QueryParser.java:475)

at org.apache.lucene.queryparser.classic.QueryParser.Clause(QueryParser.java:226)

at org.apache.lucene.queryparser.classic.QueryParser.Query(QueryParser.java:181)

at org.apache.lucene.queryparser.classic.QueryParser.TopLevelQuery(QueryParser.java:170)

at org.apache.lucene.queryparser.classic.QueryParserBase.parse(QueryParserBase.java:120)

... 36 more

问题2:对加号的处理,特别奇怪,发送get请求时,发送数据为:C/C++,但是回显回来的数据是:

        C/C  (C/C后面跟两个空格)。++不见了。

解决方案:

     问题1:根据报错信息看,应该是 “/”引起的错误。果然,当我把 “/”去掉以后,程序运行正常! 

        问题2:这个问题比较坑爹,查了一些资料。上面是这么说的。

                    html 中因为一些非标准的做法,将+ 等同于空格进行处理 (当Html 的表单被提交时, 每个表单域都会被Url 编码之后才在被发送。由于历史的原因,表单使用的Url 编码实现并不符合最新的标准。例如对于空格使用 的编码并不是%20 ,而是+ 号,如果表单使用的是Post 方法提交的,我们可以在HTTP 头中看到有一个Content-Type 的header ,值为 application/x-www-form-urlencoded ,大部分应用程序均能处理这种非标准实现的Url 编码)。

        如此看来,这个问题可能就是由于编码规范问题导致的错误。所以在发送请求之前将字符串中的 "+"给替换了一下,例如:"c/c++".replace(/\+/g,"/%20"); 问题果然得到了解决。

    问题三:get请求中对 “#”的处理,我在搜索C#/.net这类职位的时候,奇怪的发现,get请求中的参数,    C#/.net到后台以后,奇迹般的变成了C。这估计也是编码造成的,把"#"替换即可。#对应的ascii码为:%23

另外附一个博客的地址,这个博客上对于 “+” 这个问题说明的比较详细,大将可以参考一下。

http://blog.csdn.net/z69183787/article/details/35987711