aop开发,app开发需要多少钱
今天给大家分享AOP相关aop开发的知识aop开发,希望对大家能有所帮助!
1、AOP定义AOP全称为Aspect Oriented Programmingaop开发,中文含义为aop开发:面向切面编程。
通过预编译方式和运行期动态代理实现程序功能的统一维护的技术。AOP技术是Spring框架中的一个重要内容。使用AOP技术可以对业务逻辑的各个部分进行隔离,可以使业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时也提高aop开发了开发的效率。
2、AOP的用途使用AOP技术可以很好的将日志记录,性能统计,安全控制,事务处理,异常处理、Web参数校验等代码逻辑从业务代码中分离出来,让开发人员只需要关注业务代码的编写,从而开发效率,节省开发成本。
3、AOP常用的注解注解
注解说明
@Aspect
切面声明:通常标注在类、接口(包括注解类型)或枚举类型。
@Pointcut
切入点声明:即切入到哪些目标类的目标 *** 。
value 属性指定切入点的表达式,默认为 “”,用于被通知注解引用,这样通知注解只需要关联此切入点声明即可,无需再重复写切入点表达式
@Before
前置通知: 在目标 *** (切入点)执行之前执行。value 属性绑定通知的切入点表达式,可以关联切入点声明,也可以直接设置切入点表达式
注意:如果在此回调 *** 中抛出异常,则目标 *** 不会再执行,会继续执行后置通知 -> 异常通知。
@After
后置通知,:在目标 *** (切入点)执行之后执行
@AfterRunning
返回通知,:在目标 *** (切入点)返回结果之后执行,在 @After 的后面执行pointcut 属性绑定通知的切入点表达式,优先级高于 value,默认为 “”
@AfterThrowing
异常通知,:在发现 *** 抛出异常之后执行, 意味着跳过返回通知pointcut 属性绑定通知的切入点表达式,优先级高于 value,默认为 “”
说明:如果目标 *** 自己 try-catch 了异常,而没有继续往外抛,则不会进入此回调函数
@Around
环绕通知:目标 *** 执行前后分别执行一些代码,发生异常的时候执行另外一些代码
4、AOP实现Web统一日志Demo4.1 新建IErrorCode.java 接口类package com.aop.common.api;/** * 封装API的错误码 */public interface IErrorCode { long getCode(); String getMessage();}4.2 新建ResultCode.java 接口类package com.aop.common.api;/** * 枚举了一些常用API操作码 */public enum ResultCode implements IErrorCode { SUCCESS(200, "操作成功"), FAILED(500, "操作失败"), VALIDATE_FAILED(404, "参数检验失败"), UNAUTHORIZED(401, "暂未登录或token已经过期"), FORBIDDEN(403, "没有相关权限"); private long code; private String message; private ResultCode(long code, String message) { this.code = code; this.message = message; } public long getCode() { return code; } public String getMessage() { return message; }}4.3 新建WebLog.javapackage com.aop.common.dto;/** * Controller层的日志封装类 */public class WebLog { /** * 操作描述 */ private String description; /** * 操作用户 */ private String username; /** * 操作时间 */ private Long startTime; /** * 消耗时间 */ private Integer spendTime; /** * 根路径 */ private String basePath; /** * URI */ private String uri; /** * URL */ private String url; /** * 请求类型 */ private String method; /** * IP地址 */ private String ip; /** * 请求参数 */ private Object parameter; /** * 请求返回的结果 */ private Object result; public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public Long getStartTime() { return startTime; } public void setStartTime(Long startTime) { this.startTime = startTime; } public Integer getSpendTime() { return spendTime; } public void setSpendTime(Integer spendTime) { this.spendTime = spendTime; } public String getBasePath() { return basePath; } public void setBasePath(String basePath) { this.basePath = basePath; } public String getUri() { return uri; } public void setUri(String uri) { this.uri = uri; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public String getMethod() { return method; } public void setMethod(String method) { this.method = method; } public String getIp() { return ip; } public void setIp(String ip) { this.ip = ip; } public Object getParameter() { return parameter; } public void setParameter(Object parameter) { this.parameter = parameter; } public Object getResult() { return result; } public void setResult(Object result) { this.result = result; }}4.4 新建WebLogAspect.java 类package com.aop.common.component;import cn.hutool.core.util.StrUtil;import cn.hutool.core.util.URLUtil;import cn.hutool.json.JSONUtil;import com.aop.common.dto.WebLog;import io.swagger.annotations.ApiOperation;import org.aspectj.lang.JoinPoint;import org.aspectj.lang.ProceedingJoinPoint;import org.aspectj.lang.Signature;import org.aspectj.lang.annotation.*;import org.aspectj.lang.reflect.MethodSignature;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.core.annotation.Order;import org.springframework.stereotype.Component;import org.springframework.util.StringUtils;import org.springframework.web.bind.annotation.RequestBody;import org.springframework.web.bind.annotation.RequestParam;import org.springframework.web.context.request.RequestContextHolder;import org.springframework.web.context.request.ServletRequestAttributes;import javax.servlet.http.HttpServletRequest;import java.lang.reflect.Method;import java.lang.reflect.Parameter;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;/** * 统一日志处理切面 */@Aspect@Component@Order(1)public class WebLogAspect { private static final Logger LOGGER = LoggerFactory.getLogger(WebLogAspect.class); //切点定义了通知功能被应用的范围。比如日志切面的应用范围就是所有接口,即所有controller层的接口方 @Pointcut("execution(public * com.macro.mall.tiny.controller.*.*(..))") public void webLog() { } // 在目标 *** 调用前调用通知功能 @Before("webLog()") public void doBefore(JoinPoint joinPoint) throws Throwable { } // 在目标 *** 成功执行之后调用通知功能 @AfterReturning(value = "webLog()", returning = "ret") public void doAfterReturning(Object ret) throws Throwable { } // 通知包裹了目标 *** ,在目标 *** 调用之前和之后执行自定义的行为 @Around("webLog()") public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable { long startTime = System.currentTimeMillis(); //获取当前请求对象 ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); HttpServletRequest request = attributes.getRequest(); //记录请求信息 WebLog webLog = new WebLog(); Object result = joinPoint.proceed(); Signature signature = joinPoint.getSignature(); MethodSignature methodSignature = (MethodSignature) signature; Method method = methodSignature.getMethod(); if (method.isAnnotationPresent(ApiOperation.class)) { ApiOperation apiOperation = method.getAnnotation(ApiOperation.class); webLog.setDescription(apiOperation.value()); } long endTime = System.currentTimeMillis(); String urlStr = request.getRequestURL().toString(); webLog.setBasePath(StrUtil.removeSuffix(urlStr, URLUtil.url(urlStr).getPath())); webLog.setIp(request.getRemoteUser()); webLog.setMethod(request.getMethod()); webLog.setParameter(getParameter(method, joinPoint.getArgs())); webLog.setResult(result); webLog.setSpendTime((int) (endTime - startTime)); webLog.setStartTime(startTime); webLog.setUri(request.getRequestURI()); webLog.setUrl(request.getRequestURL().toString()); LOGGER.info("{}", JSONUtil.parse(webLog)); return result; } /** * 根据 *** 和传入的参数获取请求参数 */ private Object getParameter(Method method, Object[] args) { List<Object> argList = new ArrayList<>(); Parameter[] parameters = method.getParameters(); for (int i = 0; i < parameters.length; i++) { //将RequestBody注解修饰的参数作为请求参数 RequestBody requestBody = parameters[i].getAnnotation(RequestBody.class); if (requestBody != null) { argList.add(args[i]); } //将RequestParam注解修饰的参数作为请求参数 RequestParam requestParam = parameters[i].getAnnotation(RequestParam.class); if (requestParam != null) { Map<String, Object> map = new HashMap<>(); String key = parameters[i].getName(); if (!StringUtils.isEmpty(requestParam.value())) { key = requestParam.value(); } map.put(key, args[i]); argList.add(map); } } if (argList.size() == 0) { return null; } else if (argList.size() == 1) { return argList.get(0); } else { return argList; } }}4.5 新建测试控制器TestLogController.javapackage com.aop.common.controller;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;@Controller@RequestMapping("/TestLog")public class TestLogController { @RequestMapping("/Test") public String Test(String name) { return "hello"+name; }}请求参数:localhost:8080/TestLog/Test?name=121
输出结果:
{"result":"hello121","basePath":"http://localhost:8080","method":"GET","startTime":1645883742030,"uri":"/TestLog/Test","url":"http://localhost:8080/TestLog/Test","spendTime":4695}