{"id":15068774,"url":"https://github.com/zzzzbw/doodle","last_synced_at":"2025-04-10T17:36:05.864Z","repository":{"id":34294603,"uuid":"139542603","full_name":"zzzzbw/doodle","owner":"zzzzbw","description":"A Simple Java MVC Framework。提供Bean容器、Ioc、Aop、MVC功能","archived":false,"fork":false,"pushed_at":"2022-06-17T01:53:43.000Z","size":113,"stargazers_count":121,"open_issues_count":1,"forks_count":27,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-03-24T15:11:19.530Z","etag":null,"topics":["annotation","aop","ioc","java8","mvc-framework","springboot"],"latest_commit_sha":null,"homepage":"https://github.com/zzzzbw/doodle","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/zzzzbw.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-07-03T07:07:56.000Z","updated_at":"2025-02-11T02:03:53.000Z","dependencies_parsed_at":"2022-09-11T04:30:28.197Z","dependency_job_id":null,"html_url":"https://github.com/zzzzbw/doodle","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zzzzbw%2Fdoodle","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zzzzbw%2Fdoodle/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zzzzbw%2Fdoodle/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zzzzbw%2Fdoodle/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zzzzbw","download_url":"https://codeload.github.com/zzzzbw/doodle/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248262032,"owners_count":21074230,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["annotation","aop","ioc","java8","mvc-framework","springboot"],"created_at":"2024-09-25T01:39:14.907Z","updated_at":"2025-04-10T17:36:05.839Z","avatar_url":"https://github.com/zzzzbw.png","language":"Java","funding_links":[],"categories":["开发框架"],"sub_categories":["Web框架"],"readme":"# Doodle\n\n[![Build Status](https://www.travis-ci.org/zzzzbw/doodle.svg?branch=master)](https://www.travis-ci.org/zzzzbw/doodle)\n[![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.github.zzzzbw/doodle/badge.svg)](https://search.maven.org/artifact/com.github.zzzzbw/doodle-core/0.1/jar)\n[![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg)](https://www.apache.org/licenses/LICENSE-2.0.html)\n\n## 简介\n\n*doodle*是一个简易的Java MVC框架，它提供了类似于*spring* 的Bean容器、IOC、AOP、MVC等功能\n\n代码简洁、轻量，适合用于参考学习spring\n\n* 一行代码即可启动服务，内置Tomcat容器\n* `DispatcherServlet`请求逻辑处理采用责任链模式，方便增加修改规则\n* 不使用XML配置，完全注解开发\n* IOC容器，解决循环依赖注入问题\n* 支持多AOP增强，切点支持aspectj表达式\n\nHttp请求访问设计图：\n\n![](https://raw.githubusercontent.com/zzzzbw/blog_source/master/images/Doodle/doodle-DispatcherServlet.png)\n\n## 示例代码\n\n1. `git clone https://github.com/zzzzbw/doodle.git` 或直接下载代码到本地\n2. 将项目导入到IDE中，这是maven工程,确保你已经安装maven\n3. 执行`doodle-example/src/main/java`下的`github.zzzzbw.App`类的`main()`方法即可启动Tomcat服务器\n  \n   ![](https://raw.githubusercontent.com/zzzzbw/blog_source/master/images/Doodle/Snipaste_2018-07-11_20-57-15.png)\n\n4. 浏览器访问`http://localhost:9090/user/list`和`http://localhost:9090/user/detail?id=1`链接\n\n   ![](https://raw.githubusercontent.com/zzzzbw/blog_source/master/images/Doodle/Snipaste_2018-08-13_23-08-30.png)![](https://raw.githubusercontent.com/zzzzbw/blog_source/master/images/Doodle/Snipaste_2018-08-13_23-08-57.png)\n\n5. 通过'Postman'等工具用`post`方式请求到链接`http://localhost:9090/user/add?name=zzzzbw`和`http://localhost:9090/user/delete?id=1`修改数据\n\n\n## 使用方式\n\n### 引入依赖\n\n创建一个 maven 项目，引入核心依赖\n\n```xml\n\u003cdependency\u003e\n  \u003cgroupId\u003ecom.github.zzzzbw\u003c/groupId\u003e\n  \u003cartifactId\u003edoodle-core\u003c/artifactId\u003e\n  \u003cversion\u003e0.1\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\n启动类：\n\n```java\npublic class App {\n    public static void main(String[] args) {\n        Doodle.run(App.class, 9090);\n    }\n}\n```\n\n### IOC使用\n\n使用方式与*spring*基本一致，不过只支持类型注入，即如果被注入对象为类，则注入其实例，如果被注入对象为接口，则注入其实现类。\n\n```java\n@Component\npublic class EmailComponent {\n    // do something\n}\n```\n\n为`UserController`注入`EmailComponent`\n\n```java\n@Controller\npublic class UserController {\n    @Autowired\n    private EmailComponent emailComponent;\n    // do something\n}\n```\n\n### AOP使用\n\n* 增强处理类必须实现`MethodBeforeAdvice`,`AfterReturningAdvice`,`ThrowsAdvice`,`AroundAdvice`中的一个或者多个接口\n* 增强处理类被`@Aspect`注解，且有正确的aspectj切点表达式\n* (可选)`@Order`注解来决定增强处理类的先后顺序\n\n```java\n@Order(1)\n@Aspect(pointcut = \"@within(Controller)\")\npublic class Aspect1 implements AroundAdvice {\n    @Override\n    public void afterReturning(Class\u003c?\u003e clz, Object returnValue, Method method, Object[] args) throws Throwable {\n        // do something\n    }\n    @Override\n    public void before(Class\u003c?\u003e clz, Method method, Object[] args) throws Throwable {\n        // do something\n    }\n    @Override\n    public void afterThrowing(Class\u003c?\u003e clz, Method method, Object[] args, Throwable e) {\n        // do something\n    }\n}\n```\n\n```java\n@Order(2)\n@Aspect(pointcut = \"@within(Controller)\")\npublic class Aspect2 implements AroundAdvice {\n    @Override\n    public void afterReturning(Class\u003c?\u003e clz, Object returnValue, Method method, Object[] args) throws Throwable {\n        // do something\n    }\n\n    @Override\n    public void before(Class\u003c?\u003e clz, Method method, Object[] args) throws Throwable {\n        // do something\n    }\n\n    @Override\n    public void afterThrowing(Class\u003c?\u003e clz, Method method, Object[] args, Throwable e) {\n        // do something\n    }\n}\n```\n\n上面两个增强处理类`Aspect1`和`Aspect2`，会增强被`@Controller`注解的类下的方法，且顺序为：\n\nAspect1@before()-\u003eAspect2@before()-\u003emethod.invoke()-\u003eAspect2@afterReturning()-\u003eAspect1@afterReturning()\n\n### Controller使用\n\n使用几乎与*spring*一致\n\n返回String类型的则返回jsp页面的路径，返回ModelAndView则在其view中设置jsp页面路径，同时可以传一些参数给jsp页面\n\n被`@ResponseBody`注解的则返回的是json格式数据\n\n```java\n@Controller\n@RequestMapping(value = \"/user\")\npublic class UserController {\n\n    @Autowired\n    private UserService userService;\n\n    @RequestMapping(value = \"/list\", method = RequestMethod.GET)\n    public ModelAndView getUserList() {\n        List\u003cUser\u003e list = userService.getUser();\n        return new ModelAndView().setView(\"user_list.jsp\").addObject(\"list\", list);\n    }\n\n    @RequestMapping(value = \"/detail\", method = RequestMethod.GET)\n    public ModelAndView getUser(@RequestParam(value = \"id\") long id) {\n        User user = userService.getUserById(id);\n        return new ModelAndView().setView(\"user_detail.jsp\").addObject(\"user\", user);\n    }\n\n    @RequestMapping(value = \"/add\", method = RequestMethod.POST)\n    @ResponseBody\n    public Result\u003cUser\u003e addUser(@RequestParam(value = \"name\") String name) {\n        User user = userService.addUser(name);\n        return new Result\u003c\u003e(user, 0, \"\");\n    }\n\n    @RequestMapping(value = \"/delete\", method = RequestMethod.POST)\n    @ResponseBody\n    public Result\u003cString\u003e deleteUser(@RequestParam(value = \"id\") long id) {\n        userService.deleteUser(id);\n        return new Result\u003c\u003e(\"success\", 0, \"\");\n    }\n}\n```\n\n## 约束\n\n*doodle*暂时功能没有完善，在使用过程中有一些约束条件\n\n* 被Bean容器接管的类都有无参的构造方法且构造方法不是私有的 \n* `@Component`只应用于类，应用于接口或抽象类将无效 \n* 每个`Controller`被`@RequestMapping`标注的方法，其参数必须必须被`@RequestParam`注解，且参数必须是java的基本数据类型或者基本数据的包装类(如int,Integer等)\n\n\n## 详解\n\n* [从零开始实现一个简易的Java MVC框架(一)--前言](http://zzzzbw.cn/article/8)\n* [从零开始实现一个简易的Java MVC框架(二)--实现Bean容器](http://zzzzbw.cn/article/9)\n* [从零开始实现一个简易的Java MVC框架(三)--实现IOC](http://zzzzbw.cn/article/10)\n* [从零开始实现一个简易的Java MVC框架(四)--实现AOP](http://zzzzbw.cn/article/11)\n* [从零开始实现一个简易的Java MVC框架(五)--引入aspectj实现AOP切点](http://zzzzbw.cn/article/12)\n* [从零开始实现一个简易的Java MVC框架(六)--加强AOP功能](http://zzzzbw.cn/article/13)\n* [从零开始实现一个简易的Java MVC框架(七)--实现MVC](http://zzzzbw.cn/article/14)\n* [从零开始实现一个简易的Java MVC框架(八)--制作Starter](http://zzzzbw.cn/article/15)\n* [从零开始实现一个简易的Java MVC框架(九)--优化MVC代码](http://zzzzbw.cn/article/16)\n\n## 结语\n\n本项目不仅参考了spring-boot，同时还参考了:\n\n- [blade](https://github.com/lets-blade/blade )\n- [latke](https://github.com/b3log/latke)\n- [smart-framework](https://gitee.com/huangyong/smart-framework)\n\n这些都是国人写的更轻量而且也很优秀的框架，相比spring-boot来说阅读源码的难度会小一些。感谢这些框架给我提供学习的思路，同时给我们更多的选择。\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzzzzbw%2Fdoodle","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzzzzbw%2Fdoodle","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzzzzbw%2Fdoodle/lists"}