Spring Boot development unified exception and JSR303 data verification processing

Spring Boot exception handling

In actual project development, all kinds of exceptions often occur in programs, especially as service developers, we always write interfaces to the front-end calls. In the case of division of labor and cooperation, exceptions can not be avoided. If the wrong information is directly exposed to users, this experience can be imagined, and for hackers, Detailed exception information is often very helpful

Spring Boot default exception handling mechanism

Spring Boot provides a default exception handling mechanism. Once an exception occurs in the program, Spring Boot will automatically identify the type of client (browser client or machine client) and display the exception information in different forms according to different clients.

  1. For the browser client, Spring Boot will respond to a "whitelabel" error view and present the error message in HTML format, as shown in the figure below

In springboot, by default, when sending exceptions, it will jump to the value / error request to display errors. Different error results will be displayed according to different content types. For example, when requesting json, it will directly return json format parameters.

  1. For the machine client, Spring Boot will generate a JSON response to display the exception message.

    The default exception handling mechanism provided by Spring Boot is not necessarily suitable for our actual business scenarios. Therefore, we usually customize Spring Boot global exceptions according to our own needs, such as customizing error pages, customizing error data, etc.

Spring Boot global unified exception handling

In web applications, exceptions are very common when processing requests. Therefore, when various exceptions occur in the application, it is very necessary to capture or re process the exceptions (for example, if sql exceptions are normal, they cannot be thrown out). For example, when developing external api services, the response parameter formats, such as respCode and respMsg, are agreed, and the caller carries out its own business logic according to the error code.

Create a global unified exception handling class

Obviously, the default exception page is unfriendly to users or callers, so generally, we will give exception tips to implement our own business.

Use @ ControllerAdvice and @ ExceptionHandler to define a unified exception handling class

  • @ControllerAdvice: controller enhancement to apply @ ExceptionHandler, @ InitBinder, @ ModelAttribute annotated methods to all
    @Method of RequestMapping annotation.
  • @ExceptionHandler: exception handler. This annotation is used to handle the defined exception when it occurs

Create exception class: CommonExceptionHandler

public class CommonExceptionHandler {

     *  Intercept exceptions of Exception class
     * @param e
     * @return
    public Map<String,Object> exceptionHandler(Exception e){
        Map<String,Object> result = new HashMap<String,Object>();
        result.put("respCode", "9999");
        result.put("respMsg", e.getMessage());
        //In normal development, a unified response entity can be created, such as CommonResp
        return result; 

If different exceptions (such as user-defined exceptions) need to be handled differently, you can write multiple exceptionhandler methods to annotate the exception class handled by exceptionhandler, such as

 * Intercept the exception of CommonException
 * @param ex
 * @return
public Map<String,Object> exceptionHandler(CommonException ex){
    log.info("CommonException: {}({})",ex.getMsg(), ex.getCode());
    Map<String,Object> result = new HashMap<String,Object>();
    result.put("respCode", ex.getCode());
    result.put("respMsg", ex.getMsg());
    return result; 

Because @ ResponseBody is added, the returned format is json,

Different exceptions can be intercepted and prompted, such as NoHandlerFoundException, HttpMediaTypeNotSupportedException, AsyncRequestTimeoutException, etc

When returning to the page, return to ModelAndView, as shown in

@ExceptionHandler(value = Exception.class)
    public ModelAndView defaultErrorHandler(HttpServletRequest req, Exception e) throws Exception {
        ModelAndView mav = new ModelAndView();
        mav.addObject("exception", e);
        mav.addObject("url", req.getRequestURL());
        return mav;

Since there is only a front-end and back-end separation development mode in work, there is generally no need to directly return the resource page. Generally, it returns fixed response formats, such as respCode, respMsg and data. The front end determines whether to pop up or jump to the page by judging the value of respCode.

JSR303 data verification processing

For any application, the data validation done by the client is not safe and effective, and data validation is the most basic functional module on the enterprise project architecture. At this time, we are required to verify the effectiveness of the data when the server receives the data. Why do you say that? When we write programs, we often feel that the background verification is irrelevant. After all, the client has been verified, and the back end does not need to waste resources to verify the data, but it is precisely this kind of thinking that is most likely to be exploited by others. After all, as long as you have some development experience, we can simulate the HTTP request to the background address and send some data related to system security to the background during the simulation request. The consequences can be imagined

Traditional data verification

In web development, the validity of request parameters generally needs to be verified. In the original writing method, it is judged field by field. This method is too generic, so the JSR 303: Bean Validation specification of java solves this problem.

Use JSR-303 annotation

In Springboot, @ validated can be used to verify the data. If the data is abnormal, exceptions will be thrown uniformly to facilitate the unified processing of the exception center. Let's write a comment here so that our name can only support Email format;

@Component //Register bean
@ConfigurationProperties(prefix = "person")
@Validated  //data verification 
public class Person {

    @Email(message="Mailbox format error") //name must be in mailbox format
    private String name;

Running result: default message [not a legal email address];

Using data verification can ensure the correctness of data;

Common parameters

@NotNull(message="Name cannot be empty")
private String userName;
@Max(value=120,message="The oldest can't check 120")
private int age;
@Email(message="Mailbox format error")
private String email;

Empty check
@Null       Verify that the object is null
@NotNull    Verify that the object is not null, Cannot check string with length 0
@NotBlank   Check whether the constraint string is Null And by Trim Is the length greater than 0,String only,And the front and back spaces will be removed.
@NotEmpty   Check whether the constraint element is NULL Or EMPTY.
Booelan inspect
@AssertTrue     verification Boolean Whether the object is true  
@AssertFalse    verification Boolean Whether the object is false  
Length check
@Size(min=, max=) Validation object( Array,Collection,Map,String)Is the length within the given range  
@Length(min=, max=) string is between min and max included.

Date check
@Past       verification Date and Calendar Is the object before the current time  
@Future     verification Date and Calendar Is the object after the current time  
@Pattern    verification String Whether the object conforms to the rules of regular expressions

 In addition, we can also customize some data verification rules

Tags: Java Javascript Spring Boot

Posted on Thu, 11 Nov 2021 14:47:14 -0500 by danboy712