一、接收请求参数的常见方式
1、前端请求参数放在路径上的情况
1)使用路径参数注解@PathVariable,注解属性value(默认),指明对应参数名
@GetMapping(value = "/getInfo/{gId}/{gName}")
public AjaxResult getInfo(@PathVariable("gId") Long gId, @PathVariable("gName") Long gName)
{
return AjaxResult.success(ylJgService.selectYlJgByGId(gId));
}
前端请求时只需要将参数放在路径上即可,如下
http://localhost:8080/wms/getInfo/1001/海口市
2)通过方法形参接收请求参数:就是直接把请求参数写在Controller方法的形参中,要求形参名称与请求参数名称完全相同
@RequestMapping("/register")
public String register(String uname, String upass, String reupass){
if("wangguodong".equals(uname) && "123".equals(upass) && "123".equals(reupass)){
return "login" ;
}else{
model.addAttribute("uname", uname) ;
return "register" ;
}
}
3)通过实体类接受请求参数,要求实体类字段名与请求参数名相同;不相同不会报错,但是参数接收不到
这种方法与“前端将参数放在请求体”、后端通过@RequestBody接收有类似的地方,但是不用混淆。
3中说的还是“前端将参数放在请求路径”这种情况,后端接收也不用@RequestBody;只写一个实体类,只要字段名与参数名对应,也可以接收参数。
4)通过@RequestParam接收请求参数,请求参数名可以与接收参数名称不一致,如果不一致通过注解的value值(默认)来确定对应关系
@RequestMapping("/login")
public String login(@RequestParam String uname, @RequestParam String upass){
if("wangguodong".equals(uname) && "123".equals(upass)){
return "main";
}else{
model.addAttribute("messageError", "用户名或密码错误") ;
return "login";
}
}
5)通过HttpServletRequest接收请求参数,适用于get和post请求方式。
@RequestMapping("/login")
public String login(HttpServletRequest request){
String uname = request.getParameter("uname") ;
String upass = request.getParameter("upass") ;
if("wangguodong".equals(uname) && "123".equals(upass)){
return "main";
}else{
model.addAttribute("messageError", "用户名或密码错误") ;
return "login";
}
}
2、前端请求参数放在请求体的情况,补充:Get、Post、Put等请求,都可以将参数放在body中(但是get有大小限制)
1)使用@RequestBody注解接收请求参数,如下图
2)文件参数,即MultipartFile类型的参数,也要写参数名;再postman中可以这样测试
注意,传输文件的请求必须用post请求。
因为get请求有大小限制,
get请求有大小限制这种说法也不准确,其实http协议对get请求没有大小、长度限制,限制产生在浏览器和服务器。
服务器一般限制get请求大小在8kb以内;
而浏览器又随型号不通、限制也各不相同,MSIE和Safari的长度限制是2kb,Opear是4kb,Firefox是8KB…
3、前端在一个接口中即传普通参数、又传文件参数,后端的接收方法,以及用Postman的测试方式
1)postman测试
传参方式:参数放在请求体中,用form-data格式;普通格式参数选text,文件参数选择file
2)后端可以用实体类直接接收
后端接收方式有点类似参数放在请求路径时那种,但只是类似、并不一样,参数中有文件,入参是放在请求体中的。
4、前端以Base64串的格式传输图片,后端接收、以及postman测试方法
1)场景描述
前端传的图片,不是以文件流格式,无法用MultipartFile对接接收,传的是base64字符串,如图所示
2)后端接收及处理方式
我的方式是,后端先用字符串接收,然后处理成MultipartFile。
提供两个工具类
public class ImageUtils {
public static MultipartFile base64ToMultipartFile(String base64) {
//base64编码后的图片有头信息所以要分离出来 [0]data:image/png;base64, 图片内容为索引[1]
String[] baseStrs = base64.split(",");
//取索引为1的元素进行处理
byte[] b = Base64.decode(baseStrs[1]);
for (int i = 0; i < b.length; ++i) {
if (b[i] < 0) {
b[i] += 256;
}
}
//处理过后的数据通过Base64DecodeMultipartFile转换为MultipartFile对象
return new Base64DecodeMultipartFile(b, baseStrs[0]);
}
}
public class Base64DecodeMultipartFile implements MultipartFile {
private final byte[] imgContent;
private final String header;
public Base64DecodeMultipartFile(byte[] imgContent, String header) {
this.imgContent = imgContent;
this.header = header.split(";")[0];
}
@Override
public String getName() {
return System.currentTimeMillis() + Math.random() + "." + header.split("/")[1];
}
@Override
public String getOriginalFilename() {
return System.currentTimeMillis() + (int) Math.random() * 10000 + "." + header.split("/")[1];
}
@Override
public String getContentType() {
return header.split(":")[1];
}
@Override
public boolean isEmpty() {
return imgContent == null || imgContent.length == 0;
}
@Override
public long getSize() {
return imgContent.length;
}
@Override
public byte[] getBytes() throws IOException {
return imgContent;
}
@Override
public InputStream getInputStream() throws IOException {
return new ByteArrayInputStream(imgContent);
}
@Override
public void transferTo(File dest) throws IOException, IllegalStateException {
new FileOutputStream(dest).write(imgContent);
}
}
使用方式如下:
//base64串用Record对象中的picFile字符串接收,然后通过上面的工具类型进行转换
String picFile = record.getPicFile();
if(StringUtil.isEmpty(picFile)){
return Result.failure("请上传推荐截图");
}else {
//用上面提供的工具类进行转换
MultipartFile multipartFile = ImageUtils.base64ToMultipartFile(picFile);
。。。
}
3)postman测试
就和传普通字符串一样
二、Http请求相关问题汇总
1、SpringMVC项目,Controller接口没加@ResponseBody注解,导值返回404
1)问题描述
写了一个普通接口,期望返回一个对象(对象的json格式),但是实际却返回的404。
错误示例:
@PostMapping("/json/import")
public Result importByJson(@RequestBody WecomTagQuery wecomTagQuery){
Result result = Result.failure();
//推送
try{
String str = wecomTagService.saveOrUpdateByJson(wecomTagQuery.getTag_list());
result = Result.success();
result.setInfo(str);
}catch (Exception e){
e.printStackTrace();
result.setInfo("执行失败!");
}
return result;
}
错误结果:
<!doctype html>
<html lang="en">
<head><title>HTTP Status 404 – Not Found</title><style type="text/css">h1 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:22px;} h2 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:16px;} h3 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:14px;} body {font-family:Tahoma,Arial,sans-serif;color:black;background-color:white;} b {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;} p {font-family:Tahoma,Arial,sans-serif;background:white;color:black;font-size:12px;} a {color:black;} a.name {color:black;} .line {height:1px;background-color:#525D76;border:none;}</style></head>
<body><h1>HTTP Status 404 – Not Found</h1><hr class="line" /><p><b>Type</b> Status Report</p><p><b>Message</b> /admin/page/wecom/tag/json/import.jsp</p><p><b>Description</b> The origin server did not find a current representation for the target resource or is not willing to disclose that one exists.</p><hr class="line" /><h3>Apache Tomcat/8.5.39</h3></body>
</html>
2)原因分析
不加**@ResponseBody**注解springmvc框架会认为方法返回的是一个 ModelAndViewer对象,即视图对象,那么它就会去找这么一个对象,找不到则报404错。
3)解决
a、
SpringMVC项目,需要直接返回结果、而不是视图的Controller接口,要加**@ResponseBody**注解
正确示例:
@PostMapping("/json/import")
@ResponseBody
public Result importByJson(@RequestBody WecomTagQuery wecomTagQuery){
Result result = Result.failure();
//推送
try{
String str = wecomTagService.saveOrUpdateByJson(wecomTagQuery.getTag_list());
result = Result.success();
result.setInfo(str);
}catch (Exception e){
e.printStackTrace();
result.setInfo("执行失败!");
}
return result;
}
b、
现在越来越多系统是前后端分离的项目(前端用vue),这时后端controller接口返回的基本都不是视图对象,这样的话可以直接在Controller接口上、将@Controller注解替换成@RestController;
@RestController就等于@Controller + @ResponseBody,这样该Controller接口下的所有接口(直接返回json,不返回视图的接口),就都不用加@ResponseBody注解了。
2、请求体和请求路径上都有参数时,报400错误
1)问题描述
请求方式不限(post、get等都可),要求请求体中可传参数(如果有),路径上也有参数(5种方式都可);
但是我刚开始这样请求,报错“400 bad request”。
2)原因分析
因为后端接口,要求请求体传参,没有参数时可以不传参,但是请求体不能是none、请求头的需要有Context-Type。
我一开始,因为请求体没有入参,就没有设置请求体
这会导致请求头没有Context-Type,不符合后端接口的要求。
3)解决
即使这次请求没有body参数,也要设置请求体,里面不传参数就可以了
如图设置好以后,请求头就有Context-Type了
注意,body不仅不能选none,选择raw-json后,还要加{},否则也不行。