功能需求说明:
用拦截器的方式,拦截以.action结尾的类,同时记录访问的action名称、action的包路径、action后面带的参数、操作者的ID、操作者的姓名、等其他数据。
吐槽点:
1.当我拿到这个需求的时候,直接懵逼了,用日志的方式不是更好么,干嘛要用这个拦截器呢?项目经理脑袋秀逗了啊?当我把这个想法说了之后,得到的是项目经理一句“那种做法太low了”,我想请问low么?应该不low吧,你们觉得呢?
2.好久没有接触SSH,更何况拦截器以前就用得很少,没办法,只有现学现用,好吧,接着就百度,这里是最坑逼的,玛蛋,一搜一大把都是拿登录来做实例,特别让人想吐槽的就是代码和描述什么的都是千篇一律,还都说自己的是原创,wqnmlgb,好意思么?
下面就正式开始,直接上代码,不废话半天:
1.新建一个类来继承AbstractInterceptor,然后重写他的方法:
public class ActionInterceptor extends AbstractInterceptor{
/**
* 数据库表POJO {@link com.mavis.demeter.bean.interceptor.Tracker}的业务逻辑层。
* @since 4.4
*/
private ITrackerService trackerService;
// 提供getter/setter
public ITrackerService getTrackerService() {
return trackerService;
}
public void setTrackerService(ITrackerService trackerService) {
this.trackerService = trackerService;
}
public String intercept(ActionInvocation invocation) throws Exception {
// 在拦截器触发之前,需要把Spring中的bean实例取出来,
// 这样在最后才能把拦截到的数据通过方法保存到数据库中
ServletContext application = ServletActionContext.getServletContext();
WebApplicationContext ctx =
WebApplicationContextUtils.getWebApplicationContext(application);
// 从ApplicationContext中取得定义在Spring中的bean实例
this.trackerService = (ITrackerService)ctx.getBean("TrackerService");
// 获取拦截到的action名称
ActionContext ctxs = invocation.getInvocationContext();
String actionName = ctxs.getName().toString();
Tracker tt = new Tracker();
tt.setActionName(actionName);
// 获取拦截到的action参数
Map<String, String> param = new HashMap<String, String>();
HttpServletRequest request = ServletActionContext.getRequest();
Map<String, String[]> params = request.getParameterMap();
for (String key : params.keySet()) {
String[] values = params.get(key);
for (int i = 0; i < values.length; i++) {
param.put(key, values[i]);
}
}
tt.setActionParameters(param.toString());
// 获取拦截到的action所在的包路径
String actionPakeages = invocation.getAction().toString();
// 截取完整的包名
String[] split = actionPakeages.split("@", 9);
String actionPakeage = split[0].toString();
tt.setActionPakeage(actionPakeage);
// 获取拦截到的组织机构ID
Orgnization orgnization = (Orgnization)ctxs.getSession().get(Constant.SESSION_ORGNIZATION);
if(orgnization != null){
tt.setOrganizationId(orgnization.getOrgnizationId());
}
// 获取拦截到的员工ID
Staff staff = (Staff)ctxs.getSession().get(Constant.SESSION_STAFF);
if(staff != null){
tt.setStaffId(staff.getStaffId());
tt.setStaffName(staff.getShownName());
}
tt.setTrackerTime(new Date());
// 把拦截到的数据保存到数据库中
this.trackerService.save(tt);
return invocation.invoke();
}
}
第二步:配置struts2
<!-- 新增拦截器配置 -->
<package name="myInterceptor" extends="struts-default">
<interceptors>
<!-- 定义权限控制拦截器 -->
<interceptor name="authority" class="com.mavis.hermes.interceptor.ActionInterceptor"/>(name随便取,class就是你拦截器所在的地方,引入进来)
<!-- 定义一个包含权限控制的拦截器栈 -->
<interceptor-stack name="mydefault">
<!-- 默认拦截器 -->
<interceptor-ref name="defaultStack" />
<!-- 自定义拦截器 -->
<interceptor-ref name="authority" />
</interceptor-stack>
</interceptors>
<!-- 定义默认拦截器 -->
<default-interceptor-ref name="mydefault" />
</package>
<!-- 拦截器配置结束 -->
针对第二步想多BB两句:
1.先看看那个登录权限拦截器的实现原理,里面有很清晰的解释什么的默认拦截器,什么是自定义拦截器,他们执行的顺序和各自的运用时机。
2.别一上来就copy代码,先看懂再自己写,代码要自己敲出来才是自己的。
第三步:在struts.xml中,凡是配置了action类的pakeage中,都继承你自己定义的这个拦截器,代码如下:
<package name="proscenium" extends="myInterceptor" namespace="/">
第四步:最重要的东西
// 在拦截器触发之前,需要把Spring中的bean实例取出来,
// 这样在最后才能把拦截到的数据通过方法保存到数据库中
ServletContext application = ServletActionContext.getServletContext();
WebApplicationContext ctx =
WebApplicationContextUtils.getWebApplicationContext(application);
// 从ApplicationContext中取得定义在Spring中的bean实例
this.trackerService = (ITrackerService)ctx.getBean("TrackerService");
就是这个上面几句话,憋我了一天,玛蛋,好不容易想起的,都怪自己,把很多以前的都忘记了,好记性不如烂笔头啊,这也是写这篇博客的初衷吧。
解释一下:
在拦截器中,传统的注入和new都是不可行的,至于具体什么原因,我忘记了,好像跟什么反射机制有关,
第一句:
ServletContext application = ServletActionContext.getServletContext();
利用ServletActionContext获取到ServletContext
第二句:
WebApplicationContext ctx =
WebApplicationContextUtils.getWebApplicationContext(application);
利用WebApplicationContextUtils中的getWebApplicationContext(application)方法,把ServletContext丢进去,用于获取WebApplicationContext
第三句:
通过WebApplicationContext就可以获取到Spring中配置的bean
this.trackerService = (ITrackerService)ctx.getBean("TrackerService");
通过以上步骤,你就可以顺利的把POJO的Service注入到拦截器中了,这样你就可以在拦截器中进行数据的CRUD了。