Spring Boot REST服务中如何编写String转POJO转换器?
你遇到的这个转换异常,核心原因是**@RequestParam是用来处理URL查询参数或表单的简单类型参数**,而你传递的是复杂POJO列表,Spring默认没法把字符串形式的参数直接转换成ComponentDataForm对象。下面给你两种解决方案,优先推荐第一种更符合REST规范的实现:
方案一:改用@RequestBody传递请求体(推荐)
POST请求传递复杂对象列表时,标准做法是把数据放在请求体里,而不是拼在URL的查询参数中。这样既避免了URL长度限制,也更符合RESTful设计规范。
后端控制器修改
把参数注解从@RequestParam改成@RequestBody,Spring会自动解析请求体中的JSON数组为List<ComponentDataForm>:
@PostMapping private ServerResponse creatAllCompDatas(@RequestBody final List<ComponentDataForm> componentDataFormValues) { if (isSessionValid()) { List<Long> datasIds = new ArrayList(); componentDataFormValues.stream().forEach(formValue -> { MNG_COMPOSANT_DATA mng_composant_data = new MNG_COMPOSANT_DATA(); mng_composant_data.setCmp_attr_code(formValue.getAttCode()); mng_composant_data.setCmp_attr_label(formValue.getAttTitle()); mng_composant_data.setCmp_attr_value(formValue.getAttVal()); datasIds.add(mng_composant_data.getId()); }); initSuccessResponse(datasIds); return serverResponse; } initFailLoginResponse(); return serverResponse; }
前端JavaFX修改
将原来的queryString传参改成发送JSON请求体,Unirest会自动把列表序列化为JSON数组:
@FXML private void doCommit(ActionEvent event) throws UnirestException{ if(validate()){ final ObservableList<AppDataAttTDO> items = tableAtributes.getItems(); final List<ComponentDataForm> componentDataFormValues = new ArrayList(); items.stream().forEach(item -> { final ComponentDataForm requestItem = new ComponentDataForm(); requestItem.setAttCode(item.getAttCode()); requestItem.setAttTitle(item.getAttTitle()); requestItem.setAttVal(item.getAttValue()); componentDataFormValues.add(requestItem); }); HttpResponse<String> asString = Unirest.post(APPLICATION_DATA_SERVICE_URL) .header("Content-Type", "application/json") .body(componentDataFormValues) .asString(); System.out.println(asString.getStatus()); System.out.println(asString.getBody()); } }
方案二:实现Converter(仅当必须用@RequestParam时)
如果因为特殊场景必须用查询参数传递,你可以实现Spring的Converter接口,把字符串形式的参数转换成ComponentDataForm对象。假设你传递的每个参数是JSON格式的字符串:
1. 实现转换器
import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.core.convert.converter.Converter; import org.springframework.stereotype.Component; @Component public class StringToComponentDataFormConverter implements Converter<String, ComponentDataForm> { private final ObjectMapper objectMapper; // 注入Spring自动配置的ObjectMapper public StringToComponentDataFormConverter(ObjectMapper objectMapper) { this.objectMapper = objectMapper; } @Override public ComponentDataForm convert(String source) { try { // 将JSON字符串解析为ComponentDataForm对象 return objectMapper.readValue(source, ComponentDataForm.class); } catch (Exception e) { throw new IllegalArgumentException("无法解析字符串为ComponentDataForm: " + source, e); } } }
2. 注册转换器到Spring容器
在Spring Boot配置类中,把转换器注册到WebMvc配置里:
import org.springframework.context.annotation.Configuration; import org.springframework.format.FormatterRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class WebConfig implements WebMvcConfigurer { private final StringToComponentDataFormConverter converter; public WebConfig(StringToComponentDataFormConverter converter) { this.converter = converter; } @Override public void addFormatters(FormatterRegistry registry) { registry.addConverter(converter); } }
3. 前端修改
前端需要把每个ComponentDataForm对象序列化为JSON字符串,再作为查询参数传递:
@FXML private void doCommit(ActionEvent event) throws UnirestException, JsonProcessingException{ if(validate()){ final ObservableList<AppDataAttTDO> items = tableAtributes.getItems(); final ObjectMapper objectMapper = new ObjectMapper(); final List<String> componentDataJsonList = new ArrayList(); items.stream().forEach(item -> { final ComponentDataForm requestItem = new ComponentDataForm(); requestItem.setAttCode(item.getAttCode()); requestItem.setAttTitle(item.getAttTitle()); requestItem.setAttVal(item.getAttValue()); try { // 将对象转为JSON字符串 componentDataJsonList.add(objectMapper.writeValueAsString(requestItem)); } catch (JsonProcessingException e) { e.printStackTrace(); } }); HttpResponse<String> asString = Unirest.post(APPLICATION_DATA_SERVICE_URL) .queryString("componentDataFormValues", componentDataJsonList) .asString(); System.out.println(asString.getStatus()); System.out.println(asString.getBody()); } }
再次提醒:这种方式仅适用于特殊场景,日常开发优先选择方案一,它更规范且不易出问题。
内容的提问来源于stack exchange,提问作者Mohammed Housseyn Taleb
相关产品推荐
相关产品推荐

