You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring值类型转换问题:自定义错误消息未生效排查

Spring MVC类型转换错误消息自定义失败问题

问题场景

我是Spring新手,现在碰到值类型转换的问题。当给需要Integer类型的freePasses字段输入字符串时,想从properties配置文件里获取自定义错误消息“Invalid number”,但实际得到的错误信息是:

Failed to convert property value of type java.lang.String to required type java.lang.Integer for property freePasses; nested exception is java.lang.NumberFormatException: For input string: "sdf"

想问下是不是操作错了,还是缺了什么Java依赖库?

相关代码

Controller代码

import org.springframework.beans.propertyeditors.StringTrimmerEditor;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.validation.Valid;

@Controller
@RequestMapping("/customer")
public class CustomerController {

    @InitBinder
    public void initBinder(WebDataBinder dataBinder) {
        StringTrimmerEditor stringTrimmerEditor = new StringTrimmerEditor(true);
        dataBinder.registerCustomEditor(String.class, stringTrimmerEditor);
    }

    @RequestMapping("/showForm")
    public String showForm(Model theModel) {
        theModel.addAttribute("customer", new Customer());
        return "customer-form";
    }

    @RequestMapping("/processForm")
    public String processForm(
            @Valid @ModelAttribute("customer") Customer theCustomer,
            BindingResult theBindingResult
    ) {
        if (theBindingResult.hasErrors()) {
            return "customer-form";
        } else {
            return "customer-confirmation";
        }
    }
}

实体类代码

import javax.validation.constraints.*;

public class Customer {

    @NotNull(message="is required")
    @Min(value = 0, message = "cannot be less than 0")
    @Max(value = 10, message = "cannot be more than 10")
    private Integer freePasses;
    
    public Integer getFreePasses() {
        return freePasses;
    }

    public void setFreePasses(Integer freePasses) {
        this.freePasses = freePasses;
    }
}

Spring配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:util="http://www.springframework.org/schema/util"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
            http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context.xsd
            http://www.springframework.org/schema/mvc
            http://www.springframework.org/schema/mvc/spring-mvc.xsd
            http://www.springframework.org/schema/util
            http://www.springframework.org/schema/util/spring-util.xsd">

    <!-- 组件扫描支持 -->
    <context:component-scan base-package="com.autosdet.autosdetmvc" />

    <util:properties  id="countryOptions" location="classpath:countries.properties" />

    <!-- 转换、格式化及验证支持 -->
    <mvc:annotation-driven/>

    <!-- Spring MVC视图解析器 -->
    <bean
        class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/view/" />
        <property name="suffix" value=".jsp" />
    </bean>

    <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
        <property name="basenames" value="messages" />
    </bean>
</beans>

JSP表单页面

<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Customer Form</title>
    <style>
        .error {color: red}
    </style>
</head>
<body>
    Fill out the form. Asterisk (*) required.
    <form:form action="processForm" modelAttribute="customer">
        Free Passes (*): <form:input path="freePasses" />
        <form:errors path="freePasses" cssClass="error" />
        <br><br>
        <input type="submit" value="Submit" />
    </form:form>
    <br><br>
    <a href="/autosdet_mvc_war_exploded">Main Menu</a>
</body>
</html>

消息配置文件(messages.properties)

type.Mismatch.customer.freePasses=Invalid number

问题原因及解决办法

核心原因

你配置的错误消息键名不符合Spring MVC的规范:类型不匹配的错误消息键应该是驼峰式的typeMismatch(没有中间的点),而非type.Mismatch。Spring MVC会用这个键来匹配类型转换失败的错误场景。

另外,类型转换错误发生在JSR-380(@Valid)验证之前,必须确保Spring能将转换错误捕获并映射到自定义消息。

解决步骤

  1. 修正messages.properties中的键名
    将原来的配置改为以下任意一种格式:

    • 针对customer实体的freePasses字段:
      typeMismatch.customer.freePasses=Invalid number
      
    • 针对所有Integer类型字段:
      typeMismatch.java.lang.Integer=Invalid number
      
    • 通用类型不匹配消息:
      typeMismatch=Invalid number format
      
  2. 确认BindingResult参数位置
    你的Controller已经正确将BindingResult紧跟在@Valid修饰的参数之后,这是捕获错误的必要条件,无需修改。

  3. 依赖检查
    如果你用的是传统Spring MVC项目,确保已引入spring-webmvc、hibernate-validator(JSR-380实现)和spring-context依赖;如果是Spring Boot项目,确保引入spring-boot-starter-web和spring-boot-starter-validation依赖。从当前代码运行情况看,依赖应该是齐全的。

验证效果

修改配置后,再次向freePasses字段输入字符串提交,页面将显示自定义的“Invalid number”错误消息,而非默认的转换异常信息。

内容的提问来源于stack exchange,提问作者Hasan Humbatov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 19:31:02