1. 程式人生 > >Java自定義註解 和 springMVC攔截器 配合使用記錄系統操作日誌的案例

Java自定義註解 和 springMVC攔截器 配合使用記錄系統操作日誌的案例

自定義註解的用法, 好多人不知道, 在這裡, 程式碼的註釋中, 我已經詳細的介紹了,

另外就是很多人不知道自定義註解如何使用, 這裡配合springMVC攔截器, 做一個非常實用的案例.

案例: 記錄系統操作的日誌

首先是定義註解:

package cn.wxy.ssm.myAnnotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * @author wxy E-mail:[email protected]
 * @date 建立時間:2017年5月25日 下午5:05:22
 * @version 1.0版本
 * @company xxx科技公司
 * @description 描述: 自定義註解: 這個註解是用在某一個成員方法上, 標識這個方法具體是增刪改查具體什麼內容
 * */
@Target(ElementType.METHOD) //表明該註解對成員方法起作用
@Retention(RetentionPolicy.RUNTIME) //在編譯以後仍然起作用
@Documented //支援JavaDoc文件註釋
public @interface record {
	String actionType() default "預設動作型別"; //一般有增加, 刪除, 修改, 查詢
	String businessLogic() default "預設業務邏輯";
}

然後, 在一個普通的ssm框架中來只用它, 新建一個web層的controller類:

package cn.wxy.ssm.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import cn.wxy.ssm.myAnnotation.record;

/**
 * @author wxy E-mail:[email protected]
 * @date 建立時間:2017年5月25日 下午8:19:17
 * @version 1.0版本
 * @company xxx科技公司
 * @description 描述: 測試自定義註解的controller層類 
 * */
@Controller
public class TestAnnotationController extends BaseController {
	
	@RequestMapping(value = "wxy/testAnnotation.action")
	@record(actionType = "測試, 沒有做任何後臺增刪改",businessLogic="測試好不好使")
	public String test(){
		System.out.println("執行完這行程式碼, 執行攔截器");
		return "success";
	}
	
}

此時, 我們需要在springmvc的xml配置檔案中, 來構建攔截器, 攔截上面的controller

	  <!-- 配置攔截器, -->
	<mvc:interceptors>
		<mvc:interceptor>
			<mvc:mapping path="/**"/> <!-- 具體匹配原則可以百度
										/**的意思是所有資料夾及裡面的子資料夾
										/*是所有資料夾,不含子資料夾
										/是web專案的根目錄
									   -->
			<bean class="cn.wxy.ssm.interceptor.OperationLogInteceptor"></bean>
		</mvc:interceptor>
	</mvc:interceptors>

建立上面配置的攔截器, 來繼承HandlerInteceptorAdaptor 或者實現 HandlerInteceptor 介面. 個人比較推薦前者.

package cn.wxy.ssm.interceptor;

import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.UUID;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import cn.wxy.ssm.myAnnotation.record;

/**
 * @author wxy E-mail:[email protected]
 * @date 建立時間:2017年5月25日 下午3:49:55
 * @version 1.0版本
 * @company xxx科技公司
 * @description 描述: 繼承HandlerInterceptorAdapter, 重寫裡面的方法
 * */
public class OperationLogInteceptor extends HandlerInterceptorAdapter {

	/* (non-Javadoc)
	 * @see org.springframework.web.servlet.handler.HandlerInterceptorAdapter#preHandle(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, java.lang.Object)
	 * 預處理, 進行程式碼編寫, 安全控制等.
	 */
	@Override
	public boolean preHandle(HttpServletRequest request,
			HttpServletResponse response, Object handler) throws Exception {
		System.out.println("進入方法之前進行攔截");
		return super.preHandle(request, response, handler);
	}

	/* (non-Javadoc)
	 * @see org.springframework.web.servlet.handler.HandlerInterceptorAdapter#postHandle(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, java.lang.Object, org.springframework.web.servlet.ModelAndView)
	 * 返回處理, 這裡有機會修改ModelAndView 
	 */
	@Override
	public void postHandle(HttpServletRequest request,
			HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
		//wxy筆記: 現在我要在這裡做的事情是: 新增日誌, 記錄進行的操作. 日誌的內容來源於我在
		//		   操作的方法中新增的 自定義註解, 因為自定義註解中有引數, 這些引數記錄的是操作的主要內容
		//		   我只要在這裡用反射將方法上自定義註解的內容拿出來, 新增到日誌裡面就行了/
		System.out.println("攔截器執行.......");
		HandlerMethod hm =  (HandlerMethod) handler;//將其強轉過來
		record record = hm.getMethodAnnotation(record.class);//拿到裡面的自定義註解物件//通過反射
		if (record != null) {
			//Map<String, String[]> params = request.getParameterMap();
			//對params這個map集合的鍵進行遍歷
			//Set<String> paramsKey = params.keySet();
			//Iterator<String> it = paramsKey.iterator();
			/*while (it.hasNext()) {
				String key = (String) it.next();
			}*/	
		String actionType = record.actionType();//拿到自定義註解中的欄位值 動作型別
			String businessLogic = record.businessLogic();//拿到自定義註解中的欄位值 業務邏輯
			String str = "動作型別是:" + actionType + "  業務邏輯是:" + businessLogic;
			//執行日誌記錄
			saveLog(str);
		}
		super.postHandle(request, response, handler, modelAndView);
	}

	/**
	 * 進行日誌記錄, 日誌一般分兩種:一種是資料庫(系統操作日誌),一種是寫入磁碟(系統執行日誌 log4j這類)
	 * 這裡我們這是屬於系統操作日誌, 需要存入資料庫, 但是為了演示, 這裡只打印到控制檯.
	 * @param str
	 */
	private void saveLog(String str) {
		try {
			System.out.println(str);
			//真正開發中, 這裡傳遞日誌到資料庫, 操作失敗在catch中新增系統執行日誌
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/* (non-Javadoc)
	 * @see org.springframework.web.servlet.handler.HandlerInterceptorAdapter#afterCompletion(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, java.lang.Object, java.lang.Exception)
	 * 後處理, 可以根據ex是否為null判斷是否發生了異常,進行日誌記錄。 
	 */
	@Override
	public void afterCompletion(HttpServletRequest request,
			HttpServletResponse response, Object handler, Exception ex)
			throws Exception {
		
		super.afterCompletion(request, response, handler, ex);
	}

	/* (non-Javadoc)
	 * 
	 * @see org.springframework.web.servlet.handler.HandlerInterceptorAdapter#afterConcurrentHandlingStarted(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, java.lang.Object)
	 * 這個這裡不做研究暫時. 
	 */
	@Override
	public void afterConcurrentHandlingStarted(HttpServletRequest request,
			HttpServletResponse response, Object handler) throws Exception {
		// TODO Auto-generated method stub
		super.afterConcurrentHandlingStarted(request, response, handler);
	}
	
	
}

最後我們來執行測試: 直接訪問即可:

http://localhost:8080/wxySSM/wxy/testAnnotation.action  檢視你們的Tomcat是否是8080, 另外, wxySSM 是專案名.

最後我把我建立的這個專案目錄結構截圖給大家參考, 以便更清晰學習.