在@Value注解內(nèi)使用SPEL自定義函數(shù)方式
@Value注解內(nèi)使用SPEL自定義函數(shù)
@Value("#{T(com.cheetah.provider.utils.StringUtil).lower('${cluster.vendor.type}')}")
其中,${cluster.vendor.type}取的application.properties中的配置,com.cheetah.provider.utils.StringUtil#lower是用戶自定義函數(shù),
T()運算符的結果是一Class對象,它的真正價值在于它能夠訪問目標類型的靜態(tài)方法和常量
自定義注解支持SpEL表達式
利用AOP生成用戶操作日志
1.定義日志注解
@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface SysLog { ? ? //普通的操作說明 ? ? String value() default ""; ? ?? ? ? //spel表達式的操作說明 ? ? String spelValue() default ""; }
2.定義spel解析工具類
public class SpelUtil { ? ? /** ? ? ?* 用于SpEL表達式解析. ? ? ?*/ ? ? private static SpelExpressionParser parser = new SpelExpressionParser(); ? ? /** ? ? ?* 用于獲取方法參數(shù)定義名字. ? ? ?*/ ? ? private static DefaultParameterNameDiscoverer nameDiscoverer = new DefaultParameterNameDiscoverer(); ? ? public static String generateKeyBySpEL(String spELString, ProceedingJoinPoint joinPoint) { ? ? ? ? // 通過joinPoint獲取被注解方法 ? ? ? ? MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature(); ? ? ? ? Method method = methodSignature.getMethod(); ? ? ? ? // 使用spring的DefaultParameterNameDiscoverer獲取方法形參名數(shù)組 ? ? ? ? String[] paramNames = nameDiscoverer.getParameterNames(method); ? ? ? ? // 解析過后的Spring表達式對象 ? ? ? ? Expression expression = parser.parseExpression(spELString); ? ? ? ? // spring的表達式上下文對象 ? ? ? ? EvaluationContext context = new StandardEvaluationContext(); ? ? ? ? // 通過joinPoint獲取被注解方法的形參 ? ? ? ? Object[] args = joinPoint.getArgs(); ? ? ? ? // 給上下文賦值 ? ? ? ? for (int i = 0; i < args.length; i++) { ? ? ? ? ? ? context.setVariable(paramNames[i], args[i]); ? ? ? ? } ? ? ? ? // 表達式從上下文中計算出實際參數(shù)值 ? ? ? ? /*如: ? ? ? ? ? ? @annotation(key="#student.name") ? ? ? ? ? ? ?method(Student student) ? ? ? ? ? ? ?那么就可以解析出方法形參的某屬性值,return “xiaoming”; ? ? ? ? ? */ ? ? ? ? return expression.getValue(context).toString(); ? ? } }
3.定義切面類
@Aspect @Component public class SysLogAspect { ? ? @Autowired ? ? private LogService logService; ? ? @Autowired ? ? private HttpServletRequest request; ? ? @Pointcut("@annotation(com.ztri.common.annotation.SysLog)") ? ? public void logPointCut() { ? ? } ? ? @Around("logPointCut()") ? ? public Object around(ProceedingJoinPoint point) throws Throwable { ? ? ? ? long beginTime = System.currentTimeMillis(); ? ? ? ? //執(zhí)行方法 ? ? ? ? Object result = point.proceed(); ? ? ? ? //執(zhí)行時長(毫秒) ? ? ? ? long time = System.currentTimeMillis() - beginTime; ? ? ? ? //保存日志 ? ? ? ? saveSysLog(point, time); ? ? ? ? return result; ? ? } ? ? private void saveSysLog(ProceedingJoinPoint joinPoint, long time) { ? ? ? ? MethodSignature signature = (MethodSignature) joinPoint.getSignature(); ? ? ? ? Method method = signature.getMethod(); ? ? ? ? Log sysLog = new Log(); ? ? ? ? sysLog.setTime(time); ? ? ? ? SysLog syslog = method.getAnnotation(SysLog.class); ? ? ? ? if (syslog != null) { ? ? ? ? ? ? //注解上的描述 ? ? ? ? ? ? if (StrUtil.isNotBlank(syslog.value())) { ? ? ? ? ? ? ? ? sysLog.setOperation(syslog.value()); ? ? ? ? ? ? } ? ? ? ? ? ? if (StrUtil.isNotBlank(syslog.spelValue())) { ? ? ? ? ? ? ? ? String spelValue = SpelUtil.generateKeyBySpEL(syslog.spelValue(), joinPoint); ? ? ? ? ? ? ? ? sysLog.setOperation(spelValue); ? ? ? ? ? ? } ? ? ? ? } ? ? ? ? //請求的方法名 ? ? ? ? String className = joinPoint.getTarget().getClass().getName(); ? ? ? ? String methodName = signature.getName(); ? ? ? ? sysLog.setMethod(className + "." + methodName + "()"); ? ? ? ? //請求的參數(shù) ? ? ? ? Object[] args = joinPoint.getArgs(); ? ? ? ? try { ? ? ? ? ? ? String params = JSONUtil.toJsonStr(args); ? ? ? ? ? ? sysLog.setParams(params); ? ? ? ? } catch (Exception e) { ? ? ? ? } ? ? ? ? //設置IP地址 ? ? ? ? sysLog.setIp(ServletUtil.getClientIP(request)); ? ? ? ? UserAgent ua = UserAgentUtil.parse(request.getHeader("User-Agent")); ? ? ? ? sysLog.setBrowser(ua.getBrowser().toString()); ? ? ? ? //保存系統(tǒng)日志 ? ? ? ? logService.create(sysLog); ? ? } }
4.方法上使用日志注解
? ? @ApiOperation("高級搜索(包含點擊1.熱門列表 2.更多跳轉(zhuǎn)頁面)") ? ? @PostMapping("searchData") ? ? @SysLog(spelValue = "'高級搜索' + #searchVo.keyWord") ? ? public ResponseEntity<Object> searchData(@RequestBody SearchVo searchVo) throws IOException { ? ? ? ? SearchDto searchDto = searchService.searchData(searchVo); ? ? ? ? return new ResponseEntity<>(searchDto, HttpStatus.OK); ? ? } ? ? @ApiOperation("登錄授權") ? ? @PostMapping("/login") ? ? @SysLog("用戶登錄") ? ? public ResponseEntity<Object> login(@Validated(User.Create.class) @RequestBody LoginUser loginUser) { ? ? ? ? return ResponseEntity.ok(authInfo); ? ? }
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
jdk-logging?log4j?logback日志系統(tǒng)實現(xiàn)機制原理介紹
這篇文章主要介紹了jdk-logging、log4j、logback日志介紹以及三個日志系統(tǒng)的實現(xiàn)機制,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-03-03SpringMVC接收java.util.Date類型數(shù)據(jù)的2種方式小結
這篇文章主要介紹了使用SpringMVC接收java.util.Date類型數(shù)據(jù)的2種方法,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-08-08調(diào)用Process.waitfor導致的進程掛起問題及解決
這篇文章主要介紹了調(diào)用Process.waitfor導致的進程掛起問題及解決,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-12-12解決response.setHeader設置下載文件名無效的問題
這篇文章主要介紹了解決response.setHeader設置下載文件名無效的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-01-01