背景
在开发base项目中,dubbo提供者开发完之后,研发需要进行接口函数自测。本博客将提供一种提高自测和调试的方法。
旧的方法
假如你写了一个service类,如下:
写完了service之后,如果需要马上测试看效果的话,最常用的方法是,直接写一个测试单元。
如果项目大一点,测试单元跑的时间肯定是超过10s以上的,甚至更多。
这时,如果我们仅仅改变一行代码,想马上看到这行代码的调试结果,如下:
我们不得不重新再跑一下测试单元,继续等待spring boot的启动,时间成本很高。
以下将阐述一种高效的方法。此方法很大程度上借鉴了同事的做法,并在某些方面加以改变
新的方法
添加插件save action
配置如下(直接照着下面的选项配置,点击确定
),在crtl + s的时候会触发save action
插件安装好以后,将会增加一些实用的高效功能,其中包括在debug过程中,如果仅仅改变了部分函数的代码,可以高效编译
,演示效果如下:
此时添加一行代码,直接crtl + s,编译瞬间完成
编译总共花了1s左右,这个时候并没有进行重启的操作,是自动进行增量编译的。
添加一个通用入口的controller
代码如下:
package com.example.demo;
import com.alibaba.fastjson.JSONArray;
import lombok.extern.log4j.Log4j2;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Profile;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
@RestController
@Log4j2
public class TestBeanCall implements ApplicationContextAware {
private ApplicationContext applicationContext;
@RequestMapping("/{bean}/{method}")
public Object test(@PathVariable("bean") String bean, @PathVariable("method") String method, @RequestBody JSONArray params) {
log.info("bean:{}", bean);
log.info("method:{}", method);
log.info("params:{}", params);
Object obj;
try {
obj = applicationContext.getBean(bean);
} catch (Exception e) {
return e.toString();
}
Method md = getMethod(obj, method);
try {
Type[] parameterTypes = md.getGenericParameterTypes();
if (parameterTypes.length == 0) {
return md.invoke(obj);
}
Object[] pos = new Object[parameterTypes.length];
for (int i = 0; i < parameterTypes.length; i++) {
pos[i] = params.getObject(i, parameterTypes[i]);
}
md.setAccessible(true);
return md.invoke(obj, pos);
} catch (Exception e) {
log.error("{}", e);
return e.getMessage();
}
}
/**
* 由于请求参数暂时不传递参数类型列表,所以只能通过method名称来获取了
*/
private Method getMethod(Object obj, String method) {
Method[] methods = obj.getClass().getDeclaredMethods();
for (Method md : methods) {
if (md.getName().equals(method)) {
return md;
}
}
throw new RuntimeException("没有找到方法");
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
}
使用postman发起一个api调用。
注:body参数最外层需要传递jsonarray类型的
(在反射过程中,需要按照顺序去加载这些参数)
可以看到,直接就调用如下的接口
下面我们来写一个新的带有参数的接口,以方便观察参数的调用。
注:有接口级别的改动,save action的增量编译会失效,需要重新启动debug
postman中添加参数,并且发起调用。
下面我们来添加一行打印,然后直接按ctrl + s,这个时候就直接进行编译,完全不用再重启debug了
用postman再次调用,也能直接产生变化。
注意:
- 可以在类头添加@Profile({“dev”}),这样的话,controller的bean就只能在dev环境用了,避免在线上环境暴露出接口
评价
如果大家还有什么其他的效率提升的想法,可在留言区交流,博主在时间允许的情况下,将加以尝试和对比。