springmvc里面自定义注解实现aop,controller层里面注解一直不生效,但是注解放在service层又可以??
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了springmvc里面自定义注解实现aop,controller层里面注解一直不生效,但是注解放在service层又可以??相关的知识,希望对你有一定的参考价值。
在applicationContext.xml与springmvc-servlet.xml里面分别对不同的层扫描做了过滤,但还是不行!
applicationContext.xml
springmvc-servlet.xml
aop类
把注解写在service上可以,写在controller上就没效果
springmvc-servlet.xml 和 applicationContext.xml是不同的spring装载器。追问
这两个不冲突
参考技术B 贴代码,配置追问贴了
追答
加到springMVC配置试一把
这个之前就有,后面那个加了,发现还是没用
追答springmvc 主要是controller 层的,spring 主要是dao,model,services层,这里就有可能是controller也被spring 扫描注入的原因,然后让web不知道该去哪里
去掉spring里面的controller的注解
使用AOP以及自定义注解实现业务日志的收集
直接上代码
自定义注解:MyLog
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyLog
String value() default ""; //value值是说明,会被记录到数据库里面
自定义日志的实体类SysLog
@Data
@TableName("sys_log")
public class SysLog
@TableId(value = "id", type = IdType.ASSIGN_ID)
private String id;
@TableField(value = "visit_time")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date visitTime;
@TableField(value = "execution_time")
private Long executionTime;
@TableField(value = "email")
private String email;
private String ip;
private String url;
private String method;
/**
* 日志标题
*/
private String title;
private String params;
/**
* 请求类型
*/
private String type;
编写的切面类:LogAspect
@Aspect
@Order(5)
@Component
public class LogAspect
private final Logger logger = LoggerFactory.getLogger(LogAspect.class);
@Autowired
SysLogService sysLogService;
//可以直接注入HttpServletRequest 来获取当前的请求
@Autowired
HttpServletRequest request;
private Date visitTime;
private Class<?> clazz;
private Method method;
private String myLogValue;
@Pointcut("@annotation(com.example.controller.sys.MyLog)")
public void pointcut()
/**
* 前置通知,在Controller层操作前拦截
*
* @param joinPoint 切入点
*/
@Before("pointcut()")
public void doBefore(JoinPoint joinPoint) throws NoSuchMethodException
// 获取当前调用时间
visitTime = new Date();
clazz = joinPoint.getTarget().getClass();
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
if (methodSignature == null || methodSignature.getMethod().getAnnotation(MyLog.class) == null)
return;
MyLog myLog = methodSignature.getMethod().getAnnotation(MyLog.class);
myLogValue = myLog.value();
String methodName = methodSignature.getName();
Object[] args = joinPoint.getArgs();
//获取具体执行的方法的Method对象
if (args == null || args.length == 0)
//只能获取无参数的方法
this.method = clazz.getMethod(methodName);
else
Class<?>[] classArgs = new Class<?>[args.length];
for (int i = 0; i < args.length; i++)
classArgs[i] = args[i].getClass();
this.method = clazz.getMethod(methodName, classArgs);
@After("pointcut()")
public void doAfter(JoinPoint jp) throws Exception
long time = System.currentTimeMillis() - visitTime.getTime();
String url = "";
/*获取url*/
if (clazz != null && method != null && clazz != LogAspect.class)
Subject currentUser = SecurityUtils.getSubject();
String username = (String) currentUser.getPrincipal();
SysLog sysLog = new SysLog();
sysLog.setVisitTime(visitTime);
sysLog.setEmail(username);
sysLog.setUrl(request.getRequestURL().toString());
sysLog.setExecutionTime(System.currentTimeMillis() - visitTime.getTime());
//什么类的什么方法
sysLog.setMethod("[类名]:" + clazz.
getName() + ", [方法名]:" + method.getName());
sysLog.setTitle(myLogValue);
Object[] args = jp.getArgs();
if (args == null || args.length == 0)
sysLog.setParams("无参数");
//设置不能超过500长度,防止插入数据库抛异常
String s = Arrays.toString(args);
if (s.length() > 485)
s = s.substring(0, 480);
sysLog.setParams(s);
sysLog.setType(request.getMethod());
sysLog.setIp(request.getRemoteAddr());
System.out.println(sysLog);
//调用Service完成操作,调用dao将sysLog insert数据库
sysLogService.save(sysLog);
ServiceImpl
类:
@Service
public class SysLogServiceImpl implements SysLogService
@Autowired
SysLogMapper sysLogMapper;
@Override
public void save(SysLog sysLog)
sysLogMapper.insert(sysLog);
/**
* 这里就是一个简单的分页查询了。PageResultDTO是自定义的分页返回类
*/
@Override
public PageResultDTO<SysLog> pageSysLogs(Long pageNum, Long pageSize)
Page<SysLog> page = new Page<>(pageNum, pageSize);
Page<SysLog> sysLogPage = sysLogMapper.selectPage(page, null);
return PageUtil.convertToPageResult(sysLogPage);
使用时,只要把@MyLog
注解标在自己想要记录日志的方法上,就可以了。
例如:
@MyLog("测试aaa接口的日志输出")
@PostMapping("/aaa")
public RetJson<Object> aaa(@RequestBody User user)
return RetJson.success(user);
不过,当我使用AOP之后,发现我代码中使用了Shiro的controller全都404了,很奇怪,后面看别人的博客,改了配置才好了
在ShiroConfig
中加入配置:
@Bean
public static DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator()
DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
defaultAdvisorAutoProxyCreator.setUsePrefix(true);
return defaultAdvisorAutoProxyCreator;
同时我也在application.yml
中加入了配置:
aop:
auto: true
proxy-target-class: true
以上是关于springmvc里面自定义注解实现aop,controller层里面注解一直不生效,但是注解放在service层又可以??的主要内容,如果未能解决你的问题,请参考以下文章