# mynetty **Repository Path**: lawliujian/mynetty ## Basic Information - **Project Name**: mynetty - **Description**: mynetty是轻量服务架构 包含 内嵌netty服务器、jdbc(类似mybatis)、myspring、mymvc、myaop、redis、cron定时器、安全权限模块 - **Primary Language**: Java - **License**: AGPL-3.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 6 - **Forks**: 3 - **Created**: 2019-11-21 - **Last Updated**: 2025-01-10 ## Categories & Tags **Categories**: web-dev-toolkits **Tags**: None ## README #### 介绍 **mynetty简介** ``` 1.mynetty是轻量服务架构 包含 内嵌netty服务器、jdbc(类似mybatis)、myspring、mymvc、myaop、redis、cron定时器、安全权限模块; 2.同时还有几个工具包:代码生成工具类(采用beetl模版,代码模版可以自己改造),excel工具类; 3.而且上面的几个模块例如 jdbc myspring模块里的常用方法可以当工具类使用,例如SqlHelper,MySqlSession,DefaultApplication等类可以直接操作数据库和ioc操作; 4.mySafe安全权限框架、简单的定时器调度任务框架、redis操作工具类、文件服务器 ``` #### 服务快速入门 1. 启动服务 启动服务绑定端口8897 代码: ``` public static void main(String[] args) throws InterruptedException { new HttpServer(8897); } ``` 2.使用mymvc 和 ioc 和 MySqlSession写简单查询列表的功能 代码: ``` @MyController @MyRequestMapping("/CustAction") public class CustAction { @MyRequestMapping("/getCustList") public void getCustList(HttpMyRequest req, HttpMyReponse rep) { CustDao cd = MySqlSession.getMapper(CustDao.class); Map par = new HashMap<>(); par.put("name", "%杜%"); Map result = new HashMap<>(); result.put("data", cd.getCustList(par)); rep.fullWrite(JSONObject.toJSONString(result)); } } ``` dao接口 代码: ``` public interface CustDao { @MySelect("select custid,nickname,telphone from cust where 1=1 and nickname like :name ") List> getCustList(Map map); } ``` 3. 访问http://127.0.0.1:8897/CustAction/getCustList 测试接口 返回 {"data":[{"telphone":"18636929805","custid":2,"nickname":"杜业务"},{"telphone":"18234164844","custid":24,"nickname":"杜甫"}]} (该接口通过了jmeter 10000次的并发请求测试) ``` ``` #### 软件架构 简单原理介绍: ``` 服务每次请求的处理: 1.使用netty对每次请求进行myrequest myresponse对象的封装 2.构建serlvet模式,实现myserlvet,生命周期包括 init(初始化)->domain(处理)->destory(销毁) 3.每次请求封装好的 myrequest对象和myresponse对象传入myserlvet实例内(单例模式)(服务初始化时,初始化所有myserlvet实例(注解方式)) 4.mymvc实现一个myserlvet(调度serlvet,URL为"/*")(MyDispatcherServlet类)来调度处理所有请求 5.MyDispatcherServlet类再初始化时对所有myRequestMapping注解方法类都扫描,然后把url:method以key:value形式存储 6.请求过来是执行MyDispatcherServlet类的domain方法,主要就是从url:method的map中取出该url对应的方法和类,然后反射执行 session处理: 每次请求处理请求头是否有cookie及cookie内是否有mysessionid参数信息,没有时回复头内使用 set-cookie给该域名填充mysessionid信息(生成一个uuid) ``` myserlvet接口 ``` public interface MySerlvet { public void init(); public void domain(HttpMyRequest req,HttpMyReponse rep); public void destory(); } ``` mymvc 调度serlvet ``` @MySerlvetUrl("/*") public class MyDispatcherServlet extends HttpMySerlvet { ``` #### 功能介绍 ``` 1. 简单http服务器功能 重新封装了 serlvet,request,reponse等对象 serlvet采取注解的方式配置 2. 服务器有session功能 sessionid标识为 mysessionid 3. 实现轻量级 ioc和mvc 和动态代理aop 4. 实现简单的mybatis功能。 5. 常用的代码生成工具类,excel工具类,代理工具类。 ``` #### 功能详细介绍 一.spring ioc ``` DefaultMyApplication类生命周期: 初始化扫描包下的MyBean注解的类到容器里->从容器获取实例时,反射获取实例类内成员变量如有MyAuto注解,则从容器中依赖注入相应实例。 ``` com.testMvc.testSpring 下测试案例: ``` public static void main(String[] args) throws Exception { //初始化容器 DefaultMyApplication ap = new DefaultMyApplication(); //通过名字获取 CustAction ca = (CustAction) ap.getBean("CustAction"); ca.testSpring(); //通过接口获取 CustService cs= ap.getBean(CustService.class); cs.speak(); } ``` 简单配置: ``` @MyBean("CustAction") public class CustAction { @MyAuto CustService cs; public void testSpring() { List> list = cs.getCusts(); System.out.println("list:" + list); } } ``` ``` @MyBean public class CustServiceImpl implements CustService { @Override public List> getCusts() { CustDao cd = MySqlSession.getMapper(CustDao.class); Map par = new HashMap<>(); par.put("name", "%杜%"); return cd.getCustList(par); } @Override public void speak() { System.out.println("I'am speak"); } } ``` 二.myaop ``` aop原理简单介绍: 1.被切面的类实例调用时采用动态代理,优先使用jdk动态代理,如没有接口是采用cgli代理 2.判断该代理方法是有属于某个配置的切面表达式,如果属于,则取该前要执行操作的方法(method完了会反射调用),下一步 3.四个切入点采用观察者模式,例如代理方法执行到方法前,把方法前的信号标志和切面相关操作方法传给所用订阅者update,然后方法前面的订阅者执行自己的update方法 4.Update方法 执行相关切面操作方法(反射执行) ``` com.testMvc.testAop2 下测试案例testAop2 ``` public static void main(String[] args) { test1(); } public static void test1() { MyAopFactory.getInstance(); Inter1 i = MyAopFactory.getSub(inter1Impl.class); i.speak(); } ``` 执行结果: ``` 哈哈在前面 speak 哈哈在后面 ``` 简单配置: 切入点配置(com.testMvc.testAop1包下所有类的spea打头的方法执行切面方法) ``` @MyAscept("execution(* com.testMvc.testAop1.*.spea*(..))") public class testAscept { @MyBefor public void befor() { System.out.println("哈哈在前面"); } @MyAfter public void after() { System.out.println("哈哈在后面"); } } ``` inter1Impl类内的speak方法符合切入点表达式@MyAscept("execution(* com.testMvc.testAop1.*.spea*(..))") ``` public class inter1Impl implements Inter1 { @Override public void speak() { System.out.println("speak"); } } ``` 三.代码生成器: ``` 简单原理: 1.采用beetle模版引擎,直接配置action层,service层,bean层的代码模版 2.查询生成表的字段信息,相关信息保存起来执行下一步 3.beetle资源加载器把代码模版的代码加载然后用表字段信息经过“类型转换和首字母大写转换” 4.填充模版页面相关数据到模版引擎里,渲染模版,渲染结果生成相应的文件到目标目录下 ``` 使用简单介绍: ``` com.tool.createBean包下CreateHelperNew类main方法生成代码,入参有注解,如下: ``` ``` public static void main(String[] args) { getTableInfo("cust,config", "用户,配置", "E:/kkklll/"); } /** * @param table 表名 * @param describe 表模块描述 * @param path 生成bean文件路径 */ public static void getTableInfo(String table, String describe, String path) { try { ``` 模版文件在在resources下的codeTemplate包下(现在又action,bean,service几个模版文件,可自己修改或增加自己的模版文件) ``` ``` ``` ``` ``` ``` ``` ``` #### 作者 刘剑