一、描述:最近在做的一个招聘网站的项目中,有一个期望职位类别的选择。其中有一个选项是: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: <EOF> 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: <EOF> 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
转载于:https://blog.51cto.com/fengcl/1704533