Resolve log and signature checks with spring AOP custom annotations

Source: Internet
Author: User
Tags modifier throw exception

I. Issues to be addressed
    1. Some APIs have signature parameters (signature), the passport first verifies the signature, and the validation passes before the implementation method is executed.

The first implementation method (Origin): The code that writes the checksum in the interface that requires the signature check, for example:

Boolean isValid = Accountservice.validsignature (AppID, signature, client_signature); if (!isvalid) return Errorutil.builderror (errorutil.err_code_com_sing);

The second implementation (Spring interception): Using the Spring Interceptor function to intercept the specified interface, the interceptor implements the signature verification algorithm, for example:

<mvc:interceptors>     <mvc:interceptor>            <mvc:mapping path= "/connect/share/**"/>            < Mvc:mapping path= "/friend/**"/>            <mvc:mapping path= "/account/get_bind"/> <mvc:mapping            path= "/ Account/get_associate "/>            <bean class=" Com.sogou.upd.passport.web.inteceptor.  Identityandsecureinteceptor"/>     

The third implementation approach (Spring AOP): Custom annotations that add annotations to methods that require signature validation, such as:

@SecureValid@ResponseBody @requestmapping (value = "/share/add", method = requestmethod.post) public Object Addshare (httpservletrequest req, httpservletresponse res,infoapirequestparams requestparams) {...}
2. Logging functions, such as: Some interfaces need to record the request and response, execution time, class name, method name and other log information.  can also be implemented in the above three ways. 3. Code performance monitoring issues such as method invocation time, number of times, thread and stack information, and so on. This type of problem presents a solution to the latter topic, which uses the above three methods to achieve too many shortcomings.

Here are three ways to compare implementations:

Implementation method Advantages Disadvantages
Origin

Best performance with no reflection mechanism

Code reuse is not good when logic is complex

Need to write the same code in each interface (I'm too lazy to write a few letters)

Spring Inter

Ideal for intercepting all methods, such as printing all method execution times while debugging

Similar filter functions, such as log processing, encoding conversion, permission checking

is a sub-function of AOP

No reflection mechanism, performance has an impact

Need to configure which interfaces to intercept in the XML file, it is more troublesome

Spring AOP

Easy to use, add an annotation

Very flexible, can be @before, @After, @Around, etc.

No reflection mechanism, performance is affected (performance comparison is shown in detail later)
Implementation of Spring AOP custom annotations Add the following to the Maven dependency:
<!--Spring AOP + AspectJ by Shipengzhi--<dependency> <groupid>org.springframework& Lt;/groupid> <artifactId>spring-aop</artifactId> <version>3.0.6.release</ver sion> </dependency> <dependency> <groupid>org.springframework</groupid&gt            ; <artifactId>spring-aspects</artifactId> <version>3.0.6.RELEASE</version> </de pendency> <dependency> <groupId>org.aspectj</groupId> <artifactId> aspectjrt</artifactid> <version>1.6.11</version> </dependency> <depend Ency> <groupId>org.aspectj</groupId> &LT;ARTIFACTID&GT;ASPECTJWEAVER&LT;/ARTIFACTID&G            T <version>1.6.11</version> </dependency> <dependency> &LT;GROUPID&GT;CGLib</groupid> <artifactId>cglib</artifactId> <version>2.1_3</version> </dependency> <!--End--
Add spring support in Spring-***.xml to open the AOP feature
Header file declaration: xmlns:aop= "HTTP://WWW.SPRINGFRAMEWORK.ORG/SCHEMA/AOP" HTTP://WWW.SPRINGFRAMEWORK.ORG/SCHEMA/AOP/http Www.springframework.org/schema/aop/spring-aop-3.0.xsd <!--Custom AOP--    <aop:aspectj-autoproxy Proxy-target-class= "true" >        <aop:include name= "Controlleraspect"/>    </aop:aspectj-autoproxy >    
Write custom annotations. Implements a description of the functionality implemented by the method to obtain descriptive information in the notification
/* * Verify signature legitimacy Custom transaction */@Target ({Elementtype.method}) @Retention (retentionpolicy.runtime) @Documented @inheritedpublic @ Interface Securevalid {    String desc () Default "Identity and security authentication begins ...";}

@Target is used to describe the use of annotations (that is, where the annotations described can be used), and the values are:

Take value

Describe

CONSTRUCTOR

Used to describe the constructor (lead Bento).

FIELD

Used to describe the domain (lead bento).

Local_variable

Used to describe local variables (pick-up bento).

METHOD

Used to describe a method.

Package

Used to describe the package (pick box).

PARAMETER

Used to describe parameters.

TYPE

Used to describe a class or interface (even an enum).

The @Retention is used to describe the life cycle of annotations (that is, the description of the annotations in which they are valid), with the following values:

Take value

Describe

SOURCE

Valid in the source file (that is, the source file is reserved, and the boxed box is picked).

CLASS

Valid in class file (that is, class is reserved, and the boxed box is picked).

RUNTIME

Valid at run time (that is, run-time retention).

@Documented By default the Javadoc command will not generate our annotation to the doc, so using that tag is telling the JDK that it will also generate annotation into Doc.

@Inherited For example, there is a Class A, on which there is a tag annotation, then the subclass B of a is not to be labeled annotation can inherit it, the answer is yes

  There are three types of annotation property values : base type, array type, enum type

1: Basic String type

Public @interface userdefinedannotation {      intvalue ();      String name ();      String address ();  } Used: @UserdefinedAnnotation (value=123,name= "Wangwenjun", address= "Mars") public      static void Main (string[] args) {          System.out.println ("Hello");      }  }

If there is only one attribute in a annotation named value, I can omit the attribute name when I am not using it.

Public @interface userdefinedannotation {      int value ();  }  You can also write the following form of Java code  @UserdefinedAnnotation (123)  equivalent to @UserdefinedAnnotation (value=123)    public static void Main (string[] args) {          System.out.println ("Hello");  }   

2: Array type We define a property of an array type in the custom annotation code as follows:

    1. Public @interface userdefinedannotation {      int[] value ();  }  Used: Public  class Useannotation {            @UserdefinedAnnotation ({123}) public      static void Main (string[] args) {          System.out.println ("Hello");      }  

Note 1: Where 123 of the outer braces can be omitted, because there is only one element, if there is more than one element, the curly braces cannot be omitted. For example {123,234}.
Note 2: Where the property name value is omitted when we use it, it is because he is called value, and if it is a different name we can not omit the format that must be @userdefinedannotation (property name ={123,234}).

3: Enum type

public enum Dateenum {      monday,tuesday,wednesday,thursday,friday,saturday,sunday  }  Then in the definition of a annotation package  com.wangwenjun.annatation.userdefined;    Public @interface userdefinedannotation {      dateenum week ();  }  Used: public class Useannotation {      @UserdefinedAnnotation (week=dateenum.sunday) public      static void main ( String[] args) {          System.out.println ("Hello");      }  }  

4: Default Value

Public @interface userdefinedannotation {      String name () default "Zhangsan";  }  Used: Public  class Useannotation {      @UserdefinedAnnotation () public      static void Main (string[] args) {          System.out.println ("Hello");      }  }  

5: note
Annotation is not allowed to inherit other interfaces, this is the need to pay attention, this is also a rule of annotation.
Annotation is also the existence of package structure, in the use of direct import can be.
Annotation types are supported only for OST data types, one-dimensional arrays of enum types and class types, other types or user-defined classes are not available as annotation types, I have reviewed the documents and tested them.

Write an operation log slice notification implementation class

Before writing a slice notification implementation class, we need to figure out which types of notifications we need, a pre-notification, a post-notification, a surround notification, or an exception notification. According to my needs, we know that we have logged the operation log in two cases, one is the success of the operation, one is the operation failed. When the operation is successful, the method must have been completed, we need to implement a post-notification, the operation fails to indicate that the method exception does not work properly completed, Gu also need an exception notification. The code is as follows:

@Aspect//This note indicates that the class is a slice class
@Component//Inject dependent public class Logaspect {//Callout The method body is a post-notification, and when the target method executes successfully executes the method body @AfterReturning ("Within (COM.ABCHINA.I Rms.. *) && @annotation (RL) "public void addlogsuccess (Joinpoint JP, Rmpflog RL) {object[] Parames = JP.G Etargs ();//Gets the target method body parameter String params = Parseparames (parames); Parse the parameters of the target method body String className = Jp.gettarget (). GetClass (). toString ();//Gets the target class name className = Classname.subs Tring (classname.indexof ("com")); String signature = Jp.getsignature (). toString ();//Gets the target method signature String methodName = signature.substring (signature.last IndexOf (".") +1, Signature.indexof ("(")); String modelname = Getmodelname (className); Gets the owning module according to the class name ...} Label the method body as an exception notification, and when the target method exception occurs, the method body @AfterThrowing (pointcut= "Within (com.abchina.irms) is executed. *) && @annotation (RL) ", throwing=" ex ") public void Addlog (Joinpoint JP, Rmpflog RL, businessexception ex) { ... }

There are two identical parameters JP and RL,JP are tangent objects, through which we can get the class, method name, parameters and other information of the method in which the tangent point is cut, and the method can see the implementation of the methods body. RL is the object of our custom annotation, which allows us to get the value of the parameter in the annotation. This gets the descriptive information for the method. An ex parameter is given in the exception notification, which is the exception thrown when the method executes, so that the appropriate exception information can be obtained. This is the custom exception I wrote here. Note: If you specify an exception parameter, the exception object must be consistent with the exception thrown by the method body that the notification is in, otherwise the notification will not execute.

@AfterReturning ("Within (com.abchina.irms. *) && @annotation (RL)), specifies that the method body is a post-notification with an expression parameter that is used to retrieve the tangent point that meets the criteria. The expression specifies that all method bodies with @rmpflog annotations under the Com/abchina/irms directory and all subdirectories are tangent points.

@AfterThrowing (pointcut= "Within (com.abchina.irms). *) && @annotation (RL) ", throwing=" ex "), is the specified method body as an exception notification, which has an expression parameter and a throw exception argument. The expression parameter has the same meaning as the expression parameter of the post-notification, and throws an exception argument, which means that if the com/abchina/ Any method body with @rmpflog annotations under the Irms directory and all its subdirectories will execute when the Businessexception exception is thrown at execution time.

Basic concepts of AOP:
    • Facets (Aspect): Notifications and pointcuts together form facets, times, places, and "stories" to take place.
    • Connection point (Joinpoint): A program is able to apply a "timing" of notifications, which are connection points, such as when a method is invoked, when an exception is thrown, and so on.
    • Notification (ADVICE): A notification defines what a facet is and when it is used. Describes the work to be done on the slice and when it is necessary to perform the work.
    • Entry point (Pointcut): A notification defines the "story" and the time that the slice will take place, and the Pointcut defines where the story occurs, such as the name of a class or method.
    • Target object: The object that is being notified.
    • AOP Proxy (AOP proxies) has two kinds of proxy methods in spring AOP, JDK dynamic agent and cglib agent. By default, when TargetObject implements an interface, the JDK dynamic agent is used, whereas the Cglib proxy is used instead.
    • Weaving (Weaving) the process of applying facets to a target object to create a new proxy object, weaving generally occurs in the following time:

(1) Compile time: When a class file is compiled, this requires a special compiler to do so, such as AspectJ's weaving compiler;

(2) class loading: Use special ClassLoader to enhance the byte code of the class before the target class is loaded into the program;

(3) Run time: section at a time of operation is woven into, SPRINGAOP is in this way woven into the plane, the principle is the use of the JDK dynamic agent.

pointcut expression, Pointcut the definition consists of two parts: pointcut expression (expression) and Pointcut signature (signature). Let's look at the format of the execution expression first:

Execution (modifier-pattern? ret-type-pattern declaring-type-pattern?  Name-pattern (Param-pattern) Throws-pattern?)
Pattern indicates modifier match (Modifier-pattern?), return value match (Ret-type-pattern), Classpath match (Declaring-type-pattern?), method name matching (name-pattern) , Parameter matching ((Param-pattern)), exception type matching (Throws-pattern?), followed by "?" option is available.

You can use "*" in each pattern to represent all matches. In (Param-pattern), you can specify a specific parameter type, separated by "," between multiple parameters, and each can also use "*" to indicate a match of any type of parameter, such as a (string) method that matches a string parameter; (*,string) Represents a method that matches two parameters, the first argument can be any type, and the second argument is a string type; you can use (..) Represents 0 or more arbitrary parameters.
Now let's look at a few examples:
1) Execution (* * (..)) means matching all methods
2) Execution (public * com. savage.service.userservice.* (..)) represents all of the publicly-owned methods in the matching Com.savage.server.UserService
3) Execution (* com.savage.server). *.*(..)) Represents all methods that match the Com.savage.server package and its sub-packages
In addition to the execution expression, there are also within, this, target, args and other pointcut expressions. A pointcut definition consists of a pointcut expression and a pointcut signature, for example:

Pointcut expression @pointcut ("Execution (* com.savage.aop.messagesender.* (..))") When point signs private void log () {}                             and then you want to use the defined pointcut, you can specify the pointcut signature, such as: @Before ("og ()") above the definition equivalent to: @Before ("execution (* com.savage.aop.messagesender.* (..)) ")
When pointcut is defined, you can also use &&, | | |,! operations, such as:
@Pointcut ("Logsender () | | | Logreceiver () ")
Private void LogMessage () {}
Notification (Advice) type

@Before Pre-notification (before advice): A notification that is performed before a connection point (Joinpoint), but this notification does not prevent execution before the connection point.

Post- @After notification (after advice): Notification that is executed when a connection point exits (whether it is a normal return or an unexpected exit).

@AfterReturning Notification after return advice: A notification that is executed after a connection point is completed normally, excluding the case of throwing an exception.

@Around Surround notification (Around advice): A notification that surrounds a connection point, similar to the Dofilter method of the filter in the servlet specification in the Web. You can customize the behavior before and after the call to the method, or you can choose not to execute.

@AfterThrowing Notification After an exception is thrown (after throwing advice): the notification that is executed when the method throws an exception.

Custom annotation implementations at the controller level
  /** * Security and Identity Check for Controller */@Around ("Within (@org. Springframework.stereotype.Controller *) && @ann  Otation (IS) "Public Object valididentityandsecure (Proceedingjoinpoint PJP, Securevalid is) throws Exception        {object[] args = Pjp.getargs ();        The parameters of all methods in the controller, the first two are: Request,response httpservletrequest Request = (httpservletrequest) args[0];        HttpServletResponse response = (httpservletresponse) args[1];        String AppID = Request.getparameter ("AppID");        int app_id = integer.valueof (AppID);        String signature = request.getparameter ("signature");        String clientsignature = Request.getparameter ("Client_signature");        String uri = Request.getrequesturi ();        String Provider = Request.getparameter ("provider");        if (Stringutils.isempty (provider)) {Provider = "passport";            }//Check try {appservice.validateappid (app_id) for AppID and signature; BoOlean IsValid = accountservice.validsignature (app_id, signature, clientsignature);        if (!isvalid) throw new Problemexception (errorutil.err_code_com_sing);        } catch (Exception e) {return HandleException (E, provider, URI);        }//Continue executing the next code Object retVal = null;        try {retVal = Pjp.proceed ();        } catch (Throwable e) {if (e instanceof Exception) {return handleexception ((Exception) e, provider, URI);}    }//Current interface cannot go here return retVal; }

III. implementation of Spring Interceptor Add interceptor configuration to Spring-***.xml

Writing Interceptor Implementation Classes

public class Costtimeinteceptor extends Handlerinterceptoradapter {    private static final Logger log = LOGGERFACTORY.G Etlogger (costtimeinteceptor.class);    @Override Public    Boolean prehandle (httpservletrequest request, httpservletresponse response, Object handler) Throws Exception {        long startTime = System.currenttimemillis ();        Request.setattribute ("StartTime", startTime);        return true;    }    @Override public    void Posthandle (HttpServletRequest request, httpservletresponse response, Object handler,            Modelandview Modelandview) throws Exception {        long startTime = (long) request.getattribute ("StartTime");        Long endTime = System.currenttimemillis ();        Long executetime = Endtime-starttime;        if (log.isinfoenabled ()) {            log.info ("[" + Request.getrequesturi () + "] Executetime:" + executetime + "MS");        }    }}
Four, performance comparison

experimental Environment: for/account/get_associate interface, concurrent 500, 10 minutes of pressure measurement

Index Origin Spring Inter Spring AOP
Cpu user%:26.57

sys%:10.97

cpu%:37.541

user%:26.246

sys%:10.805

cpu%:37.051

User%:24.123

sys%:9.938

cpu%:34.062

Load 13.85 13.92 12.21
QPS 6169 6093.2 5813.27
Rt

0.242ms

0.242ms

0.235ms

Using AOP has no significant effect on response time

No significant impact on load with AOP

No significant CPU impact with AOP

Conclusion: The effect of using AOP performance is negligible

Transferred from: http://www.cnblogs.com/shipengzhi/articles/2716004.html

(go) Resolve log and signature checks with spring AOP custom annotations

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.