Maven、Webx、Velocity学习总结

来源:互联网 发布:北京seo排名优化公司 编辑:程序博客网 时间:2024/05/29 12:05

1. 综述

这两周的时间,通过看指南,看代码,跑实例,对淘宝网web应用开发框架有了一个整体的初步认识,主要包括四个方面:

Ø 项目管理工具Maven

Ø MVC框架Webx。

Ø Webx中的View层实现——Velocity

Ø Webx中的Model持久层实现——Ibatis

2. Maven部分

2.1. Maven基础

1. 坐标是指项目的唯一标识,以GAV(groupId,artifactId和version)区分, groupId包含公司和内部组(或产品线)的信息,如com.taobao.mercury,表示taobao.com下的mercury项目组;ArtifactId则表示项目的名称,如mercury-web,Version则表示某一Artifact的版本,如1.0-SNAPSHOT

2. 依赖是指项目所依赖的相关jar包

3. 仓库是指存放项目的产出(Artifact)的仓库,如http://mvnrepo.taobao.ali.com/mvn/repository

4. 插件是Maven的设计机制,Maven包含一个核心功能组件,而扩展功能都是通过插件完成,即使我们最常见的编译功能也是通过compiler插件完成的。

2.2. POM基础

1. 一个pom.xml文件包含以下基本信息:<modelVersion><groupId><artifactId><version><packaging><name><description><url><licenses><scm><connection><developers>

2.3. 依赖管理

1. 依赖定义具体到version

2. 依赖可以传递

3. <scope>标签定义依赖项的生效范围

4. 依赖的版本定义在父pom(项目pom)中,子pom(模块pom)设置<parent>,继承父pomclip_image003

5. 设置一个虚拟的总项目,多个实际项目作为总项目的模块

3. Webx部分

3.1. 一分钟Webx框架开发

3.1.1. 处理页面的基本流程(Turbine)

Webx是采用MVC三层架构。请求的上下文信息(RequestContext、ServletContext、HttpServletRequest、HttpServletResponse)被封装为RunData对象。在Web层和Biz层之间采用command模式实现对请求的处理。由MappingRuleService将请求分发到同名的业务处理类进行处理,处理结果被封装为Result对象。然后按照业务逻辑将所需信息放到TemplateContext中,由velocity取得并对VM模板进行渲染。最后产出的页面输出给用户。

有的请求并不要求返回页面,只需处理业务逻辑。

整个处理流程的控制由Pipeline(水管)中配置各种Valve(阀门)实现,简易的流程图如下:

clip_image005

图表 3‑1

3.1.2. Webx各层我们要做的工作的工作:

l V层(Web):采用Velocity书写vm模版,书写一个同名的Java类来接收Command,并处理业务逻辑(void execute(RunData,TemplateContext)),并根据处理得到的结果(Result对象),准备好vm模版中所需要的数据(TemplateContext.put(String key, Object value))。

l C层(Biz):书写AO对象处理Command,请求的上下文信息被封装在RunData对象中。AO中只包含简单的逻辑处理,真正的业务处理通常书写在Manager中。

l M层(ibatis):书写DAO对象负责和数据交互,持久层使用的是Ibatis。需要我们来建立数据物理模型并书写数据库操作的SQL语句。

3.2. Webx框架初探

3.2.1. Webx的基本概念

1. 页面驱动:以页面(view)为主导,先写页面,再写和页面配套的程序模块,通过规则,查找页面所对应的程序模块

2. Pull Tools:有一些定义在webx.xml中,另一些默认定义在框架中。这些tools可以再vm模板中被直接引用。Global作用域的tool在系统初始化时创建,Request作用域的tool在每次HTTP请求时创建。

3. Modules:turbine中的基本编程模块。Screen用来处理页面显示逻辑;Control和screen类似,但可以被别的screen或layout引用;Action处理用户提交表单。所有module都实现Module接口:public interface Module {void execute(RunData rundata) throws WebxException;}

3.2.2. Mecury项目目录结构

mercury

├─assets

├─biz

│ ├─src

│ │ ├─main.java.com.taobao

│ │ │ │ └─mercury

│ │ │ │ ├─amend

│ │ │ │ ├─ao

│ │ │ │ │ ├─correct

│ │ │ │ │ │ └─impl

│ │ │ │ │ └─impl

│ │ │ │ ├─aop

│ │ │ │ ├─biz

│ │ │ │ │ ├─domain

│ │ │ │ │ │ ├─mysqlmap

│ │ │ │ │ │ ├─oracle

│ │ │ │ │ │ ├─rowkey

│ │ │ │ │ │ └─sajiao

│ │ │ │ │ └─util

│ │ │ │ ├─cache

│ │ │ │ ├─dal

│ │ │ │ │ └─sajiao

│ │ │ │ ├─mananger

│ │ │ │ │ └─sajiao

│ │ │ │ ├─notify

│ │ │ │ ├─ob

│ │ │ │ │ ├─ao

│ │ │ │ │ ├─dal

│ │ │ │ │ └─mananger

│ │ │ │ ├─query

│ │ │ │ └─timetask

│ │ │ └─resources

│ │ └─test

│ └─target

└─deploy

mercury

└─protocal

├─.settings

├─src

│ ├─main.java.com.taobao

│ │ ├─common

│ │ └─mercury

│ │ ├─domain

│ │ └─util

│ │ └─partition

│ └─test

└─target

mercury

└─web

├─.settings

├─src

│ ├─main

│ │ ├─assembly

│ │ ├─filter

│ │ ├─java.com.taobao.mercury.web

│ │ │ ├─common

│ │ │ │ ├─service

│ │ │ │ ├─session

│ │ │ │ ├─util

│ │ │ │ └─valve

│ │ │ └─module

│ │ │ ├─action

│ │ │ ├─control

│ │ │ └─screen

│ │ ├─resources

│ │ │ ├─biz

│ │ │ │ ├─bean

│ │ │ │ └─persistence

│ │ │ └─top

│ │ │ └─config

│ │ └─webapp

│ │ ├─common

│ │ │ └─templates

│ │ │ └─screen

│ │ ├─default

│ │ │ └─templates

│ │ │ ├─control

│ │ │ ├─layout

│ │ │ └─screen

│ │ ├─META-INF

│ │ └─WEB-INF

│ │ ├─common

│ │ └─default

│ └─test.java.com.taobao.mercury

└─target

3.2.3. Webx应用启动流程

Webapp\WEB-INF\web.xml是SpringExt的配置文件,下面是mercury-web中的样本:

<?xml version="1.0" encoding="GB2312"?>

<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

<context-param>

<param-name>loggingRoot</param-name>

<param-value>${mercury.loggingRoot}</param-value>

</context-param>

......

<listener><listener-class>com.alibaba.citrus.logconfig.LogConfiguratorListener</listener-class>

</listener>

<!-- ???/WEB-INF/webx.xml, /WEB-INF/webx-*.xml -->

<listener>

<listener-class>com.alibaba.citrus.webx.context.WebxContextLoaderListener</listener-class>

</listener>

......

<filter>

<filter-name>sessionFilter</filter-name>

<filter-class>com.taobao.session.TaobaoSessionFilter</filter-class>

<init-param>

<param-name>tbsessionConfigGroup</param-name>

<param-value>${mercury.session.filter.group.name}</param-value>

</init-param>

<init-param>

<param-name>isloginSessionCheck</param-name>

<param-value>true</param-value>

</init-param>

</filter>

<filter-mapping>

<filter-name>sessionFilter</filter-name>

<url-pattern>*.htm</url-pattern>

</filter-mapping>

......

<filter>

<filter-name>timer</filter-name>

<filter-class>com.alibaba.webx.filter.timer.TimerFilter</filter-class>

<init-param>

<param-name>threshold</param-name>

<param-value>${mercury.timer.threshold}</param-value>

</init-param>

</filter>

<filter-mapping>

<filter-name>timer</filter-name>

<url-pattern>/*</url-pattern>

</filter-mapping>

<filter>

<filter-name>webx</filter-name>

<filter-class>com.alibaba.citrus.webx.servlet.WebxFrameworkFilter</filter-class>

</filter>

<filter>

<filter-name>mdc</filter-name>

<filter-class>com.alibaba.citrus.webx.servlet.SetLoggingContextFilter</filter-class>

</filter>

<filter-mapping>

<filter-name>mdc</filter-name>

<url-pattern>/*</url-pattern>

</filter-mapping>

<filter-mapping>

<filter-name>webx</filter-name>

<url-pattern>/*</url-pattern>

</filter-mapping>

<welcome-file-list>

<welcome-file>index.html</welcome-file>

<welcome-file>index.jsp</welcome-file>

</welcome-file-list>

<!-- ====================================================== -->

<!-- error pages -->

<!-- ====================================================== -->

<error-page>

<error-code>400</error-code>

<location>/error.html</location>

</error-page>

......

</web-app>

通过查资料,结合web.xml配置的内容,一个Webx应用的启动流程如下:

1. 初始化context-param

2. 执行各个listener,其中WebxContextLoaderListener初始化被Webx包装过的XmlWebApplicationContext(spring容器)及各个子容器,各种webx.xml里定义beans(包括<service>标签定义的服务)都被装载。

3. 加载各个filter:其中TimerFilter(timer)用来记录serverlet执行时间,WebxFrameworkFilter(webx)用来处理web请求,SetLoggingContextFilter(mdc)用来通过SLF4J MDC来记录用户和请求的信息。三者顺序为timer->webx->mdc。

clip_image001 web.xml中各种元素的含义:http://ajava.org/readbook/J2EE/servletjsphxbc2/17212.html

3.2.4. Webx响应和处理请求的流程(摘自Webx框架指南)

当一个HTTP请求到达时,首先由WebxFrameworkFilter接手这个请求(参考Webx应用启动流程),下图是WebxFrameworkFilter处理一个WEB请求的过程:

webx

如图所示,WebxFrameworkFilter接到请求以后,就会调用WebxRootController。从这里开始,进入Spring的世界。此后所有的对象:WebxRootController、WebxController、RequestContext、Pipeline等,全部是通过SpringExt配置在Spring Context中的。

WebxRootController对象存在于root context中,它被所有子应用所共享。它会创建RequestContext实例,从而增强request、response、session的功能。接下来,WebxController对象会被调用。

WebxController对象是由每个子应用独享的,子应用app1和app2可以有不同的WebxController实现。默认的实现,会调用pipeline。

Pipeline也是由各子应用自己来配置的。假如pipeline碰到无法处理的请求,如静态页面、图片等,pipeline应当执行<exit/> valve强制退出。然后WebxRootController就会“放弃控制”,这意味着request将被返还给/WEB-INF/web.xml中定义的servlet、filter或者返还给servlet engine本身来处理。

webapp\common\pipeline.xml配置了mercury-web的PipeLine:

<?xml version="1.0" encoding="UTF-8" ?>

<beans:beans xmlns:services="http://www.alibaba.com/schema/services"

......

xsi:schemaLocation="http://www.alibaba.com/schema/services

...... "

>

<services:pipeline

xmlns="http://www.alibaba.com/schema/services/pipeline/valves">

<prepareForTurbine />

<prepareForWebx2/>

<pl-valves:try-catch-finally>

<pl-valves:try>

<webx2-valve class="com.alibaba.turbine.pipeline.SetLoggingContextValve" />

<webx2-valve class="com.taobao.mercury.web.common.valve.DefaultAnalyzeURLValve" />

<webx2-valve

class="com.taobao.mercury.web.common.valve.SecurityCheckValve" />

<webx2-valve class="com.taobao.mercury.web.common.valve.SessionValve" />

<webx2-valve class="com.taobao.common.pagecache.webx.PageCacheValve"

p:action="start" />

<loop>

<choose>

<when>

<pl-conditions:target-extension-condition

extension="vm, jsp" />

<performAction />

<performTemplateScreen />

<renderTemplate />

</when>

<when>

<pl-conditions:target-extension-condition

extension="do" />

<performAction />

<performScreen />

</when>

<otherwise>

<exit />

</otherwise>

</choose>

<breakUnlessTargetRedirected />

</loop>

</pl-valves:try>

<pl-valves:finally>

<webx2-valve class="com.taobao.common.pagecache.webx.PageCacheValve"

p:action="end" />

<webx2-valve class="com.taobao.mercury.web.common.valve.SessionValve"

p:action="clean" />

<webx2-valve class="com.alibaba.turbine.pipeline.SetLoggingContextValve"

p:action="cleanup" />

</pl-valves:finally>

</pl-valves:try-catch-finally>

</services:pipeline>

</beans:beans>

假设用户以URL:http://favorite.daily.taobao.net/collect_list.htm来访问Webx应用。WebxFrameworkFilter接收请求,并且一路顺利到达pipeline。然后Pipeline开始依次执行它的valves(下面的描述略过一些相对次要的步骤):

1. <analyzeURL> - 分析URL

分析URL的目的是取得target,这里取得的target是collect_list.htm。如果用户访问的URL中并没有提供path信息,通常被理解为:用户想要访问“主页”。AnalyzeURL valve提供了一个可选的参数“homepage”,即是在这种情况下起作用。得到的target为“homepage”。

需要注意的是,target不代表模板名,也不代表类名。Target只是一个抽象的概念 —— 当前页面需要达成的目标。Target可能被后续的valves解释成模板名、类名或者其它东西。

2. 进入<choose> - 多重分支

很明显,“collect_list.htm”满足了第一个<when>所附带的条件:<target-extension-condition extension=" vm, jsp">,意思是target的后缀为“jsp”或为“vm”。

3. <performAction> - 执行action

和其它框架中的action概念不同,在Webx Turbine中,action是用来处理用户提交的表单的。

因为本次请求未提供action参数,所以跳过该步骤。

4. <performTemplateScreen> - 查找并执行screen。

如果target-extension为”do”,则没有<performTemplateScreen>这个valve。

这里要用到一个规则:target映射成screen module类名的规则。

假设target为xxx/yyy/zzz,那么Webx Turbine会依次查找下面的screen模块:

screen.xxx.yyy.Zzz,

screen.xxx.yyy.Default,

screen.xxx.Default,

screen.Default。

本次请求的target为collection_list.htm,因此它会尝试查找screen.collection_list类。

如果找到screen类,Webx Turbine就会执行它。Screen类的功能,通常是读取数据库,然后把模板所需要的对象放到TemplateContext中。

如果找不到,也没关系 —— 这就是“页面优先”:一些页面没有业务逻辑,因此不需要screen类,只需要有模板就可以了。

5. <renderTemplate> - 渲染模板

这里用到两个规则:target映射成screen template,以及target映射成layout template。

假设target为xxx/yyy/zzz,那么Webx Turbine会查找下面的screen模板:/templates/screen/xxx/yyy/zzz。Screen模板如果未找到,就会报404 Not Found错误。找到screen模板以后,Webx Turbine还会试着查找下面的layout模板:

/templates/layout/xxx/yyy/zzz

/templates/layout/xxx/yyy/default

/templates/layout/xxx/default

/templates/layout/default

Layout模板如果找不到,就直接渲染screen模板;如果存在,则把渲染screen模板后的结果,嵌入到layout模板中。

Layout模板和screen模板中,都可以调用control。每个页面只有一个screen,却可以有任意多个controls。

6. <breakUnlessTargetRedirected> - 内部重定向

在screen和action中,可以进行“内部重定向”。内部重定向实质上就是由<breakUnlessTargetRedirected>实施的 —— 如果没有重定向标记,就退出;否则循环到<loop>标签。

和外部重定向不同,外部重定向是向浏览器返回一个302或303 response,其中包含Location header,浏览器看到这样的response以后,就会发出第二个请求。而内部重定向发生在pipeline内部,浏览器并不了解内部重定向。

4. Velocity部分

尚未系统学习,只是看代码做了一些了解。

1. 模板以.vm为后缀名

2. $a:美元符“$”加上java中的引用名。可以引用的对象包括内置的对象,pull Service中pull到的对象,业务处理中put进TemplateContext中的对象

3. #set($a = $b):声明变量并赋值;

4. ##:velocity行注释

5. #if #elseif #else判断选择,最后用#end闭合

5. Ibatis部分

5.1. Ibatis的作用

Ibatis将数据库中的数据转换为java中的对象,方便C层对数据进行操作

5.2. Ibatis的配置

1. 属性文件*-persistence.xml

2. 总配置文件SqlMap-Config.xml

3. 映射文件collection_item_mapping.xml

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 Apache2.4反向代理http pci设备驱动 C语言实验题――打印菱形 C语言实验题――三个数排序 C语言实验题――三角形面积 C语言实验题――两个数比较 C语言实验题――温度转换 C语言实验题――鸡兔同笼 输入入门(1) C语言实验题――最小公倍数和最大公约数 C语言实验题――分数序列 C语言实验题――数组逆序 C语言实验题――一元二次方程 C语言实验题――某年某月的天数 相邻最大数 Picture 羊村运动会――撑杆跳高 字符矩阵排序 1535:找规律填数字 idm6.38 C语言实验题――圆周率 缺陷检测 成都瓶儿 谭松韵 桥本 YouTube、Google+、Facebook、Twitter、维基百科最全hosts C语言实验题――拍皮球 求奇数的乘积 C语言实验题――字符编码 intellijlicense andriod导航栏 mfc文件上传下载 Eclipse4.8中搭建Android开发环境 1178:C语言实验题――单词统计 现在小明决定实现一个类似malloc的内存分配系统,具体来说,他需要连续处理若干申请内存的请求,这个 给定某二叉树的前序序列和中序序列,输出该二叉树的后序序列。(输入的前序遍历和中序遍历的结果中都不含重 vibe twitter 幼呦 fasttunnel 一叫三吱