为啥这个 Json 不能从 HTTP 请求中解析?
Posted
技术标签:
【中文标题】为啥这个 Json 不能从 HTTP 请求中解析?【英文标题】:Why this Json cannot be resolved from the HTTP request?为什么这个 Json 不能从 HTTP 请求中解析? 【发布时间】:2018-04-15 20:55:44 【问题描述】:我的代码基于SpringBoot
,接收post
请求,解析json
数据并使用jdbc执行。
public class ETLController
@Autowired
@Qualifier("ETLService")
private ETLServiceImpl ETLServiceImpl;
@RequestMapping(value = "/sql", method = RequestMethod.POST)
@ResponseBody
/**
* @param sqlString
*/
public String identify(HttpServletRequest request)
//String sqlString, int maxRowNum, int maxColumnNum, int maxDuration, long startTime, String killQueryJob, int processResult
System.out.println("request: "+request) ;
String requestJson = request.getParameter("parametersJson");
System.out.println("requestJson: "+requestJson) ;
//Json parser
JsonObject object = Json.parse(requestJson).asObject();
//connection parameters
String connString = object.get("connString").asString();
String connUserName = object.get("connUserName").asString();
String connPassWord = object.get("connPassWord").asString();
//HQL query parameter
String sqlString = object.get("sqlString").asString();
int maxRowNum = object.get("maxRowNum").asInt();
int maxColumnNum = object.get("maxColumnNum").asInt();
int maxDuration = object.get("maxDuration").asInt();
String sqlResult = ETLServiceImpl.executeShellScript(connString, connUserName, connPassWord, sqlString, maxRowNum, maxColumnNum, maxDuration);
return sqlResult;
curl命令如下:
curl -H "Content-Type: application/json" -X POST --data '"sqlString":"select room_id from dim.dim_room","connString":"jdbc:hive2://192.168.7.21:10001/","connUserName":"xxxx","connPassWord":"xxxx","maxRowNum":500,"maxColumnNum":10,"maxDuration":6000' http://192.168.7.24:xxx/etl/sql
但是,当我通过 curl 发送 post 请求时,无法解析参数并且requestJson
始终为空。
为什么会出现这个问题以及如何解决?
堆栈跟踪:
2017-11-03 14:45:32.290 ERROR 181818 --- [nio-9162-exec-7] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.NullPointerException: string is null] with root cause
java.lang.NullPointerException: string is null
at com.eclipsesource.json.Json.parse(Json.java:292) ~[minimal-json-0.9.4.jar!/:na]
at com.lz.web.action.etl.ETLController.identify(ETLController.java:39) ~[classes!/:1.0-SNAPSHOT]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_101]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_101]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_101]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_101]
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205) ~[spring-web-4.3.10.RELEASE.jar!/:4.3.10.RELEASE]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:133) ~[spring-web-4.3.10.RELEASE.jar!/:4.3.10.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:97) ~[spring-webmvc-4.3.10.RELEASE.jar!/:4.3.10.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827) ~[spring-webmvc-4.3.10.RELEASE.jar!/:4.3.10.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738) ~[spring-webmvc-4.3.10.RELEASE.jar!/:4.3.10.RELEASE]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85) ~[spring-webmvc-4.3.10.RELEASE.jar!/:4.3.10.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:967) ~[spring-webmvc-4.3.10.RELEASE.jar!/:4.3.10.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901) ~[spring-webmvc-4.3.10.RELEASE.jar!/:4.3.10.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) ~[spring-webmvc-4.3.10.RELEASE.jar!/:4.3.10.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872) ~[spring-webmvc-4.3.10.RELEASE.jar!/:4.3.10.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:661) ~[tomcat-embed-core-8.5.16.jar!/:8.5.16]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846) ~[spring-webmvc-4.3.10.RELEASE.jar!/:4.3.10.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:742) ~[tomcat-embed-core-8.5.16.jar!/:8.5.16]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[tomcat-embed-core-8.5.16.jar!/:8.5.16]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.16.jar!/:8.5.16]
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) ~[tomcat-embed-websocket-8.5.16.jar!/:8.5.16]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.16.jar!/:8.5.16]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.16.jar!/:8.5.16]
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) ~[spring-web-4.3.10.RELEASE.jar!/:4.3.10.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.10.RELEASE.jar!/:4.3.10.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.16.jar!/:8.5.16]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.16.jar!/:8.5.16]
at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:105) ~[spring-web-4.3.10.RELEASE.jar!/:4.3.10.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.10.RELEASE.jar!/:4.3.10.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.16.jar!/:8.5.16]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.16.jar!/:8.5.16]
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:81) ~[spring-web-4.3.10.RELEASE.jar!/:4.3.10.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.10.RELEASE.jar!/:4.3.10.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.16.jar!/:8.5.16]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.16.jar!/:8.5.16]
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197) ~[spring-web-4.3.10.RELEASE.jar!/:4.3.10.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.10.RELEASE.jar!/:4.3.10.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.16.jar!/:8.5.16]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.16.jar!/:8.5.16]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198) ~[tomcat-embed-core-8.5.16.jar!/:8.5.16]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) [tomcat-embed-core-8.5.16.jar!/:8.5.16]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:478) [tomcat-embed-core-8.5.16.jar!/:8.5.16]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140) [tomcat-embed-core-8.5.16.jar!/:8.5.16]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:80) [tomcat-embed-core-8.5.16.jar!/:8.5.16]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87) [tomcat-embed-core-8.5.16.jar!/:8.5.16]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342) [tomcat-embed-core-8.5.16.jar!/:8.5.16]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:799) [tomcat-embed-core-8.5.16.jar!/:8.5.16]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) [tomcat-embed-core-8.5.16.jar!/:8.5.16]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868) [tomcat-embed-core-8.5.16.jar!/:8.5.16]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1455) [tomcat-embed-core-8.5.16.jar!/:8.5.16]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-8.5.16.jar!/:8.5.16]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_101]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_101]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.5.16.jar!/:8.5.16]
at java.lang.Thread.run(Thread.java:745) [na:1.8.0_101]
【问题讨论】:
您应该决定是要发送 POST 请求还是 GET 请求。您的 curl 输入对于 POST 请求是错误的(它不应包含诸如“parametersJson”之类的参数名称,它应该只包含 JSON 内容),并且您的服务器会像需要 GET 请求一样查找参数。 请使用错误堆栈跟踪添加/更新您的问题 Trying to use Spring Boot REST to Read JSON String from POST的可能重复 @Eran 感谢您的回复。该命令一开始不包含参数名称,但不起作用。 @SuperDelta 因为您正在发送 POST 请求,但您的服务器似乎期待 GET 请求。 【参考方案1】:使用类成员创建一个 Pojo 类,该类成员应与您传递的 JSON
中可用的键相同。
public class ConnectionString
private String sqlString;
private String connString;
private String connUserName;
private String connPassWord;
private Long maxRowNum ;
private Long maxColumnNum;
private Long maxDuration;
//all getters and setters.
现在对您的方法 identify()
做一个简单的更改,直接将其作为 Java 对象接收。
试试这个方法定义(见改变的参数)
public String identify(HttpServletRequest request, @RequestBody ConnectionString connectionString)
//here how receive your data you passed using curl.
System.out.println(connectionString.getSqlString());
// this will print the value you passed as a body.
您还需要编辑您传递的 curl 正文 json 数据,例如删除密钥 parametersJson
试试这个
'"sqlString":"select room_id from dim.dim_room","connString":"jdbc:hive2://192.168.7.21:10001/","connUserName":"xxxx","connPassWord":"xxxx","maxRowNum":500,"maxColumnNum":10,"maxDuration":6000'
而不是
'parametersJson='"sqlString":"select room_id from dim.dim_room","connString":"jdbc:hive2://192.168.7.21:10001/","connUserName":"xxxx","connPassWord":"xxxx","maxRowNum":500,"maxColumnNum":10,"maxDuration":6000''
注意 - Spring 会自动将您的
requestbody
数据更改为JavaObject
。 Spring 内部使用jackson-databind
jar 类来执行此操作。 :)
【讨论】:
【参考方案2】:下面可以试试
curl -H "Content-Type: application/json" -X POST -d '"sqlString":"select room_id from dim.dim_room","connString":"jdbc:hive2://192.168.7.21:10001/","connUserName":"magic","connPassWord":"w8spDGCJVMG3J2MWio5X","maxRowNum":500,"maxColumnNum":10,"maxDuration":6000' http://192.168.7.24:xxx/etl/sql
【讨论】:
你应该解释你有什么更新以及为什么你认为这会奏效【参考方案3】:尝试:
public String identify(HttpServletRequest request, @RequestBody String parametersJson)...
【讨论】:
如果您将其作为String
接收,则需要将其转换为Java Object
以执行进一步的任务。谢谢你:)
是的。无论如何,您正在做相同的 JsonObject object = Json.parse(requestJson).asObject();以上是关于为啥这个 Json 不能从 HTTP 请求中解析?的主要内容,如果未能解决你的问题,请参考以下文章
为啥 Javascript 不能从字符串文字中解析这个 JSON 数组?