Spring Boot MVC请求参数通用校验及国际化支持

本文详细介绍了如何在Spring Boot应用中实现Validation和国际化配置,包括添加验证依赖、配置校验失败提示、设置国际化资源文件,以及通过全局异常处理和MessageUtils工具类实现错误信息的国际化展示。同时,提供了测试Controller和请求DTO的示例,展示了不同语言环境下错误信息的显示效果。
摘要由CSDN通过智能技术生成

一、Validation及国际化配置

1、添加依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

2、校验失败提示消息国际化配置

@Configuration
public class ValidationConfig {

	@Bean
	public LocalValidatorFactoryBean defaultValidator(MessageSource messageSource) {
		LocalValidatorFactoryBean factoryBean = new LocalValidatorFactoryBean();
		factoryBean.setValidationMessageSource(messageSource);
		return factoryBean;
	}
}

Spring Boot中针对Validation和国际化有两个自动配置类:
1、ValidationAutoConfiguration
2、MessageSourceAutoConfiguration
其中MessageSourceAutoConfiguration会自动实例化一个MessageSource实例,如下:
在这里插入图片描述

3、application.properties

#国际化配置,basename可以用全限定类名,如下,也可以是i18n/message
spring.messages.basename=i18n.messages
spring.messages.encoding=UTF-8

更多配置可参考:
https://docs.spring.io/spring-boot/docs/current/reference/html/appendix-application-properties.html#common-application-properties-integration.
在这里插入图片描述

4、国际化资源文件

在这里插入图片描述

注意:我们basename的配置为:spring.messages.basename=i18n.messages
因此在类路径下新建i18n的文件夹即可,而不是i18n/messages文件夹,文件夹内必须有一个文件名称为message.properties的属性文件,不然会有问题。多语言以messages_语言_国家.properties命名。

二、代码演示

1、全局异常处理

public class GlobalExceptionHandler {

	@ResponseBody
	@ExceptionHandler(MethodArgumentNotValidException.class)
	public ApiRespVO<?> handleException(MethodArgumentNotValidException e) {
		FieldError fieldError = e.getBindingResult().getFieldError();
		// 校验注解名称
		String code = fieldError.getCode();
		// 校验字段名称
		String field = fieldError.getField();
		// 检验失败默认消息
		String defaultMessage = fieldError.getDefaultMessage();

		List<Object> args = Arrays.stream(Optional.ofNullable(fieldError.getArguments()).orElse(new Object[] {}))
			.filter(argument -> !(argument instanceof DefaultMessageSourceResolvable))
			.map(Object::toString)
			.collect(Collectors.toList());
		args.add(0, field);

		// 默认根据注解名称取,如果没有则取默认消息
		String errorMsg = MessageUtils.getMessage(code, args.toArray(), LocaleContextHolder.getLocale(), StringUtils.EMPTY);
		if (StringUtils.isNotBlank(errorMsg)) {
			return ApiRespVO.failure(ErrorCode.INVALID_PARAM, errorMsg);
		}

		return ApiRespVO.failure(ErrorCode.INVALID_PARAM, defaultMessage);
	}
}

备注:关于LocalContextHolder,每次web请求到来时,Spring中的RequestContextFilter会将Locale实例注入到LocalContextHolder。

2、MessageUtils工具类

public class MessageUtils {

	private static MessageSource messageSource = WebApplicationContextHolder.getBean(MessageSource.class);

	public static String getMessage(String code, Object[] args, Locale locale, String defaultValue) {
		return messageSource.getMessage(code, args, defaultValue, locale);
	}

	public static String getMessage(String code, Object[] args, Locale locale) {
		return messageSource.getMessage(code, args, locale);
	}

}

3、响应VO

public class ApiRespVO<T> {

	private static final String SUCCESS = "00000";
	private static final String FAILURE = "99999";

	private String code;
	private String message;
	private T data;

	public static <T> ApiRespVO<T> success() {
		return success(null);
	}

	public static <T> ApiRespVO<T> success(T data) {
		ApiRespVO<T> apiRespDTO = new ApiRespVO<>();
		apiRespDTO.setCode(SUCCESS);
		apiRespDTO.setData(ObjectUtils.defaultIfNull(data, (T) new Object()));
		return apiRespDTO;
	}

	public static <T> ApiRespVO<T> failure(String code) {
		return failure(code, new Object[] {});
	}

	public static <T> ApiRespVO<T> failure(String code, Object[] args) {
		String errorMsg = MessageUtils.getMessage(code, args, LocaleContextHolder.getLocale());
		return failure(FAILURE, errorMsg);
	}

	public static <T> ApiRespVO<T> failure(String code, String message) {
		ApiRespVO<T> apiRespDTO = new ApiRespVO<>();
		apiRespDTO.setCode(code);
		apiRespDTO.setMessage(message);
		return apiRespDTO;
	}

	public String getCode() {
		return code;
	}

	public void setCode(String code) {
		this.code = code;
	}

	public String getMessage() {
		return message;
	}

	public void setMessage(String message) {
		this.message = message;
	}

	public T getData() {
		return data;
	}

	public void setData(T data) {
		this.data = data;
	}

	@Override
	public String toString() {
		return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
	}
}

2、测试Controller和请求DTO

@RestController
public class ValidationController {

	@Autowired
	private MessageSource messageSource;

	@RequestMapping("/validate")
	public ApiRespVO<?> hanldeRequest(@Validated @RequestBody UserReqDTO userDTO) {
		return ApiRespVO.success();
	}

	@RequestMapping("/validate-list")
	public ApiRespVO<?> validateListParam(@Validated @RequestBody ChargeRuleReqDTO request) {
		return ApiRespVO.success();
	}
}
public class UserReqDTO {

	@NotNull
	private String username;

	@NotBlank
	@Length(min = 5,max = 8)
	private String password;

	@Size(max = 1)
	private String gender;

	@Positive
	private int age;

	@NotBlank
	@Pattern(regexp = "^\\d{11}$", message = "{Pattern.UserReqDTO.phone}")
	private String phone;

	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public String getGender() {
		return gender;
	}

	public void setGender(String gender) {
		this.gender = gender;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public String getPhone() {
		return phone;
	}

	public void setPhone(String phone) {
		this.phone = phone;
	}
}
public class ChargeRuleReqDTO {

	@NotBlank
	private String appId;

	@Valid
	private List<ChannelChargeInfo> chargeInfo;

	private static class ChannelChargeInfo {

		@NotBlank
		private String channelCode;

		@NotNull
		private BigDecimal channelCharge;

		public String getChannelCode() {
			return channelCode;
		}

		public void setChannelCode(String channelCode) {
			this.channelCode = channelCode;
		}

		public BigDecimal getChannelCharge() {
			return channelCharge;
		}

		public void setChannelCharge(BigDecimal channelCharge) {
			this.channelCharge = channelCharge;
		}
	}

	public String getAppId() {
		return appId;
	}

	public void setAppId(String appId) {
		this.appId = appId;
	}

	public List<ChannelChargeInfo> getChargeInfo() {
		return chargeInfo;
	}

	public void setChargeInfo(List<ChannelChargeInfo> chargeInfo) {
		this.chargeInfo = chargeInfo;
	}
}

备注:如果请求参数DTO中实例变量为List集合对象,则要加上@Valid注解,否则校验不会生效。

3、多语言属性文件

messages.properties

NotNull=
NotBlank=
Length=
Positive=
Pattern.UserReqDTO.phone=

备注:文件内容为空即可

messages_en_US.properties

NotNull=[{0}] cannot be null
NotBlank=[{0}] cannot be blank
Length=[{0}] minimum length is {2},maximum length is {1}
Positive=[{0}] must be greater than 0
Pattern.UserReqDTO.phone=phone number format is invalid and must be digit. maximum length is 11

messages_zh_CN.properties

NotNull=[{0}]不能为空
NotBlank=[{0}]不能为空
Length=[{0}]最小长度为{2},最大长度为{1}
Positive=[{0}]必须大于
Pattern.UserReqDTO.phone=手机号格式不正确,必须为全数字,长度为11位

4、测试用例

(1)简单对象UserReqDTO测试

语言为中文:
在这里插入图片描述
在这里插入图片描述
语言为英文:
在这里插入图片描述
在这里插入图片描述

(2)包含List集合对象的ChargeRuleReqDTO测试

语言为中文:
在这里插入图片描述
在这里插入图片描述

语言为英文:
在这里插入图片描述
在这里插入图片描述

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
Spring Boot中,可以使用Spring Boot Validation来对参数名称进行校验。通过引入spring-boot-starter-validation依赖,可以使用Spring Validator对参数进行校验Spring Validator是对Hibernate Validator的进一步封装,同时支持Spring MVC的自动校验。你可以在Spring官方文档中找到更多关于Spring Boot Validation的详细信息\[2\]。 在使用Spring Boot Validation时,可以使用@Validated注解来标记需要校验的类型、方法和方法参数。@Validated注解属于org.springframework.validation.annotation包,是Spring校验机制之一。它具有分组校验的功能,可以用于类型、方法和方法参数上,但不能用于成员属性(field)\[3\]。 通过使用Spring Boot Validation,你可以简化参数校验的代码,提高代码的可读性和美观性。 #### 引用[.reference_title] - *1* *3* [Spring Boot参数校验](https://blog.csdn.net/qq1929892209/article/details/126133350)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [Spring Boot 参数校验校验工具类](https://blog.csdn.net/WEDUEST/article/details/121594610)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

凌波漫步&

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值