下拉框选择自定义的方法,然后去反射
定义注解类
@Documented
@Retention(RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD })//作用在类和方法上
public @interface YjsOutWay
{
String wayName() default "";
// 注解说明
// https://blog.csdn.net/javazejian/article/details/71860633
}
相关类和方法加注解
@Service
@YjsOutWay
public class ZgYjsOutWayService
{
private ZgYjsCommonService zgYjsCommonService = ContainerFactory.getContainInfo().getComponent(ZgYjsCommonService.class);
@YjsOutWay(wayName = "通用业务信息保存")
public JSONObject saveCommonYw(String param) {
JSONObject jsonObject = JSONObject.fromObject(param);
String userGuids = jsonObject.optString("userguids");
if (StringUtil.isBlank(userGuids)) {
return null;
}
if (userGuids.endsWith(",")) {
userGuids = userGuids.substring(0, userGuids.length() - 1);
}
String joinPoliceType = jsonObject.optString("joinpolicetype");
return zgYjsCommonService.saveCommonYw(userGuids, joinPoliceType);
}
}
获取包下所有加了注解的类
public class HrClassUtil extends ClassUtil
{
private static final Logger log = LoggerFactory.getLogger(HrClassUtil.class);
/**
* 静态缓存所有包下的class
*/
private static List<Class<?>> allGaClass = null;
/**
* 默认包路径
*/
public static String DefaultPackageName = "com.xx.xx";
/***
* 获取到包路径下class自身、子类、实现类
*
* @param c
* @param packageName
* @return
*/
@SuppressWarnings({"unchecked", "rawtypes" })
public static List<Class> getAllClassByInterface(Class c, String packageName) {
// log.info("getAllClassByInterface:" + c + "=======" + packageName);
// 返回的classList
List<Class> returnClassList = new ArrayList<>();
// 不是接口,或者包路径为空
if (!c.isInterface() || StringUtil.isBlank(packageName)) {
log.info("包路径为空,class非接口");
return returnClassList;
}
// 扫描到的class
List<Class<?>> searchClass = null;
// 如果类名就是全路径,静态缓存,再赋值
if (DefaultPackageName.equals(packageName)) {
// 初始化 路径下的所有类
if (allGaClass == null) {
// 第一次的时候,缓存所有
allGaClass = HrClassUtil.getClasses(DefaultPackageName);
}
searchClass = allGaClass;
}
else {
// 获取包下面的类
searchClass = HrClassUtil.getClasses(packageName);
}
if (CollectionUtils.isEmpty(searchClass)) {
return returnClassList;
}
Iterator<Class<?>> var4 = searchClass.iterator();
while (var4.hasNext()) {
Class<T> classes = (Class) var4.next();
// c是的classes父类 && !c.equals(classes)
if (c.isAssignableFrom(classes) && !c.equals(classes)) {
returnClassList.add(classes);
}
}
return returnClassList;
}
/**
* 获取包下面所有具XX注解的类
*
* @param c
* @param packageName
* @return
*/
@SuppressWarnings({"unchecked", "rawtypes" })
public static Set<Class<?>> getAllClassByTypeAnnotation(Class annotationCls, String packageName) {
// log.info("getAllClassByTypeAnnotation:" + annotationCls + "=======" + packageName);
// 要扫描的包名
Reflections f = new Reflections(packageName);
// 目标注解类
// Set<Class<?>> set = f.getTypesAnnotatedWith(annotationCls);
return f.getTypesAnnotatedWith(annotationCls);
}
}
获取加了注解的方法,和反射的工具类
public class ZgYjsUtil
{
/**
* 静态缓存包下的方法
*/
private static List<Record> allMenthodList = null;
public static final String packageName = "com.xx.xx";
/**
* 通过反射信息获取方法执行后的结果
*
* @param reflectInfo
* 例如:com.xxx.className.methodName
* @return 反射方法获取的结果,获取不到结果则返回空
*/
public static String getReflect(String reflectInfo, Object... args) {
int index = reflectInfo.lastIndexOf('.');
if (index == -1) {
throw new IllegalArgumentException("反射信息格式不正确!");
}
String signature = reflectInfo;
try {
Object o = ReflectUtils.newInstance(Class.forName(signature.substring(0, index)));
Object value = null;
if (args == null || args.length == 0) {
Method method = ReflectUtils.findMethod(signature);
value = method.invoke(o);
}
else {
// 获取带多个参数
signature += "(String)";
Method method = ReflectUtils.findMethod(signature);
value = method.invoke(o, args);
}
if (value == null) {
return "";
}
return value.toString();
}
catch (Exception e) {
return "";
}
}
// 调用
// getYjsOutWayListByType("com.xx");
/**
* 获取类下的所有具有YjsOutWay注解的方法
*
* @param typeClass
* @param annotationClass
* @return
*/
@SuppressWarnings("rawtypes")
public static List<Record> getYjsOutWayListByType(String packageName) {
List<Record> recordList = new ArrayList<>();
// 全局缓存,已有就不查
if (CollectionUtils.isNotEmpty(allMenthodList)) {
recordList = allMenthodList;
return recordList;
}
Set<Class<?>> yjsTypeClass = HrClassUtil.getAllClassByTypeAnnotation(YjsOutWay.class, packageName);
if (CollectionUtils.isNotEmpty(yjsTypeClass)) {
for (Class<?> yjsClass : yjsTypeClass) {
recordList.addAll(getMenthByYjsAnnotation(yjsClass));
}
}
allMenthodList = recordList;
return recordList;
}
/**
* 获取类下的所有具有YjsOutWay注解的方法
*
* @param typeClass
* @param annotationClass
* @return
*/
@SuppressWarnings("rawtypes")
public static List<Record> getMenthByYjsAnnotation(Class typeClass) {
// 获取当前类所有方法
List<Record> recordList = new ArrayList<>();
Method[] declaredMethods = typeClass.getDeclaredMethods();
if (declaredMethods != null && declaredMethods.length > 0) {
for (Method method : declaredMethods) {
// 获取当前类有注解的方法
if (method.isAnnotationPresent(YjsOutWay.class)) {
YjsOutWay annotation = method.getAnnotation(YjsOutWay.class);
Record record = new Record();
record.set("path", method.getDeclaringClass().getName() + "." + method.getName());
record.set("name", annotation.wayName() + "[" + record.get("path") + "]");
recordList.add(record);
}
}
}
return recordList;
}
}
找所有实现此接口的所有实现类
public class HrInterfaceUtil
{
private static final Logger log = Logger.getLogger(HrInterfaceUtil.class);
/**
* 获取自定义并实现HrCustom注解的class
*
* @author YHH
* @param clazz
* @packagePath 【com.xx.xx.hr.annotation】
* @return
*/
@SuppressWarnings({"rawtypes", "unchecked" })
public static <T> T getCustomizeClass(Class<?> clazz, String packagePath) {
// 返回的class
T resultClass = null;
if (StringUtil.isBlank(packagePath)) {
return null;
}
// 获取clazz的所有接口实现类xx
List<Class> interfaceClassList = HrClassUtil.getAllClassByInterface(clazz, packagePath);
if (CollectionUtils.isEmpty(interfaceClassList)) {
// log.error("#####未发现相关类#####");
return resultClass;
}
// 是否有注解判断
int customizeNum = 0;
try {
for (Class<T> cls : interfaceClassList) {
// 加了注解
// 判断该实现类是否有注解
HrCustom hrCustom = cls.getAnnotation(HrCustom.class);
// 给resultClass 定义一个初始的实体类
if (resultClass == null) {
// 默认产品的
resultClass = cls.newInstance();
}
if (hrCustom != null) {
resultClass = cls.newInstance();
customizeNum++;
}
}
if (customizeNum > 1) {
log.error("#####该接口的个性化实现类超过一个,无法确认哪一个,请确定接口实现是否正确#####");
return null;
}
return resultClass;
}
catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 获取自定义的class,默认自身接口
*
* @author xx
* @param clazz
* @packagePath 【com.xx.xx.hr.annotation】
* @return
*/
@SuppressWarnings({"rawtypes", "unchecked" })
public static <T> T getCustomImplClass(Class<?> clazz, String packagePath) {
try {
// 返回的class,默认自身
T resultClass = null;
if (StringUtil.isBlank(packagePath)) {
return resultClass;
}
// 获取clazz的所有接口实现类【产品自身的,项目个性化的】
List<Class> interfaceClassList = HrClassUtil.getAllClassByInterface(clazz, packagePath);
if (CollectionUtils.isEmpty(interfaceClassList)) {
log.error("#####未发现相关类#####");
return resultClass;
}
int customizeNum = 0;
for (Class<T> cls : interfaceClassList) {
resultClass = cls.newInstance();
customizeNum++;
}
if (customizeNum > 1) {
log.error("#####该接口的个性化实现类超过一个,无法确认哪一个,请确定接口实现是否正确#####");
return resultClass;
}
return resultClass;
}
catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
AOP
AOP的基本概念
Advice(通知、切面): 某个连接点所采用的处理逻辑,也就是向连接点注入的代码, AOP在特定的切入点上执行的增强处理。
1.1 @Before: 标识一个前置增强方法,相当于BeforeAdvice的功能.
1.2 @After: final增强,不管是抛出异常或者正常退出都会执行.
1.3 @AfterReturning: 后置增强,似于AfterReturningAdvice, 方法正常退出时执行.
1.4 @AfterThrowing: 异常抛出增强,相当于ThrowsAdvice.
1.5 @Around: 环绕增强,相当于MethodInterceptor.
JointPoint(连接点):程序运行中的某个阶段点,比如方法的调用、异常的抛出等。
Pointcut(切入点): JoinPoint的集合,是程序中需要注入Advice的位置的集合,指明Advice要在什么样的条件下才能被触发,在程序中主要体现为书写切入点表达式。
Advisor(增强): 是PointCut和Advice的综合体,完整描述了一个advice将会在pointcut所定义的位置被触发。
@Aspect(切面): 通常是一个类的注解,里面可以定义切入点和通知
AOP Proxy:AOP框架创建的对象,代理就是目标对象的加强。Spring中的AOP代理可以使JDK动态代理,也可以是CGLIB代理,前者基于接口,后者基于子类
原文链接:https://blog.csdn.net/baidu_37366055/article/details/109989145
由下列方式来定义或者通过 &&、 ||、 !、 的方式进行组合:
execution:用于匹配方法执行的连接点;
within:用于匹配指定类型内的方法执行;
this:用于匹配当前AOP代理对象类型的执行方法;注意是AOP代理对象的类型匹配,这样就可能包括引入接口也类型匹配;
target:用于匹配当前目标对象类型的执行方法;注意是目标对象的类型匹配,这样就不包括引入接口也类型匹配;
args:用于匹配当前执行的方法传入的参数为指定类型的执行方法;
@within:用于匹配所以持有指定注解类型内的方法;
@target:用于匹配当前目标对象类型的执行方法,其中目标对象持有指定的注解;
@args:用于匹配当前执行的方法传入的参数持有指定注解的执行;
@annotation:用于匹配当前执行方法持有指定注解的方法;
eg.
任意公共方法的执行:execution(public * (…))
任何一个以“set”开始的方法的执行:execution( set*(…))
AccountService 接口的任意方法的执行:execution(* com.xyz.service.AccountService.(…))
定义在service包里的任意方法的执行: execution( com.xyz.service…(…))
定义在service包和所有子包里的任意类的任意方法的执行:execution(* com.xyz.service….(…))
第一个表示匹配任意的方法返回值, …(两个点)表示零个或多个,第一个…表示service包及其子包,第二个表示所有类, 第三个表示所有方法,第二个…表示方法的任意参数个数
定义在pointcutexp包和所有子包里的JoinPointObjP2类的任意方法的执行:execution( com.test.spring.aop.pointcutexp…JoinPointObjP2.(…))")
pointcutexp包里的任意类: within(com.test.spring.aop.pointcutexp.)
pointcutexp包和所有子包里的任意类:within(com.test.spring.aop.pointcutexp…*)
实现了Intf接口的所有类,如果Intf不是接口,限定Intf单个类:this(com.test.spring.aop.pointcutexp.Intf)
当一个实现了接口的类被AOP的时候,用getBean方法必须cast为接口类型,不能为该类的类型
带有@Transactional标注的所有类的任意方法:
@within(org.springframework.transaction.annotation.Transactional)
@target(org.springframework.transaction.annotation.Transactional)
带有@Transactional标注的任意方法:@annotation(org.springframework.transaction.annotation.Transactional)
@within和@target针对类的注解,@annotation是针对方法的注解
参数带有@Transactional标注的方法:@args(org.springframework.transaction.annotation.Transactional)
参数为String类型(运行是决定)的方法: args(String)
基于注解的AOP
@Documented
@Retention(RUNTIME)
@Target(ElementType.TYPE)
public @interface VerifyEncryptionConfig
{
}
编写切面
@Aspect
@Component
public class VerifyEncryptionAspect
{
@Pointcut("@within(com.xx.xx.zx.server.restful.rest.VerifyEncryptionConfig)")
public void doVerifyEncryption() {
}
/**
* 标识一个前置增强方法,相当于BeforeAdvice的功能(执行rest接口前相关处理)
*
* author wgd
*
* @param joinPoint
*/
@Before(value = "doVerifyEncryption()")
public void doBefore(JoinPoint joinPoint) {
// 输入的激活码
String cdkeyInput = PVerifyEncryptionUtil.getEncryptionNumber();
if (StringUtil.isBlank(cdkeyInput)) {
ApiBaseController.buildErrorResponse("激活码验证失败!注册码为:" + PVerifyEncryptionUtil.getMainboardEncryption(PVerifyEncryptionUtil.SCENE_NUMBER));
throw new ParamCheckException("激活码验证失败!注册码为:" + PVerifyEncryptionUtil.getMainboardEncryption(PVerifyEncryptionUtil.SCENE_NUMBER));
}
// 生成的激活码
String cdkReal = PVerifyEncryptionUtil.getFinalEncryptionNumber(PVerifyEncryptionUtil.SCENE_NUMBER);
if (!cdkeyInput.equals(cdkReal)) {
ApiBaseController.buildErrorResponse("激活码验证失败!注册码为:" + PVerifyEncryptionUtil.getMainboardEncryption(PVerifyEncryptionUtil.SCENE_NUMBER));
throw new ParamCheckException("激活码验证失败!注册码为:" + PVerifyEncryptionUtil.getMainboardEncryption(PVerifyEncryptionUtil.SCENE_NUMBER));
}
}
}
使用切面
@VerifyEncryptionConfig
@RestController
@RequestMapping("/xxserver")
public class PFdOutServer
{
private static final Logger log = Logger.getLogger(PFdOutServer.class);
/**
* 心跳检测
*/
@GetMapping("/ping")
public PResponse ping() {
log.debug("心跳检测");
return PResponse.success();
}
}
加解密注册码实现
public class PVerifyEncryptionUtil
{
private static final Logger log = Logger.getLogger(PVerifyEncryptionUtil.class);
private static final String MVN_TAG = "target/classes/";
/**
* 盐值 xx
*
* [test]
*/
public static final String SALT = "xx";
/**
* 场景号
*/
public static final String SCENE_NUMBER = "fastdeal";
/**
* 获取主板序列号
*
* @return
*/
public static String getMainboardNumber() {
Runtime runtime = Runtime.getRuntime();
StringBuffer b = new StringBuffer();
String mainboardNumber = "";
try {
BufferedReader br = new BufferedReader(new InputStreamReader(runtime.exec("wmic bios get serialnumber").getInputStream()));
String line = null;
while ((line = br.readLine()) != null) {
b.append(line);
}
if (StringUtil.isBlank(b.toString())) {
return mainboardNumber;
}
// 截取到主板号
String string = b.toString().replace(" ", "");
String[] strs = string.split("SerialNumber");
if (strs != null && strs.length > 0) {
mainboardNumber = strs[1];
}
}
catch (Exception e) {
log.error("获取主板信息出错", e);
}
return mainboardNumber;
}
/**
* 主板号加密后和场景号一起加密
*
* @param sceneNumber
* 场景号
* @return
*/
public static String getMainboardEncryption(String sceneNumber) {
if (StringUtil.isBlank(sceneNumber)) {
return "";
}
return SM3Util.encrypt(SM3Util.encrypt(getMainboardNumber()) + sceneNumber);
}
/**
* 最终加密字符串
*
* @param sceneNumber
* @return
*/
public static String getFinalEncryptionNumber(String sceneNumber) {
if (StringUtil.isBlank(sceneNumber)) {
return "";
}
return SM3Util.encrypt(getMainboardEncryption(sceneNumber) + SALT);
}
/**
* 根据主办号+盐加密
*
* @param sceneNumber
* @return
*/
public static String encryptionByMainBoard(String mainBoard) {
if (StringUtil.isBlank(mainBoard)) {
return "";
}
return SM3Util.encrypt(mainBoard + SALT);
}
/**
* 写入加密文件
*
* @param encryptionNumber
*/
public static void createEncryptionFile(String encryptionNumber) {
if (StringUtil.isBlank(encryptionNumber)) {
return;
}
FileManagerUtil.writeContentToFile(getLicPath(), "xx.lic", encryptionNumber);
}
/**
* 计算路径
*
* @return
*/
public static String getLicPath() {
String licPath = ClassPathUtil.getLibPath();
URL url = SerialN.class.getResource("/");
String clsPath = url.getFile();
if (clsPath.indexOf(MVN_TAG) > 0) {// 对于maven工程的特殊判断
int index = clsPath.indexOf(MVN_TAG);
if (index != -1) {
licPath = clsPath.substring(0, index) + "src/main/resources/";
}
return licPath;
}
return licPath;
}
/**
* 获取加密文件内容
*
* @return
*/
public static String getEncryptionNumber() {
if (FileManagerUtil.isExist(getLicPath() + "xx.lic", false)) {
return FileManagerUtil.getContentFromSystemByReader(getLicPath() + "xx.lic");
}
return "";
}
/**
* 获取场景号
*
* @param fileName
* @param configName
* @return
*/
public String getSceneNumber(String fileName, String configName) {
return ConfigUtil.getConfigValue(fileName, configName);
}
/**
* 验证密码文件
*
* @param sceneNumber
* @return
*/
public static boolean verifyPassWord(String sceneNumber) {
return getFinalEncryptionNumber(sceneNumber).equals(getEncryptionNumber());
}
/**
* main
*
* @param args
*/
public static void main(String[] args) {
System.out.println(encryptionByMainBoard("zz"));
}
}