V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Cloudee
V2EX  ›  Java

撸了个简单的 WebMVC 框架,求吐嘈和 Star/Fork

  •  
  •   Cloudee ·
    cloudeecn · 2015-10-23 18:20:23 +08:00 · 3370 次点击
    这是一个创建于 3320 天前的主题,其中的信息可能已经有所发展或是发生改变。

    陆陆续续用闲暇时间写的自用 MVC 框架,本来想利用十一期间整理整理代码放出来,结果一直拖延症终于缓慢地完工了(然后这帖又写了两天……)

    先放地址: https://github.com/cloudeecn/mocha-mvc 求 Star 和 Fork , orz

    README 和 Wiki 还不全,大家先凑合一下看看这里和 example 工程

    运行环境要求:

    • Java7
    • Servlet3.0 容器

    运行 Example

    clone 工程,用 eclipse/IDEA/whatever 你喜欢的 IDE 导入 maven 工程,用支持 Servlet3.0 的容器启动里面的 example 子工程就 OK 啦

    在 web.xml 中有使用SpringGuice作为 DI 的两套配置,默认打开的是用Guice作 DI 的,也可以打开Spring来试一下。

    Spring的配置在 example 工程中src/main/resources/works/cirno/mocha/example/spring/applicationContext.xml

    Guice的配置在
    works.cirno.mocha.example.guice
    包下

    快速上手

    用过Guice的同学应该对这种方式很熟悉,创建一个works.cirno.mocha.MVCConfigurator的子类,并在public void configure()方法中进行配置。配置好后配置到 DispatcherFilter / DispatcherServlet 的 init-param["configurator"]中

    配置路由项

    serve({路径}[, "GET/POST/PUT..."])
    

    会产生一个路由项,利用方法链的方式可以进一步对匹配这个路径的访问进行配置

    配置响应

    serve({路径}[, "GET/POST/PUT..."]).with({controller}, {method});
    

    中的 with 方法给路由项配置响应的Controller和其中的方法method

    Controller 返回

    Controller 方法可以支持返回一下几个类型

    Integer :直接用 response.sendError 返回返回码

    String :作为 view 的名字寻找对应的 jsp 进行渲染

    View 对象:根据 view 的名字寻找对应的 jsp 进行渲染, view 对象中有 attribute(key, value)方法可以给 request 的 attribute 提供值

    null 或者方法返回类型为 void :不做后续处理

    配置 view 返回

    可以通过 forward 方法执行响应 view 名对应的 jsp 文件( forward 方法返回一个支持 to 方法的接口,其中的 to 方法执行 JSP 的位置)

    可以配置多个

    serve({路径}[, "GET/POST/PUT..."]).with({controller}, {method})
      .forward("view 名").to("JSP 位置")
      .forward("view 名").to("JSP 位置")
      ...
      ;
    

    支持 Restful 风格的 api

    serve("/parameter/\\+${userId}").with(ParameterController.class, "user").forward("success").to("/WEB-INF/jsp/parameter-rest.jsp");
    
    serve("/parameter/\\+${userId}", "POST").with(ParameterController.class, "userPost");
    
    serve("/parameter/\\+${userId}.json").with(ParameterController.class, "userJson");
    

    会匹配 /parameter/+后面的任何内容,并作为 userId 参数和候选

    目前有两种写法:

    JDK7 终于支持了的 namedGroup :写法如下:(?<name>pattern),会匹配 pattern 正则并且作为 name 参数的候选

    另外支持一种比较基本的${name}写法,会被翻译成(?<name>.*?),最小匹配接下来的内容作为 name 参数的候选

    参数获取

    Controller 方法中的参数目前会根据以下的规则获取:

    1. 按类型匹配

      • 类型为 HttpServletRequest 的参数会给予 request 对象
      • 类型为 HttpServletResponse 的参数会给予 response 对象
      • 类型为 ServletOutputStream 或 OutputStream 的参数会给予 response.getOutputStream()的结果
      • 类型为 PrintWriter 或 Writer 的参数会给予 response.getWriter()的结果
    2. 如果是 multipart 请求,如果参数类型是 InputStream 或者 Reader ,根据参数名匹配上传文件的内容

    3. 根据参数的名称,按照url 中的变量 - multipart 中解析到的表单域 - request.getParameter的顺序获取字符串,并尝试通过系统中的 PropertyEditor 进行类型转换,如果转换成功将转换结果给予参数

    4. 将这个类型用无参构造函数实例化,如果成功作为 JavaBean 遍历其中的属性,根据规则 1-4 获取参数名.属性名的参数值进行填充,如果能获取到至少一个,将这个实例给予参数

    5. 以上都不匹配返回参数的默认值(基本类型给 false/0 ,对象类型给 null )

    TODO

    • 写文档( README.md 居然有只写了一半的句子!)
    • 写文档(注释简直是没有)
    • 写文档( Wiki 也没有!)
    • 修改路径匹配的规则,现在是用正则匹配的,对带正则元字符的的路径不友好
    • 优化获取参数的性能……从 request 中填充一个 5 个属性的 Bean 居然要 16 毫秒简直不能忍
    • 重构一下 View 的结构,现在的 View 机制是在 Renderer 之下的,结构很诡异
    • 用一个比较优雅的方式封装参数获取和转换的配置(目前是写死的规则……)

    随后我会慢慢在 GitHub 的 README.md 和 Wiki 中补充上各种文档,请大家期待;)

    16 条回复    2015-10-28 10:27:23 +08:00
    Comdex
        1
    Comdex  
       2015-10-23 21:46:06 +08:00   ❤️ 1
    撸了个简单的 Java ORM 框架,求吐嘈和 Star/Fork
    https://github.com/Comdex/Cozy
    Cloudee
        2
    Cloudee  
    OP
       2015-10-23 23:42:50 +08:00 via iPhone
    @Comdex 哈哈有没有人撸个简单的 IoC...
    nowcoder
        3
    nowcoder  
       2015-10-24 00:15:58 +08:00   ❤️ 1
    cxshun
        4
    cxshun  
       2015-10-24 00:26:23 +08:00   ❤️ 1
    @Comdex @Cloudee 赞,都已 Star 。
    简单的 IoC ,不错,我也要弄一个。
    unique
        5
    unique  
       2015-10-24 12:37:30 +08:00 via iPhone   ❤️ 1
    Cloudee
        6
    Cloudee  
    OP
       2015-10-24 13:01:23 +08:00
    @unique
    楼上都不错, Star 了 w
    unique
        7
    unique  
       2015-10-24 13:08:43 +08:00 via iPhone
    @Cloudee 😀1024 快乐!
    Cloudee
        8
    Cloudee  
    OP
       2015-10-24 14:15:42 +08:00
    @unique 同乐 w
    P.S 你那个 blade 的配置语法好现代,感觉我这个还局限在 SpringMVC/Guice Servlet 那个时代的语法上
    unique
        9
    unique  
       2015-10-24 14:51:58 +08:00 via iPhone
    @Cloudee //∇//)○ 慢慢改进,每一个创造轮子的骚年都有推动技术发展的❤
    br00k
        10
    br00k  
       2015-10-24 15:35:37 +08:00   ❤️ 1
    Start XD
    wizardforcel
        11
    wizardforcel  
       2015-10-24 17:54:18 +08:00 via Android   ❤️ 1
    。。。有没有人自制了个简单的模板引擎
    Comdex
        12
    Comdex  
       2015-10-25 13:03:15 +08:00
    @unique 路由的闭包用法必须要引入 jdk8 吧?我看简介要求 1.6 都可以?
    unique
        13
    unique  
       2015-10-25 13:59:21 +08:00
    @Comdex 可以的,支持 1.6 以及以上
    Cloudee
        14
    Cloudee  
    OP
       2015-10-25 14:15:42 +08:00 via iPhone
    @Comdex 我的理解是 1.8 可以用闭包, 1.7 以下也可以 new 接口( mocha 的 all 方法也是这样的)
    不知道对不对 @unique
    unique
        15
    unique  
       2015-10-25 14:33:10 +08:00
    @Cloudee yes ,你看看 http://winterbe.com/posts/2014/03/16/java-8-tutorial/ 只要你编写了 1.6 的接口,那么在 1.8 的语法中可以简化,我没有直接使用 jdk1.8 去做,那样看起来更优雅 : )
    moishalo
        16
    moishalo  
       2015-10-28 10:27:23 +08:00   ❤️ 1
    @Cloudee 擦,我来晚了。。。
    瞬间这么多回复了。。。已 Star 。。。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5354 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 09:38 · PVG 17:38 · LAX 01:38 · JFK 04:38
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.