栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Common-Annotation

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Common-Annotation

文章目录
  • 一 项目概述
    • 1 设计思想
    • 2 项目结构
  • 二 注解使用
    • 1 环境配置
      • 1.1 注册中心
      • 1.2 调用方式
    • 2 添加注解
      • 2.1 @Email
      • 2.2 @SMS
      • 2.3 @Message
    • 3. 属性配置
      • 3.0 type
      • 3.1 value
      • 3.2 feignName
      • 3.3 feignIP
      • 3.4 msMethod
      • 3.5 sendConfig
      • 3.6 callWay
    • 3 实战案例
    • 4 注意事项
      • 4.1 mybatis-plus 版本
      • 4.2 AOP代理生成-循环依赖
  • 三 注解开发
    • 1 项目结构
    • 2 执行流程
      • 2.1 触发器: AOP
      • 2.2 调度器: Dispatcher
      • 2.2 映射器: Mapping
      • 2.3 适配器: Adapter
      • 2.4 处理器: Handler
      • 2.5 解析器: Resolve
  • 四 后续开发
    • 1 写表日志
    • 2 邮件附件
    • 3 定时+异步调用
    • 4 集成消息队列
    • 5 配置调用
    • 6 增删改查开发
  • 后记

一 项目概述 1 设计思想

2 项目结构

二 注解使用
1 环境配置
1.1 注册中心
  1. Eureka

(1) pom.xml 依赖


     org.springframework.cloud
     spring-cloud-starter-netflix-eureka-client

(2) 依赖管理器


     
         
              org.springframework.cloud
              spring-cloud-dependencies
              Hoxton.SR1
              pom
              import
         
     

(3) application.properties

spring.application.name=Message-ann
eureka.client.service-url.defaultZone=http://localhost:8000/eureka/
spring.main.allow-bean-definition-overriding=true
  1. Nacos

(1) pom.xml 依赖


     com.alibaba.cloud
     spring-cloud-starter-alibaba-nacos-discovery
     2.2.3.RELEASE

(2) 依赖管理器


     
         
              org.springframework.cloud
              spring-cloud-dependencies
              Hoxton.SR1
              pom
              import
         
     

(3) application.properties

spring.application.name=Message-ann
spring.main.allow-bean-definition-overriding=true
# discovery
spring.cloud.nacos.discovery.server-addr=10.22.50.72:31504
#spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
spring.cloud.nacos.discovery.enabled=true
spring.cloud.nacos.discovery.namespace=a5447a9d-28e9-41c2-b5eb-8f795b17bc8f
spring.cloud.nacos.discovery.group=DEV

(4) 启动类上

@ComponentScan(basePackages={"com.boss.**","cn.**","com.sunline.ms.**"})
@EnableFeignClients(basePackages = "com.sunline.ms.feign.**")
@EnableDiscoveryClient
@RefreshScope
1.2 调用方式
  1. Ribbon

  2. Openfeign


     org.springframework.cloud
     spring-cloud-starter-openfeign

2 添加注解

注解体系:

2.1 @Email
  • 发送邮件
	@Email
    public SmsDto addEmail(SmsDto smsVo) {
    	//处理....
        return smsDto;
    }
2.2 @SMS
  • 发送短信
	@SMS
    public SmsDto addSMS(SmsDto smsVo) {
    	//处理....
        return smsDto;
    }
2.3 @Message
  • 配置发送类型
	@Message(type = MessageType.Email)
    private SmsDto b(){

    }
3. 属性配置

属性体系:

3.0 type
  1. 发送邮件

  2. 发送短信

	@Message(type = MessageType.Email)
    @Message(type = MessageType.SMS)
3.1 value
  1. 调用服务名
	@Message(value = "boss-sms")
3.2 feignName
  1. 调用服务名
    @Message(feignName = "boss-sms")
3.3 feignIP
  1. 调用服务URL: IP+端口+路径
    @Message(feignIP = "127.0.0.1:8080/123")
3.4 msMethod
  1. 增删改查
    @Message(msMethod = MSMethod.ADD_MS)
    @Message(msMethod = MSMethod.DELETE_MS)
    @Message(msMethod = MSMethod.UPDATE_MS)
    @Message(msMethod = MSMethod.SELECT_MS)
3.5 sendConfig
  1. 异步
  2. 定时
  3. 异步+定时
    @Message(sendConfig = SendConfig.ASYNC)
    @Message(sendConfig = SendConfig.SCHEDULING)
    @Message(sendConfig = SendConfig.ASYNC_SCHEDULING)
3.6 callWay
  1. OpenFeign
  2. Ribbon+RestTemplate
    @Message(callWay = CallWay.OpenFeign)
    @Message(callWay = CallWay.Ribbon_Rest)
3 实战案例

架构调整-通知org2100025-文档

(1) controller

@ApiOperation(value = "架构调整通知", notes = "架构调整通知")
@PostMapping("/org/org210025")
public ResponseResult mailArchitectAdjNoticeController(@RequestBody FlowArchitectAdjNoticeVo flowArchitectAdjNoticeVo) {
    flowArchitectADJNoticeService.mailSend(flowArchitectAdjNoticeVo.getDocNo());
    return result();
}

(2) service

  • 版本1
@Override
@Email
public SmsDto mailSend(String docNo) {
  //查询内容-->set
  SmsDto smsDto = new SmsDto();
  FlowArchitectAdjNotice one = this.getOne(new QueryWrapper().lambda().eq(FlowArchitectAdjNotice::getDocNo, docNo));
  smsDto.setSubject(one.getTitle());
  smsDto.setMessageType("email");
  smsDto.setSourceService("ERP");
  ArrayList strings = new ArrayList<>();

  List flowArchitectAdjNoticeEmplyList = flowArchitectADJNoticeEmplyService.list(new QueryWrapper().lambda().eq(FlowArchitectAdjNoticeEmply::getDocNo, docNo));
  for (FlowArchitectAdjNoticeEmply flowArchitectAdjNoticeEmply : flowArchitectAdjNoticeEmplyList) {
  Emplybase i = emplybaseService.getOne(new QueryWrapper().lambda().eq(Emplybase::getEmplyNo, flowArchitectAdjNoticeEmply.getEmplyNo()));
  strings.add(i.getCorpMail());
  }
  smsDto.setMailReceiver(strings.toArray(new String[strings.size()]));
  String url = serverFileHost+":"+serverFilePort;
  StringBuffer buffer = new StringBuffer();
  List commonFileRelationshipList = commonFileRelationshipService.list(new QueryWrapper().lambda().eq(CommonFileRelationship::getBusinessValue1, docNo));
  for (CommonFileRelationship commonFileRelationship : commonFileRelationshipList) {
  SysFileInfo byId = sysFileInfoService.getById(commonFileRelationship.getSysFileInfoId());
  buffer.append(url);
  buffer.append(byId.getFilePath()+byId.getFileName()+byId.getFileSuffix());
  buffer.append(",");
  }
  smsDto.setContent(one.getNoticeContent()+"n"+"n"+buffer);
  return smsDto;
}


  • 版本2
@Autowired
FlowArchitectADJNoticeService flowArchitectADJNoticeService;
@Override
public void mailSend(String docNo) {
    //查询内容-->set
    SmsDto smsDto = new SmsDto();
    FlowArchitectAdjNotice one = this.getOne(new QueryWrapper().lambda().eq(FlowArchitectAdjNotice::getDocNo, docNo));
    smsDto.setSubject(one.getTitle());
    smsDto.setMessageType("email");
    smsDto.setSourceService("ERP");
    ArrayList strings = new ArrayList<>();

    List flowArchitectAdjNoticeEmplyList = flowArchitectADJNoticeEmplyService.list(new QueryWrapper().lambda().eq(FlowArchitectAdjNoticeEmply::getDocNo, docNo));
    for (FlowArchitectAdjNoticeEmply flowArchitectAdjNoticeEmply : flowArchitectAdjNoticeEmplyList) {
        Emplybase i = emplybaseService.getOne(new QueryWrapper().lambda().eq(Emplybase::getEmplyNo, flowArchitectAdjNoticeEmply.getEmplyNo()));
        strings.add(i.getCorpMail());
    }
    smsDto.setMailReceiver(strings.toArray(new String[strings.size()]));
    String url = serverFileHost+":"+serverFilePort;
    StringBuffer buffer = new StringBuffer();
    List commonFileRelationshipList = commonFileRelationshipService.list(new QueryWrapper().lambda().eq(CommonFileRelationship::getBusinessValue1, docNo));
    for (CommonFileRelationship commonFileRelationship : commonFileRelationshipList) {
        SysFileInfo byId = sysFileInfoService.getById(commonFileRelationship.getSysFileInfoId());
        buffer.append(url);
        buffer.append(byId.getFilePath()+byId.getFileName()+byId.getFileSuffix());
        buffer.append(",");
    }

    smsDto.setContent(one.getNoticeContent()+"n"+"n"+buffer);
    //调发送方法
    Object o = flowArchitectADJNoticeService.messageSend(smsDto);
}
@Email
public SmsDto messageSend(SmsDto smsDto) {
    //抽取~公共处理/最后处理
    return smsDto;
}
4 注意事项 4.1 mybatis-plus 版本

版本: 3.4.3–>3.4.1

4.2 AOP代理生成-循环依赖
  1. AOP原理

调用代理对象的增强方法

  1. JDK代理与CGLib代理

  2. this调用无效

@Override
public void mailSend(String docNo) {
    //业务逻辑
        ...
    //调发送方法
    Object o = this.messageSend(smsDto);
}
@Override
public void mailSend(String docNo) {
    //业务逻辑
        ...
    //调发送方法
    Object o = flowArchitectADJNoticeService.messageSend(smsDto);
}
  1. 获取代理对象

this不是代理对象,需要在spring容器重新获取

(1) 循环依赖

用Autowired 注入自身的实例

@Autowired
FlowArchitectADJNoticeService flowArchitectADJNoticeService;

(2) ApplicationContext获取增强后的实例引用

@Autowired
private ApplicationContext applicationContext;
applicationContext.getBean(FlowArchitectADJNoticeService.class);

(3) AopContext获取增强后的实例引用

(FlowArchitectADJNoticeService)AopContext.currentProxy();
@EnableAspectJAutoProxy(exposeProxy = true)
//启动类
三 注解开发

开发顺序

1 项目结构

2 执行流程


2.1 触发器: AOP

注册触发器

	@Pointcut("@annotation(com.sunline.ms.annotation.AEmail.Email)")
    public void pointcut() {
    }
2.2 调度器: Dispatcher

链式调用: 映射器–>适配器–>处理器–>解析器

//链式调用
    @Around(value = "@annotation(com.sunline.ms.annotation.AEmail.Email)")
    public Object aroundEmail(ProceedingJoinPoint joinPoint){
        try {
            EmailConfigStream emailConfigStream = new EmailConfigStream();
            emailConfigStream.setType(MessageType.Email);
            EmailServerBean emailServerBean = new EmailServerBean(null,emailConfigStream,joinPoint);
            //配置读取-->参数校验-->调度执行-->参数封装-->解析返回
            emailServerBean.handlerMappingAOP().handlerAdapterAOP().HandlerAOP().resolverAOP();
            //返回!=null正常
            return emailServerBean.getSmsDto();

        }catch (Throwable throwable){
            throwable.printStackTrace();
            return null;
        }
    }
2.2 映射器: Mapping

注解配置映射–>ConfigBean

	public void readConfig(baseServerBean baseServerBean) {

        //获取参数
        Method method = this.getConfig(baseServerBean.getJoinPoint());
        //注入参数
        if (method!=null)
        this.setConfig(baseServerBean.getbaseConfigStream(),method);
    }
private Method getConfig(ProceedingJoinPoint joinPoint) {
        
        Object[] args = joinPoint.getArgs();
        Class[] argTypes = new Class[joinPoint.getArgs().length];
        for (int i = 0; i < args.length; i++) {
            argTypes[i] = args[i].getClass();
        }
        Method method = null;
        try {
            method = joinPoint.getTarget().getClass()
                    .getMethod(joinPoint.getSignature().getName(), argTypes);
            return method;
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
            return null;
        } catch (SecurityException e) {
            e.printStackTrace();
            return null;
        }
    }
    private void setConfig(baseConfigStream baseConfigStream, Method method) {
        if (baseConfigStream.getType().equals(MessageType.Email)){
            Email email= method.getAnnotation(Email.class);
            baseConfigStream.setValue(email.value());
            baseConfigStream.setType(email.type());
            baseConfigStream.setSendConfig(email.sendConfig());
            baseConfigStream.setCallWay(email.callWay());
            baseConfigStream.setFeignName(email.feignName());
            baseConfigStream.setFeignIP(email.feignIP());
            baseConfigStream.setMsMethod(email.msMethod());

        }else if(baseConfigStream.getType().equals(MessageType.SMS)){
            SMS sms = method.getAnnotation(SMS.class);
            baseConfigStream.setValue(sms.value());
            baseConfigStream.setType(sms.type());
            baseConfigStream.setSendConfig(sms.sendConfig());
            baseConfigStream.setCallWay(sms.callWay());
            baseConfigStream.setFeignName(sms.feignName());
            baseConfigStream.setFeignIP(sms.feignIP());
            baseConfigStream.setMsMethod(sms.msMethod());
        }else {
            Message message = method.getAnnotation(Message.class);
            baseConfigStream.setValue(message.value());
            baseConfigStream.setType(message.type());
            baseConfigStream.setSendConfig(message.sendConfig());
            baseConfigStream.setCallWay(message.callWay());
            baseConfigStream.setFeignName(message.feignName());
            baseConfigStream.setFeignIP(message.feignIP());
            baseConfigStream.setMsMethod(message.msMethod());
        }
    }
2.3 适配器: Adapter

反射注入ConfigBean配置

	public void paramReflect(baseServerBean baseServerBean) {
        try {
            //反射改变FeignName:-value
            changeFeignName(baseServerBean.getbaseConfigStream().getFeignName());
            //反射改变FeignIp
            //changeFeignIp(baseServerBean.getbaseConfigStream().getFeignIP());
            //反射改变调用方式:
            //changeFeignCallWay(baseServerBean.getbaseConfigStream().getCallWay());
        }catch (Exception e){
            e.printStackTrace();
        }
    }
    private void changeFeignName(String feignName) throws NoSuchFieldException, IllegalAccessException {
        Field nameField = FeignClientConfig.class.getDeclaredField("NAME");
        nameField.setAccessible(true);
        //去掉final
        Field modifiers = nameField.getClass().getDeclaredField("modifiers");
        modifiers.setAccessible(true);
        modifiers.setInt(nameField, nameField.getModifiers() & ~Modifier.FINAL);
        //填写配置
        nameField.set(null,feignName);
        //加上final
        modifiers.setInt(nameField, nameField.getModifiers() & ~Modifier.FINAL);
        //查看结果
        System.out.println("------------------------");
        System.out.println(FeignClientConfig.NAME);
        System.out.println("------------------------");

    }
    private void changeFeignCallWay(CallWay callWay) {

    }

    private void changeFeignIp(String feignIP) {

    }


2.4 处理器: Handler

调用OpenFeign接口

	public SmsDto executeMethod(baseServerBean baseServerBean) throws Throwable {
        //-----------------------
        //根据ConfigStream选择执行
        //-----------------------

        //执行方法
        Object o=baseServerBean.getJoinPoint().proceed();//目标方法
        //根据ConfigStream.method+sendConfig判断
        MSMethod msMethod = baseServerBean.getbaseConfigStream().getMsMethod();
        CommonSmsFeign commonSmsFeign = SpringUtils.getBean(CommonSmsFeign.class);
        switch (baseServerBean.getbaseConfigStream().getMsMethod()) {
            case ADD_MS: {
                System.out.println("ADD_MS");
                if (o instanceof SmsDto) commonSmsFeign.addMs((SmsDto) o);
                break;
            }
            case UPDATE_MS: {
                System.out.println("UPDATE_MS");
                break;
            }
            case DELETE_MS: {
                System.out.println("DELETE_MS");
                break;
            }
            case SELECT_MS: {
                System.out.println("SELECT_MS");
                break;
            }
            default: {

            }
        }
        return (SmsDto) o;
    }
2.5 解析器: Resolve

处理返回结果

	public void returnDto(baseServerBean baseServerBean) {
    }

四 后续开发 1 写表日志
  • 方案一
  • 方案二
2 邮件附件

DTO加附件

3 定时+异步调用

调用者业务

  • 例子
@Scheduled(cron = "0 30 0 * * ? *")
@Async
@Email
public SmsDto messageSend(SmsDto smsDto) {
       return smsDto;
}
4 集成消息队列

异步、解耦、消峰

5 配置调用
  • openfigname+ip+多例

问题1 : 暴力反射无效?
问题2 :Openfeign单例–>多例加载

  • ribbon调用方式配置调用
6 增删改查开发

@增删改查Email
@增删改查SMS

后记

注解模块再抽象–>开发注解框架

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/696513.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号