发布于2020-11-19 20:30 阅读(563) 评论(0) 点赞(5) 收藏(5)
23点59:在AOP中切面就是与业务逻辑独立,但又垂直存在于业务逻辑的代码结构中的通用功能组合;切面与业务逻辑相交的点就是切点;连接点就是把业务逻辑离散化后的关键节点;切点属于连接点,是连接点的子集;Advice(增强)就是切面在切点上要执行的功能增加的具体操作;在切点上可以把要完成增强操作的目标对象(Target)连接到切面里,这个连接的方式就叫织入。
execution:用于匹配方法执行的连接点;比较常用,具体可以参考:https://blog.csdn.net/zz210891470/article/details/54175107
within:用于匹配指定类型内的方法执行;within()和execution()函数不同的是,within()所指定的连接点最小范围只能是类,而execution()所指定的连接点可以大到包,小到方法入参。 所以从某种意义上讲,execution()函数功能涵盖了within()函数的功能
this:用于指定AOP代理必须是指定类型的实例,用于匹配该对象的所有连接点。当使用Spring AOP的时候,只能匹配方法执行的连接点。下面是个例子:
this(com.lcq.service.AdviceManager)//匹配实现了AdviceManager接口的代理对象的所有连接点,在Spring中只是方法执行的连接点
target:用于限定目标对象必须是指定类型的实例,用于匹配该对象的所有连接点。当使用Spring AOP的时候,只能匹配方法执行的连接点。下面是个例子:
target(com.lcq.servcie.AdviceManager)//匹配实现了AdviceManager接口的目标对象的所有连接点,在Spring中只是方法执行的连接点
args:用于对连接点的参数类型进行限制,要求参数的类型时指定类型的实例。同样,当使用Spring AOP的时候,只能匹配方法执行的连接点。下面是个例子:
args(java.io.Serializable)//匹配只接受一个参数,且参数类型是Serializable的所有连接点,在Spring中只是方法执行的连接点
注意,这个例子与使用execution(* (java.io.Serializable))定义的切点不同,args版本只匹配运行时动态传入参数值是Serializable类型的情形,而execution版本则匹配方法签名只包含一个Serializable类型的形参的方法。单独使用时报错的话,加上没带@的指示符一起使用,例如:
within(com.lcq.demo.controller.) && args(java.lang.String)
@within:用于匹配所以持有指定注解类型内的方法;在接口上声明的对它不起作用,注解写在方法上是不会执行的。
@target:用于匹配当前目标对象类型的执行方法,其中目标对象持有指定的注解;在接口上声明的对它不起作用, 注解写在方法上是不会执行的。;单独使用时报错的话,加上没带@的指示符一起使用,例如:
within(com.lcq.demo.controller.*) && @target(com.lcq.demo.annotaion.ApiControllerLog)
@args:用于匹配当前执行的方法传入的参数持有指定注解的执行;类跟方法都可以
@annotation:用于匹配当前执行方法持有指定注解的方法;注解写在类上是不会执行。
bean:Spring AOP扩展的,AspectJ没有对于指示符,用于匹配特定名称的Bean对象的执行方法;
reference pointcut:表示引用其他命名切入点,只有@ApectJ风格支持,Schema风格不支持。AspectJ切入点支持的切入点指示符还有: call、get、set、preinitialization、staticinitialization、initialization、handler、adviceexecution、withincode、cflow、cflowbelow、if、@this、@withincode;但Spring AOP目前不支持这些指示符,使用这些指示符将抛出IllegalArgumentException异常。这些指示符Spring AOP可能会在以后进行扩展。
创建一个切面:新建一个包interceptor用来存放切面类,然后再在里面创建切面AuthAspect, 内容如下:
package com.lcq.demo.interceptor;
import com.lcq.demo.util.Tool;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
//定义这是一个切面类
@Aspect
//将该类交由spring管理
@Component
public class AuthAspect {
@Autowired
private Tool tool;
//方法带有@RequestMapping切点
@Pointcut("@annotation(org.springframework.web.bind.annotation.RequestMapping)")
public void requestMapping() {
}
//方法带有@PostMapping切点
@Pointcut("@annotation(org.springframework.web.bind.annotation.PostMapping)")
public void postMapping(){
}
//方法带有@GetMapping切点
@Pointcut("@annotation(org.springframework.web.bind.annotation.GetMapping)")
public void getMapping(){
}
//方法带有@ApiControllerLog
@Pointcut("@annotation(com.lcq.demo.annotaion.ApiControllerLog)")
public void apiMapping(){
}
@Around("postMapping()")
public Object authAndDecryptPost(ProceedingJoinPoint joinPoint) {
//获取请求参数
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
Map<String, Object> requestMap = tool.getParamFromView(request);
//获取请求头
String requestHeader = request.getHeader("requestHeader");
Object[] args = joinPoint.getArgs();
System.out.println(args);
args[0] = requestMap;
//返回参数
Object resultObject = null;
try {
resultObject = joinPoint.proceed(joinPoint.getArgs());
} catch (Throwable throwable) {
Map<String,Object> resultMap = new HashMap<>();
resultMap.put("isSuccess" , 0);
resultObject = resultMap;
}
return resultObject;
}
@Around("apiMapping()")
public Object authAndDecryptApi(ProceedingJoinPoint joinPoint) {
//获取请求参数
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
Map<String, Object> requestMap = tool.getParamFromView(request);
//获取请求头
String requestHeader = request.getHeader("requestHeader");
Object[] args = joinPoint.getArgs();
System.out.println(args);
args[0] = requestMap;
//返回参数
Object resultObject = null;
try {
resultObject = joinPoint.proceed(joinPoint.getArgs());
} catch (Throwable throwable) {
Map<String,Object> resultMap = new HashMap<>();
resultMap.put("isSuccess" , 0);
resultObject = resultMap;
}
return resultObject;
}
}
/**
* 获取前端参数
*/
@SuppressWarnings("rawtypes")
public Map<String, Object> getParamFromView(HttpServletRequest request){
//处理前端请求参数
Enumeration paramNames = request.getParameterNames();
Map<String, Object> map = new TreeMap<>();
while ((paramNames != null) && paramNames.hasMoreElements()) {
String paramName = (String) paramNames.nextElement();
String[] values = request.getParameterValues(paramName);
if ((values == null) || (values.length == 0)) {
// Do nothing, no values found at all.
} else if (values.length > 1) {
map.put(paramName, values);
} else if(StringUtils.isNoneBlank(values[0])){
map.put(paramName, values[0]);
}
}
return map;
}
获取到请求参数后,就可以在切面里做一些参数判断或校验。
使用@Pointcut("@annotation()")来定义切点,常用的可以选择RequestMapping、PostMapping、GetMapping;只要在要拦截的方法上加上对应的注释
也可以使用自定义注解来标识。
创建自定义注解:创建annotaion包,并在里面创建自定义注解,如ApiControllerLog,类内容如:
package com.lcq.demo.annotaion;
import java.lang.annotation.*;
/**
* 自定义注解 拦截ApiController日志
*/
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ApiControllerLog {
String description() default "";
}
控制层被拦截方法:
效果:
作者:你不要惹我
链接:http://www.javaheidong.com/blog/article/787/a543f2657f022a10cc2d/
来源:java黑洞网
任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任
昵称:
评论内容:(最多支持255个字符)
---无人问津也好,技不如人也罢,你都要试着安静下来,去做自己该做的事,而不是让内心的烦躁、焦虑,坏掉你本来就不多的热情和定力
Copyright © 2018-2021 java黑洞网 All Rights Reserved 版权所有,并保留所有权利。京ICP备18063182号-2
投诉与举报,广告合作请联系vgs_info@163.com或QQ3083709327
免责声明:网站文章均由用户上传,仅供读者学习交流使用,禁止用做商业用途。若文章涉及色情,反动,侵权等违法信息,请向我们举报,一经核实我们会立即删除!