- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章springAop实现权限管理数据校验操作日志的场景分析由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
作为一个写java的使用最多的轻量级框架莫过于spring,不管是老项目用到的springmvc,还是现在流行的springboot,都离不开spring的一些操作,我在面试的时候问的最多的spring的问题就是我们在平常的项目中使用spring最多的有哪几个点 在我看来无非就两个 。
spring是一个很强大的轻量级框架,功能远不止这两点,但是我们用的最多的就是这两点.
想我们常用的 @Controller @Service @Component 等等都是将我们的bean交给spring管理,我们在获取bean的时候就直接通过 @Resource 就可以获取,当然@Resource 不是spring的,@Autowired 才是spring的,这样我们可以很方便的管理我们的各种bean,使用起来也很方便,不用到处new 。
这个应该是spring面试最常问道的问题了,我面试的时候一般不直接问,我会说一个场景,如果面试者使用过aop立马就可以回答出来。 有这么一个场景,一个系统已经开发完成了,而且已经上线运行了一段时间,很稳定了,现在要加一个功能,就是想收集用户的操作日志,操作日志要比较细致,比如 某某人,在哪个时间点,操作了哪个模块,请求的参数是什么样子的,操作结果如何,等一些比较细致的操作。很多面试者第一时间想到的就是使用过滤器,试想一下,过滤器真的能做到记录这么细致的内容吗?有的可能会想到,我们定义一个公共的方法,所有需要记录日志的地方都去调用这个方法,等等。其实这些都不好,最好的当然是使用aop,使用aop侵入性最小,系统已经稳定运行了,不能去动之前的代码,我们做个aop就可以了,对原来的代码几乎0侵入,对系统影响最小。 那aop实现的方式有哪几种呢?aop实现的步骤又是怎么样的呢?aop还能做些什么呢?这些问题如果在实际项目中使用过,一定能回答出来,如果没有使用过,估计有点难回答,这些都是项目框架的东西,很多公司的项目这一块已经封装好了,很多人直接一直在用,但是没有去查看源码,就不知道具体的实现,实现起来其实也很简单.
接下来我们就以一个小例子来说明下如何使用aop aop总结起来最常用的就两种方式 1、采用声明的方式来实现(基于XML) 胡子眉毛一把抓,哈哈 2、是采用注解的方式来实现(基于AspectJ)精准定位 我习惯使用注解的方式,更加灵活,使用起来也方便,接下来就以注解的方式来讲下如何使用aop来做权限校验,数据校验,操作日志记录 。
我们使用springaop,首先要将定义的类交给spring管理,然后使用aspectj 定义切面,我们要额外引入 aspectj 。
1
2
3
4
5
|
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>
1.8
.
9
</version>
</dependency>
|
1
2
3
4
5
|
@Component
@Aspect
public
class
OperationInterceptor {
}
|
定义切点 。
我们采用注解的方式,那么我们首先要申明一个注解 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
@Target
({ElementType.METHOD, ElementType.TYPE})
@Retention
(RetentionPolicy.RUNTIME)
@Documented
@Mapping
public
@interface
GlobalInterceptor {
/**
* 权限编码
*/
PermissionCodeEnum permissionCode();
/**
* 操作模块
*
* @return
*/
OperModuleEnum opObject()
default
OperModuleEnum.NO_OBJECT;
/**
* 操作描述
*
* @return
*/
String opDescription()
default
""
;
}
|
然后在我们的切面中定义切点 。
1
2
3
4
5
6
7
8
9
|
@Component
@Aspect
public
class
OperationInterceptor {
@Pointcut
(
"@annotation(com.xx.xx.GlobalInterceptor)"
)
private
void
opMethods() {
}
}
|
定义通知类型 。
我们要输入还想要输出,那么我们就要将目标方法包围,所以使用around 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
@Component
@Aspect
public
class
OperationInterceptor {
@Pointcut
(
"@annotation(com.xx.xx.GlobalInterceptor)"
)
private
void
opMethods() {
}
@Around
(
"opMethods()"
)
public
Object doMethod(ProceedingJoinPoint point)
throws
BusinessException {
//TODO 业务代码
return
null
;
}
}
|
这样一个完整的切面就定义好了 。
在我们的controller中直接使用,我们拿一个登录来讲 。
1
2
3
4
5
|
@RequestMapping
(
"/login"
)
@GlobalInterceptor
(permissionCode = PermissionCodeEnum.NO_PERMISSION, opObject = OperModuleEnum.OBJECT_LOGIN, opDescription =
"登录账号:#{#param1}"
)
public
AjaxResponseVO login(HttpSession session,
@VerifyParam
(required =
true
) String account,
@VerifyParam
(required =
true
) String password,
@VerifyParam
(required =
true
) String checkCode){
}
|
我们要传入 切面注解需要的参数 permissionCode 权限编码,我这里定义的是一个枚举,类型自己根据实际情况定义 opObject 操作模块 opDescription 操作描述,这里简单的组织下描述文字,参数的地方使用占位符,到时候根据占位符index获取具体的参数 。
这样我们在切面中就可以拿到这些参数 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
|
@Component
@Aspect
public
class
OperationInterceptor {
@Pointcut
(
"@annotation(com.xx.xx.GlobalInterceptor)"
)
private
void
opMethods() {
}
@Around
(
"opMethods()"
)
public
Object doMethod(ProceedingJoinPoint point)
throws
BusinessException {
Object obj =
null
;
try
{
/**
* 获取登录信息
*/
SessionUserDto sessionUserDto = getSessionUser();
/**
* 获取目标切点
*/
Object target = point.getTarget();
/**
* 获取参数
*/
Object[] arguments = point.getArgs();
/**
* 获取方法名
*/
String method = point.getSignature().getName();
/**
* 获取参数类型
*/
Class<?>[] parameterTypes = ((MethodSignature) point.getSignature()).getMethod().getParameterTypes();
/**
* 获取具体的方法
*/
Method m = target.getClass().getMethod(method, parameterTypes);
GlobalInterceptor interceptor = m.getAnnotation(GlobalInterceptor.
class
);
if
(
null
== interceptor) {
return
obj;
}
/**
* 校验权限
*/
if
(sessionUserDto !=
null
) {
validatePermission(interceptor, sessionUserDto);
}
/**
* 校验参数
*/
validateParams(interceptor, m, arguments);
/**
* 获取描述信息,这里在执行方法之前组织好描述信息,当参数是传值引用时 执行具体方法后,会改变原始参数对象值
*/
String description = getDescription(arguments, interceptor.opDescription());
/**
* 执行操作
*/
obj = point.proceed();
/**
* 记录日志
*/
wirteLog(obj, description, interceptor, sessionUserDto);
}
catch
(BusinessException e) {
logger.error(
"全局拦截器异常"
, e);
throw
e;
}
catch
(Exception e) {
logger.error(
"全局拦截器异常"
, e);
}
catch
(Throwable e) {
logger.error(
"全局拦截器异常"
, e);
}
return
obj;
}
}
|
这里只贴出了部分代码,完整的代码可以到这里获取 。
总结 。
回到最开始的问题,这样我们实现了一个对原有系统侵入极小,然后又实现了操作日志的解决方案。 我们使用spring的aop非常简单,我们使用aop结合反射,可以做很多事情。aop对代码的侵入非常小,不需要动原来的代码,只需要在原有的方法上加一个注解就可以完成对系统的改造,加权限,加日志 等等一系列操作.
到此这篇关于springAop实现权限管理数据校验操作日志的场景分析的文章就介绍到这了,更多相关springAop权限管理数据校验内容请搜索我以前的文章或继续浏览下面的相关文章希望大家以后多多支持我! 。
原文链接:https://blog.csdn.net/weixin_45574655/article/details/114776505 。
最后此篇关于springAop实现权限管理数据校验操作日志的场景分析的文章就讲到这里了,如果你想了解更多关于springAop实现权限管理数据校验操作日志的场景分析的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
这是真的: log(A) + log(B) = log(A * B) [0] 这也是真的吗? O(log(A)) + O(log(B)) = O(log(A * B)) [1] 据我了解 O(f
0 引言 我常以为 配置 INFO 日志级别时, 应用程序代码中日志器(logger) debug 级的日志代码,不会被执行(比如,实验1中的printTestLog函数)。但今天线上的问题,
日志 日志是构建工具的主要界面。如果日志太多,真正的警告和问题容易被隐藏。另一方面,如果出了错,你需要找出相关的信息。Gradle 定义了6个日志级别,如表 18.1,“日志级别”所示。除了那些您通
日志 关键进程日志如下…(将 替换为启动服务的用户,将 替换为计算机名称) NameNode: $ HADOOP_HOME / logs / hadoop- -namenode- .log Da
我正在探索项目的 git 历史 FFMpeg .我在提交之间对每个文件执行了更改 517573a67088b5c7a25c18373434e3448892ee93和 80bb65fafab1d2f5f
我不知道如何在 loggly 中使用正则表达式进行搜索。例如,使用表达式 /24nonstop.+7554/ 记录我想查找的内容. { "level_name": "WARNING", "ex
有没有办法为 API 调用打开日志记录? 我们有一个第三方应用程序在使用我们的商店时遇到问题,希望获得一些调试信息。 ~我已经搜索了 bt 一无所获。 我正在使用 1.7 最佳答案 在一段受控的时间内
我正在尝试获取 SVN 中所有副本/移动/等的固定路径的日志历史记录(如果可能的话,递归地)。实际上,我试图避免 peg revisions ,并将日志应用于路径而不是对象。 svn 手册提出了这个问
如何在命令行中运行 NAnt 脚本并在日志文件中获取每个任务的时间? using nant task or NAnt -buildfile:testscript.build testnanttarg
是否有任何默认方式来记录哪些用户代理访问了您的服务器?我需要编制一份访问我们网站的浏览器列表,以便我们知道我们最能支持什么。 谢谢! 最佳答案 日志CGI.HTTP_USER_AGENT ,也许在 A
我在我的应用程序中使用 Spring 发送电子邮件。 我想在发送电子邮件时记录 imap 服务器操作。 我尝试按如下方式在我的 applicationContext.xml 中实现日志:
我已经运行一个 pod 一个多星期了,从开始到现在没有重启过。但是,我仍然无法查看自它启动以来的日志,它只提供最近两天的日志。容器是否有任何日志轮换策略以及如何根据大小或日期控制轮换? 我尝试了以下命
背景: 我正在设置我的第一个 flex 堆栈,尽管我将开始简单,但是我想确保我从良好的体系结构开始。我最终希望有以下解决方案:托管指标,服务器日志(expressjs APM),单页应用程序监视(AP
常规的 hg log 命令给出每个变更集至少 4 行的输出。例如 changeset: 238:03a214f2a1cf user: My Name date: Th
我在我的项目中使用 Spring iBatis 框架。然后使用 logback 进行记录。然后,在检查日志文件时,我可以看到系统正在使用的数据库...出于安全目的我想隐藏它 这是示例日志.. 12:2
我想使用 hg log 生成一个简短的变更日志,涵盖最新版本的变更。发行版标有“v”前缀,例如“v0.9.1”或“v1.0”。是否可以使用 revsets 选择以“v”开头的最后两个标签之间的范围,不
我是 PHP 的新手,所以如果有一个简单的答案,请原谅我。我在 stackoverflow 中搜索过任何类似的问题,但找不到任何帮助。 我正在开发一个现有的基于 php 的应用程序,我只需要能够将对象
我有一个名为 Radius 的程序可以验证用户登录。运行在CentOS服务器上 日志在/var/log/radius.log 中 它们如下 Mon Jul 24 22:17:08 2017 : Aut
我最近从使用“日志”切换到“日志”。 到目前为止,还不错,但我缺少一项关键功能——在运行时更改最低级别的能力。 在“logging',我可以调用 myLogger.setLevel(logging.I
假设我们有速度关键的系统(例如统计/分析、套接字编程等),我们如何设计跟踪和日志。 更具体地说,日志和跟踪通常会降低性能(即使我们有关闭机制或冗长的扩展机制)。在这种情况下,是否有任何关于如何“放置”
我是一名优秀的程序员,十分优秀!