{"id":18938952,"url":"https://github.com/lihengming/potato-webmvc","last_synced_at":"2025-04-15T19:30:34.785Z","repository":{"id":43615744,"uuid":"54625890","full_name":"lihengming/potato-webmvc","owner":"lihengming","description":":pencil:一个简单的Web MVC框架，寂寞消遣之作~","archived":false,"fork":false,"pushed_at":"2016-10-21T09:55:21.000Z","size":42,"stargazers_count":26,"open_issues_count":0,"forks_count":10,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-03-29T01:12:55.776Z","etag":null,"topics":["java","mvc","web"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lihengming.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":"2016-03-24T08:17:45.000Z","updated_at":"2022-04-23T02:24:23.000Z","dependencies_parsed_at":"2022-08-26T08:41:18.574Z","dependency_job_id":null,"html_url":"https://github.com/lihengming/potato-webmvc","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/lihengming%2Fpotato-webmvc","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lihengming%2Fpotato-webmvc/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lihengming%2Fpotato-webmvc/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lihengming%2Fpotato-webmvc/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lihengming","download_url":"https://codeload.github.com/lihengming/potato-webmvc/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248768549,"owners_count":21158661,"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":["java","mvc","web"],"created_at":"2024-11-08T12:15:54.338Z","updated_at":"2025-04-15T19:30:34.468Z","avatar_url":"https://github.com/lihengming.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"## 简介\r\nPotato WebMVC 是用Java实现的一个简单的MVC框架，由于其简单性所以只俱备基本MVC框架的功能和以下特性~\r\n\r\n1. 约定优于配置，实现最简甚至零配置\r\n2. Model表单、请求参数、依赖对象自动构造注入所请求的HandleMethod\r\n3. 拦截器\r\n4. JSP View 、JSON响应支持\r\n\r\n## 如何使用？\r\n\r\n1.引入Maven 依赖\r\n```xml\r\n \u003cdependency\u003e\r\n    \u003cgroupId\u003ecom.github.lihengming\u003c/groupId\u003e\r\n    \u003cartifactId\u003epotato-webmvc\u003c/artifactId\u003e\r\n    \u003cversion\u003e1.0.1\u003c/version\u003e\r\n\u003c/dependency\u003e\r\n\r\n\u003c!--如果你需要打印日志的话，引入任何一种SLF4J的实现，例如logback。--\u003e\r\n\u003cdependency\u003e\r\n    \u003cgroupId\u003ech.qos.logback\u003c/groupId\u003e\r\n    \u003cartifactId\u003elogback-classic\u003c/artifactId\u003e\r\n    \u003cversion\u003e1.1.7\u003c/version\u003e\r\n\u003c/dependency\u003e\r\n```\r\n\r\n2.配置你的web.xml\r\n```xml\r\n\u003cservlet\u003e\r\n    \u003cservlet-name\u003eDispatcherServlet\u003c/servlet-name\u003e\r\n    \u003cservlet-class\u003ecn.potato.web.Dispatcher\u003c/servlet-class\u003e\r\n    \u003c!--下面的init-param并不是必须的，如果你要使用默认值的话。--\u003e\r\n    \u003cinit-param\u003e\r\n      \u003cparam-name\u003ebasePackage\u003c/param-name\u003e\r\n      \u003c!--默认值是根包--\u003e\r\n      \u003cparam-value\u003eexample.web.controller\u003c/param-value\u003e\r\n    \u003c/init-param\u003e\r\n    \u003cinit-param\u003e\r\n      \u003cparam-name\u003eviewPrefix\u003c/param-name\u003e\r\n      \u003c!--这是默认值--\u003e\r\n      \u003cparam-value\u003e/WEB-INF/views/\u003c/param-value\u003e\r\n    \u003c/init-param\u003e\r\n    \u003cinit-param\u003e\r\n      \u003cparam-name\u003eviewSuffix\u003c/param-name\u003e\r\n      \u003c!--这是默认值--\u003e\r\n      \u003cparam-value\u003e.jsp\u003c/param-value\u003e\r\n    \u003c/init-param\u003e\r\n  \u003c/servlet\u003e\r\n\r\n  \u003cservlet-mapping\u003e\r\n    \u003cservlet-name\u003eDispatcherServlet\u003c/servlet-name\u003e\r\n    \u003curl-pattern\u003e/\u003c/url-pattern\u003e\r\n  \u003c/servlet-mapping\u003e\r\n```\r\n\r\n3.创建Controller\r\n```java\r\npackage example.web.controller;\r\n\r\npublic class HomeController {\r\n\r\n    //index()映射路径 -  \u003e  ‘/home’\r\n    public Result index(Result result){\r\n        result.setViewName(\"home\");//视图\r\n        result.addData(\"name\", \"Potato\");//模型\r\n        return result;\r\n    }\r\n}\r\n```\r\n\r\n4.创建JSP\r\nReference:WEB-INF/views/home.jsp\r\n```java\r\n  \u003c%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" %\u003e\r\n  \u003chtml\u003e\r\n  \u003chead\u003e\r\n      \u003ctitle\u003eTitle\u003c/title\u003e\r\n      \u003cscript src=\"//cdn.bootcss.com/jquery/1.9.1/jquery.min.js\"\u003e\u003c/script\u003e\r\n  \u003c/head\u003e\r\n  \u003cbody\u003e\r\n  This Home Page,Hello ${name}!\r\n  \u003c/body\u003e\r\n  \u003c/html\u003e\r\n\r\n```\r\n\r\n5.部署后访问它\r\n请求：[http://localhost/home](http://localhost/home)\r\n响应：This Home Page,Hello Potato!\r\n## 使用其他特性\r\n- 使用JSON响应支持构造REST API ，以User服务为例\r\n\r\n1.创建Model\r\n```java\r\npublic class User {\r\n    private Long id;\r\n    private String username;\r\n    private Integer age;\r\n    //省略getter、setter方法\r\n}\r\n```\r\n2.创建UserController\r\n```java\r\npackage example.web.controller;\r\npublic class UserController {\r\n\r\n    //模拟持久层\r\n    private Map\u003cLong, User\u003e repository = new HashMap\u003cLong, User\u003e();\r\n\r\n    //映射路径add() - \u003e ‘/user/add’\r\n    public boolean add(User user) {\r\n        repository.put(user.getId(), user);\r\n        return true;\r\n    }\r\n\r\n    //映射路径add() - \u003e ‘/user/list’\r\n    public Collection list() {\r\n        return  repository.entrySet();\r\n    }\r\n\r\n    //映射路径add() - \u003e ‘/user/find’\r\n    public User find(Long id) {\r\n        return repository.get(id);\r\n    }\r\n\r\n}\r\n\r\n```\r\n3.使用AJAX调用API\r\n```javascript\r\n   function add(){\r\n        var url = '/user/add';\r\n        var data = {\r\n            'user.id': 1,\r\n            'user.username': 'potato',\r\n            'user.age': '24'\r\n        };\r\n        $.post(url, data).done(function (success) {\r\n            console.log(success);\r\n\r\n        });\r\n    }\r\n    function query(){\r\n        var url = '/user/find';\r\n        $.get(url, {id: 1}).done(function (result) {\r\n            console.log(result);\r\n        });\r\n    }\r\n    add();//console out：true\r\n    query();//console out：Object {age: 24, id: 1, username: \"potato\"}\r\n\r\n```\r\n\r\n- 使用拦截器支持做统一的处理\r\n\r\n1.创建拦截器Class并实现Interceptor接口\r\n```java\r\npackage example.web.interceptor;\r\n/**\r\n * 示例拦截器，统计方法执行时间\r\n */\r\npublic class ExampleInterceptor implements Interceptor {\r\n    private final ThreadLocal\u003cLong\u003e threadLocal = new ThreadLocal\u003cLong\u003e();\r\n\r\n    public void before(HttpServletRequest request, HttpServletResponse response, Method handleMethod) {\r\n        System.out.println(\"执行方法之前，方法名称：\" + handleMethod.getName());\r\n        threadLocal.set(System.currentTimeMillis());\r\n    }\r\n\r\n    public void after(HttpServletRequest request, HttpServletResponse response, Object result) {\r\n        long time = System.currentTimeMillis() - threadLocal.get();\r\n        System.out.println(\"方法执行之后，返回Result：\" + result + \",耗时\" + time + \"毫秒\");\r\n    }\r\n}\r\n```\r\n2.在Controller使用@EnableIntercept注解启动拦截器\r\n```java\r\n@EnableIntercept(classes=ExampleInterceptor.class)\r\npublic class UserController {}\r\n```\r\n3.测试\r\n\r\n请求：[http://localhost/user/list](http://localhost/user/list)\r\n查看控制台输出：\r\n```shell\r\n执行方法之前，方法名称：list\r\n14:13:43.951 [http-bio-80-exec-9] DEBUG cn.potato.web.Dispatcher - Interceptor: invoke example.web.interceptor.ExampleInterceptor.before()\r\n14:13:43.952 [http-bio-80-exec-9] DEBUG cn.potato.web.Dispatcher - ##------------Service Begin--------------##\r\n14:13:43.952 [http-bio-80-exec-9] DEBUG cn.potato.web.Dispatcher - Request: [/user/list] --\u003e [example.web.controller.UserController.list()]\r\n14:13:43.952 [http-bio-80-exec-9] DEBUG cn.potato.web.Dispatcher - Handle Finish!\r\n方法执行之后，返回Result：[1=example.model.User@6e3114f5],耗时1毫秒\r\n14:13:43.952 [http-bio-80-exec-9] DEBUG cn.potato.web.Dispatcher - Interceptor: invoke example.web.interceptor.ExampleInterceptor.after()\r\n14:13:43.952 [http-bio-80-exec-9] DEBUG cn.potato.web.Dispatcher - Response: [Type：JSON],[Data：[{\"key\":1,\"value\":{\"age\":24,\"id\":1,\"username\":\"potato\"}}]]\r\n14:13:43.952 [http-bio-80-exec-9] DEBUG cn.potato.web.Dispatcher - ##------------Service End--------------##\r\n```\r\n## 使用建议\r\n本框架仅限于娱乐，因为它可能只是一个简简单单的玩具轮子，并且随时可能会爆胎，所以并不建议你使用它上路~。\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flihengming%2Fpotato-webmvc","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flihengming%2Fpotato-webmvc","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flihengming%2Fpotato-webmvc/lists"}