目录
1、Webx简介
2、创建webx应用
一、Webx简介
Webx本质上就是一个Web框架,它建立在Java Servlet API基础之上。上图所示是webx的架构图。webx本身类似于spring容器,webx turbine类似于springMVC框架。webx中有一个特别明显的原则:约定优于配置。
1.web控制器: 所有web请求都交给一个叫WebxControlServlet(即图上的web控制器)。当然你也可以配置只有部分经过webx控制器,其它部分经过其它的控制器。
2.service框架,webx控制器初始化时会初始化service框架,service框架会初始化下面这些service(ResourceLoaderService, RunDataService,ModuleLoaderService,PipelineService,FormService,MappingService,PullService,URIBrokerService,VelocityService)。当然你也可以扩展更多的service。
3.管道处理web请求: 当请求到达时,管道pipeline会调用valves一个传递一个地处理。
4.web应用: 就是基于webx框架开发的应用。一般有三个层,VO(View Object),显示层。AO(Application Object),显示层(一般处理大粒度的业务逻辑与控制逻辑)。BO(Business Object)业务逻辑(细数度的业务逻辑)。DO(Data Object)数据层(一般与持久层通信)。这里其实还少画了一个层,就是持久层,持久层主要是DAO(Data Access Object)。
5.Spring框架: 即开源的Spring框架,并做了简单扩展。
从一个web请求到结束都经历了哪些阶段:首先,web请求首先到WebxControlServlet处理, WebxControlServlet获取管道服务,交给管道服务。其次,web请求到达管道服务,管道服务有多个阈[yù]值(Valve),Valve非常类似于Filter,但有一个比较大的区别是,Filter是顺序从配置文件配置好后就固定了,而Valve由于是Webx特定设计的,支持流程跳转。如:支持switch分支,支持goto,支持try/catch/finally分支,请求经过各个Valve。不过Valve是可以跳转或有判定条件,并不是每个Valve都需要经过。最后,管理处理完后就直接生成响应。当然,中间有可能走外部重定向那就会开启另一个web请求流程。webx(spring)本身类似与一个spring容器,webx turbine(spring MVC)框架才是真正的web框架。
上帝是如何创造万物的呢?上帝如果要创造人,那就是把先人的骨架给创建出来,然后就可以补上所有器官与血管,然后才是肉,皮等等。那么webx相当于(web应用的)上帝,webx turbine框架相当于人的骨架,而且我的应用框架当然相当于是器官与血管,最后我们的应用就相当于是肉啊,皮啊,其它的等等。这么一看就很好理解了吧。如果上帝想创建能飞的动物会是怎么样呢?那就需要先弄个能飞的骨架出来。也就是如果我们觉得turbine框架不好,要来个新的,你也可以自己定义一个新的框架基于webx框架即可。与Spring比较,webx相当于spring容器。webx turbine相当于spring的MVC框架(webx service框架根当于spring容器,都是IOC,或叫DI原理)。在spring上可以建立许多新的MVC框架,或直接整合新的MVC框架(比如用spring容器可以整合struts框架,springMVC框架);同样在webx上可以立许多新的MVC框架。
webx中涉及特色,管道与过滤器涉及模式filter。Filter机制在项目中常用来实现如下功能:页面授权,根据登录用户的权限,阻止或许可用户访问特定的页面;日志和审计,记录和检查用户访问WEB应用的情况。Filter的通用性很好。任何filter均独立于其它filter和servlet,因此它可以和任意其它filter和servlet组合搭配。下面是一段配置示例 ── 通过SetLoggingContextFilter,日志系统可以记录当前请求的信息,例如:URL、referrer URL、query string等
<?xml version="1.0" encoding="UTF-8"?> <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 "> <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> ... </web-app>
Filter工作原理(Filter chain),多个filter和至多一个servlet被串联成一个链,被称为Filter Chain。执行的时候,引擎将控制权交给链条中的头一个filter(如果有的话)。然后,就像击鼓传花一样,控制权被依次传递给filter chain中的下一个filter或servlet。每一个得到控制权的filter可以做下面的事:继续传递控制权或立即终止filter chain;Filter可将控制权传递给链条中的下一个filter或者最终的servlet;Filter也可以不将控制权传递给下一个filter或servlet,这样便中止了整个filter chain的执行。预处理。在传递控制权给下一个filter或servlet之前,filter可以预先做一些事情:设置request、response中的参数,例如:character encoding、content type等;将HttpServletRequestWrapper传递给链条中的下一位,filter可以通过wrapper改变request中的任意值;将HttpServletResponseWrapper传递给链条中的下一位,filter可以通过wrapper来拦截后续filter或servlet对response的修改、提交。在控制权从filter chain中返回以后,filter还可以做一些后续提交的操作。例如,将response中拦截而来的数据,压缩或转换格式,并发送给客户端或filter chain的上一级,通过try、catch还可以捕获filter chain下一级所有的异常,并做处理。
filter的限制,Filter是很有用的。作为servlet的补充,filter也是很成功的。但是filter并没有被设计用来完成一切事情。事实上,filter的设计限制了filter的用途。每个filter具有下面的限制:Filter可以访问和修改数据。但它只能访问和修改HttpServletRequest、HttpServletResponse、ServletContext等容器级的对象,而不能(或很难)访问应用程序中的状态。所以filter无法实现和应用逻辑密切相关的功能;Filter可以影响执行流程。但它不能改变filter chain的结构和顺序。Filter chain的结构和顺序是由web.xml中定义的。当filter得到控制权以后,它只能选择继续下去,或者立即结束,而没法进行循环、分支、条件判断等更复杂的控制。因此,filter只能用来实现粗粒度的流程控制功能(例如,当用户未获授权时,停止执行filter chain),难以应付更细致的应用程序内的控制需求;Filter与其它filter和servlet之间,除了request和response对象以外,无法共享其它的状态。这既是优点又是缺点。优点是使filter更独立、更通用;缺点是filter与其它filter、servlet之间难以协作,有时甚至会引起无谓的性能损失。
二、创建webx应用
mvn archetype:create -DgroupId=com.alibaba.study -DpackageName=com.alibaba.study -DartifactId=webapp -DarchetypeArtifactId=maven-archetype-webapp
WEB应用是JavaEE平台中最重要的一种应用。JavaEE WEB应用建立在Servlet API的基础之上。本文将由浅入深地指导你创建一个基本的WEB应用。上图,先用mvn命令创建一个web项目。得到如下的配置文件
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.alibaba.study</groupId> <artifactId>testWeb</artifactId> <packaging>war</packaging> <version>1.0-SNAPSHOT</version> <name>testWeb Maven Webapp</name> <url>http://maven.apache.org</url> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> </dependencies> <build> <finalName>testWeb</finalName> </build> </project>
我们依次在上述配置文件中加入,在dependencies节中加入servlet依赖:
<!-- 应证了那句话:webx是建立在Java Servlet API基础之上的容器 --> <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>2.4</version> <scope>provided</scope> </dependency>
再加入maven配置:
<plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>5</source> <target>5</target> </configuration> </plugin> </plugins>
接下来执行:
mvn eclipse:eclipse -Dwtpversion=2.0
这样便生成了.classpath和.project这两个eclipse相关的文件。Dwtpversion表示为项目增加Dwt支持,这样项目就成为一个Dwt可识别的web项目,这样就可以通过eclipsewtp部署到web服务器。注意:目前mvn支持的wtp版本最高为2.0,所以目前只能写2.0,而不能写最新的3.2。请打开Eclipse并导入这个项目,至此,你就可以在eclipse下开发项目了。接着,通过Eclipse导入刚才创建的项目。
package com.alibaba.study; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; public class HelloServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html; charset=GBK"); PrintWriter out = response.getWriter(); out.println("<html>"); out.println("<head>"); out.println(" <title>SimpleServlet</title>"); out.println("</head>"); out.println("<body>"); out.println(" <p>你好,世界!</p>"); out.println("</body>"); out.println("</html>"); } }
接着创建HelloServlet.java类,这是一个简单而完整的Servlet程序。我们一会来介绍它所包含的技术内涵,现在,让我们先把这个程序跑起来。为此,我们需要修改一下web.xml。在开发环境中,这个文件位于src/descriptors/web目录下,然而在build的时候,它将被复制到WEB应用的WEB-INF目录下。
<?xml version="1.0" encoding="GB2312"?> <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd"> <web-app> <servlet> <servlet-name>helloServlet</servlet-name> <servlet-class>com.alibaba.study.HelloServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>helloServlet</servlet-name> <url-pattern>/hello</url-pattern> </servlet-mapping> </web-app>
然后执行命令mvn package,如果一切正常,你会发现在项目的target目录多了一个WAR包:testWeb.war。最后一步,就是把这个WAR包布署到应用服务器上,我们采用eclipse下配置tomcat方式进行。在testWeb项目上面点击右键,选择run as ->Run on Server。
分析一下Servlet的执行过程,这个Servlet是怎么被执行的呢?首先,我们必须了解,无论采用何种技术,WEB应用的本质是相同的。即浏览器和服务器之间,通过HTTP协议通信。所以WEB协议是跨平台的,而不是专属于Java的。因此,为了更好地理解Java Servlet,我建议你安装一个IE的插件如HttpWatch,或者代理软件如TCP Monitor。通过它们,你可以观测浏览器和服务器之间的通信情况,从而更好地理解HTTP协议和Java Servlet。
通过它,我们可以看到浏览器发送给WEB服务器的请求的内容:“GET /workshop/hello HTTP/1.1”;我们也可以看到服务器发回浏览器的响应:“HTTP/1.1 200 OK”。这个工具非常有用,尤其对我们跟踪重定向、session、cookie特别有用。通过它也可以观测到一些不明显的错误,而这些错误可能无法在浏览器中直接表现出来。现在,我们已经了解了:WEB应用就是接收浏览器发送的HTTP请求,然后作出响应,返回给浏览器。而Servlet只不过是WEB应用中的一个“插件”,用来处理某一种请求。
当应用服务器接收到一个HTTP请求时,它就会:
1.根据URL找到相应的WEB应用。例如:在http://localhost:8080/workshop/hello中,/workshop决定了该请求应该交给workshop应用来处理。这部分URL被称为Context Path。
2.进一步根据URL的余下部分,在web.xml中查找匹配的servlet。由于我们在web.xml中指定了<servlet-mapping>,将/hello映射到helloServlet上,所以,应用服务器会找到这个servlet,并执行它。这部分URL被称为Servlet Path。
当Servlet收到请求时,其service()方法将被执行。不过一般来说,我们不需要实现service方法,只需要实现doGet和doPost这两个方法就可以了,它们分别对应着HTTP Get和HTTP Post两种类型的请求。
三、