Using Springboot to +aop+ Global exception handling with a custom annotation to achieve a uniform non-null checksum for parameters _springboot

Source: Internet
Author: User
Tags aop getmessage
First, the preface

When we write the background interface, it is unavoidable to the parameters of Non-null check, if one or two good, but if you need to write a large number of interfaces, and must fill in too many parameters, will bring us a lot of duplication of work, and a lot of similar code. The sping @requestparam annotation does not fully meet our needs because this annotation only verifies that the parameter exists in the request, and does not verify that the value of the parameter is Nulll or an empty string (""). If the argument does not exist, a Org.springframework.web.bind.MissingServletRequestParameterException exception is thrown. Although there are already many mature calibration framework, features rich, but we only need to do a non-empty checksum.

So we can customize an annotation to verify that the argument is empty. Used Framework Spring Boot:1.5.9.release jdk:1.8 II. Preparation work

First you need to create a spring boot project and introduce related MAVEN dependencies (mainly Spring-boot-starter-web and Aspectjweaver), and the Pom file is as follows:

<?xml version= "1.0" encoding= "UTF-8"?> <project xmlns= "http://maven.apache.org/POM/4.0.0" xmlns:xsi= "http ://www.w3.org/2001/XMLSchema-instance "xsi:schemalocation=" http://maven.apache.org/POM/4.0.0 Http://maven.apache . org/xsd/maven-4.0.0.xsd "> <modelVersion>4.0.0</modelVersion> <groupid>com.beauxie</grou pid> <artifactId>param-demo</artifactId> <version>0.0.1-SNAPSHOT</version> <pack Aging>jar</packaging> <name>param-demo</name> <description>param-demo for Spring boot& lt;/description> <parent> <groupId>org.springframework.boot</groupId> <artifa Ctid>spring-boot-starter-parent</artifactid> <version>1.5.9.RELEASE</version> <rel Ativepath/> <!--lookup parent from repository--> </parent> <properties> <projec T.build.sourceencoding>utf-8</project.build.sourceencoding> <project.reporting.outputencoding>utf-8</ Project.reporting.outputencoding> <java.version>1.8</java.version> </properties>
            ;d ependencies> <dependency> <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactid>spring-boot-starter-test</a
        Rtifactid> <scope>test</scope> </dependency> <!--add support Web--> <dependency> <groupId>org.springframework.boot</groupId> <artifactid>s Pring-boot-starter-web</artifactid> </dependency> <!--introducing AOP-related annotations--> <dependen Cy> <groupid>org.aspectj</groUpid> <artifactId>aspectjweaver</artifactId> <version>1.8.5</version> 
                </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactid>spring-boot-mav
 en-plugin</artifactid> </plugin> </plugins> </build> </project>

Description: Spring-boot-starter-web for spring boot Web support aspectjweaver related annotations for introducing AOP, such as @aspect, @Pointcut, and custom annotations for unified checksum

General idea: Customize a note, add the annotation to the required parameters, then define a slice, verify that the argument is empty, and throw a custom exception that is caught by the custom exception handler, and then returns the appropriate error message. 1. Custom annotations

Create a note called ' Paramcheck ' with the following code:

Package com.beauxie.param.demo.annotation;
Import Java.lang.annotation.ElementType;
Import java.lang.annotation.Retention;
Import Java.lang.annotation.RetentionPolicy;
Import Java.lang.annotation.Target;

/**
 * "parameter cannot be null" annotation, used on method parameters. * * 
 @author beauxie
 * @date Created on 2017/1/6 * * *
@Target (elementtype.parameter)
@ Retention (retentionpolicy.runtime) public
@interface Paramcheck {
    /**
     * is not NULL, default cannot be null
    * * Boolean notnull () default true;
}

Note: the @Target (Elementtype.parameter) indicates that the annotation acts on the method parameters that can be extended, such as increasing the length checksum 2. Custom exception Classes

This exception class is used in conjunction with a custom annotation, and when the ' @ParamCheck ' parameter is empty, the exception is thrown and the code is as follows:

 package com.beauxie.param.demo.exception; /** * @author Beauxie * @date Created on 2017/1/6 */public class Paramisnullexception extends {p
    Rivate final String parametername;

    Private final String ParameterType;
        Public Paramisnullexception (String parametername, String parametertype) {super ("");
        This.parametername = parametername;
    This.parametertype = ParameterType; @Override public String GetMessage () {return "Required" + this.parametertype + "parameter \" + This
    . parametername + "\ ' must is NOT NULL!";
    Public final String Getparametername () {return this.parametername;
    Public final String Getparametertype () {return this.parametertype; }
}

Description: This exception inherits RuntimeException and defines two member properties and overrides the GetMessage () method to customize the exception. Instead of the existing Org.springframework.web.bind.MissingServletRequestParameterException class, because the Missingservletrequestparameterexception is CH Ecked exception, in the dynamic agent process, it is easy to throw java.lang.reflect.UndeclaredThrowableException exception. 3. Customizing AOP

The code is as follows:

Package COM.BEAUXIE.PARAM.DEMO.AOP;
Import Com.beauxie.param.demo.annotation.ParamCheck;
Import com.beauxie.param.demo.exception.ParamIsNullException;
Import Org.aspectj.lang.JoinPoint;
Import Org.aspectj.lang.ProceedingJoinPoint;
Import org.aspectj.lang.annotation.*;
Import Org.aspectj.lang.reflect.MethodSignature;
Import Org.slf4j.Logger;
Import Org.slf4j.LoggerFactory;

Import org.springframework.stereotype.Component;
Import java.lang.annotation.Annotation;

Import Java.lang.reflect.Method;  /** * @author Beauxie * @date Created on 2017/1/6 */@Component @Aspect public class Paramcheckaop {private Logger


    Logger = Loggerfactory.getlogger (This.getclass ()); The/** * definition has a pointcut that is scoped to the class under the Web Package/@Pointcut ("Execution" (public * com.beauxie.param.demo.web).
    *.*(..))") public void Checkparam () {} @Before (' Checkparam () ') public void Dobefore (Joinpoint joinpoint) {}/ * * Check whether the parameter is null/@Around ("Checkparam ()") Public Object Doaround (Proceedingjoinpoint pjp) throws Throwable {Methodsignature signature = ((methodsignature) pjp.getsignature ());
        The method of obtaining interception methods = Signature.getmethod ();
        Gets the method parameter annotation, which returns a two-dimensional array because some parameters may have multiple annotations annotation[][] parameterannotations = Method.getparameterannotations ();
        if (parameterannotations = null | | parameterannotations.length = = 0) {return pjp.proceed ();
        }//Get method parameter name string[] paramnames = Signature.getparameternames ();
        Gets the parameter value object[] paranvalues = Pjp.getargs ();
        Gets the method parameter type class<?>[] parametertypes = Method.getparametertypes (); for (int i = 0; i < parameterannotations.length. i++) {for (int j = 0; J < Parameterannotations[i].leng Th J + +) {//If the annotation before the parameter is an instance of Paramcheck and Notnull () =true, a non-empty check if (parameterannotations[i][j) != null && parameterannotations[i][j] instanceof paramcheck && (PaRamcheck) Parameterannotations[i][j]). Notnull ()) {Paramisnull (paramnames[i], paranvalues[i], paramete Rtypes[i] = = null?
                    Null:parametertypes[i].getname ());
                Break
    }} return Pjp.proceed (); /** * Enter the content after the Pointcut return content (can be used to do some processing of processing the returned value) * * @param joinpoint/@AfterReturning ("Checkp Aram () ") public void doafterreturning (Joinpoint joinpoint) {}/** * parameter is NOT NULL checksum, if the argument is empty, throw Paramisnullexcepti On exception * @param paramname * @param value * @param parametertype/private void Paramisnull (String p Aramname, Object value, String parametertype {if (value = NULL | |
        '. Equals (Value.tostring (). Trim ())) {throw new Paramisnullexception (ParamName, parametertype); }
    }

}
4. Global exception Handler

The exception handler captures the paramisnullexception exception thrown in the PARAMCHECKAOP class and processes the code as follows:

Package com.beauxie.param.demo.exception;
Import Com.beauxie.param.demo.common.Result;
Import Com.beauxie.param.demo.enums.EnumResultCode;
Import Com.beauxie.param.demo.utils.ResponseMsgUtil;
Import Org.slf4j.Logger;
Import Org.slf4j.LoggerFactory;
Import org.springframework.web.bind.MissingServletRequestParameterException;
Import Org.springframework.web.bind.annotation.ExceptionHandler;

Import Org.springframework.web.bind.annotation.RestControllerAdvice;

Import Javax.servlet.http.HttpServletRequest;
 /** * Global exception handling.
 * Generally, the method has exception handling mechanism, but can not rule out the exception is not handled, resulting in the return to the foreground, so here to do an exception intercept, unified processing of those unhandled exceptions * * @author Beauxie * @date Created on 2017/1/6 * * @RestControllerAdvice public class Globalexceptionhandler {private static final Logger Logger = Loggerfactory.getl


    Ogger (Globalexceptionhandler.class); /** * parameter is null exception handling * @param ex * @return/@ExceptionHandler ({Missingservletrequestparameterex Ception.class, Paramisnullexception.class}) public result<sTring> Requestmissingservletrequest (Exception ex) {logger.error ("Request Exception:", ex);
    Return Responsemsgutil.builderresponse (EnumResultCode.FAIL.getCode (), ex.getmessage (), NULL); /** * Special NOTE: You can configure the specified exception handling, which handles all * @param request * @param e * @return * * @Except Ionhandler (value = exception.class) public result<string> ErrorHandler (httpservletrequest request, Exception e)
        {Logger.error ("Request Exception:", e);
    return Responsemsgutil.exception ();
 }
}

Description: Add @exceptionhandler ({missingservletrequestparameterexception.class) to the Requestmissingservletrequest () method. Paramisnullexception.class}) annotation, indicating only handling missingservletrequestparameterexception and Paramisnullexception exceptions The ErrorHandler () method handles other exceptions four, the test

Under Com.beauxie.param.demo.web package, create a new class named Hellocontroller for testing, the code is as follows:

Package com.beauxie.param.demo.web;
Import Com.beauxie.param.demo.annotation.ParamCheck;
Import Com.beauxie.param.demo.common.Result;
Import Com.beauxie.param.demo.enums.EnumResultCode;
Import Com.beauxie.param.demo.utils.ResponseMsgUtil;
Import org.springframework.web.bind.annotation.GetMapping;
Import Org.springframework.web.bind.annotation.RequestParam;

Import Org.springframework.web.bind.annotation.RestController; /** * @author Beauxie * @date Created on 2018/1/6 * */@RestController public class Hellocontroller {/** * Test @re Questparam Note * @param name * @return * * * @GetMapping ("/hello1") public result<string> Hello1 (@ Requestparam String Name {return Responsemsgutil.builderresponse (EnumResultCode.SUCCESS.getCode (), "Successful Request", "Hell
    O, "+ name); /** * Test @paramcheck annotation * @param name * @return * * * @GetMapping ("/hello2") public RESULT&L T String> Hello2 (@ParamCheck String name) {return ResponsemSgutil.builderresponse (EnumResultCode.SUCCESS.getCode (), "Request succeeded", "Hello," + name);
    /** * Test @paramcheck with @requestparam * @param name * @return/@GetMapping ("/hello3") Public result<string> Hello3 (@ParamCheck @RequestParam String name) {return responsemsgutil.builderresponse
    (EnumResultCode.SUCCESS.getCode (), "Request succeeded", "Hello," + name); }

Finally, run the Paramdemoapplicatio Main method and open the browser to test. 1. Test @requestparam Note parameter name is NULL test
In the browser's address bar input: http://localhost:8080/hello1, the result is as follows:

Background error message output:

The background will now report org.springframework.web.bind.MissingServletRequestParameterException:Required String parameter ' name ' is not Present error message indicating that parameter ' name ' does not exist

Parameter name is not NULL, value is NULL test
In the browser's address bar input: http://localhost:8080/hello1?name=, the result is as follows:


At this point, the value of name is empty, but the result of the request returns normally.

Parameter name and value are NOT NULL test
In the browser's address bar input: Http://localhost:8080/hello1?name=Beauxie, the result is as follows:
2. Test @paramcheck Note parameter name is NULL test
In the browser's address bar input: Http://localhost:8080/hello2, the result is as follows:

Background error message output:

Parameter name is not NULL, value is NULL test
In the browser's address bar input: http://localhost:8080/hello2?name=, the result is as follows:

At this point, the value of name is NULL, and the request result y indicates that the value of parameter name cannot be null.
Background error message output:

Parameter name and value are NOT NULL test
In the browser's address bar input: Http://localhost:8080/hello2?name=Beauxie, the result is as follows:
3. Test summary When the parameter name is empty, the interface that adds two annotations prompts the argument not to be empty, the value is empty, the @RequestParam annotation does not error, but the value of the @paramcheck annotation prompt parameter ' name ' is empty v. Through the above test also verified that @requestparam will only verify that the corresponding parameters exist, and will not verify that the value is empty Paramcheck can also be extended, such as the length of the parameter value, whether there are illegal characters, such as verification of six, the source download address

Because csdn download requires points, add GitHub Source address: Github:https://github.com/beauxie/projects-demo csdn:http://download.csdn.net/ download/beauxie/10191744

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.