HAP_接口监控(注解)

13265172-cb30643ae3ded34d.png
image.png

方法一:注解:

新建注解接口:

package wht.ora20796.aop;

import java.lang.annotation.*;

/**
 * Service注解
 */
@Inherited
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ServiceAnnotation {
    String apiName() default "";
    String sysName() default "";
}

新建切面类监听注解接口:


13265172-a4b662e8e1f2b16e.png
image.png
13265172-d6bec0ad81f6dc15.png
image.png


package wht.ora20796.aop;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.hand.hap.intergration.annotation.HapInbound;
import com.hand.hap.intergration.annotation.HapOutbound;
import com.hand.hap.intergration.aop.HapInvokeAspect;
import com.hand.hap.intergration.beans.HapInvokeInfo;
import com.hand.hap.intergration.beans.HapinterfaceBound;
import com.hand.hap.intergration.dto.HapInterfaceInbound;
import com.hand.hap.intergration.dto.HapInterfaceOutbound;
import com.hand.hap.intergration.util.HapInvokeLogUtils;
import com.hand.hap.message.IMessagePublisher;
import com.hand.hap.system.dto.ResponseData;
import net.sf.json.JSONObject;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Date;

/**
* 切面类
*/
@Component
@Aspect  // 指定当前类为切面类
public class VendorAop {
  private static final Logger logger = LoggerFactory.getLogger(HapInvokeAspect.class);
  @Autowired
  private IMessagePublisher messagePublisher;
  @Autowired
  private ObjectMapper objectMapper;
  private Class interfaceHeaderServiceClazz;
  private Class interfaceHeaderClazz;
  private Object interfaceHeaderServiceImpl;

  public VendorAop() {
  }

  public void contextInitialized(ApplicationContext applicationContext) {
      try {
          this.interfaceHeaderServiceClazz = Class.forName("com.hand.hap.intergration.service.IHapInterfaceHeaderService");
          if (this.interfaceHeaderServiceClazz != null) {
              this.interfaceHeaderClazz = Class.forName("com.hand.hap.intergration.dto.HapInterfaceHeader");
              this.interfaceHeaderServiceImpl = applicationContext.getParentBeanFactory().getBean("hapInterfaceHeaderServiceImpl", this.interfaceHeaderServiceClazz);
          }
      } catch (Exception var3) {
          logger.debug("interface module class not found");
      }

  }
//    @HapOutbound
//    HapInvokeAspect hapInvokeAspect;
  //指定切入点表单式:拦截哪些方法:即为哪些类生成代理对象
 //@Pointcut("execution(* wht.ora20796.service.ISoapVendorService.*(..))")
  @Pointcut("@annotation(wht.ora20796.aop.ServiceAnnotation)")
  public void pointCut_() {
  }
  @Around("@annotation(bound)")
  public Object aroundMethod(ProceedingJoinPoint pjd, ServiceAnnotation bound) throws Throwable {
      System.out.println("-------------------注解监听------------------");
      Long startTime = System.currentTimeMillis();
      Object result = null;
      Throwable throwable = null;
      HapInterfaceOutbound outbound = new HapInterfaceOutbound();
      HapInvokeInfo.OUTBOUND.set(outbound);
      boolean var18 = false;

      HapinterfaceBound hapinterfaceBound;
      label165: {
          try {
              var18 = true;
              outbound.setRequestTime(new Date());
              Object[] args = pjd.getArgs();
              String sysName = null;
              String apiName = null;
              Object[] var10 = args;
              int var11 = args.length;

              for(int var12 = 0; var12 < var11; ++var12) {
                  Object obj = var10[var12];
                  if (obj instanceof HttpServletRequest) {
                      sysName = ((HttpServletRequest)obj).getParameter("sysName");
                      apiName = ((HttpServletRequest)obj).getParameter("apiName");
                  }
              }

              if (sysName == null && apiName == null) {
                  sysName = bound.sysName();
                  apiName = bound.apiName();
              }

              outbound.setInterfaceName(sysName + "-" + apiName);
              if (this.interfaceHeaderServiceClazz != null && this.interfaceHeaderClazz != null && this.interfaceHeaderServiceImpl != null) {
                  Method getHeaderAndLineMethod = this.interfaceHeaderServiceClazz.getMethod("getHeaderAndLine", String.class, String.class);
                  Object hapInterfaceHeaderObject = getHeaderAndLineMethod.invoke(this.interfaceHeaderServiceImpl, sysName, apiName);
                  if (hapInterfaceHeaderObject != null) {
                      Method getDomainUrl = this.interfaceHeaderClazz.getMethod("getDomainUrl");
                      Method getIftUrl = this.interfaceHeaderClazz.getMethod("getIftUrl");
                      outbound.setInterfaceUrl(getDomainUrl.invoke(hapInterfaceHeaderObject).toString() + getIftUrl.invoke(hapInterfaceHeaderObject).toString());
                  } else {
                      outbound.setInterfaceUrl(" ");
                  }
              }

              result = pjd.proceed();
              if (HapInvokeInfo.OUTBOUND_REQUEST_PARAMETER.get() != null) {
                  outbound.setRequestParameter((String)HapInvokeInfo.OUTBOUND_REQUEST_PARAMETER.get());
              }

              if (HapInvokeInfo.HTTP_RESPONSE_CODE.get() != null) {
                  outbound.setResponseCode(((Integer)HapInvokeInfo.HTTP_RESPONSE_CODE.get()).toString());
              }

              if (HapInvokeInfo.OUTBOUND_RESPONSE_DATA.get() != null) {
                  outbound.setResponseContent((String)HapInvokeInfo.OUTBOUND_RESPONSE_DATA.get());
              } else if (result != null) {
                  outbound.setResponseContent(result.toString());
              }

              outbound.setRequestStatus("success");
              HapInterfaceInbound inbound = (HapInterfaceInbound)HapInvokeInfo.INBOUND.get();
              if (inbound != null) {
                  if (inbound.getStackTrace() != null) {
                      outbound.setStackTrace(inbound.getStackTrace());
                      outbound.setRequestStatus("failure");
                  }

                  HapInvokeInfo.INBOUND.remove();
                  var18 = false;
              } else {
                  var18 = false;
              }
              break label165;
          } catch (Throwable var19) {
              throwable = var19;
              result = new JSONObject();
              ((JSONObject)result).put("error", var19.getMessage());
              var18 = false;
          } finally {
              if (var18) {
                  outbound.setResponseTime(System.currentTimeMillis() - startTime);
                  HapInvokeLogUtils.processExceptionInfo(outbound, throwable);
                   hapinterfaceBound = new HapinterfaceBound(outbound);
                  this.messagePublisher.message("invoke.service", hapinterfaceBound);
                  HapInvokeInfo.clearOutboundInfo();
              }
          }

          outbound.setResponseTime(System.currentTimeMillis() - startTime);
          HapInvokeLogUtils.processExceptionInfo(outbound, throwable);
          hapinterfaceBound = new HapinterfaceBound(outbound);
          this.messagePublisher.message("invoke.service", hapinterfaceBound);
          HapInvokeInfo.clearOutboundInfo();
          return result;
      }

      outbound.setResponseTime(System.currentTimeMillis() - startTime);
      HapInvokeLogUtils.processExceptionInfo(outbound, throwable);
      hapinterfaceBound = new HapinterfaceBound(outbound);
      this.messagePublisher.message("invoke.service", hapinterfaceBound);
      HapInvokeInfo.clearOutboundInfo();
      return result;
  }

  // 环绕通知:环绕目标方式执行
  /*@Around("@annotation(bound)")
  public void around(ProceedingJoinPoint pjp,ServiceAnnotation bound) throws Throwable {
      System.out.println("环绕前....");
      pjp.proceed();  // 执行目标方法
      System.out.println("环绕后....");
  }*/

  // 前置通知 : 在执行目标方法之前执行
/*  @Before("pointCut_()")
  public void begin() {
      System.out.println("-----------ISoapVendorService---------");
      System.out.println("开始事务/异常");

  }

  // 后置/最终通知:在执行目标方法之后执行  【无论是否出现异常最终都会执行】
  @After("pointCut_()")
  public void after() {
      System.out.println("-----------ISoapVendorService---------");
      System.out.println("提交事务/关闭");
  }*/
/*
  // 返回后通知: 在调用目标方法结束后执行 【出现异常不执行】
  @AfterReturning("pointCut_()")
  public void afterReturning() {
      System.out.println("afterReturning()");
  }

  // 异常通知: 当目标方法执行异常时候执行此关注点代码
  @AfterThrowing("pointCut_()")
  public void afterThrowing() {
      System.out.println("afterThrowing()");
  }
*/



}

给方法添加新建的注解:


13265172-5d46ed1494964e25.png
image.png

测试:


13265172-0ecf4cc25c02fa58.png
image.png
13265172-eb355a124d0a96b3.png
image.png

方法二:(非注解)对ISoapVendorService.java中的方法继续切面增强

package wht.ora20796.aop;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

/**
 * 切面类
 */
@Component
@Aspect  // 指定当前类为切面类
public class VendorAop {
    //指定切入点表单式:拦截哪些方法:即为哪些类生成代理对象
    @Pointcut("execution(* wht.ora20796.service.ISoapVendorService.*(..))")
    //@Pointcut("execution(* wht.ora20796.aop.UserDaoImpl.save(..))")
    public void pointCut_() {
    }

    // 前置通知 : 在执行目标方法之前执行
    @Before("pointCut_()")
    public void begin() {
        System.out.println("-----------ISoapVendorService---------");
        System.out.println("开始事务/异常");

    }

    /*// 后置/最终通知:在执行目标方法之后执行  【无论是否出现异常最终都会执行】
    @After("pointCut_()")
    public void after() {
        System.out.println("提交事务/关闭");
    }

    // 返回后通知: 在调用目标方法结束后执行 【出现异常不执行】
    @AfterReturning("pointCut_()")
    public void afterReturning() {
        System.out.println("afterReturning()");
    }

    // 异常通知: 当目标方法执行异常时候执行此关注点代码
    @AfterThrowing("pointCut_()")
    public void afterThrowing() {
        System.out.println("afterThrowing()");
    }

    // 环绕通知:环绕目标方式执行
    @Around("pointCut_()")
    public void around(ProceedingJoinPoint pjp) throws Throwable {
        System.out.println("环绕前....");
        pjp.proceed();  // 执行目标方法
        System.out.println("环绕后....");
    }*/


}

效果:


13265172-b04c15256fe99ad7.png
image.png
13265172-d71855ac194499fe.png
image.png
<think>我们正在讨论鸿蒙HarmonyOS应用开发流程。用户要求涵盖从可行性分析到测试的全流程,具体包括:1.可行性分析2.需求分析3.UI/UX设计(使用ArkUI设计工具)4.代码实现(HarmonyOS4.0+,核心功能:用户登录、API数据展示、页面跳转交互)5.测试用例设计与bug修复根据引用内容,我们尤其要注意动画性能优化(引用[1][3][4])以及关键帧动画的实现(引用[2])。但用户问题更关注整体流程,因此我们将按步骤展开。步骤1:可行性分析-技术可行性:评估HarmonyOS提供的API和开发工具(如ArkUI、DevEcoStudio)是否支持所需功能。例如,用户登录需要网络和权限管理,数据展示需要列表组件和网络请求,页面跳转需要路由能力。-市场可行性:目标用户群体、设备覆盖(手机、平板、智慧屏等)。-资源可行性:开发团队技能、时间、预算。步骤2:需求分析-功能需求:用户登录(账号密码或第三方登录)、数据展示(从API获取数据并展示在列表或网格中)、页面跳转(如从登录页跳转到主页,从列表页跳转到详情页)。-非功能需求:性能(如动画流畅性,参考引用[3][4])、安全性(用户数据加密)、兼容性(HarmonyOS不同版本和设备)。步骤3:UI/UX设计-使用ArkUI设计工具(在DevEcoStudio中)进行界面设计。ArkUI提供声明式UI开发范式,支持组件化开发。-设计原则:简洁、一致、反馈及时(如交互动画)。注意动画性能优化(引用[1]提到:使用系统提供的动画接口,避免多次animateTo时统一更新状态变量等)。-设计步骤:原型设计(线框图)→视觉设计(颜色、字体、图标)→交互动画设计(如使用keyframeAnimateTo实现复杂动画,引用[2])。步骤4:代码实现(HarmonyOS4.0+)我们将分模块说明:4.1用户登录-使用`@ohos.net.http`发起网络请求。-使用`@ohos.security.huks`进行密码安全存储。-使用页面路由(`router`)跳转到主页。示例代码:```typescript//登录页面importrouterfrom'@ohos.router';importhttpfrom'@ohos.net.http';@Entry@ComponentstructLoginPage{@Stateusername:string='';@Statepassword:string='';build(){Column(){TextInput({placeholder:'用户名'}).onChange((value)=>{this.username=value;})TextInput({placeholder:'密码',type:InputType.Password}).onChange((value)=>{this.password=value;})Button('登录').onClick(()=>{this.login();})}}login(){lethttpRequest=http.createHttp();httpRequest.request("https://api.example.com/login",{method:http.RequestMethod.POST,header:{'Content-Type':'application/json'},extraData:JSON.stringify({username:this.username,password:this.password})},(err,data)=>{if(!err){//登录成功,跳转到主页router.pushUrl({url:'pages/HomePage'});}else{//处理错误}});}}```4.2API数据展示-使用`List`组件展示数据。-使用`http`模块获取数据。示例代码:```typescript@Entry@ComponentstructHomePage{@StatedataList:Array<Object>=[];onPageShow(){this.fetchData();}fetchData(){lethttpRequest=http.createHttp();httpRequest.request("https://api.example.com/data",(err,data)=>{if(!err){this.dataList=JSON.parse(data.resultasstring);}});}build(){List(){ForEach(this.dataList,(item)=>{ListItem(){Text(item.title).fontSize(20)}})}}}```4.3页面跳转交互-使用`router`模块进行页面跳转。-跳转时传递参数(如详情页的ID)。示例代码(在列表项点击时跳转):```typescript//在HomePage的List项中添加点击事件ListItem(){Text(item.title).fontSize(20)}.onClick(()=>{router.pushUrl({url:'pages/DetailPage',params:{id:item.id}});})```4.4动画优化(参考引用)-对于动画,优先使用系统提供的动画接口(如`animateTo`、`keyframeAnimateTo`)。-避免在多个动画闭包中更新状态变量,应尽量统一到一个闭包中(引用[3]表明:多个animateTo闭包会导致丢帧率更高)。-复杂动画使用关键帧动画(引用[2]示例)。步骤5:测试用例设计与bug修复-功能测试:用户登录(正确/错误凭证)、数据展示(空数据、大量数据)、页面跳转(参数传递)。-性能测试:使用Profiler工具检测丢帧率(引用[3])、内存占用、启动时间。-动画性能专项测试:确保动画流畅(参考引用[1][3][4]的优化建议)。-Bug修复:根据测试结果,定位问题(如动画卡顿可能是由于多次更新状态变量导致),应用优化措施(如统一动画更新、使用renderGroup等)。相关问题:1.鸿蒙应用开发中,如何处理用户登录的安全性?2.如何优化鸿蒙应用中列表的滚动性能?3.鸿蒙的关键帧动画(keyframeAnimateTo)与普通动画(animateTo)有何区别?</think>### 鸿蒙 HarmonyOS 应用开发全流程指南 #### 一、可行性分析 1. **技术可行性** - 确认 HarmonyOS 4.0+ 的核心能力支持: - ArkUI 声明式开发范式(支持高效 UI 渲染) - 分布式能力(跨设备协同) - 安全机制(生物识别、数据加密) - 验证目标功能实现路径: - 用户登录:依赖`@ohos.security.huks`(硬件密钥)和`@ohos.net.http`(网络请求) - API 数据展示:需评估`@ohos.data.preferences`(本地存储)与`Fetch API`兼容性 - 动画交互:优先使用系统动画接口(引用[1][4]) 2. **市场可行性** - 目标设备覆盖:手机/平板/智能穿戴(需适配不同屏幕尺寸) - 竞品分析:参考同类型鸿蒙应用的 UX 设计模式 #### 二、需求分析 1. **功能需求分解** ```mermaid graph LR A[核心功能] --> B[用户登录] A --> C[API数据展示] A --> D[页面跳转交互] B --> B1[账号密码登录] B --> B2[生物识别登录] C --> C1[列表渲染] C --> C2[下拉刷新] D --> D1[路由管理] D --> D2[转场动画] ``` 2. **非功能需求** - 性能:动画丢帧率 ≤5%(引用[3]) - 安全性:用户数据加密存储(HUKS 模块) - 兼容性:HarmonyOS 4.0~5.0 全版本覆盖 #### 三、UI/UX 设计 1. **ArkUI 设计工具使用** - **设计流程**: 1. 使用 DevEco Studio 的 **ArkUI 可视化布局器** 拖拽组件 2. 通过 `@Preview` 注解实时预览界面 3. 交互动画原型制作(推荐关键帧动画,引用[2][4]) - **设计规范**: - 响应式布局:使用 `Flex`/`Grid`/`MediaQuery` 适配多设备 - 动画优化:复杂动画优先选 `keyframeAnimateTo`(引用[2]) 2. **设计交付物** - 高保真原型(含交互流程图) - 设计规范文档(字体/色值/间距) #### 四、核心功能代码实现(HarmonyOS 4.0+) 1. **用户登录模块** ```typescript // 生物识别登录 import userAuth from '@ohos.userIAM.userAuth'; async function fingerprintLogin() { const auth = new userAuth.UserAuth(); const result = await auth.auth(userAuth.UserAuthType.FINGERPRINT, userAuth.AuthTrustLevel.ATL1); if (result.result === userAuth.AuthResult.SUCCESS) { router.replaceUrl({ url: 'pages/HomePage' }); // 页面跳转 } } ``` 2. **API 数据展示** ```typescript // 网络请求与列表渲染 import http from '@ohos.net.http'; import { ListItem } from '@ohos/arkui'; @State dataList: Array<Object> = []; fetchData() { let httpRequest = http.createHttp(); httpRequest.request('https://api.example.com/data', (err, data) => { if (!err) { this.dataList = JSON.parse(data.result as string); } }); } build() { List({ space: 12 }) { ForEach(this.dataList, (item) => { ListItem() { Text(item.title).fontSize(16) } }) } } ``` 3. **页面跳转与动画** ```typescript // 转场动画优化(引用[1][3]) import router from '@ohos.router'; @Entry @Component struct DetailPage { @State scaleVal: number = 0.5; build() { Column() { Text('详情页').scale({ x: this.scaleVal }) } .onClick(() => { // 统一动画闭包优化性能(引用[3]) animateTo({ duration: 300 }, () => { this.scaleVal = 1; router.back(); }) }) } } ``` #### 五、测试与优化 1. **测试用例设计** | 模块 | 测试用例 | 预期结果 | |-------------|--------------------------|-----------------------| | 用户登录 | 错误密码连续输入5次 | 触发账户锁定机制 | | API展示 | 模拟网络延迟500ms | 显示加载动画无卡顿 | | 页面跳转 | 快速连续点击跳转按钮 | 无页面堆叠/路由混乱 | 2. **Bug 修复方案** - **动画卡顿问题**: - 使用 `renderGroup` 合并渲染操作(引用[1]) - 避免在循环中调用 `animateTo`(引用[3]) - **数据加载白屏**: - 添加 `Skeleton` 骨架屏占位 - 使用 `@ohos.distributedDataManager` 缓存数据 #### 六、交付与上架 1. 通过 **DevEco Studio** 生成 `.hap` 安装包 2. 提交至 [AppGallery Connect](https://developer.huawei.com/consumer/cn/service/) 审核 3. 监控线上崩溃日志(集成 `HiQ` 性能分析工具) ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值