springmvc中@RequestBody使用的一些注意事项

匿名 (未验证) 提交于 2019-12-03 00:30:01

众所周知,springmvc中@RequestBody的注解是一个很实用的功能,它能帮我们解析客户端(移动设备、浏览器等)发送过来的json数据,并封装到实体类中。

但我今天要说的不是它的原理,而是记录一些工作中使用@RequestBody注解遇到的一些问题,也提醒广大java开发者避免类似的问题。

最近有个需求,接收客户的设备发送过来的json数据,客户的设备里面只能修改ip,然后通过http协议的post方式发送数据过来。我很自然地想到在登录页那里处理,在toLogin方法中增加@RequestBody Kehu kehu参数,用户解析并封装json数据。

废话不多说,上代码,如下所示:

@RequestMapping(value = "/toLogin") 	public ModelAndView toLogin(HttpServletRequest request, @RequestBody Kehu kehu) throws Exception { 		// 接收客户设备发送过来的json数据 		if (kehu != null && !StringUtil.isEmpty(kehu.cmd)) { 			uploadData(kehu); 		} 		ModelAndView mv = new ModelAndView(); 		PageData pageData = this.getPageData(request); 		pageData.put("SYSNAME", Tools.readTxtFile(Const.SYSNAME)); // 读取系统名称 		mv.setViewName("base/login"); 		mv.addObject("pd", pageData); 		return mv; 	}

一切看似很完美,在浏览器上测试一下,输入localhost(我的项目已经设置为了缺省项目,端口号也改为了80)

我傻眼了,报了400错误。如下图所示:


The request sent by the client was syntactically incorrect.

翻译过来就是:客户端发送的请求在语法上是不正确的。

没加@RequestBody Kehu kehu之前是正常的,问题肯定出在了这里。我一看RequestBody的源码:

package org.springframework.web.bind.annotation;  import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;  import org.springframework.http.converter.HttpMessageConverter;  /**  * Annotation indicating a method parameter should be bound to the body of the web request.  * The body of the request is passed through an {@link HttpMessageConverter} to resolve the  * method argument depending on the content type of the request. Optionally, automatic  * validation can be applied by annotating the argument with {@code @Valid}.  *  * <p>Supported for annotated handler methods in Servlet environments.  *  * @author Arjen Poutsma  * @since 3.0  * @see RequestHeader  * @see ResponseBody  * @see org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter  * @see org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter  */ @Target(ElementType.PARAMETER) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface RequestBody {  	/** 	 * Whether body content is required. 	 * <p>Default is {@code true}, leading to an exception thrown in case 	 * there is no body content. Switch this to {@code false} if you prefer 	 * {@code null} to be passed when the body content is {@code null}. 	 * @since 3.2 	 */ 	boolean required() default true;  } 

required方法默认返回值是true。

这样问题就明朗了,我请求localhost的时候,没有传json过去,所以就会报400错误,因为客户端发送的请求在语法上是不正确的。

解决方法:在@RequestBody后面加上(required=false)就可以了。表示kehu对象可以不传入。

/** 	 * 访问登录页 	 * @RequestBody(required=false)	表示kehu对象可以不传入。 	 * 一定要加上required=false,否则登录的时候会报400错误。错误代码: 	 * The request sent by the client was syntactically incorrect. 	 * @return 	 * @throws Exception 	 */ 	@RequestMapping(value = "/toLogin") 	public ModelAndView toLogin(HttpServletRequest request, @RequestBody(required=false) Kehu kehu) throws Exception { 		// 接收硬币机发送过来的json数据 		if (kehu != null && !StringUtil.isEmpty(kehu.cmd)) { 			uploadData(kehu); 		} 		ModelAndView mv = new ModelAndView(); 		PageData pageData = this.getPageData(request); 		pageData.put("SYSNAME", Tools.readTxtFile(Const.SYSNAME)); // 读取系统名称 		mv.setViewName("base/login"); 		mv.addObject("pd", pageData); 		return mv; 	}

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!