Spring MVC中Controller接收请求参数的常见方式

发布时间 2024-01-01 15:27:42作者: 残城碎梦

在Spring中 Controller注解用于指示Spring类的实例是一个控制器,相对于实现Controller接口变得更加简单。而且实现Controller接口只能处理一个单一的请求,而是用@Controller注解可以支持同时处理多个请求动作,更加灵活。

@Controller用于标记一个类,使用他标记的类就是一个SpringMVC Controller对象,即一个控制器类,Spring使用扫描机制查找应用程序中所有基于注解的控制器类。分发处理器会扫描使用了该注解的类的方法,并检测该方法是否使用了@RequestMapping注解的方法才是真正处理请求的处理器。

非JSON方式接收请求参数

普通方式-请求参数名和Controller方法的参数一致

GET请求和POST请求都支持

@Controller
@RequestMapping("/param")
public class TestParamController {

    private static final Logger logger = LoggerFactory.getLogger(TestParamController.class);

    /**
     * 请求参数名和Controller方法的参数一致
     * produces 设置返回参数的编码格式可以设置返回数据的类型以及编码,可以是json或者xml
     * {
     *     @RequestMapping(value="/xxx",produces = {"application/json;charset=UTF-8"})
     *      或
     *     @RequestMapping(value="/xxx",produces = {"application/xml;charset=UTF-8"})
     *      或
     *     @RequestMapping(value="/xxx",produces = "{text/html;charset=utf-8}")
     * }
     * @param name 用户名
     * @param pwd 密码
     * @return
     *
     */
    @RequestMapping(value = "/add", method = RequestMethod.GET, produces = {"application/json;charset=UTF-8"})
    @ResponseBody
    public String addUser(String name, String pwd) {
        logger.debug("name:" + name + ",pwd:" + pwd);
        return "name:" + name + ",pwd:" + pwd;
    }
}

通过访问:GET http://localhost:8080/param/add?name=张三&pwd=123456

对象方式-请求参数名和Controller方法中的对象的参数一致

GET请求和POST请求都支持

Employee实体类:

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Employee {
    private Integer id;
    private String lastName;
    private Integer gender;
    private String email;
    private Integer dId;
}

controller实现

@RestController
@RequestMapping("/param")
@Slf4j
public class ParamsController {
    @GetMapping("/employee")
    public String addEmployee(Employee employee){
        return "lastName:"+employee.getLastName()+",email:"+employee.getEmail();
    }
}

通过访问:http://127.0.0.1:8080/param/employee?lastName=战三&email=33453432@qq.com

 

通过HttpServletRequst接收请求参数

GET请求和POST请求都支持

@RestController
@RequestMapping("/param")
public class TestParamController2 {

    @RequestMapping(value = "/add2")
    public String add(HttpServletRequest request){
        String name = request.getParameter("name");
        String pwd = request.getParameter("pwd");
        return "name:" + name + ",pwd:" + pwd;
    }
}

通过@RequestParam注解接收请求参数

GET请求和POST请求都支持

RequestParam注解作用:把请求中的指定名称的参数传递给控制器中的形参赋值

注解属性:

  • value:请求参数中的名称
  • required:请求参数中是否必须提供此参数,默认值是true,必须提供
  • defaultValue:设置默认值,仅当传入参数为空时有效
@RestController
@RequestMapping("/param")
public class TestParamController3 {

    @RequestMapping(value = "/add3")
    public String add(@RequestParam(value = "name", required = false) String name, @RequestParam(value = "pwd", required = false) String pwd) {
        return "name:" + name + ",pwd:" + pwd;
    }
}

通过PathVariable注解接收请求参数

GET请求和POST请求都支持

PathVariable注解作用:拥有绑定url中的占位符的。例如:url中有/delete/{id},{id}就是占位符

注解属性 value:指定url中的占位符名称

优点:Restful风格的URL 请求路径一样,可以根据不同的请求方式去执行后台的不同方法

@RestController
@RequestMapping("/param")
public class TestParamController4 {

    @RequestMapping(path = "/hello/{id}")
    public String sayHello(@PathVariable(value = "id") String id) {
        return "id=" + id;
    }
}

JSON格式接收请求入参

JSON格式接收普通对象

@RestController
@RequestMapping("/resp")
@Slf4j
public class ParamsRespController {
    
    @PostMapping("/test")
    public String addEmployee(@RequestBody Employee employee){
        return "lastName:"+employee.getLastName()+",email:"+employee.getEmail();
    }
}

JSON格式接收List对象

@RestController
@RequestMapping("/resplist")
@Slf4j
public class ParamsRespListController {
    @PostMapping("/testlist")
    public String addEmployee(@RequestBody List<Employee> employees){
        StringBuilder sb = new StringBuilder("{");
        if( null != employees){
            for(Employee employee:employees){
                sb.append("{"+"lastName:"+employee.getLastName()+",email:"+employee.getEmail()+"}");
            }
        }
        sb.append("}");
        return sb.toString();
    }
}

JSON格式接收Map对象

@RestController
@RequestMapping("/respmap")
@Slf4j
public class ParamsRespMapController {
    @PostMapping("/testmap")
    public String addEmployee(@RequestBody Map<String,Employee> employees){
        StringBuilder sb = new StringBuilder("[");
        if( null != employees){
            for(Map.Entry<String,Employee> employeeEntry : employees.entrySet()){
                sb.append(employeeEntry.getKey()+":"+employeeEntry.getValue()+",");
            }
        }
        sb.append("]");
        return sb.toString();
    }
}

Spring MVC接收数组的三种方式

第一种方式

页面正常通过Key-Value的形式传值,数组保持原格式,后端使用@RequestParam注解标注接值的入参,注意@RequestParam里的value一定要带上中括号:

@RequestMapping("/test.htm")
@ResponseBody
public AjaxResp test(@RequestParam("dataList[]") List<String> dataList, String name){
    //do something
}

页面JS:

var dataList = [1,2,3];
$.get({
    url: "/test.htm",
    data: {dataList: dataList,name:'jack'},
    success: function (data) {
        //do something
    }
});

这种方式的好处是简单,方便。get请求和post请求都可以传值,并且后台接值的参数类型可以是List集合也可以用String[]数组。不过这种方式可能报文看起来比较奇怪。

第二种方式

页面正常通过Key-Value的形式传值,数组使用逗号分割的形式的字符串(可以使用toString()或join()将数组转成这种格式),后端使用String[]数组接值。

@RequestMapping("/test.htm")
@ResponseBody
public AjaxResp test(String[] dataList, String name){
    //do something
}

页面JS:

var dataList = "1,2,3";
$.get({
    url: "/test.htm",
    data: {dataList: dataList,name:'jack'},
    success: function (data) {
        //do something
    }
});

注意这种方式后端接口得用String[]数组来接,如果你直接用List集合会抛下面这个异常:

Could not instantiate bean class [java.util.List]: Specified class is an interface

加上@RequestParam注解并且设置value之后就可以用List集合类型了:

@RequestMapping("/test.htm")
@ResponseBody
public AjaxResp test(@RequestParam("dataList") List<String> dataList, String name){
    //do something
}

这种方式同样支持get和post请求,并且报文也没那么奇怪,推荐使用。

第三种方式

前台使用json来传值,后台使用一个数据对象来接值:

public class Dto {
    private List<String> dataList;
    private String name;

    //getters and setters
}

controller,记得加上@RequestBody,spring才能帮我们解析json对象:

@RequestMapping(value = "/test.htm", method = RequestMethod.POST)
@ResponseBody
public AjaxResp test(@RequestBody Dto dto){
    //do something
}

页面JS:

var payload = {};
payload.dataList = ["1","2","3"];
payload.name="jack";

$.post({
    url: "test.htm",
    contentType:"application/json",
    data: JSON.stringify(payload),
    success: function (data) {
        //do something
    }
});

这种方式比较适合用post请求传输多个复杂字段时候使用。记得发送请求的时候设置contentType:"application/json",表示给的是json格式的数据。