Spring MVC : GET @RequestParam과 같은 복잡한 객체
테이블의 객체를 나열하는 페이지가 있고 테이블을 필터링하기 위해 양식을 넣어야한다고 가정합니다. 필터는 다음과 같은 URL에 Ajax GET으로 전송됩니다. 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,) { ... }
가능합니까? 어떻게해야합니까?
@RequestParam
주석을 제거하면 Spring이 요청 매개 변수를 클래스 인스턴스에 깔끔하게 바인딩합니다.
public @ResponseBody List<MyObject> myAction(
@RequestParam(value = "page", required = false) int page,
MyObject myObject)
나는 저에게서 짧은 예를 추가 할 것입니다.
DTO 수업 :
public class SearchDTO {
private Long id[];
public Long[] getId() {
return id;
}
public void setId(Long[] id) {
this.id = id;
}
// reflection toString from apache commons
@Override
public String toString() {
return ReflectionToStringBuilder.toString(this, ToStringStyle.SHORT_PREFIX_STYLE);
}
}
컨트롤러 클래스 내부의 요청 매핑 :
@RequestMapping(value="/handle", method=RequestMethod.GET)
@ResponseBody
public String handleRequest(SearchDTO search) {
LOG.info("criteria: {}", search);
return "OK";
}
질문:
http://localhost:8080/app/handle?id=353,234
결과:
[http-apr-8080-exec-7] INFO c.g.g.r.f.w.ExampleController.handleRequest:59 - criteria: SearchDTO[id={353,234}]
나는 그것이 도움이되기를 바랍니다 :)
업데이트 / 코 틀린
Because currently I'm working a lot of with Kotlin if someone wants to define similar DTO the class in Kotlin should have the following form:
class SearchDTO {
var id: Array<Long>? = arrayOf()
override fun toString(): String {
// to string implementation
}
}
With the data
class like this one:
data class SearchDTO(var id: Array<Long> = arrayOf())
the Spring (tested in Boot) returns the following error for request mentioned in answer:
"Failed to convert value of type 'java.lang.String[]' to required type 'java.lang.Long[]'; nested exception is java.lang.NumberFormatException: For input string: \"353,234\""
The data class will work only for the following request params form:
http://localhost:8080/handle?id=353&id=234
Be aware of this!
I have a very similar problem. Actually the problem is deeper as I thought. I am using jquery $.post
which uses Content-Type:application/x-www-form-urlencoded; charset=UTF-8
as default. Unfortunately I based my system on that and when I needed a complex object as a @RequestParam
I couldn't just make it happen.
In my case I am trying to send user preferences with something like;
$.post("/updatePreferences",
{id: 'pr', preferences: p},
function (response) {
...
On client side the actual raw data sent to the server is;
...
id=pr&preferences%5BuserId%5D=1005012365&preferences%5Baudio%5D=false&preferences%5Btooltip%5D=true&preferences%5Blanguage%5D=en
...
parsed as;
id:pr
preferences[userId]:1005012365
preferences[audio]:false
preferences[tooltip]:true
preferences[language]:en
and the server side is;
@RequestMapping(value = "/updatePreferences")
public
@ResponseBody
Object updatePreferences(@RequestParam("id") String id, @RequestParam("preferences") UserPreferences preferences) {
...
return someService.call(preferences);
...
}
I tried @ModelAttribute
, added setter/getters, constructors with all possibilities to UserPreferences
but no chance as it recognized the sent data as 5 parameters but in fact the mapped method has only 2 parameters. I also tried Biju's solution however what happens is that, spring creates an UserPreferences object with default constructor and doesn't fill in the data.
I solved the problem by sending JSon string of the preferences from the client side and handle it as if it is a String on the server side;
client:
$.post("/updatePreferences",
{id: 'pr', preferences: JSON.stringify(p)},
function (response) {
...
server:
@RequestMapping(value = "/updatePreferences")
public
@ResponseBody
Object updatePreferences(@RequestParam("id") String id, @RequestParam("preferences") String preferencesJSon) {
String ret = null;
ObjectMapper mapper = new ObjectMapper();
try {
UserPreferences userPreferences = mapper.readValue(preferencesJSon, UserPreferences.class);
return someService.call(userPreferences);
} catch (IOException e) {
e.printStackTrace();
}
}
to brief, I did the conversion manually inside the REST method. In my opinion the reason why spring doesn't recognize the sent data is the content-type.
Since the question on how to set fields mandatory pops up under each post, I wrote a small example on how to set fields as required:
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;
}
}
@RequestMapping(value = "/test", method = RequestMethod.GET)
public String testComplexObject (@Valid ExampleDTO e){
System.out.println(e.getMandatoryParam() + " " + e.getTestDate());
return "Does this work?";
}
While answers that refer to @ModelAttribute
, @RequestParam
, @PathParam
and the likes are valid, there is a small gotcha I ran into. The resulting method parameter is a proxy that Spring wraps around your DTO. So, if you attempt to use it in a context that requires your own custom type, you may get some unexpected results.
The following will not work:
@GetMapping(produces = APPLICATION_JSON_VALUE)
public ResponseEntity<CustomDto> request(@ModelAttribute CustomDto dto) {
return ResponseEntity.ok(dto);
}
In my case, attempting to use it in Jackson binding resulted in a com.fasterxml.jackson.databind.exc.InvalidDefinitionException
.
You will need to create a new object from the dto.
참고URL : https://stackoverflow.com/questions/16942193/spring-mvc-complex-object-as-get-requestparam
'Programming' 카테고리의 다른 글
가능한 두 테이블 중 하나에 MySQL 외래 키를 수행 할 수 있습니까? (0) | 2020.05.26 |
---|---|
AngularJS는 jQuery보다 나은 점은 무엇입니까? (0) | 2020.05.26 |
curl에 대한 요청 헤더를 어떻게 설정합니까? (0) | 2020.05.26 |
경고 : 보호되지 않은 개인 키 파일! (0) | 2020.05.26 |
명시 적 도메인을 가진 localhost의 쿠키 (0) | 2020.05.26 |