怎样创建一个与Servlet-api完全解耦和的管理员后台操作日志监控,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。
目前创新互联已为近千家的企业提供了网站建设、域名、虚拟主机、网站托管运营、企业网站设计、福建网站维护等服务,公司将坚持客户导向、应用为本的策略,正道将秉承"和谐、参与、激情"的文化,与客户和合作伙伴齐心协力一起成长,共同发展。
在日常开发系统后台时,需要针对管理员操作进行监控,如果使用Spring这一套技术体系,使用AOP切面编程+自定义注解不妨是一个好办法,但是在使用这一套体系的同时也会出现一些坑。比如这一套体系是完全依赖于WEB环境,脱离WEB环境就会出现出现ServletRequestAttributes为null的情况。那么如何解决这个问题。
首先快速搭建一个Spring 的运行环境具体jar参照下图:
javax.servlet
servlet-api
2.5
provided
javax.servlet
jstl
1.2
org.springframework
spring-core
4.3.2.RELEASE
org.springframework
spring-context
4.3.2.RELEASE
org.springframework
spring-context-support
4.3.2.RELEASE
org.springframework
spring-beans
4.3.2.RELEASE
org.springframework
spring-aop
4.3.2.RELEASE
org.springframework
spring-expression
4.3.2.RELEASE
org.springframework
spring-aspects
4.3.2.RELEASE
org.springframework
spring-tx
4.3.2.RELEASE
org.springframework
spring-web
4.3.2.RELEASE
org.springframework
spring-jdbc
4.3.2.RELEASE
org.springframework
spring-webmvc
4.3.2.RELEASE
org.mybatis
mybatis
3.2.5
org.mybatis
mybatis-spring
1.3.2
mysql
mysql-connector-java
5.1.38
com.alibaba
druid
1.1.10
com.alibaba
fastjson
1.2.47
commons-fileupload
commons-fileupload
1.3
com.fasterxml.jackson.core
jackson-databind
2.9.5
log4j
log4j
1.2.16
junit
junit
4.12
test
首先对前面的开发步骤做一个简单的讲解,首先开发一个自定义注解:
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
//在方法上使用
@Target({ElementType.METHOD})
//类一旦运行 起作用
@Retention(RetentionPolicy.RUNTIME)
public @interface LogAnnotation {
public String value();
}
开发环绕通知(常规做法,下面做修改)
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;
/*
*
* 这是一个环绕通知
* 需要实现
* */
public class Around implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
/*
* 1.什么人--------
* 2.什么时间 new Date()
* 3.什么事情----方法名
* 4.是否成功-----能
* */
ServletRequestAttributes s = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
//获取HttpRequst对象,于Servlet强耦合
HttpSession session = s.getRequest().getSession();
//拿到存放在Session的数据
String adminName = (String)session.getAttribute("admin");
//时间
Date date = new Date();
//什么事情
Method method = mi.getMethod();
//拿到类对象 反射
LogAnnotation annotation = method.getAnnotation(LogAnnotation.class);
//通过反射拿到的实例 调用方法
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+"执行了"+name+"成功了么?"+flag);
return proceed;
}
}
上述实现的修改(于Servlet弱耦合),利用Spring的DI特性,实现对操作对象的自动注入。
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import java.lang.reflect.Method;
import java.util.Date;
/*
* 这是一个环绕通知
* 需要实现
* */
public class Around implements MethodInterceptor {
//将操作对象声明为成员变量
private String adminName;
//设置公开访问方法,实现未来的数据注入
public void setAdminName(String adminName) {
this.adminName = adminName;
}
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
Date date = new Date();
//什么事情
Method method = mi.getMethod();
//拿到类对象 反射
LogAnnotation annotation = method.getAnnotation(LogAnnotation.class);
//通过反射拿到的实例 调用方法
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+"执行了"+name+"成功了么?"+flag);
return proceed;
}
}
以上将操作数据设定为成员变量,未来我可以在controller层和业务层增加一个过滤器,实现对操作数据的注入。
3. 对通知类使用Spring进行管理
过滤器的开发
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();
//使用这个web工具类拿到WebApplicationContext对象
WebApplicationContext webApplicationContext = WebApplicationContextUtils.getWebApplicationContext(servletContext);
//能通过WebApplicationContext类拿到已经初始化的Bean
Around around = (Around) webApplicationContext.getBean("around");
//通过set方法注入数据
around.setAdminName(admin);
}
@Override
public void destroy() {
}
}
5.最后在web.xml中进行配置
log
com.baizhi.filter.LogFilter
log
/*
搞定测试,这样做的好处是可以在测试某个模块时,只关注于String类型的name就行了,不必去考虑web的session的获取问题和null值问题
看完上述内容是否对您有帮助呢?如果还想对相关知识有进一步的了解或阅读更多相关文章,请关注创新互联行业资讯频道,感谢您对创新互联的支持。