在控制器中映射之前转换特定字段

Convert specific fields before mapping in controller

我需要在映射到 Dto 之前转换两个特定字段 class。 我从表格中获得的数据:

userName: test
password: 123
active: N
enabled: N
external: N
id: -1

Dto class:

@Getter @Setter 
public class UserDto {
    protected Integer id;
    protected String userName;
    protected String password;
    protected boolean active = false;
    protected boolean enabled = true;
    protected String external;
}

字段 activeenabled 是布尔类型,但从表单中我得到“Y”或“N”字符串值。原因是,我得到一个错误 Failed to convert property value of type 'java.lang.String' to required type 'boolean' for property 'active'; nested exception is java.lang.IllegalArgumentException: Invalid boolean value [N]

我读过有关 Сonverter 和 PropertyEditors 的信息,但我不确定它们是否适合我,以及我如何才能将它仅应用于 2 个特定字段。

控制器:

    @RequestMapping(value = "/user/save",method = RequestMethod.POST)
    public ResponseEntity<String> saveUser(@ModelAttribute UserDto userDto, BindingResult bindingResultM, HttpServletRequest req) {

        List<FieldError> errors = bindingResultM.getFieldErrors();
        for (FieldError error : errors) {
            log.error("bindingResultM: " + error.getObjectName() + " - " + error.getDefaultMessage());
        }
        try {
            userService.saveUserDto(userDto);
            return new ResponseEntity<>("OK", HttpStatus.OK);
        } catch (Exception e){
            throw new ResponseException(e.getMessage(), HttpStatus.METHOD_FAILURE);
        }
    }

在您的 DTO 上,您可以使用 :

注释您的布尔字段
    @JsonDeserialize(
        using = BooleanDeserializer.class
    )
    protected boolean enabled;

并创建解串器:

public class BooleanDeserializer extends JsonDeserializer<Boolean> {

    public Boolean deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
        String booleanValue = StringUtils.trimToEmpty(jsonParser.getText().trim());
        return BooleanUtils.toBoolean(booleanValue, "Y", "N");
    }
}

因为你说你需要从表单中获取数据来填充UserDTO对象,这是一个将String类型转换为其他类型的过程.

因此,您需要使用“org.springframework.core.convert.converter.Converter”、“java.beans.PropertyEditor” ,或“org.springframework.format.Formatter”。这三个都可以完成将 String 类型转换为其他类型或将其他类型转换为 String 类型的工作。

但是PropertyEditor太复杂,所以一般我们都是用Converter或者Formatter,这两个可以在同一个方法里设置“default void addFormatters(FormatterRegistry registry) {}”的“WebMvcConfigurer”接口。

但这是针对整个应用程序的,您希望翻译发生在“active”和“enabled” " UserDTO 的字段。

然后你需要使用“org.springframework.web.bind.annotation.InitBinder”,它可以在控制器内部定义用于具体方法参数。 “@InitBinder”的“userDTO”表示数据绑定器仅用于“userDTO[=55=” ]" 此控制器内的 方法参数 。 (这个名字是case-sensitive,所以如果你在方法中使用“userDto”,你需要在@InitBinder注解中把它改成userDto。) 在此方法中,您可以 仅针对“active”和“enabled”字段指定 Formatter,通过使用此方法:

public void addCustomFormatter(Formatter<?> formatter, String... fields){} 

当然你可以为这两个字段指定Converter,但是在“WebDataBinder”中没有直接方法 class。因此,eaiser 使用 Formatter

@InitBinder("userDTO")
public void forUserDto(WebDataBinder binder) {
    binder.addCustomFormatter(new BooleanFormatter(), "active", "enabled");
}

这是 BooleanFormatter class:

public class BooleanFormatter implements Formatter<Boolean>{

    @Override
    public String print(Boolean object, Locale locale) {
        if (object) {
            return "Y";
        }
        return "N";
    }

    @Override
    public Boolean parse(String text, Locale locale) throws ParseException {
        if (text.equals("Y")) {
            return true;
        }
        return false;
    }
}