Structs2拦截器和注解实现自动记录日志

先看效果,其他程序员使用的时候,如下,findAllCountry被调用时,调用时间、调用人、方法名、方法描述、testValue、testValue2的值都将被存入数据库中。

 

 

public class TestAction extends ActionSupport {
	private String testValue = "hellow";
	private String testValue2 = "hellow2";	

        @IDBLog(desc="分页查询数据", params="testValue;testValue2;")
	public void findAllCountry(){
	System.out.println("in CountryAction :findAllCountry");
        //TODO:	    
	}
   
       //注解中要记录该参数的值,必须提供get方法
       	public String getTestValue() {
		return testValue;
	}

        public String getTestValue2() {
		return testValue2;
	}
}
 

1:先写一个DB日志实体:

/**
 * 
 * 数据库日志记录实体             <p>
 * @author zhuoyueping @date 2012-5-8 <br>
 * @version    <br>
 */
public class DBLog extends Core {
	/** 操作的用户 **/
	protected String remote_user;
	
	/** 操作的时间 **/
	protected Date operate_date;
	
	/** 操作的action **/
	protected String operation;

	/** 操作的action的描述 **/
	protected String oper_desc;
	
	
	/** 操作的action的成员变量 **/
	protected String oper_params;
       
         //getter 、 setter
}
 

2:注解IDBLog,指定了该注解的action方法:

/**
 * 定义注入Action的log远程业务接口<p>
 * @author zhuoyueping @date 2012-05-7<br>
 * @version 1.0<br>
 */
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface IDBLog {
	/**
	 * 指定action方法的描述名称 如:查询用户
	 * @return
	 */
	public abstract String desc();
	
	/**
	 * 指定action方法的成员参数名称,指定的参数应该覆盖toString方法,多个成员参数用;分隔
	 * @return
	 */
	public abstract String params() default "";
}

 

3:structs2的拦截器代码,CommonBaseInterceptor是公司内部对拦截器的简单封装类

/**
 * 以拦截器的方式动态注入action方法,记录用户、时间、操作的action
 * @author zhuoyueping @date 2012-04-08<br>
 * @version 1.0<br>
 */
public class DBLogInteceptor extends CommonBaseInterceptor {

	/**
	 * 系统默认生成版本号
	 */
	private static final long serialVersionUID = 1L;
	private IDBLogService dbLogService;
	/**
	 * 实现拦截功能<p>
	 */
	public String intercept(ActionInvocation actionInvocation) throws Exception {
		Object action = actionInvocation.getAction();
		java.lang.reflect.Method[] methods = action.getClass().getDeclaredMethods();
		for (Method method : methods) {
			boolean hasAnnotation = method.isAnnotationPresent(IDBLog.class);
			if (hasAnnotation) {  
				IDBLog avicLog = method.getAnnotation(IDBLog.class);
						
				//上下文
				 ActionContext actionContext = actionInvocation.getInvocationContext();     
				 HttpServletRequest request= (HttpServletRequest) actionContext.get(StrutsStatics.HTTP_REQUEST);
				
				 //登陆用户
				 String uid =request.getRemoteUser();
				
				 //操作时间
				 Date currentDate = new Date();
				 SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); 
			     String date = sdf.format(currentDate);
				 
				 //操作方法:
				 String operation = action.getClass().getName()+"."+method.getName();
				
				 //操作的方法描述
				 String desc = avicLog.desc();
				 
				 //参数
				 String params = avicLog.params();
				 List<String> fieldNames = splitParams(params);
				 StringBuffer sb = new StringBuffer();
				 if(fieldNames!=null){
					 for(String fieldName:fieldNames){
						 //调用getXX方法
						 String methodName = convertMethodName(fieldName);
						 Method getMethod=action.getClass().getMethod(methodName, new Class[]{}); 
						 Object fieldValue=getMethod.invoke(action, new Object[]{}); 
						 String value = formatFidlParam(fieldName,fieldValue.toString());
						 sb.append(value);
					 }
				 }
				 
				 
				 DBLog log = new DBLog();
				 log.setRemote_user(uid);
				 log.setOperate_date(currentDate);
				 log.setOperation(operation);
				 log.setOper_desc(desc);
				 log.setOper_params(sb.toString());
				 
				 System.out.println("************************in AvicDBLogInteceptor\n      "+log   );

				 
				 //取得spring中管理的bean,取得service执行save保存数据
		          ServletContext sc=request.getSession().getServletContext();  
		          ApplicationContext ac = WebApplicationContextUtils.getRequiredWebApplicationContext(sc);  
		          dbLogService = (IDBLogService) ac.getBean("com.system.common.dbLogService");
				//写数据库日志
				dbLogService.save(log);
				 System.out.println("******************************************写日志完成");
			
			}
		}
		return actionInvocation.invoke();
	}
	//根据传入的参数名称,
	private List<String> splitParams(String params){
		System.out.println("input:"+params);
		List<String>  lst = null;
		if(params==null||params.trim().equals("")){
			return null;
		}
		lst = new ArrayList<String>();
		StringTokenizer st = new StringTokenizer(params,";");
		while(st.hasMoreTokens()){
			String paramName = st.nextToken().trim();
			lst.add(paramName);
		}
		return lst;
	}
	
	//根据成员变量名,改第一个字母大写后,再增加get前缀,转为getXxxx方法名。
	private String convertMethodName(String fieldName){
		String fisrLetter = fieldName.substring(0, 1).toUpperCase();
		String methodName = "get"+fisrLetter+fieldName.substring(1);
		System.out.println(methodName);
		return methodName;
	}
	
	//格式化参数名和参数值输出格式
	private String formatFidlParam(String fieldName,String fiedldValue){
		String rtnValue = null;
		rtnValue = "["+fieldName+" = {"+fiedldValue+"}]";
		return rtnValue;
	}
	
}

 

3:配置拦截器:

<package name="common" extends="struts-default">
		<interceptors>
			<interceptor name="dbLogInteceptor" class="com.framework.web.struts2.interceptor.DBLogInteceptor"/>
			<interceptor-stack name="commonsStack">
				<interceptor-ref name="exception"/>
				<interceptor-ref name="prepare"/>
				<interceptor-ref name="params"/>
				<interceptor-ref name="validation"/>
				<interceptor-ref name="workflow"/>
			</interceptor-stack>
			<interceptor-stack name="uploadStack">
				<interceptor-ref name="fileUpload">
					<param name="allowedTypes">image/bmp,image/png,image/gif,image/jpeg,image/jpg</param>
					<param name="maximumSize">50485760</param>
				</interceptor-ref>
				<interceptor-ref name="commonsStack"/>
			</interceptor-stack>
			<interceptor-stack name="annotation">
				<interceptor-ref name="uploadStack"/>
				<interceptor-ref name="dbLogInteceptor"/>
			</interceptor-stack>
		</interceptors>
		<!-- *******************默认拦截器************** -->
		<default-interceptor-ref name="annotation"/>
	</package>
 

4:最后一步,在配置action时,这个action所在的xml文件的package应该继承上面的包,这些action才能被拦截。

structs2的配置文件的包继承是多继承的,extends可以多个,如下,继承了json-default和common。

common中定义的拦截器,该配置中的userList这个action中就可以通过注解使用拦截器了。

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.org/dtds/struts-2.0.dtd">
    <struts>
	<package name="avic-system-json" extends="json-default,common">
	
	<!-- ************************************************配置自定义ACTION类************************************************* -->

	<action name="userList" class="com.system.example.page.UserListAction" method="getPageList">
		<result name="success" type="json"></result>
	</action>
	</package>
	
</struts>

你可能感兴趣的:(struct)