1. Beschreibung
Vor Kurzem hatte ich die Idee, eine persönliche Website zu erstellen, und begann spontan eine Programmierreise. Machen Sie es einfach. Nachdem das Projekt-Framework (SpringMVC+mybatis+mysql) erstellt wurde, beginnen Sie über das Design des Protokolls im Projekt nachzudenken. Nach Überlegung und in Kombination mit Online-Informationen haben wir uns entschieden, Anmerkungen zum Aufzeichnen von Zugriffsprotokollen zu verwenden. Natürlich ist das aktuelle Protokolldesign noch nicht perfekt und wird im Laufe des Entwicklungsprozesses schrittweise verbessert.
2. Implementierung
2.1 Über AOP und verwandte Kommentare
Im Vergleich zu AOP bevorzugen viele Menschen die Verwendung von Interception Ein Server zum Verwalten von Protokollen. Dies hängt von Ihren persönlichen Vorlieben ab. Wie implementiert man den AOP-Interception-Controller? Da der Controller standardmäßig als Proxy an JDK übergeben wird, muss AOP den Controller daher dem cglib-Proxy zuweisen, wenn er ihn abfangen kann.
Das Folgende ist eine Einführung in die vom AOP-Interception-Controller verwendeten Annotationen (die rot markierten Felder stellen diejenigen dar, die verwendet werden). Natürlich können wir auch Konfigurationsdateien verwenden, um sie zu definieren, aber ich persönlich bevorzuge Um die Module zu gruppieren, ist es wirklich ermüdend, die Konfigurationsdatei zu finden ~
@Target: Der Zweck der Annotation, d. Enthält:
Elementtype. .Constructor Constructor
Elementtype.
RetentionPolicy. Anmerkungen werden in der Klassenbytecodedatei beibehalten Zur Laufzeit abgerufen. Die Annotation „RetentionPolicy.RUNTIME“ ist in der Klassenbytecodedatei vorhanden und kann abgerufen werden durch Reflexion zur Laufzeit. 🎜>
@Document: Dies bedeutet, dass die Anmerkung in oben in den Kommentaren in Javadoc enthalten ist, plus @ inherited,@reinaatable
>
Annotationen werden in Java als Meta-Annotationen bezeichnet. Was sind Meta-Anmerkungen?Die Rolle von Meta-Anmerkungen besteht darin, andere Anmerkungen zu kommentieren. Java5.0 definiert vier Standard-Meta-Annotationstypen, die zur Beschreibung anderer Annotationstypen verwendet werden.
Für eine Erläuterung von Annotationen und Meta-Annotationen klicken Sie bitte hier
@Aspect: Wenn @Aspect für eine Klasse deklariert wird, bedeutet dies, dass diese Klasse als Aspekt verwendet wird ist eine Aspektklasse. Zu diesem Zeitpunkt kann der Container diese Klasse lesen, jedoch nur, wenn der cglib-Agent aktiviert ist.
@Component: Deklarieren Sie die Klasse als Bean und injizieren Sie sie in den Container. Spring scannt und lädt sie beim Start. Der Effekt ist derselbe wie beim Definieren der Bean in der Konfigurationsdatei.
@Pointcut: Annotation auf Methodenebene Nach Verwendung dieser Annotation kann von anderen Methoden darauf verwiesen werden.
Es gibt 5 Benachrichtigungsanmerkungen, die mit @Aspect und @Pointcut verwendet werden und auch erweiterte Annotationen genannt werden:
Die Methode -Leiterin, verwenden Sie die Rückkehr, um auf den Methodenrückgabewert '' Out '' s 1 Way Out Out Out Out Through Avhe Through Ray Out Out Out Out Out Out Out Out Out Out Out Out Out Out Out Out Out Out Out Out Out Out Out Out Out Out of Out Out Out) aus Ofto After-To also so- w-i's tossing to base, Surround-Benachrichtigung, an der Spitze der Methode platziert, bestimmt diese Methode die tatsächliche Methode Ob sie ausgeführt werden soll, und es muss ein Rückgabewert vorhanden sein
2.2 cglib-Agent konfigurierenFügen Sie den folgenden Code zur Datei spring-mvc.xml hinzu:
<aop:aspectj-autoproxy proxy-target-class="true" />
Wenn wir benutzerdefinierte Anmerkungen erstellen, führt die Verwendung von @interface im Allgemeinen dazu, dass diese Klasse standardmäßig Anmerkungen erbt. Der Code lautet wie folgt: package com.t1heluosh1.system.log.annotion;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 日志controller层注解
*
* @author xuyong
*
*/
//作用于参数和方法上
@Target({ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SysControllerLog {
int logType() default 100; //日志类型,默认为100-系统
int module() default 100; //操作模块,默认为100-登录
String description() default ""; //操作描述
}
<context:component-scan base-package="com.t1heluosh1.system.log" > <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/> </context:component-scan>
Hier gibt es nichts mehr zu sagen, schauen Sie sich einfach den Code an:
package com.t1heluosh1.system.log.aspect; import java.lang.reflect.Method; import java.util.Date; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import org.apache.log4j.Logger; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.aspectj.lang.reflect.MethodSignature; import org.springframework.stereotype.Component; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import com.t1heluosh1.pullulate.biz.sysLog.service.SysLogService; import com.t1heluosh1.pullulate.biz.sysLog.vo.SysLogVo; import com.t1heluosh1.pullulate.biz.user.model.User; import com.t1heluosh1.system.constant.SysParams; import com.t1heluosh1.system.log.annotion.SysControllerLog; import com.t1heluosh1.util.IPUtil; /** * 日志切点类即实现类 * * @author xuyong * */ @Aspect @Component public class SysLogAspect { //本地异常日志记录对象 private static final Logger logger = Logger.getLogger(SysLogAspect.class); @Resource private SysLogService logService; //切入点定义:controller @Pointcut("@annotation(com.t1heluosh1.system.log.annotion.SysControllerLog)") public void controllerAspect() { System.out.println("---------------------controllerAspect for log start----------------------------"); } /** * controller切入点方法实现 * * @param joinPoint */ @Before("controllerAspect()") public void doBefore(JoinPoint joinPoint) { HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder .getRequestAttributes()).getRequest(); //获取登录用户的信息 User user = (User)request.getSession().getAttribute(SysParams.CURRENT_USER); //获取请求IP地址 String ip = IPUtil.getRemoteHost(request); try { String methodDesc = getControllerMethodDescription(joinPoint); System.out.println("request method : " + joinPoint.getTarget().getClass().getName()+"."+joinPoint.getSignature().getName()+"()"); System.out.println("method description : " + methodDesc); System.out.println("request username : " + (user==null?"no login info found":user.getUserName())); System.out.println("request ip address : "+ ip); System.out.println("insert log infos into db start ..."); //获取相关日志参数 Object[] orgs = joinPoint.getArgs(); SysLogVo sysLogVo = null; if (orgs != null && orgs.length > 0) { for (Object obj:orgs) { if (obj instanceof SysLogVo) sysLogVo = (SysLogVo)obj; } } if (sysLogVo == null) { sysLogVo = new SysLogVo(); } //执行日志入库操作 //获取注解的信息 MethodSignature ms = (MethodSignature)joinPoint.getSignature(); Method method = ms.getMethod(); SysControllerLog log = method.getAnnotation(SysControllerLog.class); sysLogVo.setLogType(log.logType()); sysLogVo.setModule(log.module()); sysLogVo.setIpAddr(ip); sysLogVo.setUrl(request.getRequestURI()); sysLogVo.setMethodName(joinPoint.getTarget().getClass().getName()+"."+joinPoint.getSignature().getName()+"()"); sysLogVo.setMethodDesc(methodDesc); //TODO:remark可根据业务来进行改变,暂时为方法描述 sysLogVo.setRemark(log.description()); Date date = new Date(); sysLogVo.setAddTime(date); sysLogVo.setAddUser(user==null?SysParams.ADMIN_ID:String.valueOf(user.getId())); sysLogVo.setUpdateTime(date); sysLogVo.setUpdateUser(user==null?SysParams.ADMIN_ID:String.valueOf(user.getId())); logService.save(sysLogVo); System.out.println("insert log infos into db successful."); } catch (Exception e) { logger.error("--------------controllerAspect for log fail-----------------------"); logger.error("exception info : ", e); } } /** * 获取方法的描述 * * @param joinPoint * @return * @throws Exception */ @SuppressWarnings("rawtypes") private String getControllerMethodDescription(JoinPoint joinPoint) throws Exception { //获取目标类名 String targetName = joinPoint.getTarget().getClass().getName(); //获取方法名 String methodName = joinPoint.getSignature().getName(); //获取相关参数 Object[] arguments = joinPoint.getArgs(); //生成类对象 Class targetClass = Class.forName(targetName); //获取该类中的方法 Method[] methods = targetClass.getMethods(); String description = ""; for(Method method : methods) { if(!method.getName().equals(methodName)) { continue; } Class[] clazzs = method.getParameterTypes(); if(clazzs.length != arguments.length) { continue; } description = method.getAnnotation(SysControllerLog.class).description(); } return description; } }
Die spezifische Methode ist wie folgt: Das obige ist der detaillierte Inhalt vonJava-Entwicklungspraxis: SpringMVC verwendet AOP zum Verwalten von Zugriffsprotokollen. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!/**
* 跳转到登陆页面
*
* @param request
* @return
* @throws Exception
*/
@RequestMapping(value="login")
@SysControllerLog(description="跳转到登录页面",logType=100,module=100)
public ModelAndView gotoLogin(HttpServletRequest request) {
ModelAndView modelAndView = new ModelAndView("/show/login");
return modelAndView;
}