Configure parameters for startup verification

If the configuration file does not contain the relevant configuration, the following exception will occur when ** starts:

Description: Binding to target com.toby.provide.ApplicationProperties@31da6b2e failed: Property: Feichao.info. name Value: null Reason: The name cannot be empty.Copy the code

Fat toward small voice force force: improve code stability, fat toward think the best way is to prevent in advance. In a real project, we configure various parameters in the configuration file. However, as we all know, the configuration parameters of different environments will be different. It is inevitable that some key parameters are missing in the configuration file of an environment due to human negligence. It is bound to be an inefficient and unreliable way to check by naked eyes. If you do not check this way, it is easy to trigger a pit in a particular scenario. But you use this way, do a lot of startup verification, once the parameters are not legal, the project can not start, do prevent!

Controller

HelloDTO

@Data
public class HelloDTO {

    @NotBlank
    private String name;

    @Min(0)
    @Max(150)
    private int age;

}
Copy the code

HelloController

@RestController
public class HelloController {

    @RequestMapping("/controllerValid")
    public String controllerValid(@RequestBody @Valid HelloDTO helloDTO) {
        return "ok"; }}Copy the code

Request parameters are

{
	"name":"The fat." "."age": 151}Copy the code

Is displayed, a verification exception occurs

org.springframework.web.bind.MethodArgumentNotValidException
Copy the code

Service

HelloDTO

@Data
public class HelloDTO {

    @NotBlank
    private String name;

    @Min(0)
    @Max(150)
    private int age;

}
Copy the code

AService

public interface AService {

    int insertUser(HelloDTO helloDTO);

}
Copy the code

AServiceImpl

@Service
public class AServiceImpl implements AService {

    @Autowired
    private BService bService;

    @Override
    public int insertUser(HelloDTO helloDTO) {
        returnbService.insertUser(helloDTO); }}Copy the code

BService

public interface BService {

    int insertUser(@Valid HelloDTO helloDTO);

}
Copy the code

BServiceImpl

@Service
@Slf4j
@Validated
public class BServiceImpl implements BService {

    @Override
    public int insertUser(HelloDTO helloDTO) {
        log.info("BService insertUser...");
        return 0; }}Copy the code

Unit testing

@RunWith(SpringRunner.class)
@SpringBootTest
public class AserviceTest {

    @Autowired
    private BService bService;

    @Test
    public void testInsertUser(a) throws Exception {
        HelloDTO helloDTO = newHelloDTO(); bService.insertUser(helloDTO); }}Copy the code

Output verification exception information:

javax.validation.ConstraintViolationException
Copy the code

Dubbo

Dubbo’s official documentation has been very detailed, the address is: dubbo.apache.org/zh-cn/docs/…

The parameter validation function is implemented based on JSR303. The user only needs to identify the JSR303 standard validation annotation and implement the validation by declaring filter.

Maven rely on

< the dependency > < groupId > javax.mail. Validation < / groupId > < artifactId > validation - API < / artifactId > < version > 1.0.0. GA < / version > </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-validator</artifactId> < version > 4.2.0. Final < / version > < / dependency >Copy the code

The sample

Parameter Annotation Example

import java.io.Serializable;
import java.util.Date;
 
import javax.validation.constraints.Future;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Past;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;
 
public class ValidationParameter implements Serializable {
    private static final long serialVersionUID = 7158911668568000392L;
 
    @NotNull // Null is not allowed
    @Size(min = 1, max = 20) // Length or size range
    private String name;
 
    @NotNull(groups = ValidationService.Save.class) // The field cannot be empty when saved, but can be empty when updated, indicating that the field is not updated
    @Pattern(regexp = "^\\s*\\w+(? : \ \. {0, 1} [-] \ \ w +) * @ [a - zA - Z0-9] + (? :[-.][a-zA-Z0-9]+)*\\.[a-zA-Z]+\\s*$")
    private String email;
 
    @Min(18) / / the minimum
    @Max(100) / / Max
    private int age;
 
    @Past // Must be a past time
    private Date loginDate;
 
    @Future // Must be for a future time
    private Date expiryDate;
 
    public String getName(a) {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public String getEmail(a) {
        return email;
    }
 
    public void setEmail(String email) {
        this.email = email;
    }
 
    public int getAge(a) {
        return age;
    }
 
    public void setAge(int age) {
        this.age = age;
    }
 
    public Date getLoginDate(a) {
        return loginDate;
    }
 
    public void setLoginDate(Date loginDate) {
        this.loginDate = loginDate;
    }
 
    public Date getExpiryDate(a) {
        return expiryDate;
    }
 
    public void setExpiryDate(Date expiryDate) {
        this.expiryDate = expiryDate; }}Copy the code

Group validation Example

public interface ValidationService { @notnull (groups = validationService.class)
    @interface Save{} / / interface and the method of the same name, capitalize the first letter, is used to distinguish between validation scenarios, such as: @ NotNull (groups = ValidationService. Save. Class), optional
    void save(ValidationParameter parameter);
    void update(ValidationParameter parameter);
}
Copy the code

Example of association verification

import javax.validation.GroupSequence;
 
public interface ValidationService {   
    @GroupSequence(Update.class) // Validate the Update group rules as well
    @interface Save{}
    void save(ValidationParameter parameter);
 
    @interface Update{} 
    void update(ValidationParameter parameter);
}
Copy the code

Parameter Verification Example

import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
 
public interface ValidationService {
    void save(@NotNull ValidationParameter parameter); // Verify that the parameter is not null
    void delete(@Min(1) int id); // Validate the basic type parameters directly
}
Copy the code

configuration

Validate parameters on the client side

<dubbo:reference id="validationService" interface="org.apache.dubbo.examples.validation.api.ValidationService" validation="true" />
Copy the code

Validate parameters on the server side

<dubbo:service interface="org.apache.dubbo.examples.validation.api.ValidationService" ref="validationService" validation="true" />
Copy the code

Verifying exception information

import javax.validation.ConstraintViolationException;
import javax.validation.ConstraintViolationException;
 
import org.springframework.context.support.ClassPathXmlApplicationContext;
 
import org.apache.dubbo.examples.validation.api.ValidationParameter;
import org.apache.dubbo.examples.validation.api.ValidationService;
import org.apache.dubbo.rpc.RpcException;
 
public class ValidationConsumer {   
    public static void main(String[] args) throws Exception {
        String config = ValidationConsumer.class.getPackage().getName().replace('. '.'/') + "/validation-consumer.xml";
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(config);
        context.start();
        ValidationService validationService = (ValidationService)context.getBean("validationService");
        // Error
        try {
            parameter = new ValidationParameter();
            validationService.save(parameter);
            System.out.println("Validation ERROR");
        } catch (RpcException e) { // RpcException is thrown
            ConstraintViolationException ve = (ConstraintViolationException) e.getCause(); / / embedded inside a ConstraintViolationExceptionSet<ConstraintViolation<? >> violations = ve.getConstraintViolations();// Get a collection of validation error detailsSystem.out.println(violations); }}}Copy the code

1. Supported since version 2.1.0, you can refer to the sample code in the Dubbo project (github.com/apache/incu…) for how to use it.

2. The authentication mode can be extended. For the extension mode, see authentication Extension in the Developer manual (dubbo.apache.org/zh-cn/docs/…).

Tool class verification

ValidationUtils

public class ValidationUtils {

    private static Validator validator = Validation
            .byProvider(HibernateValidator.class)
            .configure()
            .failFast(true)
            .buildValidatorFactory()
            .getValidator();


    public static <T> void validate(T obj) {
        Set<ConstraintViolation<T>> validate = validator.validate(obj);
        for (ConstraintViolation<T> violation : validate) {
            // Note that in real business
            // This will be initialized according to violation
            // Then the custom exception is thrown}}}Copy the code

Unit testing

@Test
public void testValidationUtils(a) throws Exception {
    HelloDTO helloDTO = new HelloDTO();
    ValidationUtils.validate(helloDTO);
}
Copy the code

Type on the blackboard and underline

The above five examples of verification methods are all based on hibernate-validate. But if you’re careful, you’ll notice that when you search for hibernate-validate, there’s only ** Controller ** on the web, so you’ll get code examples from multiple layers that cover almost all of your scenarios.

Also note that the controller layer throws a validation exception of the type

org.springframework.web.bind.MethodArgumentNotValidException
Copy the code

The type of validation exception thrown by the service layer is

javax.validation.ConstraintViolationException
Copy the code

Tool class verification, you need to get the parameter processing, and then custom exception thrown. So be careful when doing global exceptions.

Of course, this verification method does not only make the parameter check ratio

if (helloDTO.getAge() <= 0) {
    / /...
}
Copy the code

A lot of elegant, but also support custom annotations to achieve verification rules, internationalization, group verification, etc., these specific use of your project, you can go to see.

Of course, there are many ways to improve the stability of the code, but Fei Zhao believes that the way of parameter verification, cost and effect is one of the highest cost-effective, do you have any way to improve the stability of the code? Leave a message telling Fat Chao.

Write in the last