最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

如何通過自定義spring?invalidator注解校驗(yàn)數(shù)據(jù)合法性

 更新時(shí)間:2022年07月04日 11:08:54   作者:Elon.Yang  
這篇文章主要介紹了如何通過自定義spring?invalidator注解校驗(yàn)數(shù)據(jù)合法性,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

自定義spring invalidator注解校驗(yàn)數(shù)據(jù)合法性

在項(xiàng)目中經(jīng)常會(huì)對用戶輸入的數(shù)據(jù),或者外部導(dǎo)入到系統(tǒng)的數(shù)據(jù)做合法性檢查。在spring boot框架的微服務(wù)中可以使用invalidator注解對數(shù)據(jù)做合法性,安全性校驗(yàn)。

下面給一個(gè)樣例說明如何自定義注解實(shí)現(xiàn)校驗(yàn)邏輯。

1、定義校驗(yàn)屬性字符串長度的注解

package com.elon.springbootdemo.manager.invalidator;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.validation.Constraint;
import javax.validation.Payload;
/**
?* 屬性字段長度校驗(yàn)注解定義。
?*?
?* @author elon
?* @version 2018年9月19日
?*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = FieldLengthInvalidatorImpl.class)
@Documented
public @interface FieldLengthInvalidator {
? ? // 字段支持的最大長度(字符數(shù))
? ? int maxLength() default 50;
? ? // 校驗(yàn)失敗后返回的錯(cuò)誤信息
? ? String message() default "";
? ? // 分組
? ? Class<?>[] groups() default {};
? ? // 負(fù)載
? ? Class<? extends Payload>[] payload() default {};
}

在定義注解時(shí)可聲明變量用于輔助校驗(yàn)。上面的注解中定義了maxLength變量用于指定最大長度限制。變量可以設(shè)置默認(rèn)值,使用注解時(shí)不傳參數(shù),變量就使用默認(rèn)值。

2、實(shí)現(xiàn)校驗(yàn)邏輯,校驗(yàn)失敗后返回錯(cuò)誤提示

package com.elon.springbootdemo.manager.invalidator;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
/**
?* 字段長度校驗(yàn)實(shí)現(xiàn)類。
?*?
?* @author elon
?* @version 2018年9月19日
?*/
public class FieldLengthInvalidatorImpl implements ConstraintValidator<FieldLengthInvalidator, String> {
? ? private int maxLength = 0;
? ? @Override
? ? public void initialize(FieldLengthInvalidator invalidator) {
? ? ? ? maxLength = invalidator.maxLength();
? ? }
? ? @Override
? ? public boolean isValid(String fieldValue, ConstraintValidatorContext context) {
? ? ? ? if (fieldValue.length() > maxLength) {
? ? ? ? ? ? context.disableDefaultConstraintViolation();
? ? ? ? ? ? context.buildConstraintViolationWithTemplate("對象屬性長度超過限制。").addConstraintViolation();
? ? ? ? ? ? // 校驗(yàn)失敗返回false。返回true上游收集不到錯(cuò)誤信息。
? ? ? ? ? ? return false;
? ? ? ? }
? ? ? ? return true;
? ? }
}

3、在模型字段屬性上增加校驗(yàn)的注解

public class User
{
?? ?private int userId = -1;
?? ?@FieldLengthInvalidator(maxLength=10)
?? ?private String name = "";
}

4、提供統(tǒng)一的校驗(yàn)方法

package com.elon.springbootdemo.manager;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
/**
?* 有效性校驗(yàn)管理類。對外提供統(tǒng)一的校驗(yàn)調(diào)用接口。
?* @author elon
?* @version 2018年9月19日
?*/
public class InvalidatorMgr {
? ? private InvalidatorMgr() {
? ? ? ??
? ? }
? ??
? ? /**
? ? ?* 獲取單例對象。
? ? ?*?
? ? ?* @return 單例對象
? ? ?*/
? ? public static InvalidatorMgr instance() {
? ? ? ? return InvalidatorMgrBuilder.instance;
? ? }
? ??
? ? /**
? ? ?* 校驗(yàn)?zāi)P退袑傩缘挠行浴?
? ? ?*?
? ? ?* @param model 待校驗(yàn)?zāi)P?
? ? ?* @return 錯(cuò)誤信息列表
? ? ?*/
? ? public <T> List<String> validate(T model) {
? ? ? ??
? ? ? ? ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();
? ? ? ? Validator validator = validatorFactory.getValidator();
? ? ? ? Set<ConstraintViolation<T>> resultSet = validator.validate(model);
? ? ? ??
? ? ? ? List<String> messageList = new ArrayList<>();
? ? ? ? resultSet.forEach((r)->messageList.add(r.getMessage()));? ? ? ??
? ? ? ? return messageList;
? ? }
? ??
? ? /**
? ? ?* 單例構(gòu)建器。
? ? ?* @author elon
? ? ?* @version 2018年9月19日
? ? ?*/
? ? private static class InvalidatorMgrBuilder{
? ? ? ? private static InvalidatorMgr instance = new InvalidatorMgr();
? ? }
}

5、業(yè)務(wù)層調(diào)用校驗(yàn)方法

? ? ? ? User user = new User();
? ? ? ? user.setName("ahskahskhqlwjqlwqlwhqlhwlqjwlqhwlhqwhqlwjjqlwl");
? ? ? ? List<String> messageList = InvalidatorMgr.instance().validate(user);
? ? ? ? System.out.println(messageList);

invalidator注解主要用于實(shí)現(xiàn)長度,范圍,非法字符等通用的規(guī)則校驗(yàn)。不適合用于做業(yè)務(wù)邏輯的校驗(yàn),特定的業(yè)務(wù)校驗(yàn)寫在業(yè)務(wù)層。 

springboot 參數(shù)驗(yàn)證 validation

1、綜述

springboot提供了強(qiáng)大的基于注解的、開箱即用的驗(yàn)證功能,這種基于bean validation的實(shí)現(xiàn)和 hibernate validator類似

2、依賴

創(chuàng)建springboot項(xiàng)目,包含以下依賴

<dependency>
? ? <groupId>org.springframework.boot</groupId>
? ? <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>?
? ? <groupId>org.springframework.boot</groupId>
? ? <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>?
<dependency>?
? ? <groupId>com.h2database</groupId>?
? ? <artifactId>h2</artifactId>
? ? <version>1.4.197</version>?
? ? <scope>runtime</scope>
</dependency>

3、定義實(shí)體類

測試項(xiàng)目為了方便,直接用JPA,使用@NotBlank指定非空字段,message是驗(yàn)證觸發(fā)后返回的信息,還有@Null、@NotNull、@NotBlank、@Email、@Max、@Min、@Size、@Negative、@DecimalMax、@DecimalMin、@Positive、@PositiveOrZero、@NegativeOrZero、@AssertTrue、@AssertFalse、@Future、@FutureOrPresent、@Past、@PastOrPresent、@Pattern

@Entity
public class User {
? ??
? ? @Id
? ? @GeneratedValue(strategy = GenerationType.AUTO)
? ? private long id;
? ? ?
? ? @NotBlank(message = "Name is mandatory")
? ? private String name;
? ? ?
? ? @NotBlank(message = "Email is mandatory")
? ? private String email;
? ??
? ? // standard constructors / setters / getters / toString ? ?
? ??
}

創(chuàng)建JPA的repository定義增刪改查接口

@Repository
public interface UserRepository extends CrudRepository<User, Long> {}

4、創(chuàng)建rest controller

@RestController
public class UserController {
?
? ? @PostMapping("/users")
? ? ResponseEntity<String> addUser(@Valid @RequestBody User user) {
? ? ? ? // persisting the user
? ? ? ? return ResponseEntity.ok("User is valid");
? ? }
? ? ?
? ? // standard constructors / other methods
? ? ?
}

接收到的user對象添加了@Valid,當(dāng)Spring Boot發(fā)現(xiàn)帶有@Valid注解的參數(shù)時(shí),會(huì)自動(dòng)引導(dǎo)默認(rèn)的JSR 380驗(yàn)證器驗(yàn)證參數(shù)。當(dāng)目標(biāo)參數(shù)未能通過驗(yàn)證時(shí),Spring Boot將拋出一個(gè)MethodArgumentNotValidException

5、實(shí)現(xiàn)ExceptionHandler

直接拋出異常顯然是不合理的,大部分情況需要經(jīng)過處理返回給前端更友好的提示信息,通過@ExceptionHandler來處理拋出的異常實(shí)現(xiàn)該功能

@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(MethodArgumentNotValidException.class)
public Map<String, String> handleValidationExceptions(
? MethodArgumentNotValidException ex) {
? ? Map<String, String> errors = new HashMap<>();
? ? ex.getBindingResult().getAllErrors().forEach((error) -> {
? ? ? ? String fieldName = ((FieldError) error).getField();
? ? ? ? String errorMessage = error.getDefaultMessage();
? ? ? ? errors.put(fieldName, errorMessage);
? ? });
? ? return errors;
}

MethodArgumentNotValidException作為上一步拋出的異常,當(dāng)springboot執(zhí)行validition觸發(fā)時(shí)會(huì)調(diào)用此實(shí)現(xiàn),該方法將每個(gè)無效字段的名稱和驗(yàn)證后錯(cuò)誤消息存儲(chǔ)在映射中,然后它將映射作為JSON表示形式發(fā)送回客戶端進(jìn)行進(jìn)一步處理。

6、寫測試代碼

使用springboot自帶的插件進(jìn)行測試rest controller,

@RunWith(SpringRunner.class)?
@WebMvcTest
@AutoConfigureMockMvc
public class UserControllerIntegrationTest {
?
? ? @MockBean
? ? private UserRepository userRepository;
? ? ?
? ? @Autowired
? ? UserController userController;
?
? ? @Autowired
? ? private MockMvc mockMvc;
?
? ? //... ? ??
}

@WebMvcTest允許我們使用MockMvcRequestBuilders和MockMvcResultMatchers實(shí)現(xiàn)的一組靜態(tài)方法測試請求和響應(yīng)。測試addUser()方法,在請求體中傳遞一個(gè)有效的User對象和一個(gè)無效的User對象。

@Test
public void whenPostRequestToUsersAndValidUser_thenCorrectResponse() throws Exception {
? ? MediaType textPlainUtf8 = new MediaType(MediaType.TEXT_PLAIN, Charset.forName("UTF-8"));
? ? String user = "{\"name\": \"bob\", \"email\" : \"bob@domain.com\"}";
? ? mockMvc.perform(MockMvcRequestBuilders.post("/users")
? ? ? .content(user)
? ? ? .contentType(MediaType.APPLICATION_JSON_UTF8))
? ? ? .andExpect(MockMvcResultMatchers.status().isOk())
? ? ? .andExpect(MockMvcResultMatchers.content()
? ? ? ? .contentType(textPlainUtf8));
}
?
@Test
public void whenPostRequestToUsersAndInValidUser_thenCorrectResponse() throws Exception {
? ? String user = "{\"name\": \"\", \"email\" : \"bob@domain.com\"}";
? ? mockMvc.perform(MockMvcRequestBuilders.post("/users")
? ? ? .content(user)
? ? ? .contentType(MediaType.APPLICATION_JSON_UTF8))
? ? ? .andExpect(MockMvcResultMatchers.status().isBadRequest())
? ? ? .andExpect(MockMvcResultMatchers.jsonPath("$.name", Is.is("Name is mandatory")))
? ? ? .andExpect(MockMvcResultMatchers.content()
? ? ? ? .contentType(MediaType.APPLICATION_JSON_UTF8));
? ? }
}

也可以使用postman或fiddler來測試REST controller API。

7、跑測試

@SpringBootApplication
public class Application {
? ? ?
? ? public static void main(String[] args) {
? ? ? ? SpringApplication.run(Application.class, args);
? ? }
? ? ?
? ? @Bean
? ? public CommandLineRunner run(UserRepository userRepository) throws Exception {
? ? ? ? return (String[] args) -> {
? ? ? ? ? ? User user1 = new User("Bob", "bob@domain.com");
? ? ? ? ? ? User user2 = new User("Jenny", "jenny@domain.com");
? ? ? ? ? ? userRepository.save(user1);
? ? ? ? ? ? userRepository.save(user2);
? ? ? ? ? ? userRepository.findAll().forEach(System.out::println);
? ? ? ? };
? ? }
}

如果用沒有用戶名或郵箱的數(shù)據(jù)發(fā)送請求會(huì)收到返回的提示信息

{
? "name":"Name is mandatory",
? "email":"Email is mandatory"
}

8、自定義注解

在進(jìn)行參數(shù)驗(yàn)證的時(shí)候,往往存在現(xiàn)有的約束注解不能滿足的情況,此時(shí)就需要我們自己定義validation注解了,下次介紹如何自己定義一個(gè)驗(yàn)證注解。 

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • SpringBoot中處理JSON日期格式方式

    SpringBoot中處理JSON日期格式方式

    SpringBoot中處理JSON日期格式主要有三種方式:使用@JsonFormat注解、配置默認(rèn)格式以及自定義Jackson的ObjectMapper,每種方式都有其適用場景,可以根據(jù)具體需求選擇合適的方法
    2025-02-02
  • springboot實(shí)現(xiàn)rabbitmq消息確認(rèn)的示例代碼

    springboot實(shí)現(xiàn)rabbitmq消息確認(rèn)的示例代碼

    RabbitMQ的消息確認(rèn)有兩種, 一種是消息發(fā)送確認(rèn),第二種是消費(fèi)接收確認(rèn),本文主要介紹了springboot實(shí)現(xiàn)rabbitmq消息確認(rèn)的示例代碼,具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-09-09
  • SpringCloud Webflux過濾器增加header傳遞方式

    SpringCloud Webflux過濾器增加header傳遞方式

    這篇文章主要介紹了SpringCloud Webflux過濾器增加header傳遞方式,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-02-02
  • java ThreadGroup的作用及方法詳解

    java ThreadGroup的作用及方法詳解

    這篇文章主要介紹了java ThreadGroup的作用及方法,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-10-10
  • Java cglib動(dòng)態(tài)代理原理分析

    Java cglib動(dòng)態(tài)代理原理分析

    這篇文章主要介紹了Java cglib動(dòng)態(tài)代理的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)使用Java,感興趣的朋友可以了解下
    2021-05-05
  • Springboot2.x+Quartz分布式集群的實(shí)現(xiàn)

    Springboot2.x+Quartz分布式集群的實(shí)現(xiàn)

    這篇文章主要介紹了Springboot2.x+Quartz分布式集群的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09
  • Java解析xml的四種方法匯總

    Java解析xml的四種方法匯總

    XML在不同的語言里解析方式都是一樣的,只不過實(shí)現(xiàn)的語法不同而已。java中基本的解析方式有四種,DOM解析、sax解析、JDOM解析和DOM4J解析,下面我們就來詳細(xì)探討下這四種方式
    2016-05-05
  • 史上最通俗理解的Java死鎖代碼演示

    史上最通俗理解的Java死鎖代碼演示

    這篇文章主要給大家介紹了關(guān)于Java死鎖代碼演示的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09
  • java適配器模式如何讓不兼容的接口變得兼容

    java適配器模式如何讓不兼容的接口變得兼容

    這篇文章主要為大家介紹了java適配器模式如何讓不兼容的接口變得兼容示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-09-09
  • IDEA下SpringBoot指定配置文件啟動(dòng)項(xiàng)目的全過程

    IDEA下SpringBoot指定配置文件啟動(dòng)項(xiàng)目的全過程

    我們在使用springboot項(xiàng)目開發(fā)的時(shí)候,每次切換環(huán)境跑項(xiàng)目的時(shí)候,都得修改配置文件的數(shù)據(jù)庫地址,這樣來回修改感覺很麻煩,這篇文章主要給大家介紹了關(guān)于IDEA下SpringBoot指定配置文件啟動(dòng)項(xiàng)目的相關(guān)資料,需要的朋友可以參考下
    2023-06-06

最新評論

水城县| 且末县| 北京市| 洪湖市| 桂东县| 策勒县| 寻乌县| 和静县| 沅陵县| 昭通市| 宜州市| 日土县| 宁蒗| 白朗县| 工布江达县| 花莲市| 西宁市| 安塞县| 丰宁| 罗江县| 高邑县| 合作市| 余姚市| 西青区| 澄城县| 甘南县| 广西| 桃江县| 白银市| 如皋市| 济南市| 普兰县| 板桥市| 洪江市| 资阳市| 亚东县| 南和县| 承德县| 准格尔旗| 福清市| 建昌县|