- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章Springboot 使用 JSR 303 对 Controller 控制层校验及 Service 服务层 AOP 校验 使用消息资源文件对消息国际化由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
导包和配置 。
导入 JSR 303 的包、hibernate valid 的包 。
1
2
3
4
5
6
7
8
9
10
|
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>
6.0
.
5
.Final</version>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>
2.0
.
0
.Final</version>
</dependency>
|
springboot 配置 。
resources/application.yml 消息资源文件国际化处理配置 。
spring: messages: basename: base,todo # 资源文件 base.properties 和 todo.properties,多个用逗号隔开 。
encoding: UTF-8 # 必须指定解析编码,否则中文乱码 。
在 springboot 启动类里面配置 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
@SpringBootApplication
public
class
Application
extends
WebMvcConfigurerAdapter {
@Value
(
"${spring.messages.basename}"
)
private
String basename;
public
static
void
main(String[] args) {
SpringApplication.run(Application.
class
, args);
}
@Bean
@Primary
public
MessageSource messageSource() {
ResourceBundleMessageSource resourceBundleMessageSource =
new
ResourceBundleMessageSource();
resourceBundleMessageSource.setUseCodeAsDefaultMessage(
false
);
resourceBundleMessageSource.setDefaultEncoding(
"UTF-8"
);
// 重复定义
resourceBundleMessageSource.setBasenames(basename.split(
","
));
return
resourceBundleMessageSource;
}
@Bean
@Primary
public
LocalValidatorFactoryBean validator() {
LocalValidatorFactoryBean validatorFactoryBean =
new
LocalValidatorFactoryBean();
validatorFactoryBean.setProviderClass(HibernateValidator.
class
);
validatorFactoryBean.setValidationMessageSource(messageSource());
return
validatorFactoryBean;
}
@Override
public
Validator getValidator() {
return
validator();
}
/**
* 方法级别的单个参数验证开启
*/
@Bean
public
MethodValidationPostProcessor methodValidationPostProcessor() {
return
new
MethodValidationPostProcessor();
}
}
|
我们对于校验参数通过不了抛出的异常进行处理,是通过统一异常捕捉.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
@ControllerAdvice
@Component
public
class
BindValidExceptionHandler {
@ResponseStatus
(value = HttpStatus.OK)
@ExceptionHandler
(ConstraintViolationException.
class
)
public
@ResponseBody
Msg handleConstraintViolationException(ConstraintViolationException e) {
String messageTemplate = e.getConstraintViolations().iterator().next().getMessageTemplate();
return
Msg.error(messageTemplate);
}
@ResponseStatus
(value = HttpStatus.OK)
@ExceptionHandler
(BindException.
class
)
public
@ResponseBody
Msg handleBindException(BindException e) {
BindingResult bindingResult = e.getBindingResult();
String className = bindingResult.getTarget().getClass().getName();
FieldError next = bindingResult.getFieldErrors().iterator().next();
String fieldName = next.getField();
String defaultMessage = next.getDefaultMessage();
if
(Pattern.compile(
"IllegalArgumentException: No enum"
).matcher(defaultMessage).find()) {
Matcher matcher = Pattern.compile(
"for value '(.*?)'"
).matcher(defaultMessage);
if
(matcher.find()) {
defaultMessage =
"找不到枚举类型【"
+ matcher.group(
1
) +
"】"
;
}
}
return
Msg.error(defaultMessage);
}
@ResponseStatus
(value = HttpStatus.OK)
@ExceptionHandler
(ValidError.
class
)
public
@ResponseBody
Msg handleValidError(ValidError e) {
return
Msg.error(e.getMessage());
}
}
|
resources/base.propertie 。
creatorId=创建者 id 不能为小于 {value}.
modifierId=修改者 id 不能为小于 {value}.
resources/todo.properties 。
todo.privateId.min=私有 id 不能为小于 {value}.
在 bean 字段上使用注解,其中 group 中的 C 和 S 接口是指 Controller 和 Service 的叫法简称,里面分别有 Insert 接口、Update 接口等等,都是自定义约定的东西.
。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
/**
* 私有 id,是代表项目任务/非项目任务/风险/问题/评审待办问题等多张表的外键
*/
@Min
(value =
1
, message =
"{todo.privateId.min}"
, groups = {C.Insert.
class
, C.Update.
class
, S.Insert.
class
, S.Update.
class
})
private
long
privateId;
/**
* 创建者id
*/
@Min
(value =
1
, message =
"{creatorId}"
, groups = {S.Insert.
class
})
private
long
creatorId;
Controller 控制层验证
@Validated
@RestController
@RequestMapping
(
"todo"
)
public
class
TodoController {
@Autowired
private
TodoService todoService;
@GetMapping
(
"getVo"
)
public
Msg getVo(
@Min
(value =
1
, message =
"待办 id 不能小于 1。"
)
@RequestParam
(required =
false
, defaultValue =
"0"
)
long
id
) {
return
this
.todoService.getVo(id);
}
@PostMapping
(
"add"
)
public
Msg add(
@Validated
({C.Insert.
class
}) Todo todo) {
return
this
.todoService.add(todo);
}
}
|
@Validated({C.Insert.class}) 声明启用 bean 注解上的验证组,其他验证组不会进行验证,这样可以区别开来进行单独验证.
而像没有实体,只有一个基础数据类型的,可以进行验证,但是需要满足三个条件:
自行验证.
Service 服务层 AOP 验证 。
ValidUtil 工具类 。
需要被 springboot 扫描并注册为单例 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
|
@Component
public
class
ValidUtil {
@Autowired
private
Validator validator;
public
<T> Set<ConstraintViolation<T>> validate(T object, Class<?>... groups) {
return
validator.validate(object, groups);
}
public
<T> Set<ConstraintViolation<T>> validateValue(Class<T> beanType, String propertyName, Object value, Class<?>... groups) {
return
validator.validateValue(beanType, propertyName, value, groups);
}
/**
* 校验参数,并返回第一个错误提示
* @param t 验证的对象
* @param groups 验证的组别
* @param <T> 对象擦除前原类型
* @return 第一个错误提示
*/
public
<T>
void
validAndReturnFirstErrorTips(T t, Class<?>... groups) {
Set<ConstraintViolation<T>> validate = validator.validate(t, groups);
if
(validate.size() >
0
) {
ConstraintViolation<T> next = validate.iterator().next();
String message = next.getRootBeanClass().getName() +
"-"
+ next.getPropertyPath() +
"-"
+ next.getMessage();
throw
new
ValidError(message);
}
}
/**
* 校验参数,并返回第一个错误提示
* @param targetClass 验证的对象的 class 类型
* @param fieldName 需要验证的名字
* @param obj 需要属性值
* @param groups 验证的组别
* @param <T> 对象擦除前原类型
* @return 第一个错误提示
*/
public
<T>
void
validAndReturnFirstErrorTips(Class targetClass, String fieldName, Object obj, Class<?>... groups) {
Set<ConstraintViolation<T>> validate = validator.validateValue(targetClass, fieldName, obj, groups);
if
(validate.size() >
0
) {
String message = targetClass.getName() +
"-"
+ fieldName +
"-"
+ validate.iterator().next().getMessage();
throw
new
ValidError(message);
}
}
}
|
AOP 配置 。
主要原理是利用 aop 拦截方法执行参数,对参数获取注解。再利用工具类来验证参数,如果验证不通过,直接抛出自定义错误,自定义错误已经全局统一处理了.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
@Aspect
@Component
public
class
ValidatorAOP {
@Autowired
private
ValidUtil validUtil;
/**
* 定义拦截规则:拦截 com.servic 包下面的所有类中,有 @Service 注解的方法。
*/
@Pointcut
(
"execution(* com.service..*(..)) and @annotation(org.springframework.stereotype.Service)"
)
public
void
controllerMethodPointcut() {
}
/**
* 拦截器具体实现
*/
@Around
(
"controllerMethodPointcut()"
)
// 指定拦截器规则;也可以直接把 “execution(* com.xjj.........)” 写进这里
public
Object Interceptor(ProceedingJoinPoint pjp) {
MethodSignature methodSignature = (MethodSignature) pjp.getSignature();
Method method = methodSignature.getMethod();
Annotation[][] argAnnotations = method.getParameterAnnotations();
Object[] args = pjp.getArgs();
for
(
int
i =
0
; i < args.length; i++) {
for
(Annotation annotation : argAnnotations[i]) {
if
(Validated.
class
.isInstance(annotation)) {
Validated validated = (Validated) annotation;
Class<?>[] groups = validated.value();
validUtil.validAndReturnFirstErrorTips(args[i], groups);
}
}
}
try
{
return
pjp.proceed(args);
}
catch
(Throwable throwable) {
throwable.printStackTrace();
}
return
true
;
}
}
|
验证注解 @Min @NotNull 使用方法 。
不能写在实现类上,只能在接口中使用注解 。
与 Controller 使用方式基本一样 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
@Validated
public
interface
TodoService {
/**
* 查询 单个待办
* @param id 序号
* @return 单个待办
*/
Msg getVo(
@Min
(value =
1
, message =
"待办 id 不能小于 1。"
)
long
id);
/**
* 添加数据
* @param todo 对象
*/
Msg add(
@Validated
({S.Insert.
class
}) Todo todo);
}
|
分享几个自定义验证注解 。
字符串判空验证 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
package
javax.validation.constraints;
import
javax.validation.Constraint;
import
javax.validation.ConstraintValidator;
import
javax.validation.ConstraintValidatorContext;
import
javax.validation.Payload;
import
java.lang.annotation.*;
/**
* 字符串判空验证,hibernate 自带的可能有问题,使用不了,需要重写,package 是不能变的。
*/
@Documented
@Constraint
(
validatedBy = {NotBlank.NotBlankValidator.
class
}
)
@Target
({ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.PARAMETER})
@Retention
(RetentionPolicy.RUNTIME)
public
@interface
NotBlank {
Class<?>[] groups()
default
{};
String message()
default
"{notBlank}"
;
Class<?
extends
Payload>[] payload()
default
{};
class
NotBlankValidator
implements
ConstraintValidator<NotBlank, Object> {
public
NotBlankValidator() {
}
@Override
public
void
initialize(NotBlank constraintAnnotation) {
}
@Override
public
boolean
isValid(Object value, ConstraintValidatorContext context) {
return
value !=
null
&& !value.toString().isEmpty();
}
}
}
|
类型判断,判断 type 是否为其中一个值,可以根据验证组自定义判断 。
1
2
3
4
5
6
7
8
9
10
11
|
resources/todo.properties
todo.todoType.insert=新增时,待办类型只能是 非项目任务、项目任务、问题 之中一。
todo.todoType.update=修改时,待办类型只能是风险、评审待办问题 之中一。
bean
/**
* 待办类型0非项目任务1项目任务2问题3风险4评审待办问题
*/
@TodoTypeValid
(value = {
"0"
,
"1"
,
"2"
}, message =
"{todo.todoType.insert}"
, groups = {C.Insert.
class
, S.Insert.
class
})
@TodoTypeValid
(value = {
"3"
,
"4"
}, message =
"{todo.todoType.update}"
, groups = {C.Update.
class
, S.Update.
class
})
private
String todoType;
|
。
自定义注解 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
@Documented
@Constraint
(validatedBy = {TodoTypeValid.TodoTypeValidFactory.
class
})
@Target
({ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.PARAMETER})
@Retention
(RetentionPolicy.RUNTIME)
@Repeatable
(TodoTypeValid.List.
class
)
public
@interface
TodoTypeValid {
String message()
default
"请输入正确的类型"
;
String[] value()
default
{};
Class<?>[] groups()
default
{};
Class<?
extends
Payload>[] payload()
default
{};
class
TodoTypeValidFactory
implements
ConstraintValidator<TodoTypeValid, String> {
private
String[] annotationValue;
@Override
public
void
initialize(TodoTypeValid todoStatusValid) {
this
.annotationValue = todoStatusValid.value();
}
@Override
public
boolean
isValid(String value, ConstraintValidatorContext context) {
if
(Arrays.asList(annotationValue).contains(value))
return
true
;
return
false
;
}
}
@Target
({ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.PARAMETER})
@Retention
(RetentionPolicy.RUNTIME)
@Documented
@interface
List {
TodoTypeValid[] value();
}
}
|
@Repeatable(TodoTypeValid.List.class) 是 JDK8 支持的同一注解多次特性.
根据上面的同样也可以用在枚举类上 。
1
2
3
4
5
6
7
8
9
10
|
resources/todo.properties
todo.todoStatus.insert=新增时,状态只能是未开始。
todo.todoStatus.update=修改时,状态只能是进行中或已完成。
bean
/**
* 待办状态0未开始1进行中2已完成
*/
@TodoStatusValid
(enums = {TodoStatus.NOT_STARTED}, message =
"{todo.todoStatus.insert}"
, groups = {C.Insert.
class
, S.Insert.
class
})
@TodoStatusValid
(enums = {TodoStatus.PROCESSING, TodoStatus.COMPLETED}, message =
"{todo.todoStatus.update}"
, groups = {C.Update.
class
, S.Update.
class
})
private
TodoStatus todoStatus;
|
自定义注解 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
@Documented
@Constraint
(validatedBy = {TodoStatusValid.TodoStatusValidFactory.
class
})
@Target
({ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.PARAMETER})
@Retention
(RetentionPolicy.RUNTIME)
@Repeatable
(TodoStatusValid.List.
class
)
public
@interface
TodoStatusValid {
String message()
default
"请输入正确的状态"
;
TodoStatus[] enums()
default
{};
Class<?>[] groups()
default
{};
Class<?
extends
Payload>[] payload()
default
{};
class
TodoStatusValidFactory
implements
ConstraintValidator<TodoStatusValid, TodoStatus> {
private
TodoStatus[] enums;
@Override
public
void
initialize(TodoStatusValid todoStatusValid) {
this
.enums = todoStatusValid.enums();
}
@Override
public
boolean
isValid(TodoStatus value, ConstraintValidatorContext context) {
TodoStatus[] values = TodoStatus.values();
if
(enums !=
null
&& enums.length !=
0
) {
values = enums;
}
if
(Arrays.asList(values).contains(value))
return
true
;
return
false
;
}
}
@Target
({ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.PARAMETER})
@Retention
(RetentionPolicy.RUNTIME)
@Documented
@interface
List {
TodoStatusValid[] value();
}
}
|
总结 。
以上所述是小编给大家介绍的Springboot 使用 JSR 303 对 Controller 控制层校验及 Service 服务层 AOP 校验 使用消息资源文件对消息国际化,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对我网站的支持! 。
原文链接:http://www.cnblogs.com/zengyufei/p/8056628.html 。
最后此篇关于Springboot 使用 JSR 303 对 Controller 控制层校验及 Service 服务层 AOP 校验 使用消息资源文件对消息国际化的文章就讲到这里了,如果你想了解更多关于Springboot 使用 JSR 303 对 Controller 控制层校验及 Service 服务层 AOP 校验 使用消息资源文件对消息国际化的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我们正在创建一个 n 层 Silverlight LOB 应用程序,并且正在考虑使用 .NET RIA 服务。我们不清楚这与我们当前的 WCF 服务 API 的关系在哪里。我们当前的架构是: 银光
上下文:我在celery + rabbitmq堆栈上有一个主工作系统。 系统已docker化(此处未提供worker服务) version: '2' services: rabbit:
我是 Windows Azure 新手,我正在尝试将我的 Web 应用程序部署到 Windows Azure。在我的应用程序中,我使用了一些 Web 服务,现在我想知道如何在 Windows Azur
因此,根据我对服务的了解,自定义对象似乎是写入服务以返回数据的方式。如果我正在编写将用于 1) 填充数据库或 2) 为网站提供信息的服务,是否有返回数据集/数据表而不是包含所有这些的自定义对象列表的用
我在 google 和 stackoverflow 上都找过答案,但似乎找不到。我正在尝试将 azure 实验的输出获取到应用程序。我使用 ibuildapp 和谷歌表单制作了该应用程序。如何使用 g
我不小心删除了 kubernetes svc: service "kubernetes" deleted 使用: kubectl delete svc --all 我该怎么办?我只是想删除服务,以便
我正在努力确定解决网络服务问题的最有效方法。 我的情况:我正在开发一个 Android 应用程序,它通过 Web 服务从 mysql 数据库(在我自己的服务器 PC 上)存储和检索数据。用户按下提交按
我一直在翻阅 Android 文档,我很好奇。什么时候绑定(bind)服务而不是不绑定(bind)服务?它提供了哪些优点/限制? 最佳答案 When would you bind a service
我试图从架构的角度理解 hive,我指的是 Tom White 关于 Hadoop 的书。 我遇到了以下关于配置单元的术语:Hive Services、hiveserver2、metastore 等。
我的问题:安装服务后我无法导航到基地址,因为服务不会继续运行(立即停止)。我需要在服务器或我的机器上做些什么才能使 baseAddress 有效吗? 背景:我正在尝试学习如何使用 Windows 服务
我正在努力就 Web 服务的正确组织做出决定。我应该有多个 ASMX 来代表 Web 服务中的不同功能,还是应该有一个 ASMX? 如果我有多个 ASMX,这不构成多个 Web 服务吗? 如果我只有一
我正在从事一个在 azure 平台上提供休息服务的项目。该服务由 iPhone 客户端使用,这是选择其余方法的重要原因之一。 我们希望通过 AccessControlService(ACS) 并使用
我是 Ionic 新手,正在使用 Ionic 3.9.2 我有几个终端命令来为我的 ionic 应用程序提供服务,但是,我没有发现这两个命令之间有任何区别。 ionic serve 和 ionic s
关闭。这个问题需要多问focused 。目前不接受答案。 想要改进此问题吗?更新问题,使其仅关注一个问题 editing this post . 已关闭 8 年前。 Improve this ques
作为项目的一部分,我期待着问这个问题。我过去有开发和使用 Web 服务的经验,并且非常熟悉这些服务。但是,有人告诉我,作为下一个项目的一部分,我将需要使用“安全”的 Web 服务。您能否提供一些见解,
我浏览了很多关于这个问题的信息,但找不到解决方案。这里的问题是,我想使用 Apache Cordova 和 Visual Studio 连接到 wcf。因此,如果有人找到合适的工作解决方案,请发布链接
我在 Windows 服务中托管了一个 WCF(从 MS 网站示例中选取),我可以使用 SOAP UI 访问和调用方法。但是,当我尝试使用 jquery 从 Web 应用程序调用相同的方法时,我不断收
我们构建了一个 Android 应用程序,它从 Android 向我的 PHP 服务器发送 HTTP 请求。作为响应,Web 服务将 JSON 对象发送到 Android 应用程序以显示结果。 就像其
我想在 android 应用程序中调用 soap web 服务,它需要一个枚举值作为参数,它是一个标志枚举。如何从 Android 应用程序将一些值作为标志枚举传递给此 Web 服务方法? 我使用 K
我尝试在模拟器上安装 Google Play。我已按照 Google Dev Site 中的说明进行操作. 使用 ADV 管理器似乎没问题,设备的目标是 Google API 版本 22,但是当我运行
我是一名优秀的程序员,十分优秀!