实际项目中我们可以用自定义注解解决很多事情!
解决业务分发
最近在做的一个项目,对接科大讯飞语音平台,他们平台上面的调用地址只能填一个,所以我项目上需要做到一个接口处理很多业务场景,如果我用传统方式处理,那么我可能需要些大量的if else或者switch等语法糖,这里我们可以使用自定义注解解决,废话少说直接上代码。
- 首先创建我们的自定义注解
- 控制器/类注解,注解到类上面 ,用于我们查找我们需要的类
package com.jx.fly.common.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 控制器注解
*
* @author xiaojian
* @date 2019/5/9
**/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface ControllerAnnotation {
}
- 方法注解,注解到方法上面,用于找到我们需要的方法,这里我们加上标识值
package com.jx.fly.common.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 方法注解
*
* @author xiaojian
* @date 2019/5/9
**/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MethodAnnotation {
String value();
}
- 创建方法缓存类,我们的系统启动的时候就将我们加了注解的的方法保存到这个类里面,以便我们使用标识值去获取调用
package com.jx.fly.main.model.method;
import lombok.Data;
import java.lang.reflect.Method;
/**
* @author xiaojian
* @description
* @date 2019/5/9
**/
@Data
public class MethodObj {
private Method method;
private Object obj;
}
- 创建系统启动监听类,这里的主要作用就是在系统启动的时候通过我们的自定义注解找到我们需要的方法保存到上一步的MethodObj模型里面
package com.jx.fly.common.listener;
import com.jx.fly.common.annotation.ControllerAnnotation;
import com.jx.fly.common.annotation.MethodAnnotation;
import com.jx.fly.common.cache.MethodCache;
import com.jx.fly.main.model.method.MethodObj;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.lang.reflect.Method;
import java.util.Map;
/**
* @author xiaojian
* @description 系统启动监听
* @date 2019/4/29
**/
@Service
@Transactional(rollbackFor = Exception.class,readOnly = true)
public class SysStartListener implements CommandLineRunner, ApplicationContextAware {
private ApplicationContext applicationContext;
@Value(value = "${websocket.port}")
private int webSocketPort;
@Override
public void run(String... args) throws Exception {
this.loadAnnotation();
}
public void loadAnnotation() {
Map<String, Object> map = applicationContext.getBeansWithAnnotation(ControllerAnnotation.class);
if (map == null) {
return;
}
for (Object obj : map.values()) {
for (Method method : obj.getClass().getMethods()) {
if (method.isAnnotationPresent(MethodAnnotation.class)) {
String cmd = method.getAnnotation(MethodAnnotation.class).value();
MethodObj ref = new MethodObj();
ref.setMethod(method);
ref.setObj(obj);
MethodCache.setMethod(cmd, ref);
}
}
}
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
}
- 创建接收任务的类,也就是我们的业务处理类,根据业务量的大小自行增加,这里的方法标识值取的是1,根据业务自行的换成枚举类即可
package com.jx.fly.module.controller;
import com.jx.fly.common.annotation.ControllerAnnotation;
import com.jx.fly.common.annotation.MethodAnnotation;
import com.jx.fly.common.enums.SocketCommandEnum;
import com.jx.fly.common.result.ResultModel;
import com.jx.fly.common.utils.ResponseUtil;
import com.jx.fly.main.model.req.ReqModel;
import com.jx.smart.common.model.labor.attendance.project.LaborProjectConfigModel;
import org.springframework.stereotype.Component;
import static com.jx.fly.common.enums.MethodCommandEnum.*;
/**
* 业务1
*
* @author zhongxiaojian
* @date 2019-05-18
**/
@ControllerAnnotation()
@Component
public class ExitController {
/**
* @param body
* @return
*/
@MethodAnnotation("1")
public Object count(String body){
//业务的处理......
return null;
}
}
- 创建分发任务的类,也就是唯一入口
package com.jx.fly.main.controller;
import cn.hutool.log.StaticLog;
import com.alibaba.fastjson.JSON;
import com.jx.fly.common.annotation.SignAnnotation;
import com.jx.fly.common.cache.MethodCache;
import com.jx.fly.common.utils.ResponseUtil;
import com.jx.fly.main.model.method.MethodObj;
import com.jx.fly.main.model.req.ReqModel;
import com.jx.fly.module.mapper.LaborProjectConfigMapper;
import com.jx.smart.common.model.labor.attendance.project.LaborProjectConfigModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import java.lang.reflect.InvocationTargetException;
/**
* 业务入口
* @author xiaojian
* @date 2019/5/8
**/
@RestController
@RequestMapping("/fly")
public class MainController {
@Value("${enableTest}")
private boolean enableTest;
@Autowired
private LaborProjectConfigMapper laborProjectConfigMapper;
/**
* 业务处理分发
* @param signature
* @param body
* @return
*/
@PostMapping("/main")
public Object handle(@RequestHeader("Signature") String signature,
@RequestBody String body){
//业务分发
MethodObj ref = MethodCache.getMethod("1");
try {
LaborProjectConfigModel laborProjectConfigModel = laborProjectConfigMapper.selectById(projectId);
return ref.getMethod().invoke(ref.getObj(),body);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return null;
}
}