Spring MVC: GET @RequestParam과 같은 복잡한 객체
테이블 상의 오브젝트를 나열하는 페이지가 있고 테이블을 필터링하기 위한 폼을 넣어야 한다고 가정합니다.필터는 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,) { ... }
가능합니까?내가 어떻게 그럴 수 있을까?
수 있어요. .그냥 삭제만 하면 됩니다.@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}]
도움이 되었으면 합니다:)
업데이트 / KOTLIN
현재 Kotlin과 많은 작업을 하고 있기 때문에 누군가 유사한 DTO를 정의하고 싶다면 Kotlin의 클래스는 다음과 같은 형태를 가져야 합니다.
class SearchDTO {
var id: Array<Long>? = arrayOf()
override fun toString(): String {
// to string implementation
}
}
★data
다음과 같이 합니다.
data class SearchDTO(var id: Array<Long> = arrayOf())
스프링(부트에서 테스트됨)은 응답에서 언급된 요청에 대해 다음 오류를 반환합니다.
"java.lang 유형의 값을 변환하지 못했습니다.문자열 []을(를) 필수 유형 'java.lang'으로 지정합니다.long [ ] '. nested 예외는 java.lang 입니다.NumberFormatException:입력 문자열의 경우: "353,234"
데이터 클래스는 다음 요청 매개 변수 양식에 대해서만 작동합니다.
http://localhost:8080/handle?id=353&id=234
이 점에 유의하십시오!
각 게시물 아래에 필드를 필수적으로 설정하는 방법에 대한 질문이 뜨기 때문에 필드를 필요에 따라 설정하는 방법에 대한 간단한 예를 작성했습니다.
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?";
}
저도 비슷한 문제가 있어요.사실 생각보다 문제가 더 심각해요.는 jquery jquery를 .$.post
명령어는 ""를 사용합니다.Content-Type:application/x-www-form-urlencoded; charset=UTF-8
디폴트로 합니다.도 나는 할 때 으로 했다.@RequestParam
나는 그저 그 일이 일어날 수 없었다.그냥 그렇게 만들 수 없었어요
내 경우 다음과 같은 사용자 기본 설정을 전송하려고 합니다.
$.post("/updatePreferences",
{id: 'pr', preferences: p},
function (response) {
...
클라이언트측에서는, 서버에 송신되는 실제의 미가공 데이터는 다음과 같습니다.
...
id=pr&preferences%5BuserId%5D=1005012365&preferences%5Baudio%5D=false&preferences%5Btooltip%5D=true&preferences%5Blanguage%5D=en
...
구문 분석:
id:pr
preferences[userId]:1005012365
preferences[audio]:false
preferences[tooltip]:true
preferences[language]:en
서버측에서는
@RequestMapping(value = "/updatePreferences")
public
@ResponseBody
Object updatePreferences(@RequestParam("id") String id, @RequestParam("preferences") UserPreferences preferences) {
...
return someService.call(preferences);
...
}
나는나는 노력했다 노력했다.@ModelAttribute
,, 모든 가능성을 생성자에, setter/getters, constructors를 추가 setter/getters 덧붙였다.UserPreferences
그러나 어떠한 기회로 5매개 변수로 사용하고 있지만 실제로는 매핑 된 메서드는 2매개 변수가 있는 보내데이터를 인정했다.그러나 전송된 5개의 파라미터로인식했기때문에 가능성은 없지만,실제로는 매핑된 메서드는 2개의 파라미터만가지고 있습니다 데이터를.나는 또한 Biju의 해결책 그러나 어떤, 봄과 데이터의 양을 채우지 않는다 기본 생성자를 가진UserPreferences 개체를 만들어 냅니다 노력했다.Biju의 솔루션도 시도해 보았습니다만,스프링이기본 생성자를 사용하여 UserPreferences만들고데이터를 입력하지 않습니다 객체를.
클라이언트측에서 프리퍼런스의 JSon 문자열을 송신해, 서버측의 String인 것처럼 취급하는 것으로 문제를 해결했습니다.
클라이언트:
$.post("/updatePreferences",
{id: 'pr', preferences: JSON.stringify(p)},
function (response) {
...
서버:
@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();
}
}
간단히 말하면, REST 방식으로 변환을 수동으로 수행했습니다.스프링이 전송된 데이터를 인식하지 못하는 이유는 콘텐츠 타입이라고 생각합니다.
한편, 다음과 같은 회답은@ModelAttribute
,@RequestParam
,@PathParam
그리고 같은 것은 유효하고, 우연히 마주친 작은 gotcha가 있습니다.결과 메서드 파라미터는 Spring이 DTO를 감싼 프록시입니다.따라서 사용자 지정 유형이 필요한 컨텍스트에서 사용하려고 하면 예기치 않은 결과가 발생할 수 있습니다.
다음 기능이 작동하지 않습니다.
@GetMapping(produces = APPLICATION_JSON_VALUE)
public ResponseEntity<CustomDto> request(@ModelAttribute CustomDto dto) {
return ResponseEntity.ok(dto);
}
제 경우 잭슨 바인딩에서 사용하려고 하면com.fasterxml.jackson.databind.exc.InvalidDefinitionException
.
dto에서 새 개체를 만들어야 합니다.
네, 간단하게 할 수 있어요.아래의 라인 코드를 참조해 주세요.
URL - http://localhost:8080/get/request/map/by/map?name='&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);
}
수락된 답변은 마법처럼 작동하지만 오브젝트에 오브젝트 목록이 있으면 예상대로 작동하지 않기 때문에 좀 더 파고든 후 해결 방법이 있습니다.
- 프런트 엔드: 송신용으로 base64 로 부호화하는 것보다, 오브젝트를 문자열화합니다.
- 백엔드: base64 문자열을 디코딩한 후 문자열 json을 원하는 개체로 변환합니다.
우체부와의 API 디버깅에는 적합하지 않지만 예상대로 작동하고 있습니다.
원래 개체: { 페이지: 1, 크기: 5, 필터: [{ 필드: "id", 값: 1, 비교: "EQ" }
부호화 객체: eyJwYWdlIjoxLCJzaXplIjo1LCJmaWx0ZXJzIjpbeyJmaWVSZCI6IlkUGFyZW50IiwiY29tcGFyaXNViI6Ik5VTEwifV19
@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)
}
여기 Search Filter가 있습니다.DTO 및 필터 D로.
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 : https://stackoverflow.com/questions/16942193/spring-mvc-complex-object-as-get-requestparam
'programing' 카테고리의 다른 글
Vuex 프로파일링 : 메모리 내의 vuex 상태 또는 컴포넌트 크기를 확인하는 방법 (0) | 2022.07.11 |
---|---|
vue 맵 상태를 사용하여 어레이를 v-modeling합니다. (0) | 2022.07.11 |
VueJ: 렌더링 요소가 아닌 'v-for' (0) | 2022.07.11 |
테스트 시 Vue JS 구성 요소 템플릿 렌더링 문제 (0) | 2022.07.11 |
구성 요소에서 Vuex 모듈 작업에 액세스하는 방법 (0) | 2022.07.11 |