您好,登錄后才能下訂單哦!
怎樣創(chuàng)建一個(gè)與Servlet-api完全解耦和的管理員后臺(tái)操作日志監(jiān)控,很多新手對(duì)此不是很清楚,為了幫助大家解決這個(gè)難題,下面小編將為大家詳細(xì)講解,有這方面需求的人可以來學(xué)習(xí)下,希望你能有所收獲。
在日常開發(fā)系統(tǒng)后臺(tái)時(shí),需要針對(duì)管理員操作進(jìn)行監(jiān)控,如果使用Spring這一套技術(shù)體系,使用AOP切面編程+自定義注解不妨是一個(gè)好辦法,但是在使用這一套體系的同時(shí)也會(huì)出現(xiàn)一些坑。比如這一套體系是完全依賴于WEB環(huán)境,脫離WEB環(huán)境就會(huì)出現(xiàn)出現(xiàn)ServletRequestAttributes為null的情況。那么如何解決這個(gè)問題。
首先快速搭建一個(gè)Spring 的運(yùn)行環(huán)境具體jar參照下圖:
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<!--jstl-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!--spring-->
<!--spring相關(guān)依賴-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.3.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>4.3.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.3.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.3.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>4.3.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>4.3.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>4.3.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>4.3.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.3.2.RELEASE</version>
</dependency>
<!--springmvc-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.3.2.RELEASE</version>
</dependency>
<!--mybatis-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.2.5</version>
</dependency>
<!--mybatis-spring-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.2</version>
</dependency>
<!--mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.38</version>
</dependency>
<!--druid-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.10</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.47</version>
</dependency>
<!--commons-fileupload-->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3</version>
</dependency>
<!--jackson-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.5</version>
</dependency>
<!--log4j-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.16</version>
</dependency>
<!--junit測(cè)試-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
首先對(duì)前面的開發(fā)步驟做一個(gè)簡(jiǎn)單的講解,首先開發(fā)一個(gè)自定義注解:
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
//在方法上使用
@Target({ElementType.METHOD})
//類一旦運(yùn)行 起作用
@Retention(RetentionPolicy.RUNTIME)
public @interface LogAnnotation {
public String value();
}
開發(fā)環(huán)繞通知(常規(guī)做法,下面做修改)
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpSession;
import java.lang.reflect.Method;
import java.util.Date;
/*
*
* 這是一個(gè)環(huán)繞通知
* 需要實(shí)現(xiàn)
* */
public class Around implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
/*
* 1.什么人--------
* 2.什么時(shí)間 new Date()
* 3.什么事情----方法名
* 4.是否成功-----能
* */
ServletRequestAttributes s = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
//獲取HttpRequst對(duì)象,于Servlet強(qiáng)耦合
HttpSession session = s.getRequest().getSession();
//拿到存放在Session的數(shù)據(jù)
String adminName = (String)session.getAttribute("admin");
//時(shí)間
Date date = new Date();
//什么事情
Method method = mi.getMethod();
//拿到類對(duì)象 反射
LogAnnotation annotation = method.getAnnotation(LogAnnotation.class);
//通過反射拿到的實(shí)例 調(diào)用方法
String name = annotation.value();
//是否成功
boolean flag = false;
Object proceed = null;
try {
proceed = mi.proceed();
flag=true;
}catch (Exception a){
a.printStackTrace();
}
//這里不做插入數(shù)據(jù)庫(kù)的操作
System.out.println(adminName+"管理員在"+date+"執(zhí)行了"+name+"成功了么?"+flag);
return proceed;
}
}
上述實(shí)現(xiàn)的修改(于Servlet弱耦合),利用Spring的DI特性,實(shí)現(xiàn)對(duì)操作對(duì)象的自動(dòng)注入。
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import java.lang.reflect.Method;
import java.util.Date;
/*
* 這是一個(gè)環(huán)繞通知
* 需要實(shí)現(xiàn)
* */
public class Around implements MethodInterceptor {
//將操作對(duì)象聲明為成員變量
private String adminName;
//設(shè)置公開訪問方法,實(shí)現(xiàn)未來的數(shù)據(jù)注入
public void setAdminName(String adminName) {
this.adminName = adminName;
}
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
Date date = new Date();
//什么事情
Method method = mi.getMethod();
//拿到類對(duì)象 反射
LogAnnotation annotation = method.getAnnotation(LogAnnotation.class);
//通過反射拿到的實(shí)例 調(diào)用方法
String name = annotation.value();
//是否成功
boolean flag = false;
Object proceed = null;
try {
proceed = mi.proceed();
flag=true;
}catch (Exception a){
a.printStackTrace();
}
System.out.println(adminName+"管理員在"+date+"執(zhí)行了"+name+"成功了么?"+flag);
return proceed;
}
}
以上將操作數(shù)據(jù)設(shè)定為成員變量,未來我可以在controller層和業(yè)務(wù)層增加一個(gè)過濾器,實(shí)現(xiàn)對(duì)操作數(shù)據(jù)的注入。
3. 對(duì)通知類使用Spring進(jìn)行管理
<!--配置組裝切面-->
<aop:config proxy-target-class="true">
<!--配置切入點(diǎn)-->
<aop:pointcut id="pc" expression="@annotation(com.baizhi.aop.LogAnnotation)"/>
<!--組裝切面-->
<aop:advisor advice-ref="around" pointcut-ref="pc"/>
</aop:config>
過濾器的開發(fā)
import com.baizhi.aop.Around;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.io.IOException;
public class LogFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
filterChain.doFilter(servletRequest, servletResponse);
HttpServletRequest res = (HttpServletRequest)servletRequest;
HttpSession session = res.getSession();
String admin = (String) session.getAttribute("admin");
ServletContext servletContext = session.getServletContext();
//使用這個(gè)web工具類拿到WebApplicationContext對(duì)象
WebApplicationContext webApplicationContext = WebApplicationContextUtils.getWebApplicationContext(servletContext);
//能通過WebApplicationContext類拿到已經(jīng)初始化的Bean
Around around = (Around) webApplicationContext.getBean("around");
//通過set方法注入數(shù)據(jù)
around.setAdminName(admin);
}
@Override
public void destroy() {
}
}
5.最后在web.xml中進(jìn)行配置
<!--配置過濾器位置-->
<filter>
<filter-name>log</filter-name>
<filter-class>com.baizhi.filter.LogFilter</filter-class>
</filter>
<!--過濾器攔截位置-->
<filter-mapping>
<filter-name>log</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
搞定測(cè)試,這樣做的好處是可以在測(cè)試某個(gè)模塊時(shí),只關(guān)注于String類型的name就行了,不必去考慮web的session的獲取問題和null值問題
看完上述內(nèi)容是否對(duì)您有幫助呢?如果還想對(duì)相關(guān)知識(shí)有進(jìn)一步的了解或閱讀更多相關(guān)文章,請(qǐng)關(guān)注億速云行業(yè)資訊頻道,感謝您對(duì)億速云的支持。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。