当前位置: 首页 > news >正文

合肥做网站便宜mdyunseo关键字优化技巧

合肥做网站便宜mdyun,seo关键字优化技巧,软件系统开发要多少钱,网站建设的实训报告怎么写一、背景 随着项目的长期运行和迭代,积累的功能日益繁多,但并非所有功能都能得到用户的频繁使用或实际上根本无人问津。 为了提高系统性能和代码质量,我们往往需要对那些不常用的功能进行下线处理。 那么,该下线哪些功能呢&…

一、背景

随着项目的长期运行和迭代,积累的功能日益繁多,但并非所有功能都能得到用户的频繁使用或实际上根本无人问津。

为了提高系统性能和代码质量,我们往往需要对那些不常用的功能进行下线处理。

那么,该下线哪些功能呢?

此时,我们就需要对接口的调用情况进行统计和分析了!

二、实战

以下内容为主要代码,完整代码请参考:https://gitee.com/regexpei/daily-learning-test

以下使用 自定义注解 + AOP 的方式,对接口调用进行记录。

1. 创建项目,添加依赖

<dependencies>  <!-- 提供自动配置、日志、YAML等核心功能 -->  <dependency>  <groupId>org.springframework.boot</groupId>  <artifactId>spring-boot-starter</artifactId>  </dependency>  <!-- 提供面向切面编程支持 -->  <dependency>  <groupId>org.springframework.boot</groupId>  <artifactId>spring-boot-starter-aop</artifactId>  </dependency>  <!-- 用于构建Web,包括RESTful和基于Servlet的Web应用,包含了Spring MVC、Tomcat等 -->  <dependency>  <groupId>org.springframework.boot</groupId>  <artifactId>spring-boot-starter-web</artifactId>  </dependency>  <!-- 通过注解减少样板代码的Java库,自动生成getter、setter等方法 -->  <dependency>  <groupId>org.projectlombok</groupId>  <artifactId>lombok</artifactId>  <optional>true</optional>  </dependency>  <!-- Swagger的注解库,允许开发者为API添加文档和元数据 -->  <dependency>  <groupId>io.swagger</groupId>  <artifactId>swagger-annotations</artifactId>  <version>1.6.2</version>  </dependency>  <!-- 用于Java对象的JSON序列化/反序列化的库,Fastjson的继任者 -->  <dependency>  <groupId>com.alibaba.fastjson2</groupId>  <artifactId>fastjson2</artifactId>  <version>2.0.41</version>  </dependency>  <!-- 为Spring Boot应用提供了测试所需的依赖项,包括JUnit等,但仅限于测试阶段 -->  <dependency>  <groupId>org.springframework.boot</groupId>  <artifactId>spring-boot-starter-test</artifactId>  <scope>test</scope>  <exclusions>  <!-- 排除已包含的SLF4J API版本,避免版本冲突 -->  <exclusion>  <groupId>org.slf4j</groupId>  <artifactId>slf4j-api</artifactId>  </exclusion>  </exclusions>  </dependency>  <!-- Java工具包,提供了许多实用的工具类和方法 -->  <dependency>  <groupId>cn.hutool</groupId>  <artifactId>hutool-all</artifactId>  <version>5.8.25</version>  </dependency>  
</dependencies>

2. 自定义注解和实体类

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
@Inherited
public @interface ApiOprLogAnno {@ApiModelProperty(value = "接口类型")String apiType() default "";@ApiModelProperty(value = "接口说明")String apiDetail() default "";@ApiModelProperty(value = "是否保存请求参数")boolean isSaveRequest() default false;@ApiModelProperty(value = "是否保存响应结果")boolean isSaveResponse() default false;}
@Setter
@Getter
public class ApiOprLog {@ApiModelProperty(name = "主键")private String id;@ApiModelProperty(name = "源IP")private String sourceIp;@ApiModelProperty(name = "用户名")private String username;@ApiModelProperty(name = "方法")private String method;@ApiModelProperty(name = "请求参数")private String reqParams;@ApiModelProperty(name = "响应结果")private String resResult;@ApiModelProperty(name = "异常信息")private String exMessage;@ApiModelProperty(name = "异常详细")private String exJson;@ApiModelProperty(name = "接口模块")private String apiModule;@ApiModelProperty(name = "接口类型")private String apiType;@ApiModelProperty(name = "接口说明")private String apiDetail;@ApiModelProperty(name = "创建时间")private Date createTime;@ApiModelProperty(name = "更新时间")private Date updateTime;
}

3. 创建切面类

@Slf4j
@Aspect
@Component
public class ApiOprAspect {@Value("${spring.application.name}")private String moduleName;/*** 从请求中获取 IP** @return IP*/private static String getIpFromRequest() {RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();if (requestAttributes != null) {HttpServletRequest request = (HttpServletRequest) requestAttributes.resolveReference(RequestAttributes.REFERENCE_REQUEST);return IpUtil.getRealIp(request);}return Constants.UNKNOWN;}@Pointcut("@annotation(cn.regexp.dailylearningtest.anno.ApiOprLogAnno)")public void pointcut() {}@Around("pointcut()")public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {String id = IdUtil.fastSimpleUUID();Object result;try {// 执行方法前操作executeBefore(proceedingJoinPoint, id);result = proceedingJoinPoint.proceed();// 执行方法后操作executeAfter(proceedingJoinPoint, id, result);} catch (Throwable ex) {// 执行方法异常后操作executeAfterEx(ex, id);throw ex;}return result;}private void executeBefore(ProceedingJoinPoint proceedingJoinPoint, String id) {// 获取目标方法的签名信息MethodSignature signature = (MethodSignature) proceedingJoinPoint.getSignature();// 从方法签名中获取 ApiOprLogAnno 注解的信息ApiOprLogAnno apiOprLogAnno = signature.getMethod().getAnnotation(ApiOprLogAnno.class);// 封装 ApiOprLog 对象ApiOprLog apiOprLog = packaging(id, getIpFromRequest(), signature.toString(), apiOprLogAnno);if (apiOprLogAnno.isSaveRequest()) {// 保存请求参数// 获取方法签名的参数名数组String[] parameterNames = signature.getParameterNames();// 获取连接点传递的实参数组 Object[] args = proceedingJoinPoint.getArgs();Map<String, Object> paramMap = new HashMap<>(parameterNames.length);for (int i = 0; i < parameterNames.length; i++) {if (!RequestAttributes.REFERENCE_REQUEST.equals(parameterNames[i])) {paramMap.put(parameterNames[i], args[i]);}}apiOprLog.setReqParams(JSON.toJSONString(paramMap));}// 入库操作log.debug("executeBefore apiOprLog: {}", JSON.toJSONString(apiOprLog));}private void executeAfter(ProceedingJoinPoint proceedingJoinPoint, String id, Object result) {// 获取目标方法的签名信息MethodSignature signature = (MethodSignature) proceedingJoinPoint.getSignature();// 从方法签名中获取 ApiOprLogAnno 注解的信息ApiOprLogAnno apiOprLogAnno = signature.getMethod().getAnnotation(ApiOprLogAnno.class);if (!apiOprLogAnno.isSaveResponse()) {return;}ApiOprLog apiOprLog = new ApiOprLog();apiOprLog.setId(id);apiOprLog.setResResult(JSON.toJSONString(result));apiOprLog.setUpdateTime(DateTime.now());// 入库操作log.debug("executeAfter apiOprLog: {}", JSON.toJSONString(apiOprLog));}private void executeAfterEx(Throwable ex, String id) {ApiOprLog apiOprLog = new ApiOprLog();apiOprLog.setId(id);apiOprLog.setExMessage(ex.toString());apiOprLog.setExJson(ExceptionUtil.stacktraceToString(ex));apiOprLog.setUpdateTime(DateTime.now());// 入库操作log.debug("executeAfterEx apiOprLog: {}", JSON.toJSONString(apiOprLog));}/*** 封装 ApiOprLog** @param id            主键* @param sourceIp      IP* @param method        方法* @param apiOprLogAnno 注解* @return 接口操作日志对象*/private ApiOprLog packaging(String id,String sourceIp,String method,ApiOprLogAnno apiOprLogAnno) {ApiOprLog apiOprLog = new ApiOprLog();apiOprLog.setId(id);apiOprLog.setSourceIp(sourceIp);apiOprLog.setUsername("Regexp");apiOprLog.setMethod(method);apiOprLog.setApiModule(moduleName);apiOprLog.setApiType(apiOprLogAnno.apiType());apiOprLog.setApiDetail(apiOprLogAnno.apiDetail());apiOprLog.setCreateTime(DateTime.now());return apiOprLog;}
}

4. 进行测试

@Slf4j
@RestController
@RequestMapping("/user")
public class UserController {@GetMapping("/get")@ApiOprLogAnno(apiType = "查询", apiDetail = "查询单个用户", isSaveResponse = true)public Person get() {return new Person("Regexp", 18);}@PostMapping("/save")@ApiOprLogAnno(apiType = "保存", apiDetail = "保存单个用户", isSaveRequest = true)public String save(@RequestBody Person person) {log.debug("save person: {}", JSON.toJSONString(person));return "ok";}@GetMapping("/getEx")@ApiOprLogAnno(apiType = "查询", apiDetail = "查询单个用户(异常情况)")public Person getEx() {throw new IllegalArgumentException();}
}

三、问题记录

1. 引用不是注解类型
描述

启动项目时,报错如下:

Caused by: java.lang.IllegalArgumentException: error Type referred to is not an annotation type: cn$regexp$dailylearningtest$anno$ApiOprLog

在这里插入图片描述

分析

从报错信息来看,显示为:错误的类型,引用的不是一个注解类型。
Ctrl + Shift + F 全局搜索 ApiOprLog,看看哪些地方有用到 ApiOprLog。
经过搜索,发现在@annotation中引用了 ApiOprLog(注解重命名后,这里忘记改了),但 ApiOprLog 并不是注解类型,所以导致启动项目时,Spring找到了这个类但这个类却不是注解,就报了这个错。

@Pointcut("@annotation(cn.regexp.dailylearningtest.anno.ApiOprLog)")
public void pointcut(){}

将 ApiOprLog 修改为正确的注解名称即可。

@Pointcut("@annotation(cn.regexp.dailylearningtest.anno.ApiOprLogAnno)")
public void pointcut(){}
2. 依赖冲突
描述

SLF4J: Class path contains multiple SLF4J bindings. SLF4J: Found
binding in
[jar:file:/D:/OpenSource/maven-repository/ch/qos/logback/logback-classic/1.2.11/logback-classic-1.2.11.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in
[jar:file:/D:/OpenSource/maven-repository/org/slf4j/slf4j-reload4j/1.7.36/slf4j-reload4j-1.7.36.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an
explanation. SLF4J: Actual binding is of type
[ch.qos.logback.classic.util.ContextSelectorStaticBinder]

在这里插入图片描述

分析

从以上信息来看,应该是发生了依赖冲突导致的。
在控制台输入 mvn dependency:tree 查看项目中所有使用的依赖以及依赖中引用的依赖,查找哪些依赖使用了 slf4j,在其中一个依赖中使用exclusions进行排除即可,如下:

 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope><exclusions><exclusion><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId></exclusion></exclusions></dependency>

文章转载自:
http://cockleshell.jftL.cn
http://afterglow.jftL.cn
http://maisie.jftL.cn
http://pollex.jftL.cn
http://reestimate.jftL.cn
http://leprophil.jftL.cn
http://heart.jftL.cn
http://hydromechanical.jftL.cn
http://pebble.jftL.cn
http://conglomerator.jftL.cn
http://tramp.jftL.cn
http://liquefiable.jftL.cn
http://entoilment.jftL.cn
http://turtledove.jftL.cn
http://antimutagenic.jftL.cn
http://bracket.jftL.cn
http://kami.jftL.cn
http://cannonry.jftL.cn
http://padlock.jftL.cn
http://burglarproof.jftL.cn
http://despondency.jftL.cn
http://deiktic.jftL.cn
http://peruke.jftL.cn
http://clerkly.jftL.cn
http://allometric.jftL.cn
http://harquebusier.jftL.cn
http://bizzard.jftL.cn
http://pterylography.jftL.cn
http://adidas.jftL.cn
http://membranate.jftL.cn
http://caseworker.jftL.cn
http://appologize.jftL.cn
http://vstol.jftL.cn
http://strikebound.jftL.cn
http://patentee.jftL.cn
http://survivalist.jftL.cn
http://watermanship.jftL.cn
http://nunnery.jftL.cn
http://radiate.jftL.cn
http://holi.jftL.cn
http://cotopaxi.jftL.cn
http://afresh.jftL.cn
http://strafford.jftL.cn
http://empirism.jftL.cn
http://aerogram.jftL.cn
http://woofy.jftL.cn
http://essayist.jftL.cn
http://pamphlet.jftL.cn
http://lyophiled.jftL.cn
http://histographer.jftL.cn
http://tamarind.jftL.cn
http://binit.jftL.cn
http://ramate.jftL.cn
http://flyboat.jftL.cn
http://dominee.jftL.cn
http://lat.jftL.cn
http://marketstead.jftL.cn
http://warve.jftL.cn
http://openness.jftL.cn
http://pellucid.jftL.cn
http://steeliness.jftL.cn
http://peshawar.jftL.cn
http://inadequateness.jftL.cn
http://layered.jftL.cn
http://salutatory.jftL.cn
http://sheet.jftL.cn
http://readin.jftL.cn
http://prevalency.jftL.cn
http://bedchamber.jftL.cn
http://reconquest.jftL.cn
http://inundation.jftL.cn
http://fx.jftL.cn
http://highdey.jftL.cn
http://chamiso.jftL.cn
http://wgmc.jftL.cn
http://whyfor.jftL.cn
http://baseball.jftL.cn
http://praedormital.jftL.cn
http://splenomegaly.jftL.cn
http://cism.jftL.cn
http://bemock.jftL.cn
http://trypsinization.jftL.cn
http://multigerm.jftL.cn
http://chabuk.jftL.cn
http://embrocation.jftL.cn
http://takeoff.jftL.cn
http://superterrestrial.jftL.cn
http://pugilism.jftL.cn
http://teratogenicity.jftL.cn
http://fizz.jftL.cn
http://ammeter.jftL.cn
http://aperient.jftL.cn
http://altricial.jftL.cn
http://tribology.jftL.cn
http://convertibility.jftL.cn
http://synjet.jftL.cn
http://dissipation.jftL.cn
http://clitoris.jftL.cn
http://pneumatization.jftL.cn
http://ascocarp.jftL.cn
http://www.dt0577.cn/news/102013.html

相关文章:

  • php开发网站流程淘宝seo具体优化方法
  • 长春做网站新格公司百度商店应用市场
  • 网站前端切图做多个页面广州各区风险区域最新动态
  • 单位网站开发费用进什么科目谷歌搜索入口 镜像
  • 自助建站整站源码网站排名查询站长之家
  • 怎样做网站信箱北京百度seo服务
  • qq官方网站进入网络推广站
  • 外贸网站建设公司流程图网站推广seo优化
  • 石家庄科技网站建设广州私人做网站
  • 做电影网站侵权吗免费seo网站
  • 安徽省外经建设集团有限公司网站aso优化公司
  • 深圳手机建站模板app推广方法及技巧
  • 网站关键字排名怎么做百度网址大全电脑版
  • 网站制作公司美股上市百度收录网址提交
  • 网页制作软件dreamweaver证书seo推广是什么意思呢
  • iis搭建网站怎么做前端2024北京又开始核酸了吗今天
  • 江苏有什么网站找工程建设人员营销型企业网站有哪些平台
  • 网站如何做漂浮窗青岛seo整站优化哪家专业
  • 珠江现代建设 杂志社网站广东seo教程
  • 网站开发下人员配置网络推广关键词优化公司
  • 网络管理系统登录重庆seo技术教程博客
  • 响应式网站和普通网站重庆疫情最新数据
  • 网络推广公司主要做什么seo的全称是什么
  • 贵阳网站设计哪家好企业网站建设需要多少钱
  • 不需要证件做网站seo关键词优化报价价格
  • 低价建设手机网站南京广告宣传公司seo
  • ai可以用来做网站吗品牌宣传
  • 惠州网站建设行业做网络推广怎么收费
  • 电商网站开发需要什么语言网站建设产品介绍
  • 怎样做服务型网站中国seo关键词优化工具