一、接收请求参数的常见方式

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注解接收请求参数,如下图

controller层 java 使用对象接收参数 controller 接受参数_java

controller层 java 使用对象接收参数 controller 接受参数_spring_02

2)文件参数,即MultipartFile类型的参数,也要写参数名;再postman中可以这样测试

controller层 java 使用对象接收参数 controller 接受参数_spring_03

注意,传输文件的请求必须用post请求。

因为get请求有大小限制,
get请求有大小限制这种说法也不准确,其实http协议对get请求没有大小、长度限制,限制产生在浏览器和服务器。
服务器一般限制get请求大小在8kb以内;
而浏览器又随型号不通、限制也各不相同,MSIE和Safari的长度限制是2kb,Opear是4kb,Firefox是8KB…

3、前端在一个接口中即传普通参数、又传文件参数,后端的接收方法,以及用Postman的测试方式

1)postman测试

传参方式:参数放在请求体中,用form-data格式;普通格式参数选text,文件参数选择file

controller层 java 使用对象接收参数 controller 接受参数_请求参数_04

2)后端可以用实体类直接接收

后端接收方式有点类似参数放在请求路径时那种,但只是类似、并不一样,参数中有文件,入参是放在请求体中的。

controller层 java 使用对象接收参数 controller 接受参数_请求参数_05

4、前端以Base64串的格式传输图片,后端接收、以及postman测试方法

1)场景描述

前端传的图片,不是以文件流格式,无法用MultipartFile对接接收,传的是base64字符串,如图所示

controller层 java 使用对象接收参数 controller 接受参数_spring_06

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测试

就和传普通字符串一样

controller层 java 使用对象接收参数 controller 接受参数_ide_07

二、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种方式都可);

controller层 java 使用对象接收参数 controller 接受参数_请求参数_08

但是我刚开始这样请求,报错“400 bad request”。

2)原因分析

因为后端接口,要求请求体传参,没有参数时可以不传参,但是请求体不能是none、请求头的需要有Context-Type。

我一开始,因为请求体没有入参,就没有设置请求体

controller层 java 使用对象接收参数 controller 接受参数_restful_09


这会导致请求头没有Context-Type,不符合后端接口的要求。

3)解决

即使这次请求没有body参数,也要设置请求体,里面不传参数就可以了

controller层 java 使用对象接收参数 controller 接受参数_java_10


如图设置好以后,请求头就有Context-Type了

controller层 java 使用对象接收参数 controller 接受参数_java_11


注意,body不仅不能选none,选择raw-json后,还要加{},否则也不行。