1. 实现用户操作的记录
获取用户在系统上的相关操作,并将其保存到数据库中。
这里提供两种思路:
-
AOP :使用AOP写切面,设置切点
logPointCut()
,并使用注解方式@annotation
实现注入。然后,在切点处可以通过定义
@Before("logPointCut()")
和@After("logPointCut()")
来具体设定操作。 -
拦截器:拦截器的思路更加简单,而且更加适配struts2项目,也是我所采用的。
具体实现上,我依然采用了action层、service层和dao层的设计模式,同时在spring配置文件中进行注入。在spring配置完毕后,需要注意的是在action层和service层都需要定义新的private
变量来声明所设置的接口为一个javabean,同时完成set和get方法,否则会报错。
主要实现直接放在了action层,代码如下:
import *********
@SuppressWarnings("serial")
public class AuditLogInterceptor extends MethodFilterInterceptor {
/** 解释一下:MethodFilterInterceptor是一个已经实现的过滤器类,可以直接继承 **/
/** 定义一下需要用的的service,并声明get和set方法 **/
/** 一个例子,根据自己的设置来写 **/
private IOperationRecordService operationRecordService;
public IOperationRecordService getOperationRecordService() {
return operationRecordService;
}
public void setOperationRecordService(IOperationRecordService operationRecordService) {
this.operationRecordService = operationRecordService;
}
@Override
protected String doIntercept(ActionInvocation actioninvocation) throws Exception {
AuditLog auditLog = new AuditLog();
Timestamp nowDate = new Timestamp(System.currentTimeMillis());
String result = actioninvocation.invoke();// 递归调用拦截器
String id = UUID.randomUUID().toString();
auditLog.setId(id);
/*时间相关*/
auditLog.setCreateTime(nowDate);//设置创建时间
/** 获取网络请求 **/
HttpServletRequest request = ServletActionContext.getRequest();
/** 获取用户信息 **/
User userInfo = (User)request.getSession().getAttribute("userInfo");
String refer = request.getHeader("Referer");
String userAgent = request.getHeader("User-Agent");
String params = getParamString(request.getParameterMap());
/** 只有注册用户会有信息,如果没有注册,则将名字设置为unRegedit **/
if(userInfo == null) {
auditLog.setUserName("unRegedit");
} else {
auditLog.setUserName(userInfo.getUid());
}
auditLog.setReference(refer);
auditLog.setUserAgent(userAgent);
auditLog.setParams(params);
String methodName = actioninvocation.getProxy().getMethod();
if (methodName.length() > 0) {
Object action = actioninvocation.getAction();
Class clazz = action.getClass();
/*Action 类名*/
auditLog.setClazz(clazz.getName());
Method method = action.getClass().getMethod(methodName, null);
/*方法名称*/
auditLog.setMethod(methodName);
String ip = ServletActionContext.getRequest().getRemoteAddr();
auditLog.setIp(ip);// 记录登录的IP
userService.insertOperationRecord(auditLog);
}
return result; // 跳转
}
/** param拼接 **/
private String getParamString(Map<String, String[]> map) {
StringBuilder sb = new StringBuilder();
for (Entry<String, String[]> e : map.entrySet()) {
sb.append(e.getKey()).append("=");
String[] value = e.getValue();
if (value != null && value.length == 1) {
sb.append(value[0]).append("&");
} else {
sb.append(Arrays.toString(value)).append("&");
}
}
return sb.toString();
}
/**
* 通过HttpServletRequest返回IP地址
* @param request HttpServletRequest
* @return ip String
* @throws Exception
*/
public String getIpAddr(HttpServletRequest request) throws Exception {
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();
}
return ip;
}
/**
* 通过IP地址获取MAC地址
* @param ip String,127.0.0.1格式
* @return mac String
* @throws Exception
*/
public String getMACAddress(String ip) throws Exception {
String line = "";
String macAddress = "";
final String MAC_ADDRESS_PREFIX = "MAC Address = ";
final String LOOPBACK_ADDRESS = "127.0.0.1";
//如果为127.0.0.1,则获取本地MAC地址。
if (LOOPBACK_ADDRESS.equals(ip)) {
InetAddress inetAddress = InetAddress.getLocalHost();
//貌似此方法需要JDK1.6。
byte[] mac = NetworkInterface.getByInetAddress(inetAddress).getHardwareAddress();
//下面代码是把mac地址拼装成String
StringBuilder sb = new StringBuilder();
for (int i = 0; i < mac.length; i++) {
if (i != 0) {
sb.append("-");
}
//mac[i] & 0xFF 是为了把byte转化为正整数
String s = Integer.toHexString(mac[i] & 0xFF);
sb.append(s.length() == 1 ? 0 + s : s);
}
//把字符串所有小写字母改为大写成为正规的mac地址并返回
macAddress = sb.toString().trim().toUpperCase();
return macAddress;
}
//获取非本地IP的MAC地址
try {
Process p = Runtime.getRuntime().exec("nbtstat -A " + ip);
InputStreamReader isr = new InputStreamReader(p.getInputStream());
BufferedReader br = new BufferedReader(isr);
while ((line = br.readLine()) != null) {
if (line != null) {
int index = line.indexOf(MAC_ADDRESS_PREFIX);
if (index != -1) {
macAddress = line.substring(index + MAC_ADDRESS_PREFIX.length()).trim().toUpperCase();
}
}
}
br.close();
} catch (IOException e) {
e.printStackTrace(System.out);
}
return macAddress;
}
}
2. 使用spring配置文件实现注入
在spring.xml配置文件中要将相关的action、service、dao全部注入
其中,action层注入service,service层注入dao,dao层注入sql。要将所有用到的全部注入,否则报错!
3. 前端传参
一开始使用的是implements ModelDriven<>
的方法传参,发现参数传不过来,因此放弃了这种方式,采用了笨办法,即在action中写明需要的变量名称(注意名称要唯一)!
4. 数据库表
数据库表字段长度一定要长,否则在insert时会报错,catch住错误后一定要打印这个错误,否则很难排查。
5. list中remove的问题
这个坑排了很久!
string[]
转list<string>
时,一定不要用Arrays.asList
!!!
否则,list
的remove
功能无法使用。
直接使用循环+add传值即可。