一:通过@RequestParam 从URL 中获取参数
可以通过@RequestParam获取URL参数
@Controller
public class LoginController {
@GetMapping(value = "/test1")
@LogRequired
public String getUrlData(@RequestParam(value = "keyword1", required = true) String keyword1,
@RequestParam(value = "keyword2", required = false) String keyword2) {
System.out.println("keyword1:" + keyword1);
System.out.println("keyword2:" + keyword2);
String ret = "keyword1:" + keyword1 + " keyword2:" + keyword2;
return ret;
}
}
@RequestParam 指定的某参数的 required 属性为 true时,而访问请求又没有携带该参数,请求会被springmvc自动拦截,返回400错误。如下图:
加上 keyword1=hello 之后,依然报错如下:WhiteLable Error Page (404)
这是因为默认 springmvc 是会根据函数的返回值,去查找对应的网页资源。
给接口加上 @ResponseBody 后可以解决,注意前端没有给第二个参数时,第二个参数将会是null。
@ResponseBody注解可以简单的理解为,把函数的返回值直接返给前端。而不是去找网页资源了。
二:通过 @ResponseBody 返回JSON文档
将函数的返回值类型修改为Object,定义一个Keyword类,代码及结果如下:
@Controller
public class LoginController {
@ResponseBody
@GetMapping(value = "/test1")
@LogRequired
public Object getUrlData(@RequestParam(value = "keyword1", required = true) String keyword1,
@RequestParam(value = "keyword2", required = false) String keyword2) {
System.out.println("keyword1:" + keyword1);
System.out.println("keyword2:" + keyword2);
Keyword ret = new Keyword();
ret.keyword1 = keyword1;
ret.keyword2 = keyword2;
return ret;
}
static class Keyword {
public String keyword1;
public String keyword2;
public String getKeyword1() {
return keyword1;
}
public void setKeyword1(String keyword1) {
this.keyword1 = keyword1;
}
public String getKeyword2() {
return keyword2;
}
public void setKeyword2(String keyword2) {
this.keyword2 = keyword2;
}
}
}
三:通过@RequestBody 自动将请求参数转化为类对象
@ResponseBody
@GetMapping(value = "/test1")
@LogRequired
public Object getUrlData(@RequestBody Keyword keyword) {
System.out.println("keyword1:" + keyword.keyword1);
System.out.println("keyword2:" + keyword.keyword2);
Keyword ret = keyword;
return ret;
}
运行后,报错如下:org.springframework.http.converter.HttpMessageNotReadableException: Required request body is missing
@RequestBody 会尝试从请求的正文中获取数据,而不像@RequestParam那样会尝试从URL中获取。
因此,我们需要把@GetMapping 修改为 @PostMapping ,同时前端改成 Post 提交数据:
尝试运行,报错如下:
org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'application/x-www-form-urlencoded;charset=UTF-8' not supported
改尝试使用 Junit 来构建一个 post 请求:
@Test
public void test() throws Exception {
mMockMvc.perform(
MockMvcRequestBuilders
.post("/test1").param("keyword1", "hello1").param("keyword2", "hello2")
.contentType("application/json"))
.andExpect(MockMvcResultMatchers.status().is(200))
.andDo(MockMvcResultHandlers.print())
.andReturn();
}
很遗憾,还是不行,报错如下:
org.springframework.http.converter.HttpMessageNotReadableException: Required request body is missing: public java.lang.Object com.test.controllers.LoginController.getUrlData(com.test.controllers.LoginController$Keyword)
post的参数不可以是 key value 键值对,必须是 json 文档,另外使用 content 方法,而不是 param 方法,修改代码如下:
@Test
public void test() throws Exception {
Keyword k = new Keyword();
k.setKeyword1("hi");
k.setKeyword2("hello");
String json = new ObjectMapper().writeValueAsString(k);
mMockMvc.perform(
MockMvcRequestBuilders
.post("/test1").content(json)
.contentType("application/json"))
.andExpect(MockMvcResultMatchers.status().is(200))
.andDo(MockMvcResultHandlers.print())
.andReturn();
}
小结(摘至Spring Action 中文第四版)
@ResponseBody 注解会告知Spring,我们要将返回的对象作为资源发送给客户羰,并将其转换为客户端可接受的表达形式。更具体的讲,DispatcherServlet 将会考虑到请求中的Accept头部信息,并查找能在够为客户端提供所需表述形式的消息转换器。
举例来讲,假设客户端的Accept头部信息表明它接受 application/json.... (省略若干 字) 消息转换器会将 Controller 返回的 类转换为JSON文档。
@RequestBody 告诉 Spring 查找一个消息转换器,将来自客户 端的资源表述转换为对象。
@使用@RestController 代替 @Controller,Spring 将会为该控制器的所有处理方法应用消息转换功能。
(注意:@RestController 是 @Contoller + @ResponseBody ,但是不包括 @RequestBody )