Spring中向Model添加List时仅特定场景触发ConversionFailedException求助
解决Spring中RedirectAttributes传递自定义对象时的ConversionFailedException问题
看起来你遇到的问题根源在于错误地在转发场景中使用了RedirectAttributes来传递自定义对象,我来帮你拆解一下原因和解决方案:
为什么会出现这个异常?
首先得明确Model和RedirectAttributes的核心差异:
Model是为转发到视图设计的:它的属性直接存入当前请求的request域中,视图可以直接访问这些对象实例,不需要做额外的类型转换。RedirectAttributes是为重定向设计的:它的addAttribute方法默认会把数据转换成请求参数附加到重定向URL上——但自定义对象(比如你的Authority)没有对应的类型转换器,Spring无法把它转换成URL参数的字符串形式,所以抛出ConversionFailedException。
看你的代码:在POST方法的错误分支里,你return "user_details"是直接转发到视图,却用了RedirectAttributes来传递allAuthorities,这就触发了Spring的参数转换逻辑,导致报错;而GET方法里用Model是完全正确的,所以没有问题。
解决方案
方案1:转发场景用Model(最推荐)
既然错误分支是转发到视图,直接用Model来传递数据就可以了,修改你的POST方法:
@PostMapping(value = {"/users","/profile","/users/{any}"}) public String postUser( @Valid @ModelAttribute("user") User user, BindingResult bindingResult, @RequestParam("newPassword") Optional<String> newPassword, @RequestParam("confirmPassword") Optional<String> confirmPassword, Model model, // 添加Model参数 RedirectAttributes redirectAttributes, @PathVariable("any") String pathVariable ){ if(bindingResult.hasErrors()) { if(user.getId() == null) { model.addAttribute("newUser", true); // 用Model传递参数 } addAuthoritiesToModel(model); // 用Model调用方法 return "user_details"; // 转发到视图,正确匹配Model的使用场景 } // 正常逻辑:如果需要重定向,再用RedirectAttributes处理 redirectAttributes.addFlashAttribute("successMsg", "用户保存成功"); return "redirect:/users"; }
你的addAuthoritiesToModel方法不需要修改,因为Model是RedirectAttributes的父接口,兼容两种场景的调用。
方案2:重定向场景用Flash属性(如果确实需要重定向)
如果你因为某些原因必须在错误分支做重定向,那要改用RedirectAttributes的addFlashAttribute方法——Flash属性会存在Session中,不会被转换成URL参数,也就不会触发类型转换。
先修改addAuthoritiesToModel来区分处理:
private void addAuthoritiesToModel(Model model){ List<Authority> allAuthorities = Arrays.asList( Authority.of("ROLE_ADMIN","Admin"), Authority.of("ROLE_USER","User") ); if (model instanceof RedirectAttributes) { // 重定向场景:用Flash属性存储自定义对象 ((RedirectAttributes) model).addFlashAttribute("allAuthorities", allAuthorities); } else { // 转发场景:直接添加到Model model.addAttribute("allAuthorities", allAuthorities); } }
然后修改POST方法的错误分支,确保是重定向:
if(bindingResult.hasErrors()) { if(user.getId() == null) { redirectAttributes.addAttribute("newUser", true); // 简单类型可以作为URL参数 } addAuthoritiesToModel(redirectAttributes); return "redirect:/users/new"; // 重定向到对应的GET请求路径 }
注意:重定向后原请求的BindingResult错误信息会丢失,所以通常表单错误处理更适合用转发,这样能保留表单数据和错误提示。另外,用Flash属性时,你的Authority类需要实现Serializable接口,因为Session中的对象必须可序列化。
内容的提问来源于stack exchange,提问作者holothuroid
相关产品推荐
相关产品推荐

