假设我有一个页面,列出了一个表上的对象,我需要放一个表单来过滤表。过滤器作为Ajax GET发送到如下URL: http://foo.com/system/controller/action?page=1&prop1=x&prop2=y&prop3=z

而不是在我的控制器上有很多参数,比如:

@RequestMapping(value = "/action")
public @ResponseBody List<MyObject> myAction(
    @RequestParam(value = "page", required = false) int page,
    @RequestParam(value = "prop1", required = false) String prop1,
    @RequestParam(value = "prop2", required = false) String prop2,
    @RequestParam(value = "prop3", required = false) String prop3) { ... }

假设我有MyObject为:

public class MyObject {
    private String prop1;
    private String prop2;
    private String prop3;

    //Getters and setters
    ...
}

我想做的是:

@RequestMapping(value = "/action")
public @ResponseBody List<MyObject> myAction(
    @RequestParam(value = "page", required = false) int page,
    @RequestParam(value = "myObject", required = false) MyObject myObject,) { ... }

这可能吗? 我该怎么做呢?


当前回答

接受的答案就像一个魅力,但如果对象有一个对象列表,它不会像预期的那样工作,所以这里是我的解决方案后,一些挖掘。

遵循这个线程建议,以下是我的做法。

Frontend: stringalize你的对象,而不是在base64编码提交。 后端:解码base64字符串,然后将字符串json转换为所需的对象。

它不是最好的调试你的API与邮差,但它是为我工作预期。

原始对象:{页:1,大小:5,过滤器:[{字段:“id”,值:1,比较:“EQ”} 编码对象:eyJwYWdlIjoxLCJzaXplIjo1LCJmaWx0ZXJzIjpbeyJmaWVsZCI6ImlkUGFyZW50IiwiY29tcGFyaXNvbiI6Ik5VTEwifV19

@GetMapping
fun list(@RequestParam search: String?): ResponseEntity<ListDTO> {
    val filter: SearchFilterDTO = decodeSearchFieldDTO(search)
    ...
}

private fun decodeSearchFieldDTO(search: String?): SearchFilterDTO {
    if (search.isNullOrEmpty()) return SearchFilterDTO()
    return Gson().fromJson(String(Base64.getDecoder().decode(search)), SearchFilterDTO::class.java)
}

这里是SearchFilterDTO和FilterDTO

class SearchFilterDTO(
    var currentPage: Int = 1,
    var pageSize: Int = 10,
    var sort: Sort? = null,
    var column: String? = null,
    var filters: List<FilterDTO> = ArrayList<FilterDTO>(),
    var paged: Boolean = true
)

class FilterDTO(
    var field: String,
    var value: Any,
    var comparison: Comparison
)

其他回答

你完全可以这样做,只需要删除@RequestParam注释,Spring就会把你的请求参数绑定到你的类实例上:

public @ResponseBody List<MyObject> myAction(
    @RequestParam(value = "page", required = false) int page,
    MyObject myObject)

接受的答案就像一个魅力,但如果对象有一个对象列表,它不会像预期的那样工作,所以这里是我的解决方案后,一些挖掘。

遵循这个线程建议,以下是我的做法。

Frontend: stringalize你的对象,而不是在base64编码提交。 后端:解码base64字符串,然后将字符串json转换为所需的对象。

它不是最好的调试你的API与邮差,但它是为我工作预期。

原始对象:{页:1,大小:5,过滤器:[{字段:“id”,值:1,比较:“EQ”} 编码对象:eyJwYWdlIjoxLCJzaXplIjo1LCJmaWx0ZXJzIjpbeyJmaWVsZCI6ImlkUGFyZW50IiwiY29tcGFyaXNvbiI6Ik5VTEwifV19

@GetMapping
fun list(@RequestParam search: String?): ResponseEntity<ListDTO> {
    val filter: SearchFilterDTO = decodeSearchFieldDTO(search)
    ...
}

private fun decodeSearchFieldDTO(search: String?): SearchFilterDTO {
    if (search.isNullOrEmpty()) return SearchFilterDTO()
    return Gson().fromJson(String(Base64.getDecoder().decode(search)), SearchFilterDTO::class.java)
}

这里是SearchFilterDTO和FilterDTO

class SearchFilterDTO(
    var currentPage: Int = 1,
    var pageSize: Int = 10,
    var sort: Sort? = null,
    var column: String? = null,
    var filters: List<FilterDTO> = ArrayList<FilterDTO>(),
    var paged: Boolean = true
)

class FilterDTO(
    var field: String,
    var value: Any,
    var comparison: Comparison
)

是的,你可以用一种简单的方法做。见下面的行代码。

URL - http://localhost:8080/get/request/multiple/param/by/map?name='abc' & id='123'

 @GetMapping(path = "/get/request/header/by/map")
    public ResponseEntity<String> getRequestParamInMap(@RequestParam Map<String,String> map){
        // Do your business here 
        return new ResponseEntity<String>(map.toString(),HttpStatus.OK);
    } 

由于在每篇文章下面都会弹出关于如何设置字段强制的问题,我写了一个关于如何按要求设置字段的小例子:

public class ExampleDTO {
    @NotNull
    private String mandatoryParam;

    private String optionalParam;
    
    @DateTimeFormat(iso = ISO.DATE) //accept Dates only in YYYY-MM-DD
    @NotNull
    private LocalDate testDate;

    public String getMandatoryParam() {
        return mandatoryParam;
    }
    public void setMandatoryParam(String mandatoryParam) {
        this.mandatoryParam = mandatoryParam;
    }
    public String getOptionalParam() {
        return optionalParam;
    }
    public void setOptionalParam(String optionalParam) {
        this.optionalParam = optionalParam;
    }
    public LocalDate getTestDate() {
        return testDate;
    }
    public void setTestDate(LocalDate testDate) {
        this.testDate = testDate;
    }
}

//Add this to your rest controller class
@RequestMapping(value = "/test", method = RequestMethod.GET)
public String testComplexObject (@Valid ExampleDTO e){
    System.out.println(e.getMandatoryParam() + " " + e.getTestDate());
    return "Does this work?";
}

虽然引用@ModelAttribute、@RequestParam、@PathParam等答案是有效的,但我遇到了一个小问题。产生的方法参数是Spring封装在DTO周围的代理。因此,如果您试图在需要自定义类型的上下文中使用它,可能会得到一些意想不到的结果。

以下选项无效:

@GetMapping(produces = APPLICATION_JSON_VALUE)
public ResponseEntity<CustomDto> request(@ModelAttribute CustomDto dto) {
    return ResponseEntity.ok(dto);
}

在我的例子中,尝试在Jackson绑定中使用它导致了一个com.fasterxml.jackson.databind.exc.InvalidDefinitionException。

您需要从dto中创建一个新对象。