- 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的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我正在使用 choronos,它建议使用 start/stop 命令开始停止,如下所示 开始计时 停止计时 但是,我正在编写 puppet manifest,它只适用于下面的服务命令。 服务计时开始
来历及作用 services.exe进程程序文件是由微软公司为其发布的Windows操作系统定义的一个系统进程,常见于Windows 2000/XP/Vista/2007等系统中,被描述为服务和控
我一直在尝试使用installutil:installutil /u GSIS.FileMoverService.exe安装Windows服务。 我得到的输出是: Uninstalling assem
如果一个域有多个团队和多个 Web 应用程序,那么注册 Service Worker 来管理整个站点的最佳建议是什么?具有范围的顶级服务 worker /或子域中的多个服务 worker ?由于一个域
我已经在 eclipse 中创建了企业项目。动态web项目和ejb项目对企业项目有借鉴意义。当我运行管理员(企业项目)运行时选择 wildfly 服务器 18。我收到以下错误。谁能告诉我我错过了什么。
我已经使用 apache-cxf-2.7.4 创建了一个 Web 服务。我进入了我的项目中制作的类(class)。我的项目中的库是: math3-commons-3.2.jar XStream-1.4
我在域中的 Virtual Box 中运行集群计算机,默认情况下服务在 Network 服务下运行,服务一直停止,事件日志中出现以下错误。 请从下面的错误日志中查找错误详细信息。任何帮助都会很棒。 L
在我的应用程序中,用户可以在 map 上发布事件。应用程序的入口点是一个无状态的 web api 服务。为了在内部代表用户,我想要一个用户服务。我应该何时使用 Reliable Stateful Ac
当我尝试运行在WIX中创建的安装程序时,出现以下错误消息: “服务'Report Generator Service'(报告生成器服务)无法启动。请验证您是否具有启动系统服务的足够特权”。 我已经在这
尝试使用 cloudformation 创建 ECS 服务(在 Fargate 上)但出现错误: Invalid service in ARN (Service: AmazonECS; Status
我正在编写一个简单的Windows服务,该服务每个月向所有员工发送一封电子邮件。我的问题是,完成后如何停止自我?我是该领域的新手,请帮帮我。非常感谢。 它将部署在服务器上以每月运行。我没有开始做这件事
有谁知道是否有办法在 service worker 中获取此号码或日期: 将我的服务 worker 缓存命名为 cache-1182 会很方便或 cache-20171127171448 我想在安装事
我想开始使用 Azure Service Fabric 技术。 我按照this document工作并安装最新的SDK。安装后,我打开 PowerShell(“以管理员身份运行”)命令行窗口并写入这些
我在使用 whenever gem 时遇到了一些问题。我创建了一个 rake 任务,当我自己启动它时它工作得很好但是当我在日志中收到以下消息时尝试自动执行它: ActiveRecord::Statem
我想在 service fabric 集群中为两个不同的 web 应用程序(webpi/website)共享 http/80 端口,应用程序必须有 2 个不同的主机名: mywebapi.com 和
我创建了一个使用 MongoDB 实现 hibernate OGM 的应用程序。它在 Eclipse 中运行得很好,但是,当我构建一个 fat jar 并尝试运行它时,出现以下错误: Exceptio
我有一个 Selenium Python 测试套件。它开始运行,但几分钟后抛出以下错误: Exception AttributeError: "'Service' object has no attr
我按照此链接的说明进行操作:https://www.thegeekdiary.com/centos-rhel-7-how-to-make-custom-script-to-run-automatica
我在 ubuntu 下的 jboss 上部署了简单的“HelloWorld”Web 服务。 我创建了简单的客户端,但我无法让它工作。每次运行客户端时,我都会收到 NullPointerExceptio
我正在尝试为我的网站使用后台定期同步。我正在使用 localhost 并在 1*1000 毫秒时注册 periodicsync 事件,但这根本不会触发。 我看过这个demo ,但即使我将该网站安装为应
我是一名优秀的程序员,十分优秀!