国庆7天,写了一个轻量级API框架
前言
有些项目是我们自己或者为朋友所开发的,功能比较简单,接口也比较少,但通常使用SpringBoot开发后,少说也得20M,传输部署也不方便,且这个jar中很可能有8090的代码是永远得不到执行的,但他可能被虚拟机所加载,占用一部分内存。
所以在国庆7天写了一个小型的后端框架,称为miniapi,他的源码只有141KB,但由于引入了其他框架,所以最终大小为10M,可以使用下面方式将minapi引入到你的项目。
Gradleimplementationcom。houxinlin:miniapi:1。0。3
MavendependencygroupIdcom。houxinlingroupIdminiapiartifactIdversion1。0。3versiondependency
注意,1。0。0、1。0。2由于测试不周到,存在一些问题,需要从1。0。3开始。
框架本身依赖的第三方库如下gson:作用于json解析asm:作用于class文件解析kotlin,由于项目是kotlin方法,所以会包含一些kotlin必备的库mybatis:数据库查询mysql:mysql驱动
项目地址:https:github。comhouxinlinminiapi示例创建实例
CoolMini的构造方法需要一个端口号,且调用start后表示启动服务,他的参数同SpringBoot启动方法一样,会扫描目标Class所在包下的所有子包,这些子包下应包含标有RestController注解的类,同SpringBoot一样。publicclassMain{publicstaticvoidmain(String〔〕args)throwsThrowable{CoolMinicoolMininewCoolMini(7070);coolMini。start(Main。class);}}简单请求
创建请求同SpringBoot中一样,miniapi提供了GetMapping、PostMapping、PutMapping、DeleteMapping映射。
获取参数也一样,miniapi提供了以下几个注解用于从请求中获取参数。RequestParam用于从请求url、请求体中ContentType类型为applicationxwwwformurlencoded、formdata中获取参数,参数类型可以根据实际参数类型改变,不一定是String类型,但为了方便,提供了一个HttpParameterTypeConverter参数转换器,在后面会说。RestControllerpublicclassIndexController{GetMapping(get)publicStringindex(RequestParam(name)Stringname,RequestParam(age)intage){System。out。println(nameage);returnname;}}PathVariable同SpringBootGetMapping(get{user})publicStringindex(PathVariable(user)Stringuser){returnuser;}RequestUri获取请求url地址RestControllerpublicclassIndexController{GetMapping(get{user})publicStringindex(RequestUriStringurl){returnurl;}}RequestBody获取请求体,参数类型不一定是String,可以是具体对象,也可以是List,解析使用Gson解析,但也可以自定义json解析器。PostMapping(get)publicStringindex(RequestBodyStringbody){returnbody;}文件请求
由于不是基于Servlet规范,以往的Servlet方法在miniapi中都无法使用,而对于文件请求,可以直接使用下面方式获取,如果多个文件,可以使用List接收。RestControllerpublicclassIndexController{PostMapping(get)publicStringindex(RequestParam(name)Stringname,RequestParam(file)FilePartfilePart)throwsIOException{byte〔〕buffernewbyte〔((int)filePart。getContentLength())〕;filePart。inputStream。read(buffer);Files。write(Paths。get(homeHouXinLintempfilestemp。txt),buffer);returnOK;}}Session
miniapi提供了简单的session功能,用来在服务端存储一些数据,可以用来做认证。RestControllerpublicclassIndexController{GetMapping(get)publicStringget(Sessionsession){returnsession。getAttibute(name,)。toString();}GetMapping(set)publicStringset(Sessionsession){session。setTnvalidTime(100010);session。setAttribute(name,张三);returnOK;}}HttpParameterTypeConverter接口
用于把请求参数转换为自定义数据类型,比如url中有个参数为name张三,如果你想通过下面方法接收。RestControllerpublicclassIndexController{GetMapping(get)publicStringindex(RequestParam(name)Username,RequestParam(age)intage){System。out。println(nameage);returnname。toString();}}
那么需要添加一个参数转换器publicclassMain{publicstaticvoidmain(String〔〕args)throwsThrowable{CoolMinicoolMininewCoolMini(7070);coolMini。addHttpParameterTypeConverter(true,newHttpParameterTypeConverterUser(){OverridepublicbooleancanConvert(NotNullMethodParametermethodParameter,NotNullStrings){返回是否能转换此参数returnUser。class。equals(methodParameter。param。getType());}NullableOverridepublicUsertypeConvert(Stringvalue){returnnewUser(value);}});coolMini。start(Main。class);}}HttpIntercept接口
用于拦截所有请求,intercept方法如果返回true则表示拦截,那么postHandler方法将会被调用,可以通过httpRequestAdapter。setResponse设置响应。CoolMinicoolMininewCoolMini(7070);coolMini。addHttpIntercept(newHttpIntercept(){Overridepublicbooleanintercept(NotNullHttpRequestAdapterhttpRequestAdapter){returnfalse;}OverridepublicvoidpostHandler(NotNullHttpRequestAdapterhttpRequestAdapter){httpRequestAdapter。setResponse(拦截);}});coolMini。start(Main。class);ArgumentResolver接口
用于参数转换,不同于HttpParameterTypeConverter,HttpParameterTypeConverter用于已知参数名,但无法把String类型参数转换为目标方法中的实际参数类型。
ArgumentResolver接口则可以最大能力进行参数转换,多数用于从请求体中进行获取。coolMini。addArgumentResolvers(true,newArgumentResolver(){Overridepublicbooleansupport(NotNullMethodParametermethodParameter,NotNullHttpRequestAdapterhttpRequestAdapter){returnmethodParameter。param。getType()User。class;}NullableOverridepublicObjectresolver(NotNullMethodParametermethodParameter,NotNullHttpRequestAdapterhttpRequestAdapter,NotNullMappingInfomappingInfo){StringrequestBodynewString(httpRequestAdapter。getRequestBody());returnnewUser(requestBody);}});RestControllerpublicclassIndexController{PostMapping(get)publicStringindex(Useruser){returnuser。toString();}}全局认证器
miniapi提供了一个全局认证器,所有请求都会拦截(如果被设置了的话),所以就需要提供一个登录接口地址,用于认证。coolMini。setAuthorization(newMiniAuthentication(login,newAuthenticationIntercept(){Overridepublicbooleanintercept(NotNullHttpRequestAdapterhttpRequestAdapter){返回true则表示拦截returnfalse;}OverridepublicvoidpostHandler(NotNullHttpRequestAdapterhttpRequestAdapter){}}));DataSource
miniapi结合了mybatis进行数据库查询,扩展了动态sql,但也保留了原来mybatis通过接口注解的方式查询,但在查询之前,需要提供一个数据源。CoolMinicoolMininewCoolMini(7070);coolMini。setDataSource(newMysqlDataSource(root,pass,jdbc:mysql:localhost:3306day));coolMini。start(Main。class);
这里的动态sql不是指mybatis的动态标签,而是可以直接以字符方式进行查询,如下。RestControllerpublicclassIndexController{AutowriteCrudMybatisCrudRepositorycrudRepository;GetMapping(get)publicListUserindex(){ListUseruserscrudRepository。list(selectfromauntday,User。class);returnusers;}}
在设置了数据源后,就可以通过AutowriteCrud注解自动注入一个BaseCrudRepository实例,默认实现是MybatisCrudRepository,未来可能会加入其他,如果不想通过字符串这种方式,可以使用mybatis原生Mapper接口方式,但不支持xml方式。RestControllerpublicclassIndexController{interfaceMapper{Select(selectfromauntday)ListUserlistUser();}AutowriteCrudMybatisCrudRepositorycrudRepository;privateMappermapper;publicvoidinit(){mappercrudRepository。getMapper(Mapper。class);}GetMapping(get)publicListUserindex(){ListUserusersmapper。listUser();returnusers;}}