I. Annotations
Java defines four meta-annotations: @target,@Retention,@Documented, and @Inherited
1. @ Target annotation
Illustrates the range of objects that annotations modify: Annotations can be used for packages, classes, interfaces, enumerations, Annotation types, methods, constructors, member variables, enumerated values, method parameters, and local variables (such as loop variables, catch parameters). Target is used in the Annotation type declaration to clarify the target it modifies.
** Is used to describe the scope of the annotation (i.e. where the described annotation can be used).
The values (ElementType) are:
LOCAL_VARIABLE used to describe local variables 4.METHOD used to describe methods 5.PACKAGE Used to describe packages 6.PARAMETER Used to describe parameters 7.TYPE: Used to describe classes, interfaces (including annotation types), or enum declarations
2. @ Retention annotations
Defines how long annotations can be retained: some annotations appear only in the source code and are discarded by the compiler; Others are compiled in class files; Annotations compiled in the class file may be ignored by the virtual machine, while others will be read when the class is loaded (note that class execution is not affected, since annotations and the class are used separately). Use this meta-annotation to limit the “life cycle” of an Annotation.
** Function: ** indicates the level at which the annotation information needs to be saved to describe the lifecycle of the annotation (i.e., the extent to which the described annotation is valid)
The values are as follows:
1.SOURCE: valid in the SOURCE file (i.e. reserved) 2.CLASS: valid in the CLASS file (i.e. reserved) 3.RUNTIME: valid at RUNTIME (i.e. reserved at RUNTIME)
3. @ Documented annotation
A public API for describing other types of annotations should be used as annotated program members, and therefore can be documented by tools such as Javadoc. Documented is a marked annotation that has no member. — — — — — — — — — — — — extract
4. @ Inherited annotations
This is a markup annotation. @Inherited explains that an annotated type is Inherited. If an annotation type with the @Inherited annotation is applied to a class, the annotation will be applied to a subclass of that class.
Implement custom annotations
import java.lang.annotation.*;
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface LogRecord {
/** * The function of the labeled method *@return* /
String effect(a) default "";
}
Copy the code
Third, integrate AOP functions
1. Maven adds AOP function-dependent dependencies
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
Copy the code
2. Write AOP code
import com.almond.mpdemo.common.annotation.LogRecord;
import com.almond.mpdemo.common.utils.HttpUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;
/ * * *@Classname LogAspect
* @DescriptionScanning custom annotations for enhanced logging *@Date 2020/9/4 9:27
* @Created by hongxing
*/
@Slf4j
@Component
@Aspect
public class LogAspect {
@Resource
private TLogMapper tLogMapper;
// Set the pointcut to be the path of the annotation
@Pointcut("@annotation(com.almond.mpdemo.common.annotation.LogRecord)")
public void annotationAspect(a) {}/** * The thread ID * request IP */
@Around(value = "annotationAspect()")
@Transactional(rollbackFor = {Exception.class})
public Object doAround(ProceedingJoinPoint joinPoint) {
log.info("Proxy execution, proxy method {}", ((MethodSignature) joinPoint.getSignature())
.getMethod().getName());
LogRecord logRecord = ((MethodSignature) joinPoint.getSignature())
.getMethod()
.getAnnotation(LogRecord.class);
String name = "";
if(logRecord ! =null) {
name = ((MethodSignature) joinPoint.getSignature())
.getMethod().toGenericString();
}
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder
.getRequestAttributes()).getRequest();
String host = HttpUtil.getIpAddress(request);
Long id = Thread.currentThread().getId();
// Log drop
// Persist the log information here
try {
// Execute the original method
joinPoint.proceed();
} catch (Throwable throwable) {
log.error("Exception occurred on the agent, exception message {}", throwable.getMessage());
}
return null; }}Copy the code
3. Related tools
package com.almond.mpdemo.common.utils;
import javax.servlet.http.HttpServletRequest;
/ * * *@Classname HttpUtil
* @Description
* @Date2020/9/4 and *@Created by hongxing
*/
public class HttpUtil {
/** * Request. GetRemoteAddr (); The reason is that it is possible that users use proxy software to avoid real IP addresses, * References: http://developer.51cto.com/art/201111/305181.htm * * however, if by the multistage reverse proxy, X - Forwarded - For the value and more than one, but a string of IP value, Which is the real IP of the real client? * The answer is to take the first non-unknown valid IP string from x-Forwarded-For. * * For example, x-Forwarded-for: 192.168.1.110, 192.168.1.120, 192.168.1.130, * 192.168.1.100 * * The real IP address of this user is 192.168.1.110 * *@param request
* @return* /
public static String getIpAddress(HttpServletRequest request) {
String ip = request.getHeader("x-forwarded-for");
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_CLIENT_IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_X_FORWARDED_FOR");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
returnip; }}Copy the code
4. Test the demo
Annotate the method, call the method, observe the control log, and if proxy execution occurs, proxy method XXX indicates the function implementation.