1. 概述
在大多数典型的Web应用程序中,我们经常需要将请求参数限制为一组预定义的值,这种情况下,枚举是一种很好的方法。
在这个教程中,我们演示如何在Spring MVC中使用枚举作为Web请求参数。
2. 使用枚举作为请求参数
首先,我们定义一个枚举:
public enum Modes {
ALPHA, BETA
}
然后,我们可以将此枚举用作Spring控制器中的请求参数:
@RestController
@RequestMapping("/enums")
public class EnumController {
@GetMapping("/mode2str")
public String getStringToMode(@RequestParam("mode") Modes mode) {
return "good";
}
}
或者我们可以将其用作路径变量:
@RestController
@RequestMapping("/enums")
public class EnumController {
@GetMapping("/findbymode/{mode}")
public String findByEnum(@PathVariable Modes mode) {
return "good";
}
}
当我们发出web请求时,例如“/mode2str?mode=ALPHA”,请求参数是一个String对象。 Spring可以通过使用StringToEnumConverterFactory类将此String对象转换为Enum对象。
后端的转换调用Enum.valueOf方法,因此,输入参数字符串必须与声明的枚举值之一完全匹配。
当我们使用与枚举值不匹配的字符串值发出Web请求时,例如“/mode2str?mode=unknown”,Spring将无法将其转换为指定的枚举类型。 在这种情况下,我们会得到一个ConversionFailedException。
3. 自定义转换器
在Java中,使用大写字母定义枚举值被认为是一种很好的做法,因为它们是常量。 但是,我们可能希望在请求URL中支持小写字母。
在这种情况下,我们需要创建一个自定义转换器:
@Component
public class StringToEnumConverter implements Converter<String, Modes> {
@Override
public Modes convert(String source) {
return Modes.valueOf(source.toUpperCase());
}
}
要使用我们的自定义转换器,我们需要在Spring配置中注册它:
@Configuration
@EnableWebMvc
public class MvcConfig implements WebMvcConfigurer {
public MvcConfig() {
super();
}
@Override
public void addFormatters(FormatterRegistry registry) {
registry.addConverter(new StringToEnumConverter());
}
}
4. 异常处理
如果我们的Modes枚举没有匹配的常量,StringToEnumConverter中的Enum.valueOf方法将抛出IllegalArgumentException。 我们可以根据我们的要求以不同的方式在自定义转换器中处理此异常。
例如,我们可以简单地让转换器为不匹配的字符串返回null:
@Component
public class StringToEnumConverter implements Converter<String, Modes> {
@Override
public Modes convert(String source) {
try {
return Modes.valueOf(source.toUpperCase());
} catch (IllegalArgumentException e) {
return null;
}
}
}
但是,如果我们不在自定义转换器中自行处理异常,Spring会向调用控制器方法抛出ConversionFailedException异常,我们有几种方法可以处理此异常。
例如,我们可以使用全局异常处理程序类:
@ControllerAdvice
public class GlobalControllerExceptionHandler {
@ExceptionHandler(ConversionFailedException.class)
public ResponseEntity<String> handleConflict(RuntimeException ex) {
return new ResponseEntity<>(ex.getMessage(), HttpStatus.BAD_REQUEST);
}
}
5. 总结
在这篇简短的文章中,我们通过实际代码演示了如何在Spring中使用枚举作为请求参数。
并且通过自定义转换器,我们可以将输入字符串映射到枚举常量。
最后,我们介绍了如何处理Spring在遇到未知输入字符串时抛出的异常。
与往常一样,本教程的完整源代码可在GitHub上获得。