場景:整個系統的DML操作需要記錄日志
記錄內容:1 操作人 2 操作時間 3 操作類型(登錄 新增 修改 刪除) 4 操作描述 5 詳細請求數據(varchar2()) 6 操作IP ==>日志表
實現:
原來方式:在每個方法的里面編寫記錄日志代碼;
缺點:代碼重復 ,與原有邏輯耦合度高。
AOP: 將日志記錄功能提取到切面中。動態切入到需要日志記錄的方法上即可;
優點: 解耦合,代碼復用。
1) 先寫一個日志切面LogAspect.java;
// 日志切面 @Component//對象由spring管理 @Aspect// 切面注解 public class LogAspect { //定義切入點,切入到添加了LogData注解的方法上 @Pointcut("@annotation(aop.LogData)") public void pointCut(){} /** * 記錄日志的切面方法 * 在該方法中定義統一的日志記錄邏輯 * @param joinPoint */ @Before("pointCut()") public void log(JoinPoint joinPoint){ System.out.println("進入日志Aspect"); } }
2)寫一個日志信息LogData.java;
// 自定義日志注解 @Target({ElementType.METHOD})//指定作用的目標對象(可以添加的位置) @Retention(RetentionPolicy.RUNTIME)//指定在運行期間起作用 public @interface LogData { //定義注解中的屬性 String description() default ""; //日志類型 int logType(); }
3)在控制層方法上寫上注解,加上描述信息,描述日志;
@LogData(logType = 1,description = "學生信息修改") @RequestMapping("/update") public String update(Integer id,ModelMap modelMap){ //查詢用戶信息,展示到頁面 Student student=studentService.findById(id); modelMap.put("student",student); return "update.jsp"; }
要想起作用,還要在springmvc.xml配置文件中配置AOP注解;
<!--配置注解式AOP支持--> <aop:aspectj-autoproxy proxy-target-class="true"/>
二、自定義注解
枚舉:jdk1.5之后存在的一種數據類型。用來定義有限個對象。 enum
語法:
Public enum 類名{
對象定義;
類的成員定義
}
調用: 類名.對象名 獲取枚舉對象。
1)創建一個LogType.java文件來寫枚舉;
/** * 日志枚舉類型 * 枚舉是一個特殊的類 * class 可以創建n個對象 * 枚舉類型的對象是固定的 */ public enum LogType { //創建枚舉對象,對象的個數是有限的,對象與對象之間用逗號隔開 LOGIN(1),DELETE(2),UPDATE(3),INSERT(4); //可以定義任意的方法和屬性,與普通類類似 private final int type; //構造方法 LogType(int type) { this.type = type; } public int getType() { return type; } }
2)日志的注解也需要改變為枚舉類型的,在LogData.java文件中;
/** * 自定義注解 */ @Target({ElementType.METHOD,ElementType.FIELD})//指定作用的目標對象(可以添加的位置) @Retention(RetentionPolicy.RUNTIME) public @interface LogData { //定義注解中的屬性 String description() default ""; //日志類型 1、登錄 2、刪除 3、修改 4、插入 LogType logType(); }
3)調用日志對象,在控制層中;
@LogData(logType = LogType.DELETE,description = "學生信息刪除") @RequestMapping("/delete") public String delete(Integer id){ studentService.delete(id); return "redirect:list"; } @LogData(logType = LogType.UPDATE,description = "學生信息修改") @RequestMapping("/update2") public String update2(Integer id,ModelMap modelMap){ Student student = studentService.selectById(id); modelMap.put("student",student); return "update.jsp"; } @LogData(logType = LogType.INSERT,description = "學生信息新增") @RequestMapping("/insert") public String insert(Student student){ studentService.insert(student); return "redirect:list"; }
4)寫LogAspect.java文件;
@Component//對象由spring管理 @Aspect//切面注解 public class LogAspect { private static final Logger LOGGER = LogManager.getLogger(LogAspect.class); //定義切入點,切入到添加了LogData注解的方法上 @Pointcut("@annotation(aop.LogData)") public void pointCut(){ } /** * 記錄日志的切面方法 * 在該方法中定義統一的日志記錄邏輯 * @param joinPoint */ @Before("pointCut()") public void log(JoinPoint joinPoint){ System.out.println("進入日志Aspect"); //獲取到方法簽名 MethodSignature signature= (MethodSignature) joinPoint.getSignature(); //獲取到連接點方法對象 Method method=signature.getMethod(); //獲取方法上面特定的注解 LogData annotation=method.getAnnotation(LogData.class); LogType logType=annotation.logType(); String description=annotation.description(); LOGGER.info("獲取到注解內容:logType="+logType.getType() +",description:"+description); //aop中獲取request ServletRequestAttributes requestAttributes= (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); HttpServletRequest request=requestAttributes.getRequest(); HttpSession session=request.getSession(); //獲取操作人 Student student= (Student) session.getAttribute("student"); //獲取請求數據 Map<String,String[]> parameterMap=request.getParameterMap(); //將對象轉換成json字符串==>存儲到請求數據字段中 //jackSon json字符串操作 ObjectMapper objectMapper=new ObjectMapper(); try { String s=objectMapper.writeValueAsString(parameterMap); LOGGER.info("請求數據:"+s); } catch (JsonProcessingException e) { e.printStackTrace(); } //todo 將日志信息保存到數據庫 LogController service mapper jsp } }
三、枚舉
枚舉可用於switch語句中
public class T { public static void main(String[] args) { test(LogType.DELETE); //獲取到枚舉對象 LogType logType = LogType.DELETE; //獲取到對象之后,與普通對象操作方式一樣 int type = logType.getType(); } /** * 枚舉類型在switch中的使用 * @param logType */ public static void test(LogType logType) { switch (logType){ case LOGIN: System.out.println("登錄操作");break; case DELETE: System.out.println("刪除操作");break; case INSERT: System.out.println("插入操作");break; case UPDATE: System.out.println("修改操作");break; } } }
四、枚舉還是實現單例模式的最佳方式